From a2dc13669a3001f5024426eda36ed4c4df8b7ceb Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 2 Oct 2017 14:49:25 -0700 Subject: [PATCH 01/17] Error grants (#1025) * CacheCork: an error Grant still says 'toT' even though it is transient Grants with errors must be handled by a client as though no actual permissions were obtained, so that two clients do not both end up believing that they own a block which is only temporarily offline. However, the Grant MESSAGE should still match the request; ie. if you did Acquire.NtoT, the response must be Grant.toT, even though the 'error' bit signals that the Grant actually grants no permissions. This keeps the implementation of request-response tracking in interstitial adapters and FSMs simple, consistent with the way multibeat errors must include all their beats. * Error: handle permissions properly --- src/main/scala/devices/tilelink/Error.scala | 4 ++-- src/main/scala/tilelink/CacheCork.scala | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) 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/tilelink/CacheCork.scala b/src/main/scala/tilelink/CacheCork.scala index 9503e97d..de52286f 100644 --- a/src/main/scala/tilelink/CacheCork.scala +++ b/src/main/scala/tilelink/CacheCork.scala @@ -100,10 +100,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 From cedfb0e784d4a6fac5346a77e7fc1ad069948b7d Mon Sep 17 00:00:00 2001 From: Henry Cook Date: Mon, 2 Oct 2017 17:41:52 -0700 Subject: [PATCH 02/17] coreplex: dontTouch the rocket_tile_inputs wire which contains hartid. --- src/main/scala/coreplex/RocketCoreplex.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/scala/coreplex/RocketCoreplex.scala b/src/main/scala/coreplex/RocketCoreplex.scala index b4992a3c..e0db5333 100644 --- a/src/main/scala/coreplex/RocketCoreplex.scala +++ b/src/main/scala/coreplex/RocketCoreplex.scala @@ -3,6 +3,7 @@ package freechips.rocketchip.coreplex import Chisel._ +import chisel3.experimental.dontTouch import freechips.rocketchip.config.{Field, Parameters} import freechips.rocketchip.devices.tilelink._ import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp} @@ -110,9 +111,9 @@ trait HasRocketTilesModuleImp extends LazyModuleImp // TODO make this less gross and/or support tiles with differently sized reset vectors def resetVectorBits: Int = outer.paddrBits - val rocket_tile_inputs = Wire(Vec(outer.nRocketTiles, new ClockedRocketTileInputs()(p.alterPartial { + val rocket_tile_inputs = dontTouch(Wire(Vec(outer.nRocketTiles, new ClockedRocketTileInputs()(p.alterPartial { case SharedMemoryTLEdge => outer.sharedMemoryTLEdge - }))) + })))) // dontTouch keeps constant prop from sucking these signals into the tile // Unconditionally wire up the non-diplomatic tile inputs outer.rocket_tiles.map(_.module).zip(rocket_tile_inputs).foreach { case(tile, wire) => @@ -126,7 +127,7 @@ trait HasRocketTilesModuleImp extends LazyModuleImp rocket_tile_inputs.zipWithIndex.foreach { case(wire, i) => wire.clock := clock wire.reset := reset - wire.hartid := UInt(i) + wire.hartid := i.U wire.reset_vector := global_reset_vector } } From aa3a18222c9a3348e4ffe9543d9cacd3ca468273 Mon Sep 17 00:00:00 2001 From: Henry Cook Date: Mon, 2 Oct 2017 19:01:05 -0700 Subject: [PATCH 03/17] HellaCache: users like to peep resp.data and resp.addr --- src/main/scala/rocket/HellaCache.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/scala/rocket/HellaCache.scala b/src/main/scala/rocket/HellaCache.scala index 558e0259..ae316ee4 100644 --- a/src/main/scala/rocket/HellaCache.scala +++ b/src/main/scala/rocket/HellaCache.scala @@ -4,6 +4,7 @@ package freechips.rocketchip.rocket import Chisel._ +import chisel3.experimental.dontTouch import freechips.rocketchip.config.{Parameters, Field} import freechips.rocketchip.coreplex._ import freechips.rocketchip.diplomacy._ @@ -184,6 +185,7 @@ class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer) implicit val edge = outer.node.edges.out(0) val (tl_out, _) = outer.node.out(0) val io = IO(new HellaCacheBundle(outer)) + dontTouch(io.cpu.resp) // Users like to monitor these fields even if the core ignores some private val fifoManagers = edge.manager.managers.filter(TLFIFOFixer.allUncacheable) fifoManagers.foreach { m => From d33737802a0678a1d284dfcea057e799ef897ab9 Mon Sep 17 00:00:00 2001 From: Henry Cook Date: Mon, 2 Oct 2017 19:34:51 -0700 Subject: [PATCH 04/17] util: add DontTouch trait with dontTouchPorts method --- src/main/scala/system/ExampleRocketSystem.scala | 2 ++ src/main/scala/system/TestHarness.scala | 1 + src/main/scala/util/Misc.scala | 16 ++++++++++++++++ 3 files changed, 19 insertions(+) diff --git a/src/main/scala/system/ExampleRocketSystem.scala b/src/main/scala/system/ExampleRocketSystem.scala index f15c297b..981f7a0d 100644 --- a/src/main/scala/system/ExampleRocketSystem.scala +++ b/src/main/scala/system/ExampleRocketSystem.scala @@ -6,6 +6,7 @@ import Chisel._ import freechips.rocketchip.config.Parameters import freechips.rocketchip.coreplex._ import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.util.DontTouch /** Example Top with periphery devices and ports, and a Rocket coreplex */ class ExampleRocketSystem(implicit p: Parameters) extends RocketCoreplex @@ -25,3 +26,4 @@ class ExampleRocketSystemModule[+L <: ExampleRocketSystem](_outer: L) extends Ro with HasMasterAXI4MMIOPortModuleImp with HasSlaveAXI4PortModuleImp with HasPeripheryBootROMModuleImp + with DontTouch diff --git a/src/main/scala/system/TestHarness.scala b/src/main/scala/system/TestHarness.scala index e8accb7f..79903b32 100644 --- a/src/main/scala/system/TestHarness.scala +++ b/src/main/scala/system/TestHarness.scala @@ -14,6 +14,7 @@ class TestHarness()(implicit p: Parameters) extends Module { val dut = Module(LazyModule(new ExampleRocketSystem).module) dut.reset := reset | dut.debug.ndreset + dut.dontTouchPorts() dut.tieOffInterrupts() dut.connectSimAXIMem() dut.connectSimAXIMMIO() diff --git a/src/main/scala/util/Misc.scala b/src/main/scala/util/Misc.scala index 86590d1b..8ff24fb9 100644 --- a/src/main/scala/util/Misc.scala +++ b/src/main/scala/util/Misc.scala @@ -4,6 +4,7 @@ package freechips.rocketchip.util import Chisel._ +import chisel3.experimental.{dontTouch, RawModule} import freechips.rocketchip.config.Parameters import scala.math._ @@ -21,6 +22,21 @@ class ParameterizedBundle(implicit p: Parameters) extends Bundle { } } +// TODO: replace this with an implicit class when @chisel unprotects dontTouchPorts +trait DontTouch { + self: RawModule => + + /** Marks every port as don't touch + * + * @note This method can only be called after the Module has been fully constructed + * (after Module(...)) + */ + def dontTouchPorts(): this.type = { + self.getModulePorts.foreach(dontTouch(_)) + self + } +} + trait Clocked extends Bundle { val clock = Clock() val reset = Bool() From 190d5c50d9fa76a6408dcda76d8e5568f08907ea Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 20 Sep 2017 13:43:25 -0700 Subject: [PATCH 05/17] Remove deprecated custom-CSR support --- src/main/scala/rocket/CSR.scala | 8 -------- src/main/scala/rocket/RocketCore.scala | 2 -- 2 files changed, 10 deletions(-) diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index c3a05712..a8371c0b 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -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) @@ -438,13 +437,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) diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index bbed2edd..ae0d251b 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -23,7 +23,6 @@ case class RocketCoreParams( nBreakpoints: Int = 1, nPMPs: Int = 8, nPerfCounters: Int = 0, - nCustomMRWCSRs: Int = 0, nL2TLBEntries: Int = 0, mtvecInit: Option[BigInt] = Some(BigInt(0)), mtvecWritable: Boolean = true, @@ -49,7 +48,6 @@ trait HasRocketCoreParameters extends HasCoreParameters { val nBreakpoints = rocketParams.nBreakpoints val nPMPs = rocketParams.nPMPs val nPerfCounters = rocketParams.nPerfCounters - val nCustomMrwCsrs = rocketParams.nCustomMRWCSRs val mtvecInit = rocketParams.mtvecInit val mtvecWritable = rocketParams.mtvecWritable From ab0821f25b1ceadb40ae58b8e6744963beeeb320 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 20 Sep 2017 14:04:13 -0700 Subject: [PATCH 06/17] Move microarchitecture-neutral params from Rocket to Core This makes some of the units more reusable. --- src/main/scala/rocket/CSR.scala | 8 ++++---- src/main/scala/rocket/PMP.scala | 2 +- src/main/scala/rocket/PTW.scala | 4 ++-- src/main/scala/rocket/RocketCore.scala | 5 ----- src/main/scala/tile/Core.scala | 11 +++++++++++ 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index a8371c0b..989b665a 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 { @@ -207,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)) 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 ae0d251b..9e010def 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -45,11 +45,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 mtvecInit = rocketParams.mtvecInit - val mtvecWritable = rocketParams.mtvecWritable val mulDivParams = rocketParams.mulDiv.getOrElse(MulDivParams()) // TODO ask andrew about this diff --git a/src/main/scala/tile/Core.scala b/src/main/scala/tile/Core.scala index da400df9..9decc107 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -25,7 +25,12 @@ trait CoreParams { val retireWidth: Int val instBits: Int val nLocalInterrupts: Int + val nPMPs: Int + val nBreakpoints: Int + val nPerfCounters: Int val nL2TLBEntries: Int + val mtvecInit: Option[BigInt] + val mtvecWritable: Boolean val jumpInFrontend: Boolean val tileControlAddr: Option[BigInt] @@ -53,6 +58,12 @@ trait HasCoreParameters extends HasTileParameters { 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) From 09468a272b52e45a92fe98bb348f9d1cd5f2bb5b Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 20 Sep 2017 19:15:36 -0700 Subject: [PATCH 07/17] Add option to remove basic counters (mcycle/minstret) --- src/main/scala/rocket/CSR.scala | 57 ++++++++++++++------------ src/main/scala/rocket/RocketCore.scala | 1 + src/main/scala/tile/Core.scala | 1 + 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index 989b665a..08e88cc1 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -342,8 +342,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, @@ -371,14 +369,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) + } } } @@ -411,21 +429,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) { @@ -629,8 +632,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 } diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index 9e010def..fa6ea5a8 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -23,6 +23,7 @@ case class RocketCoreParams( nBreakpoints: Int = 1, nPMPs: Int = 8, nPerfCounters: Int = 0, + haveBasicCounters: Boolean = true, nL2TLBEntries: Int = 0, mtvecInit: Option[BigInt] = Some(BigInt(0)), mtvecWritable: Boolean = true, diff --git a/src/main/scala/tile/Core.scala b/src/main/scala/tile/Core.scala index 9decc107..21b887af 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -28,6 +28,7 @@ trait CoreParams { val nPMPs: Int val nBreakpoints: Int val nPerfCounters: Int + val haveBasicCounters: Boolean val nL2TLBEntries: Int val mtvecInit: Option[BigInt] val mtvecWritable: Boolean From 5cfe070932ca3a50ab4e42835a991241cc42238c Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 20 Sep 2017 19:16:34 -0700 Subject: [PATCH 08/17] Add option to make misa read-only --- src/main/scala/rocket/CSR.scala | 3 ++- src/main/scala/rocket/RocketCore.scala | 1 + src/main/scala/tile/Core.scala | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index 08e88cc1..421b41f7 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -606,7 +606,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 diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index fa6ea5a8..f5c4b78f 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -24,6 +24,7 @@ case class RocketCoreParams( nPMPs: Int = 8, nPerfCounters: Int = 0, haveBasicCounters: Boolean = true, + misaWritable: Boolean = true, nL2TLBEntries: Int = 0, mtvecInit: Option[BigInt] = Some(BigInt(0)), mtvecWritable: Boolean = true, diff --git a/src/main/scala/tile/Core.scala b/src/main/scala/tile/Core.scala index 21b887af..a914d6ef 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -29,6 +29,7 @@ trait CoreParams { val nBreakpoints: Int val nPerfCounters: Int val haveBasicCounters: Boolean + val misaWritable: Boolean val nL2TLBEntries: Int val mtvecInit: Option[BigInt] val mtvecWritable: Boolean From 2786e42d994c504c1e54810187121ddad604882f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 29 Sep 2017 12:30:32 -0700 Subject: [PATCH 09/17] Don't register interrupts in CSRFile They are usually registered outside the tile in a CDC. --- src/main/scala/rocket/CSR.scala | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index 421b41f7..ab136f95 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -222,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) @@ -304,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)) @@ -506,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 } @@ -719,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 From 7bcf28c5853484687828c74ecd9e0750aee8429b Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 29 Sep 2017 12:31:26 -0700 Subject: [PATCH 10/17] Define fetchBytes in HasCoreParams, not Frontend It is more generally useful. --- src/main/scala/rocket/Frontend.scala | 1 - src/main/scala/tile/Core.scala | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) 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/tile/Core.scala b/src/main/scala/tile/Core.scala index a914d6ef..26e20647 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -54,6 +54,7 @@ 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 From 32fda51a2c1877f4aa5fdc7834e0212bf0ec49db Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 4 Oct 2017 12:11:37 -0700 Subject: [PATCH 11/17] Get rid of paddrBits from SystemBus (#1029) --- src/main/scala/coreplex/RocketCoreplex.scala | 8 ++++++-- src/main/scala/coreplex/SystemBus.scala | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/scala/coreplex/RocketCoreplex.scala b/src/main/scala/coreplex/RocketCoreplex.scala index e0db5333..211ccaa5 100644 --- a/src/main/scala/coreplex/RocketCoreplex.scala +++ b/src/main/scala/coreplex/RocketCoreplex.scala @@ -109,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 = dontTouch(Wire(Vec(outer.nRocketTiles, new ClockedRocketTileInputs()(p.alterPartial { case SharedMemoryTLEdge => outer.sharedMemoryTLEdge })))) // dontTouch keeps constant prop from sucking these signals into the tile 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 } From 45581e60f03b0255c3a663c2ea96e1e9d1bbbc20 Mon Sep 17 00:00:00 2001 From: Henry Cook Date: Thu, 5 Oct 2017 00:26:44 -0700 Subject: [PATCH 12/17] Revert "Merge pull request #1027 from freechipsproject/dont-touch-hartid" This reverts commit 5232a29d7d838ef95d33bfcd2a6fbfde8a82af35, reversing changes made to a2dc13669a3001f5024426eda36ed4c4df8b7ceb. --- src/main/scala/coreplex/RocketCoreplex.scala | 7 +++---- src/main/scala/rocket/HellaCache.scala | 2 -- src/main/scala/system/ExampleRocketSystem.scala | 2 -- src/main/scala/system/TestHarness.scala | 1 - src/main/scala/util/Misc.scala | 16 ---------------- 5 files changed, 3 insertions(+), 25 deletions(-) diff --git a/src/main/scala/coreplex/RocketCoreplex.scala b/src/main/scala/coreplex/RocketCoreplex.scala index 211ccaa5..c106052b 100644 --- a/src/main/scala/coreplex/RocketCoreplex.scala +++ b/src/main/scala/coreplex/RocketCoreplex.scala @@ -3,7 +3,6 @@ package freechips.rocketchip.coreplex import Chisel._ -import chisel3.experimental.dontTouch import freechips.rocketchip.config.{Field, Parameters} import freechips.rocketchip.devices.tilelink._ import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp} @@ -115,9 +114,9 @@ trait HasRocketTilesModuleImp extends LazyModuleImp require(vectors.tail.forall(_.getWidth == vectors.head.getWidth)) vectors.head.getWidth } - val rocket_tile_inputs = dontTouch(Wire(Vec(outer.nRocketTiles, new ClockedRocketTileInputs()(p.alterPartial { + val rocket_tile_inputs = Wire(Vec(outer.nRocketTiles, new ClockedRocketTileInputs()(p.alterPartial { case SharedMemoryTLEdge => outer.sharedMemoryTLEdge - })))) // dontTouch keeps constant prop from sucking these signals into the tile + }))) // Unconditionally wire up the non-diplomatic tile inputs outer.rocket_tiles.map(_.module).zip(rocket_tile_inputs).foreach { case(tile, wire) => @@ -131,7 +130,7 @@ trait HasRocketTilesModuleImp extends LazyModuleImp rocket_tile_inputs.zipWithIndex.foreach { case(wire, i) => wire.clock := clock wire.reset := reset - wire.hartid := i.U + wire.hartid := UInt(i) wire.reset_vector := global_reset_vector } } diff --git a/src/main/scala/rocket/HellaCache.scala b/src/main/scala/rocket/HellaCache.scala index ae316ee4..558e0259 100644 --- a/src/main/scala/rocket/HellaCache.scala +++ b/src/main/scala/rocket/HellaCache.scala @@ -4,7 +4,6 @@ package freechips.rocketchip.rocket import Chisel._ -import chisel3.experimental.dontTouch import freechips.rocketchip.config.{Parameters, Field} import freechips.rocketchip.coreplex._ import freechips.rocketchip.diplomacy._ @@ -185,7 +184,6 @@ class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer) implicit val edge = outer.node.edges.out(0) val (tl_out, _) = outer.node.out(0) val io = IO(new HellaCacheBundle(outer)) - dontTouch(io.cpu.resp) // Users like to monitor these fields even if the core ignores some private val fifoManagers = edge.manager.managers.filter(TLFIFOFixer.allUncacheable) fifoManagers.foreach { m => diff --git a/src/main/scala/system/ExampleRocketSystem.scala b/src/main/scala/system/ExampleRocketSystem.scala index 981f7a0d..f15c297b 100644 --- a/src/main/scala/system/ExampleRocketSystem.scala +++ b/src/main/scala/system/ExampleRocketSystem.scala @@ -6,7 +6,6 @@ import Chisel._ import freechips.rocketchip.config.Parameters import freechips.rocketchip.coreplex._ import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.util.DontTouch /** Example Top with periphery devices and ports, and a Rocket coreplex */ class ExampleRocketSystem(implicit p: Parameters) extends RocketCoreplex @@ -26,4 +25,3 @@ class ExampleRocketSystemModule[+L <: ExampleRocketSystem](_outer: L) extends Ro with HasMasterAXI4MMIOPortModuleImp with HasSlaveAXI4PortModuleImp with HasPeripheryBootROMModuleImp - with DontTouch diff --git a/src/main/scala/system/TestHarness.scala b/src/main/scala/system/TestHarness.scala index 79903b32..e8accb7f 100644 --- a/src/main/scala/system/TestHarness.scala +++ b/src/main/scala/system/TestHarness.scala @@ -14,7 +14,6 @@ class TestHarness()(implicit p: Parameters) extends Module { val dut = Module(LazyModule(new ExampleRocketSystem).module) dut.reset := reset | dut.debug.ndreset - dut.dontTouchPorts() dut.tieOffInterrupts() dut.connectSimAXIMem() dut.connectSimAXIMMIO() diff --git a/src/main/scala/util/Misc.scala b/src/main/scala/util/Misc.scala index 8ff24fb9..86590d1b 100644 --- a/src/main/scala/util/Misc.scala +++ b/src/main/scala/util/Misc.scala @@ -4,7 +4,6 @@ package freechips.rocketchip.util import Chisel._ -import chisel3.experimental.{dontTouch, RawModule} import freechips.rocketchip.config.Parameters import scala.math._ @@ -22,21 +21,6 @@ class ParameterizedBundle(implicit p: Parameters) extends Bundle { } } -// TODO: replace this with an implicit class when @chisel unprotects dontTouchPorts -trait DontTouch { - self: RawModule => - - /** Marks every port as don't touch - * - * @note This method can only be called after the Module has been fully constructed - * (after Module(...)) - */ - def dontTouchPorts(): this.type = { - self.getModulePorts.foreach(dontTouch(_)) - self - } -} - trait Clocked extends Bundle { val clock = Clock() val reset = Bool() From 8da7aabd51a1b5199b49ec1127f454ed1869b2b8 Mon Sep 17 00:00:00 2001 From: Henry Cook Date: Thu, 5 Oct 2017 00:31:53 -0700 Subject: [PATCH 13/17] tile: supply hartid from RocketTileParams make WithNCores partial configs override rather than append more tiles --- src/main/scala/coreplex/Configs.scala | 6 +++--- src/main/scala/coreplex/RocketCoreplex.scala | 13 +++++++------ src/main/scala/system/Configs.scala | 3 --- src/main/scala/tile/RocketTile.scala | 14 ++++++++------ 4 files changed, 18 insertions(+), 18 deletions(-) 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 c106052b..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 @@ -127,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/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/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 From 81b9ac42a3a93ee28344030976a77145ffb70b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wei=20Song=20=28=E5=AE=8B=E5=A8=81=29?= Date: Thu, 5 Oct 2017 20:45:56 +0100 Subject: [PATCH 14/17] add comments to diplomacy resource. (#913) --- src/main/scala/diplomacy/Resources.scala | 58 +++++++++++++++++++++--- 1 file changed, 52 insertions(+), 6 deletions(-) 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") From bd045a3b95979b3c5dec7fc663671bc7c5b1f23b Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 5 Oct 2017 12:49:49 -0700 Subject: [PATCH 15/17] tilelink: split Acquire into Acquire{Block,Perm} (#1030) We had planned for a while to add an 'Overwrite' message which obtains permissions without requiring retrieval of data. This is useful whenever a master knows it will completely replace the contents of a cache block. Instead of calling it Overwrite, we decided to split the Acquire type. If you AcquirePerm, you MUST Release and ProbeAck with Data. --- src/main/scala/rocket/DCache.scala | 2 +- src/main/scala/rocket/NBDcache.scala | 2 +- src/main/scala/tilelink/Atomics.scala | 4 ++-- src/main/scala/tilelink/Broadcast.scala | 15 ++++++++------ src/main/scala/tilelink/Bundles.scala | 5 +++-- src/main/scala/tilelink/CacheCork.scala | 5 +++-- src/main/scala/tilelink/Edges.scala | 18 +++++++++++++++-- src/main/scala/tilelink/Monitor.scala | 27 +++++++++++++++++-------- src/main/scala/tilelink/RAMModel.scala | 2 +- 9 files changed, 55 insertions(+), 25 deletions(-) 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/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/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 de52286f..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) 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) From 7a46715cbc919687ea208dd6247049a049d740bf Mon Sep 17 00:00:00 2001 From: Henry Styles Date: Thu, 28 Sep 2017 18:34:28 -0700 Subject: [PATCH 16/17] FPU : to assist retiming move upto first 2 register stages of into FMA --- src/main/scala/tile/FPU.scala | 86 ++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/src/main/scala/tile/FPU.scala b/src/main/scala/tile/FPU.scala index 8e89a7f3..1c990777 100644 --- a/src/main/scala/tile/FPU.scala +++ b/src/main/scala/tile/FPU.scala @@ -542,7 +542,87 @@ 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)) + + if(latency>0) { + mulAddRecFNToRaw_postMul.io.fromPreMul := RegEnable(mulAddRecFNToRaw_preMul.io.toPostMul,io.validin) + mulAddRecFNToRaw_postMul.io.mulAddResult := RegEnable(mulAddResult,io.validin) + mulAddRecFNToRaw_postMul.io.roundingMode := RegEnable(io.roundingMode,io.validin) + roundingMode_stage0 := RegEnable(io.roundingMode,io.validin) + detectTininess_stage0 := RegEnable(io.detectTininess,io.validin) + valid_stage0 := RegNext(io.validin,false.B) + } else { + mulAddRecFNToRaw_postMul.io.fromPreMul := mulAddRecFNToRaw_preMul.io.toPostMul + mulAddRecFNToRaw_postMul.io.mulAddResult := mulAddResult + mulAddRecFNToRaw_postMul.io.roundingMode := io.roundingMode + roundingMode_stage0 := io.roundingMode + detectTininess_stage0 := io.detectTininess + valid_stage0 := io.validin + } + + //------------------------------------------------------------------------ + //------------------------------------------------------------------------ + val roundRawFNToRecFN = Module(new hardfloat.RoundRawFNToRecFN(expWidth, sigWidth, 0)) + // + if(latency==2){ + roundRawFNToRecFN.io.invalidExc := RegEnable(mulAddRecFNToRaw_postMul.io.invalidExc,valid_stage0) + roundRawFNToRecFN.io.in := RegEnable(mulAddRecFNToRaw_postMul.io.rawOut,valid_stage0) + roundRawFNToRecFN.io.roundingMode := RegEnable(roundingMode_stage0,valid_stage0) + roundRawFNToRecFN.io.detectTininess := RegEnable(detectTininess_stage0,valid_stage0) + io.validout := RegNext(valid_stage0, false.B) + } else { + roundRawFNToRecFN.io.invalidExc := mulAddRecFNToRaw_postMul.io.invalidExc + roundRawFNToRecFN.io.in := mulAddRecFNToRaw_postMul.io.rawOut + roundRawFNToRecFN.io.roundingMode := roundingMode_stage0 + roundRawFNToRecFN.io.detectTininess := detectTininess_stage0 + io.validout := valid_stage0 + } + + 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 +640,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 +652,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) { From 5498468743cc5dba87d280631de9b7c47741e267 Mon Sep 17 00:00:00 2001 From: Henry Styles Date: Fri, 29 Sep 2017 15:40:39 -0700 Subject: [PATCH 17/17] FPU : simplify pipeline register generation in FMA --- src/main/scala/tile/FPU.scala | 49 ++++++++++++----------------------- 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/src/main/scala/tile/FPU.scala b/src/main/scala/tile/FPU.scala index 1c990777..f64fbd2c 100644 --- a/src/main/scala/tile/FPU.scala +++ b/src/main/scala/tile/FPU.scala @@ -579,42 +579,27 @@ class MulAddRecFNPipe(latency: Int, expWidth: Int, sigWidth: Int) extends Module val valid_stage0 = Wire(Bool()) val roundingMode_stage0 = Wire(UInt(width=3)) val detectTininess_stage0 = Wire(UInt(width=1)) - - if(latency>0) { - mulAddRecFNToRaw_postMul.io.fromPreMul := RegEnable(mulAddRecFNToRaw_preMul.io.toPostMul,io.validin) - mulAddRecFNToRaw_postMul.io.mulAddResult := RegEnable(mulAddResult,io.validin) - mulAddRecFNToRaw_postMul.io.roundingMode := RegEnable(io.roundingMode,io.validin) - roundingMode_stage0 := RegEnable(io.roundingMode,io.validin) - detectTininess_stage0 := RegEnable(io.detectTininess,io.validin) - valid_stage0 := RegNext(io.validin,false.B) - } else { - mulAddRecFNToRaw_postMul.io.fromPreMul := mulAddRecFNToRaw_preMul.io.toPostMul - mulAddRecFNToRaw_postMul.io.mulAddResult := mulAddResult - mulAddRecFNToRaw_postMul.io.roundingMode := io.roundingMode - roundingMode_stage0 := io.roundingMode - detectTininess_stage0 := io.detectTininess - valid_stage0 := io.validin - } - + + 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)) - // - if(latency==2){ - roundRawFNToRecFN.io.invalidExc := RegEnable(mulAddRecFNToRaw_postMul.io.invalidExc,valid_stage0) - roundRawFNToRecFN.io.in := RegEnable(mulAddRecFNToRaw_postMul.io.rawOut,valid_stage0) - roundRawFNToRecFN.io.roundingMode := RegEnable(roundingMode_stage0,valid_stage0) - roundRawFNToRecFN.io.detectTininess := RegEnable(detectTininess_stage0,valid_stage0) - io.validout := RegNext(valid_stage0, false.B) - } else { - roundRawFNToRecFN.io.invalidExc := mulAddRecFNToRaw_postMul.io.invalidExc - roundRawFNToRecFN.io.in := mulAddRecFNToRaw_postMul.io.rawOut - roundRawFNToRecFN.io.roundingMode := roundingMode_stage0 - roundRawFNToRecFN.io.detectTininess := detectTininess_stage0 - io.validout := valid_stage0 - } - roundRawFNToRecFN.io.infiniteExc := Bool(false) + 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