From f3d3de9a1000a7cf53a942267cb2de984eaafb21 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Wed, 3 Jul 2024 21:04:52 +0800 Subject: [PATCH 01/53] Initialize base types --- .gitmodules | 3 + lib/blue_wrapper | 1 + src/DmaController.bsv | 7 ++ src/DmaTypes.bsv | 37 +++++++++ src/PcieTypes.bsv | 101 ++++++++++++++++++++++++ test/TestAxiStream.bsv | 172 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 321 insertions(+) create mode 100644 .gitmodules create mode 160000 lib/blue_wrapper create mode 100644 src/DmaController.bsv create mode 100644 src/DmaTypes.bsv create mode 100644 src/PcieTypes.bsv create mode 100644 test/TestAxiStream.bsv diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a2890b5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/blue_wrapper"] + path = lib/blue_wrapper + url = https://github.com/wengwz/blue-wrapper.git diff --git a/lib/blue_wrapper b/lib/blue_wrapper new file mode 160000 index 0000000..0845f36 --- /dev/null +++ b/lib/blue_wrapper @@ -0,0 +1 @@ +Subproject commit 0845f36b1dd60b90ba5b9163ed8ca37f493f3355 diff --git a/src/DmaController.bsv b/src/DmaController.bsv new file mode 100644 index 0000000..f8030f4 --- /dev/null +++ b/src/DmaController.bsv @@ -0,0 +1,7 @@ +import PcieTypes::*; +import DmaTypes::*; + +module mkDmaController#() (DmaController ifc); + + +endmodule \ No newline at end of file diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv new file mode 100644 index 0000000..f6d8e42 --- /dev/null +++ b/src/DmaTypes.bsv @@ -0,0 +1,37 @@ + +import SemiFifo :: *; + +typedef 512 DMA_DATA_WIDTH + + +typedef struct { + Bit#(dataWidth) data; + Bit#(TDiv#(dataWidth, 8)) byteEn; + Bool isFirst; + Bool isLast; +} DataFrame#(numeric type dataWidth) deriving(Bits, Bounded, Eq, FShow); + +typedef struct { + Bit#(32) address; + Bit#(32) length; +} CtrlFrame deriving(Bits, Bounded, Eq, FShow); + +typedef struct { + Bit#(32) address; + Bit#(32) value; +} CsrFrame deriving(Bits, Bounded, Eq, FShow); + +interface DmaController#(numeric type dataWidth); + + interface FifoIn#(DataFrame#(dataWidth)) DmaDataC2HPipeIn; + interface FifoIn#(CtrlFrame) DmaCtrlC2HPipeIn; + interface FifoIn#(CtrlFrame) DmaCtrlH2CPipeIn; + interface FifoOut#(DataFrame#(dataWidth)) DmaDataH2CPipeOut; + + interface FifoIn#(CsrFrame) DmaCsrC2HPipeIn; + interface FifoOut#(CsrFrame) DmaCsrC2HPipeOut; + interface FifoOut#(CsrFrame) DmaCsrH2CPipeOut; + + interface RawPcieRequester#(TDiv#(dataWidth, 8), PCIE_USR_WIDTH) PcieRequester; + interface RawPcieCompleter#(TDiv#(dataWidth, 8), PCIE_USR_WIDTH) PcieCompleter; +endinterface diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv new file mode 100644 index 0000000..b8d016a --- /dev/null +++ b/src/PcieTypes.bsv @@ -0,0 +1,101 @@ +import AxiStreamTypes :: *; + +// from PG213 + +typedef 512 PCIE_TDATA_WIDTH +typedef 137 PCIE_TUSER_WIDTH + +typedef struct { + Bit#(8) first_be; + Bit#(8) last_be; + Bit#(4) addr_offset; + Bit#(2) is_sop; + Bit#(2) is_sop0_ptr; + Bit#(2) is_sop1_ptr; + Bit#(2) is_eop; + Bit#(4) is_eop0_ptr; + Bit#(4) is_eop1_ptr; + Bit#(1) discontinue; + Bit#(2) tph_present; + Bit#(4) tph_type; + Bit#(2) tph_indirect_tag_en; + Bit#(16) tph_st_tag; + Bit#(6) seq_num0; + Bit#(6) seq_num1; + Bit#(64) parity; +} PcieRRSideBandFrame deriving(Bits, Bounded, Eq); + +typedef struct { + Bit#(64) byte_en; + Bit#(4) is_sop; + Bit#(2) is_sop0_ptr; + Bit#(2) is_sop1_ptr; + Bit#(2) is_sop2_ptr; +} PcieRPSideBandFrame deriving(Bits, Bounded, Eq); + +interface RawPcieRequester#(numeric type keepWidth , numeric type usrWidth); + interface RawAxiStreamMaster#(keepWidth, usrWidth) Request; + interface RawAxiStreamSlave#(keepWidth, usrWidth) Complete; +endinterface + +interface RawPcieCompleter#(numeric type keepWidth, numeric type usrWidth); + interface RawAxiStreamSlave#(keepWidth, usrWidth) Request; + interface RawAxiStreamMaster#(keepWidth, usrWidth) Complete; +endinterface + +(*always_ready, always_enabled*) +interface RawPcieCfgMgmt#(); + (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; + // (* result = cfg_mgmt_byte_enable *) method Bit#(4) cfgMgmtAddr; + // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; + // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; + // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; + // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; + // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; + // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; +endinterface + +(*always_ready, always_enabled*) +interface RawPcieCfgPm#(); + +endinterface + +(*always_ready, always_enabled*) +interface RawPcieCfgMsi#(); + +endinterface + +(*always_ready, always_enabled*) +interface RawPcieCfgInterrupt#(); + +endinterface + +(*always_ready, always_enabled*) +interface RawPcieCfgControl#(); + +endinterface + +(*always_ready, always_enabled*) +interface RawPcieCfgFC#(); + +endinterface + +(*always_ready, always_enabled*) +interface RawPcieCfgFlowMsgTx#(); + +endinterface + +(*always_ready, always_enabled*) +interface RawPcieCfgFlowMsgRx#(); + +endinterface + +(*always_ready, always_enabled*) +interface RawPcieCfgStatus#(); + +endinterface + +(*always_ready, always_enabled*) +interface RawPcieCfgTransmitFC#(); + +endinterface \ No newline at end of file diff --git a/test/TestAxiStream.bsv b/test/TestAxiStream.bsv new file mode 100644 index 0000000..f293d84 --- /dev/null +++ b/test/TestAxiStream.bsv @@ -0,0 +1,172 @@ +import FIFO::*; +import Vector::*; +import AxiStreamTypes::*; +import Counter::*; + +typedef 512 DATA_WIDTH; +typedef TDiv#(DATA_WIDTH, 8) BATCH_BYTES; +typedef 128 USR_WIDTH; +typedef 4321 RD_BYTES_LENGTH; + + +interface AxisFifo#(numeric type keepWidth, numeric type usrWidth); + interface RawAxiStreamMaster#(keepWidth, usrWidth) axisMaster; + interface RawAxiStreamSlave#(keepWidth, usrWidth) axisSlave; +endinterface + + +module mkTbAxisRdWrLoop (Empty); + Reg#(File) fileIn <- mkRegU(); + Reg#(File) fileRef <- mkRegU(); + Reg#(File) fileOut <- mkRegU(); + Reg#(Bool) initFlag <- mkReg(False); + // Read the file + Reg#(Bool) rdDoneFlag <- mkReg(False); + Reg#(UInt#(32)) rdBatchCnt <- mkReg(0); + let rdTotalBytesLen = valueOf(RD_BYTES_LENGTH); + let rdBatchBytesLen = valueOf(BATCH_BYTES); + let rdLastBatchBytesLen = rdTotalBytesLen % rdBatchBytesLen; + let rdBatchesNum = rdTotalBytesLen % rdBatchBytesLen > 0 ? rdTotalBytesLen / rdBatchBytesLen + 1 : rdTotalBytesLen / rdBatchBytesLen; + FIFO#(AxiStream#(BATCH_BYTES, USR_WIDTH)) toDutFifo <- mkSizedFIFO(16); + // DUT + AxisFifo#(BATCH_BYTES, USR_WIDTH) dut <- mkTbAxisWire(); + // Control + Reg#(UInt#(32)) tValidCnt <- mkReg(0); + + rule init(!initFlag); + initFlag <= True; + File in <- $fopen("test.txt", "rb"); + File refer <- $fopen("ref.txt", "wb"); + File out <- $fopen("out.txt", "wb"); + if (in == InvalidFile || refer == InvalidFile || out == InvalidFile) begin + $display("ERROR: couldn't open test file"); + $finish; + end + fileIn <= in; + fileRef <= refer; + fileOut <= out; + endrule + + rule readfile(initFlag && !rdDoneFlag && rdBatchCnt < fromInteger(rdBatchesNum)); + Vector#(BATCH_BYTES, Bit#(8)) getChars = replicate(0); + Bit#(BATCH_BYTES) keep = 0; + Bool last = False; + if(rdBatchCnt == fromInteger(rdBatchesNum) - 1) begin + for(Integer i = 0; i < rdLastBatchBytesLen; i = i + 1) begin + int c <- $fgetc(fileIn); + if(c == -1) begin + $fclose(fileIn); + $fclose(fileRef); + end else begin + $fwrite(fileRef, "%c", c); + getChars[i] = truncate(pack(c)); + keep[i] = 1'b1; + end + end + $fclose(fileIn); + $fclose(fileRef); + rdDoneFlag <= True; + last = True; + $display("INFO: test file read done"); + end else begin + rdBatchCnt <= rdBatchCnt + 1; + for(Integer i = 0; i < rdBatchBytesLen; i = i + 1) begin + int c <- $fgetc(fileIn); + if(c == -1) begin + $fclose(fileRef); + $fclose(fileIn); + last = True; + end else begin + $fwrite(fileRef, "%c", c); + getChars[i] = truncate(pack(c)); + keep[i] = 1'b1; + end + end + end + let axis = AxiStream{ + tData: pack(getChars), + tKeep: keep, + tLast: last, + tUser: 0 + }; + toDutFifo.enq(axis); + endrule + + rule reader2dut if(rdBatchCnt > 0); + if(dut.axisSlave.tReady) begin + // $display("INFO: simulation exec a batch"); + toDutFifo.deq(); + let axis = toDutFifo.first; + dut.axisSlave.tValid( + True, + axis.tData, + axis.tKeep, + axis.tLast, + axis.tUser); + end + endrule + + rule dut2writer; + dut.axisMaster.tReady(True); + if(dut.axisMaster.tValid) begin + tValidCnt <= tValidCnt + 1; + let data = dut.axisMaster.tData; + Vector#(BATCH_BYTES, Bit#(8)) getChars = unpack(data); + let keep = dut.axisMaster.tKeep; + for(Integer i = 0; i < rdBatchBytesLen; i = i + 1) begin + if(keep[i] == 1'b1) begin $fwrite(fileOut, "%c", getChars[i]); end + end + end + if(tValidCnt == rdBatchCnt && rdDoneFlag) begin + $display("INFO: file write done, compare the ref and out") + $fclose(fileOut); + $finish(); + end + endrule + +endmodule + +module mkTbAxisWire(AxisFifo#(keepWidth, usrWidth) ifc); + Wire#(Bit#(TMul#(keepWidth, 8))) data <- mkDWire(0); + Wire#(Bit#(keepWidth)) keep <- mkDWire(0); + Wire#(Bit#(usrWidth)) user <- mkDWire(0); + Wire#(Bit#(1)) last <- mkDWire(0); + Wire#(Bit#(1)) rdy <- mkDWire(0); + Wire#(Bit#(1)) vld <- mkDWire(0); + + interface RawAxiStreamMaster axisMaster; + method Bool tValid = unpack(vld); + method Bool tLast = unpack(last); + method Bit#(TMul#(keepWidth, 8)) tData = data; + method Bit#(keepWidth) tKeep = keep; + method Bit#(usrWidth) tUser = user; + method Action tReady(Bool ready); + rdy <= pack(ready); + endmethod + endinterface + + interface RawAxiStreamSlave axisSlave; + method Bool tReady = True; + method Action tValid( + Bool tvalid, + Bit#(TMul#(keepWidth, 8)) tData, + Bit#(keepWidth) tKeep, + Bool tLast, + Bit#(usrWidth) tUser + ); + data <= tData; + keep <= tKeep; + user <= tUser; + last <= pack(tLast); + vld <= pack(tvalid); + endmethod + endinterface +endmodule + +// module mkTbAxisPipeFifo (AxisFifo#(keepWidth, usrWidth) ifc); +// FIFOF#(AxiStream#(keepWidth, usrWidth)) <- mkSizedFIFOF(10); + +// endmodule + + + From 03eb41082567c84ae012338add232f0f676b95f4 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Thu, 4 Jul 2024 10:10:52 +0800 Subject: [PATCH 02/53] init branch develop --- src/PcieTypes.bsv | 6 +++--- test/TestAxiStream.bsv | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv index b8d016a..f4a5f21 100644 --- a/src/PcieTypes.bsv +++ b/src/PcieTypes.bsv @@ -46,9 +46,9 @@ endinterface (*always_ready, always_enabled*) interface RawPcieCfgMgmt#(); (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; - // (* result = cfg_mgmt_byte_enable *) method Bit#(4) cfgMgmtAddr; - // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; - // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; + (* result = cfg_mgmt_byte_enable *) method Bit#(4) cfgMgmtByteEn; + (* result = cfg_mgmt_debug_access *) method Bool cfgMgmtAddr; + (* result = cfg_mgmt_function_number *) method Bit#(8) cfgMgmFuncNum; // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; diff --git a/test/TestAxiStream.bsv b/test/TestAxiStream.bsv index f293d84..e395336 100644 --- a/test/TestAxiStream.bsv +++ b/test/TestAxiStream.bsv @@ -89,7 +89,7 @@ module mkTbAxisRdWrLoop (Empty); tLast: last, tUser: 0 }; - toDutFifo.enq(axis); + toDutFifo.enq(axis); endrule rule reader2dut if(rdBatchCnt > 0); From 765d837f5b4911e650412a7ca9bb73c326643df9 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Thu, 4 Jul 2024 17:50:57 +0800 Subject: [PATCH 03/53] Inplement PCIe Interface Types --- src/DmaTypes.bsv | 28 ++++-- src/PcieTypes.bsv | 222 ++++++++++++++++++++++++++++++++--------- test/TestAxiStream.bsv | 74 +++++++------- 3 files changed, 228 insertions(+), 96 deletions(-) diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index f6d8e42..1904d4a 100644 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -1,25 +1,31 @@ import SemiFifo :: *; +import PcieTypes :: *; -typedef 512 DMA_DATA_WIDTH - +typedef 512 DMA_DATA_WIDTH; +typedef 64 DMA_HOSTMEM_ADDR_WIDTH; +typedef 32 DMA_CSR_ADDR_WIDTH; +typedef 32 DMA_CSR_DATA_WIDTH; +typedef Bit#(DMA_HOSTMEM_ADDR_WIDTH) DmaMemAddr; +typedef Bit#(DMA_CSR_ADDR_WIDTH) DMACsrAddr; +typedef Bit#(DMA_CSR_DATA_WIDTH) DMACsrValue; typedef struct { Bit#(dataWidth) data; - Bit#(TDiv#(dataWidth, 8)) byteEn; + Bit#(TDiv#(dataWidth, BYTE_BITS)) byteEn; Bool isFirst; Bool isLast; } DataFrame#(numeric type dataWidth) deriving(Bits, Bounded, Eq, FShow); typedef struct { - Bit#(32) address; - Bit#(32) length; -} CtrlFrame deriving(Bits, Bounded, Eq, FShow); + DmaMemAddr startAddr; + DmaMemAddr length; +} DmaCtrlFrame deriving(Bits, Bounded, Eq, FShow); typedef struct { - Bit#(32) address; - Bit#(32) value; -} CsrFrame deriving(Bits, Bounded, Eq, FShow); + DMACsrAddr address; + DMACsrValue value; +} DmaCsrFrame deriving(Bits, Bounded, Eq, FShow); interface DmaController#(numeric type dataWidth); @@ -32,6 +38,6 @@ interface DmaController#(numeric type dataWidth); interface FifoOut#(CsrFrame) DmaCsrC2HPipeOut; interface FifoOut#(CsrFrame) DmaCsrH2CPipeOut; - interface RawPcieRequester#(TDiv#(dataWidth, 8), PCIE_USR_WIDTH) PcieRequester; - interface RawPcieCompleter#(TDiv#(dataWidth, 8), PCIE_USR_WIDTH) PcieCompleter; + interface RawPcieRequester PcieRequester; + interface RawPcieCompleter PcieCompleter; endinterface diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv index f4a5f21..f2800d0 100644 --- a/src/PcieTypes.bsv +++ b/src/PcieTypes.bsv @@ -1,58 +1,184 @@ import AxiStreamTypes :: *; -// from PG213 - -typedef 512 PCIE_TDATA_WIDTH -typedef 137 PCIE_TUSER_WIDTH - +typedef 8 BYTE_BITS +typedef TMul#(4, BYTE_BITS) DWORD_BITS; + +typedef 512 PCIE_TDATA_WIDTH; +typedef 64 PCIE_TDATA_BYTES; +typedef 16 PCIE_TDATA_DWORDS; +// Indicate DWORD valid of tDATA +typedef PCIE_TDATA_DWORDS PCIE_TKEEP_WIDTH; +// tUser width vary among RR, RC, CR and CC +typedef 183 PCIE_COMPLETER_REQUEST_TUSER_WIDTH; +typedef 81 PCIE_COMPLETER_COMPLETE_TUSER_WIDTH; +typedef 137 PCIE_REQUESTER_REQUEST_TUSER_WIDTH; +typedef 161 PCIE_REQUESTER_COMPLETE_TUSER_WIDTH; + +// PcieTlpCtl**: SideBand Signals delivered in tUser defined by PG213 +typedef 8 PCIE_TLP_FIRST_BE_WIDTH; +typedef 8 PCIE_TLP_LAST_BE_WIDTH; +typedef Bit#(PCIE_TLP_FIRST_BE_WIDTH) PcieTlpCtlFirstByteEn; +typedef Bit#(PCIE_TLP_LAST_BE_WIDTH) PcieTlpCtlLastByteEn; +typedef PCIE_TDATA_BYTES PCIE_TLP_BYTE_EN_WIDTH; +typedef Bit#(PCIE_TLP_BYTE_EN_WIDTH) PcieTlpCtlByteEn; +typedef 2 PCIE_TLP_ISSOP_WIDTH; +typedef 2 PCIE_TLP_ISSOP_PTR_WIDTH; +typedef Bit#(PCIE_TLP_ISSOP_WIDTH) PcieTlpCtlIsSop; +typedef Bit#(PCIE_TLP_ISSOP_PTR_WIDTH) PcieTlpCtlIsSopPtr; +typedef 2 PCIE_TLP_ISEOP_WIDTH; +typedef 4 PCIE_TLP_ISEOP_PTR_WIDTH; +typedef Bit#(PCIE_TLP_ISEOP_WIDTH) PcieTlpCtlIsEop; +typedef Bit#(PCIE_TLP_ISEOP_PTR_WIDTH) PcieTlpCtlIsEopPtr; +typedef 2 PCIE_TPH_PRESENT_WIDTH; +typedef 4 PCIE_TPH_TYPE_WIDTH; +typedef 16 PCIE_TPH_STTAG; +typedef 2 PCIE_TPH_INDIRECT_TAGEN_WIDTH; +typedef Bit#(PCIE_TPH_PRESENT_WIDTH) PcieTlpCtlTphPresent; +typedef Bit#(PCIE_TPH_TYPE_WIDTH) PcieTlpCtlTphType; +typedef Bit#(PCIE_TPH_STTAG) PcieTlpCtlTphSteeringTag; +typedef Bit#(PCIE_TPH_INDIRECT_TAGEN_WIDTH) PcieTlpCtlTphIndirectTagEn; +typedef 64 PCIE_TLP_PARITY +typedef Bit#(PCIE_TLP_PARITY) PcieTlpCtlParity; +typedef 4 PCIE_TLP_ADDR_OFFSET_WIDTH; +typedef Bit#(PCIE_TLP_ADDR_OFFSET_WIDTH) PcieTlpCtlAddrOffset; +typedef 6 PCIE_TLP_SEQ_NUM_WIDTH; +typedef Bit#(PCIE_TLP_SEQ_NUM_WIDTH) PcieTlpCtlSeqNum; +typedef 4 PCIE_TLP_RC_ISSOP_WIDTH; +typedef Bit#(PCIE_TLP_RC_ISSOP_WIDTH) PcieTlpCtlIsSopRC; +typedef 4 PCIE_TLP_RC_ISEOP_WIDTH; +typedef Bit#(PCIE_TLP_RC_ISEOP_WIDTH) PcieTlpCtlIsEopRC; +// Signals the start of a new TLP, 6 bit. typedef struct { - Bit#(8) first_be; - Bit#(8) last_be; - Bit#(4) addr_offset; - Bit#(2) is_sop; - Bit#(2) is_sop0_ptr; - Bit#(2) is_sop1_ptr; - Bit#(2) is_eop; - Bit#(4) is_eop0_ptr; - Bit#(4) is_eop1_ptr; - Bit#(1) discontinue; - Bit#(2) tph_present; - Bit#(4) tph_type; - Bit#(2) tph_indirect_tag_en; - Bit#(16) tph_st_tag; - Bit#(6) seq_num0; - Bit#(6) seq_num1; - Bit#(64) parity; -} PcieRRSideBandFrame deriving(Bits, Bounded, Eq); - + PcieTlpCtlIsSop isSop; + PcieTlpCtlIsSopPtr isSopPtr0; + PcieTlpCtlIsSopPtr isSopPtr1; +} PcieTlpCtlIsSopCommon deriving(Bits, Bounded, Eq); +// Signals the start of a new TLP, 12 bit. +typedef struct { + PcieTlpCtlIsSopRC isSop; + PcieTlpCtlIsSopPtr isSopPtr0; + PcieTlpCtlIsSopPtr isSopPtr1; + PcieTlpCtlIsSopPtr isSopPtr2; + PcieTlpCtlIsSopPtr isSopPtr3; +} PcieTlpCtlIsSopReqCpl deriving(Bits, Bounded, Eq); +// Indicates a TLP is ending in this beat, 10bit. +typedef struct { + PcieTlpCtlIsEop isEop; + PcieTlpCtlIsEopPtr isEopPtr0; + PcieTlpCtlIsEopPtr isEopPtr1; +} PcieTlpCtlIsEopCommon deriving(Bits, Bounded, Eq); +// Indicates a TLP is ending in this beat, 20bit. +typedef struct { + PcieTlpCtlIsEopRC isEop; + PcieTlpCtlIsEopPtr isEopPtr0; + PcieTlpCtlIsEopPtr isEopPtr1; + PcieTlpCtlIsEopPtr isEopPtr2; + PcieTlpCtlIsEopPtr isEopPtr3; +} PcieTlpCtlIsEopReqCpl deriving(Bits, Bounded, Eq); + +// 183bit tUser of PcieCompleterRequeste AXIS-slave typedef struct { - Bit#(64) byte_en; - Bit#(4) is_sop; - Bit#(2) is_sop0_ptr; - Bit#(2) is_sop1_ptr; - Bit#(2) is_sop2_ptr; -} PcieRPSideBandFrame deriving(Bits, Bounded, Eq); - -interface RawPcieRequester#(numeric type keepWidth , numeric type usrWidth); - interface RawAxiStreamMaster#(keepWidth, usrWidth) Request; - interface RawAxiStreamSlave#(keepWidth, usrWidth) Complete; + PcieTlpCtlFirstByteEn firstByteEn; + PcieTlpCtlLastByteEn lastByteEn; + PcieTlpCtlByteEn dataByteEn; + PcieTlpCtlIsSopCommon isSop; + PcieTlpCtlIsEopCommon isEop; + Bool discontinue; + PcieTlpCtlTphPresent tphPresent; + PcieTlpCtlTphType tphType; + PcieTlpCtlTphSteeringTag tphSteeringTag; + PcieTlpCtlParity parity; +} PcieCompleterRequestSideBandFrame deriving(Bits, Bounded, Eq); +// 81bit tUser of PcieCompleterComplete AXIS-master +typedef struct { + PcieTlpCtlIsSopCommon isSop; + PcieTlpCtlIsEopCommon isEop; + Bool discontinue; + PcieTlpCtlParity parity; +} PcieCompleterCompleteSideBandFrame deriving(Bits, Bounded, Eq); +// 137bit tUser of PcieRequesterRequeste AXIS-master +typedef struct { + PcieTlpCtlFirstByteEn firstByteEn; + PcieTlpCtlLastByteEn lastByteEn + PcieTlpCtlAddrOffset addrOffset; + PcieTlpCtlIsSopCommon isSop; + PcieTlpCtlIsEopCommon isEop; + Bool discontinue; + PcieTlpCtlTphPresent tphPresent; + PcieTlpCtlTphType tphType; + PcieTlpCtlTphIndirectTagEn tphIndirectTagEn; + PcieTlpCtlTphSteeringTag tphSteeringTag; + PcieTlpCtlSeqNum seqNum0; + PcieTlpCtlSeqNum seqNum1; + PcieTlpCtlParity parity; +} PcieRequsterRequestSideBandFrame deriving(Bits, Bounded, Eq); +// 161 tUser of PcieRequesterComplete AXIS-slave +typedef struct { + PcieTlpCtlByteEn dataByteEn; + PcieTlpCtlIsSopReqCpl isSop; + PcieTlpCtlIsEopReqCpl isEop; + Bool discontinue; + PcieTlpCtlParity parity; +} PcieRequesterCompleteSideBandFrame deriving(Bits, Bounded, Eq); + + +typedef 2 PCIE_CR_NP_REQ_WIDTH; +typedef 6 PCIE_CR_NP_REQ_COUNT_WIDTH; +typedef Bit#(PCIE_CR_NP_REQ_WIDTH) PcieNonPostedRequst; +typedef Bit#(PCIE_CR_NP_REQ_COUNT_WIDTH) PcieNonPostedRequstCount; +// Interface to PCIe IP Completer Interface +(*always_ready, always_enabled*) +interface RawPcieCompleter; + // TODO: the AxiStream in blue-wrapper has tDataWidth = tKeepWidth * BYTE_BITS, but the PCIe IP has tDataWidth = tKeepWidth * DWORD_BITS + (* prefix = "s_axis_cq_" *) interface RawAxiStreamSlave#(PCIE_TKEEP_WIDTH, PCIE_COMPLETER_REQUEST_TUSER_WIDTH) Request; + // (* result = "pcie_cq_np_req" *) method PcieNonPostedRequst nonPostedReqCreditIncrement; + // (* prefix = "" *) method Action nonPostedReqCreditCnt( + // (* port = "pcie_cq_np_req_count" *) PcieNonPostedRequstCount ); + (* prefix = "m_axis_cc_" *) interface RawAxiStreamMaster#(PCIE_TKEEP_WIDTH, PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) Complete; +endinterface + +// Interface to PCIe IP Requester Interface +(*always_ready, always_enabled*) +interface RawPcieRequester; + (* prefix = "m_axis_rq_" *) interface RawAxiStreamMaster#(PCIE_TKEEP_WIDTH, usrWidth) Request; + (* prefix = "s_axis_rc_" *) interface RawAxiStreamSlave#(PCIE_TKEEP_WIDTH, usrWidth) Complete; endinterface -interface RawPcieCompleter#(numeric type keepWidth, numeric type usrWidth); - interface RawAxiStreamSlave#(keepWidth, usrWidth) Request; - interface RawAxiStreamMaster#(keepWidth, usrWidth) Complete; +typedef 10 PCIE_CFG_MGMT_ADDR_WIDTH; +typedef 4 PCIE_CFG_MGMT_BE_WIDTH; +typedef 8 PCIE_CFG_MGMT_FUNC_NUM_WIDTH; +typedef 32 PCIE_CFG_MGMT_DATA_WIDTH; +typedef Bit#(PCIE_CFG_MGMT_ADDR_WIDTH) PcieCfgMgmtAddr; +typedef Bit#(PCIE_CFG_MGMT_BE_WIDTH) PcieCfgMgmtByteEn; +typedef Bit#(PCIE_CFG_MGMT_FUNC_NUM_WIDTH) PcieCfgMgmtFuncNum; +typedef Bit#(PCIE_CFG_MGMT_DATA_WIDTH) PCieCfgMgmtData; + +interface RawPcieConfiguration; + (* prefix = "cfg_mgmt_" *) interface RawPcieCfgMgmt; + (* prefix = "cfg_pm_" *) interface RawPcieCfgPm; + (* prefix = "cfg_msi_" *) interface RawPcieCfgMsi; + (* prefix = "cfg_interrupt_" *) interface RawPcieCfgInterrupt; + (* prefix = "cfg_" *) interface RawPcieCfgControl; + (* prefix = "cfg_fc_" *) interface RawPcieCfgFC; + (* prefix = "cfg_msg_transmit_" *) interface RawPcieCfgMsgTx; + (* prefix = "cfg_msg_received_" *) interface RawPcieCfgMsgRx; + (* prefix = "" *) interface RawPcieCfgStatus; + (* prefix = "pcie_tfc_" *) interface RawPcieCfgTransmitFC; endinterface (*always_ready, always_enabled*) -interface RawPcieCfgMgmt#(); - (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; - (* result = cfg_mgmt_byte_enable *) method Bit#(4) cfgMgmtByteEn; - (* result = cfg_mgmt_debug_access *) method Bool cfgMgmtAddr; - (* result = cfg_mgmt_function_number *) method Bit#(8) cfgMgmFuncNum; - // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; - // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; - // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; - // (* result = cfg_mgmt_addr *) method Bit#(10) cfgMgmtAddr; +interface RawPcieCfgMgmt; + (* result = addr *) method PcieCfgMgmtAddr cfgMgmtAddr; + (* result = byte_enable *) method PcieCfgMgmtByteEn cfgMgmtByteEn; + (* result = debug_access *) method Bool cfgMgmtDebugAccess; + (* result = function_number *) method PcieCfgMgmtFuncNum cfgMgmtFuncNum; + (* result = read *) method Bool cfgMgmtRead; + (* result = write_data *) method PCieCfgMgmtData cfgMgmtWriteData; + (* result = write *) method Bool cfgMgmtWrite; + (* prefix = "" *) method Action cfgMgmtReadData( + (* port = "read_data" *) PCieCfgMgmtData cfgMgmtRdData); + (* prefix = "" *) method Action cfgMgmtWriteDone( + (* port = "write_done" *) Bool cfgMgmtWrDone); endinterface (*always_ready, always_enabled*) @@ -81,12 +207,12 @@ interface RawPcieCfgFC#(); endinterface (*always_ready, always_enabled*) -interface RawPcieCfgFlowMsgTx#(); +interface RawPcieCfgMsgTx#(); endinterface (*always_ready, always_enabled*) -interface RawPcieCfgFlowMsgRx#(); +interface RawPcieCfgMsgRx#(); endinterface diff --git a/test/TestAxiStream.bsv b/test/TestAxiStream.bsv index e395336..1595a41 100644 --- a/test/TestAxiStream.bsv +++ b/test/TestAxiStream.bsv @@ -16,13 +16,13 @@ endinterface module mkTbAxisRdWrLoop (Empty); - Reg#(File) fileIn <- mkRegU(); - Reg#(File) fileRef <- mkRegU(); - Reg#(File) fileOut <- mkRegU(); - Reg#(Bool) initFlag <- mkReg(False); + Reg#(File) fileInReg <- mkRegU(); + Reg#(File) fileRefReg <- mkRegU(); + Reg#(File) fileOutReg <- mkRegU(); + Reg#(Bool) initFlagReg <- mkReg(False); // Read the file - Reg#(Bool) rdDoneFlag <- mkReg(False); - Reg#(UInt#(32)) rdBatchCnt <- mkReg(0); + Reg#(Bool) rdDoneFlagReg <- mkReg(False); + Reg#(UInt#(32)) rdBatchCntReg <- mkReg(0); let rdTotalBytesLen = valueOf(RD_BYTES_LENGTH); let rdBatchBytesLen = valueOf(BATCH_BYTES); let rdLastBatchBytesLen = rdTotalBytesLen % rdBatchBytesLen; @@ -33,8 +33,8 @@ module mkTbAxisRdWrLoop (Empty); // Control Reg#(UInt#(32)) tValidCnt <- mkReg(0); - rule init(!initFlag); - initFlag <= True; + rule init(!initFlagReg); + initFlagReg <= True; File in <- $fopen("test.txt", "rb"); File refer <- $fopen("ref.txt", "wb"); File out <- $fopen("out.txt", "wb"); @@ -42,44 +42,44 @@ module mkTbAxisRdWrLoop (Empty); $display("ERROR: couldn't open test file"); $finish; end - fileIn <= in; - fileRef <= refer; - fileOut <= out; + fileInReg <= in; + fileRefReg <= refer; + fileOutReg <= out; endrule - rule readfile(initFlag && !rdDoneFlag && rdBatchCnt < fromInteger(rdBatchesNum)); + rule readfile(initFlagReg && !rdDoneFlagReg && rdBatchCntReg < fromInteger(rdBatchesNum)); Vector#(BATCH_BYTES, Bit#(8)) getChars = replicate(0); Bit#(BATCH_BYTES) keep = 0; Bool last = False; - if(rdBatchCnt == fromInteger(rdBatchesNum) - 1) begin - for(Integer i = 0; i < rdLastBatchBytesLen; i = i + 1) begin - int c <- $fgetc(fileIn); + if(rdBatchCntReg == fromInteger(rdBatchesNum) - 1) begin + for(Integer idx = 0; idx < rdLastBatchBytesLen; idx = idx + 1) begin + int c <- $fgetc(fileInReg); if(c == -1) begin - $fclose(fileIn); - $fclose(fileRef); + $fclose(fileInReg); + $fclose(fileRefReg); end else begin - $fwrite(fileRef, "%c", c); - getChars[i] = truncate(pack(c)); - keep[i] = 1'b1; + $fwrite(fileRefReg, "%c", c); + getChars[idx] = truncate(pack(c)); + keep[idx] = 1'b1; end end - $fclose(fileIn); - $fclose(fileRef); - rdDoneFlag <= True; + $fclose(fileInReg); + $fclose(fileRefReg); + rdDoneFlagReg <= True; last = True; $display("INFO: test file read done"); end else begin - rdBatchCnt <= rdBatchCnt + 1; - for(Integer i = 0; i < rdBatchBytesLen; i = i + 1) begin - int c <- $fgetc(fileIn); - if(c == -1) begin - $fclose(fileRef); - $fclose(fileIn); + rdBatchCntReg <= rdBatchCntReg + 1; + for(Integer idx = 0; idx < rdBatchBytesLen; idx = idx + 1) begin + int rdChar <- $fgetc(fileInReg); + if(rdChar == -1) begin + $fclose(fileRefReg); + $fclose(fileInReg); last = True; end else begin - $fwrite(fileRef, "%c", c); - getChars[i] = truncate(pack(c)); - keep[i] = 1'b1; + $fwrite(fileRefReg, "%c", rdChar); + getChars[idx] = truncate(pack(rdChar)); + keep[idx] = 1'b1; end end end @@ -92,7 +92,7 @@ module mkTbAxisRdWrLoop (Empty); toDutFifo.enq(axis); endrule - rule reader2dut if(rdBatchCnt > 0); + rule reader2dut if(rdBatchCntReg > 0); if(dut.axisSlave.tReady) begin // $display("INFO: simulation exec a batch"); toDutFifo.deq(); @@ -113,13 +113,13 @@ module mkTbAxisRdWrLoop (Empty); let data = dut.axisMaster.tData; Vector#(BATCH_BYTES, Bit#(8)) getChars = unpack(data); let keep = dut.axisMaster.tKeep; - for(Integer i = 0; i < rdBatchBytesLen; i = i + 1) begin - if(keep[i] == 1'b1) begin $fwrite(fileOut, "%c", getChars[i]); end + for(Integer idx = 0; idx < rdBatchBytesLen; idx = idx + 1) begin + if(keep[idx] == 1'b1) begin $fwrite(fileOutReg, "%c", getChars[i]); end end end - if(tValidCnt == rdBatchCnt && rdDoneFlag) begin + if(tValidCnt == rdBatchCntReg && rdDoneFlagReg) begin $display("INFO: file write done, compare the ref and out") - $fclose(fileOut); + $fclose(fileOutReg); $finish(); end endrule From f259b917a3de85e3a20dadcca6a14dd08065d484 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Thu, 4 Jul 2024 18:01:15 +0800 Subject: [PATCH 04/53] Inplement PCIe Interface Types --- src/DmaTypes.bsv | 12 +++++++----- test/TestAxiStream.bsv | 19 ++++++++++--------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index 1904d4a..30b60da 100644 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -30,14 +30,16 @@ typedef struct { interface DmaController#(numeric type dataWidth); interface FifoIn#(DataFrame#(dataWidth)) DmaDataC2HPipeIn; - interface FifoIn#(CtrlFrame) DmaCtrlC2HPipeIn; - interface FifoIn#(CtrlFrame) DmaCtrlH2CPipeIn; + interface FifoIn#(DmaCtrlFrame) DmaCtrlC2HPipeIn; + interface FifoIn#(DmaCtrlFrame) DmaCtrlH2CPipeIn; interface FifoOut#(DataFrame#(dataWidth)) DmaDataH2CPipeOut; - interface FifoIn#(CsrFrame) DmaCsrC2HPipeIn; - interface FifoOut#(CsrFrame) DmaCsrC2HPipeOut; - interface FifoOut#(CsrFrame) DmaCsrH2CPipeOut; + interface FifoIn#(DmaCsrFrame) DmaCsrC2HPipeIn; + interface FifoOut#(DMACsrAddr) DmaCsrC2HPipeOut; + interface FifoOut#(DmaCsrFrame) DmaCsrH2CPipeOut; interface RawPcieRequester PcieRequester; interface RawPcieCompleter PcieCompleter; + interface RawPcieConfiguration PcieConfig; + endinterface diff --git a/test/TestAxiStream.bsv b/test/TestAxiStream.bsv index 1595a41..bd30140 100644 --- a/test/TestAxiStream.bsv +++ b/test/TestAxiStream.bsv @@ -4,7 +4,8 @@ import AxiStreamTypes::*; import Counter::*; typedef 512 DATA_WIDTH; -typedef TDiv#(DATA_WIDTH, 8) BATCH_BYTES; +typedef 8 BYTE_BITS; +typedef TDiv#(DATA_WIDTH, BYTE_BITS) BATCH_BYTES; typedef 128 USR_WIDTH; typedef 4321 RD_BYTES_LENGTH; @@ -48,18 +49,18 @@ module mkTbAxisRdWrLoop (Empty); endrule rule readfile(initFlagReg && !rdDoneFlagReg && rdBatchCntReg < fromInteger(rdBatchesNum)); - Vector#(BATCH_BYTES, Bit#(8)) getChars = replicate(0); + Vector#(BATCH_BYTES, Bit#(BYTE_BITS)) getChars = replicate(0); Bit#(BATCH_BYTES) keep = 0; Bool last = False; if(rdBatchCntReg == fromInteger(rdBatchesNum) - 1) begin for(Integer idx = 0; idx < rdLastBatchBytesLen; idx = idx + 1) begin - int c <- $fgetc(fileInReg); - if(c == -1) begin + int readChar <- $fgetc(fileInReg); + if(readChar == -1) begin $fclose(fileInReg); $fclose(fileRefReg); end else begin - $fwrite(fileRefReg, "%c", c); - getChars[idx] = truncate(pack(c)); + $fwrite(fileRefReg, "%c", readChar); + getChars[idx] = truncate(pack(readChar)); keep[idx] = 1'b1; end end @@ -92,10 +93,10 @@ module mkTbAxisRdWrLoop (Empty); toDutFifo.enq(axis); endrule - rule reader2dut if(rdBatchCntReg > 0); + rule reader2dut if (rdBatchCntReg > 0); if(dut.axisSlave.tReady) begin // $display("INFO: simulation exec a batch"); - toDutFifo.deq(); + toDutFifo.deq; let axis = toDutFifo.first; dut.axisSlave.tValid( True, @@ -111,7 +112,7 @@ module mkTbAxisRdWrLoop (Empty); if(dut.axisMaster.tValid) begin tValidCnt <= tValidCnt + 1; let data = dut.axisMaster.tData; - Vector#(BATCH_BYTES, Bit#(8)) getChars = unpack(data); + Vector#(BATCH_BYTES, Bit#(BYTE_BITS)) getChars = unpack(data); let keep = dut.axisMaster.tKeep; for(Integer idx = 0; idx < rdBatchBytesLen; idx = idx + 1) begin if(keep[idx] == 1'b1) begin $fwrite(fileOutReg, "%c", getChars[i]); end From a4a8d12b8bd654b689448d93ca3a6c685463ab0e Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Fri, 5 Jul 2024 20:35:59 +0800 Subject: [PATCH 05/53] update mkChunkComputer --- img/split.drawio | 100 +++++++++++++++++++++++++++++++++++++++++ src/DmaRequestCore.bsv | 99 ++++++++++++++++++++++++++++++++++++++++ src/DmaTypes.bsv | 12 ++--- src/PcieTypes.bsv | 11 +++-- 4 files changed, 212 insertions(+), 10 deletions(-) create mode 100644 img/split.drawio create mode 100644 src/DmaRequestCore.bsv diff --git a/img/split.drawio b/img/split.drawio new file mode 100644 index 0000000..6e78ab1 --- /dev/null +++ b/img/split.drawio @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/DmaRequestCore.bsv b/src/DmaRequestCore.bsv new file mode 100644 index 0000000..e2220ab --- /dev/null +++ b/src/DmaRequestCore.bsv @@ -0,0 +1,99 @@ +import FIFOF::*; +import PcieTypes::*; +import DmaTypes::*; + +typedef 4096 BUS_BOUNDARY +typedef 12 BUS_BOUNDARY_WIDTH + +typedef struct { + DmaRequestFrame dmaRequest; + Maybe#(DmaMemAddr) firstChunkLen; +} ChunkRequestFrame deriving(Bits, Eq); + +Interface ChunkCompute; + FifoIn#(DmaRequestFrame) dmaRequests; + FifoOut#(DmaRequestFrame) chunkRequests; +endinterface + +module mkChunkComputer(ChunkCompute ifc); + FIFOF#(DmaRequestFrame) inputFifo <- mkFIFOF; + FIFOF#(DmaRequestFrame) outputFifo <- mkFIFOF; + FIFOF#(ChunkRequestFrame) splitFifo <- mkFIFOF; + + Reg#(DmaMemAddr) newChunkPtrReg <- mkReg(0); + Reg#(DmaMemAddr) totalLenRemainReg <- mkReg(0); + Reg#(Bool) isSplittigReg <- mkReg(False); + + function Bool hasBoundary(DmaRequestFrame request); + let highIdx = (request.startAddr + request.length) >> BUS_BOUNDARY_WIDTH; + let lowIdx = request.startAddr >> BUS_BOUNDARY_WIDTH; + return (highIdx > lowIdx); + endfunction + + function DmaMemAddr getOffset(DmaRequestFrame request); + DmaMemAddr offset = zeroExtend(fromInteger(valueOf(BUS_BOUNDARY)) - pack(request.startAddr[BUS_BOUNDARY_WIDTH-1:0])); + return offset; + endfunction + + rule getfirstChunkLen if(inputFifo.notEmpty && splitFifo.notFull); + let request = inputFifo.first; + inputFifo.deq; + let offset = getOffSet(request); + // firstChunkLen = offset % PCIE_TLP_BYTES + DmaMemAddr firstLen = zeroExtend(offset[valueOf(PCIE_TLP_BYTES_WIDTH)-1:0]); + ChunkRequestFrame splitRequest = { + dmaRequest: request, + firstChunkLen: hasBoundary(request) ? tagged Valid firstLen : tagged Invalid; + } + splitFifo.enq(splitRequest); + endrule + + rule execSplit if(splitFifo.notEmpty && outFifo.notFull); + let splitRequest = splitFifo.first; + if (isSplittingReg) begin + if (totalLenRemainReg <= PCIE_TLP_BYTES) begin + isSplittingReg <= False; + outputFifo.enq(DmaRequestFrame { + startAddr: newChunkPtrReg; + length: totalLenRemainReg; + }); + splitFifo.deq; + totalLenRemainReg <= 0; + end else begin + isSplittingReg <= True; + outputFifo.enq(DmaRequestFrame { + startAddr: newChunkPtrReg; + length: fromInteger(valueOf(PCIE_TLP_BYTES)); + }); + newChunkPtrReg <= newChunkPtrReg + fromInteger(valueOf(PCIE_TLP_BYTES)); + totalLenRemainReg <= totalLenRemainReg - PCIE_TLP_BYTES; + end + end else begin + let remainderLength = splitRequest.dmaRequest.length - fromMaybe(0, splitRequest.firstChunkLen); + if (isValid(splitRequest.firstChunkLen)) begin + Bool isSplittingNextCycle = (remainderLength > 0); + isSplittingReg <= isSplittingNextCycle; + outputFifo.enq(DmaRequestFrame { + startAddr: splitRequest.dmaRequest.startAddr; + length: fromMaybe(0, splitRequest.firstChunkLen); + }); + if (!isSplittingNextCycle) begin splitFifo.deq; end; + newChunkPtrReg <= splitRequest.dmaRequest + fromMaybe(0, splitRequest.firstChunkLen); + totalLenRemainReg <= remainderLength; + end else begin + Bool isSplittingNextCycle = (remainderLength > PCIE_TLP_BYTES); + isSplittingReg <= isSplittingNextCycle; + outputFifo.enq(DmaRequestFrame { + startAddr: splitRequest.dmaRequest.startAddr; + length: fromInteger(valueOf(PCIE_TLP_BYTES)); + }); + if (!isSplittingNextCycle) begin splitFifo.deq; end + newChunkPtrReg <= newChunkPtrReg + fromInteger(valueOf(PCIE_TLP_BYTES)); + totalLenRemainReg <= remainderLength - PCIE_TLP_BYTES; + end + end + endrule + + interface dmaRequests = convertFifoToFifoOut(inputFifo); + interface chunkRequests = convertFifoToFifoOut(outputFifo); +endmodule \ No newline at end of file diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index 30b60da..27c4035 100644 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -20,7 +20,7 @@ typedef struct { typedef struct { DmaMemAddr startAddr; DmaMemAddr length; -} DmaCtrlFrame deriving(Bits, Bounded, Eq, FShow); +} DmaRequestFrame deriving(Bits, Bounded, Eq, FShow); typedef struct { DMACsrAddr address; @@ -30,13 +30,13 @@ typedef struct { interface DmaController#(numeric type dataWidth); interface FifoIn#(DataFrame#(dataWidth)) DmaDataC2HPipeIn; - interface FifoIn#(DmaCtrlFrame) DmaCtrlC2HPipeIn; - interface FifoIn#(DmaCtrlFrame) DmaCtrlH2CPipeIn; + interface FifoIn#(DmaRequestFrame) DmaCtrlC2HPipeIn; + interface FifoIn#(DmaRequestFrame) DmaCtrlH2CPipeIn; interface FifoOut#(DataFrame#(dataWidth)) DmaDataH2CPipeOut; - interface FifoIn#(DmaCsrFrame) DmaCsrC2HPipeIn; - interface FifoOut#(DMACsrAddr) DmaCsrC2HPipeOut; - interface FifoOut#(DmaCsrFrame) DmaCsrH2CPipeOut; + interface FifoIn#(DmaCsrFrame) DmaCsrC2HPipeIn; + interface FifoOut#(DMACsrAddr) DmaCsrC2HPipeOut; + interface FifoOut#(DmaCsrFrame) DmaCsrH2CPipeOut; interface RawPcieRequester PcieRequester; interface RawPcieCompleter PcieCompleter; diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv index f2800d0..d2fddd3 100644 --- a/src/PcieTypes.bsv +++ b/src/PcieTypes.bsv @@ -1,7 +1,10 @@ import AxiStreamTypes :: *; -typedef 8 BYTE_BITS -typedef TMul#(4, BYTE_BITS) DWORD_BITS; +typedef 8 BYTE_WIDTH +typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; + +typedef 512 PCIE_TLP_BYTES +typedef #TLog(PCIE_TLP_BYTES) PCIE_TLP_BYTES_WIDTH typedef 512 PCIE_TDATA_WIDTH; typedef 64 PCIE_TDATA_BYTES; @@ -112,7 +115,7 @@ typedef struct { PcieTlpCtlSeqNum seqNum1; PcieTlpCtlParity parity; } PcieRequsterRequestSideBandFrame deriving(Bits, Bounded, Eq); -// 161 tUser of PcieRequesterComplete AXIS-slave +// 161bit tUser of PcieRequesterComplete AXIS-slave typedef struct { PcieTlpCtlByteEn dataByteEn; PcieTlpCtlIsSopReqCpl isSop; @@ -129,7 +132,7 @@ typedef Bit#(PCIE_CR_NP_REQ_COUNT_WIDTH) PcieNonPostedRequstCount; // Interface to PCIe IP Completer Interface (*always_ready, always_enabled*) interface RawPcieCompleter; - // TODO: the AxiStream in blue-wrapper has tDataWidth = tKeepWidth * BYTE_BITS, but the PCIe IP has tDataWidth = tKeepWidth * DWORD_BITS + // TODO: the AxiStream in blue-wrapper has tDataWidth = tKeepWidth * BYTE_WIDTH, but the PCIe IP has tDataWidth = tKeepWidth * DWORD_WIDTH (* prefix = "s_axis_cq_" *) interface RawAxiStreamSlave#(PCIE_TKEEP_WIDTH, PCIE_COMPLETER_REQUEST_TUSER_WIDTH) Request; // (* result = "pcie_cq_np_req" *) method PcieNonPostedRequst nonPostedReqCreditIncrement; // (* prefix = "" *) method Action nonPostedReqCreditCnt( From 2cc532cfc4fb8ee34b41ff338cfda1a455856b13 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Sun, 7 Jul 2024 19:49:35 +0800 Subject: [PATCH 06/53] Add mkChunkComputeTb and test pass --- .gitignore | 3 + Makefile.base | 26 +++++ Makefile.test | 18 +++ backend/Makefile | 40 +++++++ backend/listVlogFiles.tcl | 223 ++++++++++++++++++++++++++++++++++++++ img/concat.drawio | 22 ++++ run.sh | 29 +++++ run_one.sh | 37 +++++++ setup.sh | 22 ++++ src/DmaRequestCore.bsv | 100 +++++++++-------- src/DmaTypes.bsv | 22 ++-- src/PcieTypes.bsv | 74 ++++++------- test/Makefile | 22 ++++ test/TestDmaCore.bsv | 78 +++++++++++++ 14 files changed, 620 insertions(+), 96 deletions(-) create mode 100644 .gitignore create mode 100755 Makefile.base create mode 100755 Makefile.test create mode 100644 backend/Makefile create mode 100644 backend/listVlogFiles.tcl create mode 100644 img/concat.drawio create mode 100755 run.sh create mode 100755 run_one.sh create mode 100755 setup.sh create mode 100644 test/Makefile create mode 100644 test/TestDmaCore.bsv diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9fe87a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +**/build/** +**/verilog/** +**/*.log diff --git a/Makefile.base b/Makefile.base new file mode 100755 index 0000000..c201f8b --- /dev/null +++ b/Makefile.base @@ -0,0 +1,26 @@ +TRANSFLAGS = -aggressive-conditions -lift # -split-if +RECOMPILEFLAGS = -u -show-compiles +SCHEDFLAGS = -show-schedule -sched-dot # -show-rule-rel dMemInit_request_put doExecute +# -show-elab-progress +DEBUGFLAGS = -check-assert \ + -continue-after-errors \ + -keep-fires \ + -keep-inlined-boundaries \ + -show-method-bvi \ + -show-method-conf \ + -show-module-use \ + -show-range-conflict \ + -show-stats \ + -warn-action-shadowing \ + -warn-method-urgency \ + -promote-warnings ALL +VERILOGFLAGS = -verilog -remove-dollar -remove-unused-modules # -use-dpi -verilog-filter cmd +BLUESIMFLAGS = -parallel-sim-link 16 # -systemc +BUILDDIR = build +OUTDIR = -bdir $(BUILDDIR) -info-dir $(BUILDDIR) -simdir $(BUILDDIR) -vdir $(BUILDDIR) +WORKDIR = -fdir $(abspath .) +LIBSRCDIR = $(abspath ../lib/blue_wrapper/src) +BSVSRCDIR = -p +:$(abspath ../src):$(LIBSRCDIR) +DIRFLAGS = $(BSVSRCDIR) $(OUTDIR) $(WORKDIR) +MISCFLAGS = -print-flags -show-timestamps -show-version -steps 6000000 # -D macro +RUNTIMEFLAGS = +RTS -K4095M -RTS diff --git a/Makefile.test b/Makefile.test new file mode 100755 index 0000000..0be9d4e --- /dev/null +++ b/Makefile.test @@ -0,0 +1,18 @@ +TESTDIR ?= $(abspath ../test) +LOGDIR ?= $(abspath ../tmp) + +TESTBENCHS = \ + TestDmaCore.bsv + +TestDmaCore.bsv = mkChunkComputerTb + +all: $(TESTBENCHS) + +%.bsv: + $(foreach testcase, $($@), $(shell cd $(TESTDIR) && make simulate TESTFILE=$@ TOPMODULE=$(testcase) > $(LOGDIR)/$@-$(testcase).log 2>&1)) + +clean: + rm -f $(LOGDIR)/*.log + +.PHONY: all TESTBENCHS %.bsv clean +.DEFAULT_GOAL := all diff --git a/backend/Makefile b/backend/Makefile new file mode 100644 index 0000000..8634dda --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,40 @@ +include ../Makefile.base + +TCLDIR ?= xdc +CLK ?= rdma_clock +OOC ?= 1 +VLOGDIR ?= verilog +OUTPUTDIR ?= output +LOGFILE ?= run.log +RUNTOPHASE ?= place # synth place route all +PARTNAME = xcvu13p-fhgb2104-2-i +TARGETFILE ?= ../src/DmaRequestCore.bsv +TOPMODULE ?= mkChunkComputer + +export TOP = $(TOPMODULE) +export RTL = $(VLOGDIR) +export XDC = $(TCLDIR) +export IPS = $(SRCDIR)/ip/$(PARTNAME) +export CLOCKS = $(CLK) +export OUTPUT = $(OUTPUTDIR) +export OOCSYNTH = $(OOC) +export RUNTO = $(RUNTOPHASE) +export PART = $(PARTNAME) + +compile: + mkdir -p $(BUILDDIR) + bsc -elab -sim -verbose $(BLUESIMFLAGS) $(DEBUGFLAGS) $(DIRFLAGS) $(MISCFLAGS) $(RECOMPILEFLAGS) $(RUNTIMEFLAGS) $(SCHEDFLAGS) $(TRANSFLAGS) -g $(TOPMODULE) $(TARGETFILE) + +verilog: compile + mkdir -p $(VLOGDIR) + bsc $(VERILOGFLAGS) $(DIRFLAGS) $(MISCFLAGS) $(RECOMPILEFLAGS) $(RUNTIMEFLAGS) $(TRANSFLAGS) -g $(TOPMODULE) $(TARGETFILE) + bluetcl listVlogFiles.tcl -bdir $(BUILDDIR) -vdir $(BUILDDIR) $(TOPMODULE) $(TOPMODULE) | grep -i '\.v' | xargs -I {} cp {} $(VLOGDIR) + +# vivado: verilog +# vivado -mode tcl -nolog -nojournal -source ./non_project_build.tcl 2>&1 | tee $(LOGFILE) + +clean: + rm -rf $(BUILDDIR) $(OUTPUTDIR) $(VLOGDIR) .Xil *.jou *.log + +.PHONY: verilog vivado clean +.DEFAULT_GOAL := verilog \ No newline at end of file diff --git a/backend/listVlogFiles.tcl b/backend/listVlogFiles.tcl new file mode 100644 index 0000000..7e30e6f --- /dev/null +++ b/backend/listVlogFiles.tcl @@ -0,0 +1,223 @@ +#!/bin/sh + +# \ +exec $BLUESPECDIR/bin/bluetcl "$0" "$@" + +package require utils + +proc usage {} { + puts "" + puts "usage: $::argv0 top_package_name top_module" + puts "Options:" + puts " -q Do not print section headers" + puts " -p Bluespec search path" + puts " -bdir Bluespec bdir directory" + puts " -vdir Bluespec vdir directory" + puts " -generated Print synthesized BSV modules" + puts " -primitives Print Bluespec primitive modules" + puts " -imported Print imported modules" + puts " -no-inline-fns Print modules for no-inline functions" + puts " -all Alias for -generated -primitives -imported -no-inline-fns" + puts "" + puts " e.g: -bdir build -p build:+ -vdir rtl mkTop fpga_a" +} + +set boolOptions [list -- -q -generated -primitives -imported -no-inline-fns -all] +set valOptions [list -p -bdir -vdir] + +if { [catch [list ::utils::scanOptions $boolOptions $valOptions true OPT "$argv"] opts] } { + puts stderr $opts + usage + exit 1 +} + +if {[llength $opts] == 0} { + puts stderr "A package name argument is required" + usage + exit 1 +} + +if {[llength $opts] == 1} { + puts stderr "A top module name is required" + usage + exit 1 +} + +if {[llength $opts] > 2} { + puts stderr "Too many arguments" + usage + exit 1 +} + +if { [info exists OPT(-p)] } { + Bluetcl::flags set -p $OPT(-p) +} +if { [info exists OPT(-bdir)] } { + Bluetcl::flags set -bdir $OPT(-bdir) +} +if { [info exists OPT(-vdir)] } { + Bluetcl::flags set -vdir $OPT(-vdir) +} + +if {![info exists OPT(-all)] && ![info exists OPT(-generated)] && + ![info exists OPT(-no-inline-fns)] && ![info exists OPT(-primitives)] && + ![info exists OPT(-imported)]} { + set OPT(-all) 1 +} + +set top_pkg [lindex $opts 0] +set top_mod [lindex $opts 1] + +# Assume -verilog +Bluetcl::flags set -verilog + +# Load the module information +Bluetcl::module load $top_pkg + +# Walk the hierarchy extracting module information +set mods_to_process [list $top_pkg] +set already_done [list] +set is_noinline 0 +while {[llength $mods_to_process] > 0} { + set this_mod [utils::head $mods_to_process] + set mods_to_process [utils::tail $mods_to_process] + set res [Bluetcl::module submods $this_mod] + set this_mod_type [lindex $res 0] + if {$this_mod_type == "user" && $is_noinline != 0} { + set this_mod_type "no-inline-fn" + } + array set mod_info [list $this_mod $this_mod_type] + lappend already_done $this_mod + set sub_mods [lindex $res 1] + set no_inlines [lindex $res 2] + foreach mod $sub_mods { + set this_sub_mod [utils::snd $mod] + if {[lsearch -exact $already_done $this_sub_mod] == -1 && + [lsearch -exact $mods_to_process $this_sub_mod] == -1 } { + lappend mods_to_process $this_sub_mod + } + } + set is_noinline 1 + foreach mod $no_inlines { + set this_sub_mod [utils::snd $mod] + if {[lsearch -exact $already_done $this_sub_mod] == -1 && + [lsearch -exact $mods_to_process $this_sub_mod] == -1 } { + lappend mods_to_process $this_sub_mod + } + } + set is_noinline 0 +} + +# Procedure to locate a file for a given module +proc lookupfile {name path exts} { + foreach dir $path { + foreach ext $exts { + set fname [join [list $name $ext] "."] + set fpath [file join $dir $fname] + if {[file exist $fpath]} { + return [file normalize $fpath] + } + } + } + return "" +} + +# Procedure to add a file to a list, avoiding duplication +proc addfile {name flName} { + upvar 1 $flName file_list + + set matched 0 + foreach f $file_list { + if {$f == $name} { + set matched 1 + break + } + } + if {$matched == 0} { + lappend file_list $name + } +} + +# Identify the location of each module's file +set user_mods [list] +set noinline_fns [list] +set primitives [list] +set imported [list] + +set vdir [lindex [Bluetcl::flags show vdir] 1] +set bsdir $::env(BLUESPECDIR) + +set libs [list [file join $bsdir "Verilog"] [file join $bsdir "Libraries"]] +set vsearch [split [lindex [Bluetcl::flags show p] 1] ":"] +set vdir_and_libs [concat $vdir $libs] +set vsearch_and_libs [concat $vsearch $libs] + +foreach mod [array names mod_info] { + set mod_type $mod_info($mod) + + # The Probe primitive has no associated Verilog module + if {$mod_type == "primitive" && $mod == "Probe"} { + continue + } + + # Add the module info to the correct list + switch -exact $mod_type { + "user" {addfile [lookupfile $mod $vdir_and_libs {v}] user_mods} + "no-inline-fn" {addfile [lookupfile $mod $vdir {v}] noinline_fns} + "primitive" {addfile [lookupfile $mod $libs {v}] primitives} + "import" {addfile [lookupfile $mod $vsearch_and_libs {v vhd vhdl}] imported} + } + + # Some primitives use other primitives + if {$mod_type == "primitive"} { + switch -exact $mod { + "MakeReset" {addfile [lookupfile "SyncReset" $libs {v}] primitives} + "MakeResetA" {addfile [lookupfile "SyncResetA" $libs {v}] primitives} + "SyncFIFOLevel" {addfile [lookupfile "ClockGen" $libs {v}] primitives + addfile [lookupfile "SyncHandshake" $libs {v}] primitives + } + "SyncFIFO" {addfile [lookupfile "ClockGen" $libs {v}] primitives} + "SyncRegister " {addfile [lookupfile "ClockGen" $libs {v}] primitives + addfile [lookupfile "SyncHandshake" $libs {v}] primitives + } + } + } +} + +if {[llength $user_mods] > 0 && ([info exists OPT(-generated)] || [info exists OPT(-all)])} { + if {![info exists OPT(-q)]} { + puts "# Synthesized user modules:" + } + foreach file $user_mods { + puts $file + } +} + +if {[llength $noinline_fns] > 0 && ([info exists OPT(-no-inline-fns)] || [info exists OPT(-all)])} { + if {![info exists OPT(-q)]} { + puts "# No-inlined functions:" + } + foreach file $noinline_fns { + puts $file + } +} + +if {[llength $imported] > 0 && ([info exists OPT(-imported)] || [info exists OPT(-all)])} { + if {![info exists OPT(-q)]} { + puts "# Imported modules:" + } + foreach file $imported { + puts $file + } +} + +if {[llength $primitives] > 0 && ([info exists OPT(-primitives)] || [info exists OPT(-all)])} { + if {![info exists OPT(-q)]} { + puts "# Bluespec library primitives:" + } + foreach file $primitives { + puts $file + } +} + +exit \ No newline at end of file diff --git a/img/concat.drawio b/img/concat.drawio new file mode 100644 index 0000000..1d4939c --- /dev/null +++ b/img/concat.drawio @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..86169fa --- /dev/null +++ b/run.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o xtrace + +BASH_PROFILE=$HOME/.bash_profile +if [ -f "$BASH_PROFILE" ]; then + source $BASH_PROFILE +fi + +TEST_DIR=`realpath ./test` +LOG_DIR=`realpath ./tmp` +ALL_LOG=$TEST_DIR/run.log + +mkdir -p $LOG_DIR + +make -j8 -f Makefile.test all TESTDIR=$TEST_DIR LOGDIR=$LOG_DIR +cat $LOG_DIR/*.log | tee $ALL_LOG + +FAIL_KEYWORKS='Error\|ImmAssert' +grep -w $FAIL_KEYWORKS $LOG_DIR/*.log | cat +ERR_NUM=`grep -c -w $FAIL_KEYWORKS $ALL_LOG | cat` +if [ $ERR_NUM -gt 0 ]; then + echo "FAIL" + false +else + echo "PASS" +fi diff --git a/run_one.sh b/run_one.sh new file mode 100755 index 0000000..f049c0d --- /dev/null +++ b/run_one.sh @@ -0,0 +1,37 @@ +#! /usr/bin/env bash + +set -o errexit +set -o nounset +set -o xtrace + +BASH_PROFILE=$HOME/.bash_profile +if [ -f "$BASH_PROFILE" ]; then + source $BASH_PROFILE +fi + +TEST_LOG=run.log +TEST_DIR=test +cd $TEST_DIR +truncate -s 0 $TEST_LOG +FILES=`ls TestDmaCore.bsv` +########################################################################### +for FILE in $FILES; do + # echo $FILE + TESTCASES=`grep -Phzo 'doc.*?\nmodule\s+\S+(?=\()' $FILE | xargs -0 -I {} echo "{}" | grep module | cut -d ' ' -f 2` + for TESTCASE in $TESTCASES; do + make -j8 TESTFILE=$FILE TOPMODULE=$TESTCASE 2>&1 | tee -a $TEST_LOG + done +########################################################################### +done +########################################################################### + +FAIL_KEYWORKS='Error\|ImmAssert' +grep -w $FAIL_KEYWORKS $TEST_LOG | cat +ERR_NUM=`grep -c -w $FAIL_KEYWORKS $TEST_LOG | cat` +if [ $ERR_NUM -gt 0 ]; then + echo "FAIL" + false +else + echo "PASS" +fi + diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..137cded --- /dev/null +++ b/setup.sh @@ -0,0 +1,22 @@ +#! /bin/sh + +set -o errexit +set -o nounset +set -o xtrace + +rm -rf bsc-* +# wget https://github.com/B-Lang-org/bsc/releases/download/2022.01/bsc-2022.01-ubuntu-20.04.tar.gz +wget https://github.com/B-Lang-org/bsc/releases/download/2023.01/bsc-2023.01-ubuntu-22.04.tar.gz +tar zxf bsc-* + +BSC_FILE_NAME=`ls bsc-*.tar.gz` +BSC_DIR_NAME=`basename $BSC_FILE_NAME .tar.gz` +BLUESPEC_HOME=`realpath $BSC_DIR_NAME` + +BASH_PROFILE=$HOME/.bash_profile +touch $BASH_PROFILE +cat <> $BASH_PROFILE +# BSV required env +export BLUESPECDIR=$BLUESPEC_HOME/lib +export PATH=$PATH:$BLUESPEC_HOME/bin +EOF diff --git a/src/DmaRequestCore.bsv b/src/DmaRequestCore.bsv index e2220ab..71fce0b 100644 --- a/src/DmaRequestCore.bsv +++ b/src/DmaRequestCore.bsv @@ -1,18 +1,20 @@ import FIFOF::*; +import SemiFifo::*; import PcieTypes::*; import DmaTypes::*; -typedef 4096 BUS_BOUNDARY -typedef 12 BUS_BOUNDARY_WIDTH + +typedef 4096 BUS_BOUNDARY; +typedef 12 BUS_BOUNDARY_WIDTH; typedef struct { DmaRequestFrame dmaRequest; Maybe#(DmaMemAddr) firstChunkLen; } ChunkRequestFrame deriving(Bits, Eq); -Interface ChunkCompute; - FifoIn#(DmaRequestFrame) dmaRequests; - FifoOut#(DmaRequestFrame) chunkRequests; +interface ChunkCompute; + interface FifoIn#(DmaRequestFrame) dmaRequests; + interface FifoOut#(DmaRequestFrame) chunkRequests; endinterface module mkChunkComputer(ChunkCompute ifc); @@ -22,78 +24,80 @@ module mkChunkComputer(ChunkCompute ifc); Reg#(DmaMemAddr) newChunkPtrReg <- mkReg(0); Reg#(DmaMemAddr) totalLenRemainReg <- mkReg(0); - Reg#(Bool) isSplittigReg <- mkReg(False); + Reg#(Bool) isSplittingReg <- mkReg(False); function Bool hasBoundary(DmaRequestFrame request); - let highIdx = (request.startAddr + request.length) >> BUS_BOUNDARY_WIDTH; - let lowIdx = request.startAddr >> BUS_BOUNDARY_WIDTH; + let highIdx = (request.startAddr + request.length - 1) >> valueOf(BUS_BOUNDARY_WIDTH); + let lowIdx = request.startAddr >> valueOf(BUS_BOUNDARY_WIDTH); return (highIdx > lowIdx); endfunction function DmaMemAddr getOffset(DmaRequestFrame request); - DmaMemAddr offset = zeroExtend(fromInteger(valueOf(BUS_BOUNDARY)) - pack(request.startAddr[BUS_BOUNDARY_WIDTH-1:0])); - return offset; + // 4096 - startAddr % 4096 + Bit#(BUS_BOUNDARY_WIDTH) remainder = truncate(request.startAddr); + Bit#(BUS_BOUNDARY_WIDTH) offset = fromInteger(valueOf(BUS_BOUNDARY)-1) - zeroExtend(remainder) + 1; + return zeroExtend(offset); endfunction - rule getfirstChunkLen if(inputFifo.notEmpty && splitFifo.notFull); + rule getfirstChunkLen; let request = inputFifo.first; inputFifo.deq; - let offset = getOffSet(request); + let offset = getOffset(request); // firstChunkLen = offset % PCIE_TLP_BYTES - DmaMemAddr firstLen = zeroExtend(offset[valueOf(PCIE_TLP_BYTES_WIDTH)-1:0]); - ChunkRequestFrame splitRequest = { + Bit#(PCIE_TLP_BYTES_WIDTH) offsetModTlpBytes = truncate(offset); + DmaMemAddr firstLen = zeroExtend(offsetModTlpBytes); + splitFifo.enq(ChunkRequestFrame { dmaRequest: request, - firstChunkLen: hasBoundary(request) ? tagged Valid firstLen : tagged Invalid; - } - splitFifo.enq(splitRequest); - endrule + firstChunkLen: hasBoundary(request) ? tagged Valid firstLen : tagged Invalid + }); +endrule - rule execSplit if(splitFifo.notEmpty && outFifo.notFull); + rule execChunkSplit; let splitRequest = splitFifo.first; - if (isSplittingReg) begin - if (totalLenRemainReg <= PCIE_TLP_BYTES) begin - isSplittingReg <= False; - outputFifo.enq(DmaRequestFrame { - startAddr: newChunkPtrReg; - length: totalLenRemainReg; - }); - splitFifo.deq; - totalLenRemainReg <= 0; - end else begin - isSplittingReg <= True; - outputFifo.enq(DmaRequestFrame { - startAddr: newChunkPtrReg; - length: fromInteger(valueOf(PCIE_TLP_BYTES)); - }); - newChunkPtrReg <= newChunkPtrReg + fromInteger(valueOf(PCIE_TLP_BYTES)); - totalLenRemainReg <= totalLenRemainReg - PCIE_TLP_BYTES; - end - end else begin + if (isSplittingReg) begin // !isFirst + if (totalLenRemainReg <= fromInteger(valueOf(PCIE_TLP_BYTES))) begin + isSplittingReg <= False; + outputFifo.enq(DmaRequestFrame { + startAddr: newChunkPtrReg, + length: totalLenRemainReg + }); + splitFifo.deq; + totalLenRemainReg <= 0; + end else begin + isSplittingReg <= True; + outputFifo.enq(DmaRequestFrame { + startAddr: newChunkPtrReg, + length: fromInteger(valueOf(PCIE_TLP_BYTES)) + }); + newChunkPtrReg <= newChunkPtrReg + fromInteger(valueOf(PCIE_TLP_BYTES)); + totalLenRemainReg <= totalLenRemainReg - fromInteger(valueOf(PCIE_TLP_BYTES)); + end + end else begin // isFirst let remainderLength = splitRequest.dmaRequest.length - fromMaybe(0, splitRequest.firstChunkLen); if (isValid(splitRequest.firstChunkLen)) begin Bool isSplittingNextCycle = (remainderLength > 0); isSplittingReg <= isSplittingNextCycle; outputFifo.enq(DmaRequestFrame { - startAddr: splitRequest.dmaRequest.startAddr; - length: fromMaybe(0, splitRequest.firstChunkLen); + startAddr: splitRequest.dmaRequest.startAddr, + length: fromMaybe(0, splitRequest.firstChunkLen) }); - if (!isSplittingNextCycle) begin splitFifo.deq; end; - newChunkPtrReg <= splitRequest.dmaRequest + fromMaybe(0, splitRequest.firstChunkLen); + if (!isSplittingNextCycle) begin splitFifo.deq; end + newChunkPtrReg <= splitRequest.dmaRequest.startAddr + fromMaybe(0, splitRequest.firstChunkLen); totalLenRemainReg <= remainderLength; end else begin - Bool isSplittingNextCycle = (remainderLength > PCIE_TLP_BYTES); + Bool isSplittingNextCycle = (remainderLength > fromInteger(valueOf(PCIE_TLP_BYTES))); isSplittingReg <= isSplittingNextCycle; outputFifo.enq(DmaRequestFrame { - startAddr: splitRequest.dmaRequest.startAddr; - length: fromInteger(valueOf(PCIE_TLP_BYTES)); + startAddr: splitRequest.dmaRequest.startAddr, + length: fromInteger(valueOf(PCIE_TLP_BYTES)) }); if (!isSplittingNextCycle) begin splitFifo.deq; end - newChunkPtrReg <= newChunkPtrReg + fromInteger(valueOf(PCIE_TLP_BYTES)); - totalLenRemainReg <= remainderLength - PCIE_TLP_BYTES; + newChunkPtrReg <= splitRequest.dmaRequest.startAddr + fromInteger(valueOf(PCIE_TLP_BYTES)); + totalLenRemainReg <= remainderLength - fromInteger(valueOf(PCIE_TLP_BYTES)); end end endrule - interface dmaRequests = convertFifoToFifoOut(inputFifo); + interface dmaRequests = convertFifoToFifoIn(inputFifo); interface chunkRequests = convertFifoToFifoOut(outputFifo); endmodule \ No newline at end of file diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index 27c4035..b8a9b51 100644 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -12,7 +12,7 @@ typedef Bit#(DMA_CSR_DATA_WIDTH) DMACsrValue; typedef struct { Bit#(dataWidth) data; - Bit#(TDiv#(dataWidth, BYTE_BITS)) byteEn; + Bit#(TDiv#(dataWidth, BYTE_WIDTH)) byteEn; Bool isFirst; Bool isLast; } DataFrame#(numeric type dataWidth) deriving(Bits, Bounded, Eq, FShow); @@ -29,17 +29,17 @@ typedef struct { interface DmaController#(numeric type dataWidth); - interface FifoIn#(DataFrame#(dataWidth)) DmaDataC2HPipeIn; - interface FifoIn#(DmaRequestFrame) DmaCtrlC2HPipeIn; - interface FifoIn#(DmaRequestFrame) DmaCtrlH2CPipeIn; - interface FifoOut#(DataFrame#(dataWidth)) DmaDataH2CPipeOut; + interface FifoIn#(DataFrame#(dataWidth)) dataC2HPipeIn; + interface FifoIn#(DmaRequestFrame) reqC2HPipeIn; + interface FifoIn#(DmaRequestFrame) reqH2CPipeIn; + interface FifoOut#(DataFrame#(dataWidth)) dataH2CPipeOut; - interface FifoIn#(DmaCsrFrame) DmaCsrC2HPipeIn; - interface FifoOut#(DMACsrAddr) DmaCsrC2HPipeOut; - interface FifoOut#(DmaCsrFrame) DmaCsrH2CPipeOut; + interface FifoIn#(DmaCsrFrame) csrC2HPipeIn; + interface FifoOut#(DMACsrAddr) csrC2HPipeOut; // read reg in the card from Host + interface FifoOut#(DmaCsrFrame) csrH2CPipeOut; - interface RawPcieRequester PcieRequester; - interface RawPcieCompleter PcieCompleter; - interface RawPcieConfiguration PcieConfig; + interface RawPcieRequester pcieRequester; + interface RawPcieCompleter pcieCompleter; + interface RawPcieConfiguration pcieConfig; endinterface diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv index d2fddd3..3fda845 100644 --- a/src/PcieTypes.bsv +++ b/src/PcieTypes.bsv @@ -1,10 +1,10 @@ import AxiStreamTypes :: *; -typedef 8 BYTE_WIDTH +typedef 8 BYTE_WIDTH; typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; -typedef 512 PCIE_TLP_BYTES -typedef #TLog(PCIE_TLP_BYTES) PCIE_TLP_BYTES_WIDTH +typedef 512 PCIE_TLP_BYTES; +typedef TLog#(PCIE_TLP_BYTES) PCIE_TLP_BYTES_WIDTH; typedef 512 PCIE_TDATA_WIDTH; typedef 64 PCIE_TDATA_BYTES; @@ -40,7 +40,7 @@ typedef Bit#(PCIE_TPH_PRESENT_WIDTH) PcieTlpCtlTphPresent; typedef Bit#(PCIE_TPH_TYPE_WIDTH) PcieTlpCtlTphType; typedef Bit#(PCIE_TPH_STTAG) PcieTlpCtlTphSteeringTag; typedef Bit#(PCIE_TPH_INDIRECT_TAGEN_WIDTH) PcieTlpCtlTphIndirectTagEn; -typedef 64 PCIE_TLP_PARITY +typedef 64 PCIE_TLP_PARITY; typedef Bit#(PCIE_TLP_PARITY) PcieTlpCtlParity; typedef 4 PCIE_TLP_ADDR_OFFSET_WIDTH; typedef Bit#(PCIE_TLP_ADDR_OFFSET_WIDTH) PcieTlpCtlAddrOffset; @@ -102,7 +102,7 @@ typedef struct { // 137bit tUser of PcieRequesterRequeste AXIS-master typedef struct { PcieTlpCtlFirstByteEn firstByteEn; - PcieTlpCtlLastByteEn lastByteEn + PcieTlpCtlLastByteEn lastByteEn; PcieTlpCtlAddrOffset addrOffset; PcieTlpCtlIsSopCommon isSop; PcieTlpCtlIsEopCommon isEop; @@ -133,18 +133,18 @@ typedef Bit#(PCIE_CR_NP_REQ_COUNT_WIDTH) PcieNonPostedRequstCount; (*always_ready, always_enabled*) interface RawPcieCompleter; // TODO: the AxiStream in blue-wrapper has tDataWidth = tKeepWidth * BYTE_WIDTH, but the PCIe IP has tDataWidth = tKeepWidth * DWORD_WIDTH - (* prefix = "s_axis_cq_" *) interface RawAxiStreamSlave#(PCIE_TKEEP_WIDTH, PCIE_COMPLETER_REQUEST_TUSER_WIDTH) Request; + (* prefix = "s_axis_cq_" *) interface RawAxiStreamSlave#(PCIE_TKEEP_WIDTH, PCIE_COMPLETER_REQUEST_TUSER_WIDTH) request; // (* result = "pcie_cq_np_req" *) method PcieNonPostedRequst nonPostedReqCreditIncrement; // (* prefix = "" *) method Action nonPostedReqCreditCnt( // (* port = "pcie_cq_np_req_count" *) PcieNonPostedRequstCount ); - (* prefix = "m_axis_cc_" *) interface RawAxiStreamMaster#(PCIE_TKEEP_WIDTH, PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) Complete; + (* prefix = "m_axis_cc_" *) interface RawAxiStreamMaster#(PCIE_TKEEP_WIDTH, PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) complete; endinterface // Interface to PCIe IP Requester Interface (*always_ready, always_enabled*) interface RawPcieRequester; - (* prefix = "m_axis_rq_" *) interface RawAxiStreamMaster#(PCIE_TKEEP_WIDTH, usrWidth) Request; - (* prefix = "s_axis_rc_" *) interface RawAxiStreamSlave#(PCIE_TKEEP_WIDTH, usrWidth) Complete; + (* prefix = "m_axis_rq_" *) interface RawAxiStreamMaster#(PCIE_TKEEP_WIDTH, usrWidth) request; + (* prefix = "s_axis_rc_" *) interface RawAxiStreamSlave#(PCIE_TKEEP_WIDTH, usrWidth) complete; endinterface typedef 10 PCIE_CFG_MGMT_ADDR_WIDTH; @@ -157,74 +157,74 @@ typedef Bit#(PCIE_CFG_MGMT_FUNC_NUM_WIDTH) PcieCfgMgmtFuncNum; typedef Bit#(PCIE_CFG_MGMT_DATA_WIDTH) PCieCfgMgmtData; interface RawPcieConfiguration; - (* prefix = "cfg_mgmt_" *) interface RawPcieCfgMgmt; - (* prefix = "cfg_pm_" *) interface RawPcieCfgPm; - (* prefix = "cfg_msi_" *) interface RawPcieCfgMsi; - (* prefix = "cfg_interrupt_" *) interface RawPcieCfgInterrupt; - (* prefix = "cfg_" *) interface RawPcieCfgControl; - (* prefix = "cfg_fc_" *) interface RawPcieCfgFC; - (* prefix = "cfg_msg_transmit_" *) interface RawPcieCfgMsgTx; - (* prefix = "cfg_msg_received_" *) interface RawPcieCfgMsgRx; - (* prefix = "" *) interface RawPcieCfgStatus; - (* prefix = "pcie_tfc_" *) interface RawPcieCfgTransmitFC; + (* prefix = "cfg_mgmt_" *) interface RawPcieCfgMgmt mgmt; + (* prefix = "cfg_pm_" *) interface RawPcieCfgPm pm; + (* prefix = "cfg_msi_" *) interface RawPcieCfgMsi msi; + (* prefix = "cfg_interrupt_" *) interface RawPcieCfgInterrupt interrupt; + (* prefix = "cfg_" *) interface RawPcieCfgControl control; + (* prefix = "cfg_fc_" *) interface RawPcieCfgFC flowControl; + (* prefix = "cfg_msg_transmit_" *) interface RawPcieCfgMsgTx msgTx; + (* prefix = "cfg_msg_received_" *) interface RawPcieCfgMsgRx msgRx; + (* prefix = "" *) interface RawPcieCfgStatus status; + (* prefix = "pcie_tfc_" *) interface RawPcieCfgTransmitFC txFlowControl; endinterface (*always_ready, always_enabled*) interface RawPcieCfgMgmt; - (* result = addr *) method PcieCfgMgmtAddr cfgMgmtAddr; - (* result = byte_enable *) method PcieCfgMgmtByteEn cfgMgmtByteEn; - (* result = debug_access *) method Bool cfgMgmtDebugAccess; - (* result = function_number *) method PcieCfgMgmtFuncNum cfgMgmtFuncNum; - (* result = read *) method Bool cfgMgmtRead; - (* result = write_data *) method PCieCfgMgmtData cfgMgmtWriteData; - (* result = write *) method Bool cfgMgmtWrite; - (* prefix = "" *) method Action cfgMgmtReadData( + (* result = "addr" *) method PcieCfgMgmtAddr addr; + (* result = "byte_enable" *) method PcieCfgMgmtByteEn byteEn; + (* result = "debug_access" *) method Bool debugAccess; + (* result = "function_number" *) method PcieCfgMgmtFuncNum funcNum; + (* result = "read" *) method Bool read; + (* result = "write_data" *) method PCieCfgMgmtData writeData; + (* result = "write" *) method Bool write; + (* prefix = "" *) method Action readData( (* port = "read_data" *) PCieCfgMgmtData cfgMgmtRdData); - (* prefix = "" *) method Action cfgMgmtWriteDone( + (* prefix = "" *) method Action writeDone( (* port = "write_done" *) Bool cfgMgmtWrDone); endinterface (*always_ready, always_enabled*) -interface RawPcieCfgPm#(); +interface RawPcieCfgPm; endinterface (*always_ready, always_enabled*) -interface RawPcieCfgMsi#(); +interface RawPcieCfgMsi; endinterface (*always_ready, always_enabled*) -interface RawPcieCfgInterrupt#(); +interface RawPcieCfgInterrupt; endinterface (*always_ready, always_enabled*) -interface RawPcieCfgControl#(); +interface RawPcieCfgControl; endinterface (*always_ready, always_enabled*) -interface RawPcieCfgFC#(); +interface RawPcieCfgFC; endinterface (*always_ready, always_enabled*) -interface RawPcieCfgMsgTx#(); +interface RawPcieCfgMsgTx; endinterface (*always_ready, always_enabled*) -interface RawPcieCfgMsgRx#(); +interface RawPcieCfgMsgRx; endinterface (*always_ready, always_enabled*) -interface RawPcieCfgStatus#(); +interface RawPcieCfgStatus; endinterface (*always_ready, always_enabled*) -interface RawPcieCfgTransmitFC#(); +interface RawPcieCfgTransmitFC; endinterface \ No newline at end of file diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..4667929 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,22 @@ +include ../Makefile.base + +TESTFILE ?= TestDmaCore.bsv +TOPMODULE ?= mkChunkComputerTb + +SIMSCRIPT = $(BUILDDIR)/$(TOPMODULE).sh + +compile: + mkdir -p $(BUILDDIR) + bsc -elab -sim -verbose $(BLUESIMFLAGS) $(DEBUGFLAGS) $(DIRFLAGS) $(MISCFLAGS) $(RECOMPILEFLAGS) $(RUNTIMEFLAGS) $(SCHEDFLAGS) $(TRANSFLAGS) -g $(TOPMODULE) $(TESTFILE) + +link: compile + bsc -sim $(BLUESIMFLAGS) $(DIRFLAGS) $(RECOMPILEFLAGS) $(SCHEDFLAGS) $(TRANSFLAGS) -e $(TOPMODULE) -o $(SIMSCRIPT) + +simulate: link + $(SIMSCRIPT) + +clean: + rm -rf $(BUILDDIR) + +.PHONY: compile link simulate clean +.DEFAULT_GOAL := simulate \ No newline at end of file diff --git a/test/TestDmaCore.bsv b/test/TestDmaCore.bsv new file mode 100644 index 0000000..0698e83 --- /dev/null +++ b/test/TestDmaCore.bsv @@ -0,0 +1,78 @@ +import SemiFifo::*; +import Randomizable::*; +import DmaTypes::*; +import DmaRequestCore::*; + +typedef 50 TEST_NUM; +typedef 64'hFFFFFFFFFFFFFFFF MAX_ADDRESS; +typedef 32'hFFFFFFFF MAX_TEST_LENGTH; + +(* doc = "testcase" *) +module mkChunkComputerTb (Empty); + + ChunkCompute dut <- mkChunkComputer; + + Reg#(Bool) isInitReg <- mkReg(False); + Reg#(UInt#(32)) testCntReg <- mkReg(0); + Reg#(DmaMemAddr) lenRemainReg <- mkReg(0); + Reg#(DmaRequestFrame) testRequest <- mkRegU; + Randomize#(DmaMemAddr) startAddrRandomVal <- mkConstrainedRandomizer(0, fromInteger(valueOf(MAX_ADDRESS)-1)); + Randomize#(DmaMemAddr) lengthRandomVal <- mkConstrainedRandomizer(1, fromInteger(valueOf(MAX_TEST_LENGTH))); + + function Bool hasBoundary(DmaRequestFrame request); + let highIdx = (request.startAddr + request.length - 1) >> valueOf(BUS_BOUNDARY_WIDTH); + let lowIdx = request.startAddr >> valueOf(BUS_BOUNDARY_WIDTH); + return (highIdx > lowIdx); + endfunction + + function Action showRequest (DmaRequestFrame request); + return action + $display("startAddr: ", request.startAddr, " length: ", request.length); + endaction; + endfunction + + rule testInit if (!isInitReg); + startAddrRandomVal.cntrl.init; + lengthRandomVal.cntrl.init; + isInitReg <= True; + $display("Start Test of mkChunkComputerTb"); + endrule + + rule testInput if (isInitReg && lenRemainReg == 0); + DmaMemAddr testAddr <- startAddrRandomVal.next; + DmaMemAddr testLength <- lengthRandomVal.next; + let testEnd = testAddr + testLength - 1; + if (testEnd > testAddr && testEnd <= fromInteger(valueOf(MAX_ADDRESS))) begin + let request = DmaRequestFrame{ + startAddr: testAddr, + length: testLength + }; + lenRemainReg <= testLength; + dut.dmaRequests.enq(request); + showRequest(request); + end else begin + lenRemainReg <= 0; + end + endrule + + rule testOutput if (isInitReg && lenRemainReg > 0); + let newRequest = dut.chunkRequests.first; + dut.chunkRequests.deq; + if (hasBoundary(newRequest)) begin + $display("Error, has 4KB boundary!"); + showRequest(newRequest); + $finish(); + end else begin + // showRequest(newRequest); + let newRemain = lenRemainReg - newRequest.length; + lenRemainReg <= newRemain; + if(newRemain == 0) begin + testCntReg <= testCntReg + 1; + end + end + endrule + + rule testFinish ; + if (testCntReg == fromInteger(valueOf(TEST_NUM))) $finish(); + endrule +endmodule \ No newline at end of file From 89dfb11710fc0384d2719ddd56a6dcd6d405d206 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Mon, 8 Jul 2024 22:48:25 +0800 Subject: [PATCH 07/53] Dynamic TLP Max Payload Size --- src/DmaRequestCore.bsv | 82 ++++++++++++++++++++++++++++-------------- src/PcieTypes.bsv | 49 +++++++++++++++++-------- test/TestDmaCore.bsv | 5 ++- 3 files changed, 94 insertions(+), 42 deletions(-) diff --git a/src/DmaRequestCore.bsv b/src/DmaRequestCore.bsv index 71fce0b..b1782ae 100644 --- a/src/DmaRequestCore.bsv +++ b/src/DmaRequestCore.bsv @@ -1,27 +1,38 @@ import FIFOF::*; +import GetPut :: *; import SemiFifo::*; import PcieTypes::*; import DmaTypes::*; -typedef 4096 BUS_BOUNDARY; -typedef 12 BUS_BOUNDARY_WIDTH; +typedef 4096 BUS_BOUNDARY; +typedef TLog#(BUS_BOUNDARY) BUS_BOUNDARY_WIDTH; +typedef Bit#(BUS_BOUNDARY_WIDTH) PcieTlpMaxMaxSize; +typedef Bit#(TLog#(BUS_BOUNDARY_WIDTH)) PcieTlpSizeWidth; +typedef 128 DEFAULT_TLP_SIZE; +typedef TLog#(DEFAULT_TLP_SIZE) DEFAULT_TLP_SIZE_WIDTH; +typedef 3 PCIE_TLP_SIZE_SETTING_WIDTH; +typedef Bit#(PCIE_TLP_SIZE_SETTING_WIDTH) PcieTlpSizeSetting; +typedef enum {DMA_RX, DMA_TX} TRXDirection deriving(Bits, Eq); + typedef struct { DmaRequestFrame dmaRequest; - Maybe#(DmaMemAddr) firstChunkLen; + Maybe#(DmaMemAddr) firstChunkLenMaybe; } ChunkRequestFrame deriving(Bits, Eq); interface ChunkCompute; - interface FifoIn#(DmaRequestFrame) dmaRequests; + interface FifoIn#(DmaRequestFrame) dmaRequests; interface FifoOut#(DmaRequestFrame) chunkRequests; + interface Put#(PcieTlpSizeSetting) setTlpMaxSize; endinterface -module mkChunkComputer(ChunkCompute ifc); +module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); FIFOF#(DmaRequestFrame) inputFifo <- mkFIFOF; FIFOF#(DmaRequestFrame) outputFifo <- mkFIFOF; FIFOF#(ChunkRequestFrame) splitFifo <- mkFIFOF; - + Reg#(DmaMemAddr) tlpMaxSize <- mkReg(fromInteger(valueOf(DEFAULT_TLP_SIZE))); //MPS if isTX, MRRS else + Reg#(PcieTlpSizeWidth) tlpMaxSizeWidth <- mkReg(fromInteger(valueOf(DEFAULT_TLP_SIZE_WIDTH))); Reg#(DmaMemAddr) newChunkPtrReg <- mkReg(0); Reg#(DmaMemAddr) totalLenRemainReg <- mkReg(0); Reg#(Bool) isSplittingReg <- mkReg(False); @@ -35,7 +46,7 @@ module mkChunkComputer(ChunkCompute ifc); function DmaMemAddr getOffset(DmaRequestFrame request); // 4096 - startAddr % 4096 Bit#(BUS_BOUNDARY_WIDTH) remainder = truncate(request.startAddr); - Bit#(BUS_BOUNDARY_WIDTH) offset = fromInteger(valueOf(BUS_BOUNDARY)-1) - zeroExtend(remainder) + 1; + Bit#(BUS_BOUNDARY_WIDTH) offset = fromInteger(valueOf(BUS_BOUNDARY) - 1) - zeroExtend(remainder) + 1; return zeroExtend(offset); endfunction @@ -44,18 +55,17 @@ module mkChunkComputer(ChunkCompute ifc); inputFifo.deq; let offset = getOffset(request); // firstChunkLen = offset % PCIE_TLP_BYTES - Bit#(PCIE_TLP_BYTES_WIDTH) offsetModTlpBytes = truncate(offset); - DmaMemAddr firstLen = zeroExtend(offsetModTlpBytes); + DmaMemAddr firstLen = zeroExtend(PcieTlpMaxMaxSize'(offset[tlpMaxSizeWidth-1:0])); splitFifo.enq(ChunkRequestFrame { dmaRequest: request, - firstChunkLen: hasBoundary(request) ? tagged Valid firstLen : tagged Invalid + firstChunkLenMaybe: hasBoundary(request) ? tagged Valid firstLen : tagged Invalid }); endrule rule execChunkSplit; let splitRequest = splitFifo.first; if (isSplittingReg) begin // !isFirst - if (totalLenRemainReg <= fromInteger(valueOf(PCIE_TLP_BYTES))) begin + if (totalLenRemainReg <= tlpMaxSize) begin isSplittingReg <= False; outputFifo.enq(DmaRequestFrame { startAddr: newChunkPtrReg, @@ -63,41 +73,59 @@ endrule }); splitFifo.deq; totalLenRemainReg <= 0; - end else begin + end + else begin isSplittingReg <= True; outputFifo.enq(DmaRequestFrame { startAddr: newChunkPtrReg, - length: fromInteger(valueOf(PCIE_TLP_BYTES)) + length: tlpMaxSize }); - newChunkPtrReg <= newChunkPtrReg + fromInteger(valueOf(PCIE_TLP_BYTES)); - totalLenRemainReg <= totalLenRemainReg - fromInteger(valueOf(PCIE_TLP_BYTES)); + newChunkPtrReg <= newChunkPtrReg + tlpMaxSize; + totalLenRemainReg <= totalLenRemainReg - tlpMaxSize; end - end else begin // isFirst - let remainderLength = splitRequest.dmaRequest.length - fromMaybe(0, splitRequest.firstChunkLen); - if (isValid(splitRequest.firstChunkLen)) begin + end + else begin // isFirst + let remainderLength = splitRequest.dmaRequest.length - fromMaybe(0, splitRequest.firstChunkLenMaybe); + if (isValid(splitRequest.firstChunkLenMaybe)) begin Bool isSplittingNextCycle = (remainderLength > 0); isSplittingReg <= isSplittingNextCycle; outputFifo.enq(DmaRequestFrame { startAddr: splitRequest.dmaRequest.startAddr, - length: fromMaybe(0, splitRequest.firstChunkLen) + length: fromMaybe(0, splitRequest.firstChunkLenMaybe) }); - if (!isSplittingNextCycle) begin splitFifo.deq; end - newChunkPtrReg <= splitRequest.dmaRequest.startAddr + fromMaybe(0, splitRequest.firstChunkLen); + if (!isSplittingNextCycle) begin + splitFifo.deq; + end + newChunkPtrReg <= splitRequest.dmaRequest.startAddr + fromMaybe(0, splitRequest.firstChunkLenMaybe); totalLenRemainReg <= remainderLength; - end else begin - Bool isSplittingNextCycle = (remainderLength > fromInteger(valueOf(PCIE_TLP_BYTES))); + end + else begin + Bool isSplittingNextCycle = (remainderLength > tlpMaxSize); isSplittingReg <= isSplittingNextCycle; outputFifo.enq(DmaRequestFrame { startAddr: splitRequest.dmaRequest.startAddr, - length: fromInteger(valueOf(PCIE_TLP_BYTES)) + length: tlpMaxSize }); - if (!isSplittingNextCycle) begin splitFifo.deq; end - newChunkPtrReg <= splitRequest.dmaRequest.startAddr + fromInteger(valueOf(PCIE_TLP_BYTES)); - totalLenRemainReg <= remainderLength - fromInteger(valueOf(PCIE_TLP_BYTES)); + if (!isSplittingNextCycle) begin + splitFifo.deq; + end + newChunkPtrReg <= splitRequest.dmaRequest.startAddr + tlpMaxSize; + totalLenRemainReg <= remainderLength - tlpMaxSize; end end endrule interface dmaRequests = convertFifoToFifoIn(inputFifo); interface chunkRequests = convertFifoToFifoOut(outputFifo); + + interface Put setTlpMaxSize; + method Action put (PcieTlpSizeSetting tlpSizeSetting); + let setting = tlpSizeSetting; + setting[valueOf(PCIE_TLP_SIZE_SETTING_WIDTH)-1] = (direction == DMA_TX) ? 0 : setting[valueOf(PCIE_TLP_SIZE_SETTING_WIDTH)-1]; + DmaMemAddr defaultTlpMaxSize = fromInteger(valueOf(DEFAULT_TLP_SIZE)); + tlpMaxSize <= DmaMemAddr'(defaultTlpMaxSize << setting); + PcieTlpSizeWidth defaultTlpMaxSizeWidth = fromInteger(valueOf(DEFAULT_TLP_SIZE_WIDTH)); + tlpMaxSizeWidth <= PcieTlpSizeWidth'(defaultTlpMaxSizeWidth << setting); + endmethod + endinterface endmodule \ No newline at end of file diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv index 3fda845..3e780b8 100644 --- a/src/PcieTypes.bsv +++ b/src/PcieTypes.bsv @@ -156,19 +156,6 @@ typedef Bit#(PCIE_CFG_MGMT_BE_WIDTH) PcieCfgMgmtByteEn; typedef Bit#(PCIE_CFG_MGMT_FUNC_NUM_WIDTH) PcieCfgMgmtFuncNum; typedef Bit#(PCIE_CFG_MGMT_DATA_WIDTH) PCieCfgMgmtData; -interface RawPcieConfiguration; - (* prefix = "cfg_mgmt_" *) interface RawPcieCfgMgmt mgmt; - (* prefix = "cfg_pm_" *) interface RawPcieCfgPm pm; - (* prefix = "cfg_msi_" *) interface RawPcieCfgMsi msi; - (* prefix = "cfg_interrupt_" *) interface RawPcieCfgInterrupt interrupt; - (* prefix = "cfg_" *) interface RawPcieCfgControl control; - (* prefix = "cfg_fc_" *) interface RawPcieCfgFC flowControl; - (* prefix = "cfg_msg_transmit_" *) interface RawPcieCfgMsgTx msgTx; - (* prefix = "cfg_msg_received_" *) interface RawPcieCfgMsgRx msgRx; - (* prefix = "" *) interface RawPcieCfgStatus status; - (* prefix = "pcie_tfc_" *) interface RawPcieCfgTransmitFC txFlowControl; -endinterface - (*always_ready, always_enabled*) interface RawPcieCfgMgmt; (* result = "addr" *) method PcieCfgMgmtAddr addr; @@ -219,12 +206,46 @@ interface RawPcieCfgMsgRx; endinterface +typedef 1 PCIE_CFG_PHY_LINK_DOWN_WIDTH; +typedef 2 PCIE_CFG_PHY_LINK_STATUS_WIDTH; +typedef Bit#(PCIE_CFG_PHY_LINK_DOWN_WIDTH) PcieCfgPhyLinkDown; +typedef Bit#(PCIE_CFG_PHY_LINK_STATUS_WIDTH) PcieCfgPhyLinkStatus; +typedef 3 PCIE_CFG_NEGOTIATED_WIDTH_WIDTH; +typedef 3 PCIE_CFG_CURRENT_SPEED_WIDTH; +typedef 2 PCIE_CFG_MAX_PAYLOAD_WIDTH; +typedef 3 PCIE_CFG_MAX_READ_REQ_WIDTH; +typedef Bit#(PCIE_CFG_NEGOTIATED_WIDTH_WIDTH) PcieCfgNegotiatedWidth; +typedef Bit#(PCIE_CFG_CURRENT_SPEED_WIDTH) PCieCfgCurrentSpeed; +typedef Bit#(PCIE_CFG_MAX_PAYLOAD_WIDTH) PcieCfgMaxPayloadSize; +typedef Bit#(PCIE_CFG_MAX_READ_REQ_WIDTH) PCieCfgMaxReadReqSize; +typedef 16 PCIE_FUNCTIONS_STATUS_WIDTH; +typedef Bit#(PCIE_FUNCTIONS_STATUS_WIDTH) PcieCfgFunctionStatus; + (*always_ready, always_enabled*) interface RawPcieCfgStatus; - + (* result = "phy_link_down" *) method PcieCfgPhyLinkDown phyLinkDown; + (* result = "phy_link_status" *) method PcieCfgPhyLinkStatus phyLinkStatus; + (* result = "negotiated_width" *) method PcieCfgNegotiatedWidth negotiatedWidth; + (* result = "current_speed" *) method PCieCfgCurrentSpeed currentSpeed; + (* result = "max_payload" *) method PcieCfgMaxPayloadSize maxPayloadSize; + (* result = "max_read_req" *) method PCieCfgMaxReadReqSize maxReadReqSize; + (* result = "function_status" *) method PcieCfgFunctionStatus functionStatus; endinterface (*always_ready, always_enabled*) interface RawPcieCfgTransmitFC; +endinterface + +interface RawPcieConfiguration; + (* prefix = "cfg_mgmt_" *) interface RawPcieCfgMgmt mgmt; + (* prefix = "cfg_pm_" *) interface RawPcieCfgPm pm; + (* prefix = "cfg_msi_" *) interface RawPcieCfgMsi msi; + (* prefix = "cfg_interrupt_" *) interface RawPcieCfgInterrupt interrupt; + (* prefix = "cfg_" *) interface RawPcieCfgControl control; + (* prefix = "cfg_fc_" *) interface RawPcieCfgFC flowControl; + (* prefix = "cfg_msg_transmit_" *) interface RawPcieCfgMsgTx msgTx; + (* prefix = "cfg_msg_received_" *) interface RawPcieCfgMsgRx msgRx; + (* prefix = "" *) interface RawPcieCfgStatus status; + (* prefix = "pcie_tfc_" *) interface RawPcieCfgTransmitFC txFlowControl; endinterface \ No newline at end of file diff --git a/test/TestDmaCore.bsv b/test/TestDmaCore.bsv index 0698e83..0f0c2cf 100644 --- a/test/TestDmaCore.bsv +++ b/test/TestDmaCore.bsv @@ -1,4 +1,5 @@ import SemiFifo::*; +import GetPut::*; import Randomizable::*; import DmaTypes::*; import DmaRequestCore::*; @@ -6,11 +7,12 @@ import DmaRequestCore::*; typedef 50 TEST_NUM; typedef 64'hFFFFFFFFFFFFFFFF MAX_ADDRESS; typedef 32'hFFFFFFFF MAX_TEST_LENGTH; +typedef 2'b10 TLP_SIZE_512_SETTING; (* doc = "testcase" *) module mkChunkComputerTb (Empty); - ChunkCompute dut <- mkChunkComputer; + ChunkCompute dut <- mkChunkComputer(DMA_TX); Reg#(Bool) isInitReg <- mkReg(False); Reg#(UInt#(32)) testCntReg <- mkReg(0); @@ -35,6 +37,7 @@ module mkChunkComputerTb (Empty); startAddrRandomVal.cntrl.init; lengthRandomVal.cntrl.init; isInitReg <= True; + dut.setTlpMaxSize.put(fromInteger(valueOf(TLP_SIZE_512_SETTING))); $display("Start Test of mkChunkComputerTb"); endrule From 85baea72b7df8241a955d9e2791eb149d3d71253 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Mon, 8 Jul 2024 23:21:48 +0800 Subject: [PATCH 08/53] Dynamic TLP Max Payload Size --- src/DmaRequestCore.bsv | 8 ++++---- test/TestDmaCore.bsv | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/DmaRequestCore.bsv b/src/DmaRequestCore.bsv index b1782ae..193cda7 100644 --- a/src/DmaRequestCore.bsv +++ b/src/DmaRequestCore.bsv @@ -6,11 +6,11 @@ import DmaTypes::*; typedef 4096 BUS_BOUNDARY; -typedef TLog#(BUS_BOUNDARY) BUS_BOUNDARY_WIDTH; +typedef TLog#(TAdd#(1, BUS_BOUNDARY)) BUS_BOUNDARY_WIDTH; typedef Bit#(BUS_BOUNDARY_WIDTH) PcieTlpMaxMaxSize; typedef Bit#(TLog#(BUS_BOUNDARY_WIDTH)) PcieTlpSizeWidth; typedef 128 DEFAULT_TLP_SIZE; -typedef TLog#(DEFAULT_TLP_SIZE) DEFAULT_TLP_SIZE_WIDTH; +typedef TLog#(TAdd#(1, DEFAULT_TLP_SIZE)) DEFAULT_TLP_SIZE_WIDTH; typedef 3 PCIE_TLP_SIZE_SETTING_WIDTH; typedef Bit#(PCIE_TLP_SIZE_SETTING_WIDTH) PcieTlpSizeSetting; typedef enum {DMA_RX, DMA_TX} TRXDirection deriving(Bits, Eq); @@ -60,7 +60,7 @@ module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); dmaRequest: request, firstChunkLenMaybe: hasBoundary(request) ? tagged Valid firstLen : tagged Invalid }); -endrule + endrule rule execChunkSplit; let splitRequest = splitFifo.first; @@ -125,7 +125,7 @@ endrule DmaMemAddr defaultTlpMaxSize = fromInteger(valueOf(DEFAULT_TLP_SIZE)); tlpMaxSize <= DmaMemAddr'(defaultTlpMaxSize << setting); PcieTlpSizeWidth defaultTlpMaxSizeWidth = fromInteger(valueOf(DEFAULT_TLP_SIZE_WIDTH)); - tlpMaxSizeWidth <= PcieTlpSizeWidth'(defaultTlpMaxSizeWidth << setting); + tlpMaxSizeWidth <= PcieTlpSizeWidth'(defaultTlpMaxSizeWidth + zeroExtend(setting)); endmethod endinterface endmodule \ No newline at end of file diff --git a/test/TestDmaCore.bsv b/test/TestDmaCore.bsv index 0f0c2cf..48eb260 100644 --- a/test/TestDmaCore.bsv +++ b/test/TestDmaCore.bsv @@ -53,7 +53,8 @@ module mkChunkComputerTb (Empty); lenRemainReg <= testLength; dut.dmaRequests.enq(request); showRequest(request); - end else begin + end + else begin lenRemainReg <= 0; end endrule @@ -65,7 +66,8 @@ module mkChunkComputerTb (Empty); $display("Error, has 4KB boundary!"); showRequest(newRequest); $finish(); - end else begin + end + else begin // showRequest(newRequest); let newRemain = lenRemainReg - newRequest.length; lenRemainReg <= newRemain; From 00a6386b8e54c84ecd9b389e5a136eb69bd0949a Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Tue, 9 Jul 2024 16:55:01 +0800 Subject: [PATCH 09/53] Test various MPS settings and verify timing --- src/DmaRequestCore.bsv | 60 +++++++++++++++--------------------------- src/DmaTypes.bsv | 20 +++++++------- src/PcieTypes.bsv | 5 ++-- src/StreamUtils.bsv | 47 +++++++++++++++++++++++++++++++++ test/TestDmaCore.bsv | 33 ++++++++++++++++------- 5 files changed, 103 insertions(+), 62 deletions(-) create mode 100644 src/StreamUtils.bsv diff --git a/src/DmaRequestCore.bsv b/src/DmaRequestCore.bsv index 193cda7..e102bce 100644 --- a/src/DmaRequestCore.bsv +++ b/src/DmaRequestCore.bsv @@ -6,19 +6,17 @@ import DmaTypes::*; typedef 4096 BUS_BOUNDARY; -typedef TLog#(TAdd#(1, BUS_BOUNDARY)) BUS_BOUNDARY_WIDTH; -typedef Bit#(BUS_BOUNDARY_WIDTH) PcieTlpMaxMaxSize; +typedef TAdd#(1, TLog#(BUS_BOUNDARY)) BUS_BOUNDARY_WIDTH; +typedef Bit#(BUS_BOUNDARY_WIDTH) PcieTlpMaxMaxPayloadSize; typedef Bit#(TLog#(BUS_BOUNDARY_WIDTH)) PcieTlpSizeWidth; typedef 128 DEFAULT_TLP_SIZE; -typedef TLog#(TAdd#(1, DEFAULT_TLP_SIZE)) DEFAULT_TLP_SIZE_WIDTH; +typedef TAdd#(1, TLog#(DEFAULT_TLP_SIZE)) DEFAULT_TLP_SIZE_WIDTH; typedef 3 PCIE_TLP_SIZE_SETTING_WIDTH; typedef Bit#(PCIE_TLP_SIZE_SETTING_WIDTH) PcieTlpSizeSetting; -typedef enum {DMA_RX, DMA_TX} TRXDirection deriving(Bits, Eq); - typedef struct { DmaRequestFrame dmaRequest; - Maybe#(DmaMemAddr) firstChunkLenMaybe; + DmaMemAddr firstChunkLen; } ChunkRequestFrame deriving(Bits, Eq); interface ChunkCompute; @@ -44,21 +42,19 @@ module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); endfunction function DmaMemAddr getOffset(DmaRequestFrame request); - // 4096 - startAddr % 4096 - Bit#(BUS_BOUNDARY_WIDTH) remainder = truncate(request.startAddr); - Bit#(BUS_BOUNDARY_WIDTH) offset = fromInteger(valueOf(BUS_BOUNDARY) - 1) - zeroExtend(remainder) + 1; - return zeroExtend(offset); + // MPS - startAddr % MPS, MPS means MRRS when the module is set to RX mode + DmaMemAddr remainderOfMps = zeroExtend(PcieTlpMaxMaxPayloadSize'(request.startAddr[tlpMaxSizeWidth-1:0])); + DmaMemAddr offsetOfMps = tlpMaxSize - remainderOfMps; + return offsetOfMps; endfunction rule getfirstChunkLen; let request = inputFifo.first; inputFifo.deq; let offset = getOffset(request); - // firstChunkLen = offset % PCIE_TLP_BYTES - DmaMemAddr firstLen = zeroExtend(PcieTlpMaxMaxSize'(offset[tlpMaxSizeWidth-1:0])); splitFifo.enq(ChunkRequestFrame { dmaRequest: request, - firstChunkLenMaybe: hasBoundary(request) ? tagged Valid firstLen : tagged Invalid + firstChunkLen: hasBoundary(request) ? offset : tlpMaxSize }); endrule @@ -85,33 +81,18 @@ module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); end end else begin // isFirst - let remainderLength = splitRequest.dmaRequest.length - fromMaybe(0, splitRequest.firstChunkLenMaybe); - if (isValid(splitRequest.firstChunkLenMaybe)) begin - Bool isSplittingNextCycle = (remainderLength > 0); - isSplittingReg <= isSplittingNextCycle; - outputFifo.enq(DmaRequestFrame { - startAddr: splitRequest.dmaRequest.startAddr, - length: fromMaybe(0, splitRequest.firstChunkLenMaybe) - }); - if (!isSplittingNextCycle) begin - splitFifo.deq; - end - newChunkPtrReg <= splitRequest.dmaRequest.startAddr + fromMaybe(0, splitRequest.firstChunkLenMaybe); - totalLenRemainReg <= remainderLength; - end - else begin - Bool isSplittingNextCycle = (remainderLength > tlpMaxSize); - isSplittingReg <= isSplittingNextCycle; - outputFifo.enq(DmaRequestFrame { - startAddr: splitRequest.dmaRequest.startAddr, - length: tlpMaxSize - }); - if (!isSplittingNextCycle) begin - splitFifo.deq; - end - newChunkPtrReg <= splitRequest.dmaRequest.startAddr + tlpMaxSize; - totalLenRemainReg <= remainderLength - tlpMaxSize; + let remainderLength = splitRequest.dmaRequest.length - splitRequest.firstChunkLen; + Bool isSplittingNextCycle = (remainderLength > 0); + isSplittingReg <= isSplittingNextCycle; + outputFifo.enq(DmaRequestFrame { + startAddr: splitRequest.dmaRequest.startAddr, + length: splitRequest.firstChunkLen + }); + if (!isSplittingNextCycle) begin + splitFifo.deq; end + newChunkPtrReg <= splitRequest.dmaRequest.startAddr + splitRequest.firstChunkLen; + totalLenRemainReg <= remainderLength; end endrule @@ -128,4 +109,5 @@ module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); tlpMaxSizeWidth <= PcieTlpSizeWidth'(defaultTlpMaxSizeWidth + zeroExtend(setting)); endmethod endinterface + endmodule \ No newline at end of file diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index b8a9b51..120c9ef 100644 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -1,6 +1,7 @@ -import SemiFifo :: *; -import PcieTypes :: *; +import SemiFifo::*; +import StreamUtils::*; +import PcieTypes::*; typedef 512 DMA_DATA_WIDTH; typedef 64 DMA_HOSTMEM_ADDR_WIDTH; @@ -10,13 +11,6 @@ typedef Bit#(DMA_HOSTMEM_ADDR_WIDTH) DmaMemAddr; typedef Bit#(DMA_CSR_ADDR_WIDTH) DMACsrAddr; typedef Bit#(DMA_CSR_DATA_WIDTH) DMACsrValue; -typedef struct { - Bit#(dataWidth) data; - Bit#(TDiv#(dataWidth, BYTE_WIDTH)) byteEn; - Bool isFirst; - Bool isLast; -} DataFrame#(numeric type dataWidth) deriving(Bits, Bounded, Eq, FShow); - typedef struct { DmaMemAddr startAddr; DmaMemAddr length; @@ -27,12 +21,16 @@ typedef struct { DMACsrValue value; } DmaCsrFrame deriving(Bits, Bounded, Eq, FShow); +typedef enum { + DMA_RX, DMA_TX +} TRXDirection deriving(Bits, Eq); + interface DmaController#(numeric type dataWidth); - interface FifoIn#(DataFrame#(dataWidth)) dataC2HPipeIn; + interface FifoIn#(DataStream#(dataWidth)) dataC2HPipeIn; interface FifoIn#(DmaRequestFrame) reqC2HPipeIn; interface FifoIn#(DmaRequestFrame) reqH2CPipeIn; - interface FifoOut#(DataFrame#(dataWidth)) dataH2CPipeOut; + interface FifoOut#(DataStream#(dataWidth)) dataH2CPipeOut; interface FifoIn#(DmaCsrFrame) csrC2HPipeIn; interface FifoOut#(DMACsrAddr) csrC2HPipeOut; // read reg in the card from Host diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv index 3e780b8..af09da9 100644 --- a/src/PcieTypes.bsv +++ b/src/PcieTypes.bsv @@ -1,7 +1,6 @@ -import AxiStreamTypes :: *; +import AxiStreamTypes::*; +import StreamUtils::*; -typedef 8 BYTE_WIDTH; -typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; typedef 512 PCIE_TLP_BYTES; typedef TLog#(PCIE_TLP_BYTES) PCIE_TLP_BYTES_WIDTH; diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv new file mode 100644 index 0000000..a8fc721 --- /dev/null +++ b/src/StreamUtils.bsv @@ -0,0 +1,47 @@ +import Vector::*; +import FIFOF::*; +import SemiFifo::*; + +typedef 8 BYTE_WIDTH; +typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; + +typedef 2 CONCAT_STREAM_NUM; + +typedef struct { + Bit#(dataWidth) data; + Bit#(TDiv#(dataWidth, BYTE_WIDTH)) byteEn; + Bool isFirst; + Bool isLast; +} DataStream#(numeric type dataWidth) deriving(Bits, Bounded, Eq, FShow); + +interface StreamConcat#(numeric type dataWidth); + interface FifoIn#(DataStream#(dataWidth)) inputStreamFirst; + interface FifoIn#(DataStream#(dataWidth)) inputStreamSecond; + interface FifoOut#(DataStream#(dataWidth)) outputStream; +endinterface + +module mkStreamConcat (StreamConcat#(dataWidth) ifc); + + FIFOF#(DataStream#(dataWidth)) firstInputFifo <- mkFIFOF; + FIFOF#(DataStream#(dataWidth)) secondInputFifo <- mkFIFOF; + FIFOF#(DataStream#(dataWidth)) outputFifo <- mkFIFOF; + + Vector#(TMul#(CONCAT_STREAM_NUM, dataWidth), Reg#(Bit#(1))) concatDataReg <- replicateM(mkReg(0)); + Vector#(TDiv#(TMul#(CONCAT_STREAM_NUM, dataWidth), BYTE_WIDTH), Reg#(Bit#(1))) concatByteEnReg <- replicateM(mkReg(0)); + + Reg#(DataStream#(dataWidth)) firstStreamReg <- mkRegU; + Reg#(DataStream#(dataWidth)) secondStreamReg <- mkRegU; + + + rule readStreamFirst; + let stream = firstInputFifo.first; + // concatDataReg[valueOf(dataWidth)-1:0] <= stream.data; + // concatByteEnReg[valueOf(dataWidth)-1:0] <= stream.byteEn; + endrule + + interface inputStreamFirst = convertFifoToFifoIn(firstInputFifo); + interface inputStreamSecond = convertFifoToFifoIn(secondInputFifo); + interface outputStream = convertFifoToFifoOut(outputFifo); + + +endmodule \ No newline at end of file diff --git a/test/TestDmaCore.bsv b/test/TestDmaCore.bsv index 48eb260..6bdbe6b 100644 --- a/test/TestDmaCore.bsv +++ b/test/TestDmaCore.bsv @@ -4,10 +4,12 @@ import Randomizable::*; import DmaTypes::*; import DmaRequestCore::*; -typedef 50 TEST_NUM; +typedef 1000 CHUNK_PER_EPOCH_TEST_NUM; typedef 64'hFFFFFFFFFFFFFFFF MAX_ADDRESS; typedef 32'hFFFFFFFF MAX_TEST_LENGTH; -typedef 2'b10 TLP_SIZE_512_SETTING; +typedef 2'b00 DEFAULT_TLP_SIZE_SETTING; +typedef 4 CHUNK_TX_TEST_SETTING_NUM; +typedef 6 CHUNK_RX_TEST_SETTING_NUM; (* doc = "testcase" *) module mkChunkComputerTb (Empty); @@ -16,6 +18,7 @@ module mkChunkComputerTb (Empty); Reg#(Bool) isInitReg <- mkReg(False); Reg#(UInt#(32)) testCntReg <- mkReg(0); + Reg#(UInt#(32)) epochCntReg <- mkReg(0); Reg#(DmaMemAddr) lenRemainReg <- mkReg(0); Reg#(DmaRequestFrame) testRequest <- mkRegU; Randomize#(DmaMemAddr) startAddrRandomVal <- mkConstrainedRandomizer(0, fromInteger(valueOf(MAX_ADDRESS)-1)); @@ -37,8 +40,9 @@ module mkChunkComputerTb (Empty); startAddrRandomVal.cntrl.init; lengthRandomVal.cntrl.init; isInitReg <= True; - dut.setTlpMaxSize.put(fromInteger(valueOf(TLP_SIZE_512_SETTING))); + dut.setTlpMaxSize.put(fromInteger(valueOf(DEFAULT_TLP_SIZE_SETTING))); $display("Start Test of mkChunkComputerTb"); + $display("INFO: Set Max Payload Size to ", valueOf(DEFAULT_TLP_SIZE)); endrule rule testInput if (isInitReg && lenRemainReg == 0); @@ -68,16 +72,27 @@ module mkChunkComputerTb (Empty); $finish(); end else begin - // showRequest(newRequest); let newRemain = lenRemainReg - newRequest.length; lenRemainReg <= newRemain; - if(newRemain == 0) begin - testCntReg <= testCntReg + 1; + if (newRemain == 0) begin + if (epochCntReg < fromInteger(valueOf(CHUNK_PER_EPOCH_TEST_NUM)-1)) begin + epochCntReg <= epochCntReg + 1; + end + else begin + epochCntReg <= 0; + testCntReg <= testCntReg + 1; + if (testCntReg == fromInteger(valueOf(CHUNK_TX_TEST_SETTING_NUM)-1)) begin + $display("INFO: ChunkComputer Test End."); + $finish(); + end + else begin + PcieTlpSizeSetting newSetting = fromInteger(valueOf(DEFAULT_TLP_SIZE_SETTING)) + truncate(pack(testCntReg)) + 1; + dut.setTlpMaxSize.put(newSetting); + $display("INFO: Set Max Payload Size to ", pack(fromInteger(valueOf(DEFAULT_TLP_SIZE)) << newSetting)); + end + end end end endrule - rule testFinish ; - if (testCntReg == fromInteger(valueOf(TEST_NUM))) $finish(); - endrule endmodule \ No newline at end of file From 5e6b0092dbd6ea97a0475c07313141660fc5e376 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Wed, 10 Jul 2024 19:58:18 +0800 Subject: [PATCH 10/53] Add StreamUtils::StreamConcat --- img/concat.drawio | 96 +++++++++++++++++++++++--- src/DmaTypes.bsv | 4 +- src/StreamUtils.bsv | 162 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 230 insertions(+), 32 deletions(-) diff --git a/img/concat.drawio b/img/concat.drawio index 1d4939c..607cf6a 100644 --- a/img/concat.drawio +++ b/img/concat.drawio @@ -1,20 +1,98 @@ - + - - + + - - + + - - + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index 120c9ef..8d9da30 100644 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -27,10 +27,10 @@ typedef enum { interface DmaController#(numeric type dataWidth); - interface FifoIn#(DataStream#(dataWidth)) dataC2HPipeIn; + interface FifoIn#(DataStream) dataC2HPipeIn; interface FifoIn#(DmaRequestFrame) reqC2HPipeIn; interface FifoIn#(DmaRequestFrame) reqH2CPipeIn; - interface FifoOut#(DataStream#(dataWidth)) dataH2CPipeOut; + interface FifoOut#(DataStream) dataH2CPipeOut; interface FifoIn#(DmaCsrFrame) csrC2HPipeIn; interface FifoOut#(DMACsrAddr) csrC2HPipeOut; // read reg in the card from Host diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv index a8fc721..3bf86db 100644 --- a/src/StreamUtils.bsv +++ b/src/StreamUtils.bsv @@ -3,44 +3,164 @@ import FIFOF::*; import SemiFifo::*; typedef 8 BYTE_WIDTH; +typedef TAdd#(1, TLog#(BYTE_WIDTH)) BYTE_WIDTH_WIDTH; typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; typedef 2 CONCAT_STREAM_NUM; +typedef 512 DATA_WIDTH; +typedef TDiv#(DATA_WIDTH, BYTE_WIDTH) BYTE_EN_WIDTH; + +typedef Bit#(DATA_WIDTH) Data; +typedef Bit#(BYTE_EN_WIDTH) ByteEn; +typedef Bit#(TAdd#(1, TLog#(DATA_WIDTH))) BitPtr; +typedef Bit#(TAdd#(1, TLog#(BYTE_EN_WIDTH))) BytePtr; + typedef struct { - Bit#(dataWidth) data; - Bit#(TDiv#(dataWidth, BYTE_WIDTH)) byteEn; + Data data; + ByteEn byteEn; Bool isFirst; Bool isLast; -} DataStream#(numeric type dataWidth) deriving(Bits, Bounded, Eq, FShow); +} DataStream deriving(Bits, Bounded, Eq, FShow); -interface StreamConcat#(numeric type dataWidth); - interface FifoIn#(DataStream#(dataWidth)) inputStreamFirst; - interface FifoIn#(DataStream#(dataWidth)) inputStreamSecond; - interface FifoOut#(DataStream#(dataWidth)) outputStream; +interface StreamConcat; + interface FifoIn#(DataStream) inputStreamFirst; + interface FifoIn#(DataStream) inputStreamSecond; + interface FifoOut#(DataStream) outputStream; endinterface -module mkStreamConcat (StreamConcat#(dataWidth) ifc); +module mkStreamConcat (StreamConcat ifc); + + FIFOF#(DataStream) inputFifoA <- mkFIFOF; + FIFOF#(DataStream) inputFifoB <- mkFIFOF; + FIFOF#(DataStream) outputFifo <- mkFIFOF; + + FIFOF#(DataStream) prepareFifoA <- mkFIFOF; + FIFOF#(DataStream) prepareFifoB <- mkFIFOF; - FIFOF#(DataStream#(dataWidth)) firstInputFifo <- mkFIFOF; - FIFOF#(DataStream#(dataWidth)) secondInputFifo <- mkFIFOF; - FIFOF#(DataStream#(dataWidth)) outputFifo <- mkFIFOF; + Reg#(BytePtr) bytePtrRegA <- mkReg(0); + Reg#(BytePtr) bytePtrRegB <- mkReg(0); + Reg#(BytePtr) remainBytePtrReg <- mkReg(0); + Reg#(Bool) hasRemainReg <- mkReg(False); + Reg#(DataStream) remainStreamReg <- mkRegU; - Vector#(TMul#(CONCAT_STREAM_NUM, dataWidth), Reg#(Bit#(1))) concatDataReg <- replicateM(mkReg(0)); - Vector#(TDiv#(TMul#(CONCAT_STREAM_NUM, dataWidth), BYTE_WIDTH), Reg#(Bit#(1))) concatByteEnReg <- replicateM(mkReg(0)); + DataStream emptyStream = DataStream{ + data: 0, + byteEn: 0, + isFirst: False, + isLast: False + }; - Reg#(DataStream#(dataWidth)) firstStreamReg <- mkRegU; - Reg#(DataStream#(dataWidth)) secondStreamReg <- mkRegU; + BytePtr maxBytePtr = fromInteger(valueOf(BYTE_EN_WIDTH)); + BitPtr maxBitPtr = fromInteger(valueOf(DATA_WIDTH)); + function BytePtr getByteConcatPtr (ByteEn byteEn); + ByteEn byteEnTemp = byteEn; + BytePtr ptr = 0; + while (byteEnTemp > 0) begin + byteEnTemp = byteEnTemp >> 1; + ptr = ptr + 1; + end + return ptr; + endfunction + + function Tuple3#(DataStream, DataStream, BytePtr) getConcatStream + (DataStream streamA, DataStream streamB, BytePtr bytePtrA, BytePtr bytePtrB); + Bool isCallLegally = (streamA.isLast && bytePtrA < maxBytePtr && bytePtrA > 0); + BitPtr bitPtrA = zeroExtend(bytePtrA) << fromInteger(valueOf(BYTE_WIDTH_WIDTH)); + // Fill the low PtrA bytes by streamA data + Data concatDataA = streamA.data; + ByteEn concatByteEnA = streamA.byteEn; + // Fill the high bytes by streamB data + Data concatDataB = streamB.data << bitPtrA; + ByteEn concatByteEnB = streamB.byteEn << bitPtrA; + Data concatData = concatDataA & concatDataB; + ByteEn concatByteEn = concatByteEnA & concatByteEnB; + // Get the remain bytes of streamB data + BitPtr resBitPtr = maxBitPtr - bitPtrA; + BytePtr resBytePtr = maxBytePtr - bytePtrA; + Data remainData = streamB.data >> resBitPtr; + ByteEn remainByteEn = streamB.byteEn >> resBytePtr; + // Get if the concat frame is the last + Bool isConcatStreamLast = streamB.isLast; + BytePtr remainBytePtr = 0; + if (resBytePtr < bytePtrB ) begin + isConcatStreamLast = False; + remainBytePtr = bytePtrB - resBytePtr; + end + DataStream concatStream = emptyStream; + DataStream remainStream = emptyStream; + // package the return concatStream and remainStream + if(isCallLegally) begin + concatStream = DataStream{ + data: concatData, + byteEn: concatByteEn, + isFirst: False, + isLast: isConcatStreamLast + }; + remainStream = DataStream{ + data: remainData, + byteEn: remainByteEn, + isFirst: False, + isLast: True + }; + end + return tuple3(concatStream, remainStream, remainBytePtr); + endfunction + + rule prepareStream; + let streamA = inputFifoA.first; + let streamB = inputFifoB.first; + inputFifoA.deq; + inputFifoB.deq; + prepareFifoA.enq(streamA); + prepareFifoB.enq(streamB); + bytePtrRegA <= streamA.isLast ? getByteConcatPtr(streamA.byteEn) : bytePtrRegA; + bytePtrRegB <= streamB.isLast ? getByteConcatPtr(streamB.byteEn) : maxBytePtr; + endrule - rule readStreamFirst; - let stream = firstInputFifo.first; - // concatDataReg[valueOf(dataWidth)-1:0] <= stream.data; - // concatByteEnReg[valueOf(dataWidth)-1:0] <= stream.byteEn; + rule concatStream; + let streamA = prepareFifoA.first; + let streamB = prepareFifoB.first; + // Only StreamA + if (!hasRemainReg && !streamA.isLast && streamB.isFirst) begin + outputFifo.enq(streamA); + prepareFifoA.deq; + end + // the last StreamA + the first StreamB + else if (!hasRemainReg && streamA.isLast && streamB.isFirst) begin + match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(streamA, streamB, bytePtrRegA, bytePtrRegB); + Bool hasRemain = unpack(remainStream.byteEn[0]); + hasRemainReg <= hasRemain; + remainStreamReg <= remainStream; + remainBytePtrReg <= remainBytePtr; + if (concatStream.byteEn[0] == 1) begin + outputFifo.enq(concatStream); + end + prepareFifoA.deq; + prepareFifoB.deq; + end + // streamB + the remain data + else if (hasRemainReg && !streamB.isFirst) begin + match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(remainStreamReg, streamB, remainBytePtrReg, bytePtrRegB); + Bool hasRemain = unpack(remainStream.byteEn[0]); + hasRemainReg <= hasRemain; + remainStreamReg <= remainStream; + remainBytePtrReg <= remainBytePtr; + if (concatStream.byteEn[0] == 1) begin + outputFifo.enq(concatStream); + end + prepareFifoB.deq; + end + // Only the remain data + else if (hasRemainReg) begin + outputFifo.enq(remainStreamReg); + hasRemainReg <= False; + end endrule - interface inputStreamFirst = convertFifoToFifoIn(firstInputFifo); - interface inputStreamSecond = convertFifoToFifoIn(secondInputFifo); + interface inputStreamFirst = convertFifoToFifoIn(inputFifoA); + interface inputStreamSecond = convertFifoToFifoIn(inputFifoB); interface outputStream = convertFifoToFifoOut(outputFifo); From 75ebadb05f016435d7357734b284f6bf9b4b6e4d Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Thu, 11 Jul 2024 02:20:42 +0800 Subject: [PATCH 11/53] a simple test: --- LICENSE | 0 Makefile.test | 2 + README.md | 0 run_one.sh | 2 +- src/DmaController.bsv | 0 src/DmaRequestCore.bsv | 0 src/DmaTypes.bsv | 0 src/PcieTypes.bsv | 0 src/StreamUtils.bsv | 20 ++++++---- test/Makefile | 0 test/TestAxiStream.bsv | 0 test/TestDmaCore.bsv | 2 +- test/TestStreamUtils.bsv | 80 ++++++++++++++++++++++++++++++++++++++++ 13 files changed, 97 insertions(+), 9 deletions(-) mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 src/DmaController.bsv mode change 100644 => 100755 src/DmaRequestCore.bsv mode change 100644 => 100755 src/DmaTypes.bsv mode change 100644 => 100755 src/PcieTypes.bsv mode change 100644 => 100755 src/StreamUtils.bsv mode change 100644 => 100755 test/Makefile mode change 100644 => 100755 test/TestAxiStream.bsv mode change 100644 => 100755 test/TestDmaCore.bsv create mode 100755 test/TestStreamUtils.bsv diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/Makefile.test b/Makefile.test index 0be9d4e..e60c219 100755 --- a/Makefile.test +++ b/Makefile.test @@ -2,8 +2,10 @@ TESTDIR ?= $(abspath ../test) LOGDIR ?= $(abspath ../tmp) TESTBENCHS = \ + TestStreamUtils.bsv \ TestDmaCore.bsv +TestStreamUtils = mkStreamConcatTb TestDmaCore.bsv = mkChunkComputerTb all: $(TESTBENCHS) diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/run_one.sh b/run_one.sh index f049c0d..ad1eac1 100755 --- a/run_one.sh +++ b/run_one.sh @@ -13,7 +13,7 @@ TEST_LOG=run.log TEST_DIR=test cd $TEST_DIR truncate -s 0 $TEST_LOG -FILES=`ls TestDmaCore.bsv` +FILES=`ls TestStreamUtils.bsv` ########################################################################### for FILE in $FILES; do # echo $FILE diff --git a/src/DmaController.bsv b/src/DmaController.bsv old mode 100644 new mode 100755 diff --git a/src/DmaRequestCore.bsv b/src/DmaRequestCore.bsv old mode 100644 new mode 100755 diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv old mode 100644 new mode 100755 diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv old mode 100644 new mode 100755 diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv old mode 100644 new mode 100755 index 3bf86db..0b609a5 --- a/src/StreamUtils.bsv +++ b/src/StreamUtils.bsv @@ -3,7 +3,7 @@ import FIFOF::*; import SemiFifo::*; typedef 8 BYTE_WIDTH; -typedef TAdd#(1, TLog#(BYTE_WIDTH)) BYTE_WIDTH_WIDTH; +typedef TLog#(BYTE_WIDTH) BYTE_WIDTH_WIDTH; typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; typedef 2 CONCAT_STREAM_NUM; @@ -64,23 +64,28 @@ module mkStreamConcat (StreamConcat ifc); return ptr; endfunction - function Tuple3#(DataStream, DataStream, BytePtr) getConcatStream - (DataStream streamA, DataStream streamB, BytePtr bytePtrA, BytePtr bytePtrB); + function Tuple3#(DataStream, DataStream, BytePtr) getConcatStream ( + DataStream streamA, DataStream streamB, BytePtr bytePtrA, BytePtr bytePtrB + ); Bool isCallLegally = (streamA.isLast && bytePtrA < maxBytePtr && bytePtrA > 0); BitPtr bitPtrA = zeroExtend(bytePtrA) << fromInteger(valueOf(BYTE_WIDTH_WIDTH)); + // Fill the low PtrA bytes by streamA data Data concatDataA = streamA.data; ByteEn concatByteEnA = streamA.byteEn; + // Fill the high bytes by streamB data Data concatDataB = streamB.data << bitPtrA; - ByteEn concatByteEnB = streamB.byteEn << bitPtrA; - Data concatData = concatDataA & concatDataB; - ByteEn concatByteEn = concatByteEnA & concatByteEnB; + ByteEn concatByteEnB = streamB.byteEn << bytePtrA; + Data concatData = concatDataA | concatDataB; + ByteEn concatByteEn = concatByteEnA | concatByteEnB; + // Get the remain bytes of streamB data BitPtr resBitPtr = maxBitPtr - bitPtrA; BytePtr resBytePtr = maxBytePtr - bytePtrA; Data remainData = streamB.data >> resBitPtr; ByteEn remainByteEn = streamB.byteEn >> resBytePtr; + // Get if the concat frame is the last Bool isConcatStreamLast = streamB.isLast; BytePtr remainBytePtr = 0; @@ -90,6 +95,7 @@ module mkStreamConcat (StreamConcat ifc); end DataStream concatStream = emptyStream; DataStream remainStream = emptyStream; + // package the return concatStream and remainStream if(isCallLegally) begin concatStream = DataStream{ @@ -129,6 +135,7 @@ module mkStreamConcat (StreamConcat ifc); end // the last StreamA + the first StreamB else if (!hasRemainReg && streamA.isLast && streamB.isFirst) begin + $display(bytePtrRegA); match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(streamA, streamB, bytePtrRegA, bytePtrRegB); Bool hasRemain = unpack(remainStream.byteEn[0]); hasRemainReg <= hasRemain; @@ -163,5 +170,4 @@ module mkStreamConcat (StreamConcat ifc); interface inputStreamSecond = convertFifoToFifoIn(inputFifoB); interface outputStream = convertFifoToFifoOut(outputFifo); - endmodule \ No newline at end of file diff --git a/test/Makefile b/test/Makefile old mode 100644 new mode 100755 diff --git a/test/TestAxiStream.bsv b/test/TestAxiStream.bsv old mode 100644 new mode 100755 diff --git a/test/TestDmaCore.bsv b/test/TestDmaCore.bsv old mode 100644 new mode 100755 index 6bdbe6b..582d27f --- a/test/TestDmaCore.bsv +++ b/test/TestDmaCore.bsv @@ -12,7 +12,7 @@ typedef 4 CHUNK_TX_TEST_SETTING_NUM; typedef 6 CHUNK_RX_TEST_SETTING_NUM; (* doc = "testcase" *) -module mkChunkComputerTb (Empty); +module mkChunkComputerTb(Empty); ChunkCompute dut <- mkChunkComputer(DMA_TX); diff --git a/test/TestStreamUtils.bsv b/test/TestStreamUtils.bsv new file mode 100755 index 0000000..5e716e1 --- /dev/null +++ b/test/TestStreamUtils.bsv @@ -0,0 +1,80 @@ +import SemiFifo::*; +import Randomizable::*; +import StreamUtils::*; + +typedef UInt#(32) StreamSize; +typedef 'hABABAB PSUEDO_DATA; +typedef 'hFFFF MAX_STREAM_SIZE; +typedef 'h1 MIN_STREAM_SIZE; +typedef 50 TEST_NUM; +typedef 'hFFFFFFFFFFFFFFFF MAX_BYTE_EN; + + +function Action showDataStream (DataStream stream); + return action + $display("Data = %b", stream.data); + $display("byteEn = %b", stream.byteEn); + $display("isFirst = %b, isLast = %b", stream.isFirst, stream.isLast); + endaction; +endfunction + +(* doc = "testcase" *) +module mkStreamConcatTb(Empty); + + StreamConcat dut <- mkStreamConcat; + + Randomize#(StreamSize) streamASizeRandomValue <- mkConstrainedRandomizer(MIN_STREAM_SIZE, MAX_STREAM_SIZE); + Randomize#(StreamSize) streamBSizeRandomValue <- mkConstrainedRandomizer(MIN_STREAM_SIZE, MAX_STREAM_SIZE); + + Reg#(StreamSize) streamASizeReg <- mkReg(0); + Reg#(StreamSize) streamBSizeReg <- mkReg(0); + Reg#(StreamSize) stramAframeCntReg <- mkReg(0); + Reg#(StreamSize) stramBframeCntReg <- mkReg(0); + + Reg#(Bool) isInitReg <- mkReg(False); + Reg#(UInt#(32)) testCntReg <- mkReg(0); + + DataStream testStream = DataStream{ + data: 'b1010101010101010, + byteEn: 'b11, + isFirst: True, + isLast: True + }; + + function DataStream generatePsuedoStream (StreamSize size, Bool isFirst); + if (size < BYTE_EN_WIDTH) begin + return DataStream{ + data: PSUEDO_DATA, + byteEn: (1 << size) - 1, + isFirst: isFirst, + isLast: True + }; + end + else begin + return DataStream{ + data: PSUEDO_DATA, + byteEn: MAX_BYTE_EN, + isFirst: isFirst, + isLast: False + }; + end + endfunction + + rule testInit if (!isInitReg); + $display("INFO: start StreamConcatTb!"); + streamSizeRandomValue.cntrl.init; + isInitReg <= True; + endrule + + rule testInput if (isInitReg && testCntReg < TEST_NUM); + dut.inputStreamFirst.enq(testStreamA); + dut.inputStreamSecond.enq(testStreamA); + testCntReg <= testCntReg + 1; + endrule + + rule testOutput; + let outStream = dut.outputStream.first; + showDataStream(outStream); + dut.outputStream.deq; + endrule +endmodule \ No newline at end of file From 1b763352b5440571243cd5221a405cda4ce328a3 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Thu, 11 Jul 2024 02:29:33 +0800 Subject: [PATCH 12/53] a simple test --- src/StreamUtils.bsv | 2 +- test/TestStreamUtils.bsv | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv index 0b609a5..20531ef 100755 --- a/src/StreamUtils.bsv +++ b/src/StreamUtils.bsv @@ -101,7 +101,7 @@ module mkStreamConcat (StreamConcat ifc); concatStream = DataStream{ data: concatData, byteEn: concatByteEn, - isFirst: False, + isFirst: streamA.isLast, isLast: isConcatStreamLast }; remainStream = DataStream{ diff --git a/test/TestStreamUtils.bsv b/test/TestStreamUtils.bsv index 5e716e1..f970eb2 100755 --- a/test/TestStreamUtils.bsv +++ b/test/TestStreamUtils.bsv @@ -23,8 +23,8 @@ module mkStreamConcatTb(Empty); StreamConcat dut <- mkStreamConcat; - Randomize#(StreamSize) streamASizeRandomValue <- mkConstrainedRandomizer(MIN_STREAM_SIZE, MAX_STREAM_SIZE); - Randomize#(StreamSize) streamBSizeRandomValue <- mkConstrainedRandomizer(MIN_STREAM_SIZE, MAX_STREAM_SIZE); + Randomize#(StreamSize) streamASizeRandomValue <- mkConstrainedRandomizer(fromInteger(valueOf(MIN_STREAM_SIZE)), fromInteger(valueOf(MAX_STREAM_SIZE))); + Randomize#(StreamSize) streamBSizeRandomValue <- mkConstrainedRandomizer(fromInteger(valueOf(MIN_STREAM_SIZE)), fromInteger(valueOf(MAX_STREAM_SIZE))); Reg#(StreamSize) streamASizeReg <- mkReg(0); Reg#(StreamSize) streamBSizeReg <- mkReg(0); @@ -42,9 +42,9 @@ module mkStreamConcatTb(Empty); }; function DataStream generatePsuedoStream (StreamSize size, Bool isFirst); - if (size < BYTE_EN_WIDTH) begin + if (size < fromInteger(valueOf(BYTE_EN_WIDTH))) begin return DataStream{ - data: PSUEDO_DATA, + data: fromInteger(valueOf(PSUEDO_DATA)), byteEn: (1 << size) - 1, isFirst: isFirst, isLast: True @@ -52,8 +52,8 @@ module mkStreamConcatTb(Empty); end else begin return DataStream{ - data: PSUEDO_DATA, - byteEn: MAX_BYTE_EN, + data: fromInteger(valueOf(PSUEDO_DATA)), + byteEn: fromInteger(valueOf(MAX_BYTE_EN)), isFirst: isFirst, isLast: False }; @@ -62,13 +62,14 @@ module mkStreamConcatTb(Empty); rule testInit if (!isInitReg); $display("INFO: start StreamConcatTb!"); - streamSizeRandomValue.cntrl.init; + streamASizeRandomValue.cntrl.init; + streamBSizeRandomValue.cntrl.init; isInitReg <= True; endrule - rule testInput if (isInitReg && testCntReg < TEST_NUM); - dut.inputStreamFirst.enq(testStreamA); - dut.inputStreamSecond.enq(testStreamA); + rule testInput if (isInitReg && testCntReg < fromInteger(valueOf(TEST_NUM))); + dut.inputStreamFirst.enq(testStream); + dut.inputStreamSecond.enq(testStream); testCntReg <= testCntReg + 1; endrule From ebc614f695097041deccaaec6c4723c22af37630 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Thu, 11 Jul 2024 19:03:51 +0800 Subject: [PATCH 13/53] Test Pass --- src/StreamUtils.bsv | 137 +++++++++++++++++++++++++-------------- test/TestStreamUtils.bsv | 135 +++++++++++++++++++++++++------------- 2 files changed, 178 insertions(+), 94 deletions(-) diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv index 20531ef..9288219 100755 --- a/src/StreamUtils.bsv +++ b/src/StreamUtils.bsv @@ -23,20 +23,43 @@ typedef struct { Bool isLast; } DataStream deriving(Bits, Bounded, Eq, FShow); +typedef struct { + DataStream stream; + BytePtr bytePtr; +} StreamWithPtr deriving(Bits, Bounded, Eq, FShow); + interface StreamConcat; interface FifoIn#(DataStream) inputStreamFirst; interface FifoIn#(DataStream) inputStreamSecond; interface FifoOut#(DataStream) outputStream; endinterface +function BytePtr convertByteEn2BytePtr (ByteEn byteEn); + ByteEn byteEnTemp = byteEn; + BytePtr ptr = 0; + while (byteEnTemp > 0) begin + byteEnTemp = byteEnTemp >> 1; + ptr = ptr + 1; + end + return ptr; +endfunction + +function Action showDataStream (DataStream stream); + return action + $display(" Data = %h", stream.data); + $display(" byteEn = %b", stream.byteEn); + $display(" isFirst = %b, isLast = %b", stream.isFirst, stream.isLast); + endaction; +endfunction + module mkStreamConcat (StreamConcat ifc); FIFOF#(DataStream) inputFifoA <- mkFIFOF; FIFOF#(DataStream) inputFifoB <- mkFIFOF; FIFOF#(DataStream) outputFifo <- mkFIFOF; - FIFOF#(DataStream) prepareFifoA <- mkFIFOF; - FIFOF#(DataStream) prepareFifoB <- mkFIFOF; + FIFOF#(StreamWithPtr) prepareFifoA <- mkFIFOF; + FIFOF#(StreamWithPtr) prepareFifoB <- mkFIFOF; Reg#(BytePtr) bytePtrRegA <- mkReg(0); Reg#(BytePtr) bytePtrRegB <- mkReg(0); @@ -47,27 +70,15 @@ module mkStreamConcat (StreamConcat ifc); DataStream emptyStream = DataStream{ data: 0, byteEn: 0, - isFirst: False, - isLast: False + isFirst: True, + isLast: True }; BytePtr maxBytePtr = fromInteger(valueOf(BYTE_EN_WIDTH)); BitPtr maxBitPtr = fromInteger(valueOf(DATA_WIDTH)); - function BytePtr getByteConcatPtr (ByteEn byteEn); - ByteEn byteEnTemp = byteEn; - BytePtr ptr = 0; - while (byteEnTemp > 0) begin - byteEnTemp = byteEnTemp >> 1; - ptr = ptr + 1; - end - return ptr; - endfunction - - function Tuple3#(DataStream, DataStream, BytePtr) getConcatStream ( - DataStream streamA, DataStream streamB, BytePtr bytePtrA, BytePtr bytePtrB - ); - Bool isCallLegally = (streamA.isLast && bytePtrA < maxBytePtr && bytePtrA > 0); + function Tuple3#(DataStream, DataStream, BytePtr) getConcatStream (DataStream streamA, DataStream streamB, BytePtr bytePtrA, BytePtr bytePtrB); + Bool isCallLegally = (streamA.isLast && bytePtrA <= maxBytePtr && bytePtrA > 0); BitPtr bitPtrA = zeroExtend(bytePtrA) << fromInteger(valueOf(BYTE_WIDTH_WIDTH)); // Fill the low PtrA bytes by streamA data @@ -114,51 +125,77 @@ module mkStreamConcat (StreamConcat ifc); return tuple3(concatStream, remainStream, remainBytePtr); endfunction - rule prepareStream; + rule prepareStreamA; let streamA = inputFifoA.first; - let streamB = inputFifoB.first; inputFifoA.deq; + BytePtr bytePtr = convertByteEn2BytePtr(streamA.byteEn); + prepareFifoA.enq(StreamWithPtr { + stream: streamA, + bytePtr: bytePtr + }); + endrule + + rule prepareStreamB; + let streamB = inputFifoB.first; inputFifoB.deq; - prepareFifoA.enq(streamA); - prepareFifoB.enq(streamB); - bytePtrRegA <= streamA.isLast ? getByteConcatPtr(streamA.byteEn) : bytePtrRegA; - bytePtrRegB <= streamB.isLast ? getByteConcatPtr(streamB.byteEn) : maxBytePtr; + BytePtr bytePtr = convertByteEn2BytePtr(streamB.byteEn); + prepareFifoB.enq(StreamWithPtr { + stream: streamB, + bytePtr: bytePtr + }); endrule rule concatStream; - let streamA = prepareFifoA.first; - let streamB = prepareFifoB.first; - // Only StreamA - if (!hasRemainReg && !streamA.isLast && streamB.isFirst) begin - outputFifo.enq(streamA); - prepareFifoA.deq; - end - // the last StreamA + the first StreamB - else if (!hasRemainReg && streamA.isLast && streamB.isFirst) begin - $display(bytePtrRegA); - match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(streamA, streamB, bytePtrRegA, bytePtrRegB); - Bool hasRemain = unpack(remainStream.byteEn[0]); - hasRemainReg <= hasRemain; - remainStreamReg <= remainStream; - remainBytePtrReg <= remainBytePtr; - if (concatStream.byteEn[0] == 1) begin + // StreamA or StreamA + first StreamB + if (prepareFifoA.notEmpty && prepareFifoB.notEmpty && !hasRemainReg) begin + let streamA = prepareFifoA.first.stream; + let streamB = prepareFifoB.first.stream; + let bytePtrA = prepareFifoA.first.bytePtr; + let bytePtrB = prepareFifoB.first.bytePtr; + // Only StreamA frame + if (!streamA.isLast && streamB.isFirst) begin + outputFifo.enq(streamA); + prepareFifoA.deq; + end + // the last StreamA + the first StreamB + else if (streamA.isLast && streamB.isFirst) begin + match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(streamA, streamB, bytePtrA, bytePtrB); + Bool hasRemain = unpack(remainStream.byteEn[0]); + hasRemainReg <= hasRemain; + remainStreamReg <= remainStream; + remainBytePtrReg <= remainBytePtr; outputFifo.enq(concatStream); + prepareFifoA.deq; + prepareFifoB.deq; end - prepareFifoA.deq; - prepareFifoB.deq; end + // streamB + the remain data - else if (hasRemainReg && !streamB.isFirst) begin - match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(remainStreamReg, streamB, remainBytePtrReg, bytePtrRegB); - Bool hasRemain = unpack(remainStream.byteEn[0]); - hasRemainReg <= hasRemain; - remainStreamReg <= remainStream; - remainBytePtrReg <= remainBytePtr; - if (concatStream.byteEn[0] == 1) begin + else if (prepareFifoB.notEmpty && hasRemainReg) begin + let streamB = prepareFifoB.first.stream; + let bytePtrB = prepareFifoB.first.bytePtr; + if (!streamB.isFirst) begin + match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(remainStreamReg, streamB, remainBytePtrReg, bytePtrB); + Bool hasRemain = unpack(remainStream.byteEn[0]); + hasRemainReg <= hasRemain; + remainStreamReg <= remainStream; + remainBytePtrReg <= remainBytePtr; + if (concatStream.byteEn == 0) begin + $display("B + remain", remainBytePtrReg, bytePtrB); + $display("StreamB"); + showDataStream(streamB); + $display("remain"); + showDataStream(remainStreamReg); + end outputFifo.enq(concatStream); + prepareFifoB.deq; + end + else begin + outputFifo.enq(remainStreamReg); + hasRemainReg <= False; end - prepareFifoB.deq; end + // Only the remain data else if (hasRemainReg) begin outputFifo.enq(remainStreamReg); diff --git a/test/TestStreamUtils.bsv b/test/TestStreamUtils.bsv index f970eb2..ca723be 100755 --- a/test/TestStreamUtils.bsv +++ b/test/TestStreamUtils.bsv @@ -1,22 +1,24 @@ +import FIFOF::*; import SemiFifo::*; import Randomizable::*; import StreamUtils::*; typedef UInt#(32) StreamSize; -typedef 'hABABAB PSUEDO_DATA; -typedef 'hFFFF MAX_STREAM_SIZE; -typedef 'h1 MIN_STREAM_SIZE; -typedef 50 TEST_NUM; typedef 'hFFFFFFFFFFFFFFFF MAX_BYTE_EN; +typedef 'hAB PSEUDO_DATA; +typedef 8 PSEUDO_DATA_WIDTH; + +typedef 'h1 MIN_STREAM_SIZE; + +// TEST HYPER PARAMETERS CASE 1 +// typedef 100 MAX_STREAM_SIZE; +// typedef 10 TEST_NUM; + +// TEST HYPER PARAMETERS CASE 2 +typedef 'hFFFF MAX_STREAM_SIZE; +typedef 1000 TEST_NUM; -function Action showDataStream (DataStream stream); - return action - $display("Data = %b", stream.data); - $display("byteEn = %b", stream.byteEn); - $display("isFirst = %b, isLast = %b", stream.isFirst, stream.isLast); - endaction; -endfunction (* doc = "testcase" *) module mkStreamConcatTb(Empty); @@ -26,56 +28,101 @@ module mkStreamConcatTb(Empty); Randomize#(StreamSize) streamASizeRandomValue <- mkConstrainedRandomizer(fromInteger(valueOf(MIN_STREAM_SIZE)), fromInteger(valueOf(MAX_STREAM_SIZE))); Randomize#(StreamSize) streamBSizeRandomValue <- mkConstrainedRandomizer(fromInteger(valueOf(MIN_STREAM_SIZE)), fromInteger(valueOf(MAX_STREAM_SIZE))); - Reg#(StreamSize) streamASizeReg <- mkReg(0); - Reg#(StreamSize) streamBSizeReg <- mkReg(0); - Reg#(StreamSize) stramAframeCntReg <- mkReg(0); - Reg#(StreamSize) stramBframeCntReg <- mkReg(0); + Reg#(StreamSize) streamARemainSizeReg <- mkReg(0); + Reg#(StreamSize) streamBRemainSizeReg <- mkReg(0); + Reg#(StreamSize) concatSizeReg <- mkReg(0); + + FIFOF#(StreamSize) ideaConcatSizeFifo <- mkSizedFIFOF(10); Reg#(Bool) isInitReg <- mkReg(False); Reg#(UInt#(32)) testCntReg <- mkReg(0); + Reg#(UInt#(32)) testRoundReg <- mkReg(0); + Reg#(UInt#(32)) testFinishCntReg <- mkReg(0); - DataStream testStream = DataStream{ - data: 'b1010101010101010, - byteEn: 'b11, - isFirst: True, - isLast: True - }; - - function DataStream generatePsuedoStream (StreamSize size, Bool isFirst); - if (size < fromInteger(valueOf(BYTE_EN_WIDTH))) begin - return DataStream{ - data: fromInteger(valueOf(PSUEDO_DATA)), - byteEn: (1 << size) - 1, - isFirst: isFirst, - isLast: True - }; - end - else begin - return DataStream{ - data: fromInteger(valueOf(PSUEDO_DATA)), - byteEn: fromInteger(valueOf(MAX_BYTE_EN)), - isFirst: isFirst, - isLast: False - }; - end + Data pseudoData = fromInteger(valueOf(PSEUDO_DATA)); + for (Integer idx = 0; idx < valueOf(TDiv#(DATA_WIDTH, PSEUDO_DATA_WIDTH)); idx = idx + 1) begin + pseudoData = pseudoData | (pseudoData << idx*valueOf(PSEUDO_DATA_WIDTH)); + end + + function DataStream generatePsuedoStream (StreamSize size, Bool isFirst, Bool isLast); + let offsetPtr = (fromInteger(valueOf(BYTE_EN_WIDTH)) - size) << valueOf(BYTE_WIDTH_WIDTH); + Data streamData = (pseudoData << offsetPtr) >> offsetPtr; + return DataStream{ + data: streamData, + byteEn: (1 << size) - 1, + isFirst: isFirst, + isLast: isLast + }; endfunction rule testInit if (!isInitReg); - $display("INFO: start StreamConcatTb!"); + $display("INFO: ================start StreamConcatTb!=================="); + $display(valueOf(BYTE_WIDTH_WIDTH)); streamASizeRandomValue.cntrl.init; streamBSizeRandomValue.cntrl.init; isInitReg <= True; endrule rule testInput if (isInitReg && testCntReg < fromInteger(valueOf(TEST_NUM))); - dut.inputStreamFirst.enq(testStream); - dut.inputStreamSecond.enq(testStream); - testCntReg <= testCntReg + 1; + + if (testRoundReg == 0 && dut.inputStreamFirst.notFull && dut.inputStreamSecond.notFull) begin + StreamSize sizeA <- streamASizeRandomValue.next; + StreamSize sizeB <- streamASizeRandomValue.next; + ideaConcatSizeFifo.enq(sizeA + sizeB); + testRoundReg <= (sizeA + sizeB) / fromInteger(valueOf(BYTE_EN_WIDTH)); + let isLast = sizeA <= fromInteger(valueOf(BYTE_EN_WIDTH)); + let firstSizeA = isLast ? sizeA : fromInteger(valueOf(BYTE_EN_WIDTH)); + let firstSizeB = isLast ? sizeB : fromInteger(valueOf(BYTE_EN_WIDTH)); + dut.inputStreamFirst.enq(generatePsuedoStream(firstSizeA, True, isLast)); + dut.inputStreamSecond.enq(generatePsuedoStream(firstSizeB, True, isLast)); + streamARemainSizeReg <= sizeA - firstSizeA; + streamBRemainSizeReg <= sizeB - firstSizeB; + testCntReg <= testCntReg + 1; + $display("INFO: Add Input of %d Epoch", testCntReg + 1); + $display("INFO: streamASize = %d, streamBSize = %d, ideaSize = %d", sizeA, sizeB, sizeA+sizeB); + end + + else if (testRoundReg > 0) begin + if (streamARemainSizeReg > 0 && dut.inputStreamFirst.notFull) begin + dut.inputStreamFirst.enq(generatePsuedoStream(streamARemainSizeReg, False, (streamARemainSizeReg <= fromInteger(valueOf(BYTE_EN_WIDTH))))); + streamARemainSizeReg <= (streamARemainSizeReg > fromInteger(valueOf(BYTE_EN_WIDTH))) ? streamARemainSizeReg - fromInteger(valueOf(BYTE_EN_WIDTH)) : 0; + end + if (streamBRemainSizeReg > 0 && dut.inputStreamSecond.notFull) begin + dut.inputStreamSecond.enq(generatePsuedoStream(streamBRemainSizeReg, False, (streamARemainSizeReg <= fromInteger(valueOf(BYTE_EN_WIDTH))))); + streamBRemainSizeReg <= (streamBRemainSizeReg > fromInteger(valueOf(BYTE_EN_WIDTH))) ? streamBRemainSizeReg - fromInteger(valueOf(BYTE_EN_WIDTH)) : 0; + end + testRoundReg <= testRoundReg - 1; + end + endrule rule testOutput; let outStream = dut.outputStream.first; - showDataStream(outStream); + StreamSize concatSize = concatSizeReg + unpack(zeroExtend(convertByteEn2BytePtr(outStream.byteEn))); + if (outStream.isLast) begin + let ideaSize = ideaConcatSizeFifo.first; + showDataStream(outStream); + if (concatSize != ideaSize) begin + $display("Error: ideaSize=%d, realSize=%d", ideaSize, concatSize); + $finish(); + end + else begin + $display("INFO: verify output ideaSize=%d, realSize=%d, ideaLastSize=%d", ideaSize, concatSize, ideaSize%fromInteger(valueOf(BYTE_EN_WIDTH))); + ideaConcatSizeFifo.deq; + testFinishCntReg <= testFinishCntReg + 1; + end + concatSizeReg <= 0; + end + else begin + concatSizeReg <= concatSize; + end dut.outputStream.deq; endrule + + rule testFinish; + if (testFinishCntReg == fromInteger(valueOf(TEST_NUM)-1)) begin + $finish(); + end + endrule + endmodule \ No newline at end of file From d20503f1790afafaae94b57bbfd0f5f8c1305008 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Fri, 12 Jul 2024 01:02:19 +0800 Subject: [PATCH 14/53] Update StreamUtils --- backend/Makefile | 4 +-- src/StreamUtils.bsv | 53 ++++++++++++++++++++++++++++++++++------ test/TestDmaCore.bsv | 4 +-- test/TestStreamUtils.bsv | 25 +++++++++++++------ 4 files changed, 67 insertions(+), 19 deletions(-) diff --git a/backend/Makefile b/backend/Makefile index 8634dda..01c68f1 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -8,8 +8,8 @@ OUTPUTDIR ?= output LOGFILE ?= run.log RUNTOPHASE ?= place # synth place route all PARTNAME = xcvu13p-fhgb2104-2-i -TARGETFILE ?= ../src/DmaRequestCore.bsv -TOPMODULE ?= mkChunkComputer +TARGETFILE ?= ../src/StreamUtils.bsv +TOPMODULE ?= mkStreamConcat export TOP = $(TOPMODULE) export RTL = $(VLOGDIR) diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv index 9288219..d311101 100755 --- a/src/StreamUtils.bsv +++ b/src/StreamUtils.bsv @@ -1,5 +1,6 @@ import Vector::*; import FIFOF::*; +import GetPut::*; import SemiFifo::*; typedef 8 BYTE_WIDTH; @@ -10,12 +11,15 @@ typedef 2 CONCAT_STREAM_NUM; typedef 512 DATA_WIDTH; typedef TDiv#(DATA_WIDTH, BYTE_WIDTH) BYTE_EN_WIDTH; +typedef 'hFFFFFFFFFFFFFFFF MAX_BYTE_EN; typedef Bit#(DATA_WIDTH) Data; typedef Bit#(BYTE_EN_WIDTH) ByteEn; typedef Bit#(TAdd#(1, TLog#(DATA_WIDTH))) BitPtr; typedef Bit#(TAdd#(1, TLog#(BYTE_EN_WIDTH))) BytePtr; +typedef UInt#(32) StreamSize; + typedef struct { Data data; ByteEn byteEn; @@ -34,6 +38,12 @@ interface StreamConcat; interface FifoOut#(DataStream) outputStream; endinterface +interface StreamSplit; + interface FifoIn#(DataStream) inputStream; + interface Put#(StreamSize) setSplitPtr; + interface FifoOut#(DataStream) outputStream; +endinterface + function BytePtr convertByteEn2BytePtr (ByteEn byteEn); ByteEn byteEnTemp = byteEn; BytePtr ptr = 0; @@ -52,6 +62,21 @@ function Action showDataStream (DataStream stream); endaction; endfunction +function Action checkDataStream (DataStream stream, String name); + if (stream.byteEn == 0 || stream.data == 0) begin + return action + $display("Error: wrong dataStream ", name); + showDataStream(stream); + $finish(); + endaction; + end + else begin + return action + endaction; + end +endfunction + +(* synthesize *) module mkStreamConcat (StreamConcat ifc); FIFOF#(DataStream) inputFifoA <- mkFIFOF; @@ -112,7 +137,7 @@ module mkStreamConcat (StreamConcat ifc); concatStream = DataStream{ data: concatData, byteEn: concatByteEn, - isFirst: streamA.isLast, + isFirst: streamA.isFirst, isLast: isConcatStreamLast }; remainStream = DataStream{ @@ -180,13 +205,6 @@ module mkStreamConcat (StreamConcat ifc); hasRemainReg <= hasRemain; remainStreamReg <= remainStream; remainBytePtrReg <= remainBytePtr; - if (concatStream.byteEn == 0) begin - $display("B + remain", remainBytePtrReg, bytePtrB); - $display("StreamB"); - showDataStream(streamB); - $display("remain"); - showDataStream(remainStreamReg); - end outputFifo.enq(concatStream); prepareFifoB.deq; end @@ -207,4 +225,23 @@ module mkStreamConcat (StreamConcat ifc); interface inputStreamSecond = convertFifoToFifoIn(inputFifoB); interface outputStream = convertFifoToFifoOut(outputFifo); +endmodule + +(* synthesize *) +module mkStreamSplit(StreamSplit ifc); + + Reg#(Maybe#(StreamSize)) splitLocationMaybeReg <- mkReg(Invalid); + + FIFOF#(DataStream) inputFifo <- mkFIFOF; + FIFOF#(DataStream) outputFifo <- mkFIFOF; + + interface Put setSplitPtr; + method Action put(StreamSize splitPtr); + + endmethod + endinterface + + interface inputStream = convertFifoToFifoIn(inputFifo); + interface outputStream = convertFifoToFifoOut(outputFifo); + endmodule \ No newline at end of file diff --git a/test/TestDmaCore.bsv b/test/TestDmaCore.bsv index 582d27f..0a9f7f2 100755 --- a/test/TestDmaCore.bsv +++ b/test/TestDmaCore.bsv @@ -4,9 +4,9 @@ import Randomizable::*; import DmaTypes::*; import DmaRequestCore::*; -typedef 1000 CHUNK_PER_EPOCH_TEST_NUM; +typedef 10 CHUNK_PER_EPOCH_TEST_NUM; typedef 64'hFFFFFFFFFFFFFFFF MAX_ADDRESS; -typedef 32'hFFFFFFFF MAX_TEST_LENGTH; +typedef 16'hFFFF MAX_TEST_LENGTH; typedef 2'b00 DEFAULT_TLP_SIZE_SETTING; typedef 4 CHUNK_TX_TEST_SETTING_NUM; typedef 6 CHUNK_RX_TEST_SETTING_NUM; diff --git a/test/TestStreamUtils.bsv b/test/TestStreamUtils.bsv index ca723be..321ee6f 100755 --- a/test/TestStreamUtils.bsv +++ b/test/TestStreamUtils.bsv @@ -3,9 +3,6 @@ import SemiFifo::*; import Randomizable::*; import StreamUtils::*; -typedef UInt#(32) StreamSize; -typedef 'hFFFFFFFFFFFFFFFF MAX_BYTE_EN; - typedef 'hAB PSEUDO_DATA; typedef 8 PSEUDO_DATA_WIDTH; @@ -19,6 +16,11 @@ typedef 'h1 MIN_STREAM_SIZE; typedef 'hFFFF MAX_STREAM_SIZE; typedef 1000 TEST_NUM; +interface TestStreamConcat; + interface FifoOut#(DataStream) stream4concatFirst; + interface FifoOut#(DataStream) stream4concatSecond; + interface FifoIn#(DataStream) outputStream; +endinterface (* doc = "testcase" *) module mkStreamConcatTb(Empty); @@ -84,12 +86,16 @@ module mkStreamConcatTb(Empty); else if (testRoundReg > 0) begin if (streamARemainSizeReg > 0 && dut.inputStreamFirst.notFull) begin - dut.inputStreamFirst.enq(generatePsuedoStream(streamARemainSizeReg, False, (streamARemainSizeReg <= fromInteger(valueOf(BYTE_EN_WIDTH))))); - streamARemainSizeReg <= (streamARemainSizeReg > fromInteger(valueOf(BYTE_EN_WIDTH))) ? streamARemainSizeReg - fromInteger(valueOf(BYTE_EN_WIDTH)) : 0; + Bool isLast = streamARemainSizeReg <= fromInteger(valueOf(BYTE_EN_WIDTH)); + StreamSize size = isLast ? streamARemainSizeReg : fromInteger(valueOf(BYTE_EN_WIDTH)); + dut.inputStreamFirst.enq(generatePsuedoStream(size, False, isLast)); + streamARemainSizeReg <= streamARemainSizeReg - size; end if (streamBRemainSizeReg > 0 && dut.inputStreamSecond.notFull) begin - dut.inputStreamSecond.enq(generatePsuedoStream(streamBRemainSizeReg, False, (streamARemainSizeReg <= fromInteger(valueOf(BYTE_EN_WIDTH))))); - streamBRemainSizeReg <= (streamBRemainSizeReg > fromInteger(valueOf(BYTE_EN_WIDTH))) ? streamBRemainSizeReg - fromInteger(valueOf(BYTE_EN_WIDTH)) : 0; + Bool isLast = streamBRemainSizeReg <= fromInteger(valueOf(BYTE_EN_WIDTH)); + StreamSize size = isLast ? streamBRemainSizeReg : fromInteger(valueOf(BYTE_EN_WIDTH)); + dut.inputStreamSecond.enq(generatePsuedoStream(size, False, isLast)); + streamBRemainSizeReg <= streamBRemainSizeReg - size; end testRoundReg <= testRoundReg - 1; end @@ -115,6 +121,11 @@ module mkStreamConcatTb(Empty); end else begin concatSizeReg <= concatSize; + if (outStream.data != pseudoData) begin + $display("Error: Wrong data in round %d", testRoundReg); + showDataStream(outStream); + $finish(); + end end dut.outputStream.deq; endrule From 9c0ac450e38e11c1ac779c2865f43c4c21418292 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Fri, 12 Jul 2024 21:29:45 +0800 Subject: [PATCH 15/53] Add StreamSplit --- img/StreamSplit.drawio | 65 ++++++ img/{split.drawio => chunkSplit.drawio} | 0 img/dmac.drawio | 56 +++++ img/{concat.drawio => streamConcat.drawio} | 0 src/StreamUtils.bsv | 255 ++++++++++++++------- test/TestStreamUtils.bsv | 96 +++++--- 6 files changed, 364 insertions(+), 108 deletions(-) create mode 100644 img/StreamSplit.drawio rename img/{split.drawio => chunkSplit.drawio} (100%) create mode 100644 img/dmac.drawio rename img/{concat.drawio => streamConcat.drawio} (100%) diff --git a/img/StreamSplit.drawio b/img/StreamSplit.drawio new file mode 100644 index 0000000..8fe59ab --- /dev/null +++ b/img/StreamSplit.drawio @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/img/split.drawio b/img/chunkSplit.drawio similarity index 100% rename from img/split.drawio rename to img/chunkSplit.drawio diff --git a/img/dmac.drawio b/img/dmac.drawio new file mode 100644 index 0000000..003b8b7 --- /dev/null +++ b/img/dmac.drawio @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/img/concat.drawio b/img/streamConcat.drawio similarity index 100% rename from img/concat.drawio rename to img/streamConcat.drawio diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv index d311101..ff2f719 100755 --- a/src/StreamUtils.bsv +++ b/src/StreamUtils.bsv @@ -33,15 +33,15 @@ typedef struct { } StreamWithPtr deriving(Bits, Bounded, Eq, FShow); interface StreamConcat; - interface FifoIn#(DataStream) inputStreamFirst; - interface FifoIn#(DataStream) inputStreamSecond; - interface FifoOut#(DataStream) outputStream; + interface FifoIn#(DataStream) inputStreamFirstFifoIn; + interface FifoIn#(DataStream) inputStreamSecondFifoIn; + interface FifoOut#(DataStream) outputStreamFifoOut; endinterface interface StreamSplit; - interface FifoIn#(DataStream) inputStream; - interface Put#(StreamSize) setSplitPtr; - interface FifoOut#(DataStream) outputStream; + interface FifoIn#(DataStream) inputStreamFifoIn; + interface FifoIn#(StreamSize) splitLocationFifoIn; + interface FifoOut#(DataStream) outputStreamFifoOut; endinterface function BytePtr convertByteEn2BytePtr (ByteEn byteEn); @@ -54,6 +54,72 @@ function BytePtr convertByteEn2BytePtr (ByteEn byteEn); return ptr; endfunction +function DataStream getEmptyStream (); + return DataStream{ + data: 0, + byteEn: 0, + isFirst: False, + isLast: True + }; +endfunction + +function BitPtr getMaxBitPtr (); + return fromInteger(valueOf(DATA_WIDTH)); +endfunction + +function BytePtr getMaxBytePtr (); + return fromInteger(valueOf(BYTE_EN_WIDTH)); +endfunction + +// Concat two DataStream frames into one +function Tuple3#(DataStream, DataStream, BytePtr) getConcatStream (DataStream streamA, DataStream streamB, BytePtr bytePtrA, BytePtr bytePtrB); + Bool isCallLegally = (streamA.isLast && bytePtrA <= getMaxBytePtr() && bytePtrA > 0); + BitPtr bitPtrA = zeroExtend(bytePtrA) << fromInteger(valueOf(BYTE_WIDTH_WIDTH)); + + // Fill the low PtrA bytes by streamA data + Data concatDataA = streamA.data; + ByteEn concatByteEnA = streamA.byteEn; + + // Fill the high bytes by streamB data + Data concatDataB = streamB.data << bitPtrA; + ByteEn concatByteEnB = streamB.byteEn << bytePtrA; + Data concatData = concatDataA | concatDataB; + ByteEn concatByteEn = concatByteEnA | concatByteEnB; + + // Get the remain bytes of streamB data + BitPtr resBitPtr = getMaxBitPtr() - bitPtrA; + BytePtr resBytePtr = getMaxBytePtr() - bytePtrA; + Data remainData = streamB.data >> resBitPtr; + ByteEn remainByteEn = streamB.byteEn >> resBytePtr; + + // Get if the concat frame is the last + Bool isConcatStreamLast = streamB.isLast; + BytePtr remainBytePtr = 0; + if (resBytePtr < bytePtrB ) begin + isConcatStreamLast = False; + remainBytePtr = bytePtrB - resBytePtr; + end + DataStream concatStream = getEmptyStream; + DataStream remainStream = getEmptyStream; + + // package the return concatStream and remainStream + if(isCallLegally) begin + concatStream = DataStream{ + data: concatData, + byteEn: concatByteEn, + isFirst: streamA.isFirst, + isLast: isConcatStreamLast + }; + remainStream = DataStream{ + data: remainData, + byteEn: remainByteEn, + isFirst: False, + isLast: True + }; + end + return tuple3(concatStream, remainStream, remainBytePtr); +endfunction + function Action showDataStream (DataStream stream); return action $display(" Data = %h", stream.data); @@ -92,64 +158,6 @@ module mkStreamConcat (StreamConcat ifc); Reg#(Bool) hasRemainReg <- mkReg(False); Reg#(DataStream) remainStreamReg <- mkRegU; - DataStream emptyStream = DataStream{ - data: 0, - byteEn: 0, - isFirst: True, - isLast: True - }; - - BytePtr maxBytePtr = fromInteger(valueOf(BYTE_EN_WIDTH)); - BitPtr maxBitPtr = fromInteger(valueOf(DATA_WIDTH)); - - function Tuple3#(DataStream, DataStream, BytePtr) getConcatStream (DataStream streamA, DataStream streamB, BytePtr bytePtrA, BytePtr bytePtrB); - Bool isCallLegally = (streamA.isLast && bytePtrA <= maxBytePtr && bytePtrA > 0); - BitPtr bitPtrA = zeroExtend(bytePtrA) << fromInteger(valueOf(BYTE_WIDTH_WIDTH)); - - // Fill the low PtrA bytes by streamA data - Data concatDataA = streamA.data; - ByteEn concatByteEnA = streamA.byteEn; - - // Fill the high bytes by streamB data - Data concatDataB = streamB.data << bitPtrA; - ByteEn concatByteEnB = streamB.byteEn << bytePtrA; - Data concatData = concatDataA | concatDataB; - ByteEn concatByteEn = concatByteEnA | concatByteEnB; - - // Get the remain bytes of streamB data - BitPtr resBitPtr = maxBitPtr - bitPtrA; - BytePtr resBytePtr = maxBytePtr - bytePtrA; - Data remainData = streamB.data >> resBitPtr; - ByteEn remainByteEn = streamB.byteEn >> resBytePtr; - - // Get if the concat frame is the last - Bool isConcatStreamLast = streamB.isLast; - BytePtr remainBytePtr = 0; - if (resBytePtr < bytePtrB ) begin - isConcatStreamLast = False; - remainBytePtr = bytePtrB - resBytePtr; - end - DataStream concatStream = emptyStream; - DataStream remainStream = emptyStream; - - // package the return concatStream and remainStream - if(isCallLegally) begin - concatStream = DataStream{ - data: concatData, - byteEn: concatByteEn, - isFirst: streamA.isFirst, - isLast: isConcatStreamLast - }; - remainStream = DataStream{ - data: remainData, - byteEn: remainByteEn, - isFirst: False, - isLast: True - }; - end - return tuple3(concatStream, remainStream, remainBytePtr); - endfunction - rule prepareStreamA; let streamA = inputFifoA.first; inputFifoA.deq; @@ -185,8 +193,7 @@ module mkStreamConcat (StreamConcat ifc); // the last StreamA + the first StreamB else if (streamA.isLast && streamB.isFirst) begin match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(streamA, streamB, bytePtrA, bytePtrB); - Bool hasRemain = unpack(remainStream.byteEn[0]); - hasRemainReg <= hasRemain; + hasRemainReg <= unpack(remainStream.byteEn[0]); remainStreamReg <= remainStream; remainBytePtrReg <= remainBytePtr; outputFifo.enq(concatStream); @@ -201,8 +208,7 @@ module mkStreamConcat (StreamConcat ifc); let bytePtrB = prepareFifoB.first.bytePtr; if (!streamB.isFirst) begin match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(remainStreamReg, streamB, remainBytePtrReg, bytePtrB); - Bool hasRemain = unpack(remainStream.byteEn[0]); - hasRemainReg <= hasRemain; + hasRemainReg <= unpack(remainStream.byteEn[0]); remainStreamReg <= remainStream; remainBytePtrReg <= remainBytePtr; outputFifo.enq(concatStream); @@ -221,27 +227,118 @@ module mkStreamConcat (StreamConcat ifc); end endrule - interface inputStreamFirst = convertFifoToFifoIn(inputFifoA); - interface inputStreamSecond = convertFifoToFifoIn(inputFifoB); - interface outputStream = convertFifoToFifoOut(outputFifo); + interface inputStreamFirstFifoIn = convertFifoToFifoIn(inputFifoA); + interface inputStreamSecondFifoIn = convertFifoToFifoIn(inputFifoB); + interface outputStreamFifoOut = convertFifoToFifoOut(outputFifo); endmodule (* synthesize *) module mkStreamSplit(StreamSplit ifc); - Reg#(Maybe#(StreamSize)) splitLocationMaybeReg <- mkReg(Invalid); - + Reg#(StreamSize) streamByteCntReg <- mkReg(0); + FIFOF#(StreamSize) splitLocationFifo <- mkFIFOF; FIFOF#(DataStream) inputFifo <- mkFIFOF; FIFOF#(DataStream) outputFifo <- mkFIFOF; + FIFOF#(StreamWithPtr) prepareFifo <- mkFIFOF; + FIFOF#(StreamWithPtr) assertFifo <- mkFIFOF; + FIFOF#(Tuple2#(BytePtr,BytePtr)) splitPtrFifo <- mkFIFOF; + + Reg#(DataStream) remainStreamReg <- mkRegU; + Reg#(Bool) hasRemainReg <- mkReg(False); + Reg#(Bool) isSplitted <- mkReg(False); + Reg#(BytePtr) remainBytePtrReg <- mkReg(0); + + rule prepareStream; + let stream = inputFifo.first; + inputFifo.deq; + StreamWithPtr streamWithPtr = StreamWithPtr{ + stream: stream, + bytePtr: convertByteEn2BytePtr(stream.byteEn) + }; + prepareFifo.enq(streamWithPtr); + endrule + + rule assertSplitStream; + let stream = prepareFifo.first.stream; + let bytePtr = prepareFifo.first.bytePtr; + let splitLocation = splitLocationFifo.first; + BytePtr truncateBytePtr = 0; + if (!isSplitted && unpack(zeroExtend(bytePtr)) + streamByteCntReg >= splitLocation) begin + truncateBytePtr = truncate(pack(splitLocation - streamByteCntReg)); + end + BytePtr resBytePtr = getMaxBytePtr() - truncateBytePtr; + splitPtrFifo.enq(tuple2(truncateBytePtr, resBytePtr)); + if (truncateBytePtr > 0 && !stream.isLast) begin + isSplitted <= True; + end + else begin + isSplitted <= False; + end + assertFifo.enq(prepareFifo.first); + prepareFifo.deq; + if (stream.isLast) begin + splitLocationFifo.deq; + end + endrule - interface Put setSplitPtr; - method Action put(StreamSize splitPtr); - endmethod - endinterface + rule execSplitStream; + if (assertFifo.notEmpty && splitPtrFifo.notEmpty) begin + let stream = assertFifo.first.stream; + let frameBytePtr = assertFifo.first.bytePtr; + assertFifo.deq; + match {.truncateBytePtr, .resBytePtr} = splitPtrFifo.first; + splitPtrFifo.deq; + + // no operatation + if (!hasRemainReg && truncateBytePtr == 0) begin + outputFifo.enq(stream); + end + + // split the frame in this cycle to a last frame and a remain frame + else if (!hasRemainReg && truncateBytePtr > 0) begin + BitPtr truncateBitPtr = zeroExtend(truncateBytePtr) << valueOf(BYTE_WIDTH_WIDTH); + BitPtr resBitPtr = zeroExtend(resBytePtr) << valueOf(BYTE_WIDTH_WIDTH); + outputFifo.enq(DataStream{ + data: (stream.data << resBitPtr) >> resBitPtr, + byteEn: (stream.byteEn << resBytePtr) >> resBytePtr, + isFirst: stream.isFirst, + isLast: True + }); + DataStream remainStream = DataStream{ + data: stream.data >> truncateBitPtr, + byteEn: stream.byteEn >> truncateBytePtr, + isFirst: True, + isLast: True + }; + hasRemainReg <= (remainStream.byteEn != 0); + remainBytePtrReg <= frameBytePtr - truncateBytePtr; + remainStreamReg <= remainStream; + end + + // concat the new frame with the remainReg + else if (hasRemainReg && !stream.isFirst) begin + match {.concatStream, .remainStream, .remainBytePtr} = getConcatStream(stream, remainStreamReg, frameBytePtr, remainBytePtrReg); + hasRemainReg <= unpack(remainStream.byteEn[0]); + remainStreamReg <= remainStream; + remainBytePtrReg <= remainBytePtr; + end + + else if (hasRemainReg) begin + outputFifo.enq(remainStreamReg); + hasRemainReg <= False; + end + + end + else if (hasRemainReg) begin + outputFifo.enq(remainStreamReg); + hasRemainReg <= False; + end + endrule - interface inputStream = convertFifoToFifoIn(inputFifo); - interface outputStream = convertFifoToFifoOut(outputFifo); + interface inputStreamFifoIn = convertFifoToFifoIn(inputFifo); + interface splitLocationFifoIn = convertFifoToFifoIn(splitLocationFifo); + interface outputStreamFifoOut = convertFifoToFifoOut(outputFifo); endmodule \ No newline at end of file diff --git a/test/TestStreamUtils.bsv b/test/TestStreamUtils.bsv index 321ee6f..7b917b3 100755 --- a/test/TestStreamUtils.bsv +++ b/test/TestStreamUtils.bsv @@ -16,11 +16,30 @@ typedef 'h1 MIN_STREAM_SIZE; typedef 'hFFFF MAX_STREAM_SIZE; typedef 1000 TEST_NUM; -interface TestStreamConcat; - interface FifoOut#(DataStream) stream4concatFirst; - interface FifoOut#(DataStream) stream4concatSecond; - interface FifoIn#(DataStream) outputStream; -endinterface +function Data getPseudoData(); + Data pseudoData = fromInteger(valueOf(PSEUDO_DATA)); + for (Integer idx = 0; idx < valueOf(TDiv#(DATA_WIDTH, PSEUDO_DATA_WIDTH)); idx = idx + 1) begin + pseudoData = pseudoData | (pseudoData << idx*valueOf(PSEUDO_DATA_WIDTH)); + end + return pseudoData; +endfunction + + +function DataStream generatePsuedoStream (StreamSize size, Bool isFirst, Bool isLast); + let pseudoData = getPseudoData(); + let offsetPtr = (unpack(zeroExtend(getMaxBytePtr())) - size) << valueOf(BYTE_WIDTH_WIDTH); + Data streamData = (pseudoData << offsetPtr) >> offsetPtr; + return DataStream{ + data: streamData, + byteEn: (1 << size) - 1, + isFirst: isFirst, + isLast: isLast + }; +endfunction + +function StreamSize getMaxFrameSize (); + return fromInteger(valueOf(BYTE_EN_WIDTH)); +endfunction (* doc = "testcase" *) module mkStreamConcatTb(Empty); @@ -41,21 +60,7 @@ module mkStreamConcatTb(Empty); Reg#(UInt#(32)) testRoundReg <- mkReg(0); Reg#(UInt#(32)) testFinishCntReg <- mkReg(0); - Data pseudoData = fromInteger(valueOf(PSEUDO_DATA)); - for (Integer idx = 0; idx < valueOf(TDiv#(DATA_WIDTH, PSEUDO_DATA_WIDTH)); idx = idx + 1) begin - pseudoData = pseudoData | (pseudoData << idx*valueOf(PSEUDO_DATA_WIDTH)); - end - function DataStream generatePsuedoStream (StreamSize size, Bool isFirst, Bool isLast); - let offsetPtr = (fromInteger(valueOf(BYTE_EN_WIDTH)) - size) << valueOf(BYTE_WIDTH_WIDTH); - Data streamData = (pseudoData << offsetPtr) >> offsetPtr; - return DataStream{ - data: streamData, - byteEn: (1 << size) - 1, - isFirst: isFirst, - isLast: isLast - }; - endfunction rule testInit if (!isInitReg); $display("INFO: ================start StreamConcatTb!=================="); @@ -67,7 +72,7 @@ module mkStreamConcatTb(Empty); rule testInput if (isInitReg && testCntReg < fromInteger(valueOf(TEST_NUM))); - if (testRoundReg == 0 && dut.inputStreamFirst.notFull && dut.inputStreamSecond.notFull) begin + if (testRoundReg == 0 && dut.inputStreamFirstFifoIn.notFull && dut.inputStreamSecondFifoIn.notFull) begin StreamSize sizeA <- streamASizeRandomValue.next; StreamSize sizeB <- streamASizeRandomValue.next; ideaConcatSizeFifo.enq(sizeA + sizeB); @@ -75,8 +80,8 @@ module mkStreamConcatTb(Empty); let isLast = sizeA <= fromInteger(valueOf(BYTE_EN_WIDTH)); let firstSizeA = isLast ? sizeA : fromInteger(valueOf(BYTE_EN_WIDTH)); let firstSizeB = isLast ? sizeB : fromInteger(valueOf(BYTE_EN_WIDTH)); - dut.inputStreamFirst.enq(generatePsuedoStream(firstSizeA, True, isLast)); - dut.inputStreamSecond.enq(generatePsuedoStream(firstSizeB, True, isLast)); + dut.inputStreamFirstFifoIn.enq(generatePsuedoStream(firstSizeA, True, isLast)); + dut.inputStreamSecondFifoIn.enq(generatePsuedoStream(firstSizeB, True, isLast)); streamARemainSizeReg <= sizeA - firstSizeA; streamBRemainSizeReg <= sizeB - firstSizeB; testCntReg <= testCntReg + 1; @@ -85,16 +90,16 @@ module mkStreamConcatTb(Empty); end else if (testRoundReg > 0) begin - if (streamARemainSizeReg > 0 && dut.inputStreamFirst.notFull) begin + if (streamARemainSizeReg > 0 && dut.inputStreamFirstFifoIn.notFull) begin Bool isLast = streamARemainSizeReg <= fromInteger(valueOf(BYTE_EN_WIDTH)); StreamSize size = isLast ? streamARemainSizeReg : fromInteger(valueOf(BYTE_EN_WIDTH)); - dut.inputStreamFirst.enq(generatePsuedoStream(size, False, isLast)); + dut.inputStreamFirstFifoIn.enq(generatePsuedoStream(size, False, isLast)); streamARemainSizeReg <= streamARemainSizeReg - size; end - if (streamBRemainSizeReg > 0 && dut.inputStreamSecond.notFull) begin + if (streamBRemainSizeReg > 0 && dut.inputStreamSecondFifoIn.notFull) begin Bool isLast = streamBRemainSizeReg <= fromInteger(valueOf(BYTE_EN_WIDTH)); StreamSize size = isLast ? streamBRemainSizeReg : fromInteger(valueOf(BYTE_EN_WIDTH)); - dut.inputStreamSecond.enq(generatePsuedoStream(size, False, isLast)); + dut.inputStreamSecondFifoIn.enq(generatePsuedoStream(size, False, isLast)); streamBRemainSizeReg <= streamBRemainSizeReg - size; end testRoundReg <= testRoundReg - 1; @@ -103,7 +108,7 @@ module mkStreamConcatTb(Empty); endrule rule testOutput; - let outStream = dut.outputStream.first; + let outStream = dut.outputStreamFifoOut.first; StreamSize concatSize = concatSizeReg + unpack(zeroExtend(convertByteEn2BytePtr(outStream.byteEn))); if (outStream.isLast) begin let ideaSize = ideaConcatSizeFifo.first; @@ -121,13 +126,13 @@ module mkStreamConcatTb(Empty); end else begin concatSizeReg <= concatSize; - if (outStream.data != pseudoData) begin + if (outStream.data != getPseudoData()) begin $display("Error: Wrong data in round %d", testRoundReg); showDataStream(outStream); $finish(); end end - dut.outputStream.deq; + dut.outputStreamFifoOut.deq; endrule rule testFinish; @@ -136,4 +141,37 @@ module mkStreamConcatTb(Empty); end endrule +endmodule + + +module mkStreamSplitTb(Empty); + + StreamSplit dut <- mkStreamSplit; + Randomize#(StreamSize) streamSizeRandomValue <- mkConstrainedRandomizer(fromInteger(valueOf(MIN_STREAM_SIZE)), fromInteger(valueOf(MAX_STREAM_SIZE))); + Reg#(Bool) isInitReg <- mkReg(False); + Reg#(UInt#(32)) testCntReg <- mkReg(0); + Reg#(StreamSize) streamSizeReg <- mkReg(0); + Reg#(StreamSize) streamSize2PutReg <- mkReg(0); + Reg#(UInt#(32)) testRoundReg <- mkReg(0); + + rule testInit if (!isInitReg); + isInitReg <= True; + streamSizeRandomValue.cntrl.init; + endrule + + rule testInput if (isInitReg); + if (testRoundReg == 0) begin + let size <- streamSizeRandomValue.next; + if (size <= getMaxFrameSize()) begin + let stream = generatePsuedoStream(size, True, True); + dut.inputStreamFifoIn.enq(stream); + streamSizeReg <= size; + end + end + endrule + + rule testOutput if (isInitReg); + + endrule + endmodule \ No newline at end of file From 4f9221255d78b9a41201cff14105a2f9ac1132b5 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Sat, 13 Jul 2024 22:48:05 +0800 Subject: [PATCH 16/53] Test StreamUtils Pass --- src/StreamUtils.bsv | 167 ++++++++++++++++++++---------------- test/TestStreamUtils.bsv | 180 ++++++++++++++++++++++++++++++--------- 2 files changed, 233 insertions(+), 114 deletions(-) diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv index ff2f719..78034bc 100755 --- a/src/StreamUtils.bsv +++ b/src/StreamUtils.bsv @@ -15,10 +15,12 @@ typedef 'hFFFFFFFFFFFFFFFF MAX_BYTE_EN; typedef Bit#(DATA_WIDTH) Data; typedef Bit#(BYTE_EN_WIDTH) ByteEn; -typedef Bit#(TAdd#(1, TLog#(DATA_WIDTH))) BitPtr; -typedef Bit#(TAdd#(1, TLog#(BYTE_EN_WIDTH))) BytePtr; +typedef Bit#(TAdd#(1, TLog#(DATA_WIDTH))) DataBitPtr; +typedef Bit#(TAdd#(1, TLog#(BYTE_EN_WIDTH))) DataBytePtr; -typedef UInt#(32) StreamSize; +typedef 32 STREAM_SIZE_WIDTH; +typedef UInt#(STREAM_SIZE_WIDTH) StreamSize; +typedef Bit#(TAdd#(1, TLog#(STREAM_SIZE_WIDTH))) StreamSizeBitPtr; typedef struct { Data data; @@ -29,7 +31,7 @@ typedef struct { typedef struct { DataStream stream; - BytePtr bytePtr; + DataBytePtr bytePtr; } StreamWithPtr deriving(Bits, Bounded, Eq, FShow); interface StreamConcat; @@ -44,9 +46,9 @@ interface StreamSplit; interface FifoOut#(DataStream) outputStreamFifoOut; endinterface -function BytePtr convertByteEn2BytePtr (ByteEn byteEn); +function DataBytePtr convertByteEn2BytePtr (ByteEn byteEn); ByteEn byteEnTemp = byteEn; - BytePtr ptr = 0; + DataBytePtr ptr = 0; while (byteEnTemp > 0) begin byteEnTemp = byteEnTemp >> 1; ptr = ptr + 1; @@ -63,18 +65,18 @@ function DataStream getEmptyStream (); }; endfunction -function BitPtr getMaxBitPtr (); +function DataBitPtr getMaxBitPtr (); return fromInteger(valueOf(DATA_WIDTH)); endfunction -function BytePtr getMaxBytePtr (); +function DataBytePtr getMaxBytePtr (); return fromInteger(valueOf(BYTE_EN_WIDTH)); endfunction -// Concat two DataStream frames into one -function Tuple3#(DataStream, DataStream, BytePtr) getConcatStream (DataStream streamA, DataStream streamB, BytePtr bytePtrA, BytePtr bytePtrB); +// Concat two DataStream frames into one. StreamA.isLast must be True, otherwise the function will return a empty frame to end the stream. +function Tuple3#(DataStream, DataStream, DataBytePtr) getConcatStream (DataStream streamA, DataStream streamB, DataBytePtr bytePtrA, DataBytePtr bytePtrB); Bool isCallLegally = (streamA.isLast && bytePtrA <= getMaxBytePtr() && bytePtrA > 0); - BitPtr bitPtrA = zeroExtend(bytePtrA) << fromInteger(valueOf(BYTE_WIDTH_WIDTH)); + DataBitPtr bitPtrA = zeroExtend(bytePtrA) << fromInteger(valueOf(BYTE_WIDTH_WIDTH)); // Fill the low PtrA bytes by streamA data Data concatDataA = streamA.data; @@ -87,14 +89,14 @@ function Tuple3#(DataStream, DataStream, BytePtr) getConcatStream (DataStream st ByteEn concatByteEn = concatByteEnA | concatByteEnB; // Get the remain bytes of streamB data - BitPtr resBitPtr = getMaxBitPtr() - bitPtrA; - BytePtr resBytePtr = getMaxBytePtr() - bytePtrA; + DataBitPtr resBitPtr = getMaxBitPtr() - bitPtrA; + DataBytePtr resBytePtr = getMaxBytePtr() - bytePtrA; Data remainData = streamB.data >> resBitPtr; ByteEn remainByteEn = streamB.byteEn >> resBytePtr; // Get if the concat frame is the last Bool isConcatStreamLast = streamB.isLast; - BytePtr remainBytePtr = 0; + DataBytePtr remainBytePtr = 0; if (resBytePtr < bytePtrB ) begin isConcatStreamLast = False; remainBytePtr = bytePtrB - resBytePtr; @@ -131,7 +133,7 @@ endfunction function Action checkDataStream (DataStream stream, String name); if (stream.byteEn == 0 || stream.data == 0) begin return action - $display("Error: wrong dataStream ", name); + $display("Error: empty dataStream ", name); showDataStream(stream); $finish(); endaction; @@ -152,16 +154,21 @@ module mkStreamConcat (StreamConcat ifc); FIFOF#(StreamWithPtr) prepareFifoA <- mkFIFOF; FIFOF#(StreamWithPtr) prepareFifoB <- mkFIFOF; - Reg#(BytePtr) bytePtrRegA <- mkReg(0); - Reg#(BytePtr) bytePtrRegB <- mkReg(0); - Reg#(BytePtr) remainBytePtrReg <- mkReg(0); + Reg#(DataBytePtr) bytePtrRegA <- mkReg(0); + Reg#(DataBytePtr) bytePtrRegB <- mkReg(0); + Reg#(DataBytePtr) remainBytePtrReg <- mkReg(0); + Reg#(Bool) hasRemainReg <- mkReg(False); + Reg#(Bool) hasLastRemainReg <- mkReg(False); + Reg#(Bool) isStreamAEnd <- mkReg(False); + Reg#(DataStream) remainStreamReg <- mkRegU; + rule prepareStreamA; let streamA = inputFifoA.first; inputFifoA.deq; - BytePtr bytePtr = convertByteEn2BytePtr(streamA.byteEn); + DataBytePtr bytePtr = convertByteEn2BytePtr(streamA.byteEn); prepareFifoA.enq(StreamWithPtr { stream: streamA, bytePtr: bytePtr @@ -171,7 +178,7 @@ module mkStreamConcat (StreamConcat ifc); rule prepareStreamB; let streamB = inputFifoB.first; inputFifoB.deq; - BytePtr bytePtr = convertByteEn2BytePtr(streamB.byteEn); + DataBytePtr bytePtr = convertByteEn2BytePtr(streamB.byteEn); prepareFifoB.enq(StreamWithPtr { stream: streamB, bytePtr: bytePtr @@ -179,52 +186,58 @@ module mkStreamConcat (StreamConcat ifc); endrule rule concatStream; + // Only the remain data + if (hasRemainReg && hasLastRemainReg) begin + outputFifo.enq(remainStreamReg); + hasRemainReg <= False; + isStreamAEnd <= False; + end + + // StreamB or streamB + the remain data + else if (prepareFifoB.notEmpty && isStreamAEnd) begin + let streamB = prepareFifoB.first.stream; + let bytePtrB = prepareFifoB.first.bytePtr; + prepareFifoB.deq; + streamB.isFirst = False; + if (hasRemainReg) begin + match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(remainStreamReg, streamB, remainBytePtrReg, bytePtrB); + hasRemainReg <= unpack(remainStream.byteEn[0]); + hasLastRemainReg <= streamB.isLast; + remainStreamReg <= remainStream; + remainBytePtrReg <= remainBytePtr; + outputFifo.enq(concatStream); + end + else begin + outputFifo.enq(streamB); + end + isStreamAEnd <= !streamB.isLast; + end + // StreamA or StreamA + first StreamB - if (prepareFifoA.notEmpty && prepareFifoB.notEmpty && !hasRemainReg) begin + else if (prepareFifoA.notEmpty) begin let streamA = prepareFifoA.first.stream; - let streamB = prepareFifoB.first.stream; let bytePtrA = prepareFifoA.first.bytePtr; - let bytePtrB = prepareFifoB.first.bytePtr; // Only StreamA frame - if (!streamA.isLast && streamB.isFirst) begin + if (!streamA.isLast) begin outputFifo.enq(streamA); prepareFifoA.deq; + isStreamAEnd <= False; end // the last StreamA + the first StreamB - else if (streamA.isLast && streamB.isFirst) begin + else if (streamA.isLast && prepareFifoB.notEmpty) begin + let streamB = prepareFifoB.first.stream; + let bytePtrB = prepareFifoB.first.bytePtr; match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(streamA, streamB, bytePtrA, bytePtrB); hasRemainReg <= unpack(remainStream.byteEn[0]); + hasLastRemainReg <= streamB.isLast; remainStreamReg <= remainStream; remainBytePtrReg <= remainBytePtr; + isStreamAEnd <= !streamB.isLast; outputFifo.enq(concatStream); prepareFifoA.deq; prepareFifoB.deq; end end - - // streamB + the remain data - else if (prepareFifoB.notEmpty && hasRemainReg) begin - let streamB = prepareFifoB.first.stream; - let bytePtrB = prepareFifoB.first.bytePtr; - if (!streamB.isFirst) begin - match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(remainStreamReg, streamB, remainBytePtrReg, bytePtrB); - hasRemainReg <= unpack(remainStream.byteEn[0]); - remainStreamReg <= remainStream; - remainBytePtrReg <= remainBytePtr; - outputFifo.enq(concatStream); - prepareFifoB.deq; - end - else begin - outputFifo.enq(remainStreamReg); - hasRemainReg <= False; - end - end - - // Only the remain data - else if (hasRemainReg) begin - outputFifo.enq(remainStreamReg); - hasRemainReg <= False; - end endrule interface inputStreamFirstFifoIn = convertFifoToFifoIn(inputFifoA); @@ -237,18 +250,21 @@ endmodule module mkStreamSplit(StreamSplit ifc); Reg#(StreamSize) streamByteCntReg <- mkReg(0); + FIFOF#(StreamSize) splitLocationFifo <- mkFIFOF; FIFOF#(DataStream) inputFifo <- mkFIFOF; FIFOF#(DataStream) outputFifo <- mkFIFOF; FIFOF#(StreamWithPtr) prepareFifo <- mkFIFOF; FIFOF#(StreamWithPtr) assertFifo <- mkFIFOF; - FIFOF#(Tuple2#(BytePtr,BytePtr)) splitPtrFifo <- mkFIFOF; + FIFOF#(Tuple2#(DataBytePtr,DataBytePtr)) splitPtrFifo <- mkFIFOF; Reg#(DataStream) remainStreamReg <- mkRegU; Reg#(Bool) hasRemainReg <- mkReg(False); - Reg#(Bool) isSplitted <- mkReg(False); - Reg#(BytePtr) remainBytePtrReg <- mkReg(0); + Reg#(Bool) hasLastRemainReg <- mkReg(False); + Reg#(DataBytePtr) remainBytePtrReg <- mkReg(0); + Reg#(Bool) isSplitted <- mkReg(False); + rule prepareStream; let stream = inputFifo.first; inputFifo.deq; @@ -263,18 +279,20 @@ module mkStreamSplit(StreamSplit ifc); let stream = prepareFifo.first.stream; let bytePtr = prepareFifo.first.bytePtr; let splitLocation = splitLocationFifo.first; - BytePtr truncateBytePtr = 0; + DataBytePtr truncateBytePtr = 0; if (!isSplitted && unpack(zeroExtend(bytePtr)) + streamByteCntReg >= splitLocation) begin truncateBytePtr = truncate(pack(splitLocation - streamByteCntReg)); end - BytePtr resBytePtr = getMaxBytePtr() - truncateBytePtr; + DataBytePtr resBytePtr = getMaxBytePtr() - truncateBytePtr; splitPtrFifo.enq(tuple2(truncateBytePtr, resBytePtr)); if (truncateBytePtr > 0 && !stream.isLast) begin isSplitted <= True; end - else begin + else if (stream.isLast) begin isSplitted <= False; end + streamByteCntReg <= stream.isLast ? 0 : streamByteCntReg + unpack(zeroExtend(bytePtr)); + assertFifo.enq(prepareFifo.first); prepareFifo.deq; if (stream.isLast) begin @@ -284,11 +302,21 @@ module mkStreamSplit(StreamSplit ifc); rule execSplitStream; - if (assertFifo.notEmpty && splitPtrFifo.notEmpty) begin + // Only output remainStreamReg + if (hasRemainReg && hasLastRemainReg) begin + if (remainStreamReg.byteEn == 0) begin + showDataStream(remainStreamReg); + end + outputFifo.enq(remainStreamReg); + hasRemainReg <= False; + hasLastRemainReg <= False; + end + + else if (assertFifo.notEmpty && splitPtrFifo.notEmpty) begin let stream = assertFifo.first.stream; let frameBytePtr = assertFifo.first.bytePtr; - assertFifo.deq; match {.truncateBytePtr, .resBytePtr} = splitPtrFifo.first; + assertFifo.deq; splitPtrFifo.deq; // no operatation @@ -296,10 +324,10 @@ module mkStreamSplit(StreamSplit ifc); outputFifo.enq(stream); end - // split the frame in this cycle to a last frame and a remain frame + // split the frame in this cycle to a last frame and a remain frame else if (!hasRemainReg && truncateBytePtr > 0) begin - BitPtr truncateBitPtr = zeroExtend(truncateBytePtr) << valueOf(BYTE_WIDTH_WIDTH); - BitPtr resBitPtr = zeroExtend(resBytePtr) << valueOf(BYTE_WIDTH_WIDTH); + DataBitPtr truncateBitPtr = zeroExtend(truncateBytePtr) << valueOf(BYTE_WIDTH_WIDTH); + DataBitPtr resBitPtr = zeroExtend(resBytePtr) << valueOf(BYTE_WIDTH_WIDTH); outputFifo.enq(DataStream{ data: (stream.data << resBitPtr) >> resBitPtr, byteEn: (stream.byteEn << resBytePtr) >> resBytePtr, @@ -313,27 +341,22 @@ module mkStreamSplit(StreamSplit ifc); isLast: True }; hasRemainReg <= (remainStream.byteEn != 0); + hasLastRemainReg <= stream.isLast; remainBytePtrReg <= frameBytePtr - truncateBytePtr; remainStreamReg <= remainStream; end // concat the new frame with the remainReg - else if (hasRemainReg && !stream.isFirst) begin - match {.concatStream, .remainStream, .remainBytePtr} = getConcatStream(stream, remainStreamReg, frameBytePtr, remainBytePtrReg); + else if (hasRemainReg) begin + match {.concatStream, .remainStream, .remainBytePtr} = getConcatStream(remainStreamReg, stream, remainBytePtrReg, frameBytePtr); + checkDataStream(concatStream, "concat remain"); + outputFifo.enq(concatStream); hasRemainReg <= unpack(remainStream.byteEn[0]); + hasLastRemainReg <= stream.isLast; remainStreamReg <= remainStream; remainBytePtrReg <= remainBytePtr; + end - - else if (hasRemainReg) begin - outputFifo.enq(remainStreamReg); - hasRemainReg <= False; - end - - end - else if (hasRemainReg) begin - outputFifo.enq(remainStreamReg); - hasRemainReg <= False; end endrule diff --git a/test/TestStreamUtils.bsv b/test/TestStreamUtils.bsv index 7b917b3..a78bc3e 100755 --- a/test/TestStreamUtils.bsv +++ b/test/TestStreamUtils.bsv @@ -1,20 +1,31 @@ import FIFOF::*; import SemiFifo::*; -import Randomizable::*; +import LFSR::*; import StreamUtils::*; typedef 'hAB PSEUDO_DATA; typedef 8 PSEUDO_DATA_WIDTH; -typedef 'h1 MIN_STREAM_SIZE; +typedef 10 TEST_IDEAL_FIFO_DEPTH; + +typedef 'h12345678 SEED_1; +typedef 'hABCDEF01 SEED_2; // TEST HYPER PARAMETERS CASE 1 -// typedef 100 MAX_STREAM_SIZE; +// typedef 3 MAX_STREAM_SIZE_PTR; // typedef 10 TEST_NUM; // TEST HYPER PARAMETERS CASE 2 -typedef 'hFFFF MAX_STREAM_SIZE; -typedef 1000 TEST_NUM; +typedef 16 MAX_STREAM_SIZE_PTR; +typedef 10000 TEST_NUM; + +typedef enum { + WAITING, FirstChunk, SecondChunk +} StreamSplitOutStatus deriving(Bits, Eq); + +interface RandomStreamSize; + method ActionValue#(StreamSize) next(); +endinterface function Data getPseudoData(); Data pseudoData = fromInteger(valueOf(PSEUDO_DATA)); @@ -24,7 +35,6 @@ function Data getPseudoData(); return pseudoData; endfunction - function DataStream generatePsuedoStream (StreamSize size, Bool isFirst, Bool isLast); let pseudoData = getPseudoData(); let offsetPtr = (unpack(zeroExtend(getMaxBytePtr())) - size) << valueOf(BYTE_WIDTH_WIDTH); @@ -41,84 +51,104 @@ function StreamSize getMaxFrameSize (); return fromInteger(valueOf(BYTE_EN_WIDTH)); endfunction +module mkRandomStreamSize(StreamSize seed, StreamSizeBitPtr maxSizeBitPtr, RandomStreamSize ifc); + LFSR#(Bit#(STREAM_SIZE_WIDTH)) lfsr <- mkLFSR_32 ; + FIFOF#(StreamSize) outputFifo <- mkFIFOF ; + Reg#(Bool) isInitReg <- mkReg(False) ; + + rule run if (isInitReg); + let value = lfsr.value >> (fromInteger(valueOf(STREAM_SIZE_WIDTH)) - maxSizeBitPtr); + if (value > 0) begin + outputFifo.enq(unpack(value)); + end + lfsr.next; + endrule + + rule init if (!isInitReg); + isInitReg <= True; + lfsr.seed(pack(seed)); + endrule + + method ActionValue#(StreamSize) next(); + outputFifo.deq; + return outputFifo.first; + endmethod +endmodule + (* doc = "testcase" *) module mkStreamConcatTb(Empty); StreamConcat dut <- mkStreamConcat; - Randomize#(StreamSize) streamASizeRandomValue <- mkConstrainedRandomizer(fromInteger(valueOf(MIN_STREAM_SIZE)), fromInteger(valueOf(MAX_STREAM_SIZE))); - Randomize#(StreamSize) streamBSizeRandomValue <- mkConstrainedRandomizer(fromInteger(valueOf(MIN_STREAM_SIZE)), fromInteger(valueOf(MAX_STREAM_SIZE))); + RandomStreamSize streamASizeRandomValue <- mkRandomStreamSize(fromInteger(valueOf(SEED_1)), fromInteger(valueOf(MAX_STREAM_SIZE_PTR))); + RandomStreamSize streamBSizeRandomValue <- mkRandomStreamSize(fromInteger(valueOf(SEED_2)), fromInteger(valueOf(MAX_STREAM_SIZE_PTR))); Reg#(StreamSize) streamARemainSizeReg <- mkReg(0); Reg#(StreamSize) streamBRemainSizeReg <- mkReg(0); Reg#(StreamSize) concatSizeReg <- mkReg(0); - FIFOF#(StreamSize) ideaConcatSizeFifo <- mkSizedFIFOF(10); + FIFOF#(StreamSize) ideaConcatSizeFifo <- mkSizedFIFOF(valueOf(TEST_IDEAL_FIFO_DEPTH)); Reg#(Bool) isInitReg <- mkReg(False); Reg#(UInt#(32)) testCntReg <- mkReg(0); Reg#(UInt#(32)) testRoundReg <- mkReg(0); Reg#(UInt#(32)) testFinishCntReg <- mkReg(0); - - rule testInit if (!isInitReg); $display("INFO: ================start StreamConcatTb!=================="); - $display(valueOf(BYTE_WIDTH_WIDTH)); - streamASizeRandomValue.cntrl.init; - streamBSizeRandomValue.cntrl.init; isInitReg <= True; endrule rule testInput if (isInitReg && testCntReg < fromInteger(valueOf(TEST_NUM))); - if (testRoundReg == 0 && dut.inputStreamFirstFifoIn.notFull && dut.inputStreamSecondFifoIn.notFull) begin StreamSize sizeA <- streamASizeRandomValue.next; - StreamSize sizeB <- streamASizeRandomValue.next; + StreamSize sizeB <- streamBSizeRandomValue.next; ideaConcatSizeFifo.enq(sizeA + sizeB); - testRoundReg <= (sizeA + sizeB) / fromInteger(valueOf(BYTE_EN_WIDTH)); - let isLast = sizeA <= fromInteger(valueOf(BYTE_EN_WIDTH)); - let firstSizeA = isLast ? sizeA : fromInteger(valueOf(BYTE_EN_WIDTH)); - let firstSizeB = isLast ? sizeB : fromInteger(valueOf(BYTE_EN_WIDTH)); - dut.inputStreamFirstFifoIn.enq(generatePsuedoStream(firstSizeA, True, isLast)); - dut.inputStreamSecondFifoIn.enq(generatePsuedoStream(firstSizeB, True, isLast)); + testRoundReg <= (sizeA + sizeB) / getMaxFrameSize(); + + let isLastA = (sizeA <= getMaxFrameSize()); + let isLastB = (sizeB <= getMaxFrameSize()); + let firstSizeA = isLastA ? sizeA : getMaxFrameSize(); + let firstSizeB = isLastB ? sizeB : getMaxFrameSize(); + + dut.inputStreamFirstFifoIn.enq(generatePsuedoStream(firstSizeA, True, isLastA)); + dut.inputStreamSecondFifoIn.enq(generatePsuedoStream(firstSizeB, True, isLastB)); streamARemainSizeReg <= sizeA - firstSizeA; streamBRemainSizeReg <= sizeB - firstSizeB; testCntReg <= testCntReg + 1; - $display("INFO: Add Input of %d Epoch", testCntReg + 1); - $display("INFO: streamASize = %d, streamBSize = %d, ideaSize = %d", sizeA, sizeB, sizeA+sizeB); + // $display("INFO: Add Input of %d Epoch", testCntReg + 1); + // $display("INFO: streamASize = %d, streamBSize = %d, ideaSize = %d", sizeA, sizeB, sizeA+sizeB); end else if (testRoundReg > 0) begin if (streamARemainSizeReg > 0 && dut.inputStreamFirstFifoIn.notFull) begin - Bool isLast = streamARemainSizeReg <= fromInteger(valueOf(BYTE_EN_WIDTH)); - StreamSize size = isLast ? streamARemainSizeReg : fromInteger(valueOf(BYTE_EN_WIDTH)); + Bool isLast = streamARemainSizeReg <= getMaxFrameSize(); + StreamSize size = isLast ? streamARemainSizeReg : getMaxFrameSize(); dut.inputStreamFirstFifoIn.enq(generatePsuedoStream(size, False, isLast)); streamARemainSizeReg <= streamARemainSizeReg - size; end if (streamBRemainSizeReg > 0 && dut.inputStreamSecondFifoIn.notFull) begin - Bool isLast = streamBRemainSizeReg <= fromInteger(valueOf(BYTE_EN_WIDTH)); - StreamSize size = isLast ? streamBRemainSizeReg : fromInteger(valueOf(BYTE_EN_WIDTH)); + Bool isLast = streamBRemainSizeReg <= getMaxFrameSize(); + StreamSize size = isLast ? streamBRemainSizeReg : getMaxFrameSize(); dut.inputStreamSecondFifoIn.enq(generatePsuedoStream(size, False, isLast)); streamBRemainSizeReg <= streamBRemainSizeReg - size; end testRoundReg <= testRoundReg - 1; end - endrule rule testOutput; let outStream = dut.outputStreamFifoOut.first; + checkDataStream(outStream, "Output Stream"); StreamSize concatSize = concatSizeReg + unpack(zeroExtend(convertByteEn2BytePtr(outStream.byteEn))); if (outStream.isLast) begin let ideaSize = ideaConcatSizeFifo.first; - showDataStream(outStream); if (concatSize != ideaSize) begin $display("Error: ideaSize=%d, realSize=%d", ideaSize, concatSize); $finish(); end else begin - $display("INFO: verify output ideaSize=%d, realSize=%d, ideaLastSize=%d", ideaSize, concatSize, ideaSize%fromInteger(valueOf(BYTE_EN_WIDTH))); + // $display("INFO: verify output ideaSize=%d, realSize=%d, ideaLastSize=%d", ideaSize, concatSize, ideaSize%getMaxFrameSize()); ideaConcatSizeFifo.deq; testFinishCntReg <= testFinishCntReg + 1; end @@ -127,7 +157,7 @@ module mkStreamConcatTb(Empty); else begin concatSizeReg <= concatSize; if (outStream.data != getPseudoData()) begin - $display("Error: Wrong data in round %d", testRoundReg); + $display("Error: Wrong output data"); showDataStream(outStream); $finish(); end @@ -143,35 +173,101 @@ module mkStreamConcatTb(Empty); endmodule - +(* doc = "testcase" *) module mkStreamSplitTb(Empty); StreamSplit dut <- mkStreamSplit; - Randomize#(StreamSize) streamSizeRandomValue <- mkConstrainedRandomizer(fromInteger(valueOf(MIN_STREAM_SIZE)), fromInteger(valueOf(MAX_STREAM_SIZE))); + + RandomStreamSize streamSizeRandomValue <- mkRandomStreamSize(fromInteger(valueOf(SEED_1)), fromInteger(valueOf(MAX_STREAM_SIZE_PTR))); + RandomStreamSize splitLocationRandomValue <- mkRandomStreamSize(fromInteger(valueOf(SEED_2)), fromInteger(valueOf(MAX_STREAM_SIZE_PTR)-1)); + Reg#(Bool) isInitReg <- mkReg(False); Reg#(UInt#(32)) testCntReg <- mkReg(0); - Reg#(StreamSize) streamSizeReg <- mkReg(0); - Reg#(StreamSize) streamSize2PutReg <- mkReg(0); Reg#(UInt#(32)) testRoundReg <- mkReg(0); + FIFOF#(StreamSize) ideaTotalSizeFifo <- mkSizedFIFOF(valueOf(TEST_IDEAL_FIFO_DEPTH)); + FIFOF#(StreamSize) ideaSplitSizeFifo <- mkSizedFIFOF(valueOf(TEST_IDEAL_FIFO_DEPTH)); + + Reg#(StreamSize) streamSize2PutReg <- mkReg(0); + + Reg#(Bool) hasRecvFirstChunkReg <- mkReg(False); + Reg#(StreamSize) totalRecvSizeReg <- mkReg(0); + rule testInit if (!isInitReg); isInitReg <= True; - streamSizeRandomValue.cntrl.init; + $display("INFO: ================start StreamSplitTb!=================="); endrule - rule testInput if (isInitReg); - if (testRoundReg == 0) begin + rule testInput if (isInitReg && testCntReg < fromInteger(valueOf(TEST_NUM))); + // First Frame + if (streamSize2PutReg == 0) begin let size <- streamSizeRandomValue.next; - if (size <= getMaxFrameSize()) begin - let stream = generatePsuedoStream(size, True, True); + let splitLocation <- splitLocationRandomValue.next; + if (splitLocation < size) begin + let isLast = size <= getMaxFrameSize(); + let firstSize = isLast ? size : getMaxFrameSize(); + let stream = generatePsuedoStream(firstSize, True, isLast); + dut.splitLocationFifoIn.enq(splitLocation); dut.inputStreamFifoIn.enq(stream); - streamSizeReg <= size; + ideaTotalSizeFifo.enq(size); + ideaSplitSizeFifo.enq(splitLocation); + streamSize2PutReg <= size - firstSize; + // $display("INFO: Add input stream size %d, split at %d", size, splitLocation); end end + else begin + let isLast = streamSize2PutReg <= getMaxFrameSize(); + let size = isLast ? streamSize2PutReg : getMaxFrameSize(); + let stream = generatePsuedoStream(size, False, isLast); + dut.inputStreamFifoIn.enq(stream); + streamSize2PutReg <= streamSize2PutReg - size; + end endrule rule testOutput if (isInitReg); + let outStream = dut.outputStreamFifoOut.first; + dut.outputStreamFifoOut.deq; + checkDataStream(outStream, "split output stream"); + StreamSize totalSize = totalRecvSizeReg + unpack(zeroExtend(convertByteEn2BytePtr(outStream.byteEn))); + + if (outStream.isLast) begin + if (hasRecvFirstChunkReg) begin + if (totalSize != ideaTotalSizeFifo.first) begin + $display("Error: wrong total size, idea = %d, real = %d", ideaTotalSizeFifo.first, totalSize); + showDataStream(outStream); + $finish(); + end + else begin + // $display("INFO: receive total size", totalSize); + ideaTotalSizeFifo.deq; + testCntReg <= testCntReg + 1; + hasRecvFirstChunkReg <= False; + totalRecvSizeReg <= 0; + end + end + else begin + if (totalSize != ideaSplitSizeFifo.first) begin + $display("Error: wrong split location, idea = %d, real = %d", ideaSplitSizeFifo.first, totalSize); + showDataStream(outStream); + $finish(); + end + else begin + // $display("INFO: receive first chunk at %d, total size %d", ideaSplitSizeFifo.first, ideaTotalSizeFifo.first); + ideaSplitSizeFifo.deq; + hasRecvFirstChunkReg <= True; + totalRecvSizeReg <= totalSize; + end + end + end + else begin + totalRecvSizeReg <= totalSize; + end + endrule + rule testFinish; + if (testCntReg == fromInteger(valueOf(TEST_NUM)-1)) begin + $finish(); + end endrule endmodule \ No newline at end of file From 44e0f8a005fbe1611be8329c7f0c76be514c7140 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Mon, 15 Jul 2024 02:59:40 +0800 Subject: [PATCH 17/53] Update all modules according to the review --- .github/workflows/ci.yml | 24 ++++++ .gitignore | 1 + Makefile.test | 5 +- img/StreamSplit.drawio | 65 --------------- img/chunkSplit.drawio | 100 ---------------------- img/dmac.drawio | 56 ------------- img/streamConcat.drawio | 100 ---------------------- run_one.sh | 2 +- src/DmaController.bsv | 17 ++++ src/DmaRequestCore.bsv | 32 +++++--- src/DmaTypes.bsv | 71 +++++++++++----- src/PcieTypes.bsv | 1 - src/PrimUtils.bsv | 15 ++++ src/StreamUtils.bsv | 127 +++++++++++----------------- test/TestAxiStream.bsv | 173 --------------------------------------- test/TestDmaCore.bsv | 75 ++++++++--------- test/TestStreamUtils.bsv | 85 +++++++++---------- 17 files changed, 252 insertions(+), 697 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 img/StreamSplit.drawio delete mode 100644 img/chunkSplit.drawio delete mode 100644 img/dmac.drawio delete mode 100644 img/streamConcat.drawio create mode 100644 src/PrimUtils.bsv delete mode 100755 test/TestAxiStream.bsv diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c4685cb --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,24 @@ +name: CI +on: + pull_request: + branches: [master] + push: + branches: [master] + # CI runs every 12 hours + schedule: [cron: "0 */12 * * *"] + +jobs: + ci-check: + name: CI Build and Simulate + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v2 + - name: build and simulate + run : | + ./setup.sh + ./run.sh + - name: Setup tmate session + if: ${{ failure() }} + uses: mxschmitt/action-tmate@v3 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9fe87a4..0190e22 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ **/build/** **/verilog/** **/*.log +img/*.drawio \ No newline at end of file diff --git a/Makefile.test b/Makefile.test index e60c219..af59283 100755 --- a/Makefile.test +++ b/Makefile.test @@ -5,8 +5,9 @@ TESTBENCHS = \ TestStreamUtils.bsv \ TestDmaCore.bsv -TestStreamUtils = mkStreamConcatTb -TestDmaCore.bsv = mkChunkComputerTb +TestStreamUtils.bsv = mkStreamConcatTb \ + mkStreamSplitTb +TestDmaCore.bsv = mkChunkComputerTb all: $(TESTBENCHS) diff --git a/img/StreamSplit.drawio b/img/StreamSplit.drawio deleted file mode 100644 index 8fe59ab..0000000 --- a/img/StreamSplit.drawio +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/img/chunkSplit.drawio b/img/chunkSplit.drawio deleted file mode 100644 index 6e78ab1..0000000 --- a/img/chunkSplit.drawio +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/img/dmac.drawio b/img/dmac.drawio deleted file mode 100644 index 003b8b7..0000000 --- a/img/dmac.drawio +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/img/streamConcat.drawio b/img/streamConcat.drawio deleted file mode 100644 index 607cf6a..0000000 --- a/img/streamConcat.drawio +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/run_one.sh b/run_one.sh index ad1eac1..f049c0d 100755 --- a/run_one.sh +++ b/run_one.sh @@ -13,7 +13,7 @@ TEST_LOG=run.log TEST_DIR=test cd $TEST_DIR truncate -s 0 $TEST_LOG -FILES=`ls TestStreamUtils.bsv` +FILES=`ls TestDmaCore.bsv` ########################################################################### for FILE in $FILES; do # echo $FILE diff --git a/src/DmaController.bsv b/src/DmaController.bsv index f8030f4..5d8df4b 100755 --- a/src/DmaController.bsv +++ b/src/DmaController.bsv @@ -1,6 +1,23 @@ import PcieTypes::*; import DmaTypes::*; +interface DmaController#(numeric type dataWidth); + + interface FifoIn#(DataStream) dataC2HPipeIn; + interface FifoIn#(DmaRequestFrame) reqC2HPipeIn; + interface FifoIn#(DmaRequestFrame) reqH2CPipeIn; + interface FifoOut#(DataStream) dataH2CPipeOut; + + interface FifoIn#(DmaCsrFrame) csrC2HPipeIn; + interface FifoOut#(DMACsrAddr) csrC2HPipeOut; // read reg in the card from Host + interface FifoOut#(DmaCsrFrame) csrH2CPipeOut; + + interface RawPcieRequester pcieRequester; + interface RawPcieCompleter pcieCompleter; + interface RawPcieConfiguration pcieConfig; + +endinterface + module mkDmaController#() (DmaController ifc); diff --git a/src/DmaRequestCore.bsv b/src/DmaRequestCore.bsv index e102bce..8c7df68 100755 --- a/src/DmaRequestCore.bsv +++ b/src/DmaRequestCore.bsv @@ -1,5 +1,6 @@ import FIFOF::*; import GetPut :: *; + import SemiFifo::*; import PcieTypes::*; import DmaTypes::*; @@ -7,10 +8,13 @@ import DmaTypes::*; typedef 4096 BUS_BOUNDARY; typedef TAdd#(1, TLog#(BUS_BOUNDARY)) BUS_BOUNDARY_WIDTH; + typedef Bit#(BUS_BOUNDARY_WIDTH) PcieTlpMaxMaxPayloadSize; typedef Bit#(TLog#(BUS_BOUNDARY_WIDTH)) PcieTlpSizeWidth; + typedef 128 DEFAULT_TLP_SIZE; typedef TAdd#(1, TLog#(DEFAULT_TLP_SIZE)) DEFAULT_TLP_SIZE_WIDTH; + typedef 3 PCIE_TLP_SIZE_SETTING_WIDTH; typedef Bit#(PCIE_TLP_SIZE_SETTING_WIDTH) PcieTlpSizeSetting; @@ -20,20 +24,23 @@ typedef struct { } ChunkRequestFrame deriving(Bits, Eq); interface ChunkCompute; - interface FifoIn#(DmaRequestFrame) dmaRequests; - interface FifoOut#(DmaRequestFrame) chunkRequests; + interface FifoIn#(DmaRequestFrame) dmaRequestFifoIn; + interface FifoOut#(DmaRequestFrame) chunkRequestFifoOut; interface Put#(PcieTlpSizeSetting) setTlpMaxSize; endinterface module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); - FIFOF#(DmaRequestFrame) inputFifo <- mkFIFOF; - FIFOF#(DmaRequestFrame) outputFifo <- mkFIFOF; - FIFOF#(ChunkRequestFrame) splitFifo <- mkFIFOF; - Reg#(DmaMemAddr) tlpMaxSize <- mkReg(fromInteger(valueOf(DEFAULT_TLP_SIZE))); //MPS if isTX, MRRS else + + FIFOF#(DmaRequestFrame) inputFifo <- mkFIFOF; + FIFOF#(DmaRequestFrame) outputFifo <- mkFIFOF; + FIFOF#(ChunkRequestFrame) splitFifo <- mkFIFOF; + + Reg#(DmaMemAddr) newChunkPtrReg <- mkReg(0); + Reg#(DmaMemAddr) totalLenRemainReg <- mkReg(0); + Reg#(Bool) isSplittingReg <- mkReg(False); + + Reg#(DmaMemAddr) tlpMaxSize <- mkReg(fromInteger(valueOf(DEFAULT_TLP_SIZE))); Reg#(PcieTlpSizeWidth) tlpMaxSizeWidth <- mkReg(fromInteger(valueOf(DEFAULT_TLP_SIZE_WIDTH))); - Reg#(DmaMemAddr) newChunkPtrReg <- mkReg(0); - Reg#(DmaMemAddr) totalLenRemainReg <- mkReg(0); - Reg#(Bool) isSplittingReg <- mkReg(False); function Bool hasBoundary(DmaRequestFrame request); let highIdx = (request.startAddr + request.length - 1) >> valueOf(BUS_BOUNDARY_WIDTH); @@ -52,9 +59,10 @@ module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); let request = inputFifo.first; inputFifo.deq; let offset = getOffset(request); + let firstLen = (request.length > tlpMaxSize) ? tlpMaxSize : request.length; splitFifo.enq(ChunkRequestFrame { dmaRequest: request, - firstChunkLen: hasBoundary(request) ? offset : tlpMaxSize + firstChunkLen: hasBoundary(request) ? offset : firstLen }); endrule @@ -96,8 +104,8 @@ module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); end endrule - interface dmaRequests = convertFifoToFifoIn(inputFifo); - interface chunkRequests = convertFifoToFifoOut(outputFifo); + interface dmaRequestFifoIn = convertFifoToFifoIn(inputFifo); + interface chunkRequestFifoOut = convertFifoToFifoOut(outputFifo); interface Put setTlpMaxSize; method Action put (PcieTlpSizeSetting tlpSizeSetting); diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index 8d9da30..59d4ec2 100755 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -1,43 +1,72 @@ +import FShow::*; import SemiFifo::*; -import StreamUtils::*; import PcieTypes::*; -typedef 512 DMA_DATA_WIDTH; -typedef 64 DMA_HOSTMEM_ADDR_WIDTH; +typedef 512 DATA_WIDTH; +typedef 64 DMA_MEM_ADDR_WIDTH; + typedef 32 DMA_CSR_ADDR_WIDTH; typedef 32 DMA_CSR_DATA_WIDTH; -typedef Bit#(DMA_HOSTMEM_ADDR_WIDTH) DmaMemAddr; + +typedef Bit#(DMA_MEM_ADDR_WIDTH) DmaMemAddr; typedef Bit#(DMA_CSR_ADDR_WIDTH) DMACsrAddr; typedef Bit#(DMA_CSR_DATA_WIDTH) DMACsrValue; +typedef 8 BYTE_WIDTH; +typedef TLog#(BYTE_WIDTH) BYTE_WIDTH_WIDTH; +typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; + +typedef 2 CONCAT_STREAM_NUM; + +typedef TDiv#(DATA_WIDTH, BYTE_WIDTH) BYTE_EN_WIDTH; +typedef 'hFFFFFFFFFFFFFFFF MAX_BYTE_EN; + +typedef Bit#(DATA_WIDTH) Data; +typedef Bit#(BYTE_EN_WIDTH) ByteEn; +typedef Bit#(TAdd#(1, TLog#(DATA_WIDTH))) DataBitPtr; +typedef Bit#(TAdd#(1, TLog#(BYTE_EN_WIDTH))) DataBytePtr; + typedef struct { DmaMemAddr startAddr; DmaMemAddr length; -} DmaRequestFrame deriving(Bits, Bounded, Eq, FShow); +} DmaRequestFrame deriving(Bits, Bounded, Eq); typedef struct { DMACsrAddr address; DMACsrValue value; -} DmaCsrFrame deriving(Bits, Bounded, Eq, FShow); +} DmaCsrFrame deriving(Bits, Bounded, Eq); typedef enum { - DMA_RX, DMA_TX -} TRXDirection deriving(Bits, Eq); + DMA_RX, + DMA_TX +} TRXDirection deriving(Bits, Eq, FShow); -interface DmaController#(numeric type dataWidth); - - interface FifoIn#(DataStream) dataC2HPipeIn; - interface FifoIn#(DmaRequestFrame) reqC2HPipeIn; - interface FifoIn#(DmaRequestFrame) reqH2CPipeIn; - interface FifoOut#(DataStream) dataH2CPipeOut; +typedef struct { + Data data; + ByteEn byteEn; + Bool isFirst; + Bool isLast; +} DataStream deriving(Bits, Bounded, Eq); - interface FifoIn#(DmaCsrFrame) csrC2HPipeIn; - interface FifoOut#(DMACsrAddr) csrC2HPipeOut; // read reg in the card from Host - interface FifoOut#(DmaCsrFrame) csrH2CPipeOut; +instance FShow#(DmaRequestFrame); + function Fmt fshow(DmaRequestFrame request); + return ($format(" 0); DataBitPtr bitPtrA = zeroExtend(bytePtrA) << fromInteger(valueOf(BYTE_WIDTH_WIDTH)); // Fill the low PtrA bytes by streamA data - Data concatDataA = streamA.data; + Data concatDataA = streamA.data; ByteEn concatByteEnA = streamA.byteEn; // Fill the high bytes by streamB data - Data concatDataB = streamB.data << bitPtrA; + Data concatDataB = streamB.data << bitPtrA; ByteEn concatByteEnB = streamB.byteEn << bytePtrA; - Data concatData = concatDataA | concatDataB; - ByteEn concatByteEn = concatByteEnA | concatByteEnB; + Data concatData = concatDataA | concatDataB; + ByteEn concatByteEn = concatByteEnA | concatByteEnB; // Get the remain bytes of streamB data - DataBitPtr resBitPtr = getMaxBitPtr() - bitPtrA; - DataBytePtr resBytePtr = getMaxBytePtr() - bytePtrA; - Data remainData = streamB.data >> resBitPtr; - ByteEn remainByteEn = streamB.byteEn >> resBytePtr; + DataBitPtr resBitPtr = getMaxBitPtr() - bitPtrA; + DataBytePtr resBytePtr = getMaxBytePtr() - bytePtrA; + Data remainData = streamB.data >> resBitPtr; + ByteEn remainByteEn = streamB.byteEn >> resBytePtr; // Get if the concat frame is the last - Bool isConcatStreamLast = streamB.isLast; - DataBytePtr remainBytePtr = 0; + Bool isConcatStreamLast = streamB.isLast; + DataBytePtr remainBytePtr = 0; if (resBytePtr < bytePtrB ) begin isConcatStreamLast = False; - remainBytePtr = bytePtrB - resBytePtr; + remainBytePtr = bytePtrB - resBytePtr; end DataStream concatStream = getEmptyStream; DataStream remainStream = getEmptyStream; @@ -119,29 +100,20 @@ function Tuple3#(DataStream, DataStream, DataBytePtr) getConcatStream (DataStrea isLast: True }; end - return tuple3(concatStream, remainStream, remainBytePtr); -endfunction - -function Action showDataStream (DataStream stream); - return action - $display(" Data = %h", stream.data); - $display(" byteEn = %b", stream.byteEn); - $display(" isFirst = %b, isLast = %b", stream.isFirst, stream.isLast); - endaction; -endfunction - -function Action checkDataStream (DataStream stream, String name); - if (stream.byteEn == 0 || stream.data == 0) begin - return action - $display("Error: empty dataStream ", name); - showDataStream(stream); - $finish(); - endaction; - end - else begin - return action - endaction; - end + return ( + actionvalue + immAssert( + (streamA.isLast && bytePtrA <= getMaxBytePtr() && bytePtrA > 0), + "request check @ getConcatStream", + $format( + "bytePtrA=%d should in range of 1~%d", bytePtrA, getMaxBytePtr(), + "bytePtrB=%d should in range of 1~%d", bytePtrB, getMaxBytePtr(), + "streamA.isLast=", fshow(streamA.isLast), "should be False" + ) + ); + return tuple3(concatStream, remainStream, remainBytePtr); + endactionvalue + ); endfunction (* synthesize *) @@ -200,10 +172,10 @@ module mkStreamConcat (StreamConcat ifc); prepareFifoB.deq; streamB.isFirst = False; if (hasRemainReg) begin - match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(remainStreamReg, streamB, remainBytePtrReg, bytePtrB); - hasRemainReg <= unpack(remainStream.byteEn[0]); + match{.concatStream, .remainStream, .remainBytePtr} <- getConcatStream(remainStreamReg, streamB, remainBytePtrReg, bytePtrB); + hasRemainReg <= unpack(remainStream.byteEn[0]); hasLastRemainReg <= streamB.isLast; - remainStreamReg <= remainStream; + remainStreamReg <= remainStream; remainBytePtrReg <= remainBytePtr; outputFifo.enq(concatStream); end @@ -227,12 +199,12 @@ module mkStreamConcat (StreamConcat ifc); else if (streamA.isLast && prepareFifoB.notEmpty) begin let streamB = prepareFifoB.first.stream; let bytePtrB = prepareFifoB.first.bytePtr; - match{.concatStream, .remainStream, .remainBytePtr} = getConcatStream(streamA, streamB, bytePtrA, bytePtrB); - hasRemainReg <= unpack(remainStream.byteEn[0]); + match{.concatStream, .remainStream, .remainBytePtr} <- getConcatStream(streamA, streamB, bytePtrA, bytePtrB); + hasRemainReg <= unpack(remainStream.byteEn[0]); hasLastRemainReg <= streamB.isLast; - remainStreamReg <= remainStream; + remainStreamReg <= remainStream; remainBytePtrReg <= remainBytePtr; - isStreamAEnd <= !streamB.isLast; + isStreamAEnd <= !streamB.isLast; outputFifo.enq(concatStream); prepareFifoA.deq; prepareFifoB.deq; @@ -240,9 +212,9 @@ module mkStreamConcat (StreamConcat ifc); end endrule - interface inputStreamFirstFifoIn = convertFifoToFifoIn(inputFifoA); + interface inputStreamFirstFifoIn = convertFifoToFifoIn(inputFifoA); interface inputStreamSecondFifoIn = convertFifoToFifoIn(inputFifoB); - interface outputStreamFifoOut = convertFifoToFifoOut(outputFifo); + interface outputStreamFifoOut = convertFifoToFifoOut(outputFifo); endmodule @@ -251,19 +223,19 @@ module mkStreamSplit(StreamSplit ifc); Reg#(StreamSize) streamByteCntReg <- mkReg(0); - FIFOF#(StreamSize) splitLocationFifo <- mkFIFOF; - FIFOF#(DataStream) inputFifo <- mkFIFOF; - FIFOF#(DataStream) outputFifo <- mkFIFOF; - FIFOF#(StreamWithPtr) prepareFifo <- mkFIFOF; - FIFOF#(StreamWithPtr) assertFifo <- mkFIFOF; + FIFOF#(StreamSize) splitLocationFifo <- mkFIFOF; + FIFOF#(DataStream) inputFifo <- mkFIFOF; + FIFOF#(DataStream) outputFifo <- mkFIFOF; + FIFOF#(StreamWithPtr) prepareFifo <- mkFIFOF; + FIFOF#(StreamWithPtr) assertFifo <- mkFIFOF; FIFOF#(Tuple2#(DataBytePtr,DataBytePtr)) splitPtrFifo <- mkFIFOF; - Reg#(DataStream) remainStreamReg <- mkRegU; - Reg#(Bool) hasRemainReg <- mkReg(False); - Reg#(Bool) hasLastRemainReg <- mkReg(False); + Reg#(DataStream) remainStreamReg <- mkRegU; Reg#(DataBytePtr) remainBytePtrReg <- mkReg(0); - Reg#(Bool) isSplitted <- mkReg(False); + Reg#(Bool) hasRemainReg <- mkReg(False); + Reg#(Bool) hasLastRemainReg <- mkReg(False); + Reg#(Bool) isSplitted <- mkReg(False); rule prepareStream; let stream = inputFifo.first; @@ -292,7 +264,6 @@ module mkStreamSplit(StreamSplit ifc); isSplitted <= False; end streamByteCntReg <= stream.isLast ? 0 : streamByteCntReg + unpack(zeroExtend(bytePtr)); - assertFifo.enq(prepareFifo.first); prepareFifo.deq; if (stream.isLast) begin @@ -304,9 +275,6 @@ module mkStreamSplit(StreamSplit ifc); rule execSplitStream; // Only output remainStreamReg if (hasRemainReg && hasLastRemainReg) begin - if (remainStreamReg.byteEn == 0) begin - showDataStream(remainStreamReg); - end outputFifo.enq(remainStreamReg); hasRemainReg <= False; hasLastRemainReg <= False; @@ -348,8 +316,7 @@ module mkStreamSplit(StreamSplit ifc); // concat the new frame with the remainReg else if (hasRemainReg) begin - match {.concatStream, .remainStream, .remainBytePtr} = getConcatStream(remainStreamReg, stream, remainBytePtrReg, frameBytePtr); - checkDataStream(concatStream, "concat remain"); + match {.concatStream, .remainStream, .remainBytePtr} <- getConcatStream(remainStreamReg, stream, remainBytePtrReg, frameBytePtr); outputFifo.enq(concatStream); hasRemainReg <= unpack(remainStream.byteEn[0]); hasLastRemainReg <= stream.isLast; diff --git a/test/TestAxiStream.bsv b/test/TestAxiStream.bsv deleted file mode 100755 index bd30140..0000000 --- a/test/TestAxiStream.bsv +++ /dev/null @@ -1,173 +0,0 @@ -import FIFO::*; -import Vector::*; -import AxiStreamTypes::*; -import Counter::*; - -typedef 512 DATA_WIDTH; -typedef 8 BYTE_BITS; -typedef TDiv#(DATA_WIDTH, BYTE_BITS) BATCH_BYTES; -typedef 128 USR_WIDTH; -typedef 4321 RD_BYTES_LENGTH; - - -interface AxisFifo#(numeric type keepWidth, numeric type usrWidth); - interface RawAxiStreamMaster#(keepWidth, usrWidth) axisMaster; - interface RawAxiStreamSlave#(keepWidth, usrWidth) axisSlave; -endinterface - - -module mkTbAxisRdWrLoop (Empty); - Reg#(File) fileInReg <- mkRegU(); - Reg#(File) fileRefReg <- mkRegU(); - Reg#(File) fileOutReg <- mkRegU(); - Reg#(Bool) initFlagReg <- mkReg(False); - // Read the file - Reg#(Bool) rdDoneFlagReg <- mkReg(False); - Reg#(UInt#(32)) rdBatchCntReg <- mkReg(0); - let rdTotalBytesLen = valueOf(RD_BYTES_LENGTH); - let rdBatchBytesLen = valueOf(BATCH_BYTES); - let rdLastBatchBytesLen = rdTotalBytesLen % rdBatchBytesLen; - let rdBatchesNum = rdTotalBytesLen % rdBatchBytesLen > 0 ? rdTotalBytesLen / rdBatchBytesLen + 1 : rdTotalBytesLen / rdBatchBytesLen; - FIFO#(AxiStream#(BATCH_BYTES, USR_WIDTH)) toDutFifo <- mkSizedFIFO(16); - // DUT - AxisFifo#(BATCH_BYTES, USR_WIDTH) dut <- mkTbAxisWire(); - // Control - Reg#(UInt#(32)) tValidCnt <- mkReg(0); - - rule init(!initFlagReg); - initFlagReg <= True; - File in <- $fopen("test.txt", "rb"); - File refer <- $fopen("ref.txt", "wb"); - File out <- $fopen("out.txt", "wb"); - if (in == InvalidFile || refer == InvalidFile || out == InvalidFile) begin - $display("ERROR: couldn't open test file"); - $finish; - end - fileInReg <= in; - fileRefReg <= refer; - fileOutReg <= out; - endrule - - rule readfile(initFlagReg && !rdDoneFlagReg && rdBatchCntReg < fromInteger(rdBatchesNum)); - Vector#(BATCH_BYTES, Bit#(BYTE_BITS)) getChars = replicate(0); - Bit#(BATCH_BYTES) keep = 0; - Bool last = False; - if(rdBatchCntReg == fromInteger(rdBatchesNum) - 1) begin - for(Integer idx = 0; idx < rdLastBatchBytesLen; idx = idx + 1) begin - int readChar <- $fgetc(fileInReg); - if(readChar == -1) begin - $fclose(fileInReg); - $fclose(fileRefReg); - end else begin - $fwrite(fileRefReg, "%c", readChar); - getChars[idx] = truncate(pack(readChar)); - keep[idx] = 1'b1; - end - end - $fclose(fileInReg); - $fclose(fileRefReg); - rdDoneFlagReg <= True; - last = True; - $display("INFO: test file read done"); - end else begin - rdBatchCntReg <= rdBatchCntReg + 1; - for(Integer idx = 0; idx < rdBatchBytesLen; idx = idx + 1) begin - int rdChar <- $fgetc(fileInReg); - if(rdChar == -1) begin - $fclose(fileRefReg); - $fclose(fileInReg); - last = True; - end else begin - $fwrite(fileRefReg, "%c", rdChar); - getChars[idx] = truncate(pack(rdChar)); - keep[idx] = 1'b1; - end - end - end - let axis = AxiStream{ - tData: pack(getChars), - tKeep: keep, - tLast: last, - tUser: 0 - }; - toDutFifo.enq(axis); - endrule - - rule reader2dut if (rdBatchCntReg > 0); - if(dut.axisSlave.tReady) begin - // $display("INFO: simulation exec a batch"); - toDutFifo.deq; - let axis = toDutFifo.first; - dut.axisSlave.tValid( - True, - axis.tData, - axis.tKeep, - axis.tLast, - axis.tUser); - end - endrule - - rule dut2writer; - dut.axisMaster.tReady(True); - if(dut.axisMaster.tValid) begin - tValidCnt <= tValidCnt + 1; - let data = dut.axisMaster.tData; - Vector#(BATCH_BYTES, Bit#(BYTE_BITS)) getChars = unpack(data); - let keep = dut.axisMaster.tKeep; - for(Integer idx = 0; idx < rdBatchBytesLen; idx = idx + 1) begin - if(keep[idx] == 1'b1) begin $fwrite(fileOutReg, "%c", getChars[i]); end - end - end - if(tValidCnt == rdBatchCntReg && rdDoneFlagReg) begin - $display("INFO: file write done, compare the ref and out") - $fclose(fileOutReg); - $finish(); - end - endrule - -endmodule - -module mkTbAxisWire(AxisFifo#(keepWidth, usrWidth) ifc); - Wire#(Bit#(TMul#(keepWidth, 8))) data <- mkDWire(0); - Wire#(Bit#(keepWidth)) keep <- mkDWire(0); - Wire#(Bit#(usrWidth)) user <- mkDWire(0); - Wire#(Bit#(1)) last <- mkDWire(0); - Wire#(Bit#(1)) rdy <- mkDWire(0); - Wire#(Bit#(1)) vld <- mkDWire(0); - - interface RawAxiStreamMaster axisMaster; - method Bool tValid = unpack(vld); - method Bool tLast = unpack(last); - method Bit#(TMul#(keepWidth, 8)) tData = data; - method Bit#(keepWidth) tKeep = keep; - method Bit#(usrWidth) tUser = user; - method Action tReady(Bool ready); - rdy <= pack(ready); - endmethod - endinterface - - interface RawAxiStreamSlave axisSlave; - method Bool tReady = True; - method Action tValid( - Bool tvalid, - Bit#(TMul#(keepWidth, 8)) tData, - Bit#(keepWidth) tKeep, - Bool tLast, - Bit#(usrWidth) tUser - ); - data <= tData; - keep <= tKeep; - user <= tUser; - last <= pack(tLast); - vld <= pack(tvalid); - endmethod - endinterface -endmodule - -// module mkTbAxisPipeFifo (AxisFifo#(keepWidth, usrWidth) ifc); -// FIFOF#(AxiStream#(keepWidth, usrWidth)) <- mkSizedFIFOF(10); - -// endmodule - - - diff --git a/test/TestDmaCore.bsv b/test/TestDmaCore.bsv index 0a9f7f2..3d26e2b 100755 --- a/test/TestDmaCore.bsv +++ b/test/TestDmaCore.bsv @@ -1,10 +1,12 @@ -import SemiFifo::*; import GetPut::*; import Randomizable::*; + +import SemiFifo::*; +import PrimUtils::*; import DmaTypes::*; import DmaRequestCore::*; -typedef 10 CHUNK_PER_EPOCH_TEST_NUM; +typedef 100000 CHUNK_PER_EPOCH_TEST_NUM; typedef 64'hFFFFFFFFFFFFFFFF MAX_ADDRESS; typedef 16'hFFFF MAX_TEST_LENGTH; typedef 2'b00 DEFAULT_TLP_SIZE_SETTING; @@ -16,13 +18,14 @@ module mkChunkComputerTb(Empty); ChunkCompute dut <- mkChunkComputer(DMA_TX); - Reg#(Bool) isInitReg <- mkReg(False); - Reg#(UInt#(32)) testCntReg <- mkReg(0); - Reg#(UInt#(32)) epochCntReg <- mkReg(0); + Reg#(Bool) isInitReg <- mkReg(False); + Reg#(UInt#(32)) testCntReg <- mkReg(0); + Reg#(UInt#(32)) epochCntReg <- mkReg(0); + Reg#(DmaMemAddr) lenRemainReg <- mkReg(0); - Reg#(DmaRequestFrame) testRequest <- mkRegU; + Randomize#(DmaMemAddr) startAddrRandomVal <- mkConstrainedRandomizer(0, fromInteger(valueOf(MAX_ADDRESS)-1)); - Randomize#(DmaMemAddr) lengthRandomVal <- mkConstrainedRandomizer(1, fromInteger(valueOf(MAX_TEST_LENGTH))); + Randomize#(DmaMemAddr) lengthRandomVal <- mkConstrainedRandomizer(1, fromInteger(valueOf(MAX_TEST_LENGTH))); function Bool hasBoundary(DmaRequestFrame request); let highIdx = (request.startAddr + request.length - 1) >> valueOf(BUS_BOUNDARY_WIDTH); @@ -30,18 +33,12 @@ module mkChunkComputerTb(Empty); return (highIdx > lowIdx); endfunction - function Action showRequest (DmaRequestFrame request); - return action - $display("startAddr: ", request.startAddr, " length: ", request.length); - endaction; - endfunction - rule testInit if (!isInitReg); startAddrRandomVal.cntrl.init; lengthRandomVal.cntrl.init; isInitReg <= True; dut.setTlpMaxSize.put(fromInteger(valueOf(DEFAULT_TLP_SIZE_SETTING))); - $display("Start Test of mkChunkComputerTb"); + $display("INFO: Start Test of mkChunkComputerTb"); $display("INFO: Set Max Payload Size to ", valueOf(DEFAULT_TLP_SIZE)); endrule @@ -55,8 +52,8 @@ module mkChunkComputerTb(Empty); length: testLength }; lenRemainReg <= testLength; - dut.dmaRequests.enq(request); - showRequest(request); + dut.dmaRequestFifoIn.enq(request); + // $display("INFO: input ", fshow(request)); end else begin lenRemainReg <= 0; @@ -64,32 +61,30 @@ module mkChunkComputerTb(Empty); endrule rule testOutput if (isInitReg && lenRemainReg > 0); - let newRequest = dut.chunkRequests.first; - dut.chunkRequests.deq; - if (hasBoundary(newRequest)) begin - $display("Error, has 4KB boundary!"); - showRequest(newRequest); - $finish(); - end - else begin - let newRemain = lenRemainReg - newRequest.length; - lenRemainReg <= newRemain; - if (newRemain == 0) begin - if (epochCntReg < fromInteger(valueOf(CHUNK_PER_EPOCH_TEST_NUM)-1)) begin - epochCntReg <= epochCntReg + 1; + let newRequest = dut.chunkRequestFifoOut.first; + dut.chunkRequestFifoOut.deq; + immAssert( + !hasBoundary(newRequest), + "has boundary assert @ mkChunkComputerTb", + fshow(newRequest) + ); + let newRemain = lenRemainReg - newRequest.length; + lenRemainReg <= newRemain; + if (newRemain == 0) begin + if (epochCntReg < fromInteger(valueOf(CHUNK_PER_EPOCH_TEST_NUM)-1)) begin + epochCntReg <= epochCntReg + 1; + end + else begin + epochCntReg <= 0; + testCntReg <= testCntReg + 1; + if (testCntReg == fromInteger(valueOf(CHUNK_TX_TEST_SETTING_NUM)-1)) begin + $display("INFO: ChunkComputer Test End."); + $finish(); end else begin - epochCntReg <= 0; - testCntReg <= testCntReg + 1; - if (testCntReg == fromInteger(valueOf(CHUNK_TX_TEST_SETTING_NUM)-1)) begin - $display("INFO: ChunkComputer Test End."); - $finish(); - end - else begin - PcieTlpSizeSetting newSetting = fromInteger(valueOf(DEFAULT_TLP_SIZE_SETTING)) + truncate(pack(testCntReg)) + 1; - dut.setTlpMaxSize.put(newSetting); - $display("INFO: Set Max Payload Size to ", pack(fromInteger(valueOf(DEFAULT_TLP_SIZE)) << newSetting)); - end + PcieTlpSizeSetting newSetting = fromInteger(valueOf(DEFAULT_TLP_SIZE_SETTING)) + truncate(pack(testCntReg)) + 1; + dut.setTlpMaxSize.put(newSetting); + $display("INFO: Set Max Payload Size to ", pack(fromInteger(valueOf(DEFAULT_TLP_SIZE)) << newSetting)); end end end diff --git a/test/TestStreamUtils.bsv b/test/TestStreamUtils.bsv index a78bc3e..3241357 100755 --- a/test/TestStreamUtils.bsv +++ b/test/TestStreamUtils.bsv @@ -1,6 +1,9 @@ import FIFOF::*; import SemiFifo::*; import LFSR::*; + +import PrimUtils::*; +import DmaTypes::*; import StreamUtils::*; typedef 'hAB PSEUDO_DATA; @@ -19,10 +22,6 @@ typedef 'hABCDEF01 SEED_2; typedef 16 MAX_STREAM_SIZE_PTR; typedef 10000 TEST_NUM; -typedef enum { - WAITING, FirstChunk, SecondChunk -} StreamSplitOutStatus deriving(Bits, Eq); - interface RandomStreamSize; method ActionValue#(StreamSize) next(); endinterface @@ -95,7 +94,7 @@ module mkStreamConcatTb(Empty); Reg#(UInt#(32)) testFinishCntReg <- mkReg(0); rule testInit if (!isInitReg); - $display("INFO: ================start StreamConcatTb!=================="); + $display("INFO: start mkStreamConcatTb!"); isInitReg <= True; endrule @@ -139,34 +138,33 @@ module mkStreamConcatTb(Empty); rule testOutput; let outStream = dut.outputStreamFifoOut.first; - checkDataStream(outStream, "Output Stream"); StreamSize concatSize = concatSizeReg + unpack(zeroExtend(convertByteEn2BytePtr(outStream.byteEn))); if (outStream.isLast) begin let ideaSize = ideaConcatSizeFifo.first; - if (concatSize != ideaSize) begin - $display("Error: ideaSize=%d, realSize=%d", ideaSize, concatSize); - $finish(); - end - else begin - // $display("INFO: verify output ideaSize=%d, realSize=%d, ideaLastSize=%d", ideaSize, concatSize, ideaSize%getMaxFrameSize()); - ideaConcatSizeFifo.deq; - testFinishCntReg <= testFinishCntReg + 1; - end + immAssert( + (concatSize == ideaSize), + "outStream length check @ mkStreamConcatTb::testOutput", + $format("ideaSize = %d, realSize = %d \n", ideaSize, concatSize) + ); + // $display("INFO: verify output ideaSize=%d, realSize=%d, ideaLastSize=%d", ideaSize, concatSize, ideaSize%getMaxFrameSize()); + ideaConcatSizeFifo.deq; + testFinishCntReg <= testFinishCntReg + 1; concatSizeReg <= 0; end else begin concatSizeReg <= concatSize; - if (outStream.data != getPseudoData()) begin - $display("Error: Wrong output data"); - showDataStream(outStream); - $finish(); - end + immAssert( + (outStream.data == getPseudoData()), + "outStream Data Check @ mkStreamConcatTb::testOutput", + $format(outStream) + ); end dut.outputStreamFifoOut.deq; endrule rule testFinish; if (testFinishCntReg == fromInteger(valueOf(TEST_NUM)-1)) begin + $display("INFO: end mkStreamConcatTb"); $finish(); end endrule @@ -195,7 +193,7 @@ module mkStreamSplitTb(Empty); rule testInit if (!isInitReg); isInitReg <= True; - $display("INFO: ================start StreamSplitTb!=================="); + $display("INFO: start mkStreamSplitTb!"); endrule rule testInput if (isInitReg && testCntReg < fromInteger(valueOf(TEST_NUM))); @@ -227,36 +225,30 @@ module mkStreamSplitTb(Empty); rule testOutput if (isInitReg); let outStream = dut.outputStreamFifoOut.first; dut.outputStreamFifoOut.deq; - checkDataStream(outStream, "split output stream"); StreamSize totalSize = totalRecvSizeReg + unpack(zeroExtend(convertByteEn2BytePtr(outStream.byteEn))); - if (outStream.isLast) begin if (hasRecvFirstChunkReg) begin - if (totalSize != ideaTotalSizeFifo.first) begin - $display("Error: wrong total size, idea = %d, real = %d", ideaTotalSizeFifo.first, totalSize); - showDataStream(outStream); - $finish(); - end - else begin - // $display("INFO: receive total size", totalSize); - ideaTotalSizeFifo.deq; - testCntReg <= testCntReg + 1; - hasRecvFirstChunkReg <= False; - totalRecvSizeReg <= 0; - end + immAssert( + (totalSize == ideaTotalSizeFifo.first), + "outStream total length check @ mkStreamSplitTb", + $format("Wrong total length, ideaLen=%d, realLen=%d \n", ideaTotalSizeFifo.first, totalSize) + ); + // $display("INFO: receive total size", totalSize); + ideaTotalSizeFifo.deq; + testCntReg <= testCntReg + 1; + hasRecvFirstChunkReg <= False; + totalRecvSizeReg <= 0; end else begin - if (totalSize != ideaSplitSizeFifo.first) begin - $display("Error: wrong split location, idea = %d, real = %d", ideaSplitSizeFifo.first, totalSize); - showDataStream(outStream); - $finish(); - end - else begin - // $display("INFO: receive first chunk at %d, total size %d", ideaSplitSizeFifo.first, ideaTotalSizeFifo.first); - ideaSplitSizeFifo.deq; - hasRecvFirstChunkReg <= True; - totalRecvSizeReg <= totalSize; - end + immAssert( + (totalSize == ideaSplitSizeFifo.first), + "outStream split location check @ mkStreamSplitTb", + $format("Wrong split location, ideaLen=%d, realLen=%d \n", ideaSplitSizeFifo.first, totalSize) + ); + // $display("INFO: receive first chunk at %d, total size %d", ideaSplitSizeFifo.first, ideaTotalSizeFifo.first); + ideaSplitSizeFifo.deq; + hasRecvFirstChunkReg <= True; + totalRecvSizeReg <= totalSize; end end else begin @@ -266,6 +258,7 @@ module mkStreamSplitTb(Empty); rule testFinish; if (testCntReg == fromInteger(valueOf(TEST_NUM)-1)) begin + $display("INFO: end mkStreamSplitTb"); $finish(); end endrule From 32670906ce3b122a3388ff807188340a0d108b15 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Tue, 16 Jul 2024 16:36:36 +0800 Subject: [PATCH 18/53] Update StreaUtils --- src/StreamUtils.bsv | 128 +++++++++++++++++++++++++++++--------------- 1 file changed, 85 insertions(+), 43 deletions(-) diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv index 58b13d0..91c9b27 100755 --- a/src/StreamUtils.bsv +++ b/src/StreamUtils.bsv @@ -28,12 +28,74 @@ interface StreamSplit; endinterface function DataBytePtr convertByteEn2BytePtr (ByteEn byteEn); - ByteEn byteEnTemp = byteEn; DataBytePtr ptr = 0; - while (byteEnTemp > 0) begin - byteEnTemp = byteEnTemp >> 1; - ptr = ptr + 1; - end + case(byteEn) + 'h0000000000000001: ptr = 1; + 'h0000000000000003: ptr = 2; + 'h0000000000000007: ptr = 3; + 'h000000000000000F: ptr = 4; + 'h000000000000001F: ptr = 5; + 'h000000000000003F: ptr = 6; + 'h000000000000007F: ptr = 7; + 'h00000000000000FF: ptr = 8; + 'h00000000000001FF: ptr = 9; + 'h00000000000003FF: ptr = 10; + 'h00000000000007FF: ptr = 11; + 'h0000000000000FFF: ptr = 12; + 'h0000000000001FFF: ptr = 13; + 'h0000000000003FFF: ptr = 14; + 'h0000000000007FFF: ptr = 15; + 'h000000000000FFFF: ptr = 16; + 'h000000000001FFFF: ptr = 17; + 'h000000000003FFFF: ptr = 18; + 'h000000000007FFFF: ptr = 19; + 'h00000000000FFFFF: ptr = 20; + 'h00000000001FFFFF: ptr = 21; + 'h00000000003FFFFF: ptr = 22; + 'h00000000007FFFFF: ptr = 23; + 'h0000000000FFFFFF: ptr = 24; + 'h0000000001FFFFFF: ptr = 25; + 'h0000000003FFFFFF: ptr = 26; + 'h0000000007FFFFFF: ptr = 27; + 'h000000000FFFFFFF: ptr = 28; + 'h000000001FFFFFFF: ptr = 29; + 'h000000003FFFFFFF: ptr = 30; + 'h000000007FFFFFFF: ptr = 31; + 'h00000000FFFFFFFF: ptr = 32; + 'h00000001FFFFFFFF: ptr = 33; + 'h00000003FFFFFFFF: ptr = 34; + 'h00000007FFFFFFFF: ptr = 35; + 'h0000000FFFFFFFFF: ptr = 36; + 'h0000001FFFFFFFFF: ptr = 37; + 'h0000003FFFFFFFFF: ptr = 38; + 'h0000007FFFFFFFFF: ptr = 39; + 'h000000FFFFFFFFFF: ptr = 40; + 'h000001FFFFFFFFFF: ptr = 41; + 'h000003FFFFFFFFFF: ptr = 42; + 'h000007FFFFFFFFFF: ptr = 43; + 'h00000FFFFFFFFFFF: ptr = 44; + 'h00001FFFFFFFFFFF: ptr = 45; + 'h00003FFFFFFFFFFF: ptr = 46; + 'h00007FFFFFFFFFFF: ptr = 47; + 'h0000FFFFFFFFFFFF: ptr = 48; + 'h0001FFFFFFFFFFFF: ptr = 49; + 'h0003FFFFFFFFFFFF: ptr = 50; + 'h0007FFFFFFFFFFFF: ptr = 51; + 'h000FFFFFFFFFFFFF: ptr = 52; + 'h001FFFFFFFFFFFFF: ptr = 53; + 'h003FFFFFFFFFFFFF: ptr = 54; + 'h007FFFFFFFFFFFFF: ptr = 55; + 'h00FFFFFFFFFFFFFF: ptr = 56; + 'h01FFFFFFFFFFFFFF: ptr = 57; + 'h03FFFFFFFFFFFFFF: ptr = 58; + 'h07FFFFFFFFFFFFFF: ptr = 59; + 'h0FFFFFFFFFFFFFFF: ptr = 60; + 'h1FFFFFFFFFFFFFFF: ptr = 61; + 'h3FFFFFFFFFFFFFFF: ptr = 62; + 'h7FFFFFFFFFFFFFFF: ptr = 63; + 'hFFFFFFFFFFFFFFFF: ptr = 64; + default : ptr = 0; + endcase return ptr; endfunction @@ -55,7 +117,7 @@ function DataBytePtr getMaxBytePtr (); endfunction // Concat two DataStream frames into one. StreamA.isLast must be True, otherwise the function will return a empty frame to end the stream. -function ActionValue#(Tuple3#(DataStream, DataStream, DataBytePtr)) getConcatStream (DataStream streamA, DataStream streamB, DataBytePtr bytePtrA, DataBytePtr bytePtrB); +function Tuple3#(DataStream, DataStream, DataBytePtr) getConcatStream (DataStream streamA, DataStream streamB, DataBytePtr bytePtrA, DataBytePtr bytePtrB); Bool isCallLegally = (streamA.isLast && bytePtrA <= getMaxBytePtr() && bytePtrA > 0); DataBitPtr bitPtrA = zeroExtend(bytePtrA) << fromInteger(valueOf(BYTE_WIDTH_WIDTH)); @@ -87,33 +149,20 @@ function ActionValue#(Tuple3#(DataStream, DataStream, DataBytePtr)) getConcatStr // package the return concatStream and remainStream if(isCallLegally) begin - concatStream = DataStream{ - data: concatData, - byteEn: concatByteEn, + concatStream = DataStream { + data : concatData, + byteEn : concatByteEn, isFirst: streamA.isFirst, - isLast: isConcatStreamLast + isLast : isConcatStreamLast }; - remainStream = DataStream{ - data: remainData, - byteEn: remainByteEn, + remainStream = DataStream { + data : remainData, + byteEn : remainByteEn, isFirst: False, - isLast: True + isLast : True }; end - return ( - actionvalue - immAssert( - (streamA.isLast && bytePtrA <= getMaxBytePtr() && bytePtrA > 0), - "request check @ getConcatStream", - $format( - "bytePtrA=%d should in range of 1~%d", bytePtrA, getMaxBytePtr(), - "bytePtrB=%d should in range of 1~%d", bytePtrB, getMaxBytePtr(), - "streamA.isLast=", fshow(streamA.isLast), "should be False" - ) - ); - return tuple3(concatStream, remainStream, remainBytePtr); - endactionvalue - ); + return tuple3(concatStream, remainStream, remainBytePtr); endfunction (* synthesize *) @@ -164,7 +213,6 @@ module mkStreamConcat (StreamConcat ifc); hasRemainReg <= False; isStreamAEnd <= False; end - // StreamB or streamB + the remain data else if (prepareFifoB.notEmpty && isStreamAEnd) begin let streamB = prepareFifoB.first.stream; @@ -172,7 +220,7 @@ module mkStreamConcat (StreamConcat ifc); prepareFifoB.deq; streamB.isFirst = False; if (hasRemainReg) begin - match{.concatStream, .remainStream, .remainBytePtr} <- getConcatStream(remainStreamReg, streamB, remainBytePtrReg, bytePtrB); + let {concatStream, remainStream, remainBytePtr} = getConcatStream(remainStreamReg, streamB, remainBytePtrReg, bytePtrB); hasRemainReg <= unpack(remainStream.byteEn[0]); hasLastRemainReg <= streamB.isLast; remainStreamReg <= remainStream; @@ -184,7 +232,6 @@ module mkStreamConcat (StreamConcat ifc); end isStreamAEnd <= !streamB.isLast; end - // StreamA or StreamA + first StreamB else if (prepareFifoA.notEmpty) begin let streamA = prepareFifoA.first.stream; @@ -199,7 +246,7 @@ module mkStreamConcat (StreamConcat ifc); else if (streamA.isLast && prepareFifoB.notEmpty) begin let streamB = prepareFifoB.first.stream; let bytePtrB = prepareFifoB.first.bytePtr; - match{.concatStream, .remainStream, .remainBytePtr} <- getConcatStream(streamA, streamB, bytePtrA, bytePtrB); + let {concatStream, remainStream, remainBytePtr} = getConcatStream(streamA, streamB, bytePtrA, bytePtrB); hasRemainReg <= unpack(remainStream.byteEn[0]); hasLastRemainReg <= streamB.isLast; remainStreamReg <= remainStream; @@ -240,7 +287,7 @@ module mkStreamSplit(StreamSplit ifc); rule prepareStream; let stream = inputFifo.first; inputFifo.deq; - StreamWithPtr streamWithPtr = StreamWithPtr{ + StreamWithPtr streamWithPtr = StreamWithPtr { stream: stream, bytePtr: convertByteEn2BytePtr(stream.byteEn) }; @@ -279,50 +326,45 @@ module mkStreamSplit(StreamSplit ifc); hasRemainReg <= False; hasLastRemainReg <= False; end - else if (assertFifo.notEmpty && splitPtrFifo.notEmpty) begin let stream = assertFifo.first.stream; let frameBytePtr = assertFifo.first.bytePtr; - match {.truncateBytePtr, .resBytePtr} = splitPtrFifo.first; + let {truncateBytePtr, resBytePtr} = splitPtrFifo.first; assertFifo.deq; splitPtrFifo.deq; - // no operatation if (!hasRemainReg && truncateBytePtr == 0) begin outputFifo.enq(stream); end - // split the frame in this cycle to a last frame and a remain frame else if (!hasRemainReg && truncateBytePtr > 0) begin DataBitPtr truncateBitPtr = zeroExtend(truncateBytePtr) << valueOf(BYTE_WIDTH_WIDTH); DataBitPtr resBitPtr = zeroExtend(resBytePtr) << valueOf(BYTE_WIDTH_WIDTH); - outputFifo.enq(DataStream{ + outputFifo.enq(DataStream { data: (stream.data << resBitPtr) >> resBitPtr, byteEn: (stream.byteEn << resBytePtr) >> resBytePtr, isFirst: stream.isFirst, isLast: True }); - DataStream remainStream = DataStream{ + DataStream remainStream = DataStream { data: stream.data >> truncateBitPtr, byteEn: stream.byteEn >> truncateBytePtr, isFirst: True, isLast: True }; - hasRemainReg <= (remainStream.byteEn != 0); + hasRemainReg <= unpack(remainStream.byteEn[0]); hasLastRemainReg <= stream.isLast; remainBytePtrReg <= frameBytePtr - truncateBytePtr; remainStreamReg <= remainStream; end - // concat the new frame with the remainReg else if (hasRemainReg) begin - match {.concatStream, .remainStream, .remainBytePtr} <- getConcatStream(remainStreamReg, stream, remainBytePtrReg, frameBytePtr); + let {concatStream, remainStream, remainBytePtr} = getConcatStream(remainStreamReg, stream, remainBytePtrReg, frameBytePtr); outputFifo.enq(concatStream); hasRemainReg <= unpack(remainStream.byteEn[0]); hasLastRemainReg <= stream.isLast; remainStreamReg <= remainStream; remainBytePtrReg <= remainBytePtr; - end end endrule From 9fb805debbaaa299bf65b91ee0690cc7b42f67ea Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Tue, 16 Jul 2024 16:46:15 +0800 Subject: [PATCH 19/53] update PcieTypes --- src/PcieTypes.bsv | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv index 7e09d71..e617cfd 100755 --- a/src/PcieTypes.bsv +++ b/src/PcieTypes.bsv @@ -20,16 +20,20 @@ typedef 8 PCIE_TLP_FIRST_BE_WIDTH; typedef 8 PCIE_TLP_LAST_BE_WIDTH; typedef Bit#(PCIE_TLP_FIRST_BE_WIDTH) PcieTlpCtlFirstByteEn; typedef Bit#(PCIE_TLP_LAST_BE_WIDTH) PcieTlpCtlLastByteEn; + typedef PCIE_TDATA_BYTES PCIE_TLP_BYTE_EN_WIDTH; typedef Bit#(PCIE_TLP_BYTE_EN_WIDTH) PcieTlpCtlByteEn; + typedef 2 PCIE_TLP_ISSOP_WIDTH; typedef 2 PCIE_TLP_ISSOP_PTR_WIDTH; typedef Bit#(PCIE_TLP_ISSOP_WIDTH) PcieTlpCtlIsSop; typedef Bit#(PCIE_TLP_ISSOP_PTR_WIDTH) PcieTlpCtlIsSopPtr; + typedef 2 PCIE_TLP_ISEOP_WIDTH; typedef 4 PCIE_TLP_ISEOP_PTR_WIDTH; typedef Bit#(PCIE_TLP_ISEOP_WIDTH) PcieTlpCtlIsEop; typedef Bit#(PCIE_TLP_ISEOP_PTR_WIDTH) PcieTlpCtlIsEopPtr; + typedef 2 PCIE_TPH_PRESENT_WIDTH; typedef 4 PCIE_TPH_TYPE_WIDTH; typedef 16 PCIE_TPH_STTAG; @@ -38,22 +42,29 @@ typedef Bit#(PCIE_TPH_PRESENT_WIDTH) PcieTlpCtlTphPresent; typedef Bit#(PCIE_TPH_TYPE_WIDTH) PcieTlpCtlTphType; typedef Bit#(PCIE_TPH_STTAG) PcieTlpCtlTphSteeringTag; typedef Bit#(PCIE_TPH_INDIRECT_TAGEN_WIDTH) PcieTlpCtlTphIndirectTagEn; + typedef 64 PCIE_TLP_PARITY; typedef Bit#(PCIE_TLP_PARITY) PcieTlpCtlParity; + typedef 4 PCIE_TLP_ADDR_OFFSET_WIDTH; typedef Bit#(PCIE_TLP_ADDR_OFFSET_WIDTH) PcieTlpCtlAddrOffset; + typedef 6 PCIE_TLP_SEQ_NUM_WIDTH; typedef Bit#(PCIE_TLP_SEQ_NUM_WIDTH) PcieTlpCtlSeqNum; + typedef 4 PCIE_TLP_RC_ISSOP_WIDTH; typedef Bit#(PCIE_TLP_RC_ISSOP_WIDTH) PcieTlpCtlIsSopRC; + typedef 4 PCIE_TLP_RC_ISEOP_WIDTH; typedef Bit#(PCIE_TLP_RC_ISEOP_WIDTH) PcieTlpCtlIsEopRC; + // Signals the start of a new TLP, 6 bit. typedef struct { PcieTlpCtlIsSop isSop; PcieTlpCtlIsSopPtr isSopPtr0; PcieTlpCtlIsSopPtr isSopPtr1; } PcieTlpCtlIsSopCommon deriving(Bits, Bounded, Eq); + // Signals the start of a new TLP, 12 bit. typedef struct { PcieTlpCtlIsSopRC isSop; @@ -62,12 +73,14 @@ typedef struct { PcieTlpCtlIsSopPtr isSopPtr2; PcieTlpCtlIsSopPtr isSopPtr3; } PcieTlpCtlIsSopReqCpl deriving(Bits, Bounded, Eq); + // Indicates a TLP is ending in this beat, 10bit. typedef struct { PcieTlpCtlIsEop isEop; PcieTlpCtlIsEopPtr isEopPtr0; PcieTlpCtlIsEopPtr isEopPtr1; } PcieTlpCtlIsEopCommon deriving(Bits, Bounded, Eq); + // Indicates a TLP is ending in this beat, 20bit. typedef struct { PcieTlpCtlIsEopRC isEop; @@ -90,6 +103,7 @@ typedef struct { PcieTlpCtlTphSteeringTag tphSteeringTag; PcieTlpCtlParity parity; } PcieCompleterRequestSideBandFrame deriving(Bits, Bounded, Eq); + // 81bit tUser of PcieCompleterComplete AXIS-master typedef struct { PcieTlpCtlIsSopCommon isSop; @@ -97,6 +111,7 @@ typedef struct { Bool discontinue; PcieTlpCtlParity parity; } PcieCompleterCompleteSideBandFrame deriving(Bits, Bounded, Eq); + // 137bit tUser of PcieRequesterRequeste AXIS-master typedef struct { PcieTlpCtlFirstByteEn firstByteEn; @@ -113,6 +128,7 @@ typedef struct { PcieTlpCtlSeqNum seqNum1; PcieTlpCtlParity parity; } PcieRequsterRequestSideBandFrame deriving(Bits, Bounded, Eq); + // 161bit tUser of PcieRequesterComplete AXIS-slave typedef struct { PcieTlpCtlByteEn dataByteEn; @@ -127,14 +143,12 @@ typedef 2 PCIE_CR_NP_REQ_WIDTH; typedef 6 PCIE_CR_NP_REQ_COUNT_WIDTH; typedef Bit#(PCIE_CR_NP_REQ_WIDTH) PcieNonPostedRequst; typedef Bit#(PCIE_CR_NP_REQ_COUNT_WIDTH) PcieNonPostedRequstCount; + // Interface to PCIe IP Completer Interface (*always_ready, always_enabled*) interface RawPcieCompleter; // TODO: the AxiStream in blue-wrapper has tDataWidth = tKeepWidth * BYTE_WIDTH, but the PCIe IP has tDataWidth = tKeepWidth * DWORD_WIDTH (* prefix = "s_axis_cq_" *) interface RawAxiStreamSlave#(PCIE_TKEEP_WIDTH, PCIE_COMPLETER_REQUEST_TUSER_WIDTH) request; - // (* result = "pcie_cq_np_req" *) method PcieNonPostedRequst nonPostedReqCreditIncrement; - // (* prefix = "" *) method Action nonPostedReqCreditCnt( - // (* port = "pcie_cq_np_req_count" *) PcieNonPostedRequstCount ); (* prefix = "m_axis_cc_" *) interface RawAxiStreamMaster#(PCIE_TKEEP_WIDTH, PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) complete; endinterface @@ -149,6 +163,7 @@ typedef 10 PCIE_CFG_MGMT_ADDR_WIDTH; typedef 4 PCIE_CFG_MGMT_BE_WIDTH; typedef 8 PCIE_CFG_MGMT_FUNC_NUM_WIDTH; typedef 32 PCIE_CFG_MGMT_DATA_WIDTH; + typedef Bit#(PCIE_CFG_MGMT_ADDR_WIDTH) PcieCfgMgmtAddr; typedef Bit#(PCIE_CFG_MGMT_BE_WIDTH) PcieCfgMgmtByteEn; typedef Bit#(PCIE_CFG_MGMT_FUNC_NUM_WIDTH) PcieCfgMgmtFuncNum; @@ -208,6 +223,7 @@ typedef 1 PCIE_CFG_PHY_LINK_DOWN_WIDTH; typedef 2 PCIE_CFG_PHY_LINK_STATUS_WIDTH; typedef Bit#(PCIE_CFG_PHY_LINK_DOWN_WIDTH) PcieCfgPhyLinkDown; typedef Bit#(PCIE_CFG_PHY_LINK_STATUS_WIDTH) PcieCfgPhyLinkStatus; + typedef 3 PCIE_CFG_NEGOTIATED_WIDTH_WIDTH; typedef 3 PCIE_CFG_CURRENT_SPEED_WIDTH; typedef 2 PCIE_CFG_MAX_PAYLOAD_WIDTH; @@ -216,6 +232,7 @@ typedef Bit#(PCIE_CFG_NEGOTIATED_WIDTH_WIDTH) PcieCfgNegotiatedWidth; typedef Bit#(PCIE_CFG_CURRENT_SPEED_WIDTH) PCieCfgCurrentSpeed; typedef Bit#(PCIE_CFG_MAX_PAYLOAD_WIDTH) PcieCfgMaxPayloadSize; typedef Bit#(PCIE_CFG_MAX_READ_REQ_WIDTH) PCieCfgMaxReadReqSize; + typedef 16 PCIE_FUNCTIONS_STATUS_WIDTH; typedef Bit#(PCIE_FUNCTIONS_STATUS_WIDTH) PcieCfgFunctionStatus; From 0c9018d2d5aa86a8067e076305fb6347ae1ce3f8 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Sat, 20 Jul 2024 12:07:31 +0800 Subject: [PATCH 20/53] Add CompleterRequest --- img/StreamSplit.drawio.svg | 424 +++++++++++++++++++++++++++++++ img/chunkSplit.drawio.svg | 1 + img/dmac.drawio.svg | 494 ++++++++++++++++++++++++++++++++++++ img/streamConcat.drawio.svg | 1 + src/CompleterRequest.bsv | 92 +++++++ src/PcieAxiStreamTypes.bsv | 97 +++++++ src/PcieDescriptorTypes.bsv | 68 +++++ src/PcieTypes.bsv | 24 +- src/PrimUtils.bsv | 4 +- 9 files changed, 1198 insertions(+), 7 deletions(-) create mode 100644 img/StreamSplit.drawio.svg create mode 100644 img/chunkSplit.drawio.svg create mode 100644 img/dmac.drawio.svg create mode 100644 img/streamConcat.drawio.svg create mode 100644 src/CompleterRequest.bsv create mode 100644 src/PcieAxiStreamTypes.bsv create mode 100644 src/PcieDescriptorTypes.bsv diff --git a/img/StreamSplit.drawio.svg b/img/StreamSplit.drawio.svg new file mode 100644 index 0000000..4ae2123 --- /dev/null +++ b/img/StreamSplit.drawio.svg @@ -0,0 +1,424 @@ + + + + + + + + + + + + + InputFifo + + + + + + InputFifo + + + + + + + + + + + + + getFrameSize + + + + + + getFrameSize + + + + + + + + + + + + + assertSplit + + + + + + assertSplit + + + + + + + + + + + + + + + dataSplit + + + + + + dataSplit + + + + + + + + + + + + + remainStream + + + + + + remainStream + + + + + + + + + + + OutputFifo + + + + + + OutputFifo + + + + + + + + + + + is Split Location in this frame? + + + + + + is Split Location in this f... + + + + + + + + + + + + + DataStream + + + + + + DataStream + + + + + + + + + + + OutputFifo + + + + + + OutputFifo + + + + + + + + + + + + + Last + + + + + + Last + + + + + + + + + + + Remain + + + + + + Remain + + + + + + + + + + + OutputFifo + + + + + + OutputFifo + + + + + + + + + + + DataStream + + + + + + DataStream + + + + + + + + + + + Remain + + + + + + Remain + + + + + + + + + + + + + ConcatStream + + + + + + ConcatStream + + + + + + + + + + + Remain + + + + + + Remain + + + + + + + + + + + OutputFifo + + + + + + OutputFifo + + + + + + + + + + + ① + + + + + + ① + + + + + + + + + + + ② + + + + + + ② + + + + + + + + + + + ③ + + + + + + ③ + + + + + + + + + + + + + Remain + + + + + + Remain + + + + + + + + + + + OutputFifo + + + + + + OutputFifo + + + + + + + + + + + ④ + + + + + + ④ + + + + + + + + + Text is not SVG - cannot display + + + + \ No newline at end of file diff --git a/img/chunkSplit.drawio.svg b/img/chunkSplit.drawio.svg new file mode 100644 index 0000000..44d1e49 --- /dev/null +++ b/img/chunkSplit.drawio.svg @@ -0,0 +1 @@ +FifoInFifoIngetFirstChunkLengetFirstChunkLensplitFifosplitFifogenSplitChunksgenSplitChunksdmaRequeststartAddrlengthfirstChunkLendmaRequest...FifoOutFifoOutstartAddrlengthstartAddrlengthstartAddrlengthstartAddrlengthnewChunkPtrRegtotalLenRemainRegisSplittingRegnewChunkPtrRegtotalLenRemainRe...4KB4KB4KB4KB4KB4KBoffsetoffset512√512...512√512...512√512...firstChunkfirstChunk512√512...512×512...512×512...............Text is not SVG - cannot display \ No newline at end of file diff --git a/img/dmac.drawio.svg b/img/dmac.drawio.svg new file mode 100644 index 0000000..3d41f42 --- /dev/null +++ b/img/dmac.drawio.svg @@ -0,0 +1,494 @@ + + + + + + + + + + + + + Stream + + + + + + Stream + + + + + + + + + + + + + cntl + + + + + + cntl + + + + + + + + + + + + + + + ChunkCompute + + + + + + ChunkCompute + + + + + + + + + + + + + StreamSplit + + + + + + StreamSplit + + + + + + + + + + + + + TlpHeaderAdd + + + + + + TlpHeaderAdd + + + + + + + + + + + Stream + + + + + + Stream + + + + + + + + + + + + + cntl + + + + + + cntl + + + + + + + + + + + + + + + ChunkCompute + + + + + + ChunkCompute + + + + + + + + + + + + + TlpHeaderAdd + + + + + + TlpHeaderAdd + + + + + + + + + + + AXIS + + + + + + AXIS + + + + + + + + + + + + + RX engine + + + + + + RX engine + + + + + + + + + + + + + PreserveOder + + + + + + PreserveOder + + + + + + + + + + + + + TX engine + + + + + + TX engine + + + + + + + + + + + + + AXIS + + + + + + AXIS + + + + + + + + + + + + + StreamConcat + + + + + + StreamConcat + + + + + + + + + + + CSR + + Write + + + + + + CSR... + + + + + + + + + + + + + + + + + CsrFrameGen + + + + + + CsrFrameGen + + + + + + + + + + + + + AXIS + + + + + + AXIS + + + + + + + + + + + + + RX engine + + + + + + RX engine + + + + + + + + + + + CSR + + Read + + + + + + CSR... + + + + + + + + + + + + + CSR + + Read + + + + + + CSR... + + + + + + + + + + + + + TlpHeaderAdd + + + + + + TlpHeaderAdd + + + + + + + + + + + + + TX engine + + + + + + TX engine + + + + + + + + + + + AXIS + + + + + + AXIS + + + + + + + + + + + + + + + Configuration + + + + + + Configuration + + + + + + + + + Text is not SVG - cannot display + + + + \ No newline at end of file diff --git a/img/streamConcat.drawio.svg b/img/streamConcat.drawio.svg new file mode 100644 index 0000000..6901206 --- /dev/null +++ b/img/streamConcat.drawio.svg @@ -0,0 +1 @@ +stage1stage1stage1stage1outputoutputremainDataRegremainDataRegmuxmuxConcatConcatisFirstAisLastBisFirstBisLastBhasRemainisFirstA...getPtrgetPtrgetPtrgetPtrInputInputInputInputText is not SVG - cannot display \ No newline at end of file diff --git a/src/CompleterRequest.bsv b/src/CompleterRequest.bsv new file mode 100644 index 0000000..f009d4a --- /dev/null +++ b/src/CompleterRequest.bsv @@ -0,0 +1,92 @@ +import FIFO::*; + +import PcieAxiStreamTypes::*; +import PcieTypes::*; +import PcieDescriptorTypes::*; +import DmaTypes::*; + +typedef 1 MAX_DWORD_CNT_OF_CSR; +typedef 4'b1111 FIRST_BE_OF_CSR; + +typedef DmaCsrFrame CsrWriteReq; +typedef struct { + DmaCsrAddr rdAddr; + PcieCompleterRequestNonPostedStore npInfo; +} CsrReadReq; + +interface CompleterRequest; + interface RawPcieCompleterRequest rawCompleterComplete; + interface FifoOut#(DmaCsrFrame) csrWriteFifoOut; + interface FifoOut#(DmaCsrAddr) csrReadFifoOut; +endinterface + +interface CompleterRxEngine; + interface FifoIn#(PcieAxiStream) axiStreamFifoIn; + interface FifoOut#(CsrWriteReq) csrWriteFifoOut; + interface FifoOut#(CsrReadReq) csrReadFifoOut; +endinterface + + +// PcieCompleter does not support straddle mode now +// The completer is designed only for CSR Rd/Wr, and will ignore any len>32bit requests +module mkCompleterRxEngine; + FIFOF#(PcieAxiStream) inFifo <- mkFIFOF; + FIFOF#(CsrWriteReq) wrReqFifo <- mkFIFOF; + FIFOF#(CsrReadReq) rdReqFifo <- mkFIFOF; + + Reg#(Bool) isInPacket <- mkReg(False); + + Reg#(Uint#(32)) illegalPcieReqCntReg <- mkReg(0); + Reg#(BarId) barIdReg <- mkReg(0); + + function DmaCsrAddr getAddrFromCqDescriptor(PcieCompleterRequestDescriptor descriptor); + + endfunction + + function PcieCompleterRequestNonPostedStore convertDescriptorToNpStore(PcieCompleterRequestDescriptor descriptor); + + endfunction + + rule parseData; + inFifo.deq; + let axiStream = inFifo.first; + PcieCompleterRequestSideBandFrame sideBand = pack(axiStream.tUser); + isInPacket <= !unpack(axiStream.isLast); + if (!isInPacket) begin + PcieCompleterRequestDescriptor descriptor = pack(axiStream.tData[valueOf(CQ_DESCRIPTOR_WIDTH)-1:0]); + case (descriptor.reqType) begin + MEM_WRITE_REQ: begin + if (descriptor.dwordCnt <= valueOf(MAX_DWORD_CNT_OF_CSR) && sideBand.dataByteEn == 4'b1111) begin + DmaCsrValue wrValue = axiStream.tData[valueOf(DWORD_WIDTH)-1:0]; + DmaCsrAddr wrAddr = getAddrFromCqDescriptor(descriptor); + let wrReq = DmaCsrFrame { + address : wrAddr, + value : wrValue + } + wrReqFifo.enq(wrReq); + end + else begin + illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; + end + end + MEM_READ_REQ: begin + DmaCsrAddr rdAddr = getAddrFromCqDescriptor(descriptor); + let npInfo = PcieCompleterRequestNonPostedStore { + attributes: descriptor.attributes, + trafficClass: descriptor.trafficClass, + + } + end + default: illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; + end + + end + outFifo.enq(stream); + endrule +endmodule + + +module mkCompleterRequest; + + +endmodule diff --git a/src/PcieAxiStreamTypes.bsv b/src/PcieAxiStreamTypes.bsv new file mode 100644 index 0000000..b133c78 --- /dev/null +++ b/src/PcieAxiStreamTypes.bsv @@ -0,0 +1,97 @@ +import FIFOF :: *; +import GetPut :: *; +import PAClib :: *; + +import BusConversion :: *; +import SemiFifo :: *; + +typedef 8 BYTE_WIDTH; +typedef TMul#(2, BYTE_WIDTH) WORD_WIDTH; +typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; + +typedef 512 PCIE_AXIS_DATA_WIDTH; +typedef TDiv#(PCIE_AXIS_DATA_WIDTH, DWORD_WIDTH) PCIE_AXIS_KEEP_WIDTH; + +typedef struct { + Bit#(PCIE_AXIS_DATA_WIDTH) tData; + Bit#(PCIE_AXIS_KEEP_WIDTH) tKeep; + Bool tLast; + Bit#(usrWidth) tUser; +} PcieAxiStream#(numeric type usrWidth) deriving(Bits, FShow, Eq, Bounded); + +(*always_ready, always_enabled*) +interface RawPcieAxiStreamMaster#(numeric type usrWidth); + (* result = "tvalid" *) method Bool tValid; + (* result = "tdata" *) method Bit#(PCIE_AXIS_DATA_WIDTH) tData; + (* result = "tkeep" *) method Bit#(PCIE_AXIS_KEEP_WIDTH) tKeep; + (* result = "tlast" *) method Bool tLast; + (* result = "tuser" *) method Bit#(usrWidth) tUser; + (* always_enabled, prefix = "" *) method Action tReady((* port="tready" *) Bool ready); +endinterface + +(* always_ready, always_enabled *) +interface RawPcieAxiStreamSlave#(numeric type usrWidth); + (* prefix = "" *) + method Action tValid ( + (* port="tvalid" *) Bool tValid, + (* port="tdata" *) Bit#(PCIE_AXIS_DATA_WIDTH) tData, + (* port="tkeep" *) Bit#(PCIE_AXIS_KEEP_WIDTH) tKeep, + (* port="tlast" *) Bool tLast, + (* port="tuser" *) Bit#(usrWidth) tUser + ); + (* result="tready" *) method Bool tReady; +endinterface + +module mkFifoOutToRawPcieAxiStreamMaster#(FifoOut#(PcieAxiStream#(usrWidth)) pipe + )(RawPcieAxiStreamMaster#(usrWidth)); + let rawBus <- mkFifoOutToRawBusMaster(pipe); + return convertRawBusToRawPcieAxiStreamMaster(rawBus); +endmodule + +module mkFifoInToRawPcieAxiStreamSlave#(FifoIn#(PcieAxiStream#(usrWidth)) pipe + )(RawPcieAxiStreamSlave#(usrWidth)); + let rawBus <- mkFifoInToRawBusSlave(pipe); + return convertRawBusToRawPcieAxiStreamSlave(rawBus); +endmodule + +function RawPcieAxiStreamMaster#(usrWidth) convertRawBusToRawPcieAxiStreamMaster( + RawBusMaster#(PcieAxiStream#(usrWidth)) rawBus +); + return ( + interface RawPcieAxiStreamMaster; + method Bool tValid = rawBus.valid; + method Bit#(PCIE_AXIS_DATA_WIDTH) tData = rawBus.data.tData; + method Bit#(PCIE_AXIS_KEEP_WIDTH) tKeep = rawBus.data.tKeep; + method Bool tLast = rawBus.data.tLast; + method Bit#(usrWidth) tUser = rawBus.data.tUser; + method Action tReady(Bool rdy); + rawBus.ready(rdy); + endmethod + endinterface + ); +endfunction + +function RawPcieAxiStreamSlave#(usrWidth) convertRawBusToRawPcieAxiStreamSlave( + RawBusSlave#(PcieAxiStream#(usrWidth)) rawBus + ); + return ( + interface RawPcieAxiStreamSlave; + method Bool tReady = rawBus.ready; + method Action tValid( + Bool valid, + Bit#(PCIE_AXIS_DATA_WIDTH) tData, + Bit#(PCIE_AXIS_KEEP_WIDTH) tKeep, + Bool tLast, + Bit#(usrWidth) tUser + ); + PcieAxiStream#(usrWidth) axiStream = PcieAxiStream { + tData: tData, + tKeep: tKeep, + tLast: tLast, + tUser: tUser + }; + rawBus.validData(valid, axiStream); + endmethod + endinterface + ); +endfunction \ No newline at end of file diff --git a/src/PcieDescriptorTypes.bsv b/src/PcieDescriptorTypes.bsv new file mode 100644 index 0000000..9762b67 --- /dev/null +++ b/src/PcieDescriptorTypes.bsv @@ -0,0 +1,68 @@ + +import PcieAxiStreamTypes::*; + +typedef 64 RQ_DESCRIPTOR_WIDTH; +typedef TDiv#(TSub#(PCIE_AXIS_DATA_WIDTH, RQ_DESCRIPTOR_WIDTH), DWORD_WIDTH) MAX_DWORD_CNT_OF_FIRST; + +typedef Bit#(1) ReserveBit1; + +typedef 64 CQ_DESCRIPTOR_WIDTH; +typedef 3 ATTR_WIDTH; +typedef 3 TC_WIDTH; +typedef 6 BAR_APERTURE_WIDTH; +typedef 3 BAR_ID_WIDTH; +typedef 8 TARGET_FUNCTION_WIDTH; +typedef 8 TAG_WIDTH; +typedef 16 BDF_WIDTH; +typedef 4 REQ_TYPE_WIDTH; +typedef 11 DWORD_COUNT_WIDTH; +typedef 62 ADDR_WIDTH; + +typedef Bit#(ATTR_WIDTH) Attributes; +typedef Bit#(TC_WIDTH) TrafficClass; +typedef Bit#(BAR_APERTURE_WIDTH) BarAperture; +typedef Bit#(BAR_ID_WIDTH) BarId; +typedef Bit#(TARGET_FUNCTION_WIDTH) TargetFunction; +typedef Bit#(TAG_WIDTH) Tag; +typedef Bit#(BDF_WIDTH) BusDeviceFunc; +typedef Bit#(REQ_TYPE_WIDTH) ReqType; +typedef Bit#(DWORD_COUNT_WIDTH) DwordCount; +typedef Bit#(ADDR_WIDTH) Address; + +// 16bytes Completer Request Descriptor Format for Memory, I/O, and Atomic Options +typedef struct { + ReserveBit1 reserve0; + Attributes attributes; + TrafficClass trafficClass; + BarAperture barAperture; + BarId barId; + TargetFunction targetFunction; + Tag tag; + BusDeviceFunc requesterId; + ReserveBit1 reserve1; + ReqType reqType; + DwordCount dwordCnt; + Address address; +} PcieCompleterRequestDescriptor deriving(Bits, Eq, Bounded, FShow); + +typedef struct { + Attributes attributes; + TrafficClass trafficClass; + Tag tag; + BusDeviceFunc requesterId; +} PcieCompleterRequestNonPostedStore deriving(Bits, Eq, Bounded, FShow); + + + +// Pcie Tlp types of descriptor +typedef 4'b0000 MEM_READ_REQ; +typedef 4'b0001 MEM_WRITE_REQ; +typedef 4'b0010 IO_READ_REQ; +typedef 4'b0011 IO_WRITE_REQ; +typedef 4'b0100 MEM_FETCHADD_REQ; +typedef 4'b0101 MEM_UNCOND_SWAP_REQ; +typedef 4'b0110 MEM_COMP_SWAP_REQ; +typedef 4'b0111 LOCK_READ_REQ; // allowed only in legacy devices +typedef 4'b1100 COMMON_MESG; +typedef 4'b1101 VENDOR_DEF_MESG; +typedef 4'b1110 ATS_MESG; diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv index e617cfd..b374ad3 100755 --- a/src/PcieTypes.bsv +++ b/src/PcieTypes.bsv @@ -1,4 +1,4 @@ -import AxiStreamTypes::*; +import PcieAxiStreamTypes::*; typedef 512 PCIE_TLP_BYTES; @@ -15,6 +15,7 @@ typedef 81 PCIE_COMPLETER_COMPLETE_TUSER_WIDTH; typedef 137 PCIE_REQUESTER_REQUEST_TUSER_WIDTH; typedef 161 PCIE_REQUESTER_COMPLETE_TUSER_WIDTH; + // PcieTlpCtl**: SideBand Signals delivered in tUser defined by PG213 typedef 8 PCIE_TLP_FIRST_BE_WIDTH; typedef 8 PCIE_TLP_LAST_BE_WIDTH; @@ -139,6 +140,7 @@ typedef struct { } PcieRequesterCompleteSideBandFrame deriving(Bits, Bounded, Eq); +// PCIe raw interfaces typedef 2 PCIE_CR_NP_REQ_WIDTH; typedef 6 PCIE_CR_NP_REQ_COUNT_WIDTH; typedef Bit#(PCIE_CR_NP_REQ_WIDTH) PcieNonPostedRequst; @@ -146,10 +148,17 @@ typedef Bit#(PCIE_CR_NP_REQ_COUNT_WIDTH) PcieNonPostedRequstCount; // Interface to PCIe IP Completer Interface (*always_ready, always_enabled*) -interface RawPcieCompleter; - // TODO: the AxiStream in blue-wrapper has tDataWidth = tKeepWidth * BYTE_WIDTH, but the PCIe IP has tDataWidth = tKeepWidth * DWORD_WIDTH - (* prefix = "s_axis_cq_" *) interface RawAxiStreamSlave#(PCIE_TKEEP_WIDTH, PCIE_COMPLETER_REQUEST_TUSER_WIDTH) request; - (* prefix = "m_axis_cc_" *) interface RawAxiStreamMaster#(PCIE_TKEEP_WIDTH, PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) complete; +interface RawPcieCompleterRequest; + (* prefix = "s_axis_cq_" *) interface RawPcieAxiStreamSlave#(PCIE_COMPLETER_REQUEST_TUSER_WIDTH) rawAxiStreamSlave; + (* result = "pcie_cq_np_req" *) method PcieNonPostedRequst nonPostedReqCreditIncrement; + (* prefix = "" *) method Action nonPostedReqCreditCnt( + (* port = "pcie_cq_np_req_count" *) PcieNonPostedRequstCount ); + method +endinterface + +(*always_ready, always_enabled*) +interface RawPcieCompleterComplete; + (* prefix = "m_axis_cc_" *) interface RawAxiStreamMaster#(PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) rawAxiStreamMaster; endinterface // Interface to PCIe IP Requester Interface @@ -159,6 +168,8 @@ interface RawPcieRequester; (* prefix = "s_axis_rc_" *) interface RawAxiStreamSlave#(PCIE_TKEEP_WIDTH, usrWidth) complete; endinterface + +// Pcie Configuration Interfaces typedef 10 PCIE_CFG_MGMT_ADDR_WIDTH; typedef 4 PCIE_CFG_MGMT_BE_WIDTH; typedef 8 PCIE_CFG_MGMT_FUNC_NUM_WIDTH; @@ -263,4 +274,5 @@ interface RawPcieConfiguration; (* prefix = "cfg_msg_received_" *) interface RawPcieCfgMsgRx msgRx; (* prefix = "" *) interface RawPcieCfgStatus status; (* prefix = "pcie_tfc_" *) interface RawPcieCfgTransmitFC txFlowControl; -endinterface \ No newline at end of file +endinterface + diff --git a/src/PrimUtils.bsv b/src/PrimUtils.bsv index 6919aae..169f6ba 100644 --- a/src/PrimUtils.bsv +++ b/src/PrimUtils.bsv @@ -12,4 +12,6 @@ function Action immAssert(Bool condition, String assertName, Fmt assertFmtMsg); $finish(1); end endaction -endfunction \ No newline at end of file +endfunction + +function t getLowBytes(t data, tPtr aperture) provisos(Bits#(t, tSz), ) \ No newline at end of file From ddc177a23bf93245e9a5687de10cf5d473f1c03d Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Sat, 20 Jul 2024 13:05:22 +0800 Subject: [PATCH 21/53] Fix Types --- src/DmaTypes.bsv | 2 +- src/PcieTypes.bsv | 87 +++++++++++++++++++++------------------------ src/PrimUtils.bsv | 74 +++++++++++++++++++++++++++++++++++++- src/StreamUtils.bsv | 8 ++--- 4 files changed, 118 insertions(+), 53 deletions(-) diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index 59d4ec2..f6af719 100755 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -20,7 +20,7 @@ typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; typedef 2 CONCAT_STREAM_NUM; typedef TDiv#(DATA_WIDTH, BYTE_WIDTH) BYTE_EN_WIDTH; -typedef 'hFFFFFFFFFFFFFFFF MAX_BYTE_EN; +typedef -1 MAX_BYTE_EN; typedef Bit#(DATA_WIDTH) Data; typedef Bit#(BYTE_EN_WIDTH) ByteEn; diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv index b374ad3..7cf68d8 100755 --- a/src/PcieTypes.bsv +++ b/src/PcieTypes.bsv @@ -1,5 +1,6 @@ -import PcieAxiStreamTypes::*; +import Vector::*; +import PcieAxiStreamTypes::*; typedef 512 PCIE_TLP_BYTES; typedef TLog#(PCIE_TLP_BYTES) PCIE_TLP_BYTES_WIDTH; @@ -9,6 +10,7 @@ typedef 64 PCIE_TDATA_BYTES; typedef 16 PCIE_TDATA_DWORDS; // Indicate DWORD valid of tDATA typedef PCIE_TDATA_DWORDS PCIE_TKEEP_WIDTH; + // tUser width vary among RR, RC, CR and CC typedef 183 PCIE_COMPLETER_REQUEST_TUSER_WIDTH; typedef 81 PCIE_COMPLETER_COMPLETE_TUSER_WIDTH; @@ -61,82 +63,74 @@ typedef Bit#(PCIE_TLP_RC_ISEOP_WIDTH) PcieTlpCtlIsEopRC; // Signals the start of a new TLP, 6 bit. typedef struct { + Vector#(PCIE_TLP_ISSOP_WIDTH, PcieTlpCtlIsSopPtr) isSopPtrs; PcieTlpCtlIsSop isSop; - PcieTlpCtlIsSopPtr isSopPtr0; - PcieTlpCtlIsSopPtr isSopPtr1; } PcieTlpCtlIsSopCommon deriving(Bits, Bounded, Eq); // Signals the start of a new TLP, 12 bit. typedef struct { + Vector#(PCIE_TLP_RC_ISSOP_WIDTH, PcieTlpCtlIsSopPtr) isSopPtrs; PcieTlpCtlIsSopRC isSop; - PcieTlpCtlIsSopPtr isSopPtr0; - PcieTlpCtlIsSopPtr isSopPtr1; - PcieTlpCtlIsSopPtr isSopPtr2; - PcieTlpCtlIsSopPtr isSopPtr3; } PcieTlpCtlIsSopReqCpl deriving(Bits, Bounded, Eq); // Indicates a TLP is ending in this beat, 10bit. typedef struct { + Vector#(PCIE_TLP_ISEOP_WIDTH, PcieTlpCtlIsEopPtr) isEopPtrs; PcieTlpCtlIsEop isEop; - PcieTlpCtlIsEopPtr isEopPtr0; - PcieTlpCtlIsEopPtr isEopPtr1; } PcieTlpCtlIsEopCommon deriving(Bits, Bounded, Eq); // Indicates a TLP is ending in this beat, 20bit. typedef struct { + Vector#(PCIE_TLP_RC_ISEOP_WIDTH, PcieTlpCtlIsEopPtr) isEopPtrs; PcieTlpCtlIsEopRC isEop; - PcieTlpCtlIsEopPtr isEopPtr0; - PcieTlpCtlIsEopPtr isEopPtr1; - PcieTlpCtlIsEopPtr isEopPtr2; - PcieTlpCtlIsEopPtr isEopPtr3; } PcieTlpCtlIsEopReqCpl deriving(Bits, Bounded, Eq); // 183bit tUser of PcieCompleterRequeste AXIS-slave typedef struct { - PcieTlpCtlFirstByteEn firstByteEn; - PcieTlpCtlLastByteEn lastByteEn; - PcieTlpCtlByteEn dataByteEn; - PcieTlpCtlIsSopCommon isSop; - PcieTlpCtlIsEopCommon isEop; - Bool discontinue; - PcieTlpCtlTphPresent tphPresent; - PcieTlpCtlTphType tphType; - PcieTlpCtlTphSteeringTag tphSteeringTag; PcieTlpCtlParity parity; + PcieTlpCtlTphSteeringTag tphSteeringTag; + PcieTlpCtlTphType tphType; + PcieTlpCtlTphPresent tphPresent; + Bool discontinue; + PcieTlpCtlIsEopCommon isEop; + PcieTlpCtlIsSopCommon isSop; + PcieTlpCtlByteEn dataByteEn; + PcieTlpCtlLastByteEn lastByteEn; + PcieTlpCtlFirstByteEn firstByteEn; } PcieCompleterRequestSideBandFrame deriving(Bits, Bounded, Eq); // 81bit tUser of PcieCompleterComplete AXIS-master typedef struct { - PcieTlpCtlIsSopCommon isSop; - PcieTlpCtlIsEopCommon isEop; - Bool discontinue; PcieTlpCtlParity parity; + Bool discontinue; + PcieTlpCtlIsEopCommon isEop; + PcieTlpCtlIsSopCommon isSop; } PcieCompleterCompleteSideBandFrame deriving(Bits, Bounded, Eq); // 137bit tUser of PcieRequesterRequeste AXIS-master typedef struct { - PcieTlpCtlFirstByteEn firstByteEn; - PcieTlpCtlLastByteEn lastByteEn; - PcieTlpCtlAddrOffset addrOffset; - PcieTlpCtlIsSopCommon isSop; - PcieTlpCtlIsEopCommon isEop; - Bool discontinue; - PcieTlpCtlTphPresent tphPresent; - PcieTlpCtlTphType tphType; - PcieTlpCtlTphIndirectTagEn tphIndirectTagEn; - PcieTlpCtlTphSteeringTag tphSteeringTag; - PcieTlpCtlSeqNum seqNum0; - PcieTlpCtlSeqNum seqNum1; PcieTlpCtlParity parity; + PcieTlpCtlSeqNum seqNum1; + PcieTlpCtlSeqNum seqNum0; + PcieTlpCtlTphSteeringTag tphSteeringTag; + PcieTlpCtlTphIndirectTagEn tphIndirectTagEn; + PcieTlpCtlTphType tphType; + PcieTlpCtlTphPresent tphPresent; + Bool discontinue; + PcieTlpCtlIsEopCommon isEop; + PcieTlpCtlIsSopCommon isSop; + PcieTlpCtlAddrOffset addrOffset; + PcieTlpCtlLastByteEn lastByteEn; + PcieTlpCtlFirstByteEn firstByteEn; } PcieRequsterRequestSideBandFrame deriving(Bits, Bounded, Eq); // 161bit tUser of PcieRequesterComplete AXIS-slave typedef struct { - PcieTlpCtlByteEn dataByteEn; - PcieTlpCtlIsSopReqCpl isSop; - PcieTlpCtlIsEopReqCpl isEop; - Bool discontinue; - PcieTlpCtlParity parity; +PcieTlpCtlParity parity; +Bool discontinue; +PcieTlpCtlIsEopReqCpl isEop; +PcieTlpCtlIsSopReqCpl isSop; +PcieTlpCtlByteEn dataByteEn; } PcieRequesterCompleteSideBandFrame deriving(Bits, Bounded, Eq); @@ -152,20 +146,19 @@ interface RawPcieCompleterRequest; (* prefix = "s_axis_cq_" *) interface RawPcieAxiStreamSlave#(PCIE_COMPLETER_REQUEST_TUSER_WIDTH) rawAxiStreamSlave; (* result = "pcie_cq_np_req" *) method PcieNonPostedRequst nonPostedReqCreditIncrement; (* prefix = "" *) method Action nonPostedReqCreditCnt( - (* port = "pcie_cq_np_req_count" *) PcieNonPostedRequstCount ); - method + (* port = "pcie_cq_np_req_count" *) PcieNonPostedRequstCount nonPostedpReqCount ); endinterface (*always_ready, always_enabled*) interface RawPcieCompleterComplete; - (* prefix = "m_axis_cc_" *) interface RawAxiStreamMaster#(PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) rawAxiStreamMaster; + (* prefix = "m_axis_cc_" *) interface RawPcieAxiStreamMaster#(PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) rawAxiStreamMaster; endinterface // Interface to PCIe IP Requester Interface (*always_ready, always_enabled*) interface RawPcieRequester; - (* prefix = "m_axis_rq_" *) interface RawAxiStreamMaster#(PCIE_TKEEP_WIDTH, usrWidth) request; - (* prefix = "s_axis_rc_" *) interface RawAxiStreamSlave#(PCIE_TKEEP_WIDTH, usrWidth) complete; + (* prefix = "m_axis_rq_" *) interface RawPcieAxiStreamMaster#(PCIE_REQUESTER_REQUEST_TUSER_WIDTH) request; + (* prefix = "s_axis_rc_" *) interface RawPcieAxiStreamSlave#(PCIE_REQUESTER_COMPLETE_TUSER_WIDTH) complete; endinterface diff --git a/src/PrimUtils.bsv b/src/PrimUtils.bsv index 169f6ba..8ba0863 100644 --- a/src/PrimUtils.bsv +++ b/src/PrimUtils.bsv @@ -1,5 +1,7 @@ import FIFO::*; +import PcieAxiStreamTypes::*; + function Action immAssert(Bool condition, String assertName, Fmt assertFmtMsg); action let pos = printPosition(getStringPosition(assertName)); @@ -14,4 +16,74 @@ function Action immAssert(Bool condition, String assertName, Fmt assertFmtMsg); endaction endfunction -function t getLowBytes(t data, tPtr aperture) provisos(Bits#(t, tSz), ) \ No newline at end of file +function Bit#(n) getLowBytes(Bit#(n) data, Bit#(TLog#(TDiv#(n, BYTE_WIDTH))) ptr); + let temp = data; + case(ptr) + 1 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 2 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 3 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 4 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 5 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 6 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 7 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 8 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 9 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 10: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 11: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 12: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 13: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 14: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 15: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 16: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 17: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 18: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 19: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 20: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 21: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 22: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 23: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 24: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 25: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 26: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 27: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 28: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 29: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 30: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 31: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 32: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 33: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 34: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 35: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 36: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 37: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 38: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 39: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 40: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 41: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 42: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 43: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 44: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 45: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 46: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 47: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 48: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 49: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 50: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 51: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 52: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 53: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 54: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 55: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 56: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 57: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 58: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 59: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 60: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 61: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 62: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 63: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 64: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + default: temp = 0; + endcase + return temp; +endfunction diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv index 91c9b27..78cc3d3 100755 --- a/src/StreamUtils.bsv +++ b/src/StreamUtils.bsv @@ -118,7 +118,7 @@ endfunction // Concat two DataStream frames into one. StreamA.isLast must be True, otherwise the function will return a empty frame to end the stream. function Tuple3#(DataStream, DataStream, DataBytePtr) getConcatStream (DataStream streamA, DataStream streamB, DataBytePtr bytePtrA, DataBytePtr bytePtrB); - Bool isCallLegally = (streamA.isLast && bytePtrA <= getMaxBytePtr() && bytePtrA > 0); + Bool isCallLegally = (streamA.isLast && bytePtrA <= getMaxBytePtr && bytePtrA > 0); DataBitPtr bitPtrA = zeroExtend(bytePtrA) << fromInteger(valueOf(BYTE_WIDTH_WIDTH)); // Fill the low PtrA bytes by streamA data @@ -132,8 +132,8 @@ function Tuple3#(DataStream, DataStream, DataBytePtr) getConcatStream (DataStrea ByteEn concatByteEn = concatByteEnA | concatByteEnB; // Get the remain bytes of streamB data - DataBitPtr resBitPtr = getMaxBitPtr() - bitPtrA; - DataBytePtr resBytePtr = getMaxBytePtr() - bytePtrA; + DataBitPtr resBitPtr = getMaxBitPtr - bitPtrA; + DataBytePtr resBytePtr = getMaxBytePtr - bytePtrA; Data remainData = streamB.data >> resBitPtr; ByteEn remainByteEn = streamB.byteEn >> resBytePtr; @@ -302,7 +302,7 @@ module mkStreamSplit(StreamSplit ifc); if (!isSplitted && unpack(zeroExtend(bytePtr)) + streamByteCntReg >= splitLocation) begin truncateBytePtr = truncate(pack(splitLocation - streamByteCntReg)); end - DataBytePtr resBytePtr = getMaxBytePtr() - truncateBytePtr; + DataBytePtr resBytePtr = getMaxBytePtr - truncateBytePtr; splitPtrFifo.enq(tuple2(truncateBytePtr, resBytePtr)); if (truncateBytePtr > 0 && !stream.isLast) begin isSplitted <= True; From c7d7d77bb3a403b84adf6135a865e14b8a31722d Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Sat, 20 Jul 2024 18:03:41 +0800 Subject: [PATCH 22/53] Add PcieCompleter --- img/dmac.drawio.svg | 494 ------------------------------------ src/CompleterRequest.bsv | 92 ------- src/DmaTypes.bsv | 1 - src/PcieCompleter.bsv | 173 +++++++++++++ src/PcieDescriptorTypes.bsv | 43 ++-- src/PrimUtils.bsv | 312 ++++++++++++++++++----- src/StreamUtils.bsv | 18 +- 7 files changed, 451 insertions(+), 682 deletions(-) delete mode 100644 img/dmac.drawio.svg delete mode 100644 src/CompleterRequest.bsv create mode 100644 src/PcieCompleter.bsv diff --git a/img/dmac.drawio.svg b/img/dmac.drawio.svg deleted file mode 100644 index 3d41f42..0000000 --- a/img/dmac.drawio.svg +++ /dev/null @@ -1,494 +0,0 @@ - - - - - - - - - - - - - Stream - - - - - - Stream - - - - - - - - - - - - - cntl - - - - - - cntl - - - - - - - - - - - - - - - ChunkCompute - - - - - - ChunkCompute - - - - - - - - - - - - - StreamSplit - - - - - - StreamSplit - - - - - - - - - - - - - TlpHeaderAdd - - - - - - TlpHeaderAdd - - - - - - - - - - - Stream - - - - - - Stream - - - - - - - - - - - - - cntl - - - - - - cntl - - - - - - - - - - - - - - - ChunkCompute - - - - - - ChunkCompute - - - - - - - - - - - - - TlpHeaderAdd - - - - - - TlpHeaderAdd - - - - - - - - - - - AXIS - - - - - - AXIS - - - - - - - - - - - - - RX engine - - - - - - RX engine - - - - - - - - - - - - - PreserveOder - - - - - - PreserveOder - - - - - - - - - - - - - TX engine - - - - - - TX engine - - - - - - - - - - - - - AXIS - - - - - - AXIS - - - - - - - - - - - - - StreamConcat - - - - - - StreamConcat - - - - - - - - - - - CSR - - Write - - - - - - CSR... - - - - - - - - - - - - - - - - - CsrFrameGen - - - - - - CsrFrameGen - - - - - - - - - - - - - AXIS - - - - - - AXIS - - - - - - - - - - - - - RX engine - - - - - - RX engine - - - - - - - - - - - CSR - - Read - - - - - - CSR... - - - - - - - - - - - - - CSR - - Read - - - - - - CSR... - - - - - - - - - - - - - TlpHeaderAdd - - - - - - TlpHeaderAdd - - - - - - - - - - - - - TX engine - - - - - - TX engine - - - - - - - - - - - AXIS - - - - - - AXIS - - - - - - - - - - - - - - - Configuration - - - - - - Configuration - - - - - - - - - Text is not SVG - cannot display - - - - \ No newline at end of file diff --git a/src/CompleterRequest.bsv b/src/CompleterRequest.bsv deleted file mode 100644 index f009d4a..0000000 --- a/src/CompleterRequest.bsv +++ /dev/null @@ -1,92 +0,0 @@ -import FIFO::*; - -import PcieAxiStreamTypes::*; -import PcieTypes::*; -import PcieDescriptorTypes::*; -import DmaTypes::*; - -typedef 1 MAX_DWORD_CNT_OF_CSR; -typedef 4'b1111 FIRST_BE_OF_CSR; - -typedef DmaCsrFrame CsrWriteReq; -typedef struct { - DmaCsrAddr rdAddr; - PcieCompleterRequestNonPostedStore npInfo; -} CsrReadReq; - -interface CompleterRequest; - interface RawPcieCompleterRequest rawCompleterComplete; - interface FifoOut#(DmaCsrFrame) csrWriteFifoOut; - interface FifoOut#(DmaCsrAddr) csrReadFifoOut; -endinterface - -interface CompleterRxEngine; - interface FifoIn#(PcieAxiStream) axiStreamFifoIn; - interface FifoOut#(CsrWriteReq) csrWriteFifoOut; - interface FifoOut#(CsrReadReq) csrReadFifoOut; -endinterface - - -// PcieCompleter does not support straddle mode now -// The completer is designed only for CSR Rd/Wr, and will ignore any len>32bit requests -module mkCompleterRxEngine; - FIFOF#(PcieAxiStream) inFifo <- mkFIFOF; - FIFOF#(CsrWriteReq) wrReqFifo <- mkFIFOF; - FIFOF#(CsrReadReq) rdReqFifo <- mkFIFOF; - - Reg#(Bool) isInPacket <- mkReg(False); - - Reg#(Uint#(32)) illegalPcieReqCntReg <- mkReg(0); - Reg#(BarId) barIdReg <- mkReg(0); - - function DmaCsrAddr getAddrFromCqDescriptor(PcieCompleterRequestDescriptor descriptor); - - endfunction - - function PcieCompleterRequestNonPostedStore convertDescriptorToNpStore(PcieCompleterRequestDescriptor descriptor); - - endfunction - - rule parseData; - inFifo.deq; - let axiStream = inFifo.first; - PcieCompleterRequestSideBandFrame sideBand = pack(axiStream.tUser); - isInPacket <= !unpack(axiStream.isLast); - if (!isInPacket) begin - PcieCompleterRequestDescriptor descriptor = pack(axiStream.tData[valueOf(CQ_DESCRIPTOR_WIDTH)-1:0]); - case (descriptor.reqType) begin - MEM_WRITE_REQ: begin - if (descriptor.dwordCnt <= valueOf(MAX_DWORD_CNT_OF_CSR) && sideBand.dataByteEn == 4'b1111) begin - DmaCsrValue wrValue = axiStream.tData[valueOf(DWORD_WIDTH)-1:0]; - DmaCsrAddr wrAddr = getAddrFromCqDescriptor(descriptor); - let wrReq = DmaCsrFrame { - address : wrAddr, - value : wrValue - } - wrReqFifo.enq(wrReq); - end - else begin - illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; - end - end - MEM_READ_REQ: begin - DmaCsrAddr rdAddr = getAddrFromCqDescriptor(descriptor); - let npInfo = PcieCompleterRequestNonPostedStore { - attributes: descriptor.attributes, - trafficClass: descriptor.trafficClass, - - } - end - default: illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; - end - - end - outFifo.enq(stream); - endrule -endmodule - - -module mkCompleterRequest; - - -endmodule diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index f6af719..66c5b44 100755 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -20,7 +20,6 @@ typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; typedef 2 CONCAT_STREAM_NUM; typedef TDiv#(DATA_WIDTH, BYTE_WIDTH) BYTE_EN_WIDTH; -typedef -1 MAX_BYTE_EN; typedef Bit#(DATA_WIDTH) Data; typedef Bit#(BYTE_EN_WIDTH) ByteEn; diff --git a/src/PcieCompleter.bsv b/src/PcieCompleter.bsv new file mode 100644 index 0000000..0288abb --- /dev/null +++ b/src/PcieCompleter.bsv @@ -0,0 +1,173 @@ +import FIFO::*; + +import PcieAxiStreamTypes::*; +import PcieTypes::*; +import PcieDescriptorTypes::*; +import DmaTypes::*; + +typedef 1 IDEA_DWORD_CNT_OF_CSR; +typedef 10 CMPL_NPREQ_INFLIGHT_NUM; +typedef 20 CMPL_NPREQ_WAITING_CLKS; + +typedef DmaCsrFrame CsrWriteReq; +typedef DmaCsrFrame CsrReadResp; +typedef struct { + DmaCsrAddr rdAddr; + PcieCompleterRequestNonPostedStore npInfo; +} CsrReadReq; + +interface Completer; + interface RawPcieCompleterRequest rawCompleterRequest; + interface RawPcieCompleterComplete rawCompleterComplete; + interface FifoOut#(DmaCsrFrame) csrWriteReqFifoOut; + interface FifoIn#(DmaCsrFrame) csrReadRespFifoIn; + interface FifoOut#(DmaCsrAddr) csrReadReqFifoOut; + method DmaCsrValue getRegisterValue(DmaCsrAddr addr); +endinterface + +interface CompleterRequest; + interface FifoIn#(PcieAxiStream) axiStreamFifoIn; + interface FifoOut#(CsrWriteReq) csrWriteReqFifoOut; + interface FifoOut#(CsrReadReq) csrReadReqFifoOut; +endinterface + +interface CompleterComplete; + interface FifoOut#(PcieAxiStream) axiStreamFifoOut; + interface FifoIn#(CsrReadResp) csrReadRespFifoIn; + interface FifoIn#(CsrReadReq) csrReadReqFifoIn; +endinterface + +// PcieCompleter does not support straddle mode now +// The completer is designed only for CSR Rd/Wr, and will ignore any len>32bit requests +(* synthesize *) +module mkCompleterRequest(CompleterRequest); + FIFOF#(PcieAxiStream) inFifo <- mkFIFOF; + FIFOF#(CsrWriteReq) wrReqFifo <- mkFIFOF; + FIFOF#(CsrReadReq) rdReqFifo <- mkFIFOF; + + Reg#(Bool) isInPacket <- mkReg(False); + Reg#(Uint#(32)) illegalPcieReqCntReg <- mkReg(0); + + function PcieCompleterRequestDescriptor getDescriptorFromFirstBeat(PcieAxiStream axiStream); + return pack(axiStream.tDATA[valueOf(CQ_DESCRIPTOR_WIDTH)-1:0]); + endfunction + + function Data getDataFromFirstBeat(PcieAxiStream axiStream); + return axiStream.tData >> valueOf(CQ_DESCRIPTOR_WIDTH); + endfunction + + function Bool isFirstBytesAllValid(PcieCompleterCompleteSideBandFrame sideBand); + return (sideBand.firstByteEn[valueOf(PCIE_TLP_FIRST_BE_WIDTH)-1] == 1); + endfunction + + function DmaCsrAddr getAddrFromCqDescriptor(PcieCompleterRequestDescriptor descriptor); + let addr = getAddrLowBits(zeroExtend(descriptor.address), descriptor.barAperture); + // Only support one BAR now, no operation + if (descriptor.barId == 0) begin + addr = addr; + end + else begin + addr = 0; + end + return truncate(addr); + endfunction + + function PcieCompleterRequestNonPostedStore convertDescriptorToNpStore(PcieCompleterRequestDescriptor descriptor); + return PcieCompleterRequestNonPostedStore { + attributes : descriptor.attributes, + trafficClass: descriptor.trafficClass, + tag : descriptor.tag, + requesterId : descriptor.requesterId + }; + endfunction + + rule parseData; + inFifo.deq; + let axiStream = inFifo.first; + PcieCompleterRequestSideBandFrame sideBand = pack(axiStream.tUser); + isInPacket <= !axiStream.isLast; + if (!isInPacket) begin + let descriptor = getDescriptorFromFirstBeat(axiStream); + case (descriptor.reqType) begin + MEM_WRITE_REQ: begin + if (descriptor.dwordCnt == valueOf(IDEA_DWORD_CNT_OF_CSR) && isFirstBytesAllValid) begin + DmaCsrValue wrValue = getDataFromFirstBeat(axiStream)[valueOf(DMA_CSR_ADDR_WIDTH)-1:0]; + DmaCsrAddr wrAddr = getAddrFromCqDescriptor(descriptor); + let wrReq = CsrWriteReq { + address : wrAddr, + value : wrValue + } + wrReqFifo.enq(wrReq); + end + else begin + illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; + end + end + MEM_READ_REQ: begin + let rdReqAddr = getAddrFromCqDescriptor(descriptor); + let npInfo = convertDescriptorToNpStore(descriptor); + let rdReq = CsrReadReq{ + rdAddr: rdReqAddr, + npInfo: npInfo + } + rdReqFifo.enq(rdReq); + end + default: illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; + end + end + outFifo.enq(stream); + endrule + + interface axiStreamFifoIn = convertFifoToFifoIn(inFifo); + interface csrWriteReqFifoOut = convertFifoToFifoOut(wrReqFifo); + interface csrReadReqFifoOut = convertFifoToFifoOut(rdReqFifo); +endmodule + +(* synthesize *) +module mkCompleterComplete(CompleterComplete); + FIFOF#(PcieAxiStream) outFifo <- mkFIFOF; + FIFOF#(CsrReadResp) rdRespFifo <- mkFIFOF; + FIFOF#(CsrReadReq) rdReqFifo <- mkFIFOF; + + // TODO: the logic of cc + + interface axiStreamFifoOut = convertFifoToFifoOut(outFifo); + interface csrReadRespFifoIn = convertFifoToFifoIn(rdRespFifo); + interface csrWriteReqFifoOut = convertFifoToFifoIn(rdReqFifo); +endmodule + +(* synthesize *) +module mkCompleter(Completer); + CompleterRequest cmplRequest = mkCompleterRequest; + CompleterComplete cmplComplete = mkCompleterComplete; + + FIFOF#(csrReadResp) csrRdRespFifo <- mkFIFOF; + FIFOF#(csrReadReq) csrRdReqOutFifo <- mkFIFOF; + FIFOF#(csrReadReq) csrRdReqWaitingFifo <- mkSizedFIFOF(CMPL_NPREQ_INFLIGHT_NUM); + + Reg#(PcieNonPostedRequstCount) npReqCreditCntReg <- mkReg(0); + + interface RawPcieCompleterRequest; + interface rawAxiStreamSlave = mkFifoInToRawPcieAxiStreamSlave#(cmplRequest.axiStreamFifoIn); + // TODO: back-pressure according to the temperory stored RdReq Num + method PcieNonPostedRequst nonPostedReqCreditIncrement = 2'b11; + method Action nonPostedReqCreditCnt(PcieNonPostedRequstCount nonPostedpReqCount); + npReqCreditCntReg <= nonPostedpReqCount; + endmethod + endinterface + + interface RawPcieCompleterComplete; + interface rawAxiStreamSlave = mkFifoOutToRawPcieAxiStreamMaster#(cmplComplete.axiStreamFifoOut); + endinterface + + interface csrWriteReqFifoOut = cmplRequest.csrWriteReqFifoOut; + + interface csrReadReqFifoOut = convertFifoToFifoOut(csrRdReqOutFifo); + interface csrReadRespFifoIn = convertFifoToFifoIn(csrRdRespFifo); + + // TODO: get internal registers value + method DmaCsrValue getRegisterValue(DmaCsrAddr addr); + return 0; + method + +endmodule diff --git a/src/PcieDescriptorTypes.bsv b/src/PcieDescriptorTypes.bsv index 9762b67..2537159 100644 --- a/src/PcieDescriptorTypes.bsv +++ b/src/PcieDescriptorTypes.bsv @@ -6,28 +6,28 @@ typedef TDiv#(TSub#(PCIE_AXIS_DATA_WIDTH, RQ_DESCRIPTOR_WIDTH), DWORD_WIDTH) MAX typedef Bit#(1) ReserveBit1; -typedef 64 CQ_DESCRIPTOR_WIDTH; -typedef 3 ATTR_WIDTH; -typedef 3 TC_WIDTH; -typedef 6 BAR_APERTURE_WIDTH; -typedef 3 BAR_ID_WIDTH; -typedef 8 TARGET_FUNCTION_WIDTH; -typedef 8 TAG_WIDTH; -typedef 16 BDF_WIDTH; -typedef 4 REQ_TYPE_WIDTH; -typedef 11 DWORD_COUNT_WIDTH; -typedef 62 ADDR_WIDTH; +typedef 64 DES_CQ_DESCRIPTOR_WIDTH; +typedef 3 DES_ATTR_WIDTH; +typedef 3 DES_TC_WIDTH; +typedef 6 DES_BAR_APERTURE_WIDTH; +typedef 3 DES_BAR_ID_WIDTH; +typedef 8 DES_TARGET_FUNCTION_WIDTH; +typedef 8 DES_TAG_WIDTH; +typedef 16 DES_BDF_WIDTH; +typedef 4 DES_REQ_TYPE_WIDTH; +typedef 11 DES_DWORD_COUNT_WIDTH; +typedef 62 DES_ADDR_WIDTH; -typedef Bit#(ATTR_WIDTH) Attributes; -typedef Bit#(TC_WIDTH) TrafficClass; -typedef Bit#(BAR_APERTURE_WIDTH) BarAperture; -typedef Bit#(BAR_ID_WIDTH) BarId; -typedef Bit#(TARGET_FUNCTION_WIDTH) TargetFunction; -typedef Bit#(TAG_WIDTH) Tag; -typedef Bit#(BDF_WIDTH) BusDeviceFunc; -typedef Bit#(REQ_TYPE_WIDTH) ReqType; -typedef Bit#(DWORD_COUNT_WIDTH) DwordCount; -typedef Bit#(ADDR_WIDTH) Address; +typedef Bit#(DES_ATTR_WIDTH) Attributes; +typedef Bit#(DES_TC_WIDTH) TrafficClass; +typedef Bit#(DES_BAR_APERTURE_WIDTH) BarAperture; +typedef Bit#(DES_BAR_ID_WIDTH) BarId; +typedef Bit#(DES_TARGET_FUNCTION_WIDTH) TargetFunction; +typedef Bit#(DES_TAG_WIDTH) Tag; +typedef Bit#(DES_BDF_WIDTH) BusDeviceFunc; +typedef Bit#(DES_REQ_TYPE_WIDTH) ReqType; +typedef Bit#(DES_DWORD_COUNT_WIDTH) DwordCount; +typedef Bit#(DES_ADDR_WIDTH) Address; // 16bytes Completer Request Descriptor Format for Memory, I/O, and Atomic Options typedef struct { @@ -50,6 +50,7 @@ typedef struct { TrafficClass trafficClass; Tag tag; BusDeviceFunc requesterId; + DmaCsrAddr reqAddr; } PcieCompleterRequestNonPostedStore deriving(Bits, Eq, Bounded, FShow); diff --git a/src/PrimUtils.bsv b/src/PrimUtils.bsv index 8ba0863..fe768e8 100644 --- a/src/PrimUtils.bsv +++ b/src/PrimUtils.bsv @@ -1,6 +1,7 @@ -import FIFO::*; +import FIFOF::*; import PcieAxiStreamTypes::*; +import DmaTypes::*; function Action immAssert(Bool condition, String assertName, Fmt assertFmtMsg); action @@ -16,74 +17,251 @@ function Action immAssert(Bool condition, String assertName, Fmt assertFmtMsg); endaction endfunction -function Bit#(n) getLowBytes(Bit#(n) data, Bit#(TLog#(TDiv#(n, BYTE_WIDTH))) ptr); - let temp = data; +function Data getDataLowBytes(Data data, DataBytePtr ptr); + Data temp = 0; case(ptr) - 1 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 2 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 3 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 4 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 5 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 6 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 7 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 8 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 9 : temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 10: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 11: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 12: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 13: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 14: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 15: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 16: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 17: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 18: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 19: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 20: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 21: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 22: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 23: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 24: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 25: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 26: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 27: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 28: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 29: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 30: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 31: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 32: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 33: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 34: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 35: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 36: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 37: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 38: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 39: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 40: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 41: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 42: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 43: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 44: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 45: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 46: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 47: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 48: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 49: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 50: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 51: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 52: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 53: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 54: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 55: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 56: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 57: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 58: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 59: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 60: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 61: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 62: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 63: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; - 64: temp = data[valueOf(BYTE_WIDTH)*1-1:0]; + 1 : temp[valueOf(BYTE_WIDTH)*1 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*1 -1:0]); + 2 : temp[valueOf(BYTE_WIDTH)*2 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*2 -1:0]); + 3 : temp[valueOf(BYTE_WIDTH)*3 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*3 -1:0]); + 4 : temp[valueOf(BYTE_WIDTH)*4 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*4 -1:0]); + 5 : temp[valueOf(BYTE_WIDTH)*5 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*5 -1:0]); + 6 : temp[valueOf(BYTE_WIDTH)*6 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*6 -1:0]); + 7 : temp[valueOf(BYTE_WIDTH)*7 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*7 -1:0]); + 8 : temp[valueOf(BYTE_WIDTH)*8 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*8 -1:0]); + 9 : temp[valueOf(BYTE_WIDTH)*9 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*9 -1:0]); + 10: temp[valueOf(BYTE_WIDTH)*10-1:0] = Data'(data[valueOf(BYTE_WIDTH)*10-1:0]); + 11: temp[valueOf(BYTE_WIDTH)*11-1:0] = Data'(data[valueOf(BYTE_WIDTH)*11-1:0]); + 12: temp[valueOf(BYTE_WIDTH)*12-1:0] = Data'(data[valueOf(BYTE_WIDTH)*12-1:0]); + 13: temp[valueOf(BYTE_WIDTH)*13-1:0] = Data'(data[valueOf(BYTE_WIDTH)*13-1:0]); + 14: temp[valueOf(BYTE_WIDTH)*14-1:0] = Data'(data[valueOf(BYTE_WIDTH)*14-1:0]); + 15: temp[valueOf(BYTE_WIDTH)*15-1:0] = Data'(data[valueOf(BYTE_WIDTH)*15-1:0]); + 16: temp[valueOf(BYTE_WIDTH)*16-1:0] = Data'(data[valueOf(BYTE_WIDTH)*16-1:0]); + 17: temp[valueOf(BYTE_WIDTH)*17-1:0] = Data'(data[valueOf(BYTE_WIDTH)*17-1:0]); + 18: temp[valueOf(BYTE_WIDTH)*18-1:0] = Data'(data[valueOf(BYTE_WIDTH)*18-1:0]); + 19: temp[valueOf(BYTE_WIDTH)*19-1:0] = Data'(data[valueOf(BYTE_WIDTH)*19-1:0]); + 20: temp[valueOf(BYTE_WIDTH)*20-1:0] = Data'(data[valueOf(BYTE_WIDTH)*20-1:0]); + 21: temp[valueOf(BYTE_WIDTH)*21-1:0] = Data'(data[valueOf(BYTE_WIDTH)*21-1:0]); + 22: temp[valueOf(BYTE_WIDTH)*22-1:0] = Data'(data[valueOf(BYTE_WIDTH)*22-1:0]); + 23: temp[valueOf(BYTE_WIDTH)*23-1:0] = Data'(data[valueOf(BYTE_WIDTH)*23-1:0]); + 24: temp[valueOf(BYTE_WIDTH)*24-1:0] = Data'(data[valueOf(BYTE_WIDTH)*24-1:0]); + 25: temp[valueOf(BYTE_WIDTH)*25-1:0] = Data'(data[valueOf(BYTE_WIDTH)*25-1:0]); + 26: temp[valueOf(BYTE_WIDTH)*26-1:0] = Data'(data[valueOf(BYTE_WIDTH)*26-1:0]); + 27: temp[valueOf(BYTE_WIDTH)*27-1:0] = Data'(data[valueOf(BYTE_WIDTH)*27-1:0]); + 28: temp[valueOf(BYTE_WIDTH)*28-1:0] = Data'(data[valueOf(BYTE_WIDTH)*28-1:0]); + 29: temp[valueOf(BYTE_WIDTH)*29-1:0] = Data'(data[valueOf(BYTE_WIDTH)*29-1:0]); + 30: temp[valueOf(BYTE_WIDTH)*30-1:0] = Data'(data[valueOf(BYTE_WIDTH)*30-1:0]); + 31: temp[valueOf(BYTE_WIDTH)*31-1:0] = Data'(data[valueOf(BYTE_WIDTH)*31-1:0]); + 32: temp[valueOf(BYTE_WIDTH)*32-1:0] = Data'(data[valueOf(BYTE_WIDTH)*32-1:0]); + 33: temp[valueOf(BYTE_WIDTH)*33-1:0] = Data'(data[valueOf(BYTE_WIDTH)*33-1:0]); + 34: temp[valueOf(BYTE_WIDTH)*34-1:0] = Data'(data[valueOf(BYTE_WIDTH)*34-1:0]); + 35: temp[valueOf(BYTE_WIDTH)*35-1:0] = Data'(data[valueOf(BYTE_WIDTH)*35-1:0]); + 36: temp[valueOf(BYTE_WIDTH)*36-1:0] = Data'(data[valueOf(BYTE_WIDTH)*36-1:0]); + 37: temp[valueOf(BYTE_WIDTH)*37-1:0] = Data'(data[valueOf(BYTE_WIDTH)*37-1:0]); + 38: temp[valueOf(BYTE_WIDTH)*38-1:0] = Data'(data[valueOf(BYTE_WIDTH)*38-1:0]); + 39: temp[valueOf(BYTE_WIDTH)*39-1:0] = Data'(data[valueOf(BYTE_WIDTH)*39-1:0]); + 40: temp[valueOf(BYTE_WIDTH)*40-1:0] = Data'(data[valueOf(BYTE_WIDTH)*40-1:0]); + 41: temp[valueOf(BYTE_WIDTH)*41-1:0] = Data'(data[valueOf(BYTE_WIDTH)*41-1:0]); + 42: temp[valueOf(BYTE_WIDTH)*42-1:0] = Data'(data[valueOf(BYTE_WIDTH)*42-1:0]); + 43: temp[valueOf(BYTE_WIDTH)*43-1:0] = Data'(data[valueOf(BYTE_WIDTH)*43-1:0]); + 44: temp[valueOf(BYTE_WIDTH)*44-1:0] = Data'(data[valueOf(BYTE_WIDTH)*44-1:0]); + 45: temp[valueOf(BYTE_WIDTH)*45-1:0] = Data'(data[valueOf(BYTE_WIDTH)*45-1:0]); + 46: temp[valueOf(BYTE_WIDTH)*46-1:0] = Data'(data[valueOf(BYTE_WIDTH)*46-1:0]); + 47: temp[valueOf(BYTE_WIDTH)*47-1:0] = Data'(data[valueOf(BYTE_WIDTH)*47-1:0]); + 48: temp[valueOf(BYTE_WIDTH)*48-1:0] = Data'(data[valueOf(BYTE_WIDTH)*48-1:0]); + 49: temp[valueOf(BYTE_WIDTH)*49-1:0] = Data'(data[valueOf(BYTE_WIDTH)*49-1:0]); + 50: temp[valueOf(BYTE_WIDTH)*50-1:0] = Data'(data[valueOf(BYTE_WIDTH)*50-1:0]); + 51: temp[valueOf(BYTE_WIDTH)*51-1:0] = Data'(data[valueOf(BYTE_WIDTH)*51-1:0]); + 52: temp[valueOf(BYTE_WIDTH)*52-1:0] = Data'(data[valueOf(BYTE_WIDTH)*52-1:0]); + 53: temp[valueOf(BYTE_WIDTH)*53-1:0] = Data'(data[valueOf(BYTE_WIDTH)*53-1:0]); + 54: temp[valueOf(BYTE_WIDTH)*54-1:0] = Data'(data[valueOf(BYTE_WIDTH)*54-1:0]); + 55: temp[valueOf(BYTE_WIDTH)*55-1:0] = Data'(data[valueOf(BYTE_WIDTH)*55-1:0]); + 56: temp[valueOf(BYTE_WIDTH)*56-1:0] = Data'(data[valueOf(BYTE_WIDTH)*56-1:0]); + 57: temp[valueOf(BYTE_WIDTH)*57-1:0] = Data'(data[valueOf(BYTE_WIDTH)*57-1:0]); + 58: temp[valueOf(BYTE_WIDTH)*58-1:0] = Data'(data[valueOf(BYTE_WIDTH)*58-1:0]); + 59: temp[valueOf(BYTE_WIDTH)*59-1:0] = Data'(data[valueOf(BYTE_WIDTH)*59-1:0]); + 60: temp[valueOf(BYTE_WIDTH)*60-1:0] = Data'(data[valueOf(BYTE_WIDTH)*60-1:0]); + 61: temp[valueOf(BYTE_WIDTH)*61-1:0] = Data'(data[valueOf(BYTE_WIDTH)*61-1:0]); + 62: temp[valueOf(BYTE_WIDTH)*62-1:0] = Data'(data[valueOf(BYTE_WIDTH)*62-1:0]); + 63: temp[valueOf(BYTE_WIDTH)*63-1:0] = Data'(data[valueOf(BYTE_WIDTH)*63-1:0]); default: temp = 0; endcase return temp; endfunction + +function Data getDataHighBytes(Data data, DataBytePtr ptr); + Data temp = 0; + case(ptr) + 1 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*1 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*1 ]); + 2 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*2 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*2 ]); + 3 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*3 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*3 ]); + 4 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*4 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*4 ]); + 5 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*5 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*5 ]); + 6 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*6 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*6 ]); + 7 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*7 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*7 ]); + 8 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*8 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*8 ]); + 9 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*9 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*9 ]); + 10: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*10] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*10]); + 11: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*11] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*11]); + 12: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*12] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*12]); + 13: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*13] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*13]); + 14: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*14] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*14]); + 15: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*15] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*15]); + 16: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*16] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*16]); + 17: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*17] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*17]); + 18: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*18] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*18]); + 19: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*19] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*19]); + 20: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*20] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*20]); + 21: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*21] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*21]); + 22: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*22] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*22]); + 23: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*23] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*23]); + 24: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*24] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*24]); + 25: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*25] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*25]); + 26: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*26] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*26]); + 27: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*27] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*27]); + 28: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*28] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*28]); + 29: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*29] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*29]); + 30: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*30] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*30]); + 31: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*31] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*31]); + 32: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*32] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*32]); + 33: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*33] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*33]); + 34: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*34] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*34]); + 35: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*35] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*35]); + 36: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*36] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*36]); + 37: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*37] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*37]); + 38: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*38] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*38]); + 39: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*39] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*39]); + 40: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*40] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*40]); + 41: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*41] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*41]); + 42: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*42] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*42]); + 43: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*43] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*43]); + 44: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*44] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*44]); + 45: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*45] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*45]); + 46: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*46] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*46]); + 47: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*47] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*47]); + 48: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*48] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*48]); + 49: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*49] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*49]); + 50: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*50] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*50]); + 51: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*51] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*51]); + 52: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*52] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*52]); + 53: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*53] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*53]); + 54: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*54] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*54]); + 55: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*55] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*55]); + 56: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*56] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*56]); + 57: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*57] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*57]); + 58: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*58] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*58]); + 59: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*59] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*59]); + 60: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*60] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*60]); + 61: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*61] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*61]); + 62: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*62] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*62]); + 63: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*63] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*63]); + default: temp = data; + endcase + return temp; +endfunction + +function DmaMemAddr getAddrLowBits(DmaMemAddr addr, Bit#(TLog#(DMA_MEM_ADDR_WIDTH)) ptr); + DmaMemAddr temp = 0; + case(ptr) + 1 : temp[1 -1:0] = DmaMemAddr'(addr[1 -1:0]); + 2 : temp[2 -1:0] = DmaMemAddr'(addr[2 -1:0]); + 3 : temp[3 -1:0] = DmaMemAddr'(addr[3 -1:0]); + 4 : temp[4 -1:0] = DmaMemAddr'(addr[4 -1:0]); + 5 : temp[5 -1:0] = DmaMemAddr'(addr[5 -1:0]); + 6 : temp[6 -1:0] = DmaMemAddr'(addr[6 -1:0]); + 7 : temp[7 -1:0] = DmaMemAddr'(addr[7 -1:0]); + 8 : temp[8 -1:0] = DmaMemAddr'(addr[8 -1:0]); + 9 : temp[9 -1:0] = DmaMemAddr'(addr[9 -1:0]); + 10: temp[10-1:0] = DmaMemAddr'(addr[10-1:0]); + 11: temp[11-1:0] = DmaMemAddr'(addr[11-1:0]); + 12: temp[12-1:0] = DmaMemAddr'(addr[12-1:0]); + 13: temp[13-1:0] = DmaMemAddr'(addr[13-1:0]); + 14: temp[14-1:0] = DmaMemAddr'(addr[14-1:0]); + 15: temp[15-1:0] = DmaMemAddr'(addr[15-1:0]); + 16: temp[16-1:0] = DmaMemAddr'(addr[16-1:0]); + 17: temp[17-1:0] = DmaMemAddr'(addr[17-1:0]); + 18: temp[18-1:0] = DmaMemAddr'(addr[18-1:0]); + 19: temp[19-1:0] = DmaMemAddr'(addr[19-1:0]); + 20: temp[20-1:0] = DmaMemAddr'(addr[20-1:0]); + 21: temp[21-1:0] = DmaMemAddr'(addr[21-1:0]); + 22: temp[22-1:0] = DmaMemAddr'(addr[22-1:0]); + 23: temp[23-1:0] = DmaMemAddr'(addr[23-1:0]); + 24: temp[24-1:0] = DmaMemAddr'(addr[24-1:0]); + 25: temp[25-1:0] = DmaMemAddr'(addr[25-1:0]); + 26: temp[26-1:0] = DmaMemAddr'(addr[26-1:0]); + 27: temp[27-1:0] = DmaMemAddr'(addr[27-1:0]); + 28: temp[28-1:0] = DmaMemAddr'(addr[28-1:0]); + 29: temp[29-1:0] = DmaMemAddr'(addr[29-1:0]); + 30: temp[30-1:0] = DmaMemAddr'(addr[30-1:0]); + 31: temp[31-1:0] = DmaMemAddr'(addr[31-1:0]); + 32: temp[32-1:0] = DmaMemAddr'(addr[32-1:0]); + 33: temp[33-1:0] = DmaMemAddr'(addr[33-1:0]); + 34: temp[34-1:0] = DmaMemAddr'(addr[34-1:0]); + 35: temp[35-1:0] = DmaMemAddr'(addr[35-1:0]); + 36: temp[36-1:0] = DmaMemAddr'(addr[36-1:0]); + 37: temp[37-1:0] = DmaMemAddr'(addr[37-1:0]); + 38: temp[38-1:0] = DmaMemAddr'(addr[38-1:0]); + 39: temp[39-1:0] = DmaMemAddr'(addr[39-1:0]); + 40: temp[40-1:0] = DmaMemAddr'(addr[40-1:0]); + 41: temp[41-1:0] = DmaMemAddr'(addr[41-1:0]); + 42: temp[42-1:0] = DmaMemAddr'(addr[42-1:0]); + 43: temp[43-1:0] = DmaMemAddr'(addr[43-1:0]); + 44: temp[44-1:0] = DmaMemAddr'(addr[44-1:0]); + 45: temp[45-1:0] = DmaMemAddr'(addr[45-1:0]); + 46: temp[46-1:0] = DmaMemAddr'(addr[46-1:0]); + 47: temp[47-1:0] = DmaMemAddr'(addr[47-1:0]); + 48: temp[48-1:0] = DmaMemAddr'(addr[48-1:0]); + 49: temp[49-1:0] = DmaMemAddr'(addr[49-1:0]); + 50: temp[50-1:0] = DmaMemAddr'(addr[50-1:0]); + 51: temp[51-1:0] = DmaMemAddr'(addr[51-1:0]); + 52: temp[52-1:0] = DmaMemAddr'(addr[52-1:0]); + 53: temp[53-1:0] = DmaMemAddr'(addr[53-1:0]); + 54: temp[54-1:0] = DmaMemAddr'(addr[54-1:0]); + 55: temp[55-1:0] = DmaMemAddr'(addr[55-1:0]); + 56: temp[56-1:0] = DmaMemAddr'(addr[56-1:0]); + 57: temp[57-1:0] = DmaMemAddr'(addr[57-1:0]); + 58: temp[58-1:0] = DmaMemAddr'(addr[58-1:0]); + 59: temp[59-1:0] = DmaMemAddr'(addr[59-1:0]); + 60: temp[60-1:0] = DmaMemAddr'(addr[60-1:0]); + 61: temp[61-1:0] = DmaMemAddr'(addr[61-1:0]); + 62: temp[62-1:0] = DmaMemAddr'(addr[62-1:0]); + 63: temp[63-1:0] = DmaMemAddr'(addr[63-1:0]); + default: temp = 0; + endcase + return temp; +endfunction + +typedef 32 CNTFIFO_SIZE_WIDTH; +typedef UInt#(CNTFIFO_SIZE_WIDTH) FifoSize; + +interface CounteredFIFOF#(type t); + method Action enq (t x); + method Action deq; + method t first; + method Action clear; + method Bool notFull; + method Bool notEmpty; + method FifoSize getCurSize; +endinterface + +module mkCounteredFIFOF#(Integer depth)(CounteredFIFOF#(t)) provisos(Bits#(t, tSz)); + Reg#(FifoSize) curSize <- mkReg(0); + FIFOF#(t) fifo <- mkSizedFIFOF(depth); + + method Action enq (t x); + fifo.enq(x); + curSize <= curSize + 1; + endmethod + + method Action deq; + fifo.deq; + curSize <= curSize - 1; + endmethod + + method t first = fifo.first; + method Action clear = fifo.clear; + method Bool notFull = fifo.notFull; + method Bool notEmpty = fifo.notEmpty; + + method FifoSize getCurSize = curSize; +endmodule + diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv index 78cc3d3..e40addf 100755 --- a/src/StreamUtils.bsv +++ b/src/StreamUtils.bsv @@ -99,6 +99,10 @@ function DataBytePtr convertByteEn2BytePtr (ByteEn byteEn); return ptr; endfunction +function Bool isByteEnZero(ByteEn byteEn) begin + return !unpack(remainStream.byteEn[0]); +end + function DataStream getEmptyStream (); return DataStream{ data: 0, @@ -221,7 +225,7 @@ module mkStreamConcat (StreamConcat ifc); streamB.isFirst = False; if (hasRemainReg) begin let {concatStream, remainStream, remainBytePtr} = getConcatStream(remainStreamReg, streamB, remainBytePtrReg, bytePtrB); - hasRemainReg <= unpack(remainStream.byteEn[0]); + hasRemainReg <= !isByteEnZero(remainStream.byteEn); hasLastRemainReg <= streamB.isLast; remainStreamReg <= remainStream; remainBytePtrReg <= remainBytePtr; @@ -247,7 +251,7 @@ module mkStreamConcat (StreamConcat ifc); let streamB = prepareFifoB.first.stream; let bytePtrB = prepareFifoB.first.bytePtr; let {concatStream, remainStream, remainBytePtr} = getConcatStream(streamA, streamB, bytePtrA, bytePtrB); - hasRemainReg <= unpack(remainStream.byteEn[0]); + hasRemainReg <= !isByteEnZero(remainStream.byteEn); hasLastRemainReg <= streamB.isLast; remainStreamReg <= remainStream; remainBytePtrReg <= remainBytePtr; @@ -352,24 +356,24 @@ module mkStreamSplit(StreamSplit ifc); isFirst: True, isLast: True }; - hasRemainReg <= unpack(remainStream.byteEn[0]); + hasRemainReg <= !isByteEnZero(remainStream.byteEn); hasLastRemainReg <= stream.isLast; remainBytePtrReg <= frameBytePtr - truncateBytePtr; - remainStreamReg <= remainStream; + remainStreamReg <= remainStream; end // concat the new frame with the remainReg else if (hasRemainReg) begin let {concatStream, remainStream, remainBytePtr} = getConcatStream(remainStreamReg, stream, remainBytePtrReg, frameBytePtr); outputFifo.enq(concatStream); - hasRemainReg <= unpack(remainStream.byteEn[0]); + hasRemainReg <= !isByteEnZero(remainStream.byteEn); hasLastRemainReg <= stream.isLast; - remainStreamReg <= remainStream; + remainStreamReg <= remainStream; remainBytePtrReg <= remainBytePtr; end end endrule - interface inputStreamFifoIn = convertFifoToFifoIn(inputFifo); + interface inputStreamFifoIn = convertFifoToFifoIn(inputFifo); interface splitLocationFifoIn = convertFifoToFifoIn(splitLocationFifo); interface outputStreamFifoOut = convertFifoToFifoOut(outputFifo); From b70f57db6e7e65d450606340cbb8c076bcadc061 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Sun, 21 Jul 2024 14:48:06 +0800 Subject: [PATCH 23/53] Add CCDescriptor and modify interface --- img/completer.drawio.svg | 384 ++++++++++++++++++++++++++++++++++++ src/DmaController.bsv | 33 ++-- src/DmaRequestCore.bsv | 20 +- src/DmaTypes.bsv | 31 ++- src/PcieCompleter.bsv | 16 +- src/PcieDescriptorTypes.bsv | 38 ++++ test/TestDmaCore.bsv | 4 +- 7 files changed, 487 insertions(+), 39 deletions(-) create mode 100644 img/completer.drawio.svg diff --git a/img/completer.drawio.svg b/img/completer.drawio.svg new file mode 100644 index 0000000..f9f2ce6 --- /dev/null +++ b/img/completer.drawio.svg @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + rawPcieCompleterRequest + + + + + + rawPcieCompleterRequest + + + + + + + + + + + DataStream#(PcieAxiStream) + + + + + + DataStream#(PcieAxiStream) + + + + + + + + + + + + + DataStream#(CQSideBand) + + + + + + DataStream#(CQSideBand) + + + + + + + + + + + + + CsrWriteReq + + + + + + CsrWriteReq + + + + + + + + + + + + + CsrReadReq + + + + + + CsrReadReq + + + + + + + + + + + + + CQDescripter + + + + + + CQDescripter + + + + + + + + + + + CompleterRequest + + + + + + CompleterRequest + + + + + + + + + + + + + + + parse + + + + + + parse + + + + + + + + + + + + + + + CQDescripterFIFO + + + + + + CQDescripterFIFO + + + + + + + + + + + rawPcieCompleterComplete + + + + + + rawPcieCompleterComplete + + + + + + + + + + + DmaHostToCardWr + + + + + + DmaHostToCardWr + + + + + + + + + + + + + DmaHostToCardRd + + + + + + DmaHostToCardRd + + + + + + + + + + + + CompleterComplete + + + + + + CompleterComplete + + + + + + + + + + + DataStream#(PcieAxiStream) + + + + + + DataStream#(PcieAxiStream) + + + + + + + + + + + + + DataStream#(CCSideBand) + + + + + + DataStream#(CCSideBand) + + + + + + + + + + + + + generate + + + + + + generate + + + + + + + + + + + + + assert + + + + + + assert + + + + + + + + + + + + + CsrReadResp + + + + + + CsrReadResp + + + + + + + + + + + + CQ_credit + + + + + + CQ_credit + + + + + + + + + + + counter + + + + + + counter + + + + + + + + + Text is not SVG - cannot display + + + + \ No newline at end of file diff --git a/src/DmaController.bsv b/src/DmaController.bsv index 5d8df4b..db36cf0 100755 --- a/src/DmaController.bsv +++ b/src/DmaController.bsv @@ -1,24 +1,31 @@ +import FIFOF::*; + import PcieTypes::*; -import DmaTypes::*; +import DmaTypes::*; interface DmaController#(numeric type dataWidth); - - interface FifoIn#(DataStream) dataC2HPipeIn; - interface FifoIn#(DmaRequestFrame) reqC2HPipeIn; - interface FifoIn#(DmaRequestFrame) reqH2CPipeIn; - interface FifoOut#(DataStream) dataH2CPipeOut; - - interface FifoIn#(DmaCsrFrame) csrC2HPipeIn; - interface FifoOut#(DMACsrAddr) csrC2HPipeOut; // read reg in the card from Host - interface FifoOut#(DmaCsrFrame) csrH2CPipeOut; - + // Requester interfaces, where the Card serve as the Master + interface FifoIn#(DataStream) c2hDataFifoIn; // Card writes Host Memory + interface FifoIn#(DmaRequest) c2hReqFifoIn; // Card writes Host Memory + interface FifoIn#(DmaRequest) h2cReqFifoIn; // Card reads Host Memory + interface FifoOut#(DataStream) h2cDataFifoOut; // Card reads Host Memory + + // Completer interfaces, where the Card serve as the Slave + interface FifoIn#(DmaCsrFrame) c2hCsrValFifoIn; // Host reads Card Registers + interface FifoOut#(DMACsrAddr) c2hCsrReqFifoOut; // Host reads Card Registers + interface FifoOut#(DmaCsrFrame) h2cCsrValFifoOut; // Host writes Card Registers + + // Raw PCIe interfaces, connected to the Xilinx PCIe IP interface RawPcieRequester pcieRequester; interface RawPcieCompleter pcieCompleter; interface RawPcieConfiguration pcieConfig; - endinterface module mkDmaController#() (DmaController ifc); + FIFOF#(DataStream) c2hDataFifo <- mkFIFOF; + FIFOF#(DataStream) h2cDataFifo <- mkFIFOF; + FIFOF#(DmaRequest) c2hReqFifo <- mkFIFOF; + FIFOF#(DmaRequest) h2cReqFifo <- mkFIFOF; - + FIFOF#(DmaCsrFrame) endmodule \ No newline at end of file diff --git a/src/DmaRequestCore.bsv b/src/DmaRequestCore.bsv index 8c7df68..a712d09 100755 --- a/src/DmaRequestCore.bsv +++ b/src/DmaRequestCore.bsv @@ -19,20 +19,20 @@ typedef 3 PCIE_TLP_SIZE_SETTING_WIDTH; typedef Bit#(PCIE_TLP_SIZE_SETTING_WIDTH) PcieTlpSizeSetting; typedef struct { - DmaRequestFrame dmaRequest; + DmaRequest dmaRequest; DmaMemAddr firstChunkLen; } ChunkRequestFrame deriving(Bits, Eq); interface ChunkCompute; - interface FifoIn#(DmaRequestFrame) dmaRequestFifoIn; - interface FifoOut#(DmaRequestFrame) chunkRequestFifoOut; + interface FifoIn#(DmaRequest) dmaRequestFifoIn; + interface FifoOut#(DmaRequest) chunkRequestFifoOut; interface Put#(PcieTlpSizeSetting) setTlpMaxSize; endinterface module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); - FIFOF#(DmaRequestFrame) inputFifo <- mkFIFOF; - FIFOF#(DmaRequestFrame) outputFifo <- mkFIFOF; + FIFOF#(DmaRequest) inputFifo <- mkFIFOF; + FIFOF#(DmaRequest) outputFifo <- mkFIFOF; FIFOF#(ChunkRequestFrame) splitFifo <- mkFIFOF; Reg#(DmaMemAddr) newChunkPtrReg <- mkReg(0); @@ -42,13 +42,13 @@ module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); Reg#(DmaMemAddr) tlpMaxSize <- mkReg(fromInteger(valueOf(DEFAULT_TLP_SIZE))); Reg#(PcieTlpSizeWidth) tlpMaxSizeWidth <- mkReg(fromInteger(valueOf(DEFAULT_TLP_SIZE_WIDTH))); - function Bool hasBoundary(DmaRequestFrame request); + function Bool hasBoundary(DmaRequest request); let highIdx = (request.startAddr + request.length - 1) >> valueOf(BUS_BOUNDARY_WIDTH); let lowIdx = request.startAddr >> valueOf(BUS_BOUNDARY_WIDTH); return (highIdx > lowIdx); endfunction - function DmaMemAddr getOffset(DmaRequestFrame request); + function DmaMemAddr getOffset(DmaRequest request); // MPS - startAddr % MPS, MPS means MRRS when the module is set to RX mode DmaMemAddr remainderOfMps = zeroExtend(PcieTlpMaxMaxPayloadSize'(request.startAddr[tlpMaxSizeWidth-1:0])); DmaMemAddr offsetOfMps = tlpMaxSize - remainderOfMps; @@ -71,7 +71,7 @@ module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); if (isSplittingReg) begin // !isFirst if (totalLenRemainReg <= tlpMaxSize) begin isSplittingReg <= False; - outputFifo.enq(DmaRequestFrame { + outputFifo.enq(DmaRequest { startAddr: newChunkPtrReg, length: totalLenRemainReg }); @@ -80,7 +80,7 @@ module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); end else begin isSplittingReg <= True; - outputFifo.enq(DmaRequestFrame { + outputFifo.enq(DmaRequest { startAddr: newChunkPtrReg, length: tlpMaxSize }); @@ -92,7 +92,7 @@ module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); let remainderLength = splitRequest.dmaRequest.length - splitRequest.firstChunkLen; Bool isSplittingNextCycle = (remainderLength > 0); isSplittingReg <= isSplittingNextCycle; - outputFifo.enq(DmaRequestFrame { + outputFifo.enq(DmaRequest { startAddr: splitRequest.dmaRequest.startAddr, length: splitRequest.firstChunkLen }); diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index 66c5b44..5069eff 100755 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -29,12 +29,7 @@ typedef Bit#(TAdd#(1, TLog#(BYTE_EN_WIDTH))) DataBytePtr; typedef struct { DmaMemAddr startAddr; DmaMemAddr length; -} DmaRequestFrame deriving(Bits, Bounded, Eq); - -typedef struct { - DMACsrAddr address; - DMACsrValue value; -} DmaCsrFrame deriving(Bits, Bounded, Eq); +} DmaRequest deriving(Bits, Bounded, Eq); typedef enum { DMA_RX, @@ -48,8 +43,8 @@ typedef struct { Bool isLast; } DataStream deriving(Bits, Bounded, Eq); -instance FShow#(DmaRequestFrame); - function Fmt fshow(DmaRequestFrame request); +instance FShow#(DmaRequest); + function Fmt fshow(DmaRequest request); return ($format("> valueOf(BUS_BOUNDARY_WIDTH); let lowIdx = request.startAddr >> valueOf(BUS_BOUNDARY_WIDTH); return (highIdx > lowIdx); @@ -47,7 +47,7 @@ module mkChunkComputerTb(Empty); DmaMemAddr testLength <- lengthRandomVal.next; let testEnd = testAddr + testLength - 1; if (testEnd > testAddr && testEnd <= fromInteger(valueOf(MAX_ADDRESS))) begin - let request = DmaRequestFrame{ + let request = DmaRequest{ startAddr: testAddr, length: testLength }; From 31d1b0f1e44da224165ecceec65822092a519be6 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Sun, 21 Jul 2024 21:35:47 +0800 Subject: [PATCH 24/53] Update dmac interfaces --- src/{PcieCompleter.bsv => DmaCompleter.bsv} | 100 +++++++++++++------- src/DmaController.bsv | 41 ++++---- src/DmaRequester.bsv | 17 ++++ src/DmaTypes.bsv | 13 +-- src/PcieDescriptorTypes.bsv | 8 -- src/PcieTypes.bsv | 89 ++++++++++++++--- test/TestDmaCompleter.bsv | 0 7 files changed, 186 insertions(+), 82 deletions(-) rename src/{PcieCompleter.bsv => DmaCompleter.bsv} (64%) create mode 100644 src/DmaRequester.bsv create mode 100644 test/TestDmaCompleter.bsv diff --git a/src/PcieCompleter.bsv b/src/DmaCompleter.bsv similarity index 64% rename from src/PcieCompleter.bsv rename to src/DmaCompleter.bsv index 624e6eb..be69863 100644 --- a/src/PcieCompleter.bsv +++ b/src/DmaCompleter.bsv @@ -6,8 +6,10 @@ import PcieDescriptorTypes::*; import DmaTypes::*; typedef 1 IDEA_DWORD_CNT_OF_CSR; -typedef 10 CMPL_NPREQ_INFLIGHT_NUM; +typedef 64 CMPL_NPREQ_INFLIGHT_NUM; typedef 20 CMPL_NPREQ_WAITING_CLKS; +typedef 2'b11 NP_CREDIT_INCREMENT; +typedef 2'b00 NP_CREDIT_NOCHANGE; typedef struct { DmaCsrAddr addr; @@ -18,14 +20,14 @@ typedef DmaCsrValue CsrReadResp; typedef struct { DmaCsrAddr rdAddr; - PcieCompleterRequestNonPostedStore npInfo; + PcieCompleterRequestDescriptor npInfo; } CsrReadReq deriving(Bits, Eq, Bounded, FShow); -interface Completer; +interface DmaCompleter; interface RawPcieCompleterRequest rawCompleterRequest; interface RawPcieCompleterComplete rawCompleterComplete; - interface DmaHostToCardWrite h2cCsrWrite; - interface DmaHostToCardRead h2cCsrRead; + interface DmaHostToCardWrite h2cWrite; + interface DmaHostToCardRead h2cRead; method DmaCsrValue getRegisterValue(DmaCsrAddr addr); endinterface @@ -64,7 +66,7 @@ module mkCompleterRequest(CompleterRequest); return (sideBand.firstByteEn[valueOf(PCIE_TLP_FIRST_BE_WIDTH)-1] == 1); endfunction - function DmaCsrAddr getAddrFromCqDescriptor(PcieCompleterRequestDescriptor descriptor); + function DmaCsrAddr getCsrAddrFromCqDescriptor(PcieCompleterRequestDescriptor descriptor); let addr = getAddrLowBits(zeroExtend(descriptor.address), descriptor.barAperture); // Only support one BAR now, no operation if (descriptor.barId == 0) begin @@ -76,16 +78,7 @@ module mkCompleterRequest(CompleterRequest); return truncate(addr); endfunction - function PcieCompleterRequestNonPostedStore convertDescriptorToNpStore(PcieCompleterRequestDescriptor descriptor); - return PcieCompleterRequestNonPostedStore { - attributes : descriptor.attributes, - trafficClass: descriptor.trafficClass, - tag : descriptor.tag, - requesterId : descriptor.requesterId - }; - endfunction - - rule parseData; + rule parse; inFifo.deq; let axiStream = inFifo.first; PcieCompleterRequestSideBandFrame sideBand = pack(axiStream.tUser); @@ -95,8 +88,9 @@ module mkCompleterRequest(CompleterRequest); case (descriptor.reqType) begin MEM_WRITE_REQ: begin if (descriptor.dwordCnt == valueOf(IDEA_DWORD_CNT_OF_CSR) && isFirstBytesAllValid) begin - DmaCsrValue wrValue = getDataFromFirstBeat(axiStream)[valueOf(DMA_CSR_ADDR_WIDTH)-1:0]; - DmaCsrAddr wrAddr = getAddrFromCqDescriptor(descriptor); + let firstData = getDataFromFirstBeat(axiStream); + DmaCsrValue wrValue = firstData[valueOf(DMA_CSR_ADDR_WIDTH)-1:0]; + DmaCsrAddr wrAddr = getCsrAddrFromCqDescriptor(descriptor); let wrReq = CsrWriteReq { address : wrAddr, value : wrValue @@ -108,18 +102,16 @@ module mkCompleterRequest(CompleterRequest); end end MEM_READ_REQ: begin - let rdReqAddr = getAddrFromCqDescriptor(descriptor); - let npInfo = convertDescriptorToNpStore(descriptor); + let rdReqAddr = getCsrAddrFromCqDescriptor(descriptor); let rdReq = CsrReadReq{ rdAddr: rdReqAddr, - npInfo: npInfo + npInfo: descriptor } rdReqFifo.enq(rdReq); end default: illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; end end - outFifo.enq(stream); endrule interface axiStreamFifoIn = convertFifoToFifoIn(inFifo); @@ -137,37 +129,75 @@ module mkCompleterComplete(CompleterComplete); interface axiStreamFifoOut = convertFifoToFifoOut(outFifo); interface csrReadRespFifoIn = convertFifoToFifoIn(rdRespFifo); - interface csrWriteReqFifoOut = convertFifoToFifoIn(rdReqFifo); + interface csrReadReqFifoOut = convertFifoToFifoIn(rdReqFifo); endmodule (* synthesize *) -module mkCompleter(Completer); +module mkDmaCompleter(DmaCompleter); CompleterRequest cmplRequest = mkCompleterRequest; CompleterComplete cmplComplete = mkCompleterComplete; - FIFOF#(csrReadResp) csrRdRespFifo <- mkFIFOF; - FIFOF#(csrReadReq) csrRdReqOutFifo <- mkFIFOF; - FIFOF#(csrReadReq) csrRdReqWaitingFifo <- mkSizedFIFOF(CMPL_NPREQ_INFLIGHT_NUM); + FIFOF#(DmaCsrValue) h2cCsrWriteDataFifo <- mkFIFOF; + FIFOF#(DmaCsrAddr) h2cCsrWriteReqFifo <- mkFIFOF; + FIFOF#(DmaCsrAddr) h2cCsrReadReqFifo <- mkFIFOF; + FIFOF#(DmaCsrValue) h2cCsrReadDataFifo <- mkFIFOF; + CounteredFIFOF#(csrReadReq) csrRdReqStoreFifo <- mkCounteredFIFOF(CMPL_NPREQ_INFLIGHT_NUM); + Reg#(PcieNonPostedRequst) npReqCreditCtrlReg <- mkReg(valueOf(NP_CREDIT_INCREMENT)); Reg#(PcieNonPostedRequstCount) npReqCreditCntReg <- mkReg(0); - interface RawPcieCompleterRequest; + + rule genCsrWriteReq; + let wrReq = cmplRequest.csrWriteReqFifoOut.first; + cmplRequest.csrWriteReqFifoOut.deq; + h2cCsrWriteDataFifo.enq(wrReq.value); + h2cCsrWriteReqFifo.enq(wrReq.addr); + endrule + + rule genCsrReadReq; + let rdReq = cmplRequest.csrReadReqFifoOut.first; + cmplRequest.csrReadReqFifoOut.deq; + h2cCsrReadReqFifo.enq(rdReq.rdAddr); + csrRdReqStoreFifo.enq(rdReq); + endrule + + rule procCsrReadResp; + let req = csrRdReqStoreFifo.first; + let resp = h2cCsrReadDataFifo.first; + cmplComplete.csrReadRespFifoIn(resp); + cmplComplete.csrReadReqFifoIn(req); + endrule + + rule npBackPressure; + if (csrRdReqDescriptorFifo.getCurSize == fromInteger(valueOf(TDiv#(CMPL_NPREQ_INFLIGHT_NUM,2)))) begin + npReqCreditCtrlReg <= valueOf(NP_CREDIT_NOCHANGE); + end + else begin + npReqCreditCtrlReg <= valueOf(NP_CREDIT_INCREMENT); + end + endrule + + interface rawCompleterRequest; interface rawAxiStreamSlave = mkFifoInToRawPcieAxiStreamSlave#(cmplRequest.axiStreamFifoIn); - // TODO: back-pressure according to the temperory stored RdReq Num - method PcieNonPostedRequst nonPostedReqCreditIncrement = 2'b11; + method PcieNonPostedRequst nonPostedReqCreditIncrement = npReqCreditCtrlReg; method Action nonPostedReqCreditCnt(PcieNonPostedRequstCount nonPostedpReqCount); npReqCreditCntReg <= nonPostedpReqCount; endmethod endinterface - interface RawPcieCompleterComplete; + interface rawCompleterComplete; interface rawAxiStreamSlave = mkFifoOutToRawPcieAxiStreamMaster#(cmplComplete.axiStreamFifoOut); endinterface - interface csrWriteReqFifoOut = cmplRequest.csrWriteReqFifoOut; + interface h2cWrite; + interface dataFifoOut = convertFifoToFifoOut(h2cCsrWriteDataFifo); + interface reqFifoOut = convertFifoToFifoOut(h2cCsrWriteReqFifo); + endinterface - interface csrReadReqFifoOut = convertFifoToFifoOut(csrRdReqOutFifo); - interface csrReadRespFifoIn = convertFifoToFifoIn(csrRdRespFifo); + interface h2cRead; + interface reqFifoOut = convertFifoToFifoOut(h2cCsrReadReqFifo); + interface dataFifoIn = convertFifoToFifoIn(h2cCsrReadDataFifo); + endinterface // TODO: get internal registers value method DmaCsrValue getRegisterValue(DmaCsrAddr addr); @@ -175,3 +205,5 @@ module mkCompleter(Completer); method endmodule + +module mkWriteReqTo \ No newline at end of file diff --git a/src/DmaController.bsv b/src/DmaController.bsv index db36cf0..dd680d4 100755 --- a/src/DmaController.bsv +++ b/src/DmaController.bsv @@ -2,30 +2,39 @@ import FIFOF::*; import PcieTypes::*; import DmaTypes::*; +import DmaCompleter::*; +import DmaRequester::*; interface DmaController#(numeric type dataWidth); // Requester interfaces, where the Card serve as the Master - interface FifoIn#(DataStream) c2hDataFifoIn; // Card writes Host Memory - interface FifoIn#(DmaRequest) c2hReqFifoIn; // Card writes Host Memory - interface FifoIn#(DmaRequest) h2cReqFifoIn; // Card reads Host Memory - interface FifoOut#(DataStream) h2cDataFifoOut; // Card reads Host Memory + interface DmaCardToHostWrite c2hWrite; + interface DmaCardToHostRead c2hRead; // Completer interfaces, where the Card serve as the Slave - interface FifoIn#(DmaCsrFrame) c2hCsrValFifoIn; // Host reads Card Registers - interface FifoOut#(DMACsrAddr) c2hCsrReqFifoOut; // Host reads Card Registers - interface FifoOut#(DmaCsrFrame) h2cCsrValFifoOut; // Host writes Card Registers + interface DmaHostToCardWrite h2cWrite; + interface DmaHostToCardRead h2cRead; // Raw PCIe interfaces, connected to the Xilinx PCIe IP - interface RawPcieRequester pcieRequester; - interface RawPcieCompleter pcieCompleter; - interface RawPcieConfiguration pcieConfig; + interface RawPcieRequesterRequest pcieRequesterRequest; + interface RawPcieRequesterComplete pcieRequesterComplete; + interface RawPcieCompleterRequest pcieCompleterRequest; + interface RawPcieCompleterComplete pcieCompleterComplete; + interface RawPcieConfiguration pcieConfiguration; endinterface -module mkDmaController#() (DmaController ifc); - FIFOF#(DataStream) c2hDataFifo <- mkFIFOF; - FIFOF#(DataStream) h2cDataFifo <- mkFIFOF; - FIFOF#(DmaRequest) c2hReqFifo <- mkFIFOF; - FIFOF#(DmaRequest) h2cReqFifo <- mkFIFOF; +module mkDmaController(DmaController); + DmaCompleter completer = mkDmaCompleter; + DmaRequester requester = mkDmaRequester; + + interface c2hWrite = requester.c2hWrite; + interface c2hRead = requester.c2hRead; + + interface h2cWrite = completer.h2cWrite; + interface h2cRead = completer.h2cRead; + + interface pcieRequesterRequest = requester.rawRequesterRequest; + interface pcieRequesterComplete = requester.rawRequesterComplete; + interface pcieCompleterRequest = completer.rawCompleterRequest; + interface pcieCompleterComplete = completer.rawCompleterComplete; - FIFOF#(DmaCsrFrame) endmodule \ No newline at end of file diff --git a/src/DmaRequester.bsv b/src/DmaRequester.bsv new file mode 100644 index 0000000..7a86abd --- /dev/null +++ b/src/DmaRequester.bsv @@ -0,0 +1,17 @@ + +import PcieTypes::*; +import PcieAxiStreamTypes::*; +import PcieDescriptorTypes::*; +import DmaTypes::*; + +interface Requester; + interface DmaCardToHostWrite c2hWrite; + interface DmaCardToHostRead c2hRead; + interface RawPcieRequesterRequest rawRequesterRequest; + interface RawPcieRequesterComplete rawRequesterComplete; +endinterface + +module mkRequester(Empty); + + +endmodule \ No newline at end of file diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index 5069eff..ea1645e 100755 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -10,8 +10,8 @@ typedef 32 DMA_CSR_ADDR_WIDTH; typedef 32 DMA_CSR_DATA_WIDTH; typedef Bit#(DMA_MEM_ADDR_WIDTH) DmaMemAddr; -typedef Bit#(DMA_CSR_ADDR_WIDTH) DMACsrAddr; -typedef Bit#(DMA_CSR_DATA_WIDTH) DMACsrValue; +typedef Bit#(DMA_CSR_ADDR_WIDTH) DmaCsrAddr; +typedef Bit#(DMA_CSR_DATA_WIDTH) DmaCsrValue; typedef 8 BYTE_WIDTH; typedef TLog#(BYTE_WIDTH) BYTE_WIDTH_WIDTH; @@ -49,12 +49,6 @@ instance FShow#(DmaRequest); endfunction endinstance -instance FShow#(DmaCsrFrame); - function Fmt fshow(DmaCsrFrame csr); - return ($format(" Date: Mon, 22 Jul 2024 04:13:27 +0800 Subject: [PATCH 25/53] testDmaCompterRequest --- run_one.sh | 2 +- src/DmaCompleter.bsv | 117 ++++++----- src/DmaController.bsv | 4 +- src/DmaRequester.bsv | 23 ++- src/PcieDescriptorTypes.bsv | 8 +- src/PrimUtils.bsv | 378 ++++++++++++++++++------------------ test/TestDmaCompleter.bsv | 97 +++++++++ 7 files changed, 378 insertions(+), 251 deletions(-) diff --git a/run_one.sh b/run_one.sh index f049c0d..7e935a8 100755 --- a/run_one.sh +++ b/run_one.sh @@ -13,7 +13,7 @@ TEST_LOG=run.log TEST_DIR=test cd $TEST_DIR truncate -s 0 $TEST_LOG -FILES=`ls TestDmaCore.bsv` +FILES=`ls TestDmaCompleter.bsv` ########################################################################### for FILE in $FILES; do # echo $FILE diff --git a/src/DmaCompleter.bsv b/src/DmaCompleter.bsv index be69863..f36d9e1 100644 --- a/src/DmaCompleter.bsv +++ b/src/DmaCompleter.bsv @@ -1,20 +1,33 @@ -import FIFO::*; +import FIFOF::*; +import SemiFifo::*; +import PrimUtils::*; import PcieAxiStreamTypes::*; import PcieTypes::*; import PcieDescriptorTypes::*; import DmaTypes::*; -typedef 1 IDEA_DWORD_CNT_OF_CSR; +typedef 1 IDEA_DWORD_CNT_OF_CSR; +typedef 4 IDEA_FIRST_BE_HIGH_VALID_PTR_OF_CSR; + typedef 64 CMPL_NPREQ_INFLIGHT_NUM; typedef 20 CMPL_NPREQ_WAITING_CLKS; typedef 2'b11 NP_CREDIT_INCREMENT; typedef 2'b00 NP_CREDIT_NOCHANGE; +typedef PcieAxiStream#(PCIE_COMPLETER_REQUEST_TUSER_WIDTH) CmplReqAxiStream; +typedef PcieAxiStream#(PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) CmplCmplAxiStream; + typedef struct { DmaCsrAddr addr; DmaCsrValue value; -} CsrWriteReq deriving(Bits, Eq, Bounded, FShow); +} CsrWriteReq deriving(Bits, Eq, Bounded); + +instance FShow#(CsrWriteReq); + function Fmt fshow(CsrWriteReq wrReq); + return ($format("32bit requests (* synthesize *) module mkCompleterRequest(CompleterRequest); - FIFOF#(PcieAxiStream) inFifo <- mkFIFOF; - FIFOF#(CsrWriteReq) wrReqFifo <- mkFIFOF; - FIFOF#(CsrReadReq) rdReqFifo <- mkFIFOF; + FIFOF#(CmplReqAxiStream) inFifo <- mkFIFOF; + FIFOF#(CsrWriteReq) wrReqFifo <- mkFIFOF; + FIFOF#(CsrReadReq) rdReqFifo <- mkFIFOF; Reg#(Bool) isInPacket <- mkReg(False); - Reg#(Uint#(32)) illegalPcieReqCntReg <- mkReg(0); + Reg#(UInt#(32)) illegalPcieReqCntReg <- mkReg(0); - function PcieCompleterRequestDescriptor getDescriptorFromFirstBeat(PcieAxiStream axiStream); - return pack(axiStream.tDATA[valueOf(CQ_DESCRIPTOR_WIDTH)-1:0]); + function PcieCompleterRequestDescriptor getDescriptorFromFirstBeat(CmplReqAxiStream axiStream); + return unpack(axiStream.tData[valueOf(DES_CQ_DESCRIPTOR_WIDTH)-1:0]); endfunction - function Data getDataFromFirstBeat(PcieAxiStream axiStream); - return axiStream.tData >> valueOf(CQ_DESCRIPTOR_WIDTH); + function Data getDataFromFirstBeat(CmplReqAxiStream axiStream); + return axiStream.tData >> valueOf(DES_CQ_DESCRIPTOR_WIDTH); endfunction - function Bool isFirstBytesAllValid(PcieCompleterCompleteSideBandFrame sideBand); - return (sideBand.firstByteEn[valueOf(PCIE_TLP_FIRST_BE_WIDTH)-1] == 1); + function Bool isFirstBytesAllValid(PcieCompleterRequestSideBandFrame sideBand); + return (sideBand.firstByteEn[valueOf(IDEA_FIRST_BE_HIGH_VALID_PTR_OF_CSR)-1] == 1); endfunction function DmaCsrAddr getCsrAddrFromCqDescriptor(PcieCompleterRequestDescriptor descriptor); @@ -81,36 +94,36 @@ module mkCompleterRequest(CompleterRequest); rule parse; inFifo.deq; let axiStream = inFifo.first; - PcieCompleterRequestSideBandFrame sideBand = pack(axiStream.tUser); - isInPacket <= !axiStream.isLast; + PcieCompleterRequestSideBandFrame sideBand = unpack(axiStream.tUser); + isInPacket <= !axiStream.tLast; if (!isInPacket) begin let descriptor = getDescriptorFromFirstBeat(axiStream); - case (descriptor.reqType) begin - MEM_WRITE_REQ: begin - if (descriptor.dwordCnt == valueOf(IDEA_DWORD_CNT_OF_CSR) && isFirstBytesAllValid) begin + case (descriptor.reqType) + fromInteger(valueOf(MEM_WRITE_REQ)): begin + if (descriptor.dwordCnt == fromInteger(valueOf(IDEA_DWORD_CNT_OF_CSR)) && isFirstBytesAllValid(sideBand)) begin let firstData = getDataFromFirstBeat(axiStream); DmaCsrValue wrValue = firstData[valueOf(DMA_CSR_ADDR_WIDTH)-1:0]; DmaCsrAddr wrAddr = getCsrAddrFromCqDescriptor(descriptor); let wrReq = CsrWriteReq { - address : wrAddr, + addr : wrAddr, value : wrValue - } + }; wrReqFifo.enq(wrReq); end else begin illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; end end - MEM_READ_REQ: begin + fromInteger(valueOf(MEM_READ_REQ)): begin let rdReqAddr = getCsrAddrFromCqDescriptor(descriptor); let rdReq = CsrReadReq{ rdAddr: rdReqAddr, npInfo: descriptor - } + }; rdReqFifo.enq(rdReq); end - default: illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; - end + default: begin $display("INFO"); illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; end + endcase end endrule @@ -121,31 +134,33 @@ endmodule (* synthesize *) module mkCompleterComplete(CompleterComplete); - FIFOF#(PcieAxiStream) outFifo <- mkFIFOF; - FIFOF#(CsrReadResp) rdRespFifo <- mkFIFOF; - FIFOF#(CsrReadReq) rdReqFifo <- mkFIFOF; + FIFOF#(CmplCmplAxiStream) outFifo <- mkFIFOF; + FIFOF#(CsrReadResp) rdRespFifo <- mkFIFOF; + FIFOF#(CsrReadReq) rdReqFifo <- mkFIFOF; // TODO: the logic of cc interface axiStreamFifoOut = convertFifoToFifoOut(outFifo); interface csrReadRespFifoIn = convertFifoToFifoIn(rdRespFifo); - interface csrReadReqFifoOut = convertFifoToFifoIn(rdReqFifo); + interface csrReadReqFifoIn = convertFifoToFifoIn(rdReqFifo); endmodule (* synthesize *) module mkDmaCompleter(DmaCompleter); - CompleterRequest cmplRequest = mkCompleterRequest; - CompleterComplete cmplComplete = mkCompleterComplete; + CompleterRequest cmplRequest <- mkCompleterRequest; + CompleterComplete cmplComplete <- mkCompleterComplete; FIFOF#(DmaCsrValue) h2cCsrWriteDataFifo <- mkFIFOF; FIFOF#(DmaCsrAddr) h2cCsrWriteReqFifo <- mkFIFOF; FIFOF#(DmaCsrAddr) h2cCsrReadReqFifo <- mkFIFOF; FIFOF#(DmaCsrValue) h2cCsrReadDataFifo <- mkFIFOF; - CounteredFIFOF#(csrReadReq) csrRdReqStoreFifo <- mkCounteredFIFOF(CMPL_NPREQ_INFLIGHT_NUM); + CounteredFIFOF#(CsrReadReq) csrRdReqStoreFifo <- mkCounteredFIFOF(valueOf(CMPL_NPREQ_INFLIGHT_NUM)); - Reg#(PcieNonPostedRequst) npReqCreditCtrlReg <- mkReg(valueOf(NP_CREDIT_INCREMENT)); + Reg#(PcieNonPostedRequst) npReqCreditCtrlReg <- mkReg(fromInteger(valueOf(NP_CREDIT_INCREMENT))); Reg#(PcieNonPostedRequstCount) npReqCreditCntReg <- mkReg(0); + let rawAxiStreamSlaveIfc <- mkFifoInToRawPcieAxiStreamSlave(cmplRequest.axiStreamFifoIn); + let rawAxiStreamMasterIfc <- mkFifoOutToRawPcieAxiStreamMaster(cmplComplete.axiStreamFifoOut); rule genCsrWriteReq; let wrReq = cmplRequest.csrWriteReqFifoOut.first; @@ -164,37 +179,37 @@ module mkDmaCompleter(DmaCompleter); rule procCsrReadResp; let req = csrRdReqStoreFifo.first; let resp = h2cCsrReadDataFifo.first; - cmplComplete.csrReadRespFifoIn(resp); - cmplComplete.csrReadReqFifoIn(req); + cmplComplete.csrReadRespFifoIn.enq(resp); + cmplComplete.csrReadReqFifoIn.enq(req); endrule rule npBackPressure; - if (csrRdReqDescriptorFifo.getCurSize == fromInteger(valueOf(TDiv#(CMPL_NPREQ_INFLIGHT_NUM,2)))) begin - npReqCreditCtrlReg <= valueOf(NP_CREDIT_NOCHANGE); + if (csrRdReqStoreFifo.getCurSize == fromInteger(valueOf(TDiv#(CMPL_NPREQ_INFLIGHT_NUM,2)))) begin + npReqCreditCtrlReg <= fromInteger(valueOf(NP_CREDIT_NOCHANGE)); end else begin - npReqCreditCtrlReg <= valueOf(NP_CREDIT_INCREMENT); + npReqCreditCtrlReg <= fromInteger(valueOf(NP_CREDIT_INCREMENT)); end endrule - interface rawCompleterRequest; - interface rawAxiStreamSlave = mkFifoInToRawPcieAxiStreamSlave#(cmplRequest.axiStreamFifoIn); + interface RawPcieCompleterRequest rawCompleterRequest; + interface rawAxiStreamSlave = rawAxiStreamSlaveIfc; method PcieNonPostedRequst nonPostedReqCreditIncrement = npReqCreditCtrlReg; method Action nonPostedReqCreditCnt(PcieNonPostedRequstCount nonPostedpReqCount); npReqCreditCntReg <= nonPostedpReqCount; endmethod endinterface - interface rawCompleterComplete; - interface rawAxiStreamSlave = mkFifoOutToRawPcieAxiStreamMaster#(cmplComplete.axiStreamFifoOut); + interface RawPcieCompleterComplete rawCompleterComplete; + interface rawAxiStreamMaster = rawAxiStreamMasterIfc; endinterface - interface h2cWrite; + interface DmaHostToCardWrite h2cWrite; interface dataFifoOut = convertFifoToFifoOut(h2cCsrWriteDataFifo); interface reqFifoOut = convertFifoToFifoOut(h2cCsrWriteReqFifo); endinterface - interface h2cRead; + interface DmaHostToCardRead h2cRead; interface reqFifoOut = convertFifoToFifoOut(h2cCsrReadReqFifo); interface dataFifoIn = convertFifoToFifoIn(h2cCsrReadDataFifo); endinterface @@ -202,8 +217,6 @@ module mkDmaCompleter(DmaCompleter); // TODO: get internal registers value method DmaCsrValue getRegisterValue(DmaCsrAddr addr); return 0; - method + endmethod endmodule - -module mkWriteReqTo \ No newline at end of file diff --git a/src/DmaController.bsv b/src/DmaController.bsv index dd680d4..c846ed4 100755 --- a/src/DmaController.bsv +++ b/src/DmaController.bsv @@ -23,8 +23,8 @@ interface DmaController#(numeric type dataWidth); endinterface module mkDmaController(DmaController); - DmaCompleter completer = mkDmaCompleter; - DmaRequester requester = mkDmaRequester; + DmaCompleter completer <- mkDmaCompleter; + DmaRequester requester <- mkDmaRequester; interface c2hWrite = requester.c2hWrite; interface c2hRead = requester.c2hRead; diff --git a/src/DmaRequester.bsv b/src/DmaRequester.bsv index 7a86abd..ef54591 100644 --- a/src/DmaRequester.bsv +++ b/src/DmaRequester.bsv @@ -11,7 +11,26 @@ interface Requester; interface RawPcieRequesterComplete rawRequesterComplete; endinterface -module mkRequester(Empty); +module mkRequester(Requester); + FIFOF#(DataStream) c2hWriteDataFifo <- mkFIFOF; + FIFOF#(DmaRequest) c2hWriteReqFifo <- mkFIFOF; + FIFOF#(DataStream) c2hReadDataFifo <- mkFIFOF; + FIFOF#(DmaRequest) c2hReadReqFifo <- mkFIFOF; + interface c2hWrite; + interface dataFifoOut = convertFifoToFifoOut(c2hWriteDataFifo); + interface reqFifoOut = convertFifoToFifoOut(c2hWriteReqFifo); + endinterface -endmodule \ No newline at end of file + interface c2hRead; + interface reqFifoOut = convertFifoToFifoOut(c2hReadReqFifo); + interface dataFifoIn = convertFifoToFifoIn(c2hReadDataFifo); + endinterface + + interface rawRequesterRequest; + endinterface + + interface rawRequesterComplete; + endinterface + +endmodule diff --git a/src/PcieDescriptorTypes.bsv b/src/PcieDescriptorTypes.bsv index 0435f3d..bcd9b22 100644 --- a/src/PcieDescriptorTypes.bsv +++ b/src/PcieDescriptorTypes.bsv @@ -8,7 +8,7 @@ typedef Bit#(1) ReserveBit1; typedef Bit#(2) ReserveBit2; typedef Bit#(6) ReserveBit6; -typedef 64 DES_CQ_DESCRIPTOR_WIDTH; +typedef 128 DES_CQ_DESCRIPTOR_WIDTH; typedef 3 DES_ATTR_WIDTH; typedef 3 DES_TC_WIDTH; typedef 6 DES_BAR_APERTURE_WIDTH; @@ -65,7 +65,7 @@ typedef struct { ReserveBit1 reserve0; Attributes attributes; TrafficClass trafficClass; - Bool completerIdEn + Bool completerIdEn; BusDeviceFunc completerId; Tag tag; // DW + 1 @@ -81,9 +81,7 @@ typedef struct { ReserveBit6 reserve3; AddrType addrType; LowerAddr lowerAddr; -} - - +} PcieCompleterCompleteDescriptor deriving(Bits, Eq, Bounded, FShow); // Pcie Tlp types of descriptor typedef 4'b0000 MEM_READ_REQ; diff --git a/src/PrimUtils.bsv b/src/PrimUtils.bsv index fe768e8..a2f6c40 100644 --- a/src/PrimUtils.bsv +++ b/src/PrimUtils.bsv @@ -20,69 +20,69 @@ endfunction function Data getDataLowBytes(Data data, DataBytePtr ptr); Data temp = 0; case(ptr) - 1 : temp[valueOf(BYTE_WIDTH)*1 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*1 -1:0]); - 2 : temp[valueOf(BYTE_WIDTH)*2 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*2 -1:0]); - 3 : temp[valueOf(BYTE_WIDTH)*3 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*3 -1:0]); - 4 : temp[valueOf(BYTE_WIDTH)*4 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*4 -1:0]); - 5 : temp[valueOf(BYTE_WIDTH)*5 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*5 -1:0]); - 6 : temp[valueOf(BYTE_WIDTH)*6 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*6 -1:0]); - 7 : temp[valueOf(BYTE_WIDTH)*7 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*7 -1:0]); - 8 : temp[valueOf(BYTE_WIDTH)*8 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*8 -1:0]); - 9 : temp[valueOf(BYTE_WIDTH)*9 -1:0] = Data'(data[valueOf(BYTE_WIDTH)*9 -1:0]); - 10: temp[valueOf(BYTE_WIDTH)*10-1:0] = Data'(data[valueOf(BYTE_WIDTH)*10-1:0]); - 11: temp[valueOf(BYTE_WIDTH)*11-1:0] = Data'(data[valueOf(BYTE_WIDTH)*11-1:0]); - 12: temp[valueOf(BYTE_WIDTH)*12-1:0] = Data'(data[valueOf(BYTE_WIDTH)*12-1:0]); - 13: temp[valueOf(BYTE_WIDTH)*13-1:0] = Data'(data[valueOf(BYTE_WIDTH)*13-1:0]); - 14: temp[valueOf(BYTE_WIDTH)*14-1:0] = Data'(data[valueOf(BYTE_WIDTH)*14-1:0]); - 15: temp[valueOf(BYTE_WIDTH)*15-1:0] = Data'(data[valueOf(BYTE_WIDTH)*15-1:0]); - 16: temp[valueOf(BYTE_WIDTH)*16-1:0] = Data'(data[valueOf(BYTE_WIDTH)*16-1:0]); - 17: temp[valueOf(BYTE_WIDTH)*17-1:0] = Data'(data[valueOf(BYTE_WIDTH)*17-1:0]); - 18: temp[valueOf(BYTE_WIDTH)*18-1:0] = Data'(data[valueOf(BYTE_WIDTH)*18-1:0]); - 19: temp[valueOf(BYTE_WIDTH)*19-1:0] = Data'(data[valueOf(BYTE_WIDTH)*19-1:0]); - 20: temp[valueOf(BYTE_WIDTH)*20-1:0] = Data'(data[valueOf(BYTE_WIDTH)*20-1:0]); - 21: temp[valueOf(BYTE_WIDTH)*21-1:0] = Data'(data[valueOf(BYTE_WIDTH)*21-1:0]); - 22: temp[valueOf(BYTE_WIDTH)*22-1:0] = Data'(data[valueOf(BYTE_WIDTH)*22-1:0]); - 23: temp[valueOf(BYTE_WIDTH)*23-1:0] = Data'(data[valueOf(BYTE_WIDTH)*23-1:0]); - 24: temp[valueOf(BYTE_WIDTH)*24-1:0] = Data'(data[valueOf(BYTE_WIDTH)*24-1:0]); - 25: temp[valueOf(BYTE_WIDTH)*25-1:0] = Data'(data[valueOf(BYTE_WIDTH)*25-1:0]); - 26: temp[valueOf(BYTE_WIDTH)*26-1:0] = Data'(data[valueOf(BYTE_WIDTH)*26-1:0]); - 27: temp[valueOf(BYTE_WIDTH)*27-1:0] = Data'(data[valueOf(BYTE_WIDTH)*27-1:0]); - 28: temp[valueOf(BYTE_WIDTH)*28-1:0] = Data'(data[valueOf(BYTE_WIDTH)*28-1:0]); - 29: temp[valueOf(BYTE_WIDTH)*29-1:0] = Data'(data[valueOf(BYTE_WIDTH)*29-1:0]); - 30: temp[valueOf(BYTE_WIDTH)*30-1:0] = Data'(data[valueOf(BYTE_WIDTH)*30-1:0]); - 31: temp[valueOf(BYTE_WIDTH)*31-1:0] = Data'(data[valueOf(BYTE_WIDTH)*31-1:0]); - 32: temp[valueOf(BYTE_WIDTH)*32-1:0] = Data'(data[valueOf(BYTE_WIDTH)*32-1:0]); - 33: temp[valueOf(BYTE_WIDTH)*33-1:0] = Data'(data[valueOf(BYTE_WIDTH)*33-1:0]); - 34: temp[valueOf(BYTE_WIDTH)*34-1:0] = Data'(data[valueOf(BYTE_WIDTH)*34-1:0]); - 35: temp[valueOf(BYTE_WIDTH)*35-1:0] = Data'(data[valueOf(BYTE_WIDTH)*35-1:0]); - 36: temp[valueOf(BYTE_WIDTH)*36-1:0] = Data'(data[valueOf(BYTE_WIDTH)*36-1:0]); - 37: temp[valueOf(BYTE_WIDTH)*37-1:0] = Data'(data[valueOf(BYTE_WIDTH)*37-1:0]); - 38: temp[valueOf(BYTE_WIDTH)*38-1:0] = Data'(data[valueOf(BYTE_WIDTH)*38-1:0]); - 39: temp[valueOf(BYTE_WIDTH)*39-1:0] = Data'(data[valueOf(BYTE_WIDTH)*39-1:0]); - 40: temp[valueOf(BYTE_WIDTH)*40-1:0] = Data'(data[valueOf(BYTE_WIDTH)*40-1:0]); - 41: temp[valueOf(BYTE_WIDTH)*41-1:0] = Data'(data[valueOf(BYTE_WIDTH)*41-1:0]); - 42: temp[valueOf(BYTE_WIDTH)*42-1:0] = Data'(data[valueOf(BYTE_WIDTH)*42-1:0]); - 43: temp[valueOf(BYTE_WIDTH)*43-1:0] = Data'(data[valueOf(BYTE_WIDTH)*43-1:0]); - 44: temp[valueOf(BYTE_WIDTH)*44-1:0] = Data'(data[valueOf(BYTE_WIDTH)*44-1:0]); - 45: temp[valueOf(BYTE_WIDTH)*45-1:0] = Data'(data[valueOf(BYTE_WIDTH)*45-1:0]); - 46: temp[valueOf(BYTE_WIDTH)*46-1:0] = Data'(data[valueOf(BYTE_WIDTH)*46-1:0]); - 47: temp[valueOf(BYTE_WIDTH)*47-1:0] = Data'(data[valueOf(BYTE_WIDTH)*47-1:0]); - 48: temp[valueOf(BYTE_WIDTH)*48-1:0] = Data'(data[valueOf(BYTE_WIDTH)*48-1:0]); - 49: temp[valueOf(BYTE_WIDTH)*49-1:0] = Data'(data[valueOf(BYTE_WIDTH)*49-1:0]); - 50: temp[valueOf(BYTE_WIDTH)*50-1:0] = Data'(data[valueOf(BYTE_WIDTH)*50-1:0]); - 51: temp[valueOf(BYTE_WIDTH)*51-1:0] = Data'(data[valueOf(BYTE_WIDTH)*51-1:0]); - 52: temp[valueOf(BYTE_WIDTH)*52-1:0] = Data'(data[valueOf(BYTE_WIDTH)*52-1:0]); - 53: temp[valueOf(BYTE_WIDTH)*53-1:0] = Data'(data[valueOf(BYTE_WIDTH)*53-1:0]); - 54: temp[valueOf(BYTE_WIDTH)*54-1:0] = Data'(data[valueOf(BYTE_WIDTH)*54-1:0]); - 55: temp[valueOf(BYTE_WIDTH)*55-1:0] = Data'(data[valueOf(BYTE_WIDTH)*55-1:0]); - 56: temp[valueOf(BYTE_WIDTH)*56-1:0] = Data'(data[valueOf(BYTE_WIDTH)*56-1:0]); - 57: temp[valueOf(BYTE_WIDTH)*57-1:0] = Data'(data[valueOf(BYTE_WIDTH)*57-1:0]); - 58: temp[valueOf(BYTE_WIDTH)*58-1:0] = Data'(data[valueOf(BYTE_WIDTH)*58-1:0]); - 59: temp[valueOf(BYTE_WIDTH)*59-1:0] = Data'(data[valueOf(BYTE_WIDTH)*59-1:0]); - 60: temp[valueOf(BYTE_WIDTH)*60-1:0] = Data'(data[valueOf(BYTE_WIDTH)*60-1:0]); - 61: temp[valueOf(BYTE_WIDTH)*61-1:0] = Data'(data[valueOf(BYTE_WIDTH)*61-1:0]); - 62: temp[valueOf(BYTE_WIDTH)*62-1:0] = Data'(data[valueOf(BYTE_WIDTH)*62-1:0]); - 63: temp[valueOf(BYTE_WIDTH)*63-1:0] = Data'(data[valueOf(BYTE_WIDTH)*63-1:0]); + 1 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*1 -1:0])); + 2 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*2 -1:0])); + 3 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*3 -1:0])); + 4 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*4 -1:0])); + 5 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*5 -1:0])); + 6 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*6 -1:0])); + 7 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*7 -1:0])); + 8 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*8 -1:0])); + 9 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*9 -1:0])); + 10: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*10-1:0])); + 11: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*11-1:0])); + 12: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*12-1:0])); + 13: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*13-1:0])); + 14: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*14-1:0])); + 15: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*15-1:0])); + 16: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*16-1:0])); + 17: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*17-1:0])); + 18: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*18-1:0])); + 19: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*19-1:0])); + 20: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*20-1:0])); + 21: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*21-1:0])); + 22: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*22-1:0])); + 23: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*23-1:0])); + 24: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*24-1:0])); + 25: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*25-1:0])); + 26: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*26-1:0])); + 27: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*27-1:0])); + 28: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*28-1:0])); + 29: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*29-1:0])); + 30: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*30-1:0])); + 31: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*31-1:0])); + 32: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*32-1:0])); + 33: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*33-1:0])); + 34: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*34-1:0])); + 35: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*35-1:0])); + 36: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*36-1:0])); + 37: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*37-1:0])); + 38: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*38-1:0])); + 39: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*39-1:0])); + 40: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*40-1:0])); + 41: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*41-1:0])); + 42: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*42-1:0])); + 43: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*43-1:0])); + 44: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*44-1:0])); + 45: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*45-1:0])); + 46: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*46-1:0])); + 47: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*47-1:0])); + 48: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*48-1:0])); + 49: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*49-1:0])); + 50: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*50-1:0])); + 51: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*51-1:0])); + 52: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*52-1:0])); + 53: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*53-1:0])); + 54: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*54-1:0])); + 55: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*55-1:0])); + 56: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*56-1:0])); + 57: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*57-1:0])); + 58: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*58-1:0])); + 59: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*59-1:0])); + 60: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*60-1:0])); + 61: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*61-1:0])); + 62: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*62-1:0])); + 63: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*63-1:0])); default: temp = 0; endcase return temp; @@ -91,69 +91,69 @@ endfunction function Data getDataHighBytes(Data data, DataBytePtr ptr); Data temp = 0; case(ptr) - 1 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*1 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*1 ]); - 2 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*2 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*2 ]); - 3 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*3 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*3 ]); - 4 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*4 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*4 ]); - 5 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*5 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*5 ]); - 6 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*6 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*6 ]); - 7 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*7 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*7 ]); - 8 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*8 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*8 ]); - 9 : temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*9 ] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*9 ]); - 10: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*10] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*10]); - 11: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*11] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*11]); - 12: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*12] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*12]); - 13: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*13] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*13]); - 14: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*14] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*14]); - 15: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*15] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*15]); - 16: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*16] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*16]); - 17: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*17] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*17]); - 18: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*18] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*18]); - 19: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*19] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*19]); - 20: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*20] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*20]); - 21: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*21] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*21]); - 22: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*22] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*22]); - 23: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*23] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*23]); - 24: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*24] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*24]); - 25: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*25] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*25]); - 26: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*26] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*26]); - 27: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*27] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*27]); - 28: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*28] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*28]); - 29: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*29] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*29]); - 30: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*30] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*30]); - 31: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*31] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*31]); - 32: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*32] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*32]); - 33: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*33] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*33]); - 34: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*34] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*34]); - 35: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*35] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*35]); - 36: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*36] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*36]); - 37: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*37] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*37]); - 38: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*38] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*38]); - 39: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*39] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*39]); - 40: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*40] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*40]); - 41: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*41] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*41]); - 42: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*42] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*42]); - 43: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*43] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*43]); - 44: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*44] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*44]); - 45: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*45] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*45]); - 46: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*46] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*46]); - 47: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*47] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*47]); - 48: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*48] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*48]); - 49: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*49] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*49]); - 50: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*50] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*50]); - 51: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*51] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*51]); - 52: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*52] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*52]); - 53: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*53] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*53]); - 54: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*54] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*54]); - 55: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*55] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*55]); - 56: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*56] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*56]); - 57: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*57] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*57]); - 58: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*58] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*58]); - 59: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*59] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*59]); - 60: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*60] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*60]); - 61: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*61] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*61]); - 62: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*62] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*62]); - 63: temp[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*63] = Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*63]); + 1 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*1 ])); + 2 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*2 ])); + 3 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*3 ])); + 4 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*4 ])); + 5 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*5 ])); + 6 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*6 ])); + 7 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*7 ])); + 8 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*8 ])); + 9 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*9 ])); + 10: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*10])); + 11: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*11])); + 12: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*12])); + 13: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*13])); + 14: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*14])); + 15: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*15])); + 16: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*16])); + 17: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*17])); + 18: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*18])); + 19: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*19])); + 20: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*20])); + 21: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*21])); + 22: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*22])); + 23: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*23])); + 24: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*24])); + 25: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*25])); + 26: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*26])); + 27: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*27])); + 28: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*28])); + 29: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*29])); + 30: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*30])); + 31: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*31])); + 32: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*32])); + 33: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*33])); + 34: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*34])); + 35: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*35])); + 36: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*36])); + 37: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*37])); + 38: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*38])); + 39: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*39])); + 40: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*40])); + 41: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*41])); + 42: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*42])); + 43: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*43])); + 44: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*44])); + 45: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*45])); + 46: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*46])); + 47: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*47])); + 48: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*48])); + 49: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*49])); + 50: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*50])); + 51: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*51])); + 52: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*52])); + 53: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*53])); + 54: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*54])); + 55: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*55])); + 56: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*56])); + 57: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*57])); + 58: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*58])); + 59: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*59])); + 60: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*60])); + 61: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*61])); + 62: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*62])); + 63: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*63])); default: temp = data; endcase return temp; @@ -162,69 +162,69 @@ endfunction function DmaMemAddr getAddrLowBits(DmaMemAddr addr, Bit#(TLog#(DMA_MEM_ADDR_WIDTH)) ptr); DmaMemAddr temp = 0; case(ptr) - 1 : temp[1 -1:0] = DmaMemAddr'(addr[1 -1:0]); - 2 : temp[2 -1:0] = DmaMemAddr'(addr[2 -1:0]); - 3 : temp[3 -1:0] = DmaMemAddr'(addr[3 -1:0]); - 4 : temp[4 -1:0] = DmaMemAddr'(addr[4 -1:0]); - 5 : temp[5 -1:0] = DmaMemAddr'(addr[5 -1:0]); - 6 : temp[6 -1:0] = DmaMemAddr'(addr[6 -1:0]); - 7 : temp[7 -1:0] = DmaMemAddr'(addr[7 -1:0]); - 8 : temp[8 -1:0] = DmaMemAddr'(addr[8 -1:0]); - 9 : temp[9 -1:0] = DmaMemAddr'(addr[9 -1:0]); - 10: temp[10-1:0] = DmaMemAddr'(addr[10-1:0]); - 11: temp[11-1:0] = DmaMemAddr'(addr[11-1:0]); - 12: temp[12-1:0] = DmaMemAddr'(addr[12-1:0]); - 13: temp[13-1:0] = DmaMemAddr'(addr[13-1:0]); - 14: temp[14-1:0] = DmaMemAddr'(addr[14-1:0]); - 15: temp[15-1:0] = DmaMemAddr'(addr[15-1:0]); - 16: temp[16-1:0] = DmaMemAddr'(addr[16-1:0]); - 17: temp[17-1:0] = DmaMemAddr'(addr[17-1:0]); - 18: temp[18-1:0] = DmaMemAddr'(addr[18-1:0]); - 19: temp[19-1:0] = DmaMemAddr'(addr[19-1:0]); - 20: temp[20-1:0] = DmaMemAddr'(addr[20-1:0]); - 21: temp[21-1:0] = DmaMemAddr'(addr[21-1:0]); - 22: temp[22-1:0] = DmaMemAddr'(addr[22-1:0]); - 23: temp[23-1:0] = DmaMemAddr'(addr[23-1:0]); - 24: temp[24-1:0] = DmaMemAddr'(addr[24-1:0]); - 25: temp[25-1:0] = DmaMemAddr'(addr[25-1:0]); - 26: temp[26-1:0] = DmaMemAddr'(addr[26-1:0]); - 27: temp[27-1:0] = DmaMemAddr'(addr[27-1:0]); - 28: temp[28-1:0] = DmaMemAddr'(addr[28-1:0]); - 29: temp[29-1:0] = DmaMemAddr'(addr[29-1:0]); - 30: temp[30-1:0] = DmaMemAddr'(addr[30-1:0]); - 31: temp[31-1:0] = DmaMemAddr'(addr[31-1:0]); - 32: temp[32-1:0] = DmaMemAddr'(addr[32-1:0]); - 33: temp[33-1:0] = DmaMemAddr'(addr[33-1:0]); - 34: temp[34-1:0] = DmaMemAddr'(addr[34-1:0]); - 35: temp[35-1:0] = DmaMemAddr'(addr[35-1:0]); - 36: temp[36-1:0] = DmaMemAddr'(addr[36-1:0]); - 37: temp[37-1:0] = DmaMemAddr'(addr[37-1:0]); - 38: temp[38-1:0] = DmaMemAddr'(addr[38-1:0]); - 39: temp[39-1:0] = DmaMemAddr'(addr[39-1:0]); - 40: temp[40-1:0] = DmaMemAddr'(addr[40-1:0]); - 41: temp[41-1:0] = DmaMemAddr'(addr[41-1:0]); - 42: temp[42-1:0] = DmaMemAddr'(addr[42-1:0]); - 43: temp[43-1:0] = DmaMemAddr'(addr[43-1:0]); - 44: temp[44-1:0] = DmaMemAddr'(addr[44-1:0]); - 45: temp[45-1:0] = DmaMemAddr'(addr[45-1:0]); - 46: temp[46-1:0] = DmaMemAddr'(addr[46-1:0]); - 47: temp[47-1:0] = DmaMemAddr'(addr[47-1:0]); - 48: temp[48-1:0] = DmaMemAddr'(addr[48-1:0]); - 49: temp[49-1:0] = DmaMemAddr'(addr[49-1:0]); - 50: temp[50-1:0] = DmaMemAddr'(addr[50-1:0]); - 51: temp[51-1:0] = DmaMemAddr'(addr[51-1:0]); - 52: temp[52-1:0] = DmaMemAddr'(addr[52-1:0]); - 53: temp[53-1:0] = DmaMemAddr'(addr[53-1:0]); - 54: temp[54-1:0] = DmaMemAddr'(addr[54-1:0]); - 55: temp[55-1:0] = DmaMemAddr'(addr[55-1:0]); - 56: temp[56-1:0] = DmaMemAddr'(addr[56-1:0]); - 57: temp[57-1:0] = DmaMemAddr'(addr[57-1:0]); - 58: temp[58-1:0] = DmaMemAddr'(addr[58-1:0]); - 59: temp[59-1:0] = DmaMemAddr'(addr[59-1:0]); - 60: temp[60-1:0] = DmaMemAddr'(addr[60-1:0]); - 61: temp[61-1:0] = DmaMemAddr'(addr[61-1:0]); - 62: temp[62-1:0] = DmaMemAddr'(addr[62-1:0]); - 63: temp[63-1:0] = DmaMemAddr'(addr[63-1:0]); + 1 : temp = zeroExtend(DmaMemAddr'(addr[1 -1:0])); + 2 : temp = zeroExtend(DmaMemAddr'(addr[2 -1:0])); + 3 : temp = zeroExtend(DmaMemAddr'(addr[3 -1:0])); + 4 : temp = zeroExtend(DmaMemAddr'(addr[4 -1:0])); + 5 : temp = zeroExtend(DmaMemAddr'(addr[5 -1:0])); + 6 : temp = zeroExtend(DmaMemAddr'(addr[6 -1:0])); + 7 : temp = zeroExtend(DmaMemAddr'(addr[7 -1:0])); + 8 : temp = zeroExtend(DmaMemAddr'(addr[8 -1:0])); + 9 : temp = zeroExtend(DmaMemAddr'(addr[9 -1:0])); + 10: temp = zeroExtend(DmaMemAddr'(addr[10-1:0])); + 11: temp = zeroExtend(DmaMemAddr'(addr[11-1:0])); + 12: temp = zeroExtend(DmaMemAddr'(addr[12-1:0])); + 13: temp = zeroExtend(DmaMemAddr'(addr[13-1:0])); + 14: temp = zeroExtend(DmaMemAddr'(addr[14-1:0])); + 15: temp = zeroExtend(DmaMemAddr'(addr[15-1:0])); + 16: temp = zeroExtend(DmaMemAddr'(addr[16-1:0])); + 17: temp = zeroExtend(DmaMemAddr'(addr[17-1:0])); + 18: temp = zeroExtend(DmaMemAddr'(addr[18-1:0])); + 19: temp = zeroExtend(DmaMemAddr'(addr[19-1:0])); + 20: temp = zeroExtend(DmaMemAddr'(addr[20-1:0])); + 21: temp = zeroExtend(DmaMemAddr'(addr[21-1:0])); + 22: temp = zeroExtend(DmaMemAddr'(addr[22-1:0])); + 23: temp = zeroExtend(DmaMemAddr'(addr[23-1:0])); + 24: temp = zeroExtend(DmaMemAddr'(addr[24-1:0])); + 25: temp = zeroExtend(DmaMemAddr'(addr[25-1:0])); + 26: temp = zeroExtend(DmaMemAddr'(addr[26-1:0])); + 27: temp = zeroExtend(DmaMemAddr'(addr[27-1:0])); + 28: temp = zeroExtend(DmaMemAddr'(addr[28-1:0])); + 29: temp = zeroExtend(DmaMemAddr'(addr[29-1:0])); + 30: temp = zeroExtend(DmaMemAddr'(addr[30-1:0])); + 31: temp = zeroExtend(DmaMemAddr'(addr[31-1:0])); + 32: temp = zeroExtend(DmaMemAddr'(addr[32-1:0])); + 33: temp = zeroExtend(DmaMemAddr'(addr[33-1:0])); + 34: temp = zeroExtend(DmaMemAddr'(addr[34-1:0])); + 35: temp = zeroExtend(DmaMemAddr'(addr[35-1:0])); + 36: temp = zeroExtend(DmaMemAddr'(addr[36-1:0])); + 37: temp = zeroExtend(DmaMemAddr'(addr[37-1:0])); + 38: temp = zeroExtend(DmaMemAddr'(addr[38-1:0])); + 39: temp = zeroExtend(DmaMemAddr'(addr[39-1:0])); + 40: temp = zeroExtend(DmaMemAddr'(addr[40-1:0])); + 41: temp = zeroExtend(DmaMemAddr'(addr[41-1:0])); + 42: temp = zeroExtend(DmaMemAddr'(addr[42-1:0])); + 43: temp = zeroExtend(DmaMemAddr'(addr[43-1:0])); + 44: temp = zeroExtend(DmaMemAddr'(addr[44-1:0])); + 45: temp = zeroExtend(DmaMemAddr'(addr[45-1:0])); + 46: temp = zeroExtend(DmaMemAddr'(addr[46-1:0])); + 47: temp = zeroExtend(DmaMemAddr'(addr[47-1:0])); + 48: temp = zeroExtend(DmaMemAddr'(addr[48-1:0])); + 49: temp = zeroExtend(DmaMemAddr'(addr[49-1:0])); + 50: temp = zeroExtend(DmaMemAddr'(addr[50-1:0])); + 51: temp = zeroExtend(DmaMemAddr'(addr[51-1:0])); + 52: temp = zeroExtend(DmaMemAddr'(addr[52-1:0])); + 53: temp = zeroExtend(DmaMemAddr'(addr[53-1:0])); + 54: temp = zeroExtend(DmaMemAddr'(addr[54-1:0])); + 55: temp = zeroExtend(DmaMemAddr'(addr[55-1:0])); + 56: temp = zeroExtend(DmaMemAddr'(addr[56-1:0])); + 57: temp = zeroExtend(DmaMemAddr'(addr[57-1:0])); + 58: temp = zeroExtend(DmaMemAddr'(addr[58-1:0])); + 59: temp = zeroExtend(DmaMemAddr'(addr[59-1:0])); + 60: temp = zeroExtend(DmaMemAddr'(addr[60-1:0])); + 61: temp = zeroExtend(DmaMemAddr'(addr[61-1:0])); + 62: temp = zeroExtend(DmaMemAddr'(addr[62-1:0])); + 63: temp = zeroExtend(DmaMemAddr'(addr[63-1:0])); default: temp = 0; endcase return temp; diff --git a/test/TestDmaCompleter.bsv b/test/TestDmaCompleter.bsv index e69de29..c2b36a2 100644 --- a/test/TestDmaCompleter.bsv +++ b/test/TestDmaCompleter.bsv @@ -0,0 +1,97 @@ + +import FIFOF::*; +import Vector::*; +import FShow::*; + +import SemiFifo::*; +import PrimUtils::*; +import PcieAxiStreamTypes::*; +import PcieTypes::*; +import PcieDescriptorTypes::*; +import DmaTypes::*; +import DmaCompleter::*; + +typedef 'hABCD TEST_DATA; +typedef 'h1234 TEST_ADDR; + +typedef 2'b10 TRANSLATED_ADDR_TYPE; + +function PcieTlpCtlIsEopCommon getEmptyEop(); + return PcieTlpCtlIsEopCommon { + isEopPtrs: replicate(0), + isEop : 0 + }; +endfunction + +function PcieTlpCtlIsSopCommon getEmptySop(); + return PcieTlpCtlIsSopCommon { + isSopPtrs: replicate(0), + isSop : 0 + }; +endfunction + +function CmplReqAxiStream genPseudoHostWriteRequest(); + let descriptor = PcieCompleterRequestDescriptor { + reserve0 : 0, + attributes : 0, + trafficClass : 0, + barAperture : fromInteger(valueOf(DMA_CSR_ADDR_WIDTH)), + barId : 0, + targetFunction: 0, + tag : 0, + requesterId : fromInteger(valueOf(TEST_DATA)), + reserve1 : 0, + reqType : fromInteger(valueOf(MEM_WRITE_REQ)), + dwordCnt : 1, + address : fromInteger(valueOf(TEST_ADDR)), + addrType : fromInteger(valueOf(TRANSLATED_ADDR_TYPE)) + }; + Data data = 0; + data = data | zeroExtend(pack(descriptor)); + Data value = fromInteger(valueOf(TEST_DATA)); + data = data | (value << valueOf(DES_CQ_DESCRIPTOR_WIDTH)); + let sideBand = PcieCompleterRequestSideBandFrame { + parity : 0, + tphSteeringTag : 0, + tphType : 0, + tphPresent : 0, + discontinue : False, + isEop : getEmptyEop, + isSop : getEmptySop, + dataByteEn : 'hFFF, + lastByteEn : 'hF, + firstByteEn : 'hF + }; + return CmplReqAxiStream { + tData : data, + tKeep : 'h3FF, + tLast : True, + tUser : pack(sideBand) + }; +endfunction + +(* doc = "testcase" *) +module mkTestDmaCompleterRequest(Empty); + CompleterRequest dut <- mkCompleterRequest; + Reg#(Bool) isInitReg <- mkReg(False); + + rule testInit if (!isInitReg); + $display("INFO: Start CompleterRequest test"); + let testAxiStram = genPseudoHostWriteRequest; + dut.axiStreamFifoIn.enq(testAxiStram); + isInitReg <= True; + endrule + + rule testOutput if (isInitReg); + dut.csrWriteReqFifoOut.deq; + let wrReq = dut.csrWriteReqFifoOut.first; + immAssert( + (wrReq.addr == fromInteger(valueOf(TEST_ADDR)) && wrReq.value == fromInteger(valueOf(TEST_DATA))), + "wrReq test @ mkTestDmaCompleterRequest", + fshow(wrReq) + ); + $display("INFO: Pass CompleterRequest test"); + $finish(); + endrule + +endmodule \ No newline at end of file From 27d3953a792bde1e62f2695fd3d633d8f7aba994 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Tue, 23 Jul 2024 17:36:39 +0800 Subject: [PATCH 26/53] Add TestDmacVivado for simulation with IP --- backend/Makefile | 4 +- src/DmaCompleter.bsv | 7 +- src/DmaController.bsv | 25 +-- src/DmaRequester.bsv | 91 ++++++++-- src/PcieConfigurator.bsv | 372 ++++++++++++++++++++++++++++++++++++++ src/PcieTypes.bsv | 221 +++++++++++++++++++--- test/TestDmaCompleter.bsv | 51 +++++- test/TestDmacVivado.bsv | 63 +++++++ 8 files changed, 777 insertions(+), 57 deletions(-) create mode 100644 src/PcieConfigurator.bsv create mode 100644 test/TestDmacVivado.bsv diff --git a/backend/Makefile b/backend/Makefile index 01c68f1..b629e29 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -8,8 +8,8 @@ OUTPUTDIR ?= output LOGFILE ?= run.log RUNTOPHASE ?= place # synth place route all PARTNAME = xcvu13p-fhgb2104-2-i -TARGETFILE ?= ../src/StreamUtils.bsv -TOPMODULE ?= mkStreamConcat +TARGETFILE ?= ../test/TestDmacVivado.bsv +TOPMODULE ?= mkTestDmacCsrWrRdLoop export TOP = $(TOPMODULE) export RTL = $(VLOGDIR) diff --git a/src/DmaCompleter.bsv b/src/DmaCompleter.bsv index f36d9e1..aa2afdf 100644 --- a/src/DmaCompleter.bsv +++ b/src/DmaCompleter.bsv @@ -37,8 +37,8 @@ typedef struct { } CsrReadReq deriving(Bits, Eq, Bounded, FShow); interface DmaCompleter; - interface RawPcieCompleterRequest rawCompleterRequest; - interface RawPcieCompleterComplete rawCompleterComplete; + (* prefix = "" *) interface RawPcieCompleterRequest rawCompleterRequest; + (* prefix = "" *) interface RawPcieCompleterComplete rawCompleterComplete; interface DmaHostToCardWrite h2cWrite; interface DmaHostToCardRead h2cRead; method DmaCsrValue getRegisterValue(DmaCsrAddr addr); @@ -58,7 +58,6 @@ endinterface // PcieCompleter does not support straddle mode now // The completer is designed only for CSR Rd/Wr, and will ignore any len>32bit requests -(* synthesize *) module mkCompleterRequest(CompleterRequest); FIFOF#(CmplReqAxiStream) inFifo <- mkFIFOF; FIFOF#(CsrWriteReq) wrReqFifo <- mkFIFOF; @@ -98,6 +97,7 @@ module mkCompleterRequest(CompleterRequest); isInPacket <= !axiStream.tLast; if (!isInPacket) begin let descriptor = getDescriptorFromFirstBeat(axiStream); + // TODO: parity check! case (descriptor.reqType) fromInteger(valueOf(MEM_WRITE_REQ)): begin if (descriptor.dwordCnt == fromInteger(valueOf(IDEA_DWORD_CNT_OF_CSR)) && isFirstBytesAllValid(sideBand)) begin @@ -132,7 +132,6 @@ module mkCompleterRequest(CompleterRequest); interface csrReadReqFifoOut = convertFifoToFifoOut(rdReqFifo); endmodule -(* synthesize *) module mkCompleterComplete(CompleterComplete); FIFOF#(CmplCmplAxiStream) outFifo <- mkFIFOF; FIFOF#(CsrReadResp) rdRespFifo <- mkFIFOF; diff --git a/src/DmaController.bsv b/src/DmaController.bsv index c846ed4..e38bfb1 100755 --- a/src/DmaController.bsv +++ b/src/DmaController.bsv @@ -1,11 +1,12 @@ import FIFOF::*; import PcieTypes::*; +import PcieConfigurator::*; import DmaTypes::*; import DmaCompleter::*; import DmaRequester::*; -interface DmaController#(numeric type dataWidth); +interface DmaController; // Requester interfaces, where the Card serve as the Master interface DmaCardToHostWrite c2hWrite; interface DmaCardToHostRead c2hRead; @@ -15,16 +16,14 @@ interface DmaController#(numeric type dataWidth); interface DmaHostToCardRead h2cRead; // Raw PCIe interfaces, connected to the Xilinx PCIe IP - interface RawPcieRequesterRequest pcieRequesterRequest; - interface RawPcieRequesterComplete pcieRequesterComplete; - interface RawPcieCompleterRequest pcieCompleterRequest; - interface RawPcieCompleterComplete pcieCompleterComplete; - interface RawPcieConfiguration pcieConfiguration; + interface RawXilinxPcieIp rawPcie; endinterface +(* synthesize *) module mkDmaController(DmaController); DmaCompleter completer <- mkDmaCompleter; DmaRequester requester <- mkDmaRequester; + PcieConfigurator pcieConfigurator <- mkPcieConfigurator; interface c2hWrite = requester.c2hWrite; interface c2hRead = requester.c2hRead; @@ -32,9 +31,11 @@ module mkDmaController(DmaController); interface h2cWrite = completer.h2cWrite; interface h2cRead = completer.h2cRead; - interface pcieRequesterRequest = requester.rawRequesterRequest; - interface pcieRequesterComplete = requester.rawRequesterComplete; - interface pcieCompleterRequest = completer.rawCompleterRequest; - interface pcieCompleterComplete = completer.rawCompleterComplete; - -endmodule \ No newline at end of file + interface RawXilinxPcieIp rawPcie; + interface requesterRequest = requester.rawRequesterRequest; + interface requesterComplete = requester.rawRequesterComplete; + interface completerRequest = completer.rawCompleterRequest; + interface completerComplete = completer.rawCompleterComplete; + interface configuration = pcieConfigurator.rawConfiguration; + endinterface +endmodule diff --git a/src/DmaRequester.bsv b/src/DmaRequester.bsv index ef54591..10e56b0 100644 --- a/src/DmaRequester.bsv +++ b/src/DmaRequester.bsv @@ -1,36 +1,103 @@ +import FIFOF::*; +import SemiFifo::*; import PcieTypes::*; import PcieAxiStreamTypes::*; import PcieDescriptorTypes::*; import DmaTypes::*; -interface Requester; +typedef PcieAxiStream#(PCIE_REQUESTER_REQUEST_TUSER_WIDTH) ReqReqAxiStream; +typedef PcieAxiStream#(PCIE_REQUESTER_COMPLETE_TUSER_WIDTH) ReqCmplAxiStream; + +interface DmaRequester; interface DmaCardToHostWrite c2hWrite; interface DmaCardToHostRead c2hRead; - interface RawPcieRequesterRequest rawRequesterRequest; - interface RawPcieRequesterComplete rawRequesterComplete; + (* prefix = "" *) interface RawPcieRequesterRequest rawRequesterRequest; + (* prefix = "" *) interface RawPcieRequesterComplete rawRequesterComplete; +endinterface + +interface RequesterRequest; + interface FifoIn#(DataStream) wrDataFifoIn; + interface FifoIn#(DmaRequest) wrReqFifoIn; + interface FifoIn#(DmaRequest) rdReqFifoIn; + interface FifoOut#(ReqReqAxiStream) axiStreamFifoOut; +endinterface + +interface RequesterComplete; + interface FifoIn#(DmaRequest) rdReqFifoIn; + interface FifoOut#(DataStream) rdDataFifoOut; + interface FifoIn#(ReqCmplAxiStream) axiStreamFifoIn; endinterface -module mkRequester(Requester); +module mkRequesterRequest(RequesterRequest); + FIFOF#(DataStream) wrDataInFifo <- mkFIFOF; + FIFOF#(DmaRequest) wrReqInFifo <- mkFIFOF; + FIFOF#(DmaRequest) rdReqInFifo <- mkFIFOF; + FIFOF#(ReqReqAxiStream) axiStreamOutFifo <- mkFIFOF; + + // TODO: RQ Logic + + interface wrDataFifoIn = convertFifoToFifoIn(wrDataInFifo); + interface wrReqFifoIn = convertFifoToFifoIn(wrReqInFifo); + interface rdReqFifoIn = convertFifoToFifoIn(rdReqInFifo); + interface axiStreamFifoOut = convertFifoToFifoOut(axiStreamOutFifo); +endmodule + +module mkRequesterComplete(RequesterComplete); + FIFOF#(DataStream) rdDataOutFifo <- mkFIFOF; + FIFOF#(DmaRequest) rdReqInFifo <- mkFIFOF; + FIFOF#(ReqCmplAxiStream) axiStreamInFifo <- mkFIFOF; + + // TODO: RC Logic + + interface rdReqFifoIn = convertFifoToFifoIn(rdReqInFifo); + interface rdDataFifoOut = convertFifoToFifoOut(rdDataOutFifo); + interface axiStreamFifoIn = convertFifoToFifoIn(axiStreamInFifo); +endmodule + +(* synthesize *) +module mkDmaRequester(DmaRequester); + RequesterRequest reqRequest <- mkRequesterRequest; + RequesterComplete reqComplete <- mkRequesterComplete; + FIFOF#(DataStream) c2hWriteDataFifo <- mkFIFOF; FIFOF#(DmaRequest) c2hWriteReqFifo <- mkFIFOF; FIFOF#(DataStream) c2hReadDataFifo <- mkFIFOF; FIFOF#(DmaRequest) c2hReadReqFifo <- mkFIFOF; - interface c2hWrite; - interface dataFifoOut = convertFifoToFifoOut(c2hWriteDataFifo); - interface reqFifoOut = convertFifoToFifoOut(c2hWriteReqFifo); + let rawAxiStreamSlaveIfc <- mkFifoInToRawPcieAxiStreamSlave(reqComplete.axiStreamFifoIn); + let rawAxiStreamMasterIfc <- mkFifoOutToRawPcieAxiStreamMaster(reqRequest.axiStreamFifoOut); + + interface DmaCardToHostWrite c2hWrite; + interface dataFifoIn = convertFifoToFifoIn(c2hWriteDataFifo); + interface reqFifoIn = convertFifoToFifoIn(c2hWriteReqFifo); + // TODO: isDone need assertion + method Bool isDone = True; endinterface - interface c2hRead; - interface reqFifoOut = convertFifoToFifoOut(c2hReadReqFifo); - interface dataFifoIn = convertFifoToFifoIn(c2hReadDataFifo); + interface DmaCardToHostRead c2hRead; + interface reqFifoIn = convertFifoToFifoIn(c2hReadReqFifo); + interface dataFifoOut = convertFifoToFifoOut(c2hReadDataFifo); endinterface - interface rawRequesterRequest; + interface RawPcieRequesterRequest rawRequesterRequest; + interface rawAxiStreamMaster = rawAxiStreamMasterIfc; + method Action pcieProgressTrack( + Bool tagValid0, + Bool tagValid1, + PcieRqTag tag0, + PcieRqTag tag1, + Bool seqNumValid0, + Bool seqNumValid1, + PcieRqSeqNum seqNum0, + PcieRqSeqNum seqNum1 + ); + // Not support progress track now + endmethod endinterface - interface rawRequesterComplete; + interface RawPcieRequesterComplete rawRequesterComplete; + interface rawAxiStreamSlave = rawAxiStreamSlaveIfc; endinterface endmodule diff --git a/src/PcieConfigurator.bsv b/src/PcieConfigurator.bsv new file mode 100644 index 0000000..78474a9 --- /dev/null +++ b/src/PcieConfigurator.bsv @@ -0,0 +1,372 @@ + +import PcieTypes::*; +import PcieAxiStreamTypes::*; + +typedef 256 PCIE_CFG_VF_FLR_INPROC_EXTEND_WIDTH; + +interface PcieConfigurator; + interface RawPcieConfiguration rawConfiguration; + // TODO: translate raw Ifcs to bluespec style Get Ifcs + method PcieCfgLtssmState getPcieLtssmState(); +endinterface + +module mkPcieConfigurator(PcieConfigurator); + // TODO: the powerStateChangeAck must waitng for completing Done + Reg#(Bool) powerStateChangeIntrReg <- mkReg(False); + + // Here has a 2-stage pipeline for FLR, according to the Xilinx PCIe Example Design + // Reg0 means stage0, and Reg1 means stage1 + Reg#(PcieCfgFlrDone) cfgFlrDoneReg0 <- mkReg(0); + Reg#(PcieCfgFlrDone) cfgFlrDoneReg1 <- mkReg(0); + Reg#(PcieCfgVFFlrFuncNum) cfgVFFlrFuncNumReg <- mkReg(0); + Reg#(PcieCfgVFFlrFuncNum) cfgVFFlrFuncNumReg1 <- mkReg(0); + Reg#(Bool) cfgVFFlrDoneReg1 <- mkReg(False); + Reg#(Bit#(PCIE_CFG_VF_FLR_INPROC_EXTEND_WIDTH)) cfgVfFlrInprocReg0 <- mkReg(0); + + rule functionLevelRst; + cfgVFFlrFuncNumReg <= cfgVFFlrFuncNumReg + 1; + cfgFlrDoneReg1 <= cfgFlrDoneReg0; + cfgVFFlrDoneReg1 <= unpack(cfgVfFlrInprocReg0[cfgVFFlrFuncNumReg]); + cfgVFFlrFuncNumReg1 <= cfgVFFlrFuncNumReg; + endrule + + interface RawPcieConfiguration rawConfiguration; + + // not use mgmt + interface RawPcieCfgMgmt mgmt; + method PcieCfgMgmtAddr addr; + return 0; + endmethod + + method PcieCfgMgmtByteEn byteEn; + return 0; + endmethod + + method Bool debugAccess; + return False; + endmethod + + method PcieCfgMgmtFuncNum funcNum; + return 0; + endmethod + + method Bool read; + return False; + endmethod + + method PCieCfgMgmtData writeData; + return 0; + endmethod + + method Bool write; + return False; + endmethod + + method Action getResp( + PCieCfgMgmtData cfgMgmtRdData, + Bool cfgMgmtRdWrDone); + endmethod + endinterface + + // assign to 0 + interface RawPcieCfgPm pm; + method Bool aspmL1EntryReject; + return False; + endmethod + method Bool aspmL0EntryDisable; + return False; + endmethod + endinterface + + // Doesn't support msi now + interface RawPcieCfgMsi msi; + method PcieCfgMsiInt msiInt; + return 0; + endmethod + + method PcieCfgMsiFuncNum funcNum; + return 0; + endmethod + + method PcieCfgMsiPendingStatus pendingStatus; + return 0; + endmethod + + method PcieCfgMsiPendingStatusFuncNum pendingStatusFuncNum; + return 0; + endmethod + + method Bool pendingStatusDataEn; + return False; + endmethod + + method PcieCfgMsiSel sel; + return 0; + endmethod + + method PcieCfgMsiAttr attr; + return 0; + endmethod + + method Bool tphPresent; + return False; + endmethod + + method PcieCfgMsiTphType tphType; + return 0; + endmethod + + method PcieCfgMsiTphStTag tphStTag; + return 0; + endmethod + + method Action getMsiSignals( + Bool msiEn, + Bool msiSent, + Bool msiFail, + PcieCfgMsiMmEn msiMmEn, + Bool maskUpdate, + PcieCfgMsiData data); + endmethod + endinterface + + // Only for Legacy Devices + interface RawPcieCfgInterrupt interrupt; + method PcieCfgIntrInt intrInt; + return 0; + endmethod + + method PcieCfgIntrPending intrPending; + return 0; + endmethod + + method Action isIntrSent(Bool isSent); + endmethod + endinterface + + interface RawPcieCfgControl control; + method Bool hotResetOut; + return True; + endmethod + + method Action hotResetIn(Bool hotReset); + endmethod + + method Bool cfgSpaceEn; + return True; + endmethod + + method PcieCfgDsn deviceSerialNum; + return 0; + endmethod + + method PcieCfgDsBusNum downStreamBusNum; + return 0; + endmethod + + method PcieCfgDsDeviceNum downStreamDeviceNum; + return 0; + endmethod + + method PcieCfgDsFuncNum downStreamFuncNum; + return 0; + endmethod + + // TODO: the powerStateChangeAck must waitng for completing Done + method Bool powerStateChangeAck; + return powerStateChangeIntrReg; + endmethod + + method Action powerStateChangeIntr(Bool powerStateChangeIntrrupt); + powerStateChangeIntrReg <= powerStateChangeIntrrupt; + endmethod + + method PcieCfgDsPortNum downStreamPortNum; + return 0; + endmethod + + method Bool errorCorrectableOut; + return False; + endmethod + + method Action getError( + Bool errorCorrectable, + Bool errorFatal, + Bool errorNonFatal); + endmethod + + method Bool errorUncorrectable; + return False; + endmethod + + method PcieCfgFlrDone funcLevelRstDone; + PcieCfgFlrDone cfgFlrDone = 0; + cfgFlrDone[0] = (~cfgFlrDoneReg1[0]) & cfgFlrDoneReg0[0]; + cfgFlrDone[1] = (~cfgFlrDoneReg1[1]) & cfgFlrDoneReg0[1]; + return cfgFlrDone; + endmethod + + method Bool vfFuncLevelRstDone; + return cfgVFFlrDoneReg1; + endmethod + + method PcieCfgVFFlrFuncNum vfFlrFuncNum; + return cfgVFFlrFuncNumReg1; + endmethod + + method Action getInproc( + PcieCfgFlrInProc flrInProcess, + PcieCfgVFFlrInProc vfFlrInProcess + ); + cfgFlrDoneReg0 <= flrInProcess; + cfgVfFlrInprocReg0 <= zeroExtend(vfFlrInProcess); + endmethod + + method Bool reqPmTransL23Ready; + return False; + endmethod + + method Bool linkTrainEn; + return True; + endmethod + + method Action busNumber(PcieCfgBusNum busNum); + endmethod + + method PcieCfgVendId vendId; + return 0; + endmethod + + method PcieCfgVendId subsysVendId; + return 0; + endmethod + + method PcieCfgDevId devIdPf0; + return 0; + endmethod + + method PcieCfgDevId devIdPf1; + return 0; + endmethod + + method PcieCfgDevId devIdPf2; + return 0; + endmethod + + method PcieCfgDevId devIdPf3; + return 0; + endmethod + + method PcieCfgRevId revIdPf0; + return 0; + endmethod + + method PcieCfgRevId revIdPf1; + return 0; + endmethod + + method PcieCfgRevId revIdPf2; + return 0; + endmethod + + method PcieCfgRevId revIdPf3; + return 0; + endmethod + + method PcieCfgSubsysId subsysIdPf0; + return 0; + endmethod + + method PcieCfgSubsysId subsysIdPf1; + return 0; + endmethod + + method PcieCfgSubsysId subsysIdPf2; + return 0; + endmethod + + method PcieCfgSubsysId subsysIdPf3; + return 0; + endmethod + endinterface + + interface RawPcieCfgFC flowControl; + method Action flowControl( + PcieCfgFlowControlHeaderCredit postedHeaderCredit, + PcieCfgFlowControlHeaderCredit nonPostedHeaderCredit, + PcieCfgFlowControlHeaderCredit cmplHeaderCredit, + PcieCfgFlowControlDataCredit postedDataCredit, + PcieCfgFlowControlDataCredit nonPostedDataCredit, + PcieCfgFlowControlDataCredit cmplDataCredit); + endmethod + + method PcieCfgFlowControlSel flowControlSel; + return 0; + endmethod + endinterface + + // Doesn't support sending Meg + interface RawPcieCfgMsgTx msgTx; + method Bool msegTransmit; + return False; + endmethod + + method PcieCfgMsgTransType msegTransmitType; + return 0; + endmethod + + method PcieCfgMsgTransData msegTransmitData; + return 0; + endmethod + + method Action msegTransmitDone(Bool isDone); + endmethod + endinterface + + interface RawPcieCfgMsgRx msgRx; + method Action receiveMsg( + Bool isMsgReceived, + PcieCfgMsgRecvData recvData, + PcieCfgMsgRecvType recvType + ); + endmethod + endinterface + + interface RawPcieCfgStatus status; + method Action getStatus ( + PcieCfgPhyLinkDown phyLinkDown, + PcieCfgPhyLinkStatus phyLinkStatus, + PcieCfgNegotiatedWidth negotiatedWidth, + PCieCfgCurrentSpeed currentSpeed, + PcieCfgMaxPayloadSize maxPayloadSize, + PCieCfgMaxReadReqSize maxReadReqSize, + PcieCfgFunctionStatus functionStatus, + PcieCfgVirtualFuncStatus virtualFuncStatus, + PcieCfgFuncPowerState functionPowerState, + PcieCfgVFPowerState virtualFuncPowerState, + PcieCfgLinkPowerState linkPowerState, + PcieCfgLocalError localError, + Bool localErrorValid, + PcieCfgRxPmState rxPmState, + PcieCfgTxPmState txPmState, + PcieCfgLtssmState ltssmState, + PcieCfgRcbStatus rcbStatus, + PcieCfgDpaSubstageChange dpaSubstageChange, + PcieCfgObffEn obffEnable); + endmethod + endinterface + + interface RawPcieCfgTransmitFC txFlowControl; + method Action getTransCredit( + PcieCfgTfcNphAv nphAvailable, + PcieCfgTfcNpdAv npdAvailable); + endmethod + endinterface + + endinterface + + method PcieCfgLtssmState getPcieLtssmState(); + return 0; + endmethod + +endmodule diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv index a11d8df..65726dc 100755 --- a/src/PcieTypes.bsv +++ b/src/PcieTypes.bsv @@ -143,7 +143,7 @@ typedef Bit#(PCIE_CR_NP_REQ_COUNT_WIDTH) PcieNonPostedRequstCount; // Interface to PCIe IP Completer Interface (*always_ready, always_enabled*) interface RawPcieCompleterRequest; - (* prefix = "s_axis_cq_" *) interface RawPcieAxiStreamSlave#(PCIE_COMPLETER_REQUEST_TUSER_WIDTH) rawAxiStreamSlave; + (* prefix = "s_axis_cq" *) interface RawPcieAxiStreamSlave#(PCIE_COMPLETER_REQUEST_TUSER_WIDTH) rawAxiStreamSlave; (* result = "pcie_cq_np_req" *) method PcieNonPostedRequst nonPostedReqCreditIncrement; (* prefix = "" *) method Action nonPostedReqCreditCnt( (* port = "pcie_cq_np_req_count" *) PcieNonPostedRequstCount nonPostedpReqCount ); @@ -151,7 +151,7 @@ endinterface (*always_ready, always_enabled*) interface RawPcieCompleterComplete; - (* prefix = "m_axis_cc_" *) interface RawPcieAxiStreamMaster#(PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) rawAxiStreamMaster; + (* prefix = "m_axis_cc" *) interface RawPcieAxiStreamMaster#(PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) rawAxiStreamMaster; endinterface typedef 8 PCIE_RQ_TAG_WIDTH; @@ -161,8 +161,8 @@ typedef PcieTlpCtlSeqNum PcieRqSeqNum; // Interface to PCIe IP Requester Interface (*always_ready, always_enabled*) interface RawPcieRequesterRequest; - (* prefix = "m_axis_rq_" *) interface RawPcieAxiStreamMaster#(PCIE_REQUESTER_REQUEST_TUSER_WIDTH) rawAxiStreamMaster; - (* prefix = "pcie_rq_" *) method Action pcieProgressTrack( + (* prefix = "m_axis_rq" *) interface RawPcieAxiStreamMaster#(PCIE_REQUESTER_REQUEST_TUSER_WIDTH) rawAxiStreamMaster; + (* prefix = "pcie_rq" *) method Action pcieProgressTrack( (* port = "tag_vld0" *) Bool tagValid0, (* port = "tag_vld1" *) Bool tagValid1, (* port = "tag0" *) PcieRqTag tag0, @@ -176,7 +176,7 @@ endinterface (*always_ready, always_enabled*) interface RawPcieRequesterComplete; - (* prefix = "s_axis_rc_" *) interface RawPcieAxiStreamSlave#(PCIE_REQUESTER_COMPLETE_TUSER_WIDTH) rawAxiStreamSlave; + (* prefix = "s_axis_rc" *) interface RawPcieAxiStreamSlave#(PCIE_REQUESTER_COMPLETE_TUSER_WIDTH) rawAxiStreamSlave; endinterface // Pcie Configuration Interfaces @@ -199,10 +199,9 @@ interface RawPcieCfgMgmt; (* result = "read" *) method Bool read; (* result = "write_data" *) method PCieCfgMgmtData writeData; (* result = "write" *) method Bool write; - (* prefix = "" *) method Action readData( - (* port = "read_data" *) PCieCfgMgmtData cfgMgmtRdData); - (* prefix = "" *) method Action rdWrDone( - (* port = "read_write_done" *) Bool cfgMgmtRdWrDone); + (* prefix = "" *) method Action getResp( + (* port = "read_data" *) PCieCfgMgmtData cfgMgmtRdData, + (* port = "read_write_done" *) Bool cfgMgmtRdWrDone); endinterface (*always_ready, always_enabled*) @@ -211,34 +210,188 @@ interface RawPcieCfgPm; (* result = "aspm_tx_l0s_entry_disable" *) method Bool aspmL0EntryDisable; endinterface +typedef 4 PCIE_CFG_MSI_ENABLE_WIDTH; +typedef 32 PCIE_CFG_MSI_INT_WIDTH; +typedef 8 PCIE_CFG_MSI_FUNC_NUM_WIDTH; +typedef 12 PCIE_CFG_MSI_MMENABLE_WIDTH; +typedef 32 PCIE_CFG_MSI_PENDING_STATUS_WIDTH; +typedef 2 PCIE_CFG_MSI_PENDING_STATUS_FUNC_NUM_WIDTH; +typedef 2 PCIE_CFG_MSI_SELECT_WIDTH; +typedef 32 PCIE_CFG_MSI_DATA; +typedef 3 PCIE_CFG_MSI_ATTR; +typedef 2 PCIE_CFG_MSI_TPH_TYPE_WIDTH; +typedef 8 PCIE_CFG_MSI_TPH_ST_TAG_WIDTH; + +typedef Bit#(PCIE_CFG_MSI_ENABLE_WIDTH) PcieCfgMsiEn; +typedef Bit#(PCIE_CFG_MSI_INT_WIDTH) PcieCfgMsiInt; +typedef Bit#(PCIE_CFG_MSI_FUNC_NUM_WIDTH) PcieCfgMsiFuncNum; +typedef Bit#(PCIE_CFG_MSI_MMENABLE_WIDTH) PcieCfgMsiMmEn; +typedef Bit#(PCIE_CFG_MSI_PENDING_STATUS_WIDTH) PcieCfgMsiPendingStatus; +typedef Bit#(PCIE_CFG_MSI_PENDING_STATUS_FUNC_NUM_WIDTH) PcieCfgMsiPendingStatusFuncNum; +typedef Bit#(PCIE_CFG_MSI_SELECT_WIDTH) PcieCfgMsiSel; +typedef Bit#(PCIE_CFG_MSI_DATA) PcieCfgMsiData; +typedef Bit#(PCIE_CFG_MSI_ATTR) PcieCfgMsiAttr; +typedef Bit#(PCIE_CFG_MSI_TPH_TYPE_WIDTH) PcieCfgMsiTphType; +typedef Bit#(PCIE_CFG_MSI_TPH_ST_TAG_WIDTH) PcieCfgMsiTphStTag; + (*always_ready, always_enabled*) interface RawPcieCfgMsi; - + (* result = "int" *) method PcieCfgMsiInt msiInt; + (* result = "function_number" *) method PcieCfgMsiFuncNum funcNum; + (* result = "pending_status" *) method PcieCfgMsiPendingStatus pendingStatus; + (* result = "pending_status_function_num" *) method PcieCfgMsiPendingStatusFuncNum pendingStatusFuncNum; + (* result = "pending_status_data_enable" *) method Bool pendingStatusDataEn; + (* result = "select" *) method PcieCfgMsiSel sel; + (* result = "attr" *) method PcieCfgMsiAttr attr; + (* result = "tph_present" *) method Bool tphPresent; + (* result = "tph_type" *) method PcieCfgMsiTphType tphType; + (* result = "tph_st_tag" *) method PcieCfgMsiTphStTag tphStTag; + (* prefix = "" *) method Action getMsiSignals( + (* port = "enable" *) Bool msiEn, + (* port = "sent" *) Bool msiSent, + (* port = "fail" *) Bool msiFail, + (* port = "mmenable" *) PcieCfgMsiMmEn msiMmEn, + (* port = "mask_update" *) Bool maskUpdate, + (* port = "data" *) PcieCfgMsiData data + ); endinterface +typedef 4 PCIE_CFG_INTR_INT_WIDTH; +typedef 4 PCIE_CFG_INTR_PENDING_WIDTH; +typedef Bit#(PCIE_CFG_INTR_INT_WIDTH) PcieCfgIntrInt; +typedef Bit#(PCIE_CFG_INTR_PENDING_WIDTH) PcieCfgIntrPending; + (*always_ready, always_enabled*) interface RawPcieCfgInterrupt; - + (* result = "int" *) method PcieCfgIntrInt intrInt; + (* result = "pending" *) method PcieCfgIntrPending intrPending; + (* prefix = "" *) method Action isIntrSent( + (* port = "sent" *) Bool isSent); endinterface +typedef 64 PCIE_CFG_DSN_WIDTH; +typedef Bit#(PCIE_CFG_DSN_WIDTH) PcieCfgDsn; + +typedef 8 PCIE_CFG_DS_BUS_NUM_WIDTH; +typedef 5 PCIE_CFG_DS_DEVICE_NUM_WIDTH; +typedef 3 PCIE_CFG_DS_FUNC_NUM_WIDTH; +typedef 8 PCIE_CFG_DS_PORT_NUM_WIDTH; +typedef Bit#(PCIE_CFG_DS_BUS_NUM_WIDTH) PcieCfgDsBusNum; +typedef Bit#(PCIE_CFG_DS_DEVICE_NUM_WIDTH) PcieCfgDsDeviceNum; +typedef Bit#(PCIE_CFG_DS_FUNC_NUM_WIDTH) PcieCfgDsFuncNum; +typedef Bit#(PCIE_CFG_DS_PORT_NUM_WIDTH) PcieCfgDsPortNum; + +typedef 4 PCIE_CFG_FLR_DONE_WIDTH; +typedef 8 PCIE_CFG_VF_FLR_FUNCNUM_WIDTH; +typedef 4 PCIE_CFG_FLR_INPROC_WIDTH; +typedef 252 PCIE_CFG_VF_FLR_INPROC_WIDTH; +typedef Bit#(PCIE_CFG_FLR_DONE_WIDTH) PcieCfgFlrDone; +typedef Bit#(PCIE_CFG_VF_FLR_FUNCNUM_WIDTH) PcieCfgVFFlrFuncNum; +typedef Bit#(PCIE_CFG_FLR_DONE_WIDTH) PcieCfgFlrInProc; +typedef Bit#(PCIE_CFG_VF_FLR_INPROC_WIDTH) PcieCfgVFFlrInProc; + +typedef 8 PCIE_CFG_BUS_NUM_WIDTH; +typedef 16 PCIE_CFG_VEND_ID_WIDTH; +typedef 16 PCIE_CFG_DEV_ID_WIDTH; +typedef 8 PCIE_CFG_REV_ID_WIDTH; +typedef 16 PCIE_CFG_SUBSYS_ID_WIDTH; +typedef Bit#(PCIE_CFG_BUS_NUM_WIDTH) PcieCfgBusNum; +typedef Bit#(PCIE_CFG_VEND_ID_WIDTH) PcieCfgVendId; +typedef Bit#(PCIE_CFG_DEV_ID_WIDTH) PcieCfgDevId; +typedef Bit#(PCIE_CFG_REV_ID_WIDTH) PcieCfgRevId; +typedef Bit#(PCIE_CFG_SUBSYS_ID_WIDTH) PcieCfgSubsysId; + (*always_ready, always_enabled*) interface RawPcieCfgControl; - + (* result = "hot_reset_out" *) method Bool hotResetOut; + (* prefix = "" *) method Action hotResetIn( + (* port = "hot_reset_in" *) Bool hotReset); + (* result = "cofig_space_enable" *) method Bool cfgSpaceEn; + (* result = "dsn" *) method PcieCfgDsn deviceSerialNum; + (* result = "ds_bus_number" *) method PcieCfgDsBusNum downStreamBusNum; + (* result = "ds_device_number" *) method PcieCfgDsDeviceNum downStreamDeviceNum; + (* result = "ds_function_number" *) method PcieCfgDsFuncNum downStreamFuncNum; + (* result = "power_state_change_ack" *) method Bool powerStateChangeAck; + (* prefix = "" *) method Action powerStateChangeIntr( + (* port = "power_state_change_interrupt" *) Bool powerStateChangeIntrrupt); + (* result = "ds_port_number" *) method PcieCfgDsPortNum downStreamPortNum; + (* result = "err_cor_in" *) method Bool errorCorrectableOut; + (* prefix = "" *) method Action getError( + (* port = "err_cor_out" *) Bool errorCorrectable, + (* port = "err_fatal_out" *) Bool errorFatal, + (* port = "err_nonfatal_out" *) Bool errorNonFatal); + (* result = "err_uncor_in" *) method Bool errorUncorrectable; + (* result = "flr_done" *) method PcieCfgFlrDone funcLevelRstDone; + (* result = "vf_flr_done" *) method Bool vfFuncLevelRstDone; + (* result = "cf_flr_func_num" *) method PcieCfgVFFlrFuncNum vfFlrFuncNum; + (* prefix = "" *) method Action getInproc( + (* port = "flr_in_process" *) PcieCfgFlrInProc flrInProcess, + (* port = "vf_flr_in_process" *) PcieCfgVFFlrInProc vfFlrInProcess); + (* result = "req_pm_transition_l23_ready" *) method Bool reqPmTransL23Ready; + (* result = "link_training_enable" *) method Bool linkTrainEn; + (* prefix = "" *) method Action busNumber( + (* port = "bus_number" *) PcieCfgBusNum busNum); + (* result = "vend_id" *) method PcieCfgVendId vendId; + (* result = "subsys_vend_id" *) method PcieCfgVendId subsysVendId; + (* result = "dev_id_pf0" *) method PcieCfgDevId devIdPf0; + (* result = "dev_id_pf1" *) method PcieCfgDevId devIdPf1; + (* result = "dev_id_pf2" *) method PcieCfgDevId devIdPf2; + (* result = "dev_id_pf3" *) method PcieCfgDevId devIdPf3; + (* result = "rev_id_pf0" *) method PcieCfgRevId revIdPf0; + (* result = "rev_id_pf1" *) method PcieCfgRevId revIdPf1; + (* result = "rev_id_pf2" *) method PcieCfgRevId revIdPf2; + (* result = "rev_id_pf3" *) method PcieCfgRevId revIdPf3; + (* result = "subsys_id_pf0" *) method PcieCfgSubsysId subsysIdPf0; + (* result = "subsys_id_pf1" *) method PcieCfgSubsysId subsysIdPf1; + (* result = "subsys_id_pf2" *) method PcieCfgSubsysId subsysIdPf2; + (* result = "subsys_id_pf3" *) method PcieCfgSubsysId subsysIdPf3; endinterface +typedef 8 PCIE_CFG_FC_HEADER_WIDTH; +typedef 12 PCIE_CFG_FC_DATA_WIDTH; +typedef 3 PCIE_CFG_FC_SEL_WIDTH; +typedef Bit#(PCIE_CFG_FC_HEADER_WIDTH) PcieCfgFlowControlHeaderCredit; +typedef Bit#(PCIE_CFG_FC_DATA_WIDTH) PcieCfgFlowControlDataCredit; +typedef Bit#(PCIE_CFG_FC_SEL_WIDTH) PcieCfgFlowControlSel; + (*always_ready, always_enabled*) interface RawPcieCfgFC; - + (* prefix = "" *) method Action flowControl( + (* port = "ph" *) PcieCfgFlowControlHeaderCredit postedHeaderCredit, + (* port = "nph" *) PcieCfgFlowControlHeaderCredit nonPostedHeaderCredit, + (* port = "cplh" *) PcieCfgFlowControlHeaderCredit cmplHeaderCredit, + (* port = "pd" *) PcieCfgFlowControlDataCredit postedDataCredit, + (* port = "npd" *) PcieCfgFlowControlDataCredit nonPostedDataCredit, + (* port = "cpld" *) PcieCfgFlowControlDataCredit cmplDataCredit + ); + (* result = "fc_sel" *) method PcieCfgFlowControlSel flowControlSel; endinterface +typedef 3 PCIE_CFG_MSG_TXTYPE_WIDTH; +typedef 32 PCIE_CFG_MSG_TXDATA_WIDTH; +typedef Bit#(PCIE_CFG_MSG_TXTYPE_WIDTH) PcieCfgMsgTransType; +typedef Bit#(PCIE_CFG_MSG_TXDATA_WIDTH) PcieCfgMsgTransData; (*always_ready, always_enabled*) interface RawPcieCfgMsgTx; - + (* result = "transmit" *) method Bool msegTransmit; + (* result = "transmit_type" *) method PcieCfgMsgTransType msegTransmitType; + (* result = "transmit_data" *) method PcieCfgMsgTransData msegTransmitData; + (* prefix = "" *) method Action msegTransmitDone( + (* port = "transmit_done" *) Bool isDone); endinterface +typedef 8 PCIE_CFG_MSG_RXDATA_WIDTH; +typedef 5 PCIE_CFG_MSG_RXTYPE_WIDTH; +typedef Bit#(PCIE_CFG_MSG_RXTYPE_WIDTH) PcieCfgMsgRecvType; +typedef Bit#(PCIE_CFG_MSG_RXDATA_WIDTH) PcieCfgMsgRecvData; + (*always_ready, always_enabled*) interface RawPcieCfgMsgRx; - + method Action receiveMsg( + (* port = "received" *) Bool isMsgReceived, + (* port = "received_data" *) PcieCfgMsgRecvData recvData, + (* port = "received_type" *) PcieCfgMsgRecvType recvType + ); endinterface typedef 1 PCIE_CFG_PHY_LINK_DOWN_WIDTH; @@ -287,7 +440,7 @@ typedef Bit#(PCIE_CFG_OBFF_ENABLE_WIDTH) PcieCfgObffEn; (*always_ready, always_enabled*) interface RawPcieCfgStatus; - method Action getStatus ( + (* prefix = "" *) method Action getStatus ( (* port = "phy_link_down" *) PcieCfgPhyLinkDown phyLinkDown, (* port = "phy_link_status" *) PcieCfgPhyLinkStatus phyLinkStatus, (* port = "negotiated_width" *) PcieCfgNegotiatedWidth negotiatedWidth, @@ -310,21 +463,37 @@ interface RawPcieCfgStatus; ); endinterface +typedef 4 PCIE_CFG_TFC_NPH_WIDTH; +typedef 4 PCIE_CFG_TFC_NPD_WIDTH; +typedef Bit#(PCIE_CFG_TFC_NPH_WIDTH) PcieCfgTfcNphAv; +typedef Bit#(PCIE_CFG_TFC_NPD_WIDTH) PcieCfgTfcNpdAv; + (*always_ready, always_enabled*) interface RawPcieCfgTransmitFC; - + (* prefix = "" *) method Action getTransCredit( + (* port = "nph_av" *) PcieCfgTfcNphAv nphAvailable, + (* port = "npd_av" *) PcieCfgTfcNpdAv npdAvailable + ); endinterface interface RawPcieConfiguration; - (* prefix = "cfg_mgmt_" *) interface RawPcieCfgMgmt mgmt; - (* prefix = "cfg_pm_" *) interface RawPcieCfgPm pm; - (* prefix = "cfg_msi_" *) interface RawPcieCfgMsi msi; - (* prefix = "cfg_interrupt_" *) interface RawPcieCfgInterrupt interrupt; - (* prefix = "cfg_" *) interface RawPcieCfgControl control; - (* prefix = "cfg_fc_" *) interface RawPcieCfgFC flowControl; - (* prefix = "cfg_msg_transmit_" *) interface RawPcieCfgMsgTx msgTx; - (* prefix = "cfg_msg_received_" *) interface RawPcieCfgMsgRx msgRx; + (* prefix = "cfg_mgmt" *) interface RawPcieCfgMgmt mgmt; + (* prefix = "cfg_pm" *) interface RawPcieCfgPm pm; + (* prefix = "cfg_msi" *) interface RawPcieCfgMsi msi; + (* prefix = "cfg_interrupt" *) interface RawPcieCfgInterrupt interrupt; + (* prefix = "cfg" *) interface RawPcieCfgControl control; + (* prefix = "cfg_fc" *) interface RawPcieCfgFC flowControl; + (* prefix = "cfg_msg" *) interface RawPcieCfgMsgTx msgTx; + (* prefix = "cfg_msg" *) interface RawPcieCfgMsgRx msgRx; (* prefix = "" *) interface RawPcieCfgStatus status; - (* prefix = "pcie_tfc_" *) interface RawPcieCfgTransmitFC txFlowControl; + (* prefix = "pcie_tfc" *) interface RawPcieCfgTransmitFC txFlowControl; endinterface +interface RawXilinxPcieIp; + // Raw PCIe interfaces, connected to the Xilinx PCIe IP + (* prefix = "" *) interface RawPcieRequesterRequest requesterRequest; + (* prefix = "" *) interface RawPcieRequesterComplete requesterComplete; + (* prefix = "" *) interface RawPcieCompleterRequest completerRequest; + (* prefix = "" *) interface RawPcieCompleterComplete completerComplete; + (* prefix = "" *) interface RawPcieConfiguration configuration; +endinterface diff --git a/test/TestDmaCompleter.bsv b/test/TestDmaCompleter.bsv index c2b36a2..626c5c5 100644 --- a/test/TestDmaCompleter.bsv +++ b/test/TestDmaCompleter.bsv @@ -94,4 +94,53 @@ module mkTestDmaCompleterRequest(Empty); $finish(); endrule -endmodule \ No newline at end of file +endmodule + +(* doc = "testcase" *) +module mkTestDmaCompleter(Empty); + DmaCompleter dut <- mkDmaCompleter; + Reg#(Bool) isInitReg <- mkReg(False); + + rule alwaysEnables; + dut.rawCompleterComplete.rawAxiStreamMaster.tReady(True); + dut.rawCompleterRequest.nonPostedReqCreditCnt(32); + endrule + + rule testInit; + let testAxiStram = genPseudoHostWriteRequest; + if (!isInitReg) begin + $display("INFO: Start Completer test"); + dut.rawCompleterRequest.rawAxiStreamSlave.tValid( + True, + testAxiStram.tData, + testAxiStram.tKeep, + testAxiStram.tLast, + testAxiStram.tUser + ); + isInitReg <= True; + end + else begin + dut.rawCompleterRequest.rawAxiStreamSlave.tValid( + False, + 0, + 0, + False, + 0 + ); + end + endrule + + rule testOutput if (isInitReg); + let wrData = dut.h2cWrite.dataFifoOut.first; + dut.h2cWrite.dataFifoOut.deq; + let wrAddr = dut.h2cWrite.reqFifoOut.first; + dut.h2cWrite.reqFifoOut.deq; + immAssert( + (wrAddr == fromInteger(valueOf(TEST_ADDR)) && wrData == fromInteger(valueOf(TEST_DATA))), + "wrReq test @ mkTestDmaCompleter", + $format("write value: %h, write addr: %h", wrData, wrAddr) + ); + $display("INFO: Pass Completer test"); + $finish(); + endrule +endmodule diff --git a/test/TestDmacVivado.bsv b/test/TestDmacVivado.bsv new file mode 100644 index 0000000..49d007c --- /dev/null +++ b/test/TestDmacVivado.bsv @@ -0,0 +1,63 @@ +import FIFOF::*; +import BRAM::*; +import GetPut::*; + +import SemiFifo::*; +import PcieTypes::*; +import DmaTypes::*; +import DmaController::*; + +typedef 16384 TEST_BRAM_SIZE; + +interface TestDmacWrRdLoop; + (* prefix = "" *) interface RawXilinxPcieIp rawPcie; +endinterface + +(* synthesize *) +module mkTestDmacCsrWrRdLoop(TestDmacWrRdLoop); + + DmaController dmac <- mkDmaController; + + BRAM2Port#(DmaCsrAddr, DmaCsrValue) ram <- mkBRAM2Server( + BRAM_Configure { + memorySize : valueOf(TEST_BRAM_SIZE), + loadFormat : None, + latency : 2, + outFIFODepth: 3, + allowWriteResponseBypass : False + } + ); + + rule testWriteReq; + dmac.h2cWrite.dataFifoOut.deq; + dmac.h2cWrite.reqFifoOut.deq; + ram.portA.request.put( + BRAMRequest { + write : True, + responseOnWrite : False, + address : dmac.h2cWrite.reqFifoOut.first, + datain : dmac.h2cWrite.dataFifoOut.first + } + ); + endrule + + rule testReadReq; + dmac.h2cRead.reqFifoOut.deq; + ram.portB.request.put( + BRAMRequest { + write : False, + responseOnWrite : False, + address : dmac.h2cRead.reqFifoOut.first, + datain : 0 + } + ); + endrule + + rule testReadResp; + let value <- ram.portB.response.get; + dmac.h2cRead.dataFifoIn.enq(value); + endrule + + interface rawPcie = dmac.rawPcie; +endmodule + From 438dda2966798151143bf4dba3c156a12151b7fd Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Tue, 23 Jul 2024 21:08:06 +0800 Subject: [PATCH 27/53] Update rawPcie interfaces --- src/DmaCompleter.bsv | 49 +++++++++++++++++++++++++++++++------ src/DmaController.bsv | 2 ++ src/PcieDescriptorTypes.bsv | 1 + src/PcieTypes.bsv | 44 ++++++++++++++++++--------------- test/TestDmacVivado.bsv | 4 +-- 5 files changed, 71 insertions(+), 29 deletions(-) diff --git a/src/DmaCompleter.bsv b/src/DmaCompleter.bsv index aa2afdf..93757b2 100644 --- a/src/DmaCompleter.bsv +++ b/src/DmaCompleter.bsv @@ -32,8 +32,8 @@ endinstance typedef DmaCsrValue CsrReadResp; typedef struct { - DmaCsrAddr rdAddr; - PcieCompleterRequestDescriptor npInfo; + DmaCsrAddr addr; + PcieCompleterRequestDescriptor cqDescriptor; } CsrReadReq deriving(Bits, Eq, Bounded, FShow); interface DmaCompleter; @@ -90,7 +90,7 @@ module mkCompleterRequest(CompleterRequest); return truncate(addr); endfunction - rule parse; + rule parseTlp; inFifo.deq; let axiStream = inFifo.first; PcieCompleterRequestSideBandFrame sideBand = unpack(axiStream.tUser); @@ -117,8 +117,8 @@ module mkCompleterRequest(CompleterRequest); fromInteger(valueOf(MEM_READ_REQ)): begin let rdReqAddr = getCsrAddrFromCqDescriptor(descriptor); let rdReq = CsrReadReq{ - rdAddr: rdReqAddr, - npInfo: descriptor + addr: rdReqAddr, + cqDescriptor: descriptor }; rdReqFifo.enq(rdReq); end @@ -137,7 +137,42 @@ module mkCompleterComplete(CompleterComplete); FIFOF#(CsrReadResp) rdRespFifo <- mkFIFOF; FIFOF#(CsrReadReq) rdReqFifo <- mkFIFOF; - // TODO: the logic of cc + // TODO: the logic of cc, not completed + rule genTlp; + let value = rdRespFifo.first; + rdRespFifo.deq; + let cqDescriptor = rdReqFifo.first.cqDescriptor; + let addr = rdReqFifo.first.addr; + rdReqFifo.deq; + let ccDescriptor = PcieCompleterCompleteDescriptor { + reserve0 : 0, + attributes : cqDescriptor.attributes, + trafficClass : cqDescriptor.trafficClass, + completerIdEn : False, + completerId : 0, + tag : cqDescriptor.tag, + requesterId : cqDescriptor.requesterId, + reserve1 : 0, + isPoisoned : False, + status : 0, + dwordCnt : 0, + reserve2 : 0, + isLockedReadCmpl: False, + byteCnt : 0, + reserve3 : 0, + addrType : 0, + lowerAddr : 0 + }; + Data data = zeroExtend(pack(ccDescriptor)); + data = data | (zeroExtend(value) << valueOf(DES_CC_DESCRIPTOR_WIDTH)); + let axiStream = CmplCmplAxiStream { + tData : data, + tKeep : 0, + tLast : True, + tUser : 0 + }; + outFifo.enq(axiStream); + endrule interface axiStreamFifoOut = convertFifoToFifoOut(outFifo); interface csrReadRespFifoIn = convertFifoToFifoIn(rdRespFifo); @@ -171,7 +206,7 @@ module mkDmaCompleter(DmaCompleter); rule genCsrReadReq; let rdReq = cmplRequest.csrReadReqFifoOut.first; cmplRequest.csrReadReqFifoOut.deq; - h2cCsrReadReqFifo.enq(rdReq.rdAddr); + h2cCsrReadReqFifo.enq(rdReq.addr); csrRdReqStoreFifo.enq(rdReq); endrule diff --git a/src/DmaController.bsv b/src/DmaController.bsv index e38bfb1..c169ab8 100755 --- a/src/DmaController.bsv +++ b/src/DmaController.bsv @@ -37,5 +37,7 @@ module mkDmaController(DmaController); interface completerRequest = completer.rawCompleterRequest; interface completerComplete = completer.rawCompleterComplete; interface configuration = pcieConfigurator.rawConfiguration; + method Action linkUp(Bool isLinkUp); + endmethod endinterface endmodule diff --git a/src/PcieDescriptorTypes.bsv b/src/PcieDescriptorTypes.bsv index bcd9b22..7a92912 100644 --- a/src/PcieDescriptorTypes.bsv +++ b/src/PcieDescriptorTypes.bsv @@ -53,6 +53,7 @@ typedef struct { AddrType addrType; } PcieCompleterRequestDescriptor deriving(Bits, Eq, Bounded, FShow); +typedef 96 DES_CC_DESCRIPTOR_WIDTH; typedef 3 DES_CMPL_STATUS_WIDTH; typedef 13 DES_CMPL_BYTE_CNT_WIDTH; typedef 7 DES_LOWER_ADDR_WIDTH; diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv index 65726dc..d88d205 100755 --- a/src/PcieTypes.bsv +++ b/src/PcieTypes.bsv @@ -141,7 +141,7 @@ typedef Bit#(PCIE_CR_NP_REQ_WIDTH) PcieNonPostedRequst; typedef Bit#(PCIE_CR_NP_REQ_COUNT_WIDTH) PcieNonPostedRequstCount; // Interface to PCIe IP Completer Interface -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieCompleterRequest; (* prefix = "s_axis_cq" *) interface RawPcieAxiStreamSlave#(PCIE_COMPLETER_REQUEST_TUSER_WIDTH) rawAxiStreamSlave; (* result = "pcie_cq_np_req" *) method PcieNonPostedRequst nonPostedReqCreditIncrement; @@ -149,7 +149,7 @@ interface RawPcieCompleterRequest; (* port = "pcie_cq_np_req_count" *) PcieNonPostedRequstCount nonPostedpReqCount ); endinterface -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieCompleterComplete; (* prefix = "m_axis_cc" *) interface RawPcieAxiStreamMaster#(PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) rawAxiStreamMaster; endinterface @@ -159,7 +159,7 @@ typedef Bit#(PCIE_RQ_TAG_WIDTH) PcieRqTag; typedef PcieTlpCtlSeqNum PcieRqSeqNum; // Interface to PCIe IP Requester Interface -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieRequesterRequest; (* prefix = "m_axis_rq" *) interface RawPcieAxiStreamMaster#(PCIE_REQUESTER_REQUEST_TUSER_WIDTH) rawAxiStreamMaster; (* prefix = "pcie_rq" *) method Action pcieProgressTrack( @@ -174,7 +174,7 @@ interface RawPcieRequesterRequest; ); endinterface -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieRequesterComplete; (* prefix = "s_axis_rc" *) interface RawPcieAxiStreamSlave#(PCIE_REQUESTER_COMPLETE_TUSER_WIDTH) rawAxiStreamSlave; endinterface @@ -190,7 +190,7 @@ typedef Bit#(PCIE_CFG_MGMT_BE_WIDTH) PcieCfgMgmtByteEn; typedef Bit#(PCIE_CFG_MGMT_FUNC_NUM_WIDTH) PcieCfgMgmtFuncNum; typedef Bit#(PCIE_CFG_MGMT_DATA_WIDTH) PCieCfgMgmtData; -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieCfgMgmt; (* result = "addr" *) method PcieCfgMgmtAddr addr; (* result = "byte_enable" *) method PcieCfgMgmtByteEn byteEn; @@ -204,7 +204,7 @@ interface RawPcieCfgMgmt; (* port = "read_write_done" *) Bool cfgMgmtRdWrDone); endinterface -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieCfgPm; (* result = "aspm_l1_entry_reject" *) method Bool aspmL1EntryReject; (* result = "aspm_tx_l0s_entry_disable" *) method Bool aspmL0EntryDisable; @@ -234,7 +234,7 @@ typedef Bit#(PCIE_CFG_MSI_ATTR) PcieCfgMsiAttr; typedef Bit#(PCIE_CFG_MSI_TPH_TYPE_WIDTH) PcieCfgMsiTphType; typedef Bit#(PCIE_CFG_MSI_TPH_ST_TAG_WIDTH) PcieCfgMsiTphStTag; -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieCfgMsi; (* result = "int" *) method PcieCfgMsiInt msiInt; (* result = "function_number" *) method PcieCfgMsiFuncNum funcNum; @@ -261,7 +261,7 @@ typedef 4 PCIE_CFG_INTR_PENDING_WIDTH; typedef Bit#(PCIE_CFG_INTR_INT_WIDTH) PcieCfgIntrInt; typedef Bit#(PCIE_CFG_INTR_PENDING_WIDTH) PcieCfgIntrPending; -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieCfgInterrupt; (* result = "int" *) method PcieCfgIntrInt intrInt; (* result = "pending" *) method PcieCfgIntrPending intrPending; @@ -301,12 +301,12 @@ typedef Bit#(PCIE_CFG_DEV_ID_WIDTH) PcieCfgDevId; typedef Bit#(PCIE_CFG_REV_ID_WIDTH) PcieCfgRevId; typedef Bit#(PCIE_CFG_SUBSYS_ID_WIDTH) PcieCfgSubsysId; -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieCfgControl; (* result = "hot_reset_out" *) method Bool hotResetOut; (* prefix = "" *) method Action hotResetIn( (* port = "hot_reset_in" *) Bool hotReset); - (* result = "cofig_space_enable" *) method Bool cfgSpaceEn; + (* result = "config_space_enable" *) method Bool cfgSpaceEn; (* result = "dsn" *) method PcieCfgDsn deviceSerialNum; (* result = "ds_bus_number" *) method PcieCfgDsBusNum downStreamBusNum; (* result = "ds_device_number" *) method PcieCfgDsDeviceNum downStreamDeviceNum; @@ -323,7 +323,7 @@ interface RawPcieCfgControl; (* result = "err_uncor_in" *) method Bool errorUncorrectable; (* result = "flr_done" *) method PcieCfgFlrDone funcLevelRstDone; (* result = "vf_flr_done" *) method Bool vfFuncLevelRstDone; - (* result = "cf_flr_func_num" *) method PcieCfgVFFlrFuncNum vfFlrFuncNum; + (* result = "vf_flr_func_num" *) method PcieCfgVFFlrFuncNum vfFlrFuncNum; (* prefix = "" *) method Action getInproc( (* port = "flr_in_process" *) PcieCfgFlrInProc flrInProcess, (* port = "vf_flr_in_process" *) PcieCfgVFFlrInProc vfFlrInProcess); @@ -354,7 +354,7 @@ typedef Bit#(PCIE_CFG_FC_HEADER_WIDTH) PcieCfgFlowControlHeaderCredit; typedef Bit#(PCIE_CFG_FC_DATA_WIDTH) PcieCfgFlowControlDataCredit; typedef Bit#(PCIE_CFG_FC_SEL_WIDTH) PcieCfgFlowControlSel; -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieCfgFC; (* prefix = "" *) method Action flowControl( (* port = "ph" *) PcieCfgFlowControlHeaderCredit postedHeaderCredit, @@ -364,14 +364,14 @@ interface RawPcieCfgFC; (* port = "npd" *) PcieCfgFlowControlDataCredit nonPostedDataCredit, (* port = "cpld" *) PcieCfgFlowControlDataCredit cmplDataCredit ); - (* result = "fc_sel" *) method PcieCfgFlowControlSel flowControlSel; + (* result = "sel" *) method PcieCfgFlowControlSel flowControlSel; endinterface typedef 3 PCIE_CFG_MSG_TXTYPE_WIDTH; typedef 32 PCIE_CFG_MSG_TXDATA_WIDTH; typedef Bit#(PCIE_CFG_MSG_TXTYPE_WIDTH) PcieCfgMsgTransType; typedef Bit#(PCIE_CFG_MSG_TXDATA_WIDTH) PcieCfgMsgTransData; -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieCfgMsgTx; (* result = "transmit" *) method Bool msegTransmit; (* result = "transmit_type" *) method PcieCfgMsgTransType msegTransmitType; @@ -385,9 +385,9 @@ typedef 5 PCIE_CFG_MSG_RXTYPE_WIDTH; typedef Bit#(PCIE_CFG_MSG_RXTYPE_WIDTH) PcieCfgMsgRecvType; typedef Bit#(PCIE_CFG_MSG_RXDATA_WIDTH) PcieCfgMsgRecvData; -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieCfgMsgRx; - method Action receiveMsg( + (* prefix = "" *) method Action receiveMsg( (* port = "received" *) Bool isMsgReceived, (* port = "received_data" *) PcieCfgMsgRecvData recvData, (* port = "received_type" *) PcieCfgMsgRecvType recvType @@ -438,7 +438,7 @@ typedef Bit#(PCIE_CFG_DPA_SUBSTAGE_CHANGE_WIDTH) PcieCfgDpaSubstageChange; typedef Bit#(PCIE_CFG_OBFF_ENABLE_WIDTH) PcieCfgObffEn; -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieCfgStatus; (* prefix = "" *) method Action getStatus ( (* port = "phy_link_down" *) PcieCfgPhyLinkDown phyLinkDown, @@ -468,7 +468,7 @@ typedef 4 PCIE_CFG_TFC_NPD_WIDTH; typedef Bit#(PCIE_CFG_TFC_NPH_WIDTH) PcieCfgTfcNphAv; typedef Bit#(PCIE_CFG_TFC_NPD_WIDTH) PcieCfgTfcNpdAv; -(*always_ready, always_enabled*) +(* always_ready, always_enabled *) interface RawPcieCfgTransmitFC; (* prefix = "" *) method Action getTransCredit( (* port = "nph_av" *) PcieCfgTfcNphAv nphAvailable, @@ -476,19 +476,21 @@ interface RawPcieCfgTransmitFC; ); endinterface +(* always_ready, always_enabled *) interface RawPcieConfiguration; (* prefix = "cfg_mgmt" *) interface RawPcieCfgMgmt mgmt; (* prefix = "cfg_pm" *) interface RawPcieCfgPm pm; - (* prefix = "cfg_msi" *) interface RawPcieCfgMsi msi; + (* prefix = "cfg_interrupt_msi" *) interface RawPcieCfgMsi msi; (* prefix = "cfg_interrupt" *) interface RawPcieCfgInterrupt interrupt; (* prefix = "cfg" *) interface RawPcieCfgControl control; (* prefix = "cfg_fc" *) interface RawPcieCfgFC flowControl; (* prefix = "cfg_msg" *) interface RawPcieCfgMsgTx msgTx; (* prefix = "cfg_msg" *) interface RawPcieCfgMsgRx msgRx; - (* prefix = "" *) interface RawPcieCfgStatus status; + (* prefix = "cfg" *) interface RawPcieCfgStatus status; (* prefix = "pcie_tfc" *) interface RawPcieCfgTransmitFC txFlowControl; endinterface +(* always_ready, always_enabled *) interface RawXilinxPcieIp; // Raw PCIe interfaces, connected to the Xilinx PCIe IP (* prefix = "" *) interface RawPcieRequesterRequest requesterRequest; @@ -496,4 +498,6 @@ interface RawXilinxPcieIp; (* prefix = "" *) interface RawPcieCompleterRequest completerRequest; (* prefix = "" *) interface RawPcieCompleterComplete completerComplete; (* prefix = "" *) interface RawPcieConfiguration configuration; + (* prefix = "" *) method Action linkUp( + (* port = "user_lnk_up" *) Bool isLinkUp); endinterface diff --git a/test/TestDmacVivado.bsv b/test/TestDmacVivado.bsv index 49d007c..d5b290d 100644 --- a/test/TestDmacVivado.bsv +++ b/test/TestDmacVivado.bsv @@ -13,8 +13,8 @@ interface TestDmacWrRdLoop; (* prefix = "" *) interface RawXilinxPcieIp rawPcie; endinterface -(* synthesize *) -module mkTestDmacCsrWrRdLoop(TestDmacWrRdLoop); +(* synthesize, clock_prefix = "user_clk", reset_prefix = "user_reset" *) +module mkTestDmacCsrWrRdLoop((* reset="sys_rst" *) Reset sysRst, TestDmacWrRdLoop ifc); DmaController dmac <- mkDmaController; From ec3c3f4ee48e6b359a81ce5144c20c283580c12b Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Thu, 25 Jul 2024 12:24:20 +0800 Subject: [PATCH 28/53] Finish CsrWrRd --- src/DmaCompleter.bsv | 40 +++++++++---- src/DmaController.bsv | 22 +++++++ src/DmaTypes.bsv | 7 ++- src/PcieConfigurator.bsv | 2 +- src/PcieDescriptorTypes.bsv | 4 ++ src/PcieTypes.bsv | 6 ++ src/PrimUtils.bsv | 16 +++++ test/TestDmaCompleter.bsv | 114 +++++++++++++++++++++++++----------- test/TestDmacVivado.bsv | 57 ++++++++++++++++++ 9 files changed, 220 insertions(+), 48 deletions(-) diff --git a/src/DmaCompleter.bsv b/src/DmaCompleter.bsv index 93757b2..1df2da9 100644 --- a/src/DmaCompleter.bsv +++ b/src/DmaCompleter.bsv @@ -1,4 +1,5 @@ import FIFOF::*; +import Vector::*; import SemiFifo::*; import PrimUtils::*; @@ -8,6 +9,7 @@ import PcieDescriptorTypes::*; import DmaTypes::*; typedef 1 IDEA_DWORD_CNT_OF_CSR; +typedef 4 IDEA_BYTE_CNT_OF_CSR; typedef 4 IDEA_FIRST_BE_HIGH_VALID_PTR_OF_CSR; typedef 64 CMPL_NPREQ_INFLIGHT_NUM; @@ -15,6 +17,9 @@ typedef 20 CMPL_NPREQ_WAITING_CLKS; typedef 2'b11 NP_CREDIT_INCREMENT; typedef 2'b00 NP_CREDIT_NOCHANGE; +typedef 'h1F IDEA_CQ_TKEEP_OF_CSR; +typedef 'hF IDEA_CC_TKEEP_OF_CSR; + typedef PcieAxiStream#(PCIE_COMPLETER_REQUEST_TUSER_WIDTH) CmplReqAxiStream; typedef PcieAxiStream#(PCIE_COMPLETER_COMPLETE_TUSER_WIDTH) CmplCmplAxiStream; @@ -87,7 +92,7 @@ module mkCompleterRequest(CompleterRequest); else begin addr = 0; end - return truncate(addr); + return truncate(addr << valueOf(TSub#(DMA_MEM_ADDR_WIDTH, DES_ADDR_WIDTH))); endfunction rule parseTlp; @@ -97,7 +102,6 @@ module mkCompleterRequest(CompleterRequest); isInPacket <= !axiStream.tLast; if (!isInPacket) begin let descriptor = getDescriptorFromFirstBeat(axiStream); - // TODO: parity check! case (descriptor.reqType) fromInteger(valueOf(MEM_WRITE_REQ)): begin if (descriptor.dwordCnt == fromInteger(valueOf(IDEA_DWORD_CNT_OF_CSR)) && isFirstBytesAllValid(sideBand)) begin @@ -122,7 +126,7 @@ module mkCompleterRequest(CompleterRequest); }; rdReqFifo.enq(rdReq); end - default: begin $display("INFO"); illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; end + default: illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; endcase end endrule @@ -137,7 +141,7 @@ module mkCompleterComplete(CompleterComplete); FIFOF#(CsrReadResp) rdRespFifo <- mkFIFOF; FIFOF#(CsrReadReq) rdReqFifo <- mkFIFOF; - // TODO: the logic of cc, not completed + // Only response MemRd TLP in this rule rule genTlp; let value = rdRespFifo.first; rdRespFifo.deq; @@ -154,22 +158,36 @@ module mkCompleterComplete(CompleterComplete); requesterId : cqDescriptor.requesterId, reserve1 : 0, isPoisoned : False, - status : 0, - dwordCnt : 0, + status : fromInteger(valueOf(DES_CC_STAUS_SUCCESS)), + dwordCnt : fromInteger(valueOf(IDEA_DWORD_CNT_OF_CSR)), reserve2 : 0, isLockedReadCmpl: False, - byteCnt : 0, + byteCnt : fromInteger(valueOf(IDEA_BYTE_CNT_OF_CSR)), reserve3 : 0, - addrType : 0, - lowerAddr : 0 + addrType : cqDescriptor.addrType, + lowerAddr : truncate(addr) }; Data data = zeroExtend(pack(ccDescriptor)); data = data | (zeroExtend(value) << valueOf(DES_CC_DESCRIPTOR_WIDTH)); + let isSop = PcieTlpCtlIsSopCommon { + isSopPtrs : replicate(0), // Straddle mode is disable of completer + isSop : 1 + }; + let isEop = PcieTlpCtlIsEopCommon { + isEopPtrs : replicate(0), // Straddle mode is disable of completer + isEop : 1 + }; + let sideBand = PcieCompleterCompleteSideBandFrame { + parity : 0, // Do not enable parity check in the core + discontinue : False, + isSop : isSop, + isEop : isEop + }; let axiStream = CmplCmplAxiStream { tData : data, - tKeep : 0, + tKeep : fromInteger(valueOf(IDEA_CC_TKEEP_OF_CSR)), tLast : True, - tUser : 0 + tUser : pack(sideBand) }; outFifo.enq(axiStream); endrule diff --git a/src/DmaController.bsv b/src/DmaController.bsv index c169ab8..c1d0999 100755 --- a/src/DmaController.bsv +++ b/src/DmaController.bsv @@ -41,3 +41,25 @@ module mkDmaController(DmaController); endmethod endinterface endmodule + +interface DmaControllerCompleter; + // Completer interfaces, where the Card serve as the Slave + interface DmaHostToCardWrite h2cWrite; + interface DmaHostToCardRead h2cRead; + + // Raw PCIe interfaces, connected to the Xilinx PCIe IP + interface RawXilinxPcieIpCompleter rawPcie; +endinterface + +// Only for testing in bsv, do not use for synthesize +module mkDmaControllerCompleter(DmaControllerCompleter); + DmaCompleter completer <- mkDmaCompleter; + + interface h2cWrite = completer.h2cWrite; + interface h2cRead = completer.h2cRead; + + interface RawXilinxPcieIpCompleter rawPcie; + interface completerRequest = completer.rawCompleterRequest; + interface completerComplete = completer.rawCompleterComplete; + endinterface +endmodule diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index ea1645e..10a0404 100755 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -2,8 +2,9 @@ import FShow::*; import SemiFifo::*; import PcieTypes::*; +import PcieAxiStreamTypes::*; -typedef 512 DATA_WIDTH; +typedef PCIE_AXIS_DATA_WIDTH DATA_WIDTH; typedef 64 DMA_MEM_ADDR_WIDTH; typedef 32 DMA_CSR_ADDR_WIDTH; @@ -17,6 +18,10 @@ typedef 8 BYTE_WIDTH; typedef TLog#(BYTE_WIDTH) BYTE_WIDTH_WIDTH; typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; +typedef Bit#(BYTE_WIDTH) Byte; +typedef Bit#(DWORD_WIDTH) DWord; +typedef Bit#(1) ByteParity; + typedef 2 CONCAT_STREAM_NUM; typedef TDiv#(DATA_WIDTH, BYTE_WIDTH) BYTE_EN_WIDTH; diff --git a/src/PcieConfigurator.bsv b/src/PcieConfigurator.bsv index 78474a9..c0553c9 100644 --- a/src/PcieConfigurator.bsv +++ b/src/PcieConfigurator.bsv @@ -146,7 +146,7 @@ module mkPcieConfigurator(PcieConfigurator); interface RawPcieCfgControl control; method Bool hotResetOut; - return True; + return False; endmethod method Action hotResetIn(Bool hotReset); diff --git a/src/PcieDescriptorTypes.bsv b/src/PcieDescriptorTypes.bsv index 7a92912..17660d0 100644 --- a/src/PcieDescriptorTypes.bsv +++ b/src/PcieDescriptorTypes.bsv @@ -61,6 +61,10 @@ typedef Bit#(DES_CMPL_STATUS_WIDTH) CmplStatus; typedef Bit#(DES_CMPL_BYTE_CNT_WIDTH) CmplByteCnt; typedef Bit#(DES_LOWER_ADDR_WIDTH) LowerAddr; +typedef 0 DES_CC_STAUS_SUCCESS; +typedef 1 DES_CC_STATUS_UPSUPPORT; +typedef 4 DES_CC_STATUS_ABORT; + typedef struct { // DW + 2 ReserveBit1 reserve0; diff --git a/src/PcieTypes.bsv b/src/PcieTypes.bsv index d88d205..fabcc0d 100755 --- a/src/PcieTypes.bsv +++ b/src/PcieTypes.bsv @@ -501,3 +501,9 @@ interface RawXilinxPcieIp; (* prefix = "" *) method Action linkUp( (* port = "user_lnk_up" *) Bool isLinkUp); endinterface + +(* always_ready, always_enabled *) +interface RawXilinxPcieIpCompleter; + (* prefix = "" *) interface RawPcieCompleterRequest completerRequest; + (* prefix = "" *) interface RawPcieCompleterComplete completerComplete; +endinterface diff --git a/src/PrimUtils.bsv b/src/PrimUtils.bsv index a2f6c40..02b681d 100644 --- a/src/PrimUtils.bsv +++ b/src/PrimUtils.bsv @@ -1,4 +1,5 @@ import FIFOF::*; +import Vector::*; import PcieAxiStreamTypes::*; import DmaTypes::*; @@ -265,3 +266,18 @@ module mkCounteredFIFOF#(Integer depth)(CounteredFIFOF#(t)) provisos(Bits#(t, tS method FifoSize getCurSize = curSize; endmodule +function ByteParity calByteParity(Byte data); + return (data[0] ^ data[1] ^ data[2] ^ data[3] ^ data[4] ^ data[5] ^ data[6] ^ data[7]); +endfunction + +typedef Bit#(BYTE_EN_WIDTH) DataParity; +typedef Bit#(TDiv#(DWORD_WIDTH, BYTE_WIDTH)) DwordParity; + +function DataParity calDataParity(Data data); + Vector#(BYTE_EN_WIDTH, Byte) dataBytes = unpack(data); + Vector#(BYTE_EN_WIDTH, ByteParity) dataParities= newVector(); + for (Integer idx = 0; idx < valueOf(BYTE_EN_WIDTH); idx = idx + 1) begin + dataParities[idx] = calByteParity(dataBytes[idx]); + end + return pack(dataParities); +endfunction \ No newline at end of file diff --git a/test/TestDmaCompleter.bsv b/test/TestDmaCompleter.bsv index 626c5c5..03d03d3 100644 --- a/test/TestDmaCompleter.bsv +++ b/test/TestDmaCompleter.bsv @@ -10,12 +10,15 @@ import PcieTypes::*; import PcieDescriptorTypes::*; import DmaTypes::*; import DmaCompleter::*; +import TestDmacVivado::*; typedef 'hABCD TEST_DATA; -typedef 'h1234 TEST_ADDR; +typedef 'h1A28 TEST_ADDR; typedef 2'b10 TRANSLATED_ADDR_TYPE; +typedef 10 READ_TIMEOUT_THRESH; + function PcieTlpCtlIsEopCommon getEmptyEop(); return PcieTlpCtlIsEopCommon { isEopPtrs: replicate(0), @@ -30,7 +33,7 @@ function PcieTlpCtlIsSopCommon getEmptySop(); }; endfunction -function CmplReqAxiStream genPseudoHostWriteRequest(); +function CmplReqAxiStream genPseudoHostRequest(DmaCsrValue testValue, DmaCsrAddr testAddr, Bool isWrite); let descriptor = PcieCompleterRequestDescriptor { reserve0 : 0, attributes : 0, @@ -41,15 +44,14 @@ function CmplReqAxiStream genPseudoHostWriteRequest(); tag : 0, requesterId : fromInteger(valueOf(TEST_DATA)), reserve1 : 0, - reqType : fromInteger(valueOf(MEM_WRITE_REQ)), + reqType : isWrite ? fromInteger(valueOf(MEM_WRITE_REQ)) :fromInteger(valueOf(MEM_READ_REQ)) , dwordCnt : 1, - address : fromInteger(valueOf(TEST_ADDR)), + address : zeroExtend(testAddr >> valueOf(TSub#(DMA_MEM_ADDR_WIDTH, DES_ADDR_WIDTH))), addrType : fromInteger(valueOf(TRANSLATED_ADDR_TYPE)) }; Data data = 0; data = data | zeroExtend(pack(descriptor)); - Data value = fromInteger(valueOf(TEST_DATA)); - data = data | (value << valueOf(DES_CQ_DESCRIPTOR_WIDTH)); + data = data | zeroExtend(testValue) << valueOf(DES_CQ_DESCRIPTOR_WIDTH); let sideBand = PcieCompleterRequestSideBandFrame { parity : 0, tphSteeringTag : 0, @@ -58,13 +60,13 @@ function CmplReqAxiStream genPseudoHostWriteRequest(); discontinue : False, isEop : getEmptyEop, isSop : getEmptySop, - dataByteEn : 'hFFF, + dataByteEn : isWrite ? 'hFFF : 'hFF, lastByteEn : 'hF, firstByteEn : 'hF }; return CmplReqAxiStream { tData : data, - tKeep : 'h3FF, + tKeep : fromInteger(valueOf(IDEA_CQ_TKEEP_OF_CSR)), tLast : True, tUser : pack(sideBand) }; @@ -77,7 +79,7 @@ module mkTestDmaCompleterRequest(Empty); rule testInit if (!isInitReg); $display("INFO: Start CompleterRequest test"); - let testAxiStram = genPseudoHostWriteRequest; + let testAxiStram = genPseudoHostRequest(fromInteger(valueOf(TEST_DATA)), fromInteger(valueOf(TEST_ADDR)), True); dut.axiStreamFifoIn.enq(testAxiStram); isInitReg <= True; endrule @@ -88,7 +90,7 @@ module mkTestDmaCompleterRequest(Empty); immAssert( (wrReq.addr == fromInteger(valueOf(TEST_ADDR)) && wrReq.value == fromInteger(valueOf(TEST_DATA))), "wrReq test @ mkTestDmaCompleterRequest", - fshow(wrReq) + $format("RawReq: Addr %h, Value %h \n But", fromInteger(valueOf(TEST_ADDR)), fromInteger(valueOf(TEST_DATA)),fshow(wrReq)) ); $display("INFO: Pass CompleterRequest test"); $finish(); @@ -98,49 +100,91 @@ endmodule (* doc = "testcase" *) module mkTestDmaCompleter(Empty); - DmaCompleter dut <- mkDmaCompleter; - Reg#(Bool) isInitReg <- mkReg(False); + TestDmacCsrWrRdLoopTb dut <- mkTestDmacCsrWrRdLoopTb; + Reg#(Bool) isInitReg <- mkReg(False); + Reg#(Bool) isWriteDoneReg <- mkReg(False); + Reg#(Bool) isWriteDoneReg1 <- mkReg(False); + Reg#(Bool) isReadDoneReg <- mkReg(False); + Reg#(UInt#(32)) timeoutReg <- mkReg(0); + + function Action setEmptyRawAxiStream(); + return action + dut.rawPcie.completerRequest.rawAxiStreamSlave.tValid( + False, + 0, + 0, + False, + 0 + ); + endaction; + endfunction rule alwaysEnables; - dut.rawCompleterComplete.rawAxiStreamMaster.tReady(True); - dut.rawCompleterRequest.nonPostedReqCreditCnt(32); + dut.rawPcie.completerComplete.rawAxiStreamMaster.tReady(True); + dut.rawPcie.completerRequest.nonPostedReqCreditCnt(32); endrule rule testInit; - let testAxiStram = genPseudoHostWriteRequest; if (!isInitReg) begin + setEmptyRawAxiStream; + isInitReg <= True; $display("INFO: Start Completer test"); - dut.rawCompleterRequest.rawAxiStreamSlave.tValid( + end + else if (isInitReg && !isWriteDoneReg) begin + let testAxiStram = genPseudoHostRequest(fromInteger(valueOf(TEST_DATA)), fromInteger(valueOf(TEST_ADDR)), True); + dut.rawPcie.completerRequest.rawAxiStreamSlave.tValid( True, testAxiStram.tData, testAxiStram.tKeep, testAxiStram.tLast, testAxiStram.tUser ); - isInitReg <= True; + isWriteDoneReg <= True; end - else begin - dut.rawCompleterRequest.rawAxiStreamSlave.tValid( - False, - 0, - 0, - False, - 0 + else if (isInitReg && isWriteDoneReg1 && !isReadDoneReg) begin + let testAxiStram = genPseudoHostRequest(0, fromInteger(valueOf(TEST_ADDR)), False); + dut.rawPcie.completerRequest.rawAxiStreamSlave.tValid( + True, + testAxiStram.tData, + testAxiStram.tKeep, + testAxiStram.tLast, + testAxiStram.tUser ); + isReadDoneReg <= True; + end + else begin + setEmptyRawAxiStream; + isWriteDoneReg1 <= isWriteDoneReg; end endrule rule testOutput if (isInitReg); - let wrData = dut.h2cWrite.dataFifoOut.first; - dut.h2cWrite.dataFifoOut.deq; - let wrAddr = dut.h2cWrite.reqFifoOut.first; - dut.h2cWrite.reqFifoOut.deq; - immAssert( - (wrAddr == fromInteger(valueOf(TEST_ADDR)) && wrData == fromInteger(valueOf(TEST_DATA))), - "wrReq test @ mkTestDmaCompleter", - $format("write value: %h, write addr: %h", wrData, wrAddr) - ); - $display("INFO: Pass Completer test"); - $finish(); + if (timeoutReg > fromInteger(valueOf(READ_TIMEOUT_THRESH))) begin + $display("Error: no valid cc axiStream out until timeout!"); + $finish(); + end + else begin + if (dut.rawPcie.completerComplete.rawAxiStreamMaster.tValid) begin + let data = dut.rawPcie.completerComplete.rawAxiStreamMaster.tData; + let keep = dut.rawPcie.completerComplete.rawAxiStreamMaster.tKeep; + let isLast = dut.rawPcie.completerComplete.rawAxiStreamMaster.tLast; + immAssert( + (isLast && (keep == 'hF)), + "completer output keep&last check @ mkTestDmaCompleter", + $format("tKeep: %h, tLast: %h", keep, isLast) + ); + DmaCsrValue value = truncate(data >> valueOf(DES_CC_DESCRIPTOR_WIDTH)); + immAssert( + (value == fromInteger(valueOf(TEST_DATA))), + "complete output data check @ mkTestDmaCompleter", + $format("write value: %h, read value: %h", valueOf(TEST_DATA), value) + ); + $display("INFO: Pass Completer test"); + $finish(); + end + else begin + timeoutReg <= timeoutReg + 1; + end + end endrule endmodule diff --git a/test/TestDmacVivado.bsv b/test/TestDmacVivado.bsv index d5b290d..5e369df 100644 --- a/test/TestDmacVivado.bsv +++ b/test/TestDmacVivado.bsv @@ -31,6 +31,7 @@ module mkTestDmacCsrWrRdLoop((* reset="sys_rst" *) Reset sysRst, TestDmacWrRdLoo rule testWriteReq; dmac.h2cWrite.dataFifoOut.deq; dmac.h2cWrite.reqFifoOut.deq; + $display("SIM INFO @ mkTestDmacCsrWrRdLoop: h2cWrite req detect!"); ram.portA.request.put( BRAMRequest { write : True, @@ -43,6 +44,7 @@ module mkTestDmacCsrWrRdLoop((* reset="sys_rst" *) Reset sysRst, TestDmacWrRdLoo rule testReadReq; dmac.h2cRead.reqFifoOut.deq; + $display("SIM INFO @ mkTestDmacCsrWrRdLoop: h2cRead req detect!"); ram.portB.request.put( BRAMRequest { write : False, @@ -61,3 +63,58 @@ module mkTestDmacCsrWrRdLoop((* reset="sys_rst" *) Reset sysRst, TestDmacWrRdLoo interface rawPcie = dmac.rawPcie; endmodule +// Only use for testing in bsv, do not use for synthesize +interface TestDmacCsrWrRdLoopTb; + interface RawXilinxPcieIpCompleter rawPcie; +endinterface + +module mkTestDmacCsrWrRdLoopTb(TestDmacCsrWrRdLoopTb); + + DmaControllerCompleter dmac <- mkDmaControllerCompleter; + + BRAM2Port#(DmaCsrAddr, DmaCsrValue) ram <- mkBRAM2Server( + BRAM_Configure { + memorySize : valueOf(TEST_BRAM_SIZE), + loadFormat : None, + latency : 2, + outFIFODepth: 3, + allowWriteResponseBypass : False + } + ); + + rule testWriteReq; + dmac.h2cWrite.dataFifoOut.deq; + dmac.h2cWrite.reqFifoOut.deq; + $display("SIM INFO @ mkTestDmacCsrWrRdLoop: h2cWrite req detect!"); + $display("BRAM: PortA write addr %h data %h", dmac.h2cWrite.reqFifoOut.first, dmac.h2cWrite.dataFifoOut.first); + ram.portA.request.put( + BRAMRequest { + write : True, + responseOnWrite : False, + address : dmac.h2cWrite.reqFifoOut.first, + datain : dmac.h2cWrite.dataFifoOut.first + } + ); + endrule + + rule testReadReq; + dmac.h2cRead.reqFifoOut.deq; + $display("SIM INFO @ mkTestDmacCsrWrRdLoop: h2cRead req detect!"); + $display("BRAM: PortB read addr %h", dmac.h2cRead.reqFifoOut.first); + ram.portB.request.put( + BRAMRequest { + write : False, + responseOnWrite : False, + address : dmac.h2cRead.reqFifoOut.first, + datain : 0 + } + ); + endrule + + rule testReadResp; + let value <- ram.portB.response.get; + dmac.h2cRead.dataFifoIn.enq(value); + endrule + + interface rawPcie = dmac.rawPcie; +endmodule \ No newline at end of file From 98c2005b717ab6e199a0df9823d769693e967bad Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Thu, 25 Jul 2024 21:25:13 +0800 Subject: [PATCH 29/53] Fix streamUtils and pass all test --- src/DmaCompleter.bsv | 7 ++++ src/DmaRequester.bsv | 66 +++++++++++++++++++++++++++++++++++++ src/PcieDescriptorTypes.bsv | 55 +++++++++++++++++++++++++++++-- src/PrimUtils.bsv | 14 ++++++-- src/StreamUtils.bsv | 6 ++-- test/TestDmacVivado.bsv | 5 +-- 6 files changed, 143 insertions(+), 10 deletions(-) diff --git a/src/DmaCompleter.bsv b/src/DmaCompleter.bsv index 1df2da9..eccc3ac 100644 --- a/src/DmaCompleter.bsv +++ b/src/DmaCompleter.bsv @@ -104,10 +104,12 @@ module mkCompleterRequest(CompleterRequest); let descriptor = getDescriptorFromFirstBeat(axiStream); case (descriptor.reqType) fromInteger(valueOf(MEM_WRITE_REQ)): begin + $display("SIM INFO @ mkCompleterRequest: MemWrite Detect!"); if (descriptor.dwordCnt == fromInteger(valueOf(IDEA_DWORD_CNT_OF_CSR)) && isFirstBytesAllValid(sideBand)) begin let firstData = getDataFromFirstBeat(axiStream); DmaCsrValue wrValue = firstData[valueOf(DMA_CSR_ADDR_WIDTH)-1:0]; DmaCsrAddr wrAddr = getCsrAddrFromCqDescriptor(descriptor); + $display("SIM INFO @ mkCompleterRequest: Valid wrReq with Addr %h, data %h", wrAddr, wrValue); let wrReq = CsrWriteReq { addr : wrAddr, value : wrValue @@ -119,11 +121,13 @@ module mkCompleterRequest(CompleterRequest); end end fromInteger(valueOf(MEM_READ_REQ)): begin + $display("SIM INFO @ mkCompleterRequest: MemRead Detect!"); let rdReqAddr = getCsrAddrFromCqDescriptor(descriptor); let rdReq = CsrReadReq{ addr: rdReqAddr, cqDescriptor: descriptor }; + $display("SIM INFO @ mkCompleterRequest: Valid rdReq with Addr %h", rdReqAddr); rdReqFifo.enq(rdReq); end default: illegalPcieReqCntReg <= illegalPcieReqCntReg + 1; @@ -148,6 +152,7 @@ module mkCompleterComplete(CompleterComplete); let cqDescriptor = rdReqFifo.first.cqDescriptor; let addr = rdReqFifo.first.addr; rdReqFifo.deq; + $display("SIM INFO @ mkCompleterComplete: Valid rdResp with Addr %h, data %h", addr, value); let ccDescriptor = PcieCompleterCompleteDescriptor { reserve0 : 0, attributes : cqDescriptor.attributes, @@ -231,6 +236,8 @@ module mkDmaCompleter(DmaCompleter); rule procCsrReadResp; let req = csrRdReqStoreFifo.first; let resp = h2cCsrReadDataFifo.first; + csrRdReqStoreFifo.deq; + h2cCsrReadDataFifo.deq; cmplComplete.csrReadRespFifoIn.enq(resp); cmplComplete.csrReadReqFifoIn.enq(req); endrule diff --git a/src/DmaRequester.bsv b/src/DmaRequester.bsv index 10e56b0..10c75a3 100644 --- a/src/DmaRequester.bsv +++ b/src/DmaRequester.bsv @@ -1,11 +1,15 @@ import FIFOF::*; +import GetPut::*; import SemiFifo::*; +import StreamUtils::*; import PcieTypes::*; import PcieAxiStreamTypes::*; import PcieDescriptorTypes::*; import DmaTypes::*; +typedef TSub#(DATA_WIDTH, DES_RQ_DESCRIPTOR_WIDTH) ONE_TLP_THRESH; + typedef PcieAxiStream#(PCIE_REQUESTER_REQUEST_TUSER_WIDTH) ReqReqAxiStream; typedef PcieAxiStream#(PCIE_REQUESTER_COMPLETE_TUSER_WIDTH) ReqCmplAxiStream; @@ -21,6 +25,9 @@ interface RequesterRequest; interface FifoIn#(DmaRequest) wrReqFifoIn; interface FifoIn#(DmaRequest) rdReqFifoIn; interface FifoOut#(ReqReqAxiStream) axiStreamFifoOut; + interface Put#(Bool) postedEn; + interface Put#(Bool) nonPostedEn; + interface Get#(Bool) isWriteDataRecvDone; endinterface interface RequesterComplete; @@ -30,17 +37,76 @@ interface RequesterComplete; endinterface module mkRequesterRequest(RequesterRequest); + StreamConcat streamConcat <- mkStreamConcat; + FIFOF#(DataStream) wrDataInFifo <- mkFIFOF; FIFOF#(DmaRequest) wrReqInFifo <- mkFIFOF; FIFOF#(DmaRequest) rdReqInFifo <- mkFIFOF; FIFOF#(ReqReqAxiStream) axiStreamOutFifo <- mkFIFOF; + Reg#(DmaMemAddr) inflightRemainBytesReg <- mkReg(0); + Reg#(Bool) isInWritingReg <- mkReg(False); + Wire#(Bool) postedEnWire <- mkDWire(False); + Wire#(Bool) nonPostedEnWire <- mkDWire(True); + + function DataStream genRQDescriptorStream(DmaRequest req, Bool isWrite); + let descriptor = PcieRequesterRequestDescriptor { + forceECRC : False, + attributes : 0, + trafficClass : 0, + requesterIdEn : False, + completerId : 0, + tag : 0, + requesterId : 0, + isPoisoned : False, + reqType : isWrite ? fromInteger(valueOf(MEM_WRITE_REQ)) : fromInteger(valueOf(MEM_READ_REQ)), + dwordCnt : truncate(req.length >> 2 + (req.length[0] | req.length[1])), + address : truncate(req.startAddr >> 2), + addrType : 2'b10 + }; + ByteEn byteEn = 1; + let stream = DataStream { + data : zeroExtend(pack(descriptor)), + byteEn : (byteEn << (valueOf(TDiv#(DES_RQ_DESCRIPTOR_WIDTH, BYTE_WIDTH)) + 1)) - 1, + isFirst : True, + isLast : False + }; + return stream; + endfunction + // TODO: RQ Logic + rule recvWriteReq if (postedEnWire); + if (!isInWritingReg) begin + let wrReq = wrReqInFifo.first; + let wrData = wrDataInFifo.first; + wrReqInFifo.deq; + wrDataInFifo.deq; + isInWritingReg <= (wrReq.length > fromInteger(valueOf(ONE_TLP_THRESH))); + end + endrule interface wrDataFifoIn = convertFifoToFifoIn(wrDataInFifo); interface wrReqFifoIn = convertFifoToFifoIn(wrReqInFifo); interface rdReqFifoIn = convertFifoToFifoIn(rdReqInFifo); interface axiStreamFifoOut = convertFifoToFifoOut(axiStreamOutFifo); + + interface Put postedEn; + method Action put(Bool postedEnable); + postedEnWire <= postedEnable; + endmethod + endinterface + + interface Put nonPostedEn; + method Action put(Bool nonPostedEnable); + nonPostedEnWire <= nonPostedEnable; + endmethod + endinterface + + interface Get isWriteDataRecvDone; + method ActionValue#(Bool) get(); + return (inflightRemainBytesReg == 0); + endmethod + endinterface endmodule module mkRequesterComplete(RequesterComplete); diff --git a/src/PcieDescriptorTypes.bsv b/src/PcieDescriptorTypes.bsv index 17660d0..2375a3b 100644 --- a/src/PcieDescriptorTypes.bsv +++ b/src/PcieDescriptorTypes.bsv @@ -56,10 +56,10 @@ typedef struct { typedef 96 DES_CC_DESCRIPTOR_WIDTH; typedef 3 DES_CMPL_STATUS_WIDTH; typedef 13 DES_CMPL_BYTE_CNT_WIDTH; -typedef 7 DES_LOWER_ADDR_WIDTH; +typedef 7 DES_CC_LOWER_ADDR_WIDTH; typedef Bit#(DES_CMPL_STATUS_WIDTH) CmplStatus; typedef Bit#(DES_CMPL_BYTE_CNT_WIDTH) CmplByteCnt; -typedef Bit#(DES_LOWER_ADDR_WIDTH) LowerAddr; +typedef Bit#(DES_CC_LOWER_ADDR_WIDTH) CCLowerAddr; typedef 0 DES_CC_STAUS_SUCCESS; typedef 1 DES_CC_STATUS_UPSUPPORT; @@ -85,9 +85,58 @@ typedef struct { CmplByteCnt byteCnt; ReserveBit6 reserve3; AddrType addrType; - LowerAddr lowerAddr; + CCLowerAddr lowerAddr; } PcieCompleterCompleteDescriptor deriving(Bits, Eq, Bounded, FShow); +typedef 128 DES_RQ_DESCRIPTOR_WIDTH; + +typedef struct { + // DW + 3 + Bool forceECRC; + Attributes attributes; + TrafficClass trafficClass; + Bool requesterIdEn; + BusDeviceFunc completerId; + Tag tag; + // DW + 2 + BusDeviceFunc requesterId; + Bool isPoisoned; + ReqType reqType; + DwordCount dwordCnt; + // DW + 1 & DW + 0 + Address address; + AddrType addrType; +} PcieRequesterRequestDescriptor deriving(Bits, Eq, Bounded, FShow); + +typedef 96 DES_RC_DESCRIPTOR_WIDTH; +typedef 4 DES_ERROR_CODE_WIDTH; +typedef 12 DES_RC_LOWER_ADDR_WIDTH; + +typedef Bit#(DES_ERROR_CODE_WIDTH) ErrorCode; +typedef Bit#(DES_RC_LOWER_ADDR_WIDTH) RCLowerAddr; + +typedef struct { + // DW + 2 + ReserveBit1 reserve0; + Attributes attributes; + TrafficClass trafficClass; + ReserveBit1 reserve1; + BusDeviceFunc completerId; + Tag tag; + // DW + 1 + BusDeviceFunc requesterId; + ReserveBit1 reserve2; + Bool isPoisoned; + CmplStatus status; + DwordCount dwordCnt; + ReserveBit1 reserve3; + Bool isRequestCompleted; + Bool isLockedReadCmpl; + CmplByteCnt byteCnt; + ErrorCode errorcode; + RCLowerAddr lowerAddr; +} PcieRequesterCompleteDescriptor deriving(Bits, Eq, Bounded, FShow); + // Pcie Tlp types of descriptor typedef 4'b0000 MEM_READ_REQ; typedef 4'b0001 MEM_WRITE_REQ; diff --git a/src/PrimUtils.bsv b/src/PrimUtils.bsv index 02b681d..66257ba 100644 --- a/src/PrimUtils.bsv +++ b/src/PrimUtils.bsv @@ -245,17 +245,27 @@ interface CounteredFIFOF#(type t); endinterface module mkCounteredFIFOF#(Integer depth)(CounteredFIFOF#(t)) provisos(Bits#(t, tSz)); + Wire#(Bool) hasDeqCall <- mkDWire(False); + Wire#(Bool) hasEnqCall <- mkDWire(False); Reg#(FifoSize) curSize <- mkReg(0); FIFOF#(t) fifo <- mkSizedFIFOF(depth); + rule updateSize; + case({pack(hasEnqCall), pack(hasDeqCall)}) + 2'b10: curSize <= curSize + 1; + 2'b01: curSize <= curSize -1; + default: curSize <= curSize; + endcase + endrule + method Action enq (t x); fifo.enq(x); - curSize <= curSize + 1; + hasEnqCall <= True; endmethod method Action deq; fifo.deq; - curSize <= curSize - 1; + hasDeqCall <= True; endmethod method t first = fifo.first; diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv index e40addf..58e6793 100755 --- a/src/StreamUtils.bsv +++ b/src/StreamUtils.bsv @@ -99,9 +99,9 @@ function DataBytePtr convertByteEn2BytePtr (ByteEn byteEn); return ptr; endfunction -function Bool isByteEnZero(ByteEn byteEn) begin - return !unpack(remainStream.byteEn[0]); -end +function Bool isByteEnZero(ByteEn byteEn); + return !unpack(byteEn[0]); +endfunction function DataStream getEmptyStream (); return DataStream{ diff --git a/test/TestDmacVivado.bsv b/test/TestDmacVivado.bsv index 5e369df..2663ed2 100644 --- a/test/TestDmacVivado.bsv +++ b/test/TestDmacVivado.bsv @@ -22,7 +22,7 @@ module mkTestDmacCsrWrRdLoop((* reset="sys_rst" *) Reset sysRst, TestDmacWrRdLoo BRAM_Configure { memorySize : valueOf(TEST_BRAM_SIZE), loadFormat : None, - latency : 2, + latency : 1, outFIFODepth: 3, allowWriteResponseBypass : False } @@ -56,6 +56,7 @@ module mkTestDmacCsrWrRdLoop((* reset="sys_rst" *) Reset sysRst, TestDmacWrRdLoo endrule rule testReadResp; + $display("SIM INFO @ mkTestDmacCsrWrRdLoop: h2cRead resp detect!"); let value <- ram.portB.response.get; dmac.h2cRead.dataFifoIn.enq(value); endrule @@ -76,7 +77,7 @@ module mkTestDmacCsrWrRdLoopTb(TestDmacCsrWrRdLoopTb); BRAM_Configure { memorySize : valueOf(TEST_BRAM_SIZE), loadFormat : None, - latency : 2, + latency : 1, outFIFODepth: 3, allowWriteResponseBypass : False } From ac1beeccfc3fe4cb4a6d75ca3606d00567eee6f7 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Fri, 2 Aug 2024 14:23:40 +0800 Subject: [PATCH 30/53] Add dmaRequester --- img/chunkSplit.drawio.svg | 561 +++++++++++++++++++++++- img/requester.drawio.svg | 837 ++++++++++++++++++++++++++++++++++++ run_one.sh | 2 +- src/DmaCompleter.bsv | 7 +- src/DmaRequestCore.bsv | 473 +++++++++++++++++++- src/DmaRequester.bsv | 57 ++- src/DmaTypes.bsv | 18 +- src/PcieAxiStreamTypes.bsv | 6 +- src/PcieDescriptorTypes.bsv | 5 + src/PrimUtils.bsv | 442 +++++++++++++------ src/StreamUtils.bsv | 367 +++++++--------- test/TestDmaCore.bsv | 27 +- test/TestStreamUtils.bsv | 1 + 13 files changed, 2421 insertions(+), 382 deletions(-) create mode 100644 img/requester.drawio.svg diff --git a/img/chunkSplit.drawio.svg b/img/chunkSplit.drawio.svg index 44d1e49..5cc7635 100644 --- a/img/chunkSplit.drawio.svg +++ b/img/chunkSplit.drawio.svg @@ -1 +1,560 @@ -FifoInFifoIngetFirstChunkLengetFirstChunkLensplitFifosplitFifogenSplitChunksgenSplitChunksdmaRequeststartAddrlengthfirstChunkLendmaRequest...FifoOutFifoOutstartAddrlengthstartAddrlengthstartAddrlengthstartAddrlengthnewChunkPtrRegtotalLenRemainRegisSplittingRegnewChunkPtrRegtotalLenRemainRe...4KB4KB4KB4KB4KB4KBoffsetoffset512√512...512√512...512√512...firstChunkfirstChunk512√512...512×512...512×512...............Text is not SVG - cannot display \ No newline at end of file + + + + + + + + + + + + + FifoIn#(DmaRequest) + + + + + + FifoIn#(DmaRequest) + + + + + + + + + + + + + + + getFirstChunkLen + + + + + + getFirstChunkLen + + + + + + + + + + + + + startAddr + + + length + + + + + + + + startAddrlength + + + + + + + + + + + 4KB + + + + + + 4KB + + + + + + + + + + + 4KB + + + + + + 4KB + + + + + + + + + + + 4KB + + + + + + 4KB + + + + + + + + + + + offset + + + + + + offset + + + + + + + + + + + + 512 + + √ + + + + + + 512... + + + + + + + + + + + 512 + + √ + + + + + + 512... + + + + + + + + + + + 512 + + √ + + + + + + 512... + + + + + + + + + + + firstChunk + + + + + + firstChunk + + + + + + + + + + + 512 + + √ + + + + + + 512... + + + + + + + + + + + 512 + + × + + + + + + 512... + + + + + + + + + + + 512 + + × + + + + + + 512... + + + + + + + + + + + ... + + + + + + ... + + + + + + + + + + + ... + + + + + + ... + + + + + + + + + + + + + + FifoIn#(DataStream) + + + + + + FifoIn#(DataStream) + + + + + + + + + + + + + streamSplit + + + + + + streamSplit + + + + + + + + + + + + + + + chunkSplit + + + + + + chunkSplit + + + + + + + + + + + split the first chunk + + + + + + split the first chunk + + + + + + + + + + + split of MaxSizePayload + + + + + + split of MaxSizePayload + + + + + + + + + + + only need tag isLast + + MPS must be n*512 + + + + + + only need tag isLast... + + + + + + + + + + + firstChunkLen < MPS + + + + + + firstChunkLen < MPS + + + + + + + + + + + FifoOut#(DataStream) + + + + + + FifoOut#(DataStream) + + + + + + + + + + + FifoOut#(DmaRequest) + + + + + + FifoOut#(DmaRequest) + + + + + + + + + + + latency=0 + + + + + + latency=0 + + + + + + + + + + + latency=3 + + + + + + latency=3 + + + + + + + + + + + latency=0 + + + + + + latency=0 + + + + + + + + + + + latency=1 + + + + + + latency=1 + + + + + + + + + + + latency=1 + + + + + + latency=1 + + + + + + + + + Text is not SVG - cannot display + + + + \ No newline at end of file diff --git a/img/requester.drawio.svg b/img/requester.drawio.svg new file mode 100644 index 0000000..2100c59 --- /dev/null +++ b/img/requester.drawio.svg @@ -0,0 +1,837 @@ + + + + + + + + + + + + + DataStream + + + + + + DataStream + + + + + + + + + + + + + Request + + + + + + Request + + + + + + + + + + + + + + StreamConcat + + + + + + + StreamConcat + + + + + + + + + + + first + + + + + + first + + + + + + + + + + + second + + + + + + second + + + + + + + + + + + + + + + + + + convertToAxis + + + + + + + convertToAxis + + + + + + + + + + + RawPcieRequeser + + + + + + RawPcieRequeser + + + + + + + + + + + + req + + + + + + req + + + + + + + + + + + + data + + + + + + data + + + + + + + + + + + ChunkSplit + + + + + + ChunkSplit + + + + + + + + + + + Descriptor + + + + + + Descriptor + + + + + + + + + + + DataStream + + + + + + DataStream + + + + + + + + + + + isDone + + + + + + isDone + + + + + + + + + + + + + DataStream + + + + + + DataStream + + + + + + + + + + + + + Request + + + + + + Request + + + + + + + + + + + isDone + + + + + + isDone + + + + + + + + + + + + dsFifoInA + + + + + + + dsFifoInA + + + + + + + + + + + + dsFifoInB + + + + + + + dsFifoInB + + + + + + + + + + + + tData + + + + + + + tData + + + + + + + + + + + + tKeep + + + + + + + tKeep + + + + + + + + + + + + tUser + + + + + + + tUser + + + + + + + + + + + + tLast + + + + + + + tLast + + + + + + + + + + + straddle 1 + + + + + + straddle 1 + + + + + + + + + + + straddle 0 + + + + + + straddle 0 + + + + + + + + + + + StreamA/B last beat bytePtr > 256bit + + + + + + StreamA/B last beat bytePtr > 256bit + + + + + + + + + + + Only singe streamA/B + + + + + + Only singe streamA/B + + + + + + + + + + + StreamA + + + + + + StreamA + + + + + + + + + + + StreamB + + + + + + StreamB + + + + + + + + + + + + x + + + + + + + x + + + + + + + + + + + + x + + + + + + + x + + + + + + + + + + + StreamA/B last beat bytePtr + + +remainPtr <= 256bit + + + + + + StreamA/B last beat bytePtr... + + + + + + + + + + + The other stream first + + + + + + The other stream first + + + + + + + + + + + Remain Data + + + + + + Remain Data + + + + + + + + + + + StreamA/B last beat bytePtr+remainPtr > 256bit + + + + + + StreamA/B last beat bytePt... + + + + + + + + + + + Remain Data + + + + + + Remain Data + + + + + + + + + + + Remain Data + + + + + + Remain... + + + + + + + + + + + + + isSop + + isEop + + + + + + + + isSop... + + + + + + + + + + + Align + + Bytes + + + + + + Align... + + + + + + + + + + + + + Same as above + + + + + + Same as above + + + + + + + + + + + + + + firstBE + + lastBE + + + + + + firstBE... + + + + + + + + + + + AlignDescGen + + + + + + AlignDescGen + + + + + + + + + + + + + DataPipe + + + + + + DataPipe + + + + + + + + + + + + remainDs + + + + + + + remainDs + + + + + + + + + + + latency=5 + + + + + + latency=5 + + + + + + + + + + + latency=3 + + + + + + latency=3 + + + + + + + + + Text is not SVG - cannot display + + + + \ No newline at end of file diff --git a/run_one.sh b/run_one.sh index 7e935a8..f049c0d 100755 --- a/run_one.sh +++ b/run_one.sh @@ -13,7 +13,7 @@ TEST_LOG=run.log TEST_DIR=test cd $TEST_DIR truncate -s 0 $TEST_LOG -FILES=`ls TestDmaCompleter.bsv` +FILES=`ls TestDmaCore.bsv` ########################################################################### for FILE in $FILES; do # echo $FILE diff --git a/src/DmaCompleter.bsv b/src/DmaCompleter.bsv index eccc3ac..2b1ed04 100644 --- a/src/DmaCompleter.bsv +++ b/src/DmaCompleter.bsv @@ -8,7 +8,8 @@ import PcieTypes::*; import PcieDescriptorTypes::*; import DmaTypes::*; -typedef 1 IDEA_DWORD_CNT_OF_CSR; +typedef 1 IDEA_CQ_CSR_DWORD_CNT; +typedef 2 IDEA_CC_CSR_DWORD_CNT; typedef 4 IDEA_BYTE_CNT_OF_CSR; typedef 4 IDEA_FIRST_BE_HIGH_VALID_PTR_OF_CSR; @@ -105,7 +106,7 @@ module mkCompleterRequest(CompleterRequest); case (descriptor.reqType) fromInteger(valueOf(MEM_WRITE_REQ)): begin $display("SIM INFO @ mkCompleterRequest: MemWrite Detect!"); - if (descriptor.dwordCnt == fromInteger(valueOf(IDEA_DWORD_CNT_OF_CSR)) && isFirstBytesAllValid(sideBand)) begin + if (descriptor.dwordCnt == fromInteger(valueOf(IDEA_CQ_CSR_DWORD_CNT)) && isFirstBytesAllValid(sideBand)) begin let firstData = getDataFromFirstBeat(axiStream); DmaCsrValue wrValue = firstData[valueOf(DMA_CSR_ADDR_WIDTH)-1:0]; DmaCsrAddr wrAddr = getCsrAddrFromCqDescriptor(descriptor); @@ -164,7 +165,7 @@ module mkCompleterComplete(CompleterComplete); reserve1 : 0, isPoisoned : False, status : fromInteger(valueOf(DES_CC_STAUS_SUCCESS)), - dwordCnt : fromInteger(valueOf(IDEA_DWORD_CNT_OF_CSR)), + dwordCnt : fromInteger(valueOf(IDEA_CC_CSR_DWORD_CNT)), reserve2 : 0, isLockedReadCmpl: False, byteCnt : fromInteger(valueOf(IDEA_BYTE_CNT_OF_CSR)), diff --git a/src/DmaRequestCore.bsv b/src/DmaRequestCore.bsv index a712d09..a0baeb9 100755 --- a/src/DmaRequestCore.bsv +++ b/src/DmaRequestCore.bsv @@ -1,9 +1,13 @@ import FIFOF::*; import GetPut :: *; +import Vector::*; import SemiFifo::*; import PcieTypes::*; import DmaTypes::*; +import PcieAxiStreamTypes::*; +import StreamUtils::*; +import PcieDescriptorTypes::*; typedef 4096 BUS_BOUNDARY; @@ -18,6 +22,16 @@ typedef TAdd#(1, TLog#(DEFAULT_TLP_SIZE)) DEFAULT_TLP_SIZE_WIDTH; typedef 3 PCIE_TLP_SIZE_SETTING_WIDTH; typedef Bit#(PCIE_TLP_SIZE_SETTING_WIDTH) PcieTlpSizeSetting; +typedef TAdd#(1, TLog#(TDiv#(BUS_BOUNDARY, BYTE_EN_WIDTH))) DATA_BEATS_WIDTH; +typedef Bit#(DATA_BEATS_WIDTH) DataBeats; + +typedef PcieAxiStream#(PCIE_REQUESTER_REQUEST_TUSER_WIDTH) RqAxisStream; + +typedef Tuple2#( + DWordByteEn, + DWordByteEn +) SideBandByteEn; + typedef struct { DmaRequest dmaRequest; DmaMemAddr firstChunkLen; @@ -29,6 +43,22 @@ interface ChunkCompute; interface Put#(PcieTlpSizeSetting) setTlpMaxSize; endinterface +interface ChunkSplit; + interface FifoIn#(DataStream) dataFifoIn; + interface FifoIn#(DmaRequest) reqFifoIn; + interface FifoOut#(DataStream) chunkDataFifoOut; + interface FifoOut#(DmaRequest) chunkReqFifoOut; + interface Put#(PcieTlpSizeSetting) setTlpMaxSize; +endinterface + +interface ConvertDataStreamsToStraddleAxis; + interface FifoIn#(DataStream) dataAFifoIn; + interface FifoIn#(SideBandByteEn) byteEnAFifoIn; + interface FifoIn#(DataStream) dataBFifoIn; + interface FifoIn#(SideBandByteEn) byteEnBFifoIn; + interface FifoOut#(PcieAxiStream) axiStreamFifoOut; +endinterface + module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); FIFOF#(DmaRequest) inputFifo <- mkFIFOF; @@ -66,7 +96,7 @@ module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); }); endrule - rule execChunkSplit; + rule execChunkCompute; let splitRequest = splitFifo.first; if (isSplittingReg) begin // !isFirst if (totalLenRemainReg <= tlpMaxSize) begin @@ -118,4 +148,443 @@ module mkChunkComputer (TRXDirection direction, ChunkCompute ifc); endmethod endinterface -endmodule \ No newline at end of file +endmodule + +// Split the single input DataStream to a list of DataStream chunks +// - Chunks cannot violate bus boundary requirement +// - Only the first and the last chunk can be shorter than MaxPayloadSize +// - Other chunks length must equal to MaxPayloadSize +// - The module may block the pipeline if one input beat is splited to two beats +module mkChunkSplit(TRXDirection direction, ChunkCompute ifc); + FIFOF#(DataStream) dataInFifo <- mkFIFOF; + FIFOF#(DmaRequest) reqInFifo <- mkFIFOF; + FIFOF#(DataStream) chunkOutFifo <- mkFIFOF; + FIFOF#(DmaRequest) reqOutFifo <- mkFIFOF; + FIFOF#(DmaRequest) firstReqPipeFifo <- mkSizedFIFOF(STREAM_SPLIT_LATENCY); + FIFOF#(DmaRequest) inputReqPipeFifo <- mkSizedFIFOF(STREAM_SPLIT_LATENCY); + + StreamSplit firstChunkSplitor <- mkStreamSplit; + + Reg#(DmaMemAddr) tlpMaxSizeReg <- mkReg(fromInteger(valueOf(DEFAULT_TLP_SIZE))); + Reg#(PcieTlpSizeWidth) tlpMaxSizeWidthReg <- mkReg(fromInteger(valueOf(DEFAULT_TLP_SIZE_WIDTH))); + Reg#(DataBeats) tlpMaxBeatsReg <- mkReg(fromInteger(valueOf(TDiv#(DEFAULT_TLP_SIZE, BYTE_EN_WIDTH)))); + + Reg#(Bool) isInProcReg <- mkReg(False); + Reg#(DataBeats) beatsReg <- mkReg(0); + + Reg#(DmaMemAddr) nextStartAddrReg <- mkReg(0); + Reg#(DmaMemAddr) remainLenReg <- mkReg(0); + + + function Bool hasBoundary(DmaRequest request); + let highIdx = (request.startAddr + request.length - 1) >> valueOf(BUS_BOUNDARY_WIDTH); + let lowIdx = request.startAddr >> valueOf(BUS_BOUNDARY_WIDTH); + return (highIdx > lowIdx); + endfunction + + function DmaMemAddr getOffset(DmaRequest request); + // MPS - startAddr % MPS, MPS means MRRS when the module is set to RX mode + DmaMemAddr remainderOfMps = zeroExtend(PcieTlpMaxMaxPayloadSize'(request.startAddr[tlpMaxSizeWidthReg-1:0])); + DmaMemAddr offsetOfMps = tlpMaxSizeReg - remainderOfMps; + return offsetOfMps; + endfunction + + // Pipeline stage 1, calculate the first chunkLen which may be smaller than MPS + rule getfirstChunkLen; + // If is the first beat of a new request, get firstChunkLen and pipe into the splitor + if (!isInProcReg) begin + let request = reqInFifo.first; + reqInFifo.deq; + let stream = dataInFifo.first; + dataInFifo.deq; + let offset = getOffset(request); + let firstLen = (request.length > tlpMaxSizeReg) ? tlpMaxSizeReg : request.length; + let firstChunkLen = hasBoundary(request) ? offset : firstLen; + firstChunkSplitor.splitLocationFifoIn.enq(unpack(truncate(firstChunkLen))); + let firstReq = DmaRequest { + startAddr : request.startAddr, + length : firstChunkLen + }; + firstReqPipeFifo.enq(firstReq); + firstChunkSplitor.inputStreamFifoIn.enq(stream); + inputReqPipeFifo.enq(request); + isInProcReg <= !stream.isLast; + end + // If is the remain beats of the request, continue pipe into the splitor + else begin + let stream = dataInFifo.first; + dataInFifo.deq; + firstChunkSplitor.inputStreamFifoIn.enq(stream); + isInProcReg <= !stream.isLast; + end + endrule + + // Pipeline stage 2: use StreamUtils::StreamSplit to split the input datastream to the firstChunk and the remain chunks + // In StreamUtils::StreamSplit firstChunkSplitor + + // Pipeline stage 3, set isFirst/isLast accroding to MaxPayloadSize, i.e. split the remain chunks + rule splitToMps; + let stream = firstChunkSplitor.outputStreamFifoOut.first; + firstChunkSplitor.outputStreamFifoOut.deq; + // End of a TLP, reset beatsReg and tag isLast=True + if (stream.isLast || beatsReg == tlpMaxBeatsReg) begin + stream.isLast = True; + beatsReg <= 0; + end + else begin + beatsReg <= beatsReg + 1; + end + // Start of a TLP, get Req Infos and tag isFirst=True + if (beatsReg == 0) begin + stream.isFirst = True; + // The first TLP of chunks + if (firstReqPipeFifo.notEmpty) begin + let chunkReq = firstReqPipeFifo.first; + let oriReq = inputReqPipeFifo.first; + firstReqPipeFifo.deq; + nextStartAddrReg <= oriReq.startAddr + chunkReq.length; + remainLenReg <= oriReq.length - chunkReq.length; + reqOutFifo.enq(chunkReq); + end + // The following chunks + else begin + if (remainLenReg == 0) begin + // Do nothing + end + else if (remainLenReg <= tlpMaxSizeReg) begin + nextStartAddrReg <= 0; + remainLenReg <= 0; + let chunkReq = DmaRequest { + startAddr: nextStartAddrReg, + length : remainLenReg + }; + reqOutFifo.enq(chunkReq); + end + else begin + nextStartAddrReg <= nextStartAddrReg + tlpMaxSizeReg; + remainLenReg <= remainLenReg - tlpMaxSizeReg; + let chunkReq = DmaRequest { + startAddr: nextStartAddrReg, + length : tlpMaxSizeReg + }; + reqOutFifo.enq(chunkReq); + end + end + end + chunkOutFifo.enq(stream); + endrule + + interface dataFifoIn = convertFifoToFifoIn(dataInFifo); + interface reqFifoIn = convertFifoToFifoIn(reqInFifo); + + interface chunkDataFifoOut = convertFifoToFifoOut(chunkOutFifo); + interface chunkReqFifoOut = convertFifoToFifoOut(reqOutFifo); + + interface Put setTlpMaxSize; + method Action put (PcieTlpSizeSetting tlpSizeSetting); + let setting = tlpSizeSetting; + setting[valueOf(PCIE_TLP_SIZE_SETTING_WIDTH)-1] = (direction == DMA_TX) ? 0 : setting[valueOf(PCIE_TLP_SIZE_SETTING_WIDTH)-1]; + DmaMemAddr defaultTlpMaxSize = fromInteger(valueOf(DEFAULT_TLP_SIZE)); + tlpMaxSizeReg <= DmaMemAddr'(defaultTlpMaxSize << setting); + PcieTlpSizeWidth defaultTlpMaxSizeWidth = fromInteger(valueOf(DEFAULT_TLP_SIZE_WIDTH)); + tlpMaxSizeWidthReg <= PcieTlpSizeWidth'(defaultTlpMaxSizeWidth + zeroExtend(setting)); + // BeatsNum = (MaxPayloadSize + DescriptorSize) / BytesPerBeat + tlpMaxBeatsReg <= truncate(DmaMemAddr'(defaultTlpMaxSize << setting) >> valueOf(BYTE_EN_WIDTH)); + endmethod + endinterface +endmodule + +typedef 2'b00 NO_TLP_IN_THIS_BEAT; +typedef 2'b01 SINGLE_TLP_IN_THIS_BEAT; +typedef 2'b11 TWO_TLP_IN_THIS_BEAT; + +typedef 3 BYTEEN_INFIFO_DEPTH; + +// Convert 2 DataStream input to 1 PcieAxiStream output +// - The axistream is in straddle mode which means tKeep and tLast are ignored +// - The core use isSop and isEop to location Tlp and allow 2 Tlp in one beat +// - The input dataStream should be added Descriptor and aligned to DW already +module mkConvertDataStreamsToStraddleAxis(ConvertDataStreamsToStraddleAxis); + FIFOF#(DataStream) dataAInFifo <- mkFIFOF; + FIFOF#(SideBandByteEn) byteEnAFifo <- mkSizedFIFOF(BYTEEN_INFIFO_DEPTH); + FIFOF#(DataStream) dataBInFifo <- mkFIFOF; + FIFOF#(SideBandByteEn) byteEnBFifo <- mkSizedFIFOF(BYTEEN_INFIFO_DEPTH); + + FIFOF#(DataBytePtr) dataPrepareAFifo <- mkFIFOF; + FIFOF#(DataBytePtr) dataPrepareBFifo <- mkFIFOF; + + FIFOF#(PcieAxiStream) axiStreamOutFifo <- mkFIFOF; + + Reg#(StreamWithPtr) remainStreamAWpReg <- mkRegU; + Reg#(StreamWithPtr) remainStreamBWpReg <- mkRegU; + + StreamConcat streamAconcater <- mkStreamConcat; + StreamConcat streamBconcater <- mkStreamConcat; + + Reg#(Bool) isInStreamAReg <- mkReg(False); + Reg#(Bool) isInStreamBReg <- mkReg(False); + Reg#(Bool) hasStreamARemainReg <- mkReg(False); + Reg#(Bool) hasStreamBRemainReg <- mkReg(False); + Reg#(Bool) hasLastStreamARemainReg <- mkReg(False); + Reg#(Bool) hasLastStreamBRemainReg <- mkReg(False); + + function PcieRequsterRequestSideBandFrame genRQSideBand( + PcieTlpCtlIsEopCommon isEop, PcieTlpCtlIsSopCommon isSop, SideBandByteEn byteEnA, SideBandByteEn byteEnB + ); + let {firstByteEnA, lastByteEnA} = byteEnA; + let {firstByteEnB, lastByteEnB} = byteEnB; + let sideBand = PcieRequsterRequestSideBandFrame { + // Do not use parity check in the core + parity : 0, + // Do not support progress track + seqNum1 : 0, + seqNum0 : 0, + //TODO: Do not support Transaction Processing Hint now, maybe we need TPH for better performance + tphSteeringTag : 0, + tphIndirectTagEn : 0, + tphType : 0, + tphPresent : 0, + // Do not support discontinue + discontinue : False, + // Indicates end of the tlp + isEop : isEop, + // Indicates starts of a new tlp + isSop : isSop, + // Disable when use DWord-aligned Mode + addrOffset : 0, + // Indicates byte enable in the first/last DWord + lastByteEn : {pack(lastByteEnB), pack(lastByteEnA)}, + firstByteEn : {pack(firstByteEnB), pack(firstByteEnA)} + }; + return sideBand; + endfunction + + // Pipeline stage 1: get the byte pointer of each stream + rule prepareBytePtr; + if (dataInAFifo.notEmpty && dataPrepareAFifo.notFull) begin + let stream = dataInAFifo.first; + dataInAFifo.deq; + let bytePtr = convertByteEn2BytePtr(stream.byteEn); + dataPrepareAFifo.enq(StreamWithPtr { + stream : stream, + bytePtr: bytePtr + }); + end + if (dataInBFifo.notEmpty && dataPrepareBFifo.notFull) begin + let stream = dataInBFifo.first; + dataInAFifo.deq; + let bytePtr = convertByteEn2BytePtr(stream.byteEn); + dataPrepareBFifo.enq(StreamWithPtr { + stream : stream, + bytePtr: bytePtr + }); + end + endrule + + // Pipeline Stage 2: concat the stream with its remain data (if exist) + rule genStraddlePcie; + let straddleWpA = getEmptyStreamWithPtr; + let straddleWpB = getEmptyStreamWithPtr; + Data straddleData = 0; + let isSop = PcieTlpCtlIsSopCommon { + isSopPtrs : replicate(0), + isSop : 0 + }; + let isEop = PcieTlpCtlIsEopCommon { + isEopPtrs : replicate(0), + isEop : 0 + }; + // This cycle isInStreamA, only transfer StreamA or StreamA + StreamB + if (isInStreamAReg) begin + // First: get the whole streamA data to transfer to the PCIe bus in this cycle + if (hasStreamARemainReg && hasLastStreamARemainReg) begin + straddleWpA = remainStreamAWpReg; + isInStreamAReg <= False; + hasStreamARemainReg <= False; + end + else if (hasStreamARemainReg) begin + let {concatStreamWpA, remainStreamWpA} = getConcatStream(remainStreamAWpReg, dataPrepareAFifo.first); + dataPrepareAFifo.deq; + if (isByteEnZero(remainStreamWpA.stream.byteEn)) begin + isInStreamAReg <= False; + hasStreamARemainReg <= False; + end + else begin + isInStreamAReg <= True; + hasStreamARemainReg <= True; + end + straddleWpA = concatStreamWpA; + remainStreamAWpReg <= remainStreamWpA; + hasLastStreamARemainReg <= dataPrepareAFifo.first.stream.isLast; + end + else begin + straddleWpA = dataPrepareAFifo.first; + dataPrepareAFifo.deq; + end + if (dataPrepareBFifo.notEmpty) begin + straddleWpB = dataPrepareBFifo.first; + end + // Second: generate straddle data + straddleData = straddleWpA.stream.data; + if (straddleWpA.stream.isLast) begin + isEop.isEop = fromInteger(valueOf(SINGLE_TLP_IN_THIS_BEAT)); + isEop.isEopPtrs[0] = convertByteEn2DwordPtr(straddleWpA.stream.byteEn); + end + // only can contains straddleA + if (straddleWpA.bytePtr > fromInteger(valueOf(STRADDLE_THRESH_WIDTH))) begin + + end + // transfer straddleA and straddleB at the same time + else begin + if (straddleWpB.bytePtr > 0) begin + + end + else begin + + end + end + end + // This cycle isInStreamB, only transfer StreamB or StreamB + StreamA + else if (isInStreamBReg) begin + // get the whole streamB data to transfer to the PCIe bus in this cycle + if (hasStreamBRemainReg && hasLastStreamBRemainReg) begin + straddleWpB = remainStreamBWpReg; + isInStreamBReg <= False; + hasStreamBRemainReg <= False; + end + else if (hasStreamBRemainReg) begin + dataPrepareBFifo.deq; + let {concatStreamWpB, remainStreamWpB} = getConcatStream(remainStreamBWpReg, dataPrepareBFifo.first); + if (isByteEnZero(remainStreamWpB.stream.byteEn)) begin + isInStreamBReg <= False; + hasStreamBRemainReg <= False; + end + else begin + isInStreamBReg <= True; + hasStreamBRemainReg <= True; + end + straddleWpB = concatStreamWpB; + remainStreamBWpReg <= remainStreamWpB; + hasLastStreamBRemainReg <= dataPrepareBFifo.first.stream.isLast; + end + else begin + straddleWpB = dataPrepareBFifo.first; + dataPrepareBFifo.deq; + end + if (dataPrepareAFifo.notEmpty) begin + straddleWpA = dataPrepareAFifo.first; + end + end + // This cycle is idle + else begin + if (dataPrepareAFifo.notEmpty) begin + straddleWpA = dataPrepareAFifo.first; + dataPrepareAFifo.deq; + end + if (dataPrepareBFifo.notEmpty) begin + straddleWpB = dataPrepareBFifo.first; + dataPrepareBFifo.deq; + end + end + + endrule + + + + interface dataAFifoIn = convertFifoToFifoIn(dataInAFifo); + interface reqAFifoIn = convertFifoToFifoIn(reqInAFifo); + interface dataBFifoIn = convertFifoToFifoIn(dataInBFifo); + interface reqBFifoIn = convertFifoToFifoIn(reqInBFifo); + +endmodule + +interface AlignedDescGen; + interface FifoIn#(DmaRequest) reqFifoIn; + interface FifoOut#(DataStream) dataFifoOut; + interface FifoOut#(SideBandByteEn) byteEnFifoOut; +endinterface + +typedef Tuple5#( + DmaRequest , + ByteModDWord, + ByteModDWord, + DataBytePtr , + DmaMemAddr + ) AlignedDescGenPipeTuple; + +// Descriptor is 4DW aligned while the input datastream may be not +// This module will add 0~3 Bytes Dummy Data in the end of DescStream to make sure concat(desc, data) is aligned +module mkAlignedRqDescGen(Bool isWrite, AlignedDescGen ifc); + FIFOF#(DmaRequest) reqInFifo <- mkFIFOF; + FIFOF#(DataStream) dataOutFifo <- mkFIFOF; + FIFOF#(SideBandByteEn) byteEnOutFifo <- mkFIFOF; + + FIFOF#(AlignedDescGenPipeTuple) pipelineFifo <- mkFIFOF; + + function DwordCount getDWordCount(DmaMemAddr startAddr, DmaMemAddr endAddr); + let endOffset = byteModDWord(endAddr); + DwordCount dwCnt = (endAddr >> valueOf(BYTE_DWORD_SHIFT_WIDTH)) - (startAddr >> valueOf(BYTE_DWORD_SHIFT_WIDTH)); + return (endOffset == 0) ? dwCnt : dwCnt + 1; + endfunction + + // Pipeline Stage 1: calculate endAddress, first/lastBytePtr and aligned BytePtr + rule getAlignedPtr; + let request = reqInFifo.first; + reqInFifo.deq; + immAssert( + (request.length <= fromInteger(valueOf(BUS_BOUNDARY))), + "Request Check @ mkAlignedRqDescGen", + fshow(request) + ); + DmaMemAddr endAddress = request.startAddr + length - 1; + // firstOffset values from {0, 1, 2, 3} + ByteModDWord firstOffset = byteModDWord(request.startAddr); + ByteModDWord lastOffset = byteModDWord(endAddress); + ByteModDWord alignOffset = ~firstOffset + 1; + DataBytePtr bytePtr = fromInteger(valueOf(TDiv#(DES_RQ_DESCRIPTOR_WIDTH, BYTE_WIDTH))) + zeroExtend(alignOffset); + pipelineFifo.enq(tuple5( + request, + firstOffset, + lastOffset, + bytePtr, + endAddress) + ); + endrule + + // Pipeline Stage 2: generate Descriptor and the dataStream + rule genDescriptor; + let {request, firstBytePtr, lastBytePtr, bytePtr, endAddress} = pipelineFifo.first; + pipelineFifo.deq; + let firstByteEn = convertDWordOffset2FirstByteEn(firstOffset); + let lastByteEn = convertDWordOffset2LastByteEn(lastOffset); + let dwordCnt = getDWordCount(request.startAddr, endAddress); + lastByteEn = (request.startAddr == endAddress) ? 0 : lastByteEn; + let byteEn = convertBytePtr2ByteEn(bytePtr); + let descriptor = PcieRequesterRequestDescriptor { + forceECRC : False, + attributes : 0, + trafficClass : 0, + requesterIdEn : False, + completerId : 0, + tag : 0, + requesterId : 0, + isPoisoned : False, + reqType : isWrite ? fromInteger(valueOf(MEM_WRITE_REQ)) : fromInteger(valueOf(MEM_READ_REQ)), + dwordCnt : dwordCnt, + address : truncate(request.startAddr >> valueOf(BYTE_DWORD_SHIFT_WIDTH)), + addrType : fromInteger(valueOf(TRANSLATED_ADDR)) + }; + let stream = DataStream { + data : zeroExtend(pack(descriptor)), + byteEn : byteEn, + isFirst : True, + isLast : True + }; + dataOutFifo.enq(stream); + byteEnOutFifo.enq(tuple2(firstByteEn, lastByteEn)); + endrule + + interface reqFifoIn = convertFifoToFifoIn(reqInFifo); + interface dataFifoOut = convertFifoToFifoOut(dataOutFifo); + interface byteEnFifoOut = convertFifoToFifoOut(byteEnOutFifo); +endmodule diff --git a/src/DmaRequester.bsv b/src/DmaRequester.bsv index 10c75a3..c7b799d 100644 --- a/src/DmaRequester.bsv +++ b/src/DmaRequester.bsv @@ -37,8 +37,6 @@ interface RequesterComplete; endinterface module mkRequesterRequest(RequesterRequest); - StreamConcat streamConcat <- mkStreamConcat; - FIFOF#(DataStream) wrDataInFifo <- mkFIFOF; FIFOF#(DmaRequest) wrReqInFifo <- mkFIFOF; FIFOF#(DmaRequest) rdReqInFifo <- mkFIFOF; @@ -49,39 +47,32 @@ module mkRequesterRequest(RequesterRequest); Wire#(Bool) postedEnWire <- mkDWire(False); Wire#(Bool) nonPostedEnWire <- mkDWire(True); - function DataStream genRQDescriptorStream(DmaRequest req, Bool isWrite); - let descriptor = PcieRequesterRequestDescriptor { - forceECRC : False, - attributes : 0, - trafficClass : 0, - requesterIdEn : False, - completerId : 0, - tag : 0, - requesterId : 0, - isPoisoned : False, - reqType : isWrite ? fromInteger(valueOf(MEM_WRITE_REQ)) : fromInteger(valueOf(MEM_READ_REQ)), - dwordCnt : truncate(req.length >> 2 + (req.length[0] | req.length[1])), - address : truncate(req.startAddr >> 2), - addrType : 2'b10 - }; - ByteEn byteEn = 1; - let stream = DataStream { - data : zeroExtend(pack(descriptor)), - byteEn : (byteEn << (valueOf(TDiv#(DES_RQ_DESCRIPTOR_WIDTH, BYTE_WIDTH)) + 1)) - 1, - isFirst : True, - isLast : False - }; - return stream; - endfunction - - // TODO: RQ Logic - rule recvWriteReq if (postedEnWire); - if (!isInWritingReg) begin - let wrReq = wrReqInFifo.first; - let wrData = wrDataInFifo.first; + ChunkSplit chunkSplit <- mkChunkSplit; + AlignedDescGen rqDescGenarator <- mkAlignedRqDescGen; + + // Pipeline stage 1: split the whole write request to chunks, latency = 3 + rule recvWriting if (postedEnWire); + if (wrReqInFifo.notEmpty && chunkSplit.dataFifoIn.notFull) begin wrReqInFifo.deq; + chunkSplit.reqFifoIn.enq(wrReqInFifo.first); + end + if (wrDataInFifo.notEmpty && chunkSplit.reqFifoIn.notFull) begin wrDataInFifo.deq; - isInWritingReg <= (wrReq.length > fromInteger(valueOf(ONE_TLP_THRESH))); + chunkSplit.dataFifoIn.enq(wrDataInFifo.first); + end + endrule + + // Pipeline stage 2: generate the RQ descriptor, which may be with 0~3 Byte invalid data for DW alignment, latency = 2 + rule addDescriptor; + if (chunkSplit.chunkReqFifoOut.notEmpty) begin + let chunkReq = chunkSplit.chunkReqFifoOut.first; + chunkSplit.chunkReqFifoOut.deq; + rqDescGenarator.reqFifoIn.enq(chunkReq); + end + if (chunkSplit.chunkDataFifoOut.notEmpty) begin + let chunkDataStream = chunkSplit.chunkDataFifoOut.first; + chunkSplit.chunkDataFifoOut.deq; + descriptorConcat.inputStreamSecondFifoIn.enq(chunkDataStream); end endrule diff --git a/src/DmaTypes.bsv b/src/DmaTypes.bsv index 10a0404..2677774 100755 --- a/src/DmaTypes.bsv +++ b/src/DmaTypes.bsv @@ -5,6 +5,8 @@ import PcieTypes::*; import PcieAxiStreamTypes::*; typedef PCIE_AXIS_DATA_WIDTH DATA_WIDTH; +typedef TDiv#(DATA_WIDTH, 2) STRADDLE_THRESH_WIDTH; + typedef 64 DMA_MEM_ADDR_WIDTH; typedef 32 DMA_CSR_ADDR_WIDTH; @@ -14,9 +16,8 @@ typedef Bit#(DMA_MEM_ADDR_WIDTH) DmaMemAddr; typedef Bit#(DMA_CSR_ADDR_WIDTH) DmaCsrAddr; typedef Bit#(DMA_CSR_DATA_WIDTH) DmaCsrValue; -typedef 8 BYTE_WIDTH; typedef TLog#(BYTE_WIDTH) BYTE_WIDTH_WIDTH; -typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; +typedef 2 BYTE_DWORD_SHIFT_WIDTH; typedef Bit#(BYTE_WIDTH) Byte; typedef Bit#(DWORD_WIDTH) DWord; @@ -24,12 +25,19 @@ typedef Bit#(1) ByteParity; typedef 2 CONCAT_STREAM_NUM; -typedef TDiv#(DATA_WIDTH, BYTE_WIDTH) BYTE_EN_WIDTH; +typedef TDiv#(DATA_WIDTH, BYTE_WIDTH) BYTE_EN_WIDTH; +typedef TDiv#(DATA_WIDTH, DWORD_WIDTH) DWORD_EN_WIDTH; typedef Bit#(DATA_WIDTH) Data; typedef Bit#(BYTE_EN_WIDTH) ByteEn; -typedef Bit#(TAdd#(1, TLog#(DATA_WIDTH))) DataBitPtr; -typedef Bit#(TAdd#(1, TLog#(BYTE_EN_WIDTH))) DataBytePtr; +typedef Bit#(DWORD_BYTES) DWordByteEn; + +typedef Bit#(TAdd#(1, TLog#(DATA_WIDTH))) DataBitPtr; +typedef Bit#(TAdd#(1, TLog#(BYTE_EN_WIDTH))) DataBytePtr; +typedef Bit#(TAdd#(1, TLog#(DWORD_EN_WIDTH))) DataDwordPtr; + +typedef Bit#(TAdd#(1, TLog#(DWORD_BYTES))) DWordBytePtr; +typedef Bit#(BYTE_DWORD_SHIFT_WIDTH) ByteModDWord; typedef struct { DmaMemAddr startAddr; diff --git a/src/PcieAxiStreamTypes.bsv b/src/PcieAxiStreamTypes.bsv index b133c78..bc833bc 100644 --- a/src/PcieAxiStreamTypes.bsv +++ b/src/PcieAxiStreamTypes.bsv @@ -6,8 +6,10 @@ import BusConversion :: *; import SemiFifo :: *; typedef 8 BYTE_WIDTH; -typedef TMul#(2, BYTE_WIDTH) WORD_WIDTH; -typedef TMul#(4, BYTE_WIDTH) DWORD_WIDTH; +typedef 2 WORD_BYTES; +typedef 4 DWORD_BYTES; +typedef TMul#(WORD_BYTES, BYTE_WIDTH) WORD_WIDTH; +typedef TMul#(DWORD_BYTES, BYTE_WIDTH) DWORD_WIDTH; typedef 512 PCIE_AXIS_DATA_WIDTH; typedef TDiv#(PCIE_AXIS_DATA_WIDTH, DWORD_WIDTH) PCIE_AXIS_KEEP_WIDTH; diff --git a/src/PcieDescriptorTypes.bsv b/src/PcieDescriptorTypes.bsv index 2375a3b..2513002 100644 --- a/src/PcieDescriptorTypes.bsv +++ b/src/PcieDescriptorTypes.bsv @@ -149,3 +149,8 @@ typedef 4'b0111 LOCK_READ_REQ; // allowed only in legacy devices typedef 4'b1100 COMMON_MESG; typedef 4'b1101 VENDOR_DEF_MESG; typedef 4'b1110 ATS_MESG; + +// Pcie Addr Types +typedef 2'b00 UNTRANSLATED_ADDR; +typedef 2'b01 TRANSLATION_REQ; +typedef 2'b10 TRANSLATED_ADDR; \ No newline at end of file diff --git a/src/PrimUtils.bsv b/src/PrimUtils.bsv index 66257ba..30a5810 100644 --- a/src/PrimUtils.bsv +++ b/src/PrimUtils.bsv @@ -18,144 +18,319 @@ function Action immAssert(Bool condition, String assertName, Fmt assertFmtMsg); endaction endfunction -function Data getDataLowBytes(Data data, DataBytePtr ptr); - Data temp = 0; - case(ptr) - 1 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*1 -1:0])); - 2 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*2 -1:0])); - 3 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*3 -1:0])); - 4 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*4 -1:0])); - 5 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*5 -1:0])); - 6 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*6 -1:0])); - 7 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*7 -1:0])); - 8 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*8 -1:0])); - 9 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*9 -1:0])); - 10: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*10-1:0])); - 11: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*11-1:0])); - 12: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*12-1:0])); - 13: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*13-1:0])); - 14: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*14-1:0])); - 15: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*15-1:0])); - 16: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*16-1:0])); - 17: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*17-1:0])); - 18: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*18-1:0])); - 19: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*19-1:0])); - 20: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*20-1:0])); - 21: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*21-1:0])); - 22: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*22-1:0])); - 23: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*23-1:0])); - 24: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*24-1:0])); - 25: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*25-1:0])); - 26: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*26-1:0])); - 27: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*27-1:0])); - 28: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*28-1:0])); - 29: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*29-1:0])); - 30: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*30-1:0])); - 31: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*31-1:0])); - 32: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*32-1:0])); - 33: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*33-1:0])); - 34: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*34-1:0])); - 35: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*35-1:0])); - 36: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*36-1:0])); - 37: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*37-1:0])); - 38: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*38-1:0])); - 39: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*39-1:0])); - 40: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*40-1:0])); - 41: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*41-1:0])); - 42: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*42-1:0])); - 43: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*43-1:0])); - 44: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*44-1:0])); - 45: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*45-1:0])); - 46: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*46-1:0])); - 47: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*47-1:0])); - 48: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*48-1:0])); - 49: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*49-1:0])); - 50: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*50-1:0])); - 51: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*51-1:0])); - 52: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*52-1:0])); - 53: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*53-1:0])); - 54: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*54-1:0])); - 55: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*55-1:0])); - 56: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*56-1:0])); - 57: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*57-1:0])); - 58: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*58-1:0])); - 59: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*59-1:0])); - 60: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*60-1:0])); - 61: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*61-1:0])); - 62: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*62-1:0])); - 63: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*63-1:0])); - default: temp = 0; +function ByteModDWord byteModDWord(Bit#(tSz) bytes) provisos(Add#(_a, BYTE_DWORD_SHIFT_WIDTH, tSz)); + return truncate(bytes); +endfunction + +function DataBytePtr convertByteEn2BytePtr (ByteEn byteEn); + DataBytePtr ptr = 0; + case(byteEn) + 'h0000000000000001: ptr = 1; + 'h0000000000000003: ptr = 2; + 'h0000000000000007: ptr = 3; + 'h000000000000000F: ptr = 4; + 'h000000000000001F: ptr = 5; + 'h000000000000003F: ptr = 6; + 'h000000000000007F: ptr = 7; + 'h00000000000000FF: ptr = 8; + 'h00000000000001FF: ptr = 9; + 'h00000000000003FF: ptr = 10; + 'h00000000000007FF: ptr = 11; + 'h0000000000000FFF: ptr = 12; + 'h0000000000001FFF: ptr = 13; + 'h0000000000003FFF: ptr = 14; + 'h0000000000007FFF: ptr = 15; + 'h000000000000FFFF: ptr = 16; + 'h000000000001FFFF: ptr = 17; + 'h000000000003FFFF: ptr = 18; + 'h000000000007FFFF: ptr = 19; + 'h00000000000FFFFF: ptr = 20; + 'h00000000001FFFFF: ptr = 21; + 'h00000000003FFFFF: ptr = 22; + 'h00000000007FFFFF: ptr = 23; + 'h0000000000FFFFFF: ptr = 24; + 'h0000000001FFFFFF: ptr = 25; + 'h0000000003FFFFFF: ptr = 26; + 'h0000000007FFFFFF: ptr = 27; + 'h000000000FFFFFFF: ptr = 28; + 'h000000001FFFFFFF: ptr = 29; + 'h000000003FFFFFFF: ptr = 30; + 'h000000007FFFFFFF: ptr = 31; + 'h00000000FFFFFFFF: ptr = 32; + 'h00000001FFFFFFFF: ptr = 33; + 'h00000003FFFFFFFF: ptr = 34; + 'h00000007FFFFFFFF: ptr = 35; + 'h0000000FFFFFFFFF: ptr = 36; + 'h0000001FFFFFFFFF: ptr = 37; + 'h0000003FFFFFFFFF: ptr = 38; + 'h0000007FFFFFFFFF: ptr = 39; + 'h000000FFFFFFFFFF: ptr = 40; + 'h000001FFFFFFFFFF: ptr = 41; + 'h000003FFFFFFFFFF: ptr = 42; + 'h000007FFFFFFFFFF: ptr = 43; + 'h00000FFFFFFFFFFF: ptr = 44; + 'h00001FFFFFFFFFFF: ptr = 45; + 'h00003FFFFFFFFFFF: ptr = 46; + 'h00007FFFFFFFFFFF: ptr = 47; + 'h0000FFFFFFFFFFFF: ptr = 48; + 'h0001FFFFFFFFFFFF: ptr = 49; + 'h0003FFFFFFFFFFFF: ptr = 50; + 'h0007FFFFFFFFFFFF: ptr = 51; + 'h000FFFFFFFFFFFFF: ptr = 52; + 'h001FFFFFFFFFFFFF: ptr = 53; + 'h003FFFFFFFFFFFFF: ptr = 54; + 'h007FFFFFFFFFFFFF: ptr = 55; + 'h00FFFFFFFFFFFFFF: ptr = 56; + 'h01FFFFFFFFFFFFFF: ptr = 57; + 'h03FFFFFFFFFFFFFF: ptr = 58; + 'h07FFFFFFFFFFFFFF: ptr = 59; + 'h0FFFFFFFFFFFFFFF: ptr = 60; + 'h1FFFFFFFFFFFFFFF: ptr = 61; + 'h3FFFFFFFFFFFFFFF: ptr = 62; + 'h7FFFFFFFFFFFFFFF: ptr = 63; + 'hFFFFFFFFFFFFFFFF: ptr = 64; + default : ptr = 0; endcase - return temp; + return ptr; endfunction -function Data getDataHighBytes(Data data, DataBytePtr ptr); +function ByteEn convertBytePtr2ByteEn (DataBytePtr bytePtr); + ByteEn byteEn = 0; + case(bytePtr) + 1 : byteEn = 'h0000000000000001; + 2 : byteEn = 'h0000000000000003; + 3 : byteEn = 'h0000000000000007; + 4 : byteEn = 'h000000000000000F; + 5 : byteEn = 'h000000000000001F; + 6 : byteEn = 'h000000000000003F; + 7 : byteEn = 'h000000000000007F; + 8 : byteEn = 'h00000000000000FF; + 9 : byteEn = 'h00000000000001FF; + 10 : byteEn = 'h00000000000003FF; + 11 : byteEn = 'h00000000000007FF; + 12 : byteEn = 'h0000000000000FFF; + 13 : byteEn = 'h0000000000001FFF; + 14 : byteEn = 'h0000000000003FFF; + 15 : byteEn = 'h0000000000007FFF; + 16 : byteEn = 'h000000000000FFFF; + 17 : byteEn = 'h000000000001FFFF; + 18 : byteEn = 'h000000000003FFFF; + 19 : byteEn = 'h000000000007FFFF; + 20 : byteEn = 'h00000000000FFFFF; + 21 : byteEn = 'h00000000001FFFFF; + 22 : byteEn = 'h00000000003FFFFF; + 23 : byteEn = 'h00000000007FFFFF; + 24 : byteEn = 'h0000000000FFFFFF; + 25 : byteEn = 'h0000000001FFFFFF; + 26 : byteEn = 'h0000000003FFFFFF; + 27 : byteEn = 'h0000000007FFFFFF; + 28 : byteEn = 'h000000000FFFFFFF; + 29 : byteEn = 'h000000001FFFFFFF; + 30 : byteEn = 'h000000003FFFFFFF; + 31 : byteEn = 'h000000007FFFFFFF; + 32 : byteEn = 'h00000000FFFFFFFF; + 33 : byteEn = 'h00000001FFFFFFFF; + 34 : byteEn = 'h00000003FFFFFFFF; + 35 : byteEn = 'h00000007FFFFFFFF; + 36 : byteEn = 'h0000000FFFFFFFFF; + 37 : byteEn = 'h0000001FFFFFFFFF; + 38 : byteEn = 'h0000003FFFFFFFFF; + 39 : byteEn = 'h0000007FFFFFFFFF; + 40 : byteEn = 'h000000FFFFFFFFFF; + 41 : byteEn = 'h000001FFFFFFFFFF; + 42 : byteEn = 'h000003FFFFFFFFFF; + 43 : byteEn = 'h000007FFFFFFFFFF; + 44 : byteEn = 'h00000FFFFFFFFFFF; + 45 : byteEn = 'h00001FFFFFFFFFFF; + 46 : byteEn = 'h00003FFFFFFFFFFF; + 47 : byteEn = 'h00007FFFFFFFFFFF; + 48 : byteEn = 'h0000FFFFFFFFFFFF; + 49 : byteEn = 'h0001FFFFFFFFFFFF; + 50 : byteEn = 'h0003FFFFFFFFFFFF; + 51 : byteEn = 'h0007FFFFFFFFFFFF; + 52 : byteEn = 'h000FFFFFFFFFFFFF; + 53 : byteEn = 'h001FFFFFFFFFFFFF; + 54 : byteEn = 'h003FFFFFFFFFFFFF; + 55 : byteEn = 'h007FFFFFFFFFFFFF; + 56 : byteEn = 'h00FFFFFFFFFFFFFF; + 57 : byteEn = 'h01FFFFFFFFFFFFFF; + 58 : byteEn = 'h03FFFFFFFFFFFFFF; + 59 : byteEn = 'h07FFFFFFFFFFFFFF; + 60 : byteEn = 'h0FFFFFFFFFFFFFFF; + 61 : byteEn = 'h1FFFFFFFFFFFFFFF; + 62 : byteEn = 'h3FFFFFFFFFFFFFFF; + 63 : byteEn = 'h7FFFFFFFFFFFFFFF; + 64 : byteEn = 'hFFFFFFFFFFFFFFFF; + default : byteEn = 0; + endcase + return byteEn; +endfunction + +function DWordByteEn convertDWordOffset2FirstByteEn (ByteModDWord dwOffset); + DWordByteEn dwByteEn = 0; + case(dwOffset) + 0: dwByteEn = 'b1111; + 1: dwByteEn = 'b1110; + 2: dwByteEn = 'b1100; + 3: dwByteEn = 'b1000; + default: dwByteEn = 'b0000; + endcase + return dwByteEn; +endfunction + +function DWordByteEn convertDWordOffset2LastByteEn (ByteModDWord dwOffset); + DWordByteEn dwByteEn = 0; + case(dwOffset) + 0: dwByteEn = 'b1111; + 1: dwByteEn = 'b0001; + 2: dwByteEn = 'b0011; + 3: dwByteEn = 'b0111; + default: dwByteEn = 'b0000; + endcase + return dwByteEn; +endfunction + +// DWordPtr strarts from 0 not 1 to align to PcieTlpIsEop +function DataDwordPtr convertByteEn2DwordPtr (ByteEn byteEn); + DataDwordPtr ptr = 0; + case(byteEn) + 'h0000000000000001: ptr = 0; + 'h0000000000000003: ptr = 0; + 'h0000000000000007: ptr = 0; + 'h000000000000000F: ptr = 0; + 'h000000000000001F: ptr = 1; + 'h000000000000003F: ptr = 1; + 'h000000000000007F: ptr = 1; + 'h00000000000000FF: ptr = 1; + 'h00000000000001FF: ptr = 2; + 'h00000000000003FF: ptr = 2; + 'h00000000000007FF: ptr = 2; + 'h0000000000000FFF: ptr = 2; + 'h0000000000001FFF: ptr = 3; + 'h0000000000003FFF: ptr = 3; + 'h0000000000007FFF: ptr = 3; + 'h000000000000FFFF: ptr = 3; + 'h000000000001FFFF: ptr = 4; + 'h000000000003FFFF: ptr = 4; + 'h000000000007FFFF: ptr = 4; + 'h00000000000FFFFF: ptr = 4; + 'h00000000001FFFFF: ptr = 5; + 'h00000000003FFFFF: ptr = 5; + 'h00000000007FFFFF: ptr = 5; + 'h0000000000FFFFFF: ptr = 5; + 'h0000000001FFFFFF: ptr = 6; + 'h0000000003FFFFFF: ptr = 6; + 'h0000000007FFFFFF: ptr = 6; + 'h000000000FFFFFFF: ptr = 6; + 'h000000001FFFFFFF: ptr = 7; + 'h000000003FFFFFFF: ptr = 7; + 'h000000007FFFFFFF: ptr = 7; + 'h00000000FFFFFFFF: ptr = 7; + 'h00000001FFFFFFFF: ptr = 8; + 'h00000003FFFFFFFF: ptr = 8; + 'h00000007FFFFFFFF: ptr = 8; + 'h0000000FFFFFFFFF: ptr = 8; + 'h0000001FFFFFFFFF: ptr = 9; + 'h0000003FFFFFFFFF: ptr = 9; + 'h0000007FFFFFFFFF: ptr = 9; + 'h000000FFFFFFFFFF: ptr = 9; + 'h000001FFFFFFFFFF: ptr = 10; + 'h000003FFFFFFFFFF: ptr = 10; + 'h000007FFFFFFFFFF: ptr = 10; + 'h00000FFFFFFFFFFF: ptr = 10; + 'h00001FFFFFFFFFFF: ptr = 11; + 'h00003FFFFFFFFFFF: ptr = 11; + 'h00007FFFFFFFFFFF: ptr = 11; + 'h0000FFFFFFFFFFFF: ptr = 11; + 'h0001FFFFFFFFFFFF: ptr = 12; + 'h0003FFFFFFFFFFFF: ptr = 12; + 'h0007FFFFFFFFFFFF: ptr = 12; + 'h000FFFFFFFFFFFFF: ptr = 12; + 'h001FFFFFFFFFFFFF: ptr = 13; + 'h003FFFFFFFFFFFFF: ptr = 13; + 'h007FFFFFFFFFFFFF: ptr = 13; + 'h00FFFFFFFFFFFFFF: ptr = 13; + 'h01FFFFFFFFFFFFFF: ptr = 14; + 'h03FFFFFFFFFFFFFF: ptr = 14; + 'h07FFFFFFFFFFFFFF: ptr = 14; + 'h0FFFFFFFFFFFFFFF: ptr = 14; + 'h1FFFFFFFFFFFFFFF: ptr = 15; + 'h3FFFFFFFFFFFFFFF: ptr = 15; + 'h7FFFFFFFFFFFFFFF: ptr = 15; + 'hFFFFFFFFFFFFFFFF: ptr = 15; + default : ptr = 0; + endcase + return ptr; +endfunction + +function Data getDataLowBytes(Data data, DataBytePtr ptr); Data temp = 0; case(ptr) - 1 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*1 ])); - 2 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*2 ])); - 3 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*3 ])); - 4 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*4 ])); - 5 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*5 ])); - 6 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*6 ])); - 7 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*7 ])); - 8 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*8 ])); - 9 : temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*9 ])); - 10: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*10])); - 11: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*11])); - 12: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*12])); - 13: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*13])); - 14: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*14])); - 15: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*15])); - 16: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*16])); - 17: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*17])); - 18: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*18])); - 19: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*19])); - 20: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*20])); - 21: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*21])); - 22: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*22])); - 23: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*23])); - 24: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*24])); - 25: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*25])); - 26: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*26])); - 27: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*27])); - 28: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*28])); - 29: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*29])); - 30: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*30])); - 31: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*31])); - 32: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*32])); - 33: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*33])); - 34: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*34])); - 35: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*35])); - 36: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*36])); - 37: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*37])); - 38: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*38])); - 39: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*39])); - 40: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*40])); - 41: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*41])); - 42: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*42])); - 43: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*43])); - 44: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*44])); - 45: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*45])); - 46: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*46])); - 47: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*47])); - 48: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*48])); - 49: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*49])); - 50: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*50])); - 51: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*51])); - 52: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*52])); - 53: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*53])); - 54: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*54])); - 55: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*55])); - 56: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*56])); - 57: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*57])); - 58: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*58])); - 59: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*59])); - 60: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*60])); - 61: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*61])); - 62: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*62])); - 63: temp = zeroExtend(Data'(data[valueOf(DATA_WIDTH)-1:valueOf(DATA_WIDTH)-valueOf(BYTE_WIDTH)*63])); - default: temp = data; + 1 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*1 -1 : 0])); + 2 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*2 -1 : 0])); + 3 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*3 -1 : 0])); + 4 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*4 -1 : 0])); + 5 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*5 -1 : 0])); + 6 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*6 -1 : 0])); + 7 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*7 -1 : 0])); + 8 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*8 -1 : 0])); + 9 : temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*9 -1 : 0])); + 10: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*10-1 : 0])); + 11: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*11-1 : 0])); + 12: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*12-1 : 0])); + 13: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*13-1 : 0])); + 14: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*14-1 : 0])); + 15: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*15-1 : 0])); + 16: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*16-1 : 0])); + 17: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*17-1 : 0])); + 18: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*18-1 : 0])); + 19: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*19-1 : 0])); + 20: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*20-1 : 0])); + 21: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*21-1 : 0])); + 22: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*22-1 : 0])); + 23: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*23-1 : 0])); + 24: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*24-1 : 0])); + 25: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*25-1 : 0])); + 26: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*26-1 : 0])); + 27: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*27-1 : 0])); + 28: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*28-1 : 0])); + 29: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*29-1 : 0])); + 30: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*30-1 : 0])); + 31: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*31-1 : 0])); + 32: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*32-1 : 0])); + 33: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*33-1 : 0])); + 34: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*34-1 : 0])); + 35: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*35-1 : 0])); + 36: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*36-1 : 0])); + 37: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*37-1 : 0])); + 38: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*38-1 : 0])); + 39: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*39-1 : 0])); + 40: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*40-1 : 0])); + 41: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*41-1 : 0])); + 42: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*42-1 : 0])); + 43: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*43-1 : 0])); + 44: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*44-1 : 0])); + 45: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*45-1 : 0])); + 46: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*46-1 : 0])); + 47: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*47-1 : 0])); + 48: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*48-1 : 0])); + 49: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*49-1 : 0])); + 50: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*50-1 : 0])); + 51: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*51-1 : 0])); + 52: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*52-1 : 0])); + 53: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*53-1 : 0])); + 54: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*54-1 : 0])); + 55: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*55-1 : 0])); + 56: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*56-1 : 0])); + 57: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*57-1 : 0])); + 58: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*58-1 : 0])); + 59: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*59-1 : 0])); + 60: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*60-1 : 0])); + 61: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*61-1 : 0])); + 62: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*62-1 : 0])); + 63: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*63-1 : 0])); + 64: temp = zeroExtend(Data'(data[valueOf(BYTE_WIDTH)*64-1 : 0])); + default: temp = 0; endcase return temp; endfunction @@ -226,6 +401,7 @@ function DmaMemAddr getAddrLowBits(DmaMemAddr addr, Bit#(TLog#(DMA_MEM_ADDR_WIDT 61: temp = zeroExtend(DmaMemAddr'(addr[61-1:0])); 62: temp = zeroExtend(DmaMemAddr'(addr[62-1:0])); 63: temp = zeroExtend(DmaMemAddr'(addr[63-1:0])); + 64: temp = zeroExtend(DmaMemAddr'(addr[64-1:0])); default: temp = 0; endcase return temp; diff --git a/src/StreamUtils.bsv b/src/StreamUtils.bsv index 58e6793..bfe2466 100755 --- a/src/StreamUtils.bsv +++ b/src/StreamUtils.bsv @@ -16,9 +16,10 @@ typedef struct { } StreamWithPtr deriving(Bits, Bounded, Eq, FShow); interface StreamConcat; - interface FifoIn#(DataStream) inputStreamFirstFifoIn; - interface FifoIn#(DataStream) inputStreamSecondFifoIn; - interface FifoOut#(DataStream) outputStreamFifoOut; + interface FifoIn#(DataStream) inputStreamFirstFifoIn; + interface FifoIn#(DataStream) inputStreamSecondFifoIn; + interface FifoOut#(DataStream) outputStreamFifoOut; + interface FifoOut#(DataBytePtr) outputBytePtrFifoOut; endinterface interface StreamSplit; @@ -27,84 +28,12 @@ interface StreamSplit; interface FifoOut#(DataStream) outputStreamFifoOut; endinterface -function DataBytePtr convertByteEn2BytePtr (ByteEn byteEn); - DataBytePtr ptr = 0; - case(byteEn) - 'h0000000000000001: ptr = 1; - 'h0000000000000003: ptr = 2; - 'h0000000000000007: ptr = 3; - 'h000000000000000F: ptr = 4; - 'h000000000000001F: ptr = 5; - 'h000000000000003F: ptr = 6; - 'h000000000000007F: ptr = 7; - 'h00000000000000FF: ptr = 8; - 'h00000000000001FF: ptr = 9; - 'h00000000000003FF: ptr = 10; - 'h00000000000007FF: ptr = 11; - 'h0000000000000FFF: ptr = 12; - 'h0000000000001FFF: ptr = 13; - 'h0000000000003FFF: ptr = 14; - 'h0000000000007FFF: ptr = 15; - 'h000000000000FFFF: ptr = 16; - 'h000000000001FFFF: ptr = 17; - 'h000000000003FFFF: ptr = 18; - 'h000000000007FFFF: ptr = 19; - 'h00000000000FFFFF: ptr = 20; - 'h00000000001FFFFF: ptr = 21; - 'h00000000003FFFFF: ptr = 22; - 'h00000000007FFFFF: ptr = 23; - 'h0000000000FFFFFF: ptr = 24; - 'h0000000001FFFFFF: ptr = 25; - 'h0000000003FFFFFF: ptr = 26; - 'h0000000007FFFFFF: ptr = 27; - 'h000000000FFFFFFF: ptr = 28; - 'h000000001FFFFFFF: ptr = 29; - 'h000000003FFFFFFF: ptr = 30; - 'h000000007FFFFFFF: ptr = 31; - 'h00000000FFFFFFFF: ptr = 32; - 'h00000001FFFFFFFF: ptr = 33; - 'h00000003FFFFFFFF: ptr = 34; - 'h00000007FFFFFFFF: ptr = 35; - 'h0000000FFFFFFFFF: ptr = 36; - 'h0000001FFFFFFFFF: ptr = 37; - 'h0000003FFFFFFFFF: ptr = 38; - 'h0000007FFFFFFFFF: ptr = 39; - 'h000000FFFFFFFFFF: ptr = 40; - 'h000001FFFFFFFFFF: ptr = 41; - 'h000003FFFFFFFFFF: ptr = 42; - 'h000007FFFFFFFFFF: ptr = 43; - 'h00000FFFFFFFFFFF: ptr = 44; - 'h00001FFFFFFFFFFF: ptr = 45; - 'h00003FFFFFFFFFFF: ptr = 46; - 'h00007FFFFFFFFFFF: ptr = 47; - 'h0000FFFFFFFFFFFF: ptr = 48; - 'h0001FFFFFFFFFFFF: ptr = 49; - 'h0003FFFFFFFFFFFF: ptr = 50; - 'h0007FFFFFFFFFFFF: ptr = 51; - 'h000FFFFFFFFFFFFF: ptr = 52; - 'h001FFFFFFFFFFFFF: ptr = 53; - 'h003FFFFFFFFFFFFF: ptr = 54; - 'h007FFFFFFFFFFFFF: ptr = 55; - 'h00FFFFFFFFFFFFFF: ptr = 56; - 'h01FFFFFFFFFFFFFF: ptr = 57; - 'h03FFFFFFFFFFFFFF: ptr = 58; - 'h07FFFFFFFFFFFFFF: ptr = 59; - 'h0FFFFFFFFFFFFFFF: ptr = 60; - 'h1FFFFFFFFFFFFFFF: ptr = 61; - 'h3FFFFFFFFFFFFFFF: ptr = 62; - 'h7FFFFFFFFFFFFFFF: ptr = 63; - 'hFFFFFFFFFFFFFFFF: ptr = 64; - default : ptr = 0; - endcase - return ptr; -endfunction - function Bool isByteEnZero(ByteEn byteEn); return !unpack(byteEn[0]); endfunction function DataStream getEmptyStream (); - return DataStream{ + return DataStream { data: 0, byteEn: 0, isFirst: False, @@ -112,6 +41,13 @@ function DataStream getEmptyStream (); }; endfunction +function StreamWithPtr getEmptyStreamWithPtr (); + return StreamWithPtr { + stream : getEmptyStream, + bytePtr: 0 + }; +endfunction + function DataBitPtr getMaxBitPtr (); return fromInteger(valueOf(DATA_WIDTH)); endfunction @@ -121,42 +57,47 @@ function DataBytePtr getMaxBytePtr (); endfunction // Concat two DataStream frames into one. StreamA.isLast must be True, otherwise the function will return a empty frame to end the stream. -function Tuple3#(DataStream, DataStream, DataBytePtr) getConcatStream (DataStream streamA, DataStream streamB, DataBytePtr bytePtrA, DataBytePtr bytePtrB); - Bool isCallLegally = (streamA.isLast && bytePtrA <= getMaxBytePtr && bytePtrA > 0); - DataBitPtr bitPtrA = zeroExtend(bytePtrA) << fromInteger(valueOf(BYTE_WIDTH_WIDTH)); +function Tuple2#(StreamWithPtr, StreamWithPtr) getConcatStream (StreamWithPtr streamA, StreamWithPtr streamB); + Bool isCallLegally = (streamA.stream.isLast && streamA.bytePtr <= getMaxBytePtr && streamA.bytePtr >= 0); + DataBitPtr bitPtrA = zeroExtend(streamA.bytePtr) << fromInteger(valueOf(BYTE_WIDTH_WIDTH)); // Fill the low PtrA bytes by streamA data - Data concatDataA = streamA.data; - ByteEn concatByteEnA = streamA.byteEn; + Data concatDataA = streamA.stream.data; + ByteEn concatByteEnA = streamA.stream.byteEn; // Fill the high bytes by streamB data - Data concatDataB = streamB.data << bitPtrA; - ByteEn concatByteEnB = streamB.byteEn << bytePtrA; - Data concatData = concatDataA | concatDataB; + Data concatDataB = streamB.stream.data << bitPtrA; + ByteEn concatByteEnB = streamB.stream.byteEn << streamA.bytePtr; + Data concatData = concatDataA | concatDataB; ByteEn concatByteEn = concatByteEnA | concatByteEnB; // Get the remain bytes of streamB data - DataBitPtr resBitPtr = getMaxBitPtr - bitPtrA; - DataBytePtr resBytePtr = getMaxBytePtr - bytePtrA; - Data remainData = streamB.data >> resBitPtr; - ByteEn remainByteEn = streamB.byteEn >> resBytePtr; + DataBitPtr resBitPtr = getMaxBitPtr - bitPtrA; + DataBytePtr resBytePtr = getMaxBytePtr - streamA.bytePtr; + Data remainData = streamB.stream.data >> resBitPtr; + ByteEn remainByteEn = streamB.stream.byteEn >> resBytePtr; - // Get if the concat frame is the last - Bool isConcatStreamLast = streamB.isLast; + // Get if the concat frame is the last, i.e. can streamB be contained by the residual empty bytes + Bool isConcatStreamLast = streamB.stream.isLast; DataBytePtr remainBytePtr = 0; - if (resBytePtr < bytePtrB ) begin + DataBytePtr concatStreamPtr = streamA.bytePtr; + if (resBytePtr < streamB.bytePtr ) begin isConcatStreamLast = False; - remainBytePtr = bytePtrB - resBytePtr; + remainBytePtr = streamB.bytePtr - resBytePtr; + concatStreamPtr = getMaxBytePtr; + end + else begin + concatStreamPtr = streamA.bytePtr + streamB.bytePtr; end - DataStream concatStream = getEmptyStream; - DataStream remainStream = getEmptyStream; // package the return concatStream and remainStream + DataStream concatStream = getEmptyStream; + DataStream remainStream = getEmptyStream; if(isCallLegally) begin concatStream = DataStream { data : concatData, byteEn : concatByteEn, - isFirst: streamA.isFirst, + isFirst: streamA.stream.isFirst, isLast : isConcatStreamLast }; remainStream = DataStream { @@ -166,7 +107,15 @@ function Tuple3#(DataStream, DataStream, DataBytePtr) getConcatStream (DataStrea isLast : True }; end - return tuple3(concatStream, remainStream, remainBytePtr); + let concatStreamWithPtr = StreamWithPtr { + stream : concatStream, + bytePtr: concatStreamPtr + }; + let remainStreamWithPtr = StreamWithPtr { + stream : remainStream, + bytePtr: remainBytePtr + }; + return tuple2(concatStreamWithPtr, remainStreamWithPtr); endfunction (* synthesize *) @@ -175,119 +124,133 @@ module mkStreamConcat (StreamConcat ifc); FIFOF#(DataStream) inputFifoA <- mkFIFOF; FIFOF#(DataStream) inputFifoB <- mkFIFOF; FIFOF#(DataStream) outputFifo <- mkFIFOF; + FIFOF#(DataBytePtr) bytePtrFifo <- mkFIFOF; FIFOF#(StreamWithPtr) prepareFifoA <- mkFIFOF; FIFOF#(StreamWithPtr) prepareFifoB <- mkFIFOF; - Reg#(DataBytePtr) bytePtrRegA <- mkReg(0); - Reg#(DataBytePtr) bytePtrRegB <- mkReg(0); - Reg#(DataBytePtr) remainBytePtrReg <- mkReg(0); - Reg#(Bool) hasRemainReg <- mkReg(False); + Reg#(Bool) hasRemainReg <- mkReg(False); Reg#(Bool) hasLastRemainReg <- mkReg(False); - Reg#(Bool) isStreamAEnd <- mkReg(False); + Reg#(Bool) isStreamAEndReg <- mkReg(False); - Reg#(DataStream) remainStreamReg <- mkRegU; + Reg#(StreamWithPtr) remainStreamWpReg <- mkRegU; - - rule prepareStreamA; - let streamA = inputFifoA.first; - inputFifoA.deq; - DataBytePtr bytePtr = convertByteEn2BytePtr(streamA.byteEn); - prepareFifoA.enq(StreamWithPtr { - stream: streamA, - bytePtr: bytePtr - }); - endrule - - rule prepareStreamB; - let streamB = inputFifoB.first; - inputFifoB.deq; - DataBytePtr bytePtr = convertByteEn2BytePtr(streamB.byteEn); - prepareFifoB.enq(StreamWithPtr { - stream: streamB, - bytePtr: bytePtr - }); + // Pipeline stage 1: get the bytePtr of each stream + rule prepareStream; + if (inputFifoA.notEmpty) begin + let streamA = inputFifoA.first; + inputFifoA.deq; + let bytePtr = convertByteEn2BytePtr(streamA.byteEn); + prepareFifoA.enq(StreamWithPtr { + stream: streamA, + bytePtr: bytePtr + }); + end + if (inputFifoB.notEmpty) begin + let streamB = inputFifoB.first; + inputFifoB.deq; + let bytePtr = convertByteEn2BytePtr(streamB.byteEn); + prepareFifoB.enq(StreamWithPtr { + stream: streamB, + bytePtr: bytePtr + }); + end endrule + // Pipeline stage 2: concat the stream frame rule concatStream; // Only the remain data if (hasRemainReg && hasLastRemainReg) begin - outputFifo.enq(remainStreamReg); - hasRemainReg <= False; - isStreamAEnd <= False; + outputFifo.enq(remainStreamWpReg.stream); + bytePtrFifo.enq(remainStreamWpReg.bytePtr); + hasRemainReg <= False; + isStreamAEndReg <= False; end // StreamB or streamB + the remain data - else if (prepareFifoB.notEmpty && isStreamAEnd) begin - let streamB = prepareFifoB.first.stream; - let bytePtrB = prepareFifoB.first.bytePtr; + else if (prepareFifoB.notEmpty && isStreamAEndReg) begin + let streamBWp = prepareFifoB.first; prepareFifoB.deq; - streamB.isFirst = False; + streamBWp.stream.isFirst = False; if (hasRemainReg) begin - let {concatStream, remainStream, remainBytePtr} = getConcatStream(remainStreamReg, streamB, remainBytePtrReg, bytePtrB); - hasRemainReg <= !isByteEnZero(remainStream.byteEn); - hasLastRemainReg <= streamB.isLast; - remainStreamReg <= remainStream; - remainBytePtrReg <= remainBytePtr; - outputFifo.enq(concatStream); + let {concatStreamWp, remainStreamWp} = getConcatStream(remainStreamWpReg, streamBWp); + hasRemainReg <= !isByteEnZero(remainStreamWp.stream.byteEn); + hasLastRemainReg <= streamBWp.stream.isLast; + remainStreamWpReg <= remainStreamWp; + outputFifo.enq(concatStreamWp.stream); + bytePtrFifo.enq(concatStreamWp.bytePtr); end else begin - outputFifo.enq(streamB); + outputFifo.enq(streamBWp.stream); + bytePtrFifo.enq(streamBWp.bytePtr); end - isStreamAEnd <= !streamB.isLast; + // reset isStreamAEnd to False when the whole concat end + isStreamAEndReg <= streamBWp.stream.isLast ? False : isStreamAEndReg; end // StreamA or StreamA + first StreamB else if (prepareFifoA.notEmpty) begin - let streamA = prepareFifoA.first.stream; - let bytePtrA = prepareFifoA.first.bytePtr; + let streamAWp = prepareFifoA.first; // Only StreamA frame - if (!streamA.isLast) begin - outputFifo.enq(streamA); + if (!streamAWp.stream.isLast) begin + outputFifo.enq(streamAWp.stream); + bytePtrFifo.enq(streamAWp.bytePtr); prepareFifoA.deq; - isStreamAEnd <= False; + isStreamAEndReg <= False; end // the last StreamA + the first StreamB - else if (streamA.isLast && prepareFifoB.notEmpty) begin - let streamB = prepareFifoB.first.stream; - let bytePtrB = prepareFifoB.first.bytePtr; - let {concatStream, remainStream, remainBytePtr} = getConcatStream(streamA, streamB, bytePtrA, bytePtrB); - hasRemainReg <= !isByteEnZero(remainStream.byteEn); - hasLastRemainReg <= streamB.isLast; - remainStreamReg <= remainStream; - remainBytePtrReg <= remainBytePtr; - isStreamAEnd <= !streamB.isLast; - outputFifo.enq(concatStream); + else if(streamAWp.stream.isLast && prepareFifoB.notEmpty) begin + let streamBWp = prepareFifoB.first; + let {concatStreamWp, remainStreamWp} = getConcatStream(streamAWp, streamBWp); + hasRemainReg <= !isByteEnZero(remainStreamWp.stream.byteEn); + hasLastRemainReg <= streamBWp.stream.isLast; + remainStreamWpReg <= remainStreamWp; + // If streamB.isLast, reset isStreamAEnd; otherwise assert isStreamAEnd + isStreamAEndReg <= streamBWp.stream.isLast ? False : True; + outputFifo.enq(concatStreamWp.stream); + bytePtrFifo.enq(concatStreamWp.bytePtr); prepareFifoA.deq; prepareFifoB.deq; end + // Do nothing + else begin + // - !prepareB.notEmpty ==> waiting StreamB for concatation + end + end + // Do nothing + else begin + // - prepareB.notEmpty && !isStreamAEnd ==> waiting streamAEnd asserts + // - !prepareB.notEmpty && !prepareA.notEmpty ==> waiting new data end endrule interface inputStreamFirstFifoIn = convertFifoToFifoIn(inputFifoA); interface inputStreamSecondFifoIn = convertFifoToFifoIn(inputFifoB); interface outputStreamFifoOut = convertFifoToFifoOut(outputFifo); + interface outputBytePtrFifoOut = convertFifoToFifoOut(bytePtrFifo); endmodule +typedef 3 STREAM_SPLIT_LATENCY; + (* synthesize *) module mkStreamSplit(StreamSplit ifc); Reg#(StreamSize) streamByteCntReg <- mkReg(0); - FIFOF#(StreamSize) splitLocationFifo <- mkFIFOF; + FIFOF#(StreamSize) splitLocationFifo <- mkSizedFIFOF(valueOf(STREAM_SPLIT_LATENCY)); FIFOF#(DataStream) inputFifo <- mkFIFOF; FIFOF#(DataStream) outputFifo <- mkFIFOF; FIFOF#(StreamWithPtr) prepareFifo <- mkFIFOF; FIFOF#(StreamWithPtr) assertFifo <- mkFIFOF; - FIFOF#(Tuple2#(DataBytePtr,DataBytePtr)) splitPtrFifo <- mkFIFOF; + FIFOF#(DataBytePtr) splitPtrFifo <- mkSizedFIFOF(valueOf(STREAM_SPLIT_LATENCY)); - Reg#(DataStream) remainStreamReg <- mkRegU; - Reg#(DataBytePtr) remainBytePtrReg <- mkReg(0); + Reg#(StreamWithPtr) remainStreamWpReg <- mkRegU; Reg#(Bool) hasRemainReg <- mkReg(False); Reg#(Bool) hasLastRemainReg <- mkReg(False); - Reg#(Bool) isSplitted <- mkReg(False); + Reg#(Bool) isSplittedReg <- mkReg(False); + // Pipeline stage 1: get the bytePtr of the input stream frame rule prepareStream; let stream = inputFifo.first; inputFifo.deq; @@ -298,77 +261,79 @@ module mkStreamSplit(StreamSplit ifc); prepareFifo.enq(streamWithPtr); endrule + // Pipeline stage 2: assert if splitLocation in this beat and calculate the offsetBytePtr rule assertSplitStream; let stream = prepareFifo.first.stream; - let bytePtr = prepareFifo.first.bytePtr; + let bytePtr = prepareFifo.first.bytePtr; + prepareFifo.deq; let splitLocation = splitLocationFifo.first; - DataBytePtr truncateBytePtr = 0; - if (!isSplitted && unpack(zeroExtend(bytePtr)) + streamByteCntReg >= splitLocation) begin - truncateBytePtr = truncate(pack(splitLocation - streamByteCntReg)); + if (stream.isLast) begin + splitLocationFifo.deq; + end + DataBytePtr offsetBytePtr = 0; + let curLocation = unpack(zeroExtend(bytePtr)) + streamByteCntReg; + if (!isSplittedReg && curLocation >= splitLocation) begin + offsetBytePtr = truncate(pack(splitLocation - streamByteCntReg)); end - DataBytePtr resBytePtr = getMaxBytePtr - truncateBytePtr; - splitPtrFifo.enq(tuple2(truncateBytePtr, resBytePtr)); - if (truncateBytePtr > 0 && !stream.isLast) begin - isSplitted <= True; + splitPtrFifo.enq(offsetBytePtr); + if (offsetBytePtr > 0 && !stream.isLast) begin + isSplittedReg <= True; end else if (stream.isLast) begin - isSplitted <= False; + isSplittedReg <= False; end streamByteCntReg <= stream.isLast ? 0 : streamByteCntReg + unpack(zeroExtend(bytePtr)); assertFifo.enq(prepareFifo.first); - prepareFifo.deq; - if (stream.isLast) begin - splitLocationFifo.deq; - end endrule - + // Pipeline stage 3: split the stream frame or output it without modify accroding to offsetBytePtr rule execSplitStream; // Only output remainStreamReg if (hasRemainReg && hasLastRemainReg) begin - outputFifo.enq(remainStreamReg); + outputFifo.enq(remainStreamWpReg.stream); hasRemainReg <= False; hasLastRemainReg <= False; end + // not the last remain stream else if (assertFifo.notEmpty && splitPtrFifo.notEmpty) begin - let stream = assertFifo.first.stream; - let frameBytePtr = assertFifo.first.bytePtr; - let {truncateBytePtr, resBytePtr} = splitPtrFifo.first; + let streamWp = assertFifo.first; + let offsetBytePtr = splitPtrFifo.first; assertFifo.deq; splitPtrFifo.deq; - // no operatation - if (!hasRemainReg && truncateBytePtr == 0) begin - outputFifo.enq(stream); + // split location not in this beat, do nothing + if (!hasRemainReg && offsetBytePtr == 0) begin + outputFifo.enq(streamWp.stream); end - // split the frame in this cycle to a last frame and a remain frame - else if (!hasRemainReg && truncateBytePtr > 0) begin - DataBitPtr truncateBitPtr = zeroExtend(truncateBytePtr) << valueOf(BYTE_WIDTH_WIDTH); - DataBitPtr resBitPtr = zeroExtend(resBytePtr) << valueOf(BYTE_WIDTH_WIDTH); - outputFifo.enq(DataStream { - data: (stream.data << resBitPtr) >> resBitPtr, - byteEn: (stream.byteEn << resBytePtr) >> resBytePtr, - isFirst: stream.isFirst, + // split the frame in this cycle to a isLast=True frame and a remain frame + else if (!hasRemainReg && offsetBytePtr > 0) begin + DataBitPtr offsetBitPtr = zeroExtend(offsetBytePtr) << valueOf(BYTE_WIDTH_WIDTH); + let splitStream = DataStream { + data: getDataLowBytes(streamWp.stream.data, offsetBytePtr), + byteEn: convertBytePtr2ByteEn(offsetBytePtr), + isFirst: streamWp.stream.isFirst, isLast: True - }); - DataStream remainStream = DataStream { - data: stream.data >> truncateBitPtr, - byteEn: stream.byteEn >> truncateBytePtr, + }; + outputFifo.enq(splitStream); + let remainStream = DataStream { + data: streamWp.stream.data >> offsetBitPtr, + byteEn: streamWp.stream.byteEn >> offsetBytePtr, isFirst: True, isLast: True }; - hasRemainReg <= !isByteEnZero(remainStream.byteEn); - hasLastRemainReg <= stream.isLast; - remainBytePtrReg <= frameBytePtr - truncateBytePtr; - remainStreamReg <= remainStream; + hasRemainReg <= True; + hasLastRemainReg <= streamWp.stream.isLast; + remainStreamWpReg <= StreamWithPtr { + stream : remainStream, + bytePtr: streamWp.bytePtr - offsetBytePtr + }; end - // concat the new frame with the remainReg - else if (hasRemainReg) begin - let {concatStream, remainStream, remainBytePtr} = getConcatStream(remainStreamReg, stream, remainBytePtrReg, frameBytePtr); - outputFifo.enq(concatStream); - hasRemainReg <= !isByteEnZero(remainStream.byteEn); - hasLastRemainReg <= stream.isLast; - remainStreamReg <= remainStream; - remainBytePtrReg <= remainBytePtr; + // concat the stream frame with the remainReg + else begin + let {concatStreamWp, remainStreamWp} = getConcatStream(remainStreamWpReg, streamWp); + outputFifo.enq(concatStreamWp.stream); + hasRemainReg <= streamWp.stream.isLast ? !isByteEnZero(remainStreamWp.stream.byteEn) : True; + hasLastRemainReg <= streamWp.stream.isLast; + remainStreamWpReg <= remainStreamWp; end end endrule diff --git a/test/TestDmaCore.bsv b/test/TestDmaCore.bsv index 14d6178..696ff80 100755 --- a/test/TestDmaCore.bsv +++ b/test/TestDmaCore.bsv @@ -13,7 +13,6 @@ typedef 2'b00 DEFAULT_TLP_SIZE_SETTING; typedef 4 CHUNK_TX_TEST_SETTING_NUM; typedef 6 CHUNK_RX_TEST_SETTING_NUM; -(* doc = "testcase" *) module mkChunkComputerTb(Empty); ChunkCompute dut <- mkChunkComputer(DMA_TX); @@ -90,4 +89,30 @@ module mkChunkComputerTb(Empty); end endrule +endmodule + +typedef 'hABCD311 SIMPLE_TEST_ADDR ; +typedef 'h1111 SIMPLE_TEST_LEN ; + +(* doc = "testcase" *) +module mkSimpleTestAlignedRqDescGen(Empty); + AlignedDescGen dut <- mkAlignedRqDescGen; + + Reg#(Bool) isInitReg <- mkReg(False); + + rule testInit if (!isInitReg); + isInitReg <= True; + dut.reqFifoIn.enq(DmaRequest { + startAddr: fromInteger(valueOf(SIMPLE_TEST_ADDR)), + length : fromInteger(valueOf(SIMPLE_TEST_LEN)) + }); + endrule + + rule testOutput if (isInitReg); + let stream = dut.dataFifoOut.first; + stream.deq; + $display(fshow(stream)); + $finish(); + endrule + endmodule \ No newline at end of file diff --git a/test/TestStreamUtils.bsv b/test/TestStreamUtils.bsv index 3241357..9682120 100755 --- a/test/TestStreamUtils.bsv +++ b/test/TestStreamUtils.bsv @@ -160,6 +160,7 @@ module mkStreamConcatTb(Empty); ); end dut.outputStreamFifoOut.deq; + dut.outputBytePtrFifoOut.deq; endrule rule testFinish; From 63777bcbac1c1044a2cc2d3fc43d1a88f82970d5 Mon Sep 17 00:00:00 2001 From: BIGWJZ <1059537323@qq.com> Date: Mon, 5 Aug 2024 11:07:07 +0800 Subject: [PATCH 31/53] Add streamShift --- img/requester.drawio.svg | 784 ++++++++++++++++++++++++++------------- run_one.sh | 2 +- src/DmaRequestCore.bsv | 151 ++------ src/DmaTypes.bsv | 2 +- src/StreamUtils.bsv | 110 ++++-- test/TestDmaCore.bsv | 5 +- test/TestStreamUtils.bsv | 146 +++++++- 7 files changed, 758 insertions(+), 442 deletions(-) diff --git a/img/requester.drawio.svg b/img/requester.drawio.svg index 2100c59..d678ef1 100644 --- a/img/requester.drawio.svg +++ b/img/requester.drawio.svg @@ -1,13 +1,13 @@ - + - - - - + + + + - - + + DataStream @@ -15,18 +15,18 @@ - + DataStream - - - - + + + + - - + + Request @@ -34,18 +34,18 @@ - + Request - - - - + + + + - - + + @@ -55,16 +55,16 @@ - + StreamConcat - - + + - - + + first @@ -72,16 +72,16 @@ - + first - - + + - - + + second @@ -89,22 +89,22 @@ - + second - - - - - - - - + + + + + + + + - - + + @@ -114,16 +114,16 @@ - + convertToAxis - - + + - - + + RawPcieRequeser @@ -131,17 +131,17 @@ - + RawPcieRequeser - - - + + + - - + + req @@ -149,17 +149,17 @@ - + req - - - + + + - - + + data @@ -167,16 +167,16 @@ - + data - - + + - - + + ChunkSplit @@ -184,16 +184,16 @@ - + ChunkSplit - - + + - - + + Descriptor @@ -201,16 +201,16 @@ - + Descriptor - - + + - - + + DataStream @@ -218,16 +218,16 @@ - + DataStream - - + + - - + + isDone @@ -235,18 +235,18 @@ - + isDone - - - - + + + + - - + + DataStream @@ -254,18 +254,18 @@ - + DataStream - - - - + + + + - - + + Request @@ -273,16 +273,16 @@ - + Request - - + + - - + + isDone @@ -290,16 +290,16 @@ - + isDone - - + + - - + + @@ -309,35 +309,16 @@ - + dsFifoInA - - + + - - - - - - dsFifoInB - - - - - - - dsFifoInB - - - - - - - - + + @@ -347,16 +328,16 @@ - + tData - - + + - - + + @@ -366,16 +347,16 @@ - + tKeep - - + + - - + + @@ -385,16 +366,16 @@ - + tUser - - + + - - + + @@ -404,16 +385,16 @@ - + tLast - - + + - - + + straddle 1 @@ -421,16 +402,16 @@ - + straddle 1 - - + + - - + + straddle 0 @@ -438,16 +419,16 @@ - + straddle 0 - - + + - - + + StreamA/B last beat bytePtr > 256bit @@ -455,16 +436,16 @@ - + StreamA/B last beat bytePtr > 256bit - - + + - - + + Only singe streamA/B @@ -472,16 +453,16 @@ - + Only singe streamA/B - - + + - - + + StreamA @@ -489,16 +470,16 @@ - + StreamA - - + + - - + + StreamB @@ -506,16 +487,16 @@ - + StreamB - - + + - - + + @@ -525,16 +506,16 @@ - + x - - + + - - + + @@ -544,16 +525,16 @@ - + x - - + + - - + +