diff --git a/src/main/scala/tlserdes/Configs.scala b/src/main/scala/tlserdes/Configs.scala new file mode 100644 index 00000000..0bea9967 --- /dev/null +++ b/src/main/scala/tlserdes/Configs.scala @@ -0,0 +1,16 @@ +package tlserdes + +import freechips.rocketchip.config.{Parameters, Config} +import testchipip.WithSerialAdapter + +class WithTLSerdes extends Config((site, here, up) => { + case TLSerdesWidth => 16 +}) + +class DefaultSerdesConfig extends Config( + new WithTLSerdes ++ + new WithSerialAdapter ++ + new freechips.rocketchip.chip.DefaultConfig) + +class WithTwoMemChannels extends example.WithTwoMemChannels +class WithFourMemChannels extends example.WithFourMemChannels diff --git a/src/main/scala/tlserdes/Periphery.scala b/src/main/scala/tlserdes/Periphery.scala new file mode 100644 index 00000000..f37168ee --- /dev/null +++ b/src/main/scala/tlserdes/Periphery.scala @@ -0,0 +1,95 @@ +package tlserdes + +import chisel3._ +import chisel3.util._ +import freechips.rocketchip.config.{Parameters, Field} +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.chip.{ExtMem, HasSystemNetworks} +import freechips.rocketchip.coreplex.{BankedL2Config, CacheBlockBytes} +import freechips.rocketchip.tilelink._ +import testchipip._ + +case object TLSerdesWidth extends Field[Int] + +class TLSerdesMem(implicit p: Parameters) extends LazyModule { + val config = p(ExtMem) + val channels = p(BankedL2Config).nMemoryChannels + val serdesWidth = p(TLSerdesWidth) + val blockBytes = p(CacheBlockBytes) + + val desser = LazyModule(new TLDesser(serdesWidth, + Seq.tabulate(channels) { ch => + TLClientParameters( + name = s"tl-desser$ch", sourceId = IdRange(0, 1 << config.idBits)) + })) + + for (ch <- 0 until channels) { + val base = AddressSet(config.base, config.size-1) + val filter = AddressSet(ch * blockBytes, ~((channels-1) * blockBytes)) + + val mem = LazyModule(new TLRAM( + address = base.intersect(filter).get, + executable = true, + beatBytes = config.beatBytes)) + + mem.node := TLBuffer()( + TLFragmenter(config.beatBytes, blockBytes)(desser.node)) + } + + lazy val module = new LazyModuleImp(this) { + val io = IO(new Bundle { + val ser = Vec(channels, new SerialIO(serdesWidth)) + }) + + desser.module.io.ser <> io.ser + } +} + +trait HasPeripheryTLSerdesMemPort extends HasSystemNetworks { + private val config = p(ExtMem) + private val channels = p(BankedL2Config).nMemoryChannels + private val serdesWidth = p(TLSerdesWidth) + private val blockBytes = p(CacheBlockBytes) + private val device = new MemoryDevice + + val serdes = LazyModule(new TLSerdes( + w = serdesWidth, + params = Seq.tabulate(channels) { ch => + val base = AddressSet(config.base, config.size-1) + val filter = AddressSet(ch * blockBytes, ~((channels-1) * blockBytes)) + + TLManagerParameters( + address = base.intersect(filter).toSeq, + resources = device.reg, + regionType = RegionType.UNCACHED, + executable = true, + supportsGet = TransferSizes(1, blockBytes), + supportsPutFull = TransferSizes(1, blockBytes), + supportsPutPartial = TransferSizes(1, blockBytes), + fifoId = Some(0)) + }, + beatBytes = config.beatBytes)) + + mem.foreach { xbar => + serdes.node := + TLBuffer()( + TLAtomicAutomata()( + TLSourceShrinker(1 << config.idBits)(xbar.node))) + } +} + +trait HasPeripheryTLSerdesMemPortModuleImp extends LazyMultiIOModuleImp { + private val serdesWidth = p(TLSerdesWidth) + private val config = p(ExtMem) + private val channels = p(BankedL2Config).nMemoryChannels + + val outer: HasPeripheryTLSerdesMemPort + val tlser = IO(Vec(channels, new SerialIO(serdesWidth))) + + tlser <> outer.serdes.module.io.ser + + def connectSerdesMem(dummy: Int = 0) { + val memser = Module(LazyModule(new TLSerdesMem).module).io.ser + memser.zip(tlser).foreach { case (mem, tl) => mem.connect(tl) } + } +} diff --git a/src/main/scala/tlserdes/TestHarness.scala b/src/main/scala/tlserdes/TestHarness.scala new file mode 100644 index 00000000..4aaca709 --- /dev/null +++ b/src/main/scala/tlserdes/TestHarness.scala @@ -0,0 +1,20 @@ +package tlserdes + +import chisel3._ +import freechips.rocketchip.diplomacy.LazyModule +import freechips.rocketchip.config.{Field, Parameters} +import testchipip.GeneratorApp + +class TestHarness(implicit val p: Parameters) extends Module { + val io = IO(new Bundle { + val success = Output(Bool()) + }) + + val dut = Module(LazyModule(new SerdesTop).module) + dut.connectSerdesMem() + io.success := dut.connectSimSerial() +} + +object Generator extends GeneratorApp { + generateFirrtl +} diff --git a/src/main/scala/tlserdes/Top.scala b/src/main/scala/tlserdes/Top.scala new file mode 100644 index 00000000..113f4348 --- /dev/null +++ b/src/main/scala/tlserdes/Top.scala @@ -0,0 +1,27 @@ +package tlserdes + +import chisel3._ +import chisel3.util._ +import freechips.rocketchip.chip._ +import freechips.rocketchip.config.Parameters +import testchipip._ + +class SerdesTop(implicit p: Parameters) extends BaseSystem + with HasPeripheryTLSerdesMemPort + with HasPeripheryErrorSlave + with HasPeripheryZeroSlave + with HasPeripheryBootROM + with HasPeripheryRTCCounter + with HasRocketPlexMaster + with HasNoDebug + with HasPeripherySerial { + override lazy val module = new SerdesTopModule(this) +} + +class SerdesTopModule(outer: SerdesTop) extends BaseSystemModule(outer) + with HasPeripheryTLSerdesMemPortModuleImp + with HasPeripheryBootROMModuleImp + with HasPeripheryRTCCounterModuleImp + with HasRocketPlexMasterModuleImp + with HasNoDebugModuleImp + with HasPeripherySerialModuleImp