问题描述
我正在创建某种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_addr
界面读取了多个数据之后,您才确认来自write_data
界面的数据,因此存在死锁,并且PyGears模拟器检测到无法进行进一步的模拟步骤,并最终退出的第0步。
驱动程序中还有两个其他问题:
- 它将永远不会为输出数据
eot
生成Queue
。相反,应在eot
时生成i == matrix[command_id].size - 1
。 -
async
模块由PyGears无限循环运行,因此,除非您明确生成GearDone异常,否则ram_model_drv
将无休止地生成数据。
好,回到主要问题。有几种方法可以绕过它:
-
使用去耦
要执行此操作,您首先需要将数据输出分成两个
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_model_drv
的输出数据,然后ram_write_op
使用它们。out = ram_model(stimul[0] | decouple,stimul[1] | decouple)
-
将驱动程序分为两个模块,一个驱动两个接口中的每个
-
对接口使用低级同步API
在
yield
机制之下,有一个用于通过PyGears接口进行通信的较低级API。可以通过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,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