From 1c4d26342395b1458ea3dbee54d0daaa1a122c85 Mon Sep 17 00:00:00 2001 From: Yunhao Deng Date: Sun, 1 Sep 2024 17:53:31 +0200 Subject: [PATCH] The helper function to connect CSR to xdmaStreamer easily (#296) * Initial Commit * Bug Fix * Bug Fix --- .../snax/xdma/xdmaFrontend/DMACtrl.scala | 74 ++----------------- .../snax/xdma/xdmaFrontend/DMADataPath.scala | 19 +++++ .../xdma/xdmaStreamer/AddressGenUnit.scala | 23 ++++++ .../scala/snax/xdma/xdmaStreamer/Reader.scala | 5 ++ .../xdma/xdmaStreamer/ReaderWriterIO.scala | 24 ++++++ .../scala/snax/xdma/xdmaTop/xdmaTop.scala | 8 +- .../xdma/xdmaFrontEnd/DMADataPathTester.scala | 5 +- .../snax/xdma/xdmaStreamer/ReaderTester.scala | 3 +- .../snax/xdma/xdmaTop/xdmaTopTester.scala | 23 +++--- 9 files changed, 99 insertions(+), 85 deletions(-) diff --git a/hw/chisel/src/main/scala/snax/xdma/xdmaFrontend/DMACtrl.scala b/hw/chisel/src/main/scala/snax/xdma/xdmaFrontend/DMACtrl.scala index fcff44ec2..3b3dba3da 100644 --- a/hw/chisel/src/main/scala/snax/xdma/xdmaFrontend/DMACtrl.scala +++ b/hw/chisel/src/main/scala/snax/xdma/xdmaFrontend/DMACtrl.scala @@ -219,79 +219,21 @@ class DMACtrl( ) var remainingCSR = i_csrmanager.io.csr_config_out.bits.toIndexedSeq - // Pack the unstructured signal from csrManager to structured signal: Src side - // Connect agu_cfg.Ptr & readerPtr - preRoute_src_local.bits.aguCfg.ptr := Cat(remainingCSR(1), remainingCSR(0)) - preRoute_src_local.bits.readerPtr := Cat(remainingCSR(1), remainingCSR(0)) - preRoute_dst_local.bits.readerPtr := Cat(remainingCSR(1), remainingCSR(0)) - remainingCSR = remainingCSR.tail.tail - - // Connect aguCfg.spatialStrides - for (i <- 0 until preRoute_src_local.bits.aguCfg.spatialStrides.length) { - preRoute_src_local.bits.aguCfg.spatialStrides(i) := remainingCSR.head - remainingCSR = remainingCSR.tail - } - - // Connect aguCfg.temporalStrides - for (i <- 0 until preRoute_src_local.bits.aguCfg.temporalStrides.length) { - preRoute_src_local.bits.aguCfg.temporalStrides(i) := remainingCSR.head - remainingCSR = remainingCSR.tail - } + // Connect reader + writer cfg to the structured signal: Src side + remainingCSR = + preRoute_src_local.bits.connectReaderWriterCfgWithList(remainingCSR) - // Connect aguCfg.temporalBounds - for (i <- 0 until preRoute_src_local.bits.aguCfg.temporalBounds.length) { - preRoute_src_local.bits.aguCfg.temporalBounds(i) := remainingCSR.head - remainingCSR = remainingCSR.tail - } - // Connect enabledChannel signal - preRoute_src_local.bits.readerwriterCfg.enabledChannel := remainingCSR.head - remainingCSR = remainingCSR.tail - - // Connect enabledByte signal. As the enabledByte is not effective, so assign all true, and not take any value from CSR right now - preRoute_src_local.bits.readerwriterCfg.enabledByte := VecInit( - Seq.fill(readerparam.rwParam.tcdmParam.dataWidth / 8)(true.B) - ).asUInt - - // Connect extension signal + // Connect extension signal: Src side for (i <- 0 until preRoute_src_local.bits.extCfg.length) { preRoute_src_local.bits.extCfg(i) := remainingCSR.head remainingCSR = remainingCSR.tail } - // Pack the unstructured signal from csrManager to structured signal: Dst side - // Connect agu_cfg.Ptr & writerPtr - preRoute_dst_local.bits.aguCfg.ptr := Cat(remainingCSR(1), remainingCSR(0)) - preRoute_src_local.bits.writerPtr := Cat(remainingCSR(1), remainingCSR(0)) - preRoute_dst_local.bits.writerPtr := Cat(remainingCSR(1), remainingCSR(0)) - remainingCSR = remainingCSR.tail.tail - - // Connect aguCfg.spatialStrides - for (i <- 0 until preRoute_dst_local.bits.aguCfg.spatialStrides.length) { - preRoute_dst_local.bits.aguCfg.spatialStrides(i) := remainingCSR.head - remainingCSR = remainingCSR.tail - } - - // Connect aguCfg.temporalStrides - for (i <- 0 until preRoute_dst_local.bits.aguCfg.temporalStrides.length) { - preRoute_dst_local.bits.aguCfg.temporalStrides(i) := remainingCSR.head - remainingCSR = remainingCSR.tail - } - - // Connect aguCfg.temporalBounds - for (i <- 0 until preRoute_dst_local.bits.aguCfg.temporalBounds.length) { - preRoute_dst_local.bits.aguCfg.temporalBounds(i) := remainingCSR.head - remainingCSR = remainingCSR.tail - } - - // Connect enabledChannel signal - preRoute_dst_local.bits.readerwriterCfg.enabledChannel := remainingCSR.head - remainingCSR = remainingCSR.tail - - // Connect enabledByte signal. As the strb is effective, so assign the value from CSR - preRoute_dst_local.bits.readerwriterCfg.enabledByte := remainingCSR.head - remainingCSR = remainingCSR.tail + // Connect reader + writer cfg to the structured signal: Dst side + remainingCSR = + preRoute_dst_local.bits.connectReaderWriterCfgWithList(remainingCSR) - // Connect extension signal + // Connect extension signal: Dst side for (i <- 0 until preRoute_dst_local.bits.extCfg.length) { preRoute_dst_local.bits.extCfg(i) := remainingCSR.head remainingCSR = remainingCSR.tail diff --git a/hw/chisel/src/main/scala/snax/xdma/xdmaFrontend/DMADataPath.scala b/hw/chisel/src/main/scala/snax/xdma/xdmaFrontend/DMADataPath.scala index 7af188713..18522d7c1 100644 --- a/hw/chisel/src/main/scala/snax/xdma/xdmaFrontend/DMADataPath.scala +++ b/hw/chisel/src/main/scala/snax/xdma/xdmaFrontend/DMADataPath.scala @@ -20,6 +20,16 @@ class DMADataPathCfgIO(param: DMADataPathParam) extends Bundle { param.rwParam.aguParam ) // Buffered within AGU val readerwriterCfg = new ReaderWriterCfgIO(param.rwParam) + + def connectReaderWriterCfgWithList( + csrList: IndexedSeq[UInt] + ): IndexedSeq[UInt] = { + var remaincsrList = csrList + remaincsrList = aguCfg.connectWithList(remaincsrList) + remaincsrList = readerwriterCfg.connectWithList(remaincsrList) + remaincsrList + } + val extCfg = if (param.extParam.length != 0) { Vec( param.extParam.map { i => i.totalCsrNum }.reduce(_ + _) + 1, @@ -68,6 +78,15 @@ class DMADataPathCfgInternalIO(param: DMADataPathParam) val loopBack = Bool() val readerPtr = UInt(param.axiParam.addrWidth.W) val writerPtr = UInt(param.axiParam.addrWidth.W) + override def connectReaderWriterCfgWithList( + csrList: IndexedSeq[UInt] + ): IndexedSeq[UInt] = { + var remainingCSR = csrList + readerPtr := Cat(remainingCSR(1), remainingCSR(0)) + writerPtr := Cat(remainingCSR(1), remainingCSR(0)) + remainingCSR = super.connectReaderWriterCfgWithList(remainingCSR) + remainingCSR + } override def serialize(): UInt = { super.serialize() ++ writerPtr ++ readerPtr } diff --git a/hw/chisel/src/main/scala/snax/xdma/xdmaStreamer/AddressGenUnit.scala b/hw/chisel/src/main/scala/snax/xdma/xdmaStreamer/AddressGenUnit.scala index 53f82fc83..0d826e814 100644 --- a/hw/chisel/src/main/scala/snax/xdma/xdmaStreamer/AddressGenUnit.scala +++ b/hw/chisel/src/main/scala/snax/xdma/xdmaStreamer/AddressGenUnit.scala @@ -111,6 +111,29 @@ class AddressGenUnitCfgIO(param: AddressGenUnitParam) extends Bundle { Vec(param.spatialBounds.length, UInt(param.addressWidth.W)) val temporalStrides = Vec(param.temporalDimension, UInt(param.addressWidth.W)) val temporalBounds = Vec(param.temporalDimension, UInt(param.addressWidth.W)) + + def connectWithList(csrList: IndexedSeq[UInt]): IndexedSeq[UInt] = { + var remainingCSR = csrList + // Connect the ptr + ptr := Cat(remainingCSR(1), remainingCSR(0)) + remainingCSR = remainingCSR.drop(2) + // Connect the spatial strides + for (i <- 0 until spatialStrides.length) { + spatialStrides(i) := remainingCSR.head + remainingCSR = remainingCSR.tail + } + // Connect the temporal strides + for (i <- 0 until temporalStrides.length) { + temporalStrides(i) := remainingCSR.head + remainingCSR = remainingCSR.tail + } + // Connect the temporal bounds + for (i <- 0 until temporalBounds.length) { + temporalBounds(i) := remainingCSR.head + remainingCSR = remainingCSR.tail + } + remainingCSR + } } /** AGU is the module to automatically generate the address for all ports. diff --git a/hw/chisel/src/main/scala/snax/xdma/xdmaStreamer/Reader.scala b/hw/chisel/src/main/scala/snax/xdma/xdmaStreamer/Reader.scala index 11b464a7f..c8507ffa4 100644 --- a/hw/chisel/src/main/scala/snax/xdma/xdmaStreamer/Reader.scala +++ b/hw/chisel/src/main/scala/snax/xdma/xdmaStreamer/Reader.scala @@ -15,6 +15,11 @@ class Reader(param: ReaderWriterParam, clusterName: String = "unnamed_cluster") override val desiredName = s"${clusterName}_xdma_Reader" + require( + param.configurableByteMask == false, + "Byte Mask is not supported in Reader" + ) + val io = IO(new ReaderIO(param)) // New Address Generator diff --git a/hw/chisel/src/main/scala/snax/xdma/xdmaStreamer/ReaderWriterIO.scala b/hw/chisel/src/main/scala/snax/xdma/xdmaStreamer/ReaderWriterIO.scala index b102dbc70..909e3fc50 100644 --- a/hw/chisel/src/main/scala/snax/xdma/xdmaStreamer/ReaderWriterIO.scala +++ b/hw/chisel/src/main/scala/snax/xdma/xdmaStreamer/ReaderWriterIO.scala @@ -15,6 +15,23 @@ class ReaderWriterCfgIO(val param: ReaderWriterParam) extends Bundle { if (param.configurableChannel) UInt(param.tcdmParam.numChannel.W) else UInt(0.W) + + def connectWithList(csrList: IndexedSeq[UInt]): IndexedSeq[UInt] = { + var remaincsrList = csrList + if (param.configurableChannel) { + enabledChannel := remaincsrList.head + remaincsrList = remaincsrList.tail + } else { + enabledChannel := Fill(param.tcdmParam.numChannel, 1.U) + } + if (param.configurableByteMask) { + enabledByte := remaincsrList.head + remaincsrList = remaincsrList.tail + } else { + enabledByte := Fill(param.tcdmParam.dataWidth / 8, 1.U) + } + remaincsrList + } } abstract class ReaderWriterCommomIO(val param: ReaderWriterParam) @@ -24,6 +41,13 @@ abstract class ReaderWriterCommomIO(val param: ReaderWriterParam) // The signal to control which byte is written to TCDM val readerwriterCfg = Input(new ReaderWriterCfgIO(param)) + def connectCfgWithList(csrList: IndexedSeq[UInt]): IndexedSeq[UInt] = { + var remaincsrList = csrList + remaincsrList = aguCfg.connectWithList(remaincsrList) + remaincsrList = readerwriterCfg.connectWithList(remaincsrList) + remaincsrList + } + // The signal trigger the start of Address Generator. The non-empty of address generator will cause data requestor to read the data val start = Input(Bool()) // The module is busy if addressgen is busy or fifo in addressgen is not empty diff --git a/hw/chisel/src/main/scala/snax/xdma/xdmaTop/xdmaTop.scala b/hw/chisel/src/main/scala/snax/xdma/xdmaTop/xdmaTop.scala index bb373e3e7..19af636ce 100644 --- a/hw/chisel/src/main/scala/snax/xdma/xdmaTop/xdmaTop.scala +++ b/hw/chisel/src/main/scala/snax/xdma/xdmaTop/xdmaTop.scala @@ -169,7 +169,9 @@ object xdmaTopGen extends App { tcdmSize = parsedArgs("tcdmSize").toInt, numChannel = parsedArgs("axiDataWidth").toInt / parsedArgs("tcdmDataWidth").toInt, - addressBufferDepth = parsedArgs("readerBufferDepth").toInt + addressBufferDepth = parsedArgs("readerBufferDepth").toInt, + configurableChannel = true, + configurableByteMask = false ) val writerparam = new ReaderWriterParam( @@ -180,7 +182,9 @@ object xdmaTopGen extends App { tcdmSize = parsedArgs("tcdmSize").toInt, numChannel = parsedArgs("axiDataWidth").toInt / parsedArgs("tcdmDataWidth").toInt, - addressBufferDepth = parsedArgs("writerBufferDepth").toInt + addressBufferDepth = parsedArgs("writerBufferDepth").toInt, + configurableChannel = true, + configurableByteMask = true ) var readerextensionparam = Seq[HasDMAExtension]() var writerextensionparam = Seq[HasDMAExtension]() diff --git a/hw/chisel/src/test/scala/snax/xdma/xdmaFrontEnd/DMADataPathTester.scala b/hw/chisel/src/test/scala/snax/xdma/xdmaFrontEnd/DMADataPathTester.scala index 744bbbb4e..fd29a3933 100644 --- a/hw/chisel/src/test/scala/snax/xdma/xdmaFrontEnd/DMADataPathTester.scala +++ b/hw/chisel/src/test/scala/snax/xdma/xdmaFrontEnd/DMADataPathTester.scala @@ -28,11 +28,11 @@ class DMADataPathTester extends AnyFreeSpec with ChiselScalatestTester { new DMADataPath( readerparam = new DMADataPathParam( axiParam = new AXIParam, - rwParam = new ReaderWriterParam + rwParam = new ReaderWriterParam(configurableByteMask = false) ), writerparam = new DMADataPathParam( axiParam = new AXIParam, - rwParam = new ReaderWriterParam + rwParam = new ReaderWriterParam(configurableByteMask = true) ) ) ).withAnnotations(Seq(WriteVcdAnnotation, VerilatorBackendAnnotation)) { @@ -81,7 +81,6 @@ class DMADataPathTester extends AnyFreeSpec with ChiselScalatestTester { // Poke the reader agu dut.io.readerCfg.aguCfg.ptr.poke(readerTestingParams.address) dut.io.readerCfg.readerwriterCfg.enabledChannel.poke(0xff.U) - dut.io.readerCfg.readerwriterCfg.enabledByte.poke(0xff.U) dut.io.readerCfg.aguCfg .temporalBounds(0) .poke(readerTestingParams.temporal_bound(0)) diff --git a/hw/chisel/src/test/scala/snax/xdma/xdmaStreamer/ReaderTester.scala b/hw/chisel/src/test/scala/snax/xdma/xdmaStreamer/ReaderTester.scala index 7f3d4d498..547db9972 100644 --- a/hw/chisel/src/test/scala/snax/xdma/xdmaStreamer/ReaderTester.scala +++ b/hw/chisel/src/test/scala/snax/xdma/xdmaStreamer/ReaderTester.scala @@ -14,7 +14,7 @@ import snax.xdma.DesignParams._ class ReaderTester extends AnyFreeSpec with ChiselScalatestTester { "Reader's behavior is as expected" in test( - new Reader(new ReaderWriterParam) + new Reader(new ReaderWriterParam(configurableByteMask = false)) ).withAnnotations(Seq(WriteVcdAnnotation, VerilatorBackendAnnotation)) { dut => // The accessed address is 1KB (0x0 - 0x400) @@ -31,7 +31,6 @@ class ReaderTester extends AnyFreeSpec with ChiselScalatestTester { dut.io.aguCfg.temporalBounds(1).poke(16) dut.io.readerwriterCfg.enabledChannel.poke(0xff.U) - dut.io.readerwriterCfg.enabledByte.poke(0xff.U) dut.io.start.poke(true) dut.clock.step() diff --git a/hw/chisel/src/test/scala/snax/xdma/xdmaTop/xdmaTopTester.scala b/hw/chisel/src/test/scala/snax/xdma/xdmaTop/xdmaTopTester.scala index a2f4ba80d..9bcb9598e 100644 --- a/hw/chisel/src/test/scala/snax/xdma/xdmaTop/xdmaTopTester.scala +++ b/hw/chisel/src/test/scala/snax/xdma/xdmaTop/xdmaTopTester.scala @@ -107,11 +107,11 @@ class xDMATopTester extends AnyFreeSpec with ChiselScalatestTester { new xdmaTop( readerParam = new DMADataPathParam( axiParam = new AXIParam, - rwParam = new ReaderWriterParam + rwParam = new ReaderWriterParam(configurableByteMask = false) ), writerParam = new DMADataPathParam( axiParam = new AXIParam, - rwParam = new ReaderWriterParam, + rwParam = new ReaderWriterParam(configurableByteMask = true), extParam = Seq(HasVerilogMemset, HasMaxPool, HasTransposer) ) ) @@ -129,13 +129,13 @@ class xDMATopTester extends AnyFreeSpec with ChiselScalatestTester { address = 0, spatialStrides = Array(8), temporalStrides = Array(8, 0), - temporalBounds = Array(2048, 1), + temporalBounds = Array(2048, 1) ) var writerAGUParam = new AGUParamTest( address = 16 * 1024, spatialStrides = Array(8), temporalStrides = Array(8, 0), - temporalBounds = Array(2048, 1), + temporalBounds = Array(2048, 1) ) var readerRWParam = new RWParamTest( @@ -337,13 +337,13 @@ class xDMATopTester extends AnyFreeSpec with ChiselScalatestTester { address = 0, spatialStrides = Array(8), temporalStrides = Array(64, 0), - temporalBounds = Array(256, 1), + temporalBounds = Array(256, 1) ) writerAGUParam = new AGUParamTest( address = 16 * 1024, spatialStrides = Array(8), temporalStrides = Array(64, 0), - temporalBounds = Array(256, 1), + temporalBounds = Array(256, 1) ) readerRWParam = new RWParamTest( @@ -529,7 +529,6 @@ class xDMATopTester extends AnyFreeSpec with ChiselScalatestTester { ) != 2 ) {} - // Check whether the data in memory is coincide with the expectation mem_to_be_checked = tcdm_mem.filter(_._1 >= 1024 * 16) if (mem_to_be_checked.map(_._2 == 0).reduce(_ & _)) @@ -542,13 +541,13 @@ class xDMATopTester extends AnyFreeSpec with ChiselScalatestTester { address = 0, spatialStrides = Array(8), temporalStrides = Array(64, 0), - temporalBounds = Array(256, 1), + temporalBounds = Array(256, 1) ) writerAGUParam = new AGUParamTest( address = 16 * 1024, spatialStrides = Array(8), temporalStrides = Array(64, 0), - temporalBounds = Array(256, 1), + temporalBounds = Array(256, 1) ) readerRWParam = new RWParamTest( @@ -559,7 +558,7 @@ class xDMATopTester extends AnyFreeSpec with ChiselScalatestTester { enabledChannel = Integer.parseInt("11111111", 2), enabledByte = Integer.parseInt("00000001", 2) ) - + writerExtParam = new ExtParam( bypassMemset = 0, MemsetValue = 0xff, @@ -781,13 +780,13 @@ class xDMATopTester extends AnyFreeSpec with ChiselScalatestTester { address = 0, spatialStrides = Array(8), temporalStrides = Array(64, 0), - temporalBounds = Array(256, 1), + temporalBounds = Array(256, 1) ) writerAGUParam = new AGUParamTest( address = 16 * 1024, spatialStrides = Array(8), temporalStrides = Array(64, 0), - temporalBounds = Array(256, 1), + temporalBounds = Array(256, 1) ) readerRWParam = new RWParamTest(