Add BarrierSynchronizer module
This commit is contained in:
98
src/main/scala/radiance/tile/Barrier.scala
Normal file
98
src/main/scala/radiance/tile/Barrier.scala
Normal file
@@ -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
|
||||||
|
}
|
||||||
@@ -7,10 +7,10 @@ import chisel3._
|
|||||||
import chisel3.experimental.SourceInfo
|
import chisel3.experimental.SourceInfo
|
||||||
import chisel3.util._
|
import chisel3.util._
|
||||||
|
|
||||||
import org.chipsalliance.cde.config.{Field, Parameters}
|
import org.chipsalliance.cde.config.Parameters
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy.{LazyModule, AddressSet, SimpleDevice, ClockCrossingType}
|
||||||
import freechips.rocketchip.regmapper.RegField
|
import freechips.rocketchip.regmapper.RegField
|
||||||
import freechips.rocketchip.prci.ClockSinkParameters
|
import freechips.rocketchip.prci.ClockSinkParameters
|
||||||
|
|
||||||
@@ -98,20 +98,28 @@ class RadianceClusterModuleImp(outer: RadianceCluster) extends ClusterModuleImp(
|
|||||||
println(s"======= RadianceCluster: clbus name = ${outer.clbus.busName}")
|
println(s"======= RadianceCluster: clbus name = ${outer.clbus.busName}")
|
||||||
}
|
}
|
||||||
|
|
||||||
outer.barrierSlaveNode.in.foreach { case (b, e) =>
|
val numBarriers = 4 // FIXME: hardcoded
|
||||||
b.req.ready := true.B // barrier module is always ready
|
|
||||||
b.resp.valid := 0.U
|
// @cleanup: This assumes barrier params on all edges are the same, i.e. all
|
||||||
b.resp.bits.barrierId := 0.U
|
// 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, _) =>
|
// outer.barrierSlaveNode.in.foreach { case (b, e) =>
|
||||||
println(s"======= RadianceCluster.elements.name: ${name}")
|
// 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 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) =>
|
(allSyncedRegs zip perCoreSyncedRegs).foreach{ case (all, per) =>
|
||||||
all := per.reduce((x0, x1) => (x0 =/= 0.U) && (x1 =/= 0.U))
|
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}")
|
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()))
|
|
||||||
|
|||||||
@@ -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.barrierId := core.io.gbar_req_id
|
||||||
outer.barrierMasterNode.out(0)._1.req.bits.coreId := core.io.gbar_req_core_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_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_valid := outer.barrierMasterNode.out(0)._1.resp.valid
|
||||||
core.io.gbar_rsp_id := outer.barrierMasterNode.out(0)._1.resp.bits.barrierId
|
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]],
|
def performanceCounters(reqBundles: Seq[DecoupledIO[VortexBundleA]],
|
||||||
|
|||||||
@@ -90,16 +90,15 @@ class VortexBundle(tile: RadianceTile)(implicit p: Parameters) extends CoreBundl
|
|||||||
val smem_d_ready = Output(UInt((tile.numLsuLanes * 1).W))
|
val smem_d_ready = Output(UInt((tile.numLsuLanes * 1).W))
|
||||||
|
|
||||||
// FIXME: hardcoded
|
// FIXME: hardcoded
|
||||||
val numCoresPerCluster = 2
|
|
||||||
val NB_WIDTH = 2
|
val NB_WIDTH = 2
|
||||||
val NC_WIDTH = 1
|
val NC_WIDTH = 1
|
||||||
val gbar_req_valid = Output(UInt((numCoresPerCluster * 1).W))
|
val gbar_req_valid = Output(Bool())
|
||||||
val gbar_req_id = Output(UInt((numCoresPerCluster * NB_WIDTH).W))
|
val gbar_req_id = Output(UInt(NB_WIDTH.W))
|
||||||
val gbar_req_size_m1 = Output(UInt((numCoresPerCluster * NC_WIDTH).W))
|
val gbar_req_size_m1 = Output(UInt(NC_WIDTH.W))
|
||||||
val gbar_req_core_id = Output(UInt((numCoresPerCluster * NC_WIDTH).W))
|
val gbar_req_core_id = Output(UInt(NC_WIDTH.W))
|
||||||
val gbar_req_ready = Input(UInt((numCoresPerCluster * 1).W))
|
val gbar_req_ready = Input(Bool())
|
||||||
val gbar_rsp_valid = Input(UInt((numCoresPerCluster * 1).W))
|
val gbar_rsp_valid = Input(Bool())
|
||||||
val gbar_rsp_id = Input(UInt((numCoresPerCluster * NB_WIDTH).W))
|
val gbar_rsp_id = Input(UInt(NB_WIDTH.W))
|
||||||
|
|
||||||
// val fpu = Flipped(new FPUCoreIO())
|
// val fpu = Flipped(new FPUCoreIO())
|
||||||
//val rocc = Flipped(new RoCCCoreIO(nTotalRoCCCSRs))
|
//val rocc = Flipped(new RoCCCoreIO(nTotalRoCCCSRs))
|
||||||
|
|||||||
Reference in New Issue
Block a user