diff --git a/src/main/scala/uncore/apb/Test.scala b/src/main/scala/uncore/apb/Test.scala index 2163b5cb..960fd73d 100644 --- a/src/main/scala/uncore/apb/Test.scala +++ b/src/main/scala/uncore/apb/Test.scala @@ -25,7 +25,7 @@ class APBFuzzBridge()(implicit p: Parameters) extends LazyModule val gpio = LazyModule(new RRTest0(0x100)) model.node := fuzz.node -// xbar.node := TLToAPB()(model.node) + xbar.node := TLToAPB()(model.node) ram.node := xbar.node gpio.node := xbar.node diff --git a/src/main/scala/uncore/tilelink2/ToAPB.scala b/src/main/scala/uncore/tilelink2/ToAPB.scala new file mode 100644 index 00000000..218892f6 --- /dev/null +++ b/src/main/scala/uncore/tilelink2/ToAPB.scala @@ -0,0 +1,101 @@ +// See LICENSE.SiFive for license details. + +package uncore.tilelink2 + +import Chisel._ +import chisel3.internal.sourceinfo.SourceInfo +import config._ +import diplomacy._ +import uncore.apb._ +import scala.math.{min, max} +import APBParameters._ + +case class TLToAPBNode() extends MixedNode(TLImp, APBImp)( + dFn = { case (1, Seq(TLClientPortParameters(clients, unsafeAtomics, minLatency))) => + val masters = clients.map { case c => APBMasterParameters(nodePath = c.nodePath) } + Seq(APBMasterPortParameters(masters)) + }, + uFn = { case (1, Seq(APBSlavePortParameters(slaves, beatBytes))) => + val managers = slaves.map { case s => + TLManagerParameters( + address = s.address, + regionType = s.regionType, + executable = s.executable, + nodePath = s.nodePath, + supportsGet = if (s.supportsRead) TransferSizes(1, beatBytes) else TransferSizes.none, + supportsPutPartial = if (s.supportsWrite) TransferSizes(1, beatBytes) else TransferSizes.none, + supportsPutFull = if (s.supportsWrite) TransferSizes(1, beatBytes) else TransferSizes.none, + fifoId = Some(0)) // a common FIFO domain + } + Seq(TLManagerPortParameters(managers, beatBytes, 1, 0)) + }, + numPO = 1 to 1, + numPI = 1 to 1) + +class TLToAPB(combinational: Boolean = true)(implicit p: Parameters) extends LazyModule +{ + val node = TLToAPBNode() + + lazy val module = new LazyModuleImp(this) { + val io = new Bundle { + val in = node.bundleIn + val out = node.bundleOut + } + + val in = io.in(0) + val out = io.out(0) + val edgeIn = node.edgesIn(0) + val edgeOut = node.edgesOut(0) + val beatBytes = edgeOut.slave.beatBytes + val lgBytes = log2Ceil(beatBytes) + + // APB has no cache coherence + in.b.valid := Bool(false) + in.c.ready := Bool(true) + in.e.ready := Bool(true) + + // We need a skidpad to capture D output: + // We cannot know if the D response will be accepted until we have + // presented it on D as valid. We also can't back-pressure APB in the + // data phase. Therefore, we must have enough space to save the data + // phase result. Whenever we have a queued response, we can not allow + // APB to present new responses, so we must quash the address phase. + val d = Wire(in.d) + in.d <> Queue(d, 1, flow = true) + + // We need an irrevocable input for APB to stall + val a = Queue(in.a, 1, flow = combinational, pipe = !combinational) + + val a_enable = RegInit(Bool(false)) + val a_sel = a.valid && RegNext(!in.d.valid || in.d.ready) + val a_write = edgeIn.hasData(a.bits) + + when (a_sel) { a_enable := Bool(true) } + when (d.fire()) { a_enable := Bool(false) } + + out.psel := a_sel + out.penable := a_enable + out.pwrite := a_write + out.paddr := a.bits.address + out.pprot := PROT_DEFAULT + out.pwdata := a.bits.data + out.pstrb := Mux(a_write, a.bits.mask, UInt(0)) + + a.ready := a_enable && out.pready + d.valid := a_enable && out.pready + assert (!d.valid || d.ready) + + d.bits := edgeIn.AccessAck(a.bits, UInt(0), out.prdata, out.pslverr) + d.bits.opcode := Mux(a_write, TLMessages.AccessAck, TLMessages.AccessAckData) + } +} + +object TLToAPB +{ + // applied to the TL source node; y.node := TLToAPB()(x.node) + def apply(combinational: Boolean = true)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): APBOutwardNode = { + val apb = LazyModule(new TLToAPB(combinational)) + apb.node := x + apb.node + } +} diff --git a/src/main/scala/unittest/Configs.scala b/src/main/scala/unittest/Configs.scala index ab714be3..62efd91a 100644 --- a/src/main/scala/unittest/Configs.scala +++ b/src/main/scala/unittest/Configs.scala @@ -33,6 +33,7 @@ class WithUncoreUnitTests extends Config( Module(new uncore.converters.TileLinkWidthAdapterTest()), Module(new uncore.tilelink2.TLFuzzRAMTest), Module(new uncore.ahb.AHBBridgeTest), + Module(new uncore.apb.APBBridgeTest), Module(new uncore.axi4.AXI4LiteFuzzRAMTest), Module(new uncore.axi4.AXI4FullFuzzRAMTest), Module(new uncore.axi4.AXI4BridgeTest)) }