如何在 python 设备中获取 event.post(clock, data, duration) 的时钟参数?

问题描述 投票:0回答:2

我无法在 Simics 文档中找到有关如何获取时钟对象的示例,以便我们可以将其用作

post()
方法中的参数。

我怀疑是

  • 一个属性可用于获取时钟或
  • 在 ConfObject 类范围内,我们使用 SIM_object_clock() 获取时钟

我使用

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
python post events clock simics
2个回答
1
投票

您提到使用 vacuum 示例机器,并且在其脚本中您看到 sdp->queue 将指向 timer。所以 SIM_object_clock(sdp) 会返回定时器。

Simics 在所有 conf-objects 中使用 queue 属性来单独引用它们的时钟,尽管也使用了其他实现。

BR 西蒙 #IAmIntel


1
投票

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>
© www.soinside.com 2019 - 2024. All rights reserved.