[Feature] Implement DMA support#293
Conversation
| s.mem_rd_req_val = OutPort() # dma_read_request_valid | ||
| s.mem_rd_req_rdy = InPort() # dma_read_request_ready | ||
| s.mem_rd_req_addr = OutPort(DmaDramAddrType) |
There was a problem hiding this comment.
Why can't we use the RecvIfcRTL and SendIfcRTL interfaces to connect the DmaRTL?
| s.data_mem.spm_dma_rval //= s.spm_dma_rval | ||
| s.data_mem.spm_dma_rrdy //= s.spm_dma_rrdy | ||
| s.data_mem.spm_dma_raddr //= s.spm_dma_raddr | ||
| s.data_mem.spm_dma_rresp_val //= s.spm_dma_rresp_val | ||
| s.data_mem.spm_dma_rresp_rdy //= s.spm_dma_rresp_rdy | ||
| s.data_mem.spm_dma_rresp_data //= s.spm_dma_rresp_data |
There was a problem hiding this comment.
As we discussed before, should we connect the dma to the controller (as intermediate interface/transition)? instead of directly connecting to data spm?
So then we can leverage
VectorCGRA/controller/ControllerRTL.py
Lines 138 to 139 in 44618d5
…RecvIfcRTL. Replace `mem` with `dram` for clarity.
|
Hi @tancheng @BenkangPeng , I summarized two direction of DMA design as below:
I prefer the second method but I think there are still some logic should be written in DataMemControllerRTL. WDTY? |
|
Hi @HobbitQia, option 2 looks good to me. Though I am not sure what logic should be additionally in |
I am thinking if we want enable the concurrent running of DMA and traditional load/store, then we need to multiplex the port of Data SPM and I think this logic can be implemented in |
I thought they are the same latency if we can distinguish the Adding logic inside the |
If the DMA data should go through the controller packet path, there may be extra latency of packeting, and there may be competitions between NoC/CPU/tile request to SPM? Or we have two separate paths in Controller? |
Packing can just be combinational logic before putting into a queue.
I was thinking about separate paths, so mentioned |
Got it. I mean the conflict between different paths. Even we have |
Oh, we don't need to distinguish VectorCGRA/controller/ControllerRTL.py Line 207 in eb71842 |
But if we add DMA, there should be another path |
Ah, yes, makes sense. That |
So this |
DMA engine in your figure, or @BenkangPeng's |
|
@BenkangPeng will you update this PR accordingly? |
Yes, sorry for the delay. I will update this PR as soon as possible. |
…RTL. The DMA is connected to the data memory controller indirectly via the controller, with the decoding logic integrated into the controller.
…lateRTL, and ControllerRTL.
… error of pytml verilog backend.
…interface for enhanced data transfer capabilities.
… then drives types from them
…te requests and adjust related signal handling for clarity and consistency.
…TL by passing DmaDataType and DmaCmdType as parameters, and updating related type definitions for improved clarity and consistency.
…rite requests, enhancing type definitions for DmaCmdType and DmaDataType
| YType = mk_bits(max(clog2(multi_cgra_rows), 1)) | ||
| TileIdType = mk_bits(clog2(num_tiles + 1)) | ||
| ControllerXbarPktType = mk_controller_noc_xbar_pkt(InterCgraPktType) | ||
| DmaOpcodeType = DmaCmdType.get_field_type('opcode') |
There was a problem hiding this comment.
Similar to above attr, we should use kAttrOpcode instead of opcode here?
| TileIdType = mk_bits(clog2(num_tiles + 1)) | ||
| ControllerXbarPktType = mk_controller_noc_xbar_pkt(InterCgraPktType) | ||
| DmaOpcodeType = DmaCmdType.get_field_type('opcode') | ||
| DmaDramAddrType = DmaCmdType.get_field_type('dram_addr') |
| s.dma_done //= s.controller.dma_done | ||
|
|
||
| # DMA engine <-> controller side of the SPM path. | ||
| s.dma_spm //= s.controller.dma_spm_from_dma |
There was a problem hiding this comment.
Rename this? dma_spm and dma_spm_from_dma sound confusing.
There was a problem hiding this comment.
How about s.dma_spm_from_dma //= s.controller.dma_spm_from_dma? My original idea was that dma_spm indicates the signal is used for communication between DMA and SPM, with suffixes like from_dma and to_mem indicating the direction of the signal.
There was a problem hiding this comment.
We should have two interfaces, one send and one recv, WDYT? and the "send"/"recv" should be in the name.
|
|
||
| # Abstract external dram memory interfaces for the internal DMA engine. | ||
|
|
||
| s.dram_rd_req = SendIfcRTL(DmaDramAddrType) |
There was a problem hiding this comment.
Name this as s.send_dram_rd_req, to indicate its direction.
| # Abstract external dram memory interfaces for the internal DMA engine. | ||
|
|
||
| s.dram_rd_req = SendIfcRTL(DmaDramAddrType) | ||
| s.dram_rd_resp = RecvIfcRTL(DmaMemDataType) |
There was a problem hiding this comment.
name this as s.recv_dram_rd_resp.
|
|
||
| # Components. | ||
|
|
||
| s.cgra = CgraTemplateRTL(CgraPayloadType, |
There was a problem hiding this comment.
I was actually wondering why we need this CgraDmaRTL.py. Can we just expand the CgraTemplateRTL to include the DMA-related ports/interfaces?
| s.msg = OutPort( Type ) | ||
| s.val = OutPort() | ||
| s.rdy = OutPort() | ||
| s.trace_len = len(str(Type())) |
There was a problem hiding this comment.
Can we just reuse the ValRdySendIfcRTL, but embed the trace_len into msg? The msg could have both msg.data and msg.trace_len. WDYT?
| - write : Output (Send). DMA sends write requests to SPM. | ||
| - read : Output (Send). DMA sends read requests to SPM. | ||
| - read_resp: Input (Recv). DMA receives read data from SPM. |
There was a problem hiding this comment.
Can we reuse our send/recv interfaces, instead of creating new one?
| - write : Input (Recv). SPM receives write requests from DMA. | ||
| - read : Input (Recv). SPM receives read requests from DMA. | ||
| - read_resp: Output (Send). SPM sends read data back to DMA. |
| STATE_IDLE = StateType( 0 ) # Waiting for a new DMA command | ||
| STATE_MVIN_REQ = StateType( 1 ) # MVIN: Issuing DRAM read request | ||
| STATE_MVIN_RESP = StateType( 2 ) # MVIN: Waiting for DRAM read response | ||
| STATE_MVIN_WRITE = StateType( 3 ) # MVIN: Writing unpacked words to SPM | ||
| STATE_MVOUT_READ = StateType( 4 ) # MVOUT: Issuing SPM read request | ||
| STATE_MVOUT_RESP = StateType( 5 ) # MVOUT: Receiving SPM read response and packing | ||
| STATE_MVOUT_WRITE = StateType( 6 ) # MVOUT: Issuing DRAM write request | ||
| STATE_MVOUT_WAIT = StateType( 7 ) # MVOUT: Waiting for DRAM write response | ||
| STATE_DONE = StateType( 8 ) # Signaling command completion |
There was a problem hiding this comment.
Change from STATE_xxx to STATE_DMA_xxx.
|
|
||
| return mk_bitstruct(new_name, { | ||
| 'dram_data': DramDataType, | ||
| 'dram_mask': DramMaskType, |
There was a problem hiding this comment.
explain what is dram_mask with comment?
| 'dram_data': DramDataType, | ||
| 'dram_mask': DramMaskType, | ||
| 'spm_data': SpmDataType, | ||
| 'spm_mask': SpmMaskType, |
There was a problem hiding this comment.
explain what is spm_mask with comment?
We should also include the figure 2 into our |




Related issue: coredac/CGRA-SoC#2
This PR introduces
CgraDmaRTLwhich integrates the CGRA with a DMA engine, enabling direct memory transfers between external DRAM(don't implement now) and the CGRA's dataSPM.