This commit is contained in:
Hansung Kim
2023-11-10 14:46:33 -08:00
parent 17a39a369f
commit d51ce4cfa8

View File

@@ -47,49 +47,50 @@ case class VortexTileParams(
// field, so VortexCoreParams needs to extend from that, requiring all // field, so VortexCoreParams needs to extend from that, requiring all
// these fields to be initialized. Most of this is unnecessary though. TODO // these fields to be initialized. Most of this is unnecessary though. TODO
case class VortexCoreParams( case class VortexCoreParams(
bootFreqHz: BigInt = 0, bootFreqHz: BigInt = 0,
useVM: Boolean = true, useVM: Boolean = true,
useUser: Boolean = false, useUser: Boolean = false,
useSupervisor: Boolean = false, useSupervisor: Boolean = false,
useHypervisor: Boolean = false, useHypervisor: Boolean = false,
useDebug: Boolean = true, useDebug: Boolean = true,
useAtomics: Boolean = false, useAtomics: Boolean = false,
useAtomicsOnlyForIO: Boolean = false, useAtomicsOnlyForIO: Boolean = false,
useCompressed: Boolean = false, useCompressed: Boolean = false,
useRVE: Boolean = false, useRVE: Boolean = false,
useSCIE: Boolean = false, useSCIE: Boolean = false,
useBitManip: Boolean = false, useBitManip: Boolean = false,
useBitManipCrypto: Boolean = false, useBitManipCrypto: Boolean = false,
useCryptoNIST: Boolean = false, useCryptoNIST: Boolean = false,
useCryptoSM: Boolean = false, useCryptoSM: Boolean = false,
useConditionalZero: Boolean = false, useConditionalZero: Boolean = false,
nLocalInterrupts: Int = 0, nLocalInterrupts: Int = 0,
useNMI: Boolean = false, useNMI: Boolean = false,
nBreakpoints: Int = 1, nBreakpoints: Int = 1,
useBPWatch: Boolean = false, useBPWatch: Boolean = false,
mcontextWidth: Int = 0, mcontextWidth: Int = 0,
scontextWidth: Int = 0, scontextWidth: Int = 0,
nPMPs: Int = 8, nPMPs: Int = 8,
nPerfCounters: Int = 0, nPerfCounters: Int = 0,
haveBasicCounters: Boolean = true, haveBasicCounters: Boolean = true,
haveCFlush: Boolean = false, haveCFlush: Boolean = false,
misaWritable: Boolean = true, misaWritable: Boolean = true,
nL2TLBEntries: Int = 0, nL2TLBEntries: Int = 0,
nL2TLBWays: Int = 1, nL2TLBWays: Int = 1,
nPTECacheEntries: Int = 8, nPTECacheEntries: Int = 8,
mtvecInit: Option[BigInt] = Some(BigInt(0)), mtvecInit: Option[BigInt] = Some(BigInt(0)),
mtvecWritable: Boolean = true, mtvecWritable: Boolean = true,
fastLoadWord: Boolean = true, fastLoadWord: Boolean = true,
fastLoadByte: Boolean = false, fastLoadByte: Boolean = false,
branchPredictionModeCSR: Boolean = false, branchPredictionModeCSR: Boolean = false,
clockGate: Boolean = false, clockGate: Boolean = false,
mvendorid: Int = 0, // 0 means non-commercial implementation mvendorid: Int = 0, // 0 means non-commercial implementation
mimpid: Int = 0x20181004, // release date in BCD mimpid: Int = 0x20181004, // release date in BCD
mulDiv: Option[MulDivParams] = Some(MulDivParams()), mulDiv: Option[MulDivParams] = Some(MulDivParams()),
fpu: Option[FPUParams] = Some(FPUParams()), fpu: Option[FPUParams] = Some(FPUParams()),
debugROB: Boolean = false, // if enabled, uses a C++ debug ROB to generate trace-with-wdata debugROB: Boolean =
haveCease: Boolean = true, // non-standard CEASE instruction false, // if enabled, uses a C++ debug ROB to generate trace-with-wdata
haveSimTimeout: Boolean = true // add plusarg for simulation timeout haveCease: Boolean = true, // non-standard CEASE instruction
haveSimTimeout: Boolean = true // add plusarg for simulation timeout
) extends CoreParams { ) extends CoreParams {
val haveFSDirty = false val haveFSDirty = false
val pmpGranularity: Int = if (useHypervisor) 4096 else 4 val pmpGranularity: Int = if (useHypervisor) 4096 else 4
@@ -123,12 +124,14 @@ class VortexTile private (
// Memory-mapped region for HTIF communication // Memory-mapped region for HTIF communication
// We use fixed addresses instead of tohost/fromhost // We use fixed addresses instead of tohost/fromhost
val regDevice = new SimpleDevice("vortex-reg", Seq(s"vortex-reg${tileParams.hartId}")) val regDevice =
new SimpleDevice("vortex-reg", Seq(s"vortex-reg${tileParams.hartId}"))
val regNode = TLRegisterNode( val regNode = TLRegisterNode(
address = Seq(AddressSet(0x7c000000 + 0x1000 * tileParams.hartId, 0xfff)), address = Seq(AddressSet(0x7c000000 + 0x1000 * tileParams.hartId, 0xfff)),
device = regDevice, device = regDevice,
beatBytes = 4, beatBytes = 4,
concurrency = 1) concurrency = 1
)
regNode := tlSlaveXbar.node regNode := tlSlaveXbar.node
@@ -149,11 +152,13 @@ class VortexTile private (
beatBytes = lazyCoreParamsView.coreDataBytes, beatBytes = lazyCoreParamsView.coreDataBytes,
minLatency = 1)))*/ minLatency = 1)))*/
require(p(SIMTCoreKey).isDefined, require(
"SIMTCoreKey not defined; make sure to use WithSimtLanes when using VortexTile") p(SIMTCoreKey).isDefined,
"SIMTCoreKey not defined; make sure to use WithSimtLanes when using VortexTile"
)
val numLanes = p(SIMTCoreKey) match { val numLanes = p(SIMTCoreKey) match {
case Some(simtParam) => simtParam.nLanes case Some(simtParam) => simtParam.nLanes
case None => 4 case None => 4
} }
// CAUTION: imemSourceWidth is dependent on the ibuffer size. We have to // CAUTION: imemSourceWidth is dependent on the ibuffer size. We have to
@@ -168,46 +173,60 @@ class VortexTile private (
// ibuffer size is set as a hardcoded macro IBUF_SIZE that's uncontrollable // ibuffer size is set as a hardcoded macro IBUF_SIZE that's uncontrollable
// from Chisel, there's no easy solution. We at least don't expose this as a // from Chisel, there's no easy solution. We at least don't expose this as a
// Parameter and leave as a hardcoded value here. // Parameter and leave as a hardcoded value here.
val imemSourceWidth = 1 // 1 << 2 == IBUF_SIZE = 4 val imemSourceWidth = 6 // 1 << imemSourceWidth == IBUF_SIZE
val dmemSourceWidth = p(SIMTCoreKey) match { val dmemSourceWidth = p(SIMTCoreKey) match {
// TODO: respect coalescer newSrcIds // TODO: respect coalescer newSrcIds
case Some(simtParam) => log2Ceil(simtParam.nSrcIds) case Some(simtParam) => log2Ceil(simtParam.nSrcIds)
case None => 4 case None => 4
} }
require(dmemSourceWidth >= 4, require(
dmemSourceWidth >= 4,
"Setting a small number of sourceIds may cause correctness bug inside " + "Setting a small number of sourceIds may cause correctness bug inside " +
"Vortex core due to synchronization issues in vx_wspawn. " + "Vortex core due to synchronization issues in vx_wspawn. " +
"We recommend setting nSrcIds to at least 16.") "We recommend setting nSrcIds to at least 16."
)
val imemNodes = Seq.tabulate(1) { i => val imemNodes = Seq.tabulate(1) { i =>
TLClientNode(Seq(TLMasterPortParameters.v1( TLClientNode(
clients = Seq(TLMasterParameters.v1( Seq(
sourceId = IdRange(0, 1 << imemSourceWidth), TLMasterPortParameters.v1(
name = s"Vortex Core ${vortexParams.hartId} I-Mem $i", clients = Seq(
requestFifo = true, TLMasterParameters.v1(
supportsProbe = sourceId = IdRange(0, 1 << imemSourceWidth),
TransferSizes(1, lazyCoreParamsView.coreDataBytes), name = s"Vortex Core ${vortexParams.hartId} I-Mem $i",
supportsGet = TransferSizes(1, lazyCoreParamsView.coreDataBytes) requestFifo = true,
)) supportsProbe =
))) TransferSizes(1, lazyCoreParamsView.coreDataBytes),
supportsGet = TransferSizes(1, lazyCoreParamsView.coreDataBytes)
)
)
)
)
)
} }
val dmemNodes = Seq.tabulate(numLanes) { i => val dmemNodes = Seq.tabulate(numLanes) { i =>
TLClientNode(Seq(TLMasterPortParameters.v1( TLClientNode(
clients = Seq(TLMasterParameters.v1( Seq(
sourceId = IdRange(0, 1 << dmemSourceWidth), TLMasterPortParameters.v1(
name = s"Vortex Core ${vortexParams.hartId} D-Mem Lane $i", clients = Seq(
requestFifo = true, TLMasterParameters.v1(
supportsProbe = sourceId = IdRange(0, 1 << dmemSourceWidth),
TransferSizes(1, lazyCoreParamsView.coreDataBytes), name = s"Vortex Core ${vortexParams.hartId} D-Mem Lane $i",
supportsGet = TransferSizes(1, lazyCoreParamsView.coreDataBytes), requestFifo = true,
supportsPutFull = supportsProbe =
TransferSizes(1, lazyCoreParamsView.coreDataBytes), TransferSizes(1, lazyCoreParamsView.coreDataBytes),
supportsPutPartial = supportsGet = TransferSizes(1, lazyCoreParamsView.coreDataBytes),
TransferSizes(1, lazyCoreParamsView.coreDataBytes) supportsPutFull =
)) TransferSizes(1, lazyCoreParamsView.coreDataBytes),
))) supportsPutPartial =
TransferSizes(1, lazyCoreParamsView.coreDataBytes)
)
)
)
)
)
} }
// combine outgoing per-lane dmemNode into 1 idenity node // combine outgoing per-lane dmemNode into 1 idenity node
// //
@@ -220,23 +239,31 @@ class VortexTile private (
val dmemAggregateNode = TLIdentityNode() val dmemAggregateNode = TLIdentityNode()
dmemNodes.foreach { dmemAggregateNode := TLWidthWidget(4) := _ } dmemNodes.foreach { dmemAggregateNode := TLWidthWidget(4) := _ }
val memNode = TLClientNode(Seq(TLMasterPortParameters.v1( val memNode = TLClientNode(
clients = Seq(TLMasterParameters.v1( Seq(
// FIXME: need to also respect imemSourceWidth TLMasterPortParameters.v1(
sourceId = IdRange(0, 1 << dmemSourceWidth), clients = Seq(
name = s"Vortex Core ${vortexParams.hartId} Mem Interface", TLMasterParameters.v1(
requestFifo = true, // FIXME: need to also respect imemSourceWidth
supportsProbe = TransferSizes(16, 16), // FIXME: hardcoded sourceId = IdRange(0, 1 << dmemSourceWidth),
supportsGet = TransferSizes(16, 16), name = s"Vortex Core ${vortexParams.hartId} Mem Interface",
supportsPutFull = TransferSizes(16, 16), requestFifo = true,
supportsPutPartial = TransferSizes(16, 16) supportsProbe = TransferSizes(16, 16), // FIXME: hardcoded
)) supportsGet = TransferSizes(16, 16),
))) supportsPutFull = TransferSizes(16, 16),
supportsPutPartial = TransferSizes(16, 16)
)
)
)
)
)
// Conditionally instantiate memory coalescer // Conditionally instantiate memory coalescer
val coalescerNode = p(CoalescerKey) match { val coalescerNode = p(CoalescerKey) match {
case Some(coalescerParam) => { case Some(coalescerParam) => {
val coal = LazyModule(new CoalescingUnit(coalescerParam.copy(enable = true))) val coal = LazyModule(
new CoalescingUnit(coalescerParam.copy(enable = true))
)
coal.cpuNode :=* dmemAggregateNode coal.cpuNode :=* dmemAggregateNode
coal.aggregateNode // N+1 lanes coal.aggregateNode // N+1 lanes
} }
@@ -245,10 +272,14 @@ class VortexTile private (
// Conditionally instantiate L1 cache // Conditionally instantiate L1 cache
val l1Node = p(L1SystemKey) match { val l1Node = p(L1SystemKey) match {
case Some(l1SystemCfg) =>{ case Some(l1SystemCfg) => {
println(s"============ Using Vortex FatBank as L1 System =================") println(
require(p(CoalescerKey).isDefined, s"============ Using Vortex FatBank as L1 System ================="
"Vortex L1 configuration currently only works when coalescer is also enabled.") )
require(
p(CoalescerKey).isDefined,
"Vortex L1 configuration currently only works when coalescer is also enabled."
)
val L1System = LazyModule(new L1System(l1SystemCfg)) val L1System = LazyModule(new L1System(l1SystemCfg))
// Connect L1System with imem_fetch_interface without XBar // Connect L1System with imem_fetch_interface without XBar
@@ -299,19 +330,28 @@ class VortexTile private (
masterNode :=* tlOtherMastersNode masterNode :=* tlOtherMastersNode
DisableMonitors { implicit p => tlSlaveXbar.node :*= slaveNode } DisableMonitors { implicit p => tlSlaveXbar.node :*= slaveNode }
val dtimProperty = Nil //Seq(dmemDevice.asProperty).flatMap(p => Map("sifive,dtim" -> p)) val dtimProperty =
Nil // Seq(dmemDevice.asProperty).flatMap(p => Map("sifive,dtim" -> p))
val itimProperty = Nil //frontend.icache.itimProperty.toSeq.flatMap(p => Map("sifive,itim" -> p)) val itimProperty =
Nil // frontend.icache.itimProperty.toSeq.flatMap(p => Map("sifive,itim" -> p))
val beuProperty = bus_error_unit.map(d => Map( val beuProperty = bus_error_unit
"sifive,buserror" -> d.device.asProperty)).getOrElse(Nil) .map(d => Map("sifive,buserror" -> d.device.asProperty))
.getOrElse(Nil)
val cpuDevice: SimpleDevice = new SimpleDevice("cpu", Seq(s"sifive,vortex${tileParams.hartId}", "riscv")) { val cpuDevice: SimpleDevice = new SimpleDevice(
"cpu",
Seq(s"sifive,vortex${tileParams.hartId}", "riscv")
) {
override def parent = Some(ResourceAnchors.cpus) override def parent = Some(ResourceAnchors.cpus)
override def describe(resources: ResourceBindings): Description = { override def describe(resources: ResourceBindings): Description = {
val Description(name, mapping) = super.describe(resources) val Description(name, mapping) = super.describe(resources)
Description(name, mapping ++ cpuProperties ++ nextLevelCacheProperty Description(
++ tileProperties ++ dtimProperty ++ itimProperty ++ beuProperty) name,
mapping ++ cpuProperties ++ nextLevelCacheProperty
++ tileProperties ++ dtimProperty ++ itimProperty ++ beuProperty
)
} }
} }
@@ -402,12 +442,14 @@ class VortexTileModuleImp(outer: VortexTile) extends BaseTileModuleImp(outer) {
println(s"width of a channel data ${core.io.mem.get.a.bits.data.getWidth}") println(s"width of a channel data ${core.io.mem.get.a.bits.data.getWidth}")
println(s"width of d channel data ${core.io.mem.get.d.bits.data.getWidth}") println(s"width of d channel data ${core.io.mem.get.d.bits.data.getWidth}")
val memTLAdapter = Module(new VortexTLAdapter( val memTLAdapter = Module(
outer.dmemSourceWidth, new VortexTLAdapter(
chiselTypeOf(core.io.mem.get.a.bits), outer.dmemSourceWidth,
chiselTypeOf(core.io.mem.get.d.bits), chiselTypeOf(core.io.mem.get.a.bits),
outer.memNode.out.head chiselTypeOf(core.io.mem.get.d.bits),
)) outer.memNode.out.head
)
)
// connection: VortexBundle <--> VortexTLAdapter <--> TL memNode // connection: VortexBundle <--> VortexTLAdapter <--> TL memNode
memTLAdapter.io.inReq <> core.io.mem.get.a memTLAdapter.io.inReq <> core.io.mem.get.a
@@ -415,12 +457,14 @@ class VortexTileModuleImp(outer: VortexTile) extends BaseTileModuleImp(outer) {
outer.memNode.out(0)._1.a <> memTLAdapter.io.outReq outer.memNode.out(0)._1.a <> memTLAdapter.io.outReq
memTLAdapter.io.outResp <> outer.memNode.out(0)._1.d memTLAdapter.io.outResp <> outer.memNode.out(0)._1.d
} else { } else {
val imemTLAdapter = Module(new VortexTLAdapter( val imemTLAdapter = Module(
new VortexTLAdapter(
outer.imemSourceWidth, outer.imemSourceWidth,
chiselTypeOf(core.io.imem.get(0).a.bits), chiselTypeOf(core.io.imem.get(0).a.bits),
chiselTypeOf(core.io.imem.get(0).d.bits), chiselTypeOf(core.io.imem.get(0).d.bits),
outer.imemNodes.head.out.head outer.imemNodes.head.out.head
)) )
)
// TODO: make imemNodes not a vector // TODO: make imemNodes not a vector
imemTLAdapter.io.inReq <> core.io.imem.get(0).a imemTLAdapter.io.inReq <> core.io.imem.get(0).a
core.io.imem.get(0).d <> imemTLAdapter.io.inResp core.io.imem.get(0).d <> imemTLAdapter.io.inResp
@@ -431,12 +475,14 @@ class VortexTileModuleImp(outer: VortexTile) extends BaseTileModuleImp(outer) {
// up some area // up some area
val dmemTLBundles = outer.dmemNodes.map(_.out.head._1) val dmemTLBundles = outer.dmemNodes.map(_.out.head._1)
val dmemTLAdapters = Seq.tabulate(outer.numLanes) { _ => val dmemTLAdapters = Seq.tabulate(outer.numLanes) { _ =>
Module(new VortexTLAdapter( Module(
outer.dmemSourceWidth, new VortexTLAdapter(
chiselTypeOf(core.io.dmem.get(0).a.bits), outer.dmemSourceWidth,
chiselTypeOf(core.io.dmem.get(0).d.bits), chiselTypeOf(core.io.dmem.get(0).a.bits),
outer.dmemNodes(0).out.head chiselTypeOf(core.io.dmem.get(0).d.bits),
)) outer.dmemNodes(0).out.head
)
)
} }
// Since the individual per-lane TL requests might come back out-of-sync between // Since the individual per-lane TL requests might come back out-of-sync between
@@ -459,7 +505,10 @@ class VortexTileModuleImp(outer: VortexTile) extends BaseTileModuleImp(outer) {
// TODO: A cleaner solution would be to simply do a synchronized allocation // TODO: A cleaner solution would be to simply do a synchronized allocation
// of a same source id for all lanes. // of a same source id for all lanes.
val arb = Module( val arb = Module(
new RRArbiter(core.io.dmem.get.head.d.bits.source.cloneType, outer.numLanes) new RRArbiter(
core.io.dmem.get.head.d.bits.source.cloneType,
outer.numLanes
)
) )
arb.io.out.ready := true.B arb.io.out.ready := true.B
val dmemBundles = dmemTLAdapters.map(_.io.inResp) val dmemBundles = dmemTLAdapters.map(_.io.inResp)
@@ -470,10 +519,11 @@ class VortexTileModuleImp(outer: VortexTile) extends BaseTileModuleImp(outer) {
val matchingSources = Wire(UInt(outer.numLanes.W)) val matchingSources = Wire(UInt(outer.numLanes.W))
matchingSources := dmemBundles matchingSources := dmemBundles
.map(b => .map(b =>
// If there is no valid response pending across all lanes, // If there is no valid response pending across all lanes,
// matchingSources should not filter out upstream ready signals, so // matchingSources should not filter out upstream ready signals, so
// set it to all-1 // set it to all-1
!arb.io.out.valid || (b.bits.source === arb.io.out.bits)) !arb.io.out.valid || (b.bits.source === arb.io.out.bits)
)
.asUInt .asUInt
// make connection: // make connection:
@@ -484,8 +534,8 @@ class VortexTileModuleImp(outer: VortexTile) extends BaseTileModuleImp(outer) {
} }
(core.io.dmem.get zip dmemTLAdapters).zipWithIndex.foreach { (core.io.dmem.get zip dmemTLAdapters).zipWithIndex.foreach {
case ((coreMem, tlAdapter), i) => case ((coreMem, tlAdapter), i) =>
coreMem.d.valid := tlAdapter.io.inResp.valid && matchingSources(i) coreMem.d.valid := tlAdapter.io.inResp.valid && matchingSources(i)
tlAdapter.io.inResp.ready := coreMem.d.ready && matchingSources(i) tlAdapter.io.inResp.ready := coreMem.d.ready && matchingSources(i)
} }
(dmemTLAdapters zip dmemTLBundles) foreach { case (tlAdapter, tlOut) => (dmemTLAdapters zip dmemTLBundles) foreach { case (tlAdapter, tlOut) =>
tlOut.a <> tlAdapter.io.outReq tlOut.a <> tlAdapter.io.outReq
@@ -499,16 +549,15 @@ class VortexTileModuleImp(outer: VortexTile) extends BaseTileModuleImp(outer) {
} }
// TODO: generalize for useVxCache // TODO: generalize for useVxCache
if (!outer.vortexParams.useVxCache) { if (!outer.vortexParams.useVxCache) {}
}
} }
// Some @copypaste from CoalescerSourceGen. // Some @copypaste from CoalescerSourceGen.
class VortexTLAdapter( class VortexTLAdapter(
newSourceWidth: Int, newSourceWidth: Int,
inReqT: VortexBundleA, inReqT: VortexBundleA,
inRespT: VortexBundleD, inRespT: VortexBundleD,
outTL: (TLBundle, TLEdge) outTL: (TLBundle, TLEdge)
) extends Module { ) extends Module {
val io = IO(new Bundle { val io = IO(new Bundle {
// in/out means upstream/downstream // in/out means upstream/downstream
@@ -518,11 +567,13 @@ class VortexTLAdapter(
val outResp = chiselTypeOf(outTL._1.d) val outResp = chiselTypeOf(outTL._1.d)
}) })
val edge = outTL._2 val edge = outTL._2
val sourceGen = Module(new SourceGenerator( val sourceGen = Module(
newSourceWidth, new SourceGenerator(
Some(inReqT.source), newSourceWidth,
ignoreInUse = false Some(inReqT.source),
)) ignoreInUse = false
)
)
sourceGen.io.gen := io.outReq.fire // use up a source ID only when request is created sourceGen.io.gen := io.outReq.fire // use up a source ID only when request is created
sourceGen.io.reclaim.valid := io.outResp.fire sourceGen.io.reclaim.valid := io.outResp.fire
sourceGen.io.reclaim.bits := io.outResp.bits.source sourceGen.io.reclaim.bits := io.outResp.bits.source