diff --git a/src/main/scala/coreplex/Configs.scala b/src/main/scala/coreplex/Configs.scala index c320390c..0d932c04 100644 --- a/src/main/scala/coreplex/Configs.scala +++ b/src/main/scala/coreplex/Configs.scala @@ -45,7 +45,7 @@ class WithNBigCores(n: Int) extends Config((site, here, up) => { icache = Some(ICacheParams( rowBits = site(SystemBusKey).beatBits, blockBytes = site(CacheBlockBytes)))) - List.fill(n)(big) ++ up(RocketTilesKey, site) + List.tabulate(n)(i => big.copy(hartid = i)) } }) @@ -67,7 +67,7 @@ class WithNSmallCores(n: Int) extends Config((site, here, up) => { nWays = 1, nTLBEntries = 4, blockBytes = site(CacheBlockBytes)))) - List.fill(n)(small) ++ up(RocketTilesKey, site) + List.tabulate(n)(i => small.copy(hartid = i)) } }) @@ -94,7 +94,7 @@ class WithNTinyCores(n: Int) extends Config((site, here, up) => { nWays = 1, nTLBEntries = 4, blockBytes = site(CacheBlockBytes)))) - List.fill(n)(tiny) ++ up(RocketTilesKey, site) + List.tabulate(n)(i => tiny.copy(hartid = i)) } }) diff --git a/src/main/scala/coreplex/RocketCoreplex.scala b/src/main/scala/coreplex/RocketCoreplex.scala index b4992a3c..e7009316 100644 --- a/src/main/scala/coreplex/RocketCoreplex.scala +++ b/src/main/scala/coreplex/RocketCoreplex.scala @@ -24,6 +24,7 @@ trait HasRocketTiles extends HasSystemBus private val crossing = p(RocketCrossing) private val tileParams = p(RocketTilesKey) val nRocketTiles = tileParams.size + val hartIdList = tileParams.map(_.hartid) // Handle interrupts to be routed directly into each tile // TODO: figure out how to merge the localIntNodes and coreIntXbar below @@ -34,8 +35,8 @@ trait HasRocketTiles extends HasSystemBus // Make a wrapper for each tile that will wire it to coreplex devices and crossbars, // according to the specified type of clock crossing. - val wiringTuple = localIntNodes.zip(tileParams).zipWithIndex - val rocket_tiles: Seq[RocketTileWrapper] = wiringTuple.map { case ((lip, tp), i) => + val wiringTuple = localIntNodes.zip(tileParams) + val rocket_tiles: Seq[RocketTileWrapper] = wiringTuple.map { case (lip, tp) => val pWithExtra = p.alterPartial { case TileKey => tp case BuildRoCC => tp.rocc @@ -44,19 +45,19 @@ trait HasRocketTiles extends HasSystemBus val wrapper = crossing match { case SynchronousCrossing(params) => { - val wrapper = LazyModule(new SyncRocketTile(tp, i)(pWithExtra)) + val wrapper = LazyModule(new SyncRocketTile(tp)(pWithExtra)) sbus.fromSyncTiles(params, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode FlipRendering { implicit p => wrapper.slaveNode :*= pbus.toSyncSlaves(tp.name, tp.externalSlaveBuffers) } wrapper } case AsynchronousCrossing(depth, sync) => { - val wrapper = LazyModule(new AsyncRocketTile(tp, i)(pWithExtra)) + val wrapper = LazyModule(new AsyncRocketTile(tp)(pWithExtra)) sbus.fromAsyncTiles(depth, sync, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode FlipRendering { implicit p => wrapper.slaveNode :*= pbus.toAsyncSlaves(sync, tp.name, tp.externalSlaveBuffers) } wrapper } case RationalCrossing(direction) => { - val wrapper = LazyModule(new RationalRocketTile(tp, i)(pWithExtra)) + val wrapper = LazyModule(new RationalRocketTile(tp)(pWithExtra)) sbus.fromRationalTiles(direction, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode FlipRendering { implicit p => wrapper.slaveNode :*= pbus.toRationalSlaves(tp.name, tp.externalSlaveBuffers) } wrapper @@ -108,8 +109,12 @@ trait HasRocketTilesModuleImp extends LazyModuleImp with HasPeripheryDebugModuleImp { val outer: HasRocketTiles - // TODO make this less gross and/or support tiles with differently sized reset vectors - def resetVectorBits: Int = outer.paddrBits + def resetVectorBits: Int = { + // Consider using the minimum over all widths, rather than enforcing homogeneity + val vectors = outer.rocket_tiles.map(_.module.io.reset_vector) + require(vectors.tail.forall(_.getWidth == vectors.head.getWidth)) + vectors.head.getWidth + } val rocket_tile_inputs = Wire(Vec(outer.nRocketTiles, new ClockedRocketTileInputs()(p.alterPartial { case SharedMemoryTLEdge => outer.sharedMemoryTLEdge }))) @@ -123,7 +128,7 @@ trait HasRocketTilesModuleImp extends LazyModuleImp } // Default values for tile inputs; may be overriden in other traits - rocket_tile_inputs.zipWithIndex.foreach { case(wire, i) => + rocket_tile_inputs.zip(outer.hartIdList).foreach { case(wire, i) => wire.clock := clock wire.reset := reset wire.hartid := UInt(i) diff --git a/src/main/scala/coreplex/SystemBus.scala b/src/main/scala/coreplex/SystemBus.scala index 6721ead8..7096b3e5 100644 --- a/src/main/scala/coreplex/SystemBus.scala +++ b/src/main/scala/coreplex/SystemBus.scala @@ -125,5 +125,4 @@ trait HasSystemBus extends HasInterruptBus { val sbus = LazyModule(new SystemBus(sbusParams)) def sharedMemoryTLEdge: TLEdge = sbus.busView - def paddrBits: Int = sbus.busView.bundle.addressBits } diff --git a/src/main/scala/devices/tilelink/Error.scala b/src/main/scala/devices/tilelink/Error.scala index a1a4d945..cdbb95e0 100644 --- a/src/main/scala/devices/tilelink/Error.scala +++ b/src/main/scala/devices/tilelink/Error.scala @@ -59,7 +59,7 @@ class TLError(params: ErrorParams, beatBytes: Int = 4)(implicit p: Parameters) e val a_opcodes = Vec(AccessAck, AccessAck, AccessAckData, AccessAckData, AccessAckData, HintAck, Grant) da.bits.opcode := a_opcodes(a.bits.opcode) - da.bits.param := UInt(0) + da.bits.param := UInt(0) // toT, but error grants must be handled transiently (ie: you don't keep permissions) da.bits.size := a.bits.size da.bits.source := a.bits.source da.bits.sink := UInt(0) @@ -70,7 +70,7 @@ class TLError(params: ErrorParams, beatBytes: Int = 4)(implicit p: Parameters) e dc.valid := c.valid && c_last dc.bits.opcode := ReleaseAck - dc.bits.param := Vec(toN, toN, toB)(c.bits.param) + dc.bits.param := Vec(toB, toN, toN)(c.bits.param) dc.bits.size := c.bits.size dc.bits.source := c.bits.source dc.bits.sink := UInt(0) diff --git a/src/main/scala/diplomacy/Resources.scala b/src/main/scala/diplomacy/Resources.scala index d62f829e..4a76f87b 100644 --- a/src/main/scala/diplomacy/Resources.scala +++ b/src/main/scala/diplomacy/Resources.scala @@ -6,11 +6,33 @@ import Chisel.log2Ceil import scala.collection.immutable.{ListMap,SortedMap} sealed trait ResourceValue + +/** Permission of an address space. + * @param r readable. + * @param w writable. + * @param x executable. + * @param c cacheable. + */ case class ResourcePermissions(r: Boolean, w: Boolean, x: Boolean, c: Boolean) // Not part of DTS + +/** An address space description. + * @param address the address space. + * @param permissions the permission attributes of this space. See [[freechips.rocketchip.diplomacy.ResourcePermissions]]. + */ final case class ResourceAddress(address: Seq[AddressSet], permissions: ResourcePermissions) extends ResourceValue + +/** A mapped address space (eg: when map a device to a bus). + * @param address the address space. + * @param offset the address offset of the mapped device (eg: base address of the bus). + * @param permissions the permission attributes of this space. See [[freechips.rocketchip.diplomacy.ResourcePermissions]]. + */ final case class ResourceMapping(address: Seq[AddressSet], offset: BigInt, permissions: ResourcePermissions) extends ResourceValue final case class ResourceInt(value: BigInt) extends ResourceValue final case class ResourceString(value: String) extends ResourceValue + +/** A reference pointing to another device in DTS (eg: interrupt to interrupt controller). + * @param value the label (String) of the device. + */ final case class ResourceReference(value: String) extends ResourceValue final case class ResourceMap(value: Map[String, Seq[ResourceValue]], labels: Seq[String] = Nil) extends ResourceValue @@ -21,12 +43,17 @@ case class ResourceBindings(map: Map[String, Seq[Binding]]) def apply(key: String): Seq[Binding] = map.getOrElse(key, Nil) } +/** A serializable description of a device. + * @param name the resolved name of this device. See [[freechips.rocketchip.diplomacy.DeviceRegName]]. + * @param mapping the property map of this device. + */ case class Description(name: String, mapping: Map[String, Seq[ResourceValue]]) abstract class Device { def describe(resources: ResourceBindings): Description + /** make sure all derived devices have an unique label */ val label = "L" + Device.index.toString Device.index = Device.index + 1 } @@ -36,9 +63,12 @@ object Device private var index: Int = 0 } +/** A trait for devices that generate interrupts. */ trait DeviceInterrupts { this: Device => + + /** Whether to always use the expanded interrupt description in DTS: "interrupts-extended" */ val alwaysExtended = false def describeInterrupts(resources: ResourceBindings): Map[String, Seq[ResourceValue]] = { val int = resources("int") @@ -64,6 +94,7 @@ trait DeviceInterrupts def int = Seq(Resource(this, "int")) } +/** A trait for resolving the name of a device. */ trait DeviceRegName { this: Device => @@ -94,14 +125,18 @@ trait DeviceRegName } } +/** A simple device descriptor for devices that may support interrupts and address spaces. + * @param devname the base device named used in device name generation. + * @param devcompat a list of compatible devices. See device tree property "compatible". + */ class SimpleDevice(devname: String, devcompat: Seq[String]) extends Device with DeviceInterrupts with DeviceRegName { def describe(resources: ResourceBindings): Description = { - val name = describeName(devname, resources) - val int = describeInterrupts(resources) + val name = describeName(devname, resources) // the generated device name in device tree + val int = describeInterrupts(resources) // interrupt description def optDef(x: String, seq: Seq[ResourceValue]) = if (seq.isEmpty) None else Some(x -> seq) - val compat = optDef("compatible", devcompat.map(ResourceString(_))) + val compat = optDef("compatible", devcompat.map(ResourceString(_))) // describe the list of compatiable devices val reg = resources.map.filterKeys(regFilter) val (named, bulk) = reg.partition { case (k, v) => regName(k).isDefined } @@ -114,13 +149,18 @@ class SimpleDevice(devname: String, devcompat: Seq[String]) extends Device with require (false, s"DTS device $name has $k = $seq, must be a single ResourceAddress!") } - val names = optDef("reg-names", named.map(x => ResourceString(regName(x._1).get)).toList) - val regs = optDef("reg", (named ++ bulk).flatMap(_._2.map(_.value)).toList) + val names = optDef("reg-names", named.map(x => ResourceString(regName(x._1).get)).toList) // names of the named address space + val regs = optDef("reg", (named ++ bulk).flatMap(_._2.map(_.value)).toList) // address ranges of all spaces (named and bulk) Description(name, ListMap() ++ compat ++ int ++ names ++ regs) } } +/** A simple bus + * @param devname the base device named used in device name generation. + * @param devcompat a list of compatible devices. See device tree property "compatible". + * @param offset the base address of this bus. + */ class SimpleBus(devname: String, devcompat: Seq[String], offset: BigInt = 0) extends SimpleDevice(devname, devcompat ++ Seq("simple-bus")) { override def describe(resources: ResourceBindings): Description = { @@ -147,6 +187,7 @@ class SimpleBus(devname: String, devcompat: Seq[String], offset: BigInt = 0) ext def ranges = Seq(Resource(this, "ranges")) } +/** A generic memory block. */ class MemoryDevice extends Device with DeviceRegName { override val prefix = "" @@ -169,12 +210,13 @@ case class Resource(owner: Device, key: String) } } +/** The resource binding scope for a LazyModule that generates a device tree (currently Coreplex only). */ trait BindingScope { this: LazyModule => private val parentScope = BindingScope.find(parent) - protected[diplomacy] var resourceBindingFns: Seq[() => Unit] = Nil + protected[diplomacy] var resourceBindingFns: Seq[() => Unit] = Nil // callback functions to resolve resource binding during elaboration protected[diplomacy] var resourceBindings: Seq[(Resource, Option[Device], ResourceValue)] = Nil private case class ExpandedValue(path: Seq[String], labels: Seq[String], value: Seq[ResourceValue]) @@ -208,6 +250,7 @@ trait BindingScope } } + /** Generate the device tree. */ def bindingTree: ResourceMap = { eval val map: Map[Device, ResourceBindings] = @@ -232,6 +275,9 @@ object BindingScope object ResourceBinding { + /** Add a resource callback function to the callback list BindingScope.resourceBindingFns. + * @param block the callback function to be added. + */ def apply(block: => Unit) { val scope = BindingScope.find() require (scope.isDefined, "ResourceBinding must be called from within a BindingScope") diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index c3a05712..ab136f95 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -63,7 +63,7 @@ class DCSR extends Bundle { } class MIP(implicit p: Parameters) extends CoreBundle()(p) - with HasRocketCoreParameters { + with HasCoreParameters { val lip = Vec(coreParams.nLocalInterrupts, Bool()) val zero2 = Bool() val debug = Bool() // keep in sync with CSR.debugIntCause @@ -144,7 +144,7 @@ object CSR } class PerfCounterIO(implicit p: Parameters) extends CoreBundle - with HasRocketCoreParameters { + with HasCoreParameters { val eventSel = UInt(OUTPUT, xLen) val inc = UInt(INPUT, log2Ceil(1+retireWidth)) } @@ -161,7 +161,7 @@ class TracedInstruction(implicit p: Parameters) extends CoreBundle { } class CSRFileIO(implicit p: Parameters) extends CoreBundle - with HasRocketCoreParameters { + with HasCoreParameters { val interrupts = new TileInterrupts().asInput val hartid = UInt(INPUT, hartIdLen) val rw = new Bundle { @@ -190,7 +190,6 @@ class CSRFileIO(implicit p: Parameters) extends CoreBundle val evec = UInt(OUTPUT, vaddrBitsExtended) val exception = Bool(INPUT) val retire = UInt(INPUT, log2Up(1+retireWidth)) - val custom_mrw_csrs = Vec(nCustomMrwCsrs, UInt(INPUT, xLen)) val cause = UInt(INPUT, xLen) val pc = UInt(INPUT, vaddrBitsExtended) val badaddr = UInt(INPUT, vaddrBitsExtended) @@ -208,7 +207,7 @@ class CSRFileIO(implicit p: Parameters) extends CoreBundle } class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Parameters) extends CoreModule()(p) - with HasRocketCoreParameters { + with HasCoreParameters { val io = new CSRFileIO val reset_mstatus = Wire(init=new MStatus().fromBits(0)) @@ -223,7 +222,6 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param reset_dcsr.xdebugver := 1 reset_dcsr.prv := PRV.M val reg_dcsr = Reg(init=reset_dcsr) - val reg_debugint = Reg(Bool()) val (supported_interrupts, delegable_interrupts) = { val sup = Wire(new MIP) @@ -305,13 +303,17 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param val hpm_mask = reg_mcounteren & Mux((!usingVM).B || reg_mstatus.prv === PRV.S, delegable_counters.U, reg_scounteren) val mip = Wire(init=reg_mip) + mip.lip := (io.interrupts.lip: Seq[Bool]) + mip.mtip := io.interrupts.mtip + mip.msip := io.interrupts.msip + mip.meip := io.interrupts.meip // seip is the OR of reg_mip.seip and the actual line from the PLIC io.interrupts.seip.foreach { mip.seip := reg_mip.seip || RegNext(_) } mip.rocc := io.rocc_interrupt val read_mip = mip.asUInt & supported_interrupts val pending_interrupts = read_mip & reg_mie - val d_interrupts = reg_debugint << CSR.debugIntCause + val d_interrupts = io.interrupts.debug << CSR.debugIntCause val m_interrupts = Mux(reg_mstatus.prv <= PRV.S || (reg_mstatus.prv === PRV.M && reg_mstatus.mie), pending_interrupts & ~reg_mideleg, UInt(0)) val s_interrupts = Mux(reg_mstatus.prv < PRV.S || (reg_mstatus.prv === PRV.S && reg_mstatus.sie), pending_interrupts & reg_mideleg, UInt(0)) val (anyInterrupt, whichInterrupt) = chooseInterrupt(Seq(s_interrupts, m_interrupts, d_interrupts)) @@ -343,8 +345,6 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param CSRs.mimpid -> UInt(0), CSRs.marchid -> UInt(0), CSRs.mvendorid -> UInt(0), - CSRs.mcycle -> reg_cycle, - CSRs.minstret -> reg_instret, CSRs.misa -> reg_misa, CSRs.mstatus -> read_mstatus, CSRs.mtvec -> reg_mtvec, @@ -372,14 +372,34 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param if (usingFPU) read_mapping ++= fp_csrs - for (((e, c), i) <- (reg_hpmevent.padTo(CSR.nHPM, UInt(0)) - zip reg_hpmcounter.map(x => x: UInt).padTo(CSR.nHPM, UInt(0))) zipWithIndex) { - read_mapping += (i + CSR.firstHPE) -> e // mhpmeventN - read_mapping += (i + CSR.firstMHPC) -> c // mhpmcounterN - if (usingUser) read_mapping += (i + CSR.firstHPC) -> c // hpmcounterN + if (coreParams.haveBasicCounters) { + read_mapping += CSRs.mcycle -> reg_cycle + read_mapping += CSRs.minstret -> reg_instret + + for (((e, c), i) <- (reg_hpmevent.padTo(CSR.nHPM, UInt(0)) + zip reg_hpmcounter.map(x => x: UInt).padTo(CSR.nHPM, UInt(0))) zipWithIndex) { + read_mapping += (i + CSR.firstHPE) -> e // mhpmeventN + read_mapping += (i + CSR.firstMHPC) -> c // mhpmcounterN + if (usingUser) read_mapping += (i + CSR.firstHPC) -> c // hpmcounterN + if (xLen == 32) { + read_mapping += (i + CSR.firstMHPCH) -> c // mhpmcounterNh + if (usingUser) read_mapping += (i + CSR.firstHPCH) -> c // hpmcounterNh + } + } + + if (usingUser) { + read_mapping += CSRs.mcounteren -> reg_mcounteren + read_mapping += CSRs.cycle -> reg_cycle + read_mapping += CSRs.instret -> reg_instret + } + if (xLen == 32) { - read_mapping += (i + CSR.firstMHPCH) -> c // mhpmcounterNh - if (usingUser) read_mapping += (i + CSR.firstHPCH) -> c // hpmcounterNh + read_mapping += CSRs.mcycleh -> (reg_cycle >> 32) + read_mapping += CSRs.minstreth -> (reg_instret >> 32) + if (usingUser) { + read_mapping += CSRs.cycleh -> (reg_cycle >> 32) + read_mapping += CSRs.instreth -> (reg_instret >> 32) + } } } @@ -412,21 +432,6 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param read_mapping += CSRs.medeleg -> reg_medeleg } - if (usingUser) { - read_mapping += CSRs.mcounteren -> reg_mcounteren - read_mapping += CSRs.cycle -> reg_cycle - read_mapping += CSRs.instret -> reg_instret - } - - if (xLen == 32) { - read_mapping += CSRs.mcycleh -> (reg_cycle >> 32) - read_mapping += CSRs.minstreth -> (reg_instret >> 32) - if (usingUser) { - read_mapping += CSRs.cycleh -> (reg_cycle >> 32) - read_mapping += CSRs.instreth -> (reg_instret >> 32) - } - } - val pmpCfgPerCSR = xLen / new PMPConfig().getWidth def pmpCfgIndex(i: Int) = (xLen / 32) * (i / pmpCfgPerCSR) if (reg_pmp.nonEmpty) { @@ -438,13 +443,6 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param read_mapping += (CSRs.pmpaddr0 + i) -> pmp.addr } - for (i <- 0 until nCustomMrwCsrs) { - val addr = 0xff0 + i - require(addr < (1 << CSR.ADDRSZ)) - require(!read_mapping.contains(addr), "custom MRW CSR address " + i + " is already in use") - read_mapping += addr -> io.custom_mrw_csrs(i) - } - val decoded_addr = read_mapping map { case (k, v) => k -> (io.rw.addr === k) } val wdata = readModifyWriteCSR(io.rw.cmd, io.rw.rdata, io.rw.wdata) @@ -511,7 +509,7 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param assert(PopCount(insn_ret :: insn_call :: insn_break :: io.exception :: Nil) <= 1, "these conditions must be mutually exclusive") when (insn_wfi && !io.singleStep && !reg_debug) { reg_wfi := true } - when (pending_interrupts.orR || exception || reg_debugint) { reg_wfi := false } + when (pending_interrupts.orR || exception || io.interrupts.debug) { reg_wfi := false } assert(!reg_wfi || io.retire === UInt(0)) when (io.retire(0) || exception) { reg_singleStepped := true } @@ -611,7 +609,8 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param when (decoded_addr(CSRs.misa)) { val mask = UInt(isaStringToMask(isaMaskString), xLen) val f = wdata('f' - 'a') - reg_misa := ~(~wdata | (!f << ('d' - 'a'))) & mask | reg_misa & ~mask + if (coreParams.misaWritable) + reg_misa := ~(~wdata | (!f << ('d' - 'a'))) & mask | reg_misa & ~mask } when (decoded_addr(CSRs.mip)) { // MIP should be modified based on the value in reg_mip, not the value @@ -637,8 +636,10 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param writeCounter(i + CSR.firstMHPC, c, wdata) when (decoded_addr(i + CSR.firstHPE)) { e := perfEventSets.maskEventSelector(wdata) } } - writeCounter(CSRs.mcycle, reg_cycle, wdata) - writeCounter(CSRs.minstret, reg_instret, wdata) + if (coreParams.haveBasicCounters) { + writeCounter(CSRs.mcycle, reg_cycle, wdata) + writeCounter(CSRs.minstret, reg_instret, wdata) + } if (usingFPU) { when (decoded_addr(CSRs.fflags)) { reg_fflags := wdata } @@ -721,12 +722,6 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param } } - reg_mip.lip := (io.interrupts.lip: Seq[Bool]) - reg_mip.mtip := io.interrupts.mtip - reg_mip.msip := io.interrupts.msip - reg_mip.meip := io.interrupts.meip - reg_debugint := io.interrupts.debug - if (!usingVM) { reg_mideleg := 0 reg_medeleg := 0 diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index 7f3b3b63..e3daa973 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -384,7 +384,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val a_size = mtSize(s2_req.typ) val a_data = Fill(beatWords, pstore1_data) val acquire = if (edge.manager.anySupportAcquireB) { - edge.Acquire(UInt(0), acquire_address, lgCacheBlockBytes, s2_grow_param)._2 // Cacheability checked by tlb + edge.AcquireBlock(UInt(0), acquire_address, lgCacheBlockBytes, s2_grow_param)._2 // Cacheability checked by tlb } else { Wire(new TLBundleA(edge.bundle)) } diff --git a/src/main/scala/rocket/Frontend.scala b/src/main/scala/rocket/Frontend.scala index 7319e7ea..408088c3 100644 --- a/src/main/scala/rocket/Frontend.scala +++ b/src/main/scala/rocket/Frontend.scala @@ -75,7 +75,6 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) val icache = outer.icache.module require(fetchWidth*coreInstBytes == outer.icacheParams.fetchBytes) - val fetchBytes = coreInstBytes * fetchWidth val tlb = Module(new TLB(true, log2Ceil(fetchBytes), nTLBEntries)) val fq = withReset(reset || io.cpu.req.valid) { Module(new ShiftQueue(new FrontendResp, 5, flow = true)) } diff --git a/src/main/scala/rocket/NBDcache.scala b/src/main/scala/rocket/NBDcache.scala index 8d9899d4..cf0fa9bb 100644 --- a/src/main/scala/rocket/NBDcache.scala +++ b/src/main/scala/rocket/NBDcache.scala @@ -276,7 +276,7 @@ class MSHR(id: Int)(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCach io.wb_req.bits.voluntary := Bool(true) io.mem_acquire.valid := state === s_refill_req && grantackq.io.enq.ready - io.mem_acquire.bits := edge.Acquire( + io.mem_acquire.bits := edge.AcquireBlock( fromSource = UInt(id), toAddress = Cat(io.tag, req_idx) << blockOffBits, lgSize = lgCacheBlockBytes, diff --git a/src/main/scala/rocket/PMP.scala b/src/main/scala/rocket/PMP.scala index 2e277a77..02d69aab 100644 --- a/src/main/scala/rocket/PMP.scala +++ b/src/main/scala/rocket/PMP.scala @@ -127,7 +127,7 @@ class PMPHomogeneityChecker(pmps: Seq[PMP])(implicit p: Parameters) { } class PMPChecker(lgMaxSize: Int)(implicit p: Parameters) extends CoreModule()(p) - with HasRocketCoreParameters { + with HasCoreParameters { val io = new Bundle { val prv = UInt(INPUT, PRV.SZ) val pmp = Vec(nPMPs, new PMP).asInput diff --git a/src/main/scala/rocket/PTW.scala b/src/main/scala/rocket/PTW.scala index 4618715f..70ec7b12 100644 --- a/src/main/scala/rocket/PTW.scala +++ b/src/main/scala/rocket/PTW.scala @@ -24,7 +24,7 @@ class PTWResp(implicit p: Parameters) extends CoreBundle()(p) { } class TLBPTWIO(implicit p: Parameters) extends CoreBundle()(p) - with HasRocketCoreParameters { + with HasCoreParameters { val req = Decoupled(new PTWReq) val resp = Valid(new PTWResp).flip val ptbr = new PTBR().asInput @@ -37,7 +37,7 @@ class PTWPerfEvents extends Bundle { } class DatapathPTWIO(implicit p: Parameters) extends CoreBundle()(p) - with HasRocketCoreParameters { + with HasCoreParameters { val ptbr = new PTBR().asInput val sfence = Valid(new SFenceReq).flip val status = new MStatus().asInput diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index bbed2edd..f5c4b78f 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -23,7 +23,8 @@ case class RocketCoreParams( nBreakpoints: Int = 1, nPMPs: Int = 8, nPerfCounters: Int = 0, - nCustomMRWCSRs: Int = 0, + haveBasicCounters: Boolean = true, + misaWritable: Boolean = true, nL2TLBEntries: Int = 0, mtvecInit: Option[BigInt] = Some(BigInt(0)), mtvecWritable: Boolean = true, @@ -46,12 +47,6 @@ trait HasRocketCoreParameters extends HasCoreParameters { val fastLoadWord = rocketParams.fastLoadWord val fastLoadByte = rocketParams.fastLoadByte - val nBreakpoints = rocketParams.nBreakpoints - val nPMPs = rocketParams.nPMPs - val nPerfCounters = rocketParams.nPerfCounters - val nCustomMrwCsrs = rocketParams.nCustomMRWCSRs - val mtvecInit = rocketParams.mtvecInit - val mtvecWritable = rocketParams.mtvecWritable val mulDivParams = rocketParams.mulDiv.getOrElse(MulDivParams()) // TODO ask andrew about this diff --git a/src/main/scala/system/Configs.scala b/src/main/scala/system/Configs.scala index 187e127f..1d5fe758 100644 --- a/src/main/scala/system/Configs.scala +++ b/src/main/scala/system/Configs.scala @@ -63,9 +63,6 @@ class EightChannelConfig extends Config(new WithNMemoryChannels(8) ++ new BaseCo class DualCoreConfig extends Config( new WithNBigCores(2) ++ new BaseConfig) -class HeterogeneousDualCoreConfig extends Config( - new WithNSmallCores(1) ++ new WithNBigCores(1) ++ new BaseConfig) - class TinyConfig extends Config( new WithNMemoryChannels(0) ++ new WithStatelessBridge ++ diff --git a/src/main/scala/tile/Core.scala b/src/main/scala/tile/Core.scala index da400df9..26e20647 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -25,7 +25,14 @@ trait CoreParams { val retireWidth: Int val instBits: Int val nLocalInterrupts: Int + val nPMPs: Int + val nBreakpoints: Int + val nPerfCounters: Int + val haveBasicCounters: Boolean + val misaWritable: Boolean val nL2TLBEntries: Int + val mtvecInit: Option[BigInt] + val mtvecWritable: Boolean val jumpInFrontend: Boolean val tileControlAddr: Option[BigInt] @@ -47,12 +54,19 @@ trait HasCoreParameters extends HasTileParameters { val fetchWidth = coreParams.fetchWidth val decodeWidth = coreParams.decodeWidth + val fetchBytes = coreParams.fetchBytes val coreInstBits = coreParams.instBits val coreInstBytes = coreInstBits/8 val coreDataBits = xLen max fLen val coreDataBytes = coreDataBits/8 val coreMaxAddrBits = paddrBits max vaddrBitsExtended + val nBreakpoints = coreParams.nBreakpoints + val nPMPs = coreParams.nPMPs + val nPerfCounters = coreParams.nPerfCounters + val mtvecInit = coreParams.mtvecInit + val mtvecWritable = coreParams.mtvecWritable + val coreDCacheReqTagBits = 6 val dcacheReqTagBits = coreDCacheReqTagBits + log2Ceil(dcacheArbPorts) diff --git a/src/main/scala/tile/FPU.scala b/src/main/scala/tile/FPU.scala index 8e89a7f3..f64fbd2c 100644 --- a/src/main/scala/tile/FPU.scala +++ b/src/main/scala/tile/FPU.scala @@ -542,7 +542,72 @@ class FPToFP(val latency: Int)(implicit p: Parameters) extends FPUModule()(p) { io.out <> Pipe(in.valid, mux, latency-1) } +class MulAddRecFNPipe(latency: Int, expWidth: Int, sigWidth: Int) extends Module +{ + require(latency<=2) + + val io = new Bundle { + val validin = Bool(INPUT) + val op = Bits(INPUT, 2) + val a = Bits(INPUT, expWidth + sigWidth + 1) + val b = Bits(INPUT, expWidth + sigWidth + 1) + val c = Bits(INPUT, expWidth + sigWidth + 1) + val roundingMode = UInt(INPUT, 3) + val detectTininess = UInt(INPUT, 1) + val out = Bits(OUTPUT, expWidth + sigWidth + 1) + val exceptionFlags = Bits(OUTPUT, 5) + val validout = Bool(OUTPUT) + } + + //------------------------------------------------------------------------ + //------------------------------------------------------------------------ + val mulAddRecFNToRaw_preMul = + Module(new hardfloat.MulAddRecFNToRaw_preMul(expWidth, sigWidth)) + val mulAddRecFNToRaw_postMul = + Module(new hardfloat.MulAddRecFNToRaw_postMul(expWidth, sigWidth)) + + mulAddRecFNToRaw_preMul.io.op := io.op + mulAddRecFNToRaw_preMul.io.a := io.a + mulAddRecFNToRaw_preMul.io.b := io.b + mulAddRecFNToRaw_preMul.io.c := io.c + + val mulAddResult = + (mulAddRecFNToRaw_preMul.io.mulAddA * + mulAddRecFNToRaw_preMul.io.mulAddB) +& + mulAddRecFNToRaw_preMul.io.mulAddC + + val valid_stage0 = Wire(Bool()) + val roundingMode_stage0 = Wire(UInt(width=3)) + val detectTininess_stage0 = Wire(UInt(width=1)) + + val postmul_regs = if(latency>0) 1 else 0 + mulAddRecFNToRaw_postMul.io.fromPreMul := Pipe(io.validin, mulAddRecFNToRaw_preMul.io.toPostMul, postmul_regs).bits + mulAddRecFNToRaw_postMul.io.mulAddResult := Pipe(io.validin, mulAddResult, postmul_regs).bits + mulAddRecFNToRaw_postMul.io.roundingMode := Pipe(io.validin, io.roundingMode, postmul_regs).bits + roundingMode_stage0 := Pipe(io.validin, io.roundingMode, postmul_regs).bits + detectTininess_stage0 := Pipe(io.validin, io.detectTininess, postmul_regs).bits + valid_stage0 := Pipe(io.validin, false.B, postmul_regs).valid + + //------------------------------------------------------------------------ + //------------------------------------------------------------------------ + val roundRawFNToRecFN = Module(new hardfloat.RoundRawFNToRecFN(expWidth, sigWidth, 0)) + + val round_regs = if(latency==2) 1 else 0 + roundRawFNToRecFN.io.invalidExc := Pipe(valid_stage0, mulAddRecFNToRaw_postMul.io.invalidExc, round_regs).bits + roundRawFNToRecFN.io.in := Pipe(valid_stage0, mulAddRecFNToRaw_postMul.io.rawOut, round_regs).bits + roundRawFNToRecFN.io.roundingMode := Pipe(valid_stage0, roundingMode_stage0, round_regs).bits + roundRawFNToRecFN.io.detectTininess := Pipe(valid_stage0, detectTininess_stage0, round_regs).bits + io.validout := Pipe(valid_stage0, false.B, round_regs).valid + + roundRawFNToRecFN.io.infiniteExc := Bool(false) + + io.out := roundRawFNToRecFN.io.out + io.exceptionFlags := roundRawFNToRecFN.io.exceptionFlags +} + class FPUFMAPipe(val latency: Int, val t: FType)(implicit p: Parameters) extends FPUModule()(p) { + require(latency>0) + val io = new Bundle { val in = Valid(new FPInput).flip val out = Valid(new FPResult) @@ -560,7 +625,8 @@ class FPUFMAPipe(val latency: Int, val t: FType)(implicit p: Parameters) extends when (!(cmd_fma || cmd_addsub)) { in.in3 := zero } } - val fma = Module(new hardfloat.MulAddRecFN(t.exp, t.sig)) + val fma = Module(new MulAddRecFNPipe((latency-1) min 2, t.exp, t.sig)) + fma.io.validin := valid fma.io.op := in.fmaCmd fma.io.roundingMode := in.rm fma.io.detectTininess := hardfloat.consts.tininess_afterRounding @@ -571,7 +637,8 @@ class FPUFMAPipe(val latency: Int, val t: FType)(implicit p: Parameters) extends val res = Wire(new FPResult) res.data := sanitizeNaN(fma.io.out, t) res.exc := fma.io.exceptionFlags - io.out := Pipe(valid, res, latency-1) + + io.out := Pipe(fma.io.validout, res, (latency-3) max 0) } class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { diff --git a/src/main/scala/tile/RocketTile.scala b/src/main/scala/tile/RocketTile.scala index b9aaa542..9d9b7b94 100644 --- a/src/main/scala/tile/RocketTile.scala +++ b/src/main/scala/tile/RocketTile.scala @@ -22,13 +22,14 @@ case class RocketTileParams( trace: Boolean = false, hcfOnUncorrectable: Boolean = false, name: Option[String] = Some("tile"), + hartid: Int = 0, externalMasterBuffers: Int = 0, externalSlaveBuffers: Int = 0) extends TileParams { require(icache.isDefined) require(dcache.isDefined) } -class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p: Parameters) extends BaseTile(rocketParams)(p) +class RocketTile(val rocketParams: RocketTileParams)(implicit p: Parameters) extends BaseTile(rocketParams)(p) with HasExternalInterrupts with HasLazyRoCC // implies CanHaveSharedFPU with CanHavePTW with HasHellaCache with CanHaveScratchpad { // implies CanHavePTW with HasHellaCache with HasICacheFrontend @@ -39,6 +40,7 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p private def ofStr(x: String) = Seq(ResourceString(x)) private def ofRef(x: Device) = Seq(ResourceReference(x.label)) + val hartid = rocketParams.hartid val cpuDevice = new Device { def describe(resources: ResourceBindings): Description = { val block = p(CacheBlockBytes) @@ -179,8 +181,8 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne ptw.io.requestor <> ptwPorts } -abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends LazyModule { - val rocket = LazyModule(new RocketTile(rtp, hartid)) +abstract class RocketTileWrapper(rtp: RocketTileParams)(implicit p: Parameters) extends LazyModule { + val rocket = LazyModule(new RocketTile(rtp)) val asyncIntNode : IntInwardNode val periphIntNode : IntInwardNode val coreIntNode : IntInwardNode @@ -226,7 +228,7 @@ abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p: } } -class SyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) { +class SyncRocketTile(rtp: RocketTileParams)(implicit p: Parameters) extends RocketTileWrapper(rtp) { val masterNode = optionalMasterBuffer(rocket.masterNode) val slaveNode = optionalSlaveBuffer(rocket.slaveNode) @@ -246,7 +248,7 @@ class SyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) def outputInterruptXingLatency = 0 } -class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) { +class AsyncRocketTile(rtp: RocketTileParams)(implicit p: Parameters) extends RocketTileWrapper(rtp) { val source = LazyModule(new TLAsyncCrossingSource) source.node :=* rocket.masterNode val masterNode = source.node @@ -272,7 +274,7 @@ class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters def outputInterruptXingLatency = 3 } -class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) { +class RationalRocketTile(rtp: RocketTileParams)(implicit p: Parameters) extends RocketTileWrapper(rtp) { val source = LazyModule(new TLRationalCrossingSource) source.node :=* optionalMasterBuffer(rocket.masterNode) val masterNode = source.node diff --git a/src/main/scala/tilelink/Atomics.scala b/src/main/scala/tilelink/Atomics.scala index 5f412cc6..370817a3 100644 --- a/src/main/scala/tilelink/Atomics.scala +++ b/src/main/scala/tilelink/Atomics.scala @@ -51,8 +51,8 @@ class Atomics(params: TLBundleParameters) extends Module UInt(3), // LogicalData UInt(0), // Get UInt(0), // Hint - UInt(0), // Acquire - UInt(0)))( // Overwrite + UInt(0), // AcquireBlock + UInt(0)))( // AcquirePerm io.a.opcode)) // Only the masked bytes can be modified diff --git a/src/main/scala/tilelink/Broadcast.scala b/src/main/scala/tilelink/Broadcast.scala index 3e203a13..4681b8f3 100644 --- a/src/main/scala/tilelink/Broadcast.scala +++ b/src/main/scala/tilelink/Broadcast.scala @@ -176,6 +176,11 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa t.probe := (if (caches.size == 0) UInt(0) else Mux(a_cache.orR(), UInt(caches.size-1), UInt(caches.size))) } + val acq_perms = MuxLookup(in.a.bits.param, Wire(UInt(width = 2)), Array( + TLPermissions.NtoB -> TLPermissions.toB, + TLPermissions.NtoT -> TLPermissions.toN, + TLPermissions.BtoT -> TLPermissions.toN)) + when (in.a.fire() && a_first) { probe_todo := ~a_cache // probe all but the cache who poked us probe_line := in.a.bits.address >> lineShift @@ -188,10 +193,8 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa TLMessages.Hint -> MuxLookup(in.a.bits.param, Wire(UInt(width = 2)), Array( TLHints.PREFETCH_READ -> TLPermissions.toB, TLHints.PREFETCH_WRITE -> TLPermissions.toN)), - TLMessages.Acquire -> MuxLookup(in.a.bits.param, Wire(UInt(width = 2)), Array( - TLPermissions.NtoB -> TLPermissions.toB, - TLPermissions.NtoT -> TLPermissions.toN, - TLPermissions.BtoT -> TLPermissions.toN)))) + TLMessages.AcquireBlock -> acq_perms, + TLMessages.AcquirePerm -> acq_perms)) } // The outer TL connections may not be cached @@ -236,7 +239,7 @@ class TLBroadcastTracker(id: Int, lineBytes: Int, probeCountBits: Int, bufferles when (io.in_a.fire() && io.in_a_first) { assert (idle) sent_d := Bool(false) - got_e := io.in_a.bits.opcode =/= TLMessages.Acquire + got_e := io.in_a.bits.opcode =/= TLMessages.AcquireBlock && io.in_a.bits.opcode =/= TLMessages.AcquirePerm opcode := io.in_a.bits.opcode param := io.in_a.bits.param size := io.in_a.bits.size @@ -271,7 +274,7 @@ class TLBroadcastTracker(id: Int, lineBytes: Int, probeCountBits: Int, bufferles i_data.bits.data := io.in_a.bits.data val probe_done = count === UInt(0) - val acquire = opcode === TLMessages.Acquire + val acquire = opcode === TLMessages.AcquireBlock || opcode === TLMessages.AcquirePerm val transform = MuxLookup(param, Wire(UInt(width = 2)), Array( TLPermissions.NtoB -> TRANSFORM_B, diff --git a/src/main/scala/tilelink/Bundles.scala b/src/main/scala/tilelink/Bundles.scala index d58bc907..118b01e5 100644 --- a/src/main/scala/tilelink/Bundles.scala +++ b/src/main/scala/tilelink/Bundles.scala @@ -22,7 +22,8 @@ object TLMessages def LogicalData = UInt(3) // . . => AccessAckData def Get = UInt(4) // . . => AccessAckData def Hint = UInt(5) // . . => HintAck - def Acquire = UInt(6) // . => Grant[Data] + def AcquireBlock = UInt(6) // . => Grant[Data] + def AcquirePerm = UInt(7) // . => Grant[Data] def Probe = UInt(6) // . => ProbeAck[Data] def AccessAck = UInt(0) // . . def AccessAckData = UInt(1) // . . @@ -36,7 +37,7 @@ object TLMessages def ReleaseAck = UInt(6) // . def GrantAck = UInt(0) // . - def isA(x: UInt) = x <= Acquire + def isA(x: UInt) = x <= AcquirePerm def isB(x: UInt) = x <= Probe def isC(x: UInt) = x <= ReleaseData def isD(x: UInt) = x <= ReleaseAck diff --git a/src/main/scala/tilelink/CacheCork.scala b/src/main/scala/tilelink/CacheCork.scala index 9503e97d..063c58a4 100644 --- a/src/main/scala/tilelink/CacheCork.scala +++ b/src/main/scala/tilelink/CacheCork.scala @@ -47,7 +47,8 @@ class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyM val a_a = Wire(out.a) val a_d = Wire(in.d) val isPut = in.a.bits.opcode === PutFullData || in.a.bits.opcode === PutPartialData - val toD = in.a.bits.opcode === Acquire && in.a.bits.param === TLPermissions.BtoT + val toD = (in.a.bits.opcode === AcquireBlock && in.a.bits.param === TLPermissions.BtoT) || + (in.a.bits.opcode === AcquirePerm) in.a.ready := Mux(toD, a_d.ready, a_a.ready) a_a.valid := in.a.valid && !toD @@ -55,7 +56,7 @@ class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyM a_a.bits.source := in.a.bits.source << 1 | Mux(isPut, UInt(1), UInt(0)) // Transform Acquire into Get - when (in.a.bits.opcode === Acquire) { + when (in.a.bits.opcode === AcquireBlock || in.a.bits.opcode === AcquirePerm) { a_a.bits.opcode := Get a_a.bits.param := UInt(0) a_a.bits.source := in.a.bits.source << 1 | UInt(1) @@ -100,10 +101,7 @@ class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyM when (out.d.bits.opcode === AccessAckData && out.d.bits.source(0)) { d_d.bits.opcode := GrantData - // On Grant error, you do NOT get the permissions you asked for. - // We only enter this case from NtoT or NtoB, so that means use toN. - // (the BtoT case was handled by a_d) - d_d.bits.param := Mux(out.d.bits.error, TLPermissions.toN, TLPermissions.toT) + d_d.bits.param := TLPermissions.toT } when (out.d.bits.opcode === AccessAck && !out.d.bits.source(0)) { d_d.bits.opcode := ReleaseAck diff --git a/src/main/scala/tilelink/Edges.scala b/src/main/scala/tilelink/Edges.scala index 55c21711..4f59c9a3 100644 --- a/src/main/scala/tilelink/Edges.scala +++ b/src/main/scala/tilelink/Edges.scala @@ -271,11 +271,25 @@ class TLEdgeOut( extends TLEdge(client, manager, params, sourceInfo) { // Transfers - def Acquire(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = { + def AcquireBlock(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = { require (manager.anySupportAcquireB) val legal = manager.supportsAcquireBFast(toAddress, lgSize) val a = Wire(new TLBundleA(bundle)) - a.opcode := TLMessages.Acquire + a.opcode := TLMessages.AcquireBlock + a.param := growPermissions + a.size := lgSize + a.source := fromSource + a.address := toAddress + a.mask := mask(toAddress, lgSize) + a.data := UInt(0) + (legal, a) + } + + def AcquirePerm(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = { + require (manager.anySupportAcquireB) + val legal = manager.supportsAcquireBFast(toAddress, lgSize) + val a = Wire(new TLBundleA(bundle)) + a.opcode := TLMessages.AcquirePerm a.param := growPermissions a.size := lgSize a.source := fromSource diff --git a/src/main/scala/tilelink/Monitor.scala b/src/main/scala/tilelink/Monitor.scala index 11ddd0ec..9b258684 100644 --- a/src/main/scala/tilelink/Monitor.scala +++ b/src/main/scala/tilelink/Monitor.scala @@ -37,14 +37,25 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args) val is_aligned = edge.isAligned(bundle.address, bundle.size) val mask = edge.full_mask(bundle) - when (bundle.opcode === TLMessages.Acquire) { - assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'A' channel carries Acquire type unsupported by manager" + extra) - assert (edge.client.supportsProbe(edge.source(bundle), bundle.size), "'A' channel carries Acquire from a client which does not support Probe" + extra) - assert (source_ok, "'A' channel Acquire carries invalid source ID" + extra) - assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel Acquire smaller than a beat" + extra) - assert (is_aligned, "'A' channel Acquire address not aligned to size" + extra) - assert (TLPermissions.isGrow(bundle.param), "'A' channel Acquire carries invalid grow param" + extra) - assert (~bundle.mask === UInt(0), "'A' channel Acquire contains invalid mask" + extra) + when (bundle.opcode === TLMessages.AcquireBlock) { + assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'A' channel carries AcquireBlock type unsupported by manager" + extra) + assert (edge.client.supportsProbe(edge.source(bundle), bundle.size), "'A' channel carries AcquireBlock from a client which does not support Probe" + extra) + assert (source_ok, "'A' channel AcquireBlock carries invalid source ID" + extra) + assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel AcquireBlock smaller than a beat" + extra) + assert (is_aligned, "'A' channel AcquireBlock address not aligned to size" + extra) + assert (TLPermissions.isGrow(bundle.param), "'A' channel AcquireBlock carries invalid grow param" + extra) + assert (~bundle.mask === UInt(0), "'A' channel AcquireBlock contains invalid mask" + extra) + } + + when (bundle.opcode === TLMessages.AcquirePerm) { + assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'A' channel carries AcquirePerm type unsupported by manager" + extra) + assert (edge.client.supportsProbe(edge.source(bundle), bundle.size), "'A' channel carries AcquirePerm from a client which does not support Probe" + extra) + assert (source_ok, "'A' channel AcquirePerm carries invalid source ID" + extra) + assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel AcquirePerm smaller than a beat" + extra) + assert (is_aligned, "'A' channel AcquirePerm address not aligned to size" + extra) + assert (TLPermissions.isGrow(bundle.param), "'A' channel AcquirePerm carries invalid grow param" + extra) + assert (bundle.param =/= TLPermissions.NtoB, "'A' channel AcquirePerm requests NtoB" + extra) + assert (~bundle.mask === UInt(0), "'A' channel AcquirePerm contains invalid mask" + extra) } when (bundle.opcode === TLMessages.Get) { diff --git a/src/main/scala/tilelink/RAMModel.scala b/src/main/scala/tilelink/RAMModel.scala index c121c002..21c5cf14 100644 --- a/src/main/scala/tilelink/RAMModel.scala +++ b/src/main/scala/tilelink/RAMModel.scala @@ -116,7 +116,7 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule when (a_fire) { // Record the request so we can handle it's response - assert (a.opcode =/= TLMessages.Acquire) + assert (a.opcode =/= TLMessages.AcquireBlock && a.opcode =/= TLMessages.AcquirePerm) // Mark the operation as valid valid(a.source) := Bool(true)