Merge remote-tracking branch 'origin/master' into HEAD
This commit is contained in:
commit
9efe1c448e
@ -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))
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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,6 +372,10 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
|
||||
if (usingFPU)
|
||||
read_mapping ++= fp_csrs
|
||||
|
||||
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
|
||||
@ -383,6 +387,22 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (usingVM) {
|
||||
val read_sie = reg_mie & reg_mideleg
|
||||
val read_sip = read_mip & reg_mideleg
|
||||
@ -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,6 +609,7 @@ 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')
|
||||
if (coreParams.misaWritable)
|
||||
reg_misa := ~(~wdata | (!f << ('d' - 'a'))) & mask | reg_misa & ~mask
|
||||
}
|
||||
when (decoded_addr(CSRs.mip)) {
|
||||
@ -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) }
|
||||
}
|
||||
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
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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)) }
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 ++
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user