Passed memory offsets to genHeader (#1416)

Instead of emitting a constant and referencing it by name in the header for
a bridge constructor, the memory mapping is passed alongside the base offset
for MMIO for bridge header emission to reference.
This commit is contained in:
Nandor Licker 2023-02-01 12:47:14 +02:00 committed by GitHub
parent 4d1876334e
commit 9ae4ed7f52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 46 additions and 53 deletions

View File

@ -251,8 +251,8 @@ class BlockDevBridgeModule(blockDevExternal: BlockDeviceConfig, hostP: Parameter
genCRFile()
override def genHeader(base: BigInt, sb: StringBuilder): Unit = {
super.genHeader(base, sb)
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
super.genHeader(base, memoryRegions, sb)
sb.append(CppGenerationUtils.genMacro(s"${getWName.toUpperCase}_latency_bits", UInt32(latencyBits)))
sb.append(CppGenerationUtils.genMacro(s"${getWName.toUpperCase}_num_trackers", UInt32(nTrackers)))
}

View File

@ -144,8 +144,8 @@ class DromajoBridgeModule(key: DromajoKey)(implicit p: Parameters) extends Bridg
genCRFile()
// modify the output header file
override def genHeader(base: BigInt, sb: StringBuilder): Unit = {
super.genHeader(base, sb)
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
super.genHeader(base, memoryRegions, sb)
sb.append(CppGenerationUtils.genMacro(s"${getWName.toUpperCase}_iaddr_width", UInt32(iaddrWidth)))
sb.append(CppGenerationUtils.genMacro(s"${getWName.toUpperCase}_insn_width", UInt32(insnWidth)))

View File

@ -88,14 +88,14 @@ class SerialBridgeModule(serialBridgeParams: SerialBridgeParams)(implicit p: Par
genCRFile()
override def genHeader(base: BigInt, sb: StringBuilder): Unit = {
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
import CppGenerationUtils._
val headerWidgetName = getWName.toUpperCase
super.genHeader(base, sb)
super.genHeader(base, memoryRegions, sb)
val memoryRegionNameOpt = serialBridgeParams.memoryRegionNameOpt
val offsetConstName = memoryRegionNameOpt.map(GetMemoryRegionOffsetConstName(_)).getOrElse("0")
val offsetConst = memoryRegionNameOpt.map(memoryRegions(_)).getOrElse(BigInt(0))
sb.append(genMacro(s"${headerWidgetName}_has_memory", memoryRegionNameOpt.isDefined.toString))
sb.append(genMacro(s"${headerWidgetName}_memory_offset", offsetConstName))
sb.append(genMacro(s"${headerWidgetName}_memory_offset", UInt64(offsetConst)))
}
}
}

View File

@ -211,10 +211,10 @@ class TracerVBridgeModule(key: TracerVKey)(implicit p: Parameters)
}
genCRFile()
override def genHeader(base: BigInt, sb: StringBuilder): Unit = {
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
import CppGenerationUtils._
val headerWidgetName = getWName.toUpperCase
super.genHeader(base, sb)
super.genHeader(base, memoryRegions, sb)
sb.append(genConstStatic(s"${headerWidgetName}_max_core_ipc", UInt32(traces.size)))
emitClockDomainInfo(headerWidgetName, sb)
}

View File

@ -200,9 +200,9 @@ class CPUManagedStreamEngine(p: Parameters, val params: StreamEngineParameters)
genCRFile()
override def genHeader(base: BigInt, sb: StringBuilder) {
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder) {
val headerWidgetName = getWName.toUpperCase
super.genHeader(base, sb)
super.genHeader(base, memoryRegions, sb)
def serializeStreamParameters(prefix: String, params: Seq[StreamDriverParameters]): Unit = {
val numStreams = params.size

View File

@ -247,9 +247,9 @@ class FPGAManagedStreamEngine(p: Parameters, val params: StreamEngineParameters)
genCRFile()
override def genHeader(base: BigInt, sb: StringBuilder) {
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder) {
val headerWidgetName = getWName.toUpperCase
super.genHeader(base, sb)
super.genHeader(base, memoryRegions, sb)
def serializeStreamParameters(prefix: String, params: Seq[ToCPUStreamDriverParameters]): Unit = {
val numStreams = params.size

View File

@ -214,7 +214,7 @@ class FPGATop(implicit p: Parameters) extends LazyModule with HasWidgets {
}
xbar := loadMem.toHostMemory
val targetMemoryRegions = sortedRegionTuples.zip(dramOffsets).map({ case ((bridgeSeq, addresses), hostBaseAddr) =>
val targetMemoryRegions = Map(sortedRegionTuples.zip(dramOffsets).map({ case ((bridgeSeq, addresses), hostBaseAddr) =>
val regionName = bridgeSeq.head.memoryRegionName
val virtualBaseAddr = addresses.map(_.base).min
val offset = hostBaseAddr - virtualBaseAddr
@ -225,8 +225,8 @@ class FPGATop(implicit p: Parameters) extends LazyModule with HasWidgets {
(preTranslationPort := AXI4Deinterleaver(bridge.memorySlaveConstraints.supportsRead.max)
:= bridge.memoryMasterNode)
}
HostMemoryMapping(regionName, offset)
})
regionName -> offset
}):_*)
def printHostDRAMSummary(): Unit = {
def toIECString(value: BigInt): String = {
@ -323,9 +323,8 @@ class FPGATop(implicit p: Parameters) extends LazyModule with HasWidgets {
(node, params)
}
override def genHeader(sb: StringBuilder): Unit = {
super.genHeader(sb)
targetMemoryRegions.foreach(_.serializeToHeader(sb))
def genHeader(sb: StringBuilder): Unit = {
super.genWidgetHeaders(sb, targetMemoryRegions)
}
lazy val module = new FPGATopImp(this)

View File

@ -554,12 +554,12 @@ class FASEDMemoryTimingModel(completeConfig: CompleteConfig, hostParams: Paramet
genCRFile()
override def genHeader(base: BigInt, sb: StringBuilder): Unit = {
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
def genCPPmap(mapName: String, map: Map[String, BigInt]): String = {
val prefix = s"const std::map<std::string, int> $mapName = {\n"
map.foldLeft(prefix)((str, kvp) => str + s""" {\"${kvp._1}\", ${kvp._2}},\n""") + "};\n"
}
super.genHeader(base, sb)
super.genHeader(base, memoryRegions, sb)
sb.append(CppGenerationUtils.genMacro(s"${getWName.toUpperCase}_target_addr_bits", UInt32(p(NastiKey).addrBits)))
}

View File

@ -64,10 +64,10 @@ class AssertBridgeModule(params: AssertBridgeParameters)(implicit p: Parameters)
attach(enable, "enable")
genCRFile()
override def genHeader(base: BigInt, sb: StringBuilder): Unit = {
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
import CppGenerationUtils._
val headerWidgetName = getWName.toUpperCase
super.genHeader(base, sb)
super.genHeader(base, memoryRegions, sb)
sb.append(genConstStatic(s"${headerWidgetName}_assert_count", UInt32(assertMessages.size)))
sb.append(genArray(s"${headerWidgetName}_assert_messages", assertMessages.map(CStrLit)))
}

View File

@ -160,7 +160,7 @@ class AutoCounterBridgeModule(key: AutoCounterParameters)(implicit p: Parameters
attach(btht_queue.io.deq.valid, "countersready", ReadOnly)
Pulsify(genWORegInit(btht_queue.io.deq.ready, "readdone", false.B), 1)
override def genHeader(base: BigInt, sb: StringBuilder): Unit = {
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
headerComment(sb)
// Exclude counter addresses as their names can vary across AutoCounter instances, but
// we only generate a single struct typedef

View File

@ -179,8 +179,8 @@ class LoadMemWidget(val totalDRAMAllocated: BigInt)(implicit p: Parameters) exte
def memDataChunk: Long =
((hKey.dataBits - 1) / p(CtrlNastiKey).dataBits) + 1
override def genHeader(base: BigInt, sb: StringBuilder): Unit = {
super.genHeader(base, sb)
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
super.genHeader(base, memoryRegions, sb)
import CppGenerationUtils._
sb.append(genConstStatic(s"${getWName.toUpperCase}_mem_data_chunk", UInt32(memDataChunk)))
}

View File

@ -149,14 +149,14 @@ class PeekPokeBridgeModule(key: PeekPokeKey)(implicit p: Parameters) extends Bri
poked := addrs.map(i => crFile.io.mcr.activeWriteToAddress(i)).reduce(_ || _)
})
override def genHeader(base: BigInt, sb: StringBuilder): Unit = {
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
import CppGenerationUtils._
val name = getWName.toUpperCase
def genOffsets(signals: Seq[String]): Unit = (signals.zipWithIndex) foreach {
case (name, idx) => sb.append(genConstStatic(name, UInt32(idx)))}
super.genHeader(base, sb)
super.genHeader(base, memoryRegions, sb)
sb.append(genComment("Pokeable target inputs"))
sb.append(genMacro("POKE_SIZE", UInt64(hPort.ins.size)))
genOffsets(hPort.ins.unzip._1)

View File

@ -183,10 +183,10 @@ class PlusArgsBridgeModule(params: PlusArgsBridgeParams)(implicit p: Parameters)
assert(plusArgValueNext === plusArgValue)
}
override def genHeader(base: BigInt, sb: StringBuilder) {
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder) {
import CppGenerationUtils._
val headerWidgetName = getWName.toUpperCase
super.genHeader(base, sb)
super.genHeader(base, memoryRegions, sb)
sb.append(genStatic(s"${headerWidgetName}_name", CStrLit(params.name)))
sb.append(genStatic(s"${headerWidgetName}_default", CStrLit(s"${params.default}")))
sb.append(genStatic(s"${headerWidgetName}_docstring", CStrLit(params.docstring)))

View File

@ -185,10 +185,10 @@ class PrintBridgeModule(key: PrintBridgeParameters)(implicit p: Parameters)
val argumentOffsets = printPort.printRecords.map(_._2.argumentOffsets().map(UInt32(_)))
val formatStrings = printPort.printRecords.map(_._2.formatString).map(CStrLit)
override def genHeader(base: BigInt, sb: StringBuilder): Unit = {
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
import CppGenerationUtils._
val headerWidgetName = getWName.toUpperCase
super.genHeader(base, sb)
super.genHeader(base, memoryRegions, sb)
sb.append(genConstStatic(s"${headerWidgetName}_print_count", UInt32(printPort.printRecords.size)))
sb.append(genConstStatic(s"${headerWidgetName}_token_bytes", UInt32(pow2Bits / 8)))
sb.append(genConstStatic(s"${headerWidgetName}_idle_cycles_mask",

View File

@ -74,10 +74,10 @@ class ResetPulseBridgeModule(cfg: ResetPulseBridgeParameters)(implicit p: Parame
remainingPulseLength := Mux(pulseComplete, 0.U, remainingPulseLength - 1.U)
}
override def genHeader(base: BigInt, sb: StringBuilder): Unit = {
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
import CppGenerationUtils._
val headerWidgetName = getWName.toUpperCase
super.genHeader(base, sb)
super.genHeader(base, memoryRegions, sb)
sb.append(genConstStatic(s"${headerWidgetName}_max_pulse_length", UInt32(cfg.maxPulseLength)))
sb.append(genConstStatic(s"${headerWidgetName}_default_pulse_length", UInt32(cfg.defaultPulseLength)))
}

View File

@ -145,10 +145,10 @@ class TerminationBridgeModule(params: TerminationBridgeParams)(implicit p: Param
//MMIO to indicate one of the target defined termination messages
genROReg(terminationCode.bits, "out_terminationCode")
override def genHeader(base: BigInt, sb: StringBuilder): Unit = {
override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
import CppGenerationUtils._
val headerWidgetName = getWName.toUpperCase
super.genHeader(base, sb)
super.genHeader(base, memoryRegions, sb)
sb.append(genConstStatic(s"${headerWidgetName}_message_count", UInt32((params.conditionInfo).size)))
sb.append(genArray(s"${headerWidgetName}_message_type", (params.conditionInfo).map(x => UInt32(if(x.isErr) 1 else 0))))
sb.append(genArray(s"${headerWidgetName}_message", (params.conditionInfo).map(x => CStrLit(x.message))))

View File

@ -2,7 +2,6 @@
package midas.widgets
import midas.widgets.CppGenerationUtils._
import freechips.rocketchip.amba.axi4.AXI4OutwardNode
import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes}
@ -32,10 +31,6 @@ import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes}
*/
case class MemorySlaveConstraints(address: Seq[AddressSet], supportsRead: TransferSizes, supportsWrite: TransferSizes)
object GetMemoryRegionOffsetConstName {
def apply(memoryRegionName: String) = s"${memoryRegionName}_offset"
}
/**
* A common trait for referring collateral in the generated header.
*
@ -51,7 +46,6 @@ trait HostDramHeaderConsts {
*
*/
def memoryRegionName: String
def offsetConstName = GetMemoryRegionOffsetConstName(memoryRegionName)
}
/**
@ -71,13 +65,6 @@ trait UsesHostDRAM extends HostDramHeaderConsts {
def memorySlaveConstraints: MemorySlaveConstraints
}
private[midas] case class HostMemoryMapping(memoryRegionName: String, hostOffset: BigInt) extends HostDramHeaderConsts {
def serializeToHeader(sb: StringBuilder): Unit = {
sb.append(genComment(s"Host FPGA memory mapping for region: ${memoryRegionName}"))
sb.append(genConstStatic(offsetConstName, Int64(hostOffset)))
}
}
private[midas] object BytesOfDRAMRequired {
// Returns the difference between the bounds of the range that the requested
// address set spans, neglecting discontinuities

View File

@ -190,7 +190,14 @@ abstract class WidgetImp(wrapper: Widget) extends LazyModuleImp(wrapper) {
crFile
}
def genHeader(base: BigInt, sb: StringBuilder): Unit = {
/** Emits a header snippet for this widget.
* @param base
* The base address of the MMIO region allocated to the widget.
* @param memoryRegions
* A mapping of names to allocated FPGA-DRAM regions. This is one mechanism
* for establishing side-channels between two otherwise unconnected bridges or widgets.
*/
def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = {
wrapper.headerComment(sb)
crRegistry.genHeader(wrapper.getWName.toUpperCase, base, sb)
crRegistry.genArrayHeader(wrapper.getWName.toUpperCase, base, sb)
@ -276,8 +283,8 @@ trait HasWidgets {
* Iterates through each bridge, generating the header fragment. Must be
* called after bridge address assignment is complete.
*/
def genHeader(sb: StringBuilder): Unit = {
widgets foreach ((w: Widget) => w.module.genHeader(addrMap(w.getWName).start, sb))
def genWidgetHeaders(sb: StringBuilder, memoryRegions: Map[String, BigInt]): Unit = {
widgets foreach ((w: Widget) => w.module.genHeader(addrMap(w.getWName).start, memoryRegions, sb))
}
def printWidgets: Unit = {