diff --git a/src/main/scala/radiance/tile/Barrier.scala b/src/main/scala/radiance/tile/Barrier.scala new file mode 100644 index 0000000..e3e965b --- /dev/null +++ b/src/main/scala/radiance/tile/Barrier.scala @@ -0,0 +1,98 @@ +// See LICENSE.SiFive for license details. +// See LICENSE.Berkeley for license details. + +package radiance.tile + +import chisel3._ +import chisel3.experimental.SourceInfo +import chisel3.util._ + +import org.chipsalliance.cde.config.{Field, Parameters} +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.diplomacy._ + +case class EmptyParams() + +case class BarrierParams( + barrierIdBits: Int, + numCoreBits: Int +) + +class BarrierRequestBits( + param: BarrierParams +) extends Bundle { + val barrierId = UInt(param.barrierIdBits.W) + val sizeMinusOne = UInt(param.numCoreBits.W) + val coreId = UInt(param.numCoreBits.W) +} + +class BarrierResponseBits( + param: BarrierParams +) extends Bundle { + val barrierId = UInt(param.barrierIdBits.W) +} + +class BarrierBundle(param: BarrierParams) extends Bundle { + val req = Decoupled(new BarrierRequestBits(param)) + val resp = Flipped(Decoupled(new BarrierResponseBits(param))) +} + +// FIXME Separate BarrierEdgeParams from BarrierParams +object BarrierNodeImp extends SimpleNodeImp[BarrierParams, EmptyParams, BarrierParams, BarrierBundle] { + def edge(pd: BarrierParams, pu: EmptyParams, p: Parameters, sourceInfo: SourceInfo) = { + // barrier parameters flow strictly downward from the master node + pd + } + def bundle(e: BarrierParams) = new BarrierBundle(e) + // FIXME render + def render(e: BarrierParams) = RenderedEdge(colour = "ffffff", label = "X") +} + +case class BarrierMasterNode(val srcParams: BarrierParams)(implicit valName: ValName) + extends SourceNode(BarrierNodeImp)(Seq(srcParams)) +case class BarrierSlaveNode(val numEdges: Int)(implicit valName: ValName) + extends SinkNode(BarrierNodeImp)(Seq.fill(numEdges)(EmptyParams())) + +class BarrierSynchronizer(param: BarrierParams) extends Module { + val numBarrierIds = 1 << param.barrierIdBits + val numCores = 1 << param.numCoreBits + println(s"numBarrierIds: ${numBarrierIds}, numCores: ${numCores}") + + val io = IO(new Bundle { + val reqs = Vec(numCores, Flipped(Decoupled(new BarrierRequestBits(param)))) + val resp = Decoupled(new BarrierResponseBits(param)) + }) + + // 2-dimensional table of per-id, per-core "done" signals + val table = RegInit(VecInit(Seq.fill(numBarrierIds)(VecInit(Seq.fill(numCores)(false.B))))) + val done = Wire(Vec(numBarrierIds, Bool())) + table.zipWithIndex.foreach { case (row, i) => + done(i) := row.reduce(_ && _) + } + dontTouch(done) + + io.reqs.zipWithIndex.foreach { case (req, coreId) => + // always ready; all this module does is latch to boolean regs + req.ready := true.B + when(req.fire) { + assert(coreId.U === req.bits.coreId) + // FIXME: don't need coreId to be hardware here + table(req.bits.barrierId)(coreId.U) := true.B + } + } + + val doneArbiter = Module(new RRArbiter(Bool(), numBarrierIds)) + (doneArbiter.io.in zip done).zipWithIndex.foreach { case ((in, d), i) => + in.valid := d + in.bits := d + when(in.fire) { + table(i).foreach(_ := false.B) + } + } + io.resp.valid := doneArbiter.io.out.valid + io.resp.bits.barrierId := doneArbiter.io.chosen + when(io.resp.fire) { + table(io.resp.bits.barrierId).foreach(_ := false.B) + } + doneArbiter.io.out.ready := io.resp.ready +} diff --git a/src/main/scala/radiance/tile/RadianceCluster.scala b/src/main/scala/radiance/tile/RadianceCluster.scala index 2d67a24..7d6752c 100644 --- a/src/main/scala/radiance/tile/RadianceCluster.scala +++ b/src/main/scala/radiance/tile/RadianceCluster.scala @@ -7,10 +7,10 @@ import chisel3._ import chisel3.experimental.SourceInfo import chisel3.util._ -import org.chipsalliance.cde.config.{Field, Parameters} +import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.subsystem._ import freechips.rocketchip.tilelink._ -import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.diplomacy.{LazyModule, AddressSet, SimpleDevice, ClockCrossingType} import freechips.rocketchip.regmapper.RegField import freechips.rocketchip.prci.ClockSinkParameters @@ -98,20 +98,28 @@ class RadianceClusterModuleImp(outer: RadianceCluster) extends ClusterModuleImp( println(s"======= RadianceCluster: clbus name = ${outer.clbus.busName}") } - outer.barrierSlaveNode.in.foreach { case (b, e) => - b.req.ready := true.B // barrier module is always ready - b.resp.valid := 0.U - b.resp.bits.barrierId := 0.U + val numBarriers = 4 // FIXME: hardcoded + + // @cleanup: This assumes barrier params on all edges are the same, i.e. all + // cores are configured to have the same barrier id range. While true, might + // be better to actually assert this + val barrierParam = outer.barrierSlaveNode.in(0)._2 + val synchronizer = Module(new BarrierSynchronizer(barrierParam)) + (synchronizer.io.reqs zip outer.barrierSlaveNode.in).foreach { case (req, (b, _)) => + req <> b.req + b.resp <> synchronizer.io.resp // broadcast } - auto.elements.foreach({case (name, _) => - println(s"======= RadianceCluster.elements.name: ${name}") - }) + // outer.barrierSlaveNode.in.foreach { case (b, e) => + // val fakeBarrierRespId = RegNext(b.req.bits.barrierId) + // val fakeBarrierRespValid = RegNext(b.req.fire) + // b.req.ready := true.B // barrier module is always ready + // b.resp.valid := fakeBarrierRespValid + // b.resp.bits.barrierId := fakeBarrierRespId + // } - val numCores = outer.leafTiles.size - val numBarriers = 4 // FIXME: hardcoded val allSyncedRegs = Seq.fill(numBarriers)(Wire(UInt(32.W))) - val perCoreSyncedRegs = Seq.fill(numBarriers)(Seq.fill(numCores)(RegInit(0.U(32.W)))) + val perCoreSyncedRegs = Seq.fill(numBarriers)(Seq.fill(outer.numCores)(RegInit(0.U(32.W)))) (allSyncedRegs zip perCoreSyncedRegs).foreach{ case (all, per) => all := per.reduce((x0, x1) => (x0 =/= 0.U) && (x1 =/= 0.U)) @@ -140,45 +148,3 @@ class RadianceClusterModuleImp(outer: RadianceCluster) extends ClusterModuleImp( println(s"======== barrierSlaveNode: ${outer.barrierSlaveNode.in(0)._2.barrierIdBits}") } - -case class EmptyParams() - -case class BarrierParams( - barrierIdBits: Int, - numCoreBits: Int -) - -class BarrierRequestBits( - param: BarrierParams -) extends Bundle { - val barrierId = UInt(param.barrierIdBits.W) - val sizeMinusOne = UInt(param.numCoreBits.W) - val coreId = UInt(param.numCoreBits.W) -} - -class BarrierResponseBits( - param: BarrierParams -) extends Bundle { - val barrierId = UInt(param.barrierIdBits.W) -} - -class BarrierBundle(param: BarrierParams) extends Bundle { - val req = Decoupled(new BarrierRequestBits(param)) - val resp = Flipped(Decoupled(new BarrierResponseBits(param))) -} - -// FIXME Separate BarrierEdgeParams from BarrierParams -object BarrierNodeImp extends SimpleNodeImp[BarrierParams, EmptyParams, BarrierParams, BarrierBundle] { - def edge(pd: BarrierParams, pu: EmptyParams, p: Parameters, sourceInfo: SourceInfo) = { - // barrier parameters flow strictly downward from the master node - pd - } - def bundle(e: BarrierParams) = new BarrierBundle(e) - // FIXME render - def render(e: BarrierParams) = RenderedEdge(colour = "ffffff", label = "X") -} - -case class BarrierMasterNode(val srcParams: BarrierParams)(implicit valName: ValName) - extends SourceNode(BarrierNodeImp)(Seq(srcParams)) -case class BarrierSlaveNode(val numEdges: Int)(implicit valName: ValName) - extends SinkNode(BarrierNodeImp)(Seq.fill(numEdges)(EmptyParams())) diff --git a/src/main/scala/radiance/tile/RadianceTile.scala b/src/main/scala/radiance/tile/RadianceTile.scala index c9fe609..bf4dfa3 100644 --- a/src/main/scala/radiance/tile/RadianceTile.scala +++ b/src/main/scala/radiance/tile/RadianceTile.scala @@ -701,8 +701,11 @@ class RadianceTileModuleImp(outer: RadianceTile) outer.barrierMasterNode.out(0)._1.req.bits.barrierId := core.io.gbar_req_id outer.barrierMasterNode.out(0)._1.req.bits.coreId := core.io.gbar_req_core_id core.io.gbar_req_ready := outer.barrierMasterNode.out(0)._1.req.ready + core.io.gbar_rsp_valid := outer.barrierMasterNode.out(0)._1.resp.valid core.io.gbar_rsp_id := outer.barrierMasterNode.out(0)._1.resp.bits.barrierId + // core doesn't have a resp.ready port + outer.barrierMasterNode.out(0)._1.resp.ready := true.B } def performanceCounters(reqBundles: Seq[DecoupledIO[VortexBundleA]], diff --git a/src/main/scala/radiance/tile/VortexCore.scala b/src/main/scala/radiance/tile/VortexCore.scala index 7a37c24..7a06f7d 100644 --- a/src/main/scala/radiance/tile/VortexCore.scala +++ b/src/main/scala/radiance/tile/VortexCore.scala @@ -90,16 +90,15 @@ class VortexBundle(tile: RadianceTile)(implicit p: Parameters) extends CoreBundl val smem_d_ready = Output(UInt((tile.numLsuLanes * 1).W)) // FIXME: hardcoded - val numCoresPerCluster = 2 val NB_WIDTH = 2 val NC_WIDTH = 1 - val gbar_req_valid = Output(UInt((numCoresPerCluster * 1).W)) - val gbar_req_id = Output(UInt((numCoresPerCluster * NB_WIDTH).W)) - val gbar_req_size_m1 = Output(UInt((numCoresPerCluster * NC_WIDTH).W)) - val gbar_req_core_id = Output(UInt((numCoresPerCluster * NC_WIDTH).W)) - val gbar_req_ready = Input(UInt((numCoresPerCluster * 1).W)) - val gbar_rsp_valid = Input(UInt((numCoresPerCluster * 1).W)) - val gbar_rsp_id = Input(UInt((numCoresPerCluster * NB_WIDTH).W)) + val gbar_req_valid = Output(Bool()) + val gbar_req_id = Output(UInt(NB_WIDTH.W)) + val gbar_req_size_m1 = Output(UInt(NC_WIDTH.W)) + val gbar_req_core_id = Output(UInt(NC_WIDTH.W)) + val gbar_req_ready = Input(Bool()) + val gbar_rsp_valid = Input(Bool()) + val gbar_rsp_id = Input(UInt(NB_WIDTH.W)) // val fpu = Flipped(new FPUCoreIO()) //val rocc = Flipped(new RoCCCoreIO(nTotalRoCCCSRs))