零模拟时间
Zero simulation time
我正在创建某种 RAM 内存。想法首先是创建 RAM“写入”功能,如您在下面的代码中所见。除了 RAM 内存之外,还有 RAM 模型驱动程序,它应该将数据写入 RAM(只是为了简要验证写入功能是否正常工作)。
RAM 模型驱动程序和 RAM 模型相互连接,应该会发生一些事务,但问题是模拟在零模拟秒内完成。
任何人都知道可能是什么问题?
@gear
def ram_model(write_addr: Uint,
write_data: Queue['dtype'],*,
ram_mem = None,
dtype = b'dtype',
mem_granularity_in_bytes = 1) -> (Queue['dtype']):
if(ram_mem is None and type(ram_mem) is not dict):
ram_mem = {}
ram_write_op(write_addr = write_addr,
write_data = write_data,
ram_memory = ram_mem)
@gear
async def ram_write_op(write_addr: Uint,
write_data: Queue,*,
ram_memory = None,
mem_granularity_in_bytes = 1):
if(ram_memory is None and type(ram_mem) is not dict):
SystemError("Ram memory is %s but it should be dictionary",(type(ram_memory)))
byte_t = Array[Uint[8], mem_granularity_in_bytes]
async with write_addr as addr:
async for data, _ in write_data:
for b in code(data, byte_t):
ram_memory[addr] = b
addr += 1
@gear
async def ram_model_drv(*,addr_bus_width = b'asize',
data_type = b'dtype') -> (Uint[8], Queue['data_type']):
num_of_w_comnds = 15
matrix = np.random.randint(10, size = (num_of_w_comnds, 10))
for command_id in range(num_of_w_comnds):
for i in range(matrix[command_id].size):
yield (command_id, (matrix[command_id][i], i == matrix[command_id].size))
stimul = ram_model_drv(addr_bus_width = 8, data_type = Fixp[8,8])
out = ram_model(stimul[0], stimul[1])
sim()
这是输出消息:
python ram_model.py
- [INFO]: Running sim with seed: 3934280405122873233
0 [INFO]: -------------- Simulation start --------------
0 [INFO]: ----------- Simulation done ---------------
0 [INFO]: Elapsed: 0.00
是的,这个有点绕。问题的要点是,在 ram_model_drv
模块中,您使用 yield
语句在其两个输出接口上同步输出数据。对于 PyGears,这意味着您希望在继续之前确认这两个接口上的数据。 ram_write_op
模块通过 write_addr
和 write_data
参数连接到这两个接口。在该模块内部,只有在从 write_data
接口读取多个数据后,您才确认来自 write_addr
接口的数据,因此存在死锁,PyGears 模拟器检测到没有进一步的模拟步骤是可能的,并在最后退出步骤 0.
驱动程序中还有两个额外的问题:
- 它永远不会为输出数据
Queue
生成eot
。相反 eot
应该在 i == matrix[command_id].size - 1
. 时生成
async
模块 运行 处于 PyGears 的无限循环中,因此您的 ram_model_drv
将无休止地生成数据,除非您显式生成 GearDone 异常。
好了,回到正题。有几种可能可以规避它:
使用解耦
为此,您首先需要将数据输出拆分为两个 yield
语句,一个用于 write_addr
,另一个用于 write_data
,因为您的 ram_write_op
每次写数据只使用一个地址。
@gear
async def ram_model_drv(*, addr_bus_width, data_type) -> (Uint[8], Queue['data_type']):
num_of_w_comnds = 15
matrix = np.random.randint(10, size=(num_of_w_comnds, 10))
for command_id in range(num_of_w_comnds):
yield (command_id, None)
for i in range(matrix[command_id].size):
yield (None, (matrix[command_id][i], i == matrix[command_id].size - 1))
raise GearDone
您可以使用 dreg
或 decouple
模块在 ram_write_op
使用之前临时存储来自 ram_model_drv
的输出数据。
out = ram_model(stimul[0] | decouple, stimul[1] | decouple)
将驱动程序拆分为两个模块,一个驱动两个接口中的每一个
对接口使用低级同步API
在 yield
机制下,有一个较低级别 API 用于通过 PyGears 接口进行通信。可以通过 module().dout
字段获得输出接口的句柄。数据可以通过接口发送,无需等待使用 put_nb()
方法确认。稍后,为了等待确认,可以等待 ready()
方法。最后,put()
方法将两者合而为一,因此它既会发送数据又会等待确认。
@gear
async def ram_model_drv(*,
addr_bus_width=b'asize',
data_type=b'dtype') -> (Uint[8], Queue['data_type']):
addr, data = module().dout
num_of_w_comnds = 15
matrix = np.random.randint(10, size=(num_of_w_comnds, 10))
for command_id in range(num_of_w_comnds):
addr.put_nb(command_id)
for i in range(matrix[command_id].size):
await data.put((matrix[command_id][i], i == matrix[command_id].size - 1))
await addr.ready()
raise GearDone
我正在创建某种 RAM 内存。想法首先是创建 RAM“写入”功能,如您在下面的代码中所见。除了 RAM 内存之外,还有 RAM 模型驱动程序,它应该将数据写入 RAM(只是为了简要验证写入功能是否正常工作)。 RAM 模型驱动程序和 RAM 模型相互连接,应该会发生一些事务,但问题是模拟在零模拟秒内完成。 任何人都知道可能是什么问题?
@gear
def ram_model(write_addr: Uint,
write_data: Queue['dtype'],*,
ram_mem = None,
dtype = b'dtype',
mem_granularity_in_bytes = 1) -> (Queue['dtype']):
if(ram_mem is None and type(ram_mem) is not dict):
ram_mem = {}
ram_write_op(write_addr = write_addr,
write_data = write_data,
ram_memory = ram_mem)
@gear
async def ram_write_op(write_addr: Uint,
write_data: Queue,*,
ram_memory = None,
mem_granularity_in_bytes = 1):
if(ram_memory is None and type(ram_mem) is not dict):
SystemError("Ram memory is %s but it should be dictionary",(type(ram_memory)))
byte_t = Array[Uint[8], mem_granularity_in_bytes]
async with write_addr as addr:
async for data, _ in write_data:
for b in code(data, byte_t):
ram_memory[addr] = b
addr += 1
@gear
async def ram_model_drv(*,addr_bus_width = b'asize',
data_type = b'dtype') -> (Uint[8], Queue['data_type']):
num_of_w_comnds = 15
matrix = np.random.randint(10, size = (num_of_w_comnds, 10))
for command_id in range(num_of_w_comnds):
for i in range(matrix[command_id].size):
yield (command_id, (matrix[command_id][i], i == matrix[command_id].size))
stimul = ram_model_drv(addr_bus_width = 8, data_type = Fixp[8,8])
out = ram_model(stimul[0], stimul[1])
sim()
这是输出消息:
python ram_model.py
- [INFO]: Running sim with seed: 3934280405122873233
0 [INFO]: -------------- Simulation start --------------
0 [INFO]: ----------- Simulation done ---------------
0 [INFO]: Elapsed: 0.00
是的,这个有点绕。问题的要点是,在 ram_model_drv
模块中,您使用 yield
语句在其两个输出接口上同步输出数据。对于 PyGears,这意味着您希望在继续之前确认这两个接口上的数据。 ram_write_op
模块通过 write_addr
和 write_data
参数连接到这两个接口。在该模块内部,只有在从 write_data
接口读取多个数据后,您才确认来自 write_addr
接口的数据,因此存在死锁,PyGears 模拟器检测到没有进一步的模拟步骤是可能的,并在最后退出步骤 0.
驱动程序中还有两个额外的问题:
- 它永远不会为输出数据
Queue
生成eot
。相反eot
应该在i == matrix[command_id].size - 1
. 时生成
async
模块 运行 处于 PyGears 的无限循环中,因此您的ram_model_drv
将无休止地生成数据,除非您显式生成 GearDone 异常。
好了,回到正题。有几种可能可以规避它:
使用解耦
为此,您首先需要将数据输出拆分为两个
yield
语句,一个用于write_addr
,另一个用于write_data
,因为您的ram_write_op
每次写数据只使用一个地址。@gear async def ram_model_drv(*, addr_bus_width, data_type) -> (Uint[8], Queue['data_type']): num_of_w_comnds = 15 matrix = np.random.randint(10, size=(num_of_w_comnds, 10)) for command_id in range(num_of_w_comnds): yield (command_id, None) for i in range(matrix[command_id].size): yield (None, (matrix[command_id][i], i == matrix[command_id].size - 1)) raise GearDone
您可以使用
dreg
或decouple
模块在ram_write_op
使用之前临时存储来自ram_model_drv
的输出数据。out = ram_model(stimul[0] | decouple, stimul[1] | decouple)
将驱动程序拆分为两个模块,一个驱动两个接口中的每一个
对接口使用低级同步API
在
yield
机制下,有一个较低级别 API 用于通过 PyGears 接口进行通信。可以通过module().dout
字段获得输出接口的句柄。数据可以通过接口发送,无需等待使用put_nb()
方法确认。稍后,为了等待确认,可以等待ready()
方法。最后,put()
方法将两者合而为一,因此它既会发送数据又会等待确认。@gear async def ram_model_drv(*, addr_bus_width=b'asize', data_type=b'dtype') -> (Uint[8], Queue['data_type']): addr, data = module().dout num_of_w_comnds = 15 matrix = np.random.randint(10, size=(num_of_w_comnds, 10)) for command_id in range(num_of_w_comnds): addr.put_nb(command_id) for i in range(matrix[command_id].size): await data.put((matrix[command_id][i], i == matrix[command_id].size - 1)) await addr.ready() raise GearDone