我无法在 Simics 文档中找到有关如何获取时钟对象的示例,以便我们可以将其用作
post()
方法中的参数。
我怀疑是
我使用
bin\project-setup --py-device event-py
创建了一个新模块
我在
ConfObject
类作用域中定义了两个方法,称为 clock_set
和 clock_get
。
我想使用这些方法,以便我可以设置/获取要在 post 方法中使用的时钟对象。
读取真空机中的设备寄存器时,
post()
方法失败。
import pyobj
# Tie code to specific API, simplifying upgrade to new major version
import simics_6_api as simics
class event_py(pyobj.ConfObject):
"""This is the long-winded documentation for this Simics class.
It can be as long as you want."""
_class_desc = "one-line doc for the class"
_do_not_init = object()
def _initialize(self):
super()._initialize()
def _info(self):
return []
def _status(self):
return [("Registers", [("value", self.value.val)])]
def getter(self):
return self
# In my mind, clock_set is supposed to set the clock object. That way we can use
# it in post()
def clock_set(self):
self.clock = simics.SIM_object_clock(self)
def clock_get(self):
return self.clock(self):
class value(pyobj.SimpleAttribute(0, 'i')):
"""The <i>value</i> register."""
class ev1(pyobj.Event):
def callback(self, data):
return 'ev1 with %s' % data
class regs(pyobj.Port):
class io_memory(pyobj.Interface):
def operation(self, mop, info):
offset = (simics.SIM_get_mem_op_physical_address(mop)
+ info.start - info.base)
size = simics.SIM_get_mem_op_size(mop)
if offset == 0x00 and size == 1:
if simics.SIM_mem_op_is_read(mop):
val = self._up._up.value.val
simics.SIM_set_mem_op_value_le(mop, val)
# POST HERE AS TEST self._up._up.ev1.post(clock, val, seconds = 1)
else:
val = simics.SIM_get_mem_op_value_le(mop)
self._up._up.value.val = val
return simics.Sim_PE_No_Exception
else:
return simics.Sim_PE_IO_Error
您提到使用 vacuum 示例机器,并且在其脚本中您看到 sdp->queue 将指向 timer。所以 SIM_object_clock(sdp) 会返回定时器。
Simics 在所有 conf-objects 中使用 queue 属性来单独引用它们的时钟,尽管也使用了其他实现。
BR 西蒙 #IAmIntel
pyobj 文档和示例 Python 代码似乎不是最佳状态。抱歉,问题已提交。
这里是对有效代码的改写建议。使用端口对象映射寄存器。添加事件日志以明确发生了什么。并使用对象的队列属性以您应该的方式发布事件。
import pyobj
# Tie code to specific API, simplifying upgrade to new major version
import simics_6_api as simics
class event_py(pyobj.ConfObject):
"""This is the long-winded documentation for this Simics class.
It can be as long as you want."""
_class_desc = "one-line doc for the class"
_do_not_init = object()
def _initialize(self):
super()._initialize()
def _info(self):
return []
def _status(self):
return [("Registers", [("value", self.value.val)])]
def getter(self):
return self
class value(pyobj.SimpleAttribute(0, 'i')):
"""The <i>value</i> register."""
class ev1(pyobj.Event):
def callback(self, data):
## When event triggers, log
simics.SIM_log_info(1, self._up.obj, 0,
f"Event callback called, data={data}")
## Use PortObject to get a modern-style port for the bank
class regs(pyobj.PortObject):
## Register banks should go into the bank namespace
## Resulting port object is called <dev>.bank.regs
namespace="bank"
class io_memory(pyobj.Interface):
def operation(self, mop, info):
offset = (simics.SIM_get_mem_op_physical_address(mop)
+ info.start - info.base)
size = simics.SIM_get_mem_op_size(mop)
## Make the register 4 bytes to be slightly more interesting
if offset == 0x00 and size == 4:
if simics.SIM_mem_op_is_read(mop):
val = self._up._up.value.val
simics.SIM_set_mem_op_value_le(mop, val)
else:
## Update stored register value
val = simics.SIM_get_mem_op_value_le(mop)
self._up._up.value.val = val
## Post event on write
simics.SIM_log_info(1, self._up._up.obj, 0, f"Posting callback with data={val}")
self._up._up.ev1.post(self._up._up.obj.queue, val, cycles = 10)
return simics.Sim_PE_No_Exception
else:
return simics.Sim_PE_IO_Error
要使用它,您需要有一个实际的时钟对象作为队列。我使用这段代码建立了一个带有时钟、此类实例和内存映射的小型测试系统。把它放到一个单独的 Python 文件中,并在启动 Simics 时运行它。
import simics
def create_test_subsystem(name="test"):
n = simics.pre_conf_object(name, 'namespace')
# Clock
n.clock = simics.pre_conf_object('clock', freq_mhz = 1000)
# Device
n.dut = simics.pre_conf_object('event_py')
## Set the queue attribute of the device to point at the clock
## This is how the device finds the clock to post on
## All Simics objects have a "queue" attribute, it is part of the
## framework.
n.dut.attr.queue = n.clock
# Memory map
n.memmap = simics.pre_conf_object('memory-space',map=[])
n.memmap.attr.map.append( [0x1000, n.dut.bank.regs, 0, 0, 0x1000] )
simics.SIM_add_configuration([n],None)
create_test_subsystem()
现在,开始一个新的Simics:
C:...> .\simics.bat test_event_py.py
在 Simics 中,我们应该得到这个会话:
simics> list-objects -tree
┐
├ bp ┐
│ ├ bank
│ ├ console_string
│ ├ control_register
│ ├ cycle
│ ├ cycle_event
│ ├ exception
│ ├ gfx
│ ├ hap
│ ├ log
│ ├ magic
│ ├ memory
│ ├ notifier
│ ├ os_awareness
│ ├ source_line
│ ├ source_location
│ ├ step
│ ├ step_event
│ └ time
├ breakpoints
├ default_cell0 ┐
│ └ ps
├ default_sync_domain
├ params
├ prefs
├ sim ┐
│ ├ cli
│ ├ cmdline
│ ├ gui
│ ├ rexec
│ ├ tlmtry
│ └ transactions
└ test ┐
├ clock ┐
│ └ vtime ┐
│ ├ cycles
│ └ ps
├ dut ┐
│ └ bank ┐
│ └ regs
└ memmap
simics> test.memmap.map
┌──────┬──────────────────┬──┬──────┬──────┬──────┬────┬─────┬────┐
│ Base│Object │Fn│Offset│Length│Target│Prio│Align│Swap│
├──────┼──────────────────┼──┼──────┼──────┼──────┼────┼─────┼────┤
│0x1000│test.dut.bank.regs│ │0x0000│0x1000│ │ 0│ 8│ │
└──────┴──────────────────┴──┴──────┴──────┴──────┴────┴─────┴────┘
simics> log-setup -time-stamp
simics> peq
simics> test.memmap.write 0x1000 1000 4 -l
[test.dut info] {test.clock 0} Posting callback with data=1000
simics> peq
┌─────┬────────┬───────────┐
│Cycle│ Object │Description│
├─────┼────────┼───────────┤
│ 10│test.dut│ev1 │
└─────┴────────┴───────────┘
simics> run 5 cycles
simics> test.memmap.write 0x1000 2000 4 -l
[test.dut info] {test.clock 5} Posting callback with data=2000
simics> peq
┌─────┬────────┬───────────┐
│Cycle│ Object │Description│
├─────┼────────┼───────────┤
│ 5│test.dut│ev1 │
│ 10│test.dut│ev1 │
└─────┴────────┴───────────┘
simics> run 5 cycles
[test.dut info] {test.clock 10} Event callback called, data=1000
simics> peq
┌─────┬────────┬───────────┐
│Cycle│ Object │Description│
├─────┼────────┼───────────┤
│ 5│test.dut│ev1 │
└─────┴────────┴───────────┘
simics>