apb: add a TileLink to APB bridge and unittest it
This commit is contained in:
parent
ed091f55e6
commit
16febe7e94
@ -25,7 +25,7 @@ class APBFuzzBridge()(implicit p: Parameters) extends LazyModule
|
|||||||
val gpio = LazyModule(new RRTest0(0x100))
|
val gpio = LazyModule(new RRTest0(0x100))
|
||||||
|
|
||||||
model.node := fuzz.node
|
model.node := fuzz.node
|
||||||
// xbar.node := TLToAPB()(model.node)
|
xbar.node := TLToAPB()(model.node)
|
||||||
ram.node := xbar.node
|
ram.node := xbar.node
|
||||||
gpio.node := xbar.node
|
gpio.node := xbar.node
|
||||||
|
|
||||||
|
101
src/main/scala/uncore/tilelink2/ToAPB.scala
Normal file
101
src/main/scala/uncore/tilelink2/ToAPB.scala
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -33,6 +33,7 @@ class WithUncoreUnitTests extends Config(
|
|||||||
Module(new uncore.converters.TileLinkWidthAdapterTest()),
|
Module(new uncore.converters.TileLinkWidthAdapterTest()),
|
||||||
Module(new uncore.tilelink2.TLFuzzRAMTest),
|
Module(new uncore.tilelink2.TLFuzzRAMTest),
|
||||||
Module(new uncore.ahb.AHBBridgeTest),
|
Module(new uncore.ahb.AHBBridgeTest),
|
||||||
|
Module(new uncore.apb.APBBridgeTest),
|
||||||
Module(new uncore.axi4.AXI4LiteFuzzRAMTest),
|
Module(new uncore.axi4.AXI4LiteFuzzRAMTest),
|
||||||
Module(new uncore.axi4.AXI4FullFuzzRAMTest),
|
Module(new uncore.axi4.AXI4FullFuzzRAMTest),
|
||||||
Module(new uncore.axi4.AXI4BridgeTest)) }
|
Module(new uncore.axi4.AXI4BridgeTest)) }
|
||||||
|
Loading…
Reference in New Issue
Block a user