Merge branch 'master' into ma-fetch
This commit is contained in:
commit
5b2f458214
@ -84,6 +84,8 @@ trait HasRocketTiles extends HasSystemBus
|
|||||||
lip.foreach { coreIntXbar.intnode := _ } // lip
|
lip.foreach { coreIntXbar.intnode := _ } // lip
|
||||||
wrapper.coreIntNode := coreIntXbar.intnode
|
wrapper.coreIntNode := coreIntXbar.intnode
|
||||||
|
|
||||||
|
wrapper.intOutputNode.foreach { plic.intnode := _ }
|
||||||
|
|
||||||
wrapper
|
wrapper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,7 @@ case class TraceGenParams(
|
|||||||
memStart: BigInt, //p(ExtMem).base
|
memStart: BigInt, //p(ExtMem).base
|
||||||
numGens: Int) extends GroundTestTileParams {
|
numGens: Int) extends GroundTestTileParams {
|
||||||
def build(i: Int, p: Parameters): GroundTestTile = new TraceGenTile(i, this)(p)
|
def build(i: Int, p: Parameters): GroundTestTile = new TraceGenTile(i, this)(p)
|
||||||
|
val trace = false
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasTraceGenParams {
|
trait HasTraceGenParams {
|
||||||
|
76
src/main/scala/rocket/BusErrorUnit.scala
Normal file
76
src/main/scala/rocket/BusErrorUnit.scala
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.rocket
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import Chisel.ImplicitConversions._
|
||||||
|
import chisel3.util.Valid
|
||||||
|
import freechips.rocketchip.config.Parameters
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
import freechips.rocketchip.tile._
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.regmapper._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
|
||||||
|
trait BusErrors extends Bundle {
|
||||||
|
def toErrorList: List[Option[Valid[UInt]]]
|
||||||
|
}
|
||||||
|
|
||||||
|
class L1BusErrors(implicit p: Parameters) extends CoreBundle()(p) with BusErrors {
|
||||||
|
val icache = new ICacheErrors
|
||||||
|
val dcache = new DCacheErrors
|
||||||
|
|
||||||
|
def toErrorList =
|
||||||
|
List(None, None, icache.correctable, icache.uncorrectable,
|
||||||
|
None, Some(dcache.bus), dcache.correctable, dcache.uncorrectable)
|
||||||
|
}
|
||||||
|
|
||||||
|
case class BusErrorUnitParams(addr: BigInt, size: Int = 4096)
|
||||||
|
|
||||||
|
class BusErrorUnit[T <: BusErrors](t: => T, params: BusErrorUnitParams)(implicit p: Parameters) extends LazyModule {
|
||||||
|
val regWidth = 64
|
||||||
|
val device = new SimpleDevice("bus-error-unit", Seq("sifive,buserror0"))
|
||||||
|
val intNode = IntSourceNode(IntSourcePortSimple(resources = device.int))
|
||||||
|
val node = TLRegisterNode(
|
||||||
|
address = Seq(AddressSet(params.addr, params.size-1)),
|
||||||
|
device = device,
|
||||||
|
beatBytes = p(XLen)/8)
|
||||||
|
|
||||||
|
lazy val module = new LazyModuleImp(this) {
|
||||||
|
val io = new Bundle {
|
||||||
|
val tl = node.bundleIn
|
||||||
|
val interrupt = intNode.bundleOut
|
||||||
|
val errors = t.flip
|
||||||
|
}
|
||||||
|
|
||||||
|
val sources = io.errors.toErrorList
|
||||||
|
val mask = sources.map(_.nonEmpty.B).asUInt
|
||||||
|
val cause = Reg(init = UInt(0, log2Ceil(sources.lastIndexWhere(_.nonEmpty) + 1)))
|
||||||
|
val value = Reg(UInt(width = sources.flatten.map(_.bits.getWidth).max))
|
||||||
|
require(value.getWidth <= regWidth)
|
||||||
|
val enable = Reg(init = mask)
|
||||||
|
val interrupt = Reg(init = UInt(0, sources.size))
|
||||||
|
val accrued = Reg(init = UInt(0, sources.size))
|
||||||
|
|
||||||
|
accrued := accrued | sources.map(_.map(_.valid).getOrElse(false.B)).asUInt
|
||||||
|
|
||||||
|
for ((s, i) <- sources.zipWithIndex; if s.nonEmpty) {
|
||||||
|
when (s.get.valid && enable(i) && cause === 0) {
|
||||||
|
cause := i
|
||||||
|
value := s.get.bits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
io.interrupt.head(0) := (accrued & interrupt).orR
|
||||||
|
|
||||||
|
def reg(r: UInt) = RegField(regWidth, r)
|
||||||
|
def maskedReg(r: UInt, m: UInt) = RegField(regWidth, r, RegWriteFn((v, d) => { when (v) { r := d & m }; true }))
|
||||||
|
|
||||||
|
node.regmap(
|
||||||
|
0 -> Seq(reg(cause),
|
||||||
|
reg(value),
|
||||||
|
maskedReg(enable, mask),
|
||||||
|
maskedReg(interrupt, mask),
|
||||||
|
maskedReg(accrued, mask)))
|
||||||
|
}
|
||||||
|
}
|
@ -149,6 +149,16 @@ class PerfCounterIO(implicit p: Parameters) extends CoreBundle
|
|||||||
val inc = UInt(INPUT, log2Ceil(1+retireWidth))
|
val inc = UInt(INPUT, log2Ceil(1+retireWidth))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TracedInstruction(implicit p: Parameters) extends CoreBundle {
|
||||||
|
val valid = Bool()
|
||||||
|
val addr = UInt(width = coreMaxAddrBits)
|
||||||
|
val insn = UInt(width = iLen)
|
||||||
|
val priv = UInt(width = 3)
|
||||||
|
val exception = Bool()
|
||||||
|
val cause = UInt(width = 1 + log2Ceil(xLen))
|
||||||
|
val tval = UInt(width = coreMaxAddrBits max iLen)
|
||||||
|
}
|
||||||
|
|
||||||
class CSRFileIO(implicit p: Parameters) extends CoreBundle
|
class CSRFileIO(implicit p: Parameters) extends CoreBundle
|
||||||
with HasRocketCoreParameters {
|
with HasRocketCoreParameters {
|
||||||
val interrupts = new TileInterrupts().asInput
|
val interrupts = new TileInterrupts().asInput
|
||||||
@ -192,6 +202,8 @@ class CSRFileIO(implicit p: Parameters) extends CoreBundle
|
|||||||
val bp = Vec(nBreakpoints, new BP).asOutput
|
val bp = Vec(nBreakpoints, new BP).asOutput
|
||||||
val pmp = Vec(nPMPs, new PMP).asOutput
|
val pmp = Vec(nPMPs, new PMP).asOutput
|
||||||
val counters = Vec(nPerfCounters, new PerfCounterIO)
|
val counters = Vec(nPerfCounters, new PerfCounterIO)
|
||||||
|
val inst = Vec(retireWidth, UInt(width = iLen)).asInput
|
||||||
|
val trace = Vec(retireWidth, new TracedInstruction).asOutput
|
||||||
}
|
}
|
||||||
|
|
||||||
class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Parameters) extends CoreModule()(p)
|
class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Parameters) extends CoreModule()(p)
|
||||||
@ -506,15 +518,14 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
|
|||||||
assert(!io.singleStep || io.retire <= UInt(1))
|
assert(!io.singleStep || io.retire <= UInt(1))
|
||||||
assert(!reg_singleStepped || io.retire === UInt(0))
|
assert(!reg_singleStepped || io.retire === UInt(0))
|
||||||
|
|
||||||
when (exception) {
|
|
||||||
val epc = ~(~io.pc | (coreInstBytes-1))
|
val epc = ~(~io.pc | (coreInstBytes-1))
|
||||||
|
|
||||||
val write_badaddr = cause isOneOf (Causes.illegal_instruction, Causes.breakpoint,
|
val write_badaddr = cause isOneOf (Causes.illegal_instruction, Causes.breakpoint,
|
||||||
Causes.misaligned_load, Causes.misaligned_store,
|
Causes.misaligned_load, Causes.misaligned_store,
|
||||||
Causes.load_access, Causes.store_access, Causes.fetch_access,
|
Causes.load_access, Causes.store_access, Causes.fetch_access,
|
||||||
Causes.load_page_fault, Causes.store_page_fault, Causes.fetch_page_fault)
|
Causes.load_page_fault, Causes.store_page_fault, Causes.fetch_page_fault)
|
||||||
val badaddr_value = Mux(write_badaddr, io.badaddr, 0.U)
|
val badaddr_value = Mux(write_badaddr, io.badaddr, 0.U)
|
||||||
|
|
||||||
|
when (exception) {
|
||||||
when (trapToDebug) {
|
when (trapToDebug) {
|
||||||
when (!reg_debug) {
|
when (!reg_debug) {
|
||||||
reg_debug := true
|
reg_debug := true
|
||||||
@ -756,6 +767,16 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (((t, insn), i) <- (io.trace zip io.inst).zipWithIndex) {
|
||||||
|
t.exception := io.retire >= i && exception
|
||||||
|
t.valid := io.retire > i || t.exception
|
||||||
|
t.insn := insn
|
||||||
|
t.addr := io.pc
|
||||||
|
t.priv := Cat(reg_debug, reg_mstatus.prv)
|
||||||
|
t.cause := Cat(cause(xLen-1), cause(log2Ceil(xLen)-1, 0))
|
||||||
|
t.tval := badaddr_value
|
||||||
|
}
|
||||||
|
|
||||||
def chooseInterrupt(masks: Seq[UInt]): (Bool, UInt) = {
|
def chooseInterrupt(masks: Seq[UInt]): (Bool, UInt) = {
|
||||||
val nonstandard = supported_interrupts.getWidth-1 to 12 by -1
|
val nonstandard = supported_interrupts.getWidth-1 to 12 by -1
|
||||||
// MEI, MSI, MTI, SEI, SSI, STI, UEI, USI, UTI
|
// MEI, MSI, MTI, SEI, SSI, STI, UEI, USI, UTI
|
||||||
|
@ -11,6 +11,12 @@ import freechips.rocketchip.tilelink._
|
|||||||
import freechips.rocketchip.util._
|
import freechips.rocketchip.util._
|
||||||
import TLMessages._
|
import TLMessages._
|
||||||
|
|
||||||
|
class DCacheErrors(implicit p: Parameters) extends L1HellaCacheBundle()(p) {
|
||||||
|
val correctable = (cacheParams.tagECC.canCorrect || cacheParams.dataECC.canCorrect).option(Valid(UInt(width = paddrBits)))
|
||||||
|
val uncorrectable = (cacheParams.tagECC.canDetect || cacheParams.dataECC.canDetect).option(Valid(UInt(width = paddrBits)))
|
||||||
|
val bus = Valid(UInt(width = paddrBits))
|
||||||
|
}
|
||||||
|
|
||||||
class DCacheDataReq(implicit p: Parameters) extends L1HellaCacheBundle()(p) {
|
class DCacheDataReq(implicit p: Parameters) extends L1HellaCacheBundle()(p) {
|
||||||
val eccBytes = cacheParams.dataECCBytes
|
val eccBytes = cacheParams.dataECCBytes
|
||||||
val addr = Bits(width = untagBits)
|
val addr = Bits(width = untagBits)
|
||||||
@ -216,9 +222,11 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
|
|||||||
val s2_flush_valid_pre_tag_ecc = RegNext(s1_flush_valid)
|
val s2_flush_valid_pre_tag_ecc = RegNext(s1_flush_valid)
|
||||||
val s1_meta_decoded = s1_meta.map(tECC.decode(_))
|
val s1_meta_decoded = s1_meta.map(tECC.decode(_))
|
||||||
val s1_meta_clk_en = s1_valid_not_nacked || s1_flush_valid || s1_probe
|
val s1_meta_clk_en = s1_valid_not_nacked || s1_flush_valid || s1_probe
|
||||||
val s2_meta_errors = s1_meta_decoded.map(m => RegEnable(m.error, s1_meta_clk_en)).asUInt
|
val s2_meta_correctable_errors = s1_meta_decoded.map(m => RegEnable(m.correctable, s1_meta_clk_en)).asUInt
|
||||||
|
val s2_meta_uncorrectable_errors = s1_meta_decoded.map(m => RegEnable(m.uncorrectable, s1_meta_clk_en)).asUInt
|
||||||
|
val s2_meta_error_uncorrectable = s2_meta_uncorrectable_errors.orR
|
||||||
val s2_meta_corrected = s1_meta_decoded.map(m => RegEnable(m.corrected, s1_meta_clk_en).asTypeOf(new L1Metadata))
|
val s2_meta_corrected = s1_meta_decoded.map(m => RegEnable(m.corrected, s1_meta_clk_en).asTypeOf(new L1Metadata))
|
||||||
val s2_meta_error = s2_meta_errors.orR
|
val s2_meta_error = (s2_meta_uncorrectable_errors | s2_meta_correctable_errors).orR
|
||||||
val s2_flush_valid = s2_flush_valid_pre_tag_ecc && !s2_meta_error
|
val s2_flush_valid = s2_flush_valid_pre_tag_ecc && !s2_meta_error
|
||||||
val s2_data = {
|
val s2_data = {
|
||||||
val en = s1_valid || inWriteback || tl_out.d.fire()
|
val en = s1_valid || inWriteback || tl_out.d.fire()
|
||||||
@ -242,6 +250,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
|
|||||||
val s2_word_idx = s2_req.addr.extract(log2Up(rowBits/8)-1, log2Up(wordBytes))
|
val s2_word_idx = s2_req.addr.extract(log2Up(rowBits/8)-1, log2Up(wordBytes))
|
||||||
val s2_did_read = RegEnable(s1_did_read, s1_valid_not_nacked)
|
val s2_did_read = RegEnable(s1_did_read, s1_valid_not_nacked)
|
||||||
val s2_data_error = s2_did_read && (s2_data_decoded.map(_.error).grouped(wordBits/eccBits).map(_.reduce(_||_)).toSeq)(s2_word_idx)
|
val s2_data_error = s2_did_read && (s2_data_decoded.map(_.error).grouped(wordBits/eccBits).map(_.reduce(_||_)).toSeq)(s2_word_idx)
|
||||||
|
val s2_data_error_uncorrectable = (s2_data_decoded.map(_.uncorrectable).grouped(wordBits/eccBits).map(_.reduce(_||_)).toSeq)(s2_word_idx)
|
||||||
val s2_data_corrected = (s2_data_decoded.map(_.corrected): Seq[UInt]).asUInt
|
val s2_data_corrected = (s2_data_decoded.map(_.corrected): Seq[UInt]).asUInt
|
||||||
val s2_data_uncorrected = (s2_data_decoded.map(_.uncorrected): Seq[UInt]).asUInt
|
val s2_data_uncorrected = (s2_data_decoded.map(_.uncorrected): Seq[UInt]).asUInt
|
||||||
val s2_valid_hit_pre_data_ecc = s2_valid_masked && s2_readwrite && !s2_meta_error && s2_hit
|
val s2_valid_hit_pre_data_ecc = s2_valid_masked && s2_readwrite && !s2_meta_error && s2_hit
|
||||||
@ -264,9 +273,10 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
|
|||||||
// tag updates on ECC errors
|
// tag updates on ECC errors
|
||||||
metaArb.io.in(1).valid := s2_meta_error && (s2_valid_masked || s2_flush_valid_pre_tag_ecc || s2_probe)
|
metaArb.io.in(1).valid := s2_meta_error && (s2_valid_masked || s2_flush_valid_pre_tag_ecc || s2_probe)
|
||||||
metaArb.io.in(1).bits.write := true
|
metaArb.io.in(1).bits.write := true
|
||||||
metaArb.io.in(1).bits.way_en := PriorityEncoderOH(s2_meta_errors)
|
metaArb.io.in(1).bits.way_en := s2_meta_uncorrectable_errors | Mux(s2_meta_error_uncorrectable, 0.U, PriorityEncoderOH(s2_meta_correctable_errors))
|
||||||
metaArb.io.in(1).bits.addr := Cat(io.cpu.req.bits.addr >> untagBits, Mux(s2_probe, probe_bits.address, s2_req.addr)(idxMSB, 0))
|
metaArb.io.in(1).bits.addr := Cat(io.cpu.req.bits.addr >> untagBits, Mux(s2_probe, probe_bits.address, s2_req.addr)(idxMSB, 0))
|
||||||
metaArb.io.in(1).bits.data := PriorityMux(s2_meta_errors, s2_meta_corrected)
|
metaArb.io.in(1).bits.data := PriorityMux(s2_meta_correctable_errors, s2_meta_corrected)
|
||||||
|
when (s2_meta_error_uncorrectable) { metaArb.io.in(1).bits.data.coh := ClientMetadata.onReset }
|
||||||
|
|
||||||
// tag updates on hit/miss
|
// tag updates on hit/miss
|
||||||
metaArb.io.in(2).valid := (s2_valid_hit && s2_update_meta) || (s2_victimize && !s2_victim_dirty)
|
metaArb.io.in(2).valid := (s2_valid_hit && s2_update_meta) || (s2_victimize && !s2_victim_dirty)
|
||||||
@ -703,6 +713,30 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
|
|||||||
io.cpu.perf.release := edge.done(tl_out_c)
|
io.cpu.perf.release := edge.done(tl_out_c)
|
||||||
io.cpu.perf.tlbMiss := io.ptw.req.fire()
|
io.cpu.perf.tlbMiss := io.ptw.req.fire()
|
||||||
|
|
||||||
|
// report errors
|
||||||
|
{
|
||||||
|
val (data_error, data_error_uncorrectable, data_error_addr) =
|
||||||
|
if (usingDataScratchpad) (s2_valid_data_error, s2_data_error_uncorrectable, s2_req.addr) else {
|
||||||
|
(tl_out_c.valid && edge.hasData(tl_out_c.bits) && s2_data_decoded.map(_.error).reduce(_||_),
|
||||||
|
s2_data_decoded.map(_.uncorrectable).reduce(_||_),
|
||||||
|
tl_out_c.bits.address)
|
||||||
|
}
|
||||||
|
val error_addr =
|
||||||
|
Mux(metaArb.io.in(1).valid, Cat(metaArb.io.in(1).bits.data.tag, metaArb.io.in(1).bits.addr(untagBits-1, idxLSB)),
|
||||||
|
data_error_addr >> idxLSB) << idxLSB
|
||||||
|
io.errors.uncorrectable.foreach { u =>
|
||||||
|
u.valid := metaArb.io.in(1).valid && s2_meta_error_uncorrectable || data_error && data_error_uncorrectable
|
||||||
|
u.bits := error_addr
|
||||||
|
}
|
||||||
|
io.errors.correctable.foreach { c =>
|
||||||
|
c.valid := metaArb.io.in(1).valid || data_error
|
||||||
|
c.bits := error_addr
|
||||||
|
io.errors.uncorrectable.foreach { u => when (u.valid) { c.valid := false } }
|
||||||
|
}
|
||||||
|
io.errors.bus.valid := tl_out.d.fire() && tl_out.d.bits.error
|
||||||
|
io.errors.bus.bits := Mux(grantIsCached, s2_req.addr >> idxLSB << idxLSB, 0.U)
|
||||||
|
}
|
||||||
|
|
||||||
def encodeData(x: UInt) = x.grouped(eccBits).map(dECC.encode(_)).asUInt
|
def encodeData(x: UInt) = x.grouped(eccBits).map(dECC.encode(_)).asUInt
|
||||||
def dummyEncodeData(x: UInt) = x.grouped(eccBits).map(dECC.swizzle(_)).asUInt
|
def dummyEncodeData(x: UInt) = x.grouped(eccBits).map(dECC.swizzle(_)).asUInt
|
||||||
def decodeData(x: UInt) = x.grouped(dECC.width(eccBits)).map(dECC.decode(_))
|
def decodeData(x: UInt) = x.grouped(dECC.width(eccBits)).map(dECC.decode(_))
|
||||||
|
@ -70,6 +70,7 @@ class FrontendBundle(outer: Frontend) extends CoreBundle()(outer.p)
|
|||||||
val ptw = new TLBPTWIO()
|
val ptw = new TLBPTWIO()
|
||||||
val tl_out = outer.masterNode.bundleOut
|
val tl_out = outer.masterNode.bundleOut
|
||||||
val tl_in = outer.slaveNode.bundleIn
|
val tl_in = outer.slaveNode.bundleIn
|
||||||
|
val errors = new ICacheErrors
|
||||||
}
|
}
|
||||||
|
|
||||||
class FrontendModule(outer: Frontend) extends LazyModuleImp(outer)
|
class FrontendModule(outer: Frontend) extends LazyModuleImp(outer)
|
||||||
@ -286,6 +287,7 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer)
|
|||||||
// performance events
|
// performance events
|
||||||
io.cpu.perf := icache.io.perf
|
io.cpu.perf := icache.io.perf
|
||||||
io.cpu.perf.tlbMiss := io.ptw.req.fire()
|
io.cpu.perf.tlbMiss := io.ptw.req.fire()
|
||||||
|
io.errors := icache.io.errors
|
||||||
|
|
||||||
def alignPC(pc: UInt) = ~(~pc | (coreInstBytes - 1))
|
def alignPC(pc: UInt) = ~(~pc | (coreInstBytes - 1))
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,7 @@ class HellaCacheBundle(outer: HellaCache)(implicit p: Parameters) extends CoreBu
|
|||||||
val cpu = (new HellaCacheIO).flip
|
val cpu = (new HellaCacheIO).flip
|
||||||
val ptw = new TLBPTWIO()
|
val ptw = new TLBPTWIO()
|
||||||
val mem = outer.node.bundleOut
|
val mem = outer.node.bundleOut
|
||||||
|
val errors = new DCacheErrors
|
||||||
}
|
}
|
||||||
|
|
||||||
class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer)
|
class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer)
|
||||||
|
@ -16,7 +16,6 @@ class Instruction(implicit val p: Parameters) extends ParameterizedBundle with H
|
|||||||
val rvc = Bool()
|
val rvc = Bool()
|
||||||
val inst = new ExpandedInstruction
|
val inst = new ExpandedInstruction
|
||||||
val raw = UInt(width = 32)
|
val raw = UInt(width = 32)
|
||||||
val cinst = UInt(width = 32)
|
|
||||||
require(coreInstBits == (if (usingCompressed) 16 else 32))
|
require(coreInstBits == (if (usingCompressed) 16 else 32))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +95,6 @@ class IBuf(implicit p: Parameters) extends CoreModule {
|
|||||||
exp.io.in := curInst
|
exp.io.in := curInst
|
||||||
io.inst(i).bits.inst := exp.io.out
|
io.inst(i).bits.inst := exp.io.out
|
||||||
io.inst(i).bits.raw := curInst
|
io.inst(i).bits.raw := curInst
|
||||||
io.inst(i).bits.cinst := Mux(exp.io.rvc, curInst & 0xFFFF, curInst)
|
|
||||||
|
|
||||||
if (usingCompressed) {
|
if (usingCompressed) {
|
||||||
val replay = ic_replay(j) || (!exp.io.rvc && (btbHitMask(j) || ic_replay(j+1)))
|
val replay = ic_replay(j) || (!exp.io.rvc && (btbHitMask(j) || ic_replay(j+1)))
|
||||||
|
@ -36,6 +36,11 @@ class ICacheReq(implicit p: Parameters) extends CoreBundle()(p) with HasL1ICache
|
|||||||
val addr = UInt(width = vaddrBits)
|
val addr = UInt(width = vaddrBits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ICacheErrors(implicit p: Parameters) extends CoreBundle()(p) with HasL1ICacheParameters {
|
||||||
|
val correctable = (cacheParams.tagECC.canDetect || cacheParams.dataECC.canDetect).option(Valid(UInt(width = paddrBits)))
|
||||||
|
val uncorrectable = (cacheParams.itimAddr.nonEmpty && cacheParams.dataECC.canDetect).option(Valid(UInt(width = paddrBits)))
|
||||||
|
}
|
||||||
|
|
||||||
class ICache(val icacheParams: ICacheParams, val hartid: Int)(implicit p: Parameters) extends LazyModule {
|
class ICache(val icacheParams: ICacheParams, val hartid: Int)(implicit p: Parameters) extends LazyModule {
|
||||||
lazy val module = new ICacheModule(this)
|
lazy val module = new ICacheModule(this)
|
||||||
val masterNode = TLClientNode(TLClientParameters(
|
val masterNode = TLClientNode(TLClientParameters(
|
||||||
@ -87,6 +92,7 @@ class ICacheBundle(outer: ICache) extends CoreBundle()(outer.p) {
|
|||||||
val tl_out = outer.masterNode.bundleOut
|
val tl_out = outer.masterNode.bundleOut
|
||||||
val tl_in = outer.slaveNode.map(_.bundleIn)
|
val tl_in = outer.slaveNode.map(_.bundleIn)
|
||||||
|
|
||||||
|
val errors = new ICacheErrors
|
||||||
val perf = new ICachePerfEvents().asOutput
|
val perf = new ICachePerfEvents().asOutput
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,10 +122,10 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
|
|||||||
val scratchpadOn = RegInit(false.B)
|
val scratchpadOn = RegInit(false.B)
|
||||||
val scratchpadMax = tl_in.map(tl => Reg(UInt(width = log2Ceil(nSets * (nWays - 1)))))
|
val scratchpadMax = tl_in.map(tl => Reg(UInt(width = log2Ceil(nSets * (nWays - 1)))))
|
||||||
def lineInScratchpad(line: UInt) = scratchpadMax.map(scratchpadOn && line <= _).getOrElse(false.B)
|
def lineInScratchpad(line: UInt) = scratchpadMax.map(scratchpadOn && line <= _).getOrElse(false.B)
|
||||||
def addrMaybeInScratchpad(addr: UInt) = if (outer.icacheParams.itimAddr.isEmpty) false.B else {
|
val scratchpadBase = outer.icacheParams.itimAddr.map { dummy =>
|
||||||
val base = GetPropertyByHartId(p(RocketTilesKey), _.icache.flatMap(_.itimAddr.map(_.U)), io.hartid)
|
GetPropertyByHartId(p(RocketTilesKey), _.icache.flatMap(_.itimAddr.map(_.U)), io.hartid)
|
||||||
addr >= base && addr < base + outer.size
|
|
||||||
}
|
}
|
||||||
|
def addrMaybeInScratchpad(addr: UInt) = scratchpadBase.map(base => addr >= base && addr < base + outer.size).getOrElse(false.B)
|
||||||
def addrInScratchpad(addr: UInt) = addrMaybeInScratchpad(addr) && lineInScratchpad(addr(untagBits+log2Ceil(nWays)-1, blockOffBits))
|
def addrInScratchpad(addr: UInt) = addrMaybeInScratchpad(addr) && lineInScratchpad(addr(untagBits+log2Ceil(nWays)-1, blockOffBits))
|
||||||
def scratchpadWay(addr: UInt) = addr.extract(untagBits+log2Ceil(nWays)-1, untagBits)
|
def scratchpadWay(addr: UInt) = addr.extract(untagBits+log2Ceil(nWays)-1, untagBits)
|
||||||
def scratchpadWayValid(way: UInt) = way < nWays - 1
|
def scratchpadWayValid(way: UInt) = way < nWays - 1
|
||||||
@ -248,12 +254,15 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
|
|||||||
io.resp.valid := s1_valid && s1_hit
|
io.resp.valid := s1_valid && s1_hit
|
||||||
|
|
||||||
case 2 =>
|
case 2 =>
|
||||||
val s2_tag_hit = RegEnable(s1_tag_hit, s1_valid || s1_slaveValid)
|
val s1_clk_en = s1_valid || s1_slaveValid
|
||||||
val s2_dout = RegEnable(s1_dout, s1_valid || s1_slaveValid)
|
val s2_tag_hit = RegEnable(s1_tag_hit, s1_clk_en)
|
||||||
|
val s2_hit_way = OHToUInt(s2_tag_hit)
|
||||||
|
val s2_scratchpad_word_addr = Cat(s2_hit_way, io.s2_vaddr(untagBits-1, log2Ceil(wordBits/8)), UInt(0, log2Ceil(wordBits/8)))
|
||||||
|
val s2_dout = RegEnable(s1_dout, s1_clk_en)
|
||||||
val s2_way_mux = Mux1H(s2_tag_hit, s2_dout)
|
val s2_way_mux = Mux1H(s2_tag_hit, s2_dout)
|
||||||
|
|
||||||
val s2_tag_disparity = RegEnable(s1_tag_disparity, s1_valid || s1_slaveValid).asUInt.orR
|
val s2_tag_disparity = RegEnable(s1_tag_disparity, s1_clk_en).asUInt.orR
|
||||||
val s2_tl_error = RegEnable(s1_tl_error.asUInt.orR, s1_valid || s1_slaveValid)
|
val s2_tl_error = RegEnable(s1_tl_error.asUInt.orR, s1_clk_en)
|
||||||
val s2_data_decoded = dECC.decode(s2_way_mux)
|
val s2_data_decoded = dECC.decode(s2_way_mux)
|
||||||
val s2_disparity = s2_tag_disparity || s2_data_decoded.error
|
val s2_disparity = s2_tag_disparity || s2_data_decoded.error
|
||||||
when (s2_valid && s2_disparity) { invalidate := true }
|
when (s2_valid && s2_disparity) { invalidate := true }
|
||||||
@ -263,6 +272,17 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
|
|||||||
io.resp.bits.replay := s2_disparity
|
io.resp.bits.replay := s2_disparity
|
||||||
io.resp.valid := s2_valid && s2_hit
|
io.resp.valid := s2_valid && s2_hit
|
||||||
|
|
||||||
|
val s1_scratchpad_hit = Mux(s1_slaveValid, lineInScratchpad(scratchpadLine(s1s3_slaveAddr)), addrInScratchpad(io.s1_paddr))
|
||||||
|
val s2_scratchpad_hit = RegEnable(s1_scratchpad_hit, s1_clk_en)
|
||||||
|
io.errors.correctable.foreach { c =>
|
||||||
|
c.valid := s2_valid && Mux(s2_scratchpad_hit, s2_data_decoded.correctable, s2_disparity)
|
||||||
|
c.bits := 0.U
|
||||||
|
}
|
||||||
|
io.errors.uncorrectable.foreach { u =>
|
||||||
|
u.valid := s2_valid && s2_scratchpad_hit && s2_data_decoded.uncorrectable
|
||||||
|
u.bits := scratchpadBase.get + s2_scratchpad_word_addr
|
||||||
|
}
|
||||||
|
|
||||||
tl_in.map { tl =>
|
tl_in.map { tl =>
|
||||||
val respValid = RegInit(false.B)
|
val respValid = RegInit(false.B)
|
||||||
tl.a.ready := !(tl_out.d.valid || s1_slaveValid || s2_slaveValid || s3_slaveValid || respValid)
|
tl.a.ready := !(tl_out.d.valid || s1_slaveValid || s2_slaveValid || s3_slaveValid || respValid)
|
||||||
@ -290,7 +310,7 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
|
|||||||
// a structural hazard on s1s3_slaveData/s1s3_slaveAddress).
|
// a structural hazard on s1s3_slaveData/s1s3_slaveAddress).
|
||||||
s3_slaveValid := true
|
s3_slaveValid := true
|
||||||
s1s3_slaveData := s2_data_decoded.corrected
|
s1s3_slaveData := s2_data_decoded.corrected
|
||||||
s1s3_slaveAddr := Cat(OHToUInt(s2_tag_hit), io.s2_vaddr(untagBits-1, log2Ceil(wordBits/8)), s1s3_slaveAddr(log2Ceil(wordBits/8)-1, 0))
|
s1s3_slaveAddr := s2_scratchpad_word_addr | s1s3_slaveAddr(log2Ceil(wordBits/8)-1, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
respValid := s2_slaveValid || (respValid && !tl.d.ready)
|
respValid := s2_slaveValid || (respValid && !tl.d.ready)
|
||||||
|
@ -30,6 +30,7 @@ case class RocketCoreParams(
|
|||||||
fastLoadWord: Boolean = true,
|
fastLoadWord: Boolean = true,
|
||||||
fastLoadByte: Boolean = false,
|
fastLoadByte: Boolean = false,
|
||||||
jumpInFrontend: Boolean = true,
|
jumpInFrontend: Boolean = true,
|
||||||
|
tileControlAddr: Option[BigInt] = None,
|
||||||
mulDiv: Option[MulDivParams] = Some(MulDivParams()),
|
mulDiv: Option[MulDivParams] = Some(MulDivParams()),
|
||||||
fpu: Option[FPUParams] = Some(FPUParams())
|
fpu: Option[FPUParams] = Some(FPUParams())
|
||||||
) extends CoreParams {
|
) extends CoreParams {
|
||||||
@ -136,7 +137,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
val ex_reg_replay = Reg(Bool())
|
val ex_reg_replay = Reg(Bool())
|
||||||
val ex_reg_pc = Reg(UInt())
|
val ex_reg_pc = Reg(UInt())
|
||||||
val ex_reg_inst = Reg(Bits())
|
val ex_reg_inst = Reg(Bits())
|
||||||
val ex_reg_cinst = Reg(Bits())
|
val ex_reg_raw_inst = Reg(UInt())
|
||||||
|
|
||||||
val mem_reg_xcpt_interrupt = Reg(Bool())
|
val mem_reg_xcpt_interrupt = Reg(Bool())
|
||||||
val mem_reg_valid = Reg(Bool())
|
val mem_reg_valid = Reg(Bool())
|
||||||
@ -153,7 +154,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
val mem_reg_sfence = Reg(Bool())
|
val mem_reg_sfence = Reg(Bool())
|
||||||
val mem_reg_pc = Reg(UInt())
|
val mem_reg_pc = Reg(UInt())
|
||||||
val mem_reg_inst = Reg(Bits())
|
val mem_reg_inst = Reg(Bits())
|
||||||
val mem_reg_cinst = Reg(Bits())
|
val mem_reg_raw_inst = Reg(UInt())
|
||||||
val mem_reg_wdata = Reg(Bits())
|
val mem_reg_wdata = Reg(Bits())
|
||||||
val mem_reg_rs2 = Reg(Bits())
|
val mem_reg_rs2 = Reg(Bits())
|
||||||
val take_pc_mem = Wire(Bool())
|
val take_pc_mem = Wire(Bool())
|
||||||
@ -167,7 +168,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
val wb_reg_sfence = Reg(Bool())
|
val wb_reg_sfence = Reg(Bool())
|
||||||
val wb_reg_pc = Reg(UInt())
|
val wb_reg_pc = Reg(UInt())
|
||||||
val wb_reg_inst = Reg(Bits())
|
val wb_reg_inst = Reg(Bits())
|
||||||
val wb_reg_cinst = Reg(Bits())
|
val wb_reg_raw_inst = Reg(UInt())
|
||||||
val wb_reg_wdata = Reg(Bits())
|
val wb_reg_wdata = Reg(Bits())
|
||||||
val wb_reg_rs2 = Reg(Bits())
|
val wb_reg_rs2 = Reg(Bits())
|
||||||
val take_pc_wb = Wire(Bool())
|
val take_pc_wb = Wire(Bool())
|
||||||
@ -178,7 +179,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
// decode stage
|
// decode stage
|
||||||
val ibuf = Module(new IBuf)
|
val ibuf = Module(new IBuf)
|
||||||
val id_expanded_inst = ibuf.io.inst.map(_.bits.inst)
|
val id_expanded_inst = ibuf.io.inst.map(_.bits.inst)
|
||||||
val id_nonexpanded_inst = ibuf.io.inst.map(_.bits.cinst)
|
val id_raw_inst = ibuf.io.inst.map(_.bits.raw)
|
||||||
val id_inst = id_expanded_inst.map(_.bits)
|
val id_inst = id_expanded_inst.map(_.bits)
|
||||||
ibuf.io.imem <> io.imem.resp
|
ibuf.io.imem <> io.imem.resp
|
||||||
ibuf.io.kill := take_pc
|
ibuf.io.kill := take_pc
|
||||||
@ -335,7 +336,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
when (id_illegal_insn) {
|
when (id_illegal_insn) {
|
||||||
val inst = Mux(ibuf.io.inst(0).bits.rvc, ibuf.io.inst(0).bits.raw(15, 0), ibuf.io.inst(0).bits.raw)
|
val inst = Mux(ibuf.io.inst(0).bits.rvc, id_raw_inst(0)(15, 0), id_raw_inst(0))
|
||||||
ex_reg_rs_bypass(0) := false
|
ex_reg_rs_bypass(0) := false
|
||||||
ex_reg_rs_lsb(0) := inst(log2Ceil(bypass_sources.size)-1, 0)
|
ex_reg_rs_lsb(0) := inst(log2Ceil(bypass_sources.size)-1, 0)
|
||||||
ex_reg_rs_msb(0) := inst >> log2Ceil(bypass_sources.size)
|
ex_reg_rs_msb(0) := inst >> log2Ceil(bypass_sources.size)
|
||||||
@ -344,7 +345,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
when (!ctrl_killd || csr.io.interrupt || ibuf.io.inst(0).bits.replay) {
|
when (!ctrl_killd || csr.io.interrupt || ibuf.io.inst(0).bits.replay) {
|
||||||
ex_reg_cause := id_cause
|
ex_reg_cause := id_cause
|
||||||
ex_reg_inst := id_inst(0)
|
ex_reg_inst := id_inst(0)
|
||||||
ex_reg_cinst := id_nonexpanded_inst(0)
|
ex_reg_raw_inst := id_raw_inst(0)
|
||||||
ex_reg_pc := ibuf.io.pc
|
ex_reg_pc := ibuf.io.pc
|
||||||
ex_reg_btb_resp := ibuf.io.btb_resp
|
ex_reg_btb_resp := ibuf.io.btb_resp
|
||||||
}
|
}
|
||||||
@ -405,7 +406,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
|
|
||||||
mem_reg_cause := ex_cause
|
mem_reg_cause := ex_cause
|
||||||
mem_reg_inst := ex_reg_inst
|
mem_reg_inst := ex_reg_inst
|
||||||
mem_reg_cinst := ex_reg_cinst
|
mem_reg_raw_inst := ex_reg_raw_inst
|
||||||
mem_reg_pc := ex_reg_pc
|
mem_reg_pc := ex_reg_pc
|
||||||
mem_reg_wdata := alu.io.out
|
mem_reg_wdata := alu.io.out
|
||||||
|
|
||||||
@ -453,7 +454,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
}
|
}
|
||||||
wb_reg_cause := mem_cause
|
wb_reg_cause := mem_cause
|
||||||
wb_reg_inst := mem_reg_inst
|
wb_reg_inst := mem_reg_inst
|
||||||
wb_reg_cinst := mem_reg_cinst
|
wb_reg_raw_inst := mem_reg_raw_inst
|
||||||
wb_reg_pc := mem_reg_pc
|
wb_reg_pc := mem_reg_pc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,10 +514,11 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
when (rf_wen) { rf.write(rf_waddr, rf_wdata) }
|
when (rf_wen) { rf.write(rf_waddr, rf_wdata) }
|
||||||
|
|
||||||
// hook up control/status regfile
|
// hook up control/status regfile
|
||||||
csr.io.decode.csr := ibuf.io.inst(0).bits.raw(31,20)
|
csr.io.decode.csr := id_raw_inst(0)(31,20)
|
||||||
csr.io.exception := wb_xcpt
|
csr.io.exception := wb_xcpt
|
||||||
csr.io.cause := wb_cause
|
csr.io.cause := wb_cause
|
||||||
csr.io.retire := wb_valid
|
csr.io.retire := wb_valid
|
||||||
|
csr.io.inst(0) := Cat(Mux(wb_reg_rvc, 0.U, wb_reg_inst >> 16), wb_reg_raw_inst(15, 0))
|
||||||
csr.io.interrupts := io.interrupts
|
csr.io.interrupts := io.interrupts
|
||||||
csr.io.hartid := io.hartid
|
csr.io.hartid := io.hartid
|
||||||
io.fpu.fcsr_rm := csr.io.fcsr_rm
|
io.fpu.fcsr_rm := csr.io.fcsr_rm
|
||||||
@ -530,6 +532,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
csr.io.rw.addr := wb_reg_inst(31,20)
|
csr.io.rw.addr := wb_reg_inst(31,20)
|
||||||
csr.io.rw.cmd := Mux(wb_reg_valid, wb_ctrl.csr, CSR.N)
|
csr.io.rw.cmd := Mux(wb_reg_valid, wb_ctrl.csr, CSR.N)
|
||||||
csr.io.rw.wdata := wb_reg_wdata
|
csr.io.rw.wdata := wb_reg_wdata
|
||||||
|
io.trace := csr.io.trace
|
||||||
|
|
||||||
val hazard_targets = Seq((id_ctrl.rxs1 && id_raddr1 =/= UInt(0), id_raddr1),
|
val hazard_targets = Seq((id_ctrl.rxs1 && id_raddr1 =/= UInt(0), id_raddr1),
|
||||||
(id_ctrl.rxs2 && id_raddr2 =/= UInt(0), id_raddr2),
|
(id_ctrl.rxs2 && id_raddr2 =/= UInt(0), id_raddr2),
|
||||||
@ -664,28 +667,24 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
csr.io.counters foreach { c => c.inc := RegNext(perfEvents.evaluate(c.eventSel)) }
|
csr.io.counters foreach { c => c.inc := RegNext(perfEvents.evaluate(c.eventSel)) }
|
||||||
|
|
||||||
if (enableCommitLog) {
|
if (enableCommitLog) {
|
||||||
val pc = Wire(SInt(width=xLen))
|
val t = csr.io.trace(0)
|
||||||
pc := wb_reg_pc.asSInt
|
val rd = wb_waddr
|
||||||
val inst = wb_reg_inst
|
|
||||||
val cinst = wb_reg_cinst
|
|
||||||
val rd = RegNext(RegNext(RegNext(id_waddr)))
|
|
||||||
val wfd = wb_ctrl.wfd
|
val wfd = wb_ctrl.wfd
|
||||||
val wxd = wb_ctrl.wxd
|
val wxd = wb_ctrl.wxd
|
||||||
val has_data = wb_wen && !wb_set_sboard
|
val has_data = wb_wen && !wb_set_sboard
|
||||||
val priv = csr.io.status.prv
|
|
||||||
|
|
||||||
when (wb_valid) {
|
when (t.valid) {
|
||||||
when (wfd) {
|
when (wfd) {
|
||||||
printf ("%d 0x%x (0x%x) f%d p%d 0xXXXXXXXXXXXXXXXX\n", priv, pc, cinst, rd, rd+UInt(32))
|
printf ("%d 0x%x (0x%x) f%d p%d 0xXXXXXXXXXXXXXXXX\n", t.priv, t.addr, t.insn, rd, rd+UInt(32))
|
||||||
}
|
}
|
||||||
.elsewhen (wxd && rd =/= UInt(0) && has_data) {
|
.elsewhen (wxd && rd =/= UInt(0) && has_data) {
|
||||||
printf ("%d 0x%x (0x%x) x%d 0x%x\n", priv, pc, cinst, rd, rf_wdata)
|
printf ("%d 0x%x (0x%x) x%d 0x%x\n", t.priv, t.addr, t.insn, rd, rf_wdata)
|
||||||
}
|
}
|
||||||
.elsewhen (wxd && rd =/= UInt(0) && !has_data) {
|
.elsewhen (wxd && rd =/= UInt(0) && !has_data) {
|
||||||
printf ("%d 0x%x (0x%x) x%d p%d 0xXXXXXXXXXXXXXXXX\n", priv, pc, cinst, rd, rd)
|
printf ("%d 0x%x (0x%x) x%d p%d 0xXXXXXXXXXXXXXXXX\n", t.priv, t.addr, t.insn, rd, rd)
|
||||||
}
|
}
|
||||||
.otherwise {
|
.otherwise {
|
||||||
printf ("%d 0x%x (0x%x)\n", priv, pc, cinst)
|
printf ("%d 0x%x (0x%x)\n", t.priv, t.addr, t.insn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -695,11 +694,11 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("C%d: %d [%d] pc=[%x] W[r%d=%x][%d] R[r%d=%x] R[r%d=%x] inst=[%x] DASM(%x)\n",
|
printf("C%d: %d [%d] pc=[%x] W[r%d=%x][%d] R[r%d=%x] R[r%d=%x] inst=[%x] DASM(%x)\n",
|
||||||
io.hartid, csr.io.time(31,0), wb_valid, wb_reg_pc,
|
io.hartid, csr.io.time(31,0), csr.io.trace(0).valid, csr.io.trace(0).addr(vaddrBitsExtended-1, 0),
|
||||||
Mux(rf_wen && !(wb_set_sboard && wb_wen), rf_waddr, UInt(0)), rf_wdata, rf_wen,
|
Mux(rf_wen && !(wb_set_sboard && wb_wen), rf_waddr, UInt(0)), rf_wdata, rf_wen,
|
||||||
wb_reg_inst(19,15), Reg(next=Reg(next=ex_rs(0))),
|
wb_reg_inst(19,15), Reg(next=Reg(next=ex_rs(0))),
|
||||||
wb_reg_inst(24,20), Reg(next=Reg(next=ex_rs(1))),
|
wb_reg_inst(24,20), Reg(next=Reg(next=ex_rs(1))),
|
||||||
wb_reg_cinst, wb_reg_cinst)
|
csr.io.trace(0).insn, csr.io.trace(0).insn)
|
||||||
}
|
}
|
||||||
|
|
||||||
val max_core_cycles = PlusArg("max-core-cycles",
|
val max_core_cycles = PlusArg("max-core-cycles",
|
||||||
|
@ -100,21 +100,32 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend {
|
|||||||
val module: CanHaveScratchpadModule
|
val module: CanHaveScratchpadModule
|
||||||
val cacheBlockBytes = p(CacheBlockBytes)
|
val cacheBlockBytes = p(CacheBlockBytes)
|
||||||
|
|
||||||
val slaveNode = TLInputNode() // Up to two uses for this input node:
|
|
||||||
|
|
||||||
// 1) Frontend always exists, but may or may not have a scratchpad node
|
|
||||||
// 2) ScratchpadSlavePort always has a node, but only exists when the HellaCache has a scratchpad
|
|
||||||
val fg = LazyModule(new TLFragmenter(tileParams.core.fetchBytes, cacheBlockBytes, earlyAck=true))
|
|
||||||
val ww = LazyModule(new TLWidthWidget(xBytes))
|
|
||||||
val scratch = tileParams.dcache.flatMap { d => d.scratch.map(s =>
|
val scratch = tileParams.dcache.flatMap { d => d.scratch.map(s =>
|
||||||
LazyModule(new ScratchpadSlavePort(AddressSet(s, d.dataScratchpadBytes-1), xBytes, tileParams.core.useAtomics)))
|
LazyModule(new ScratchpadSlavePort(AddressSet(s, d.dataScratchpadBytes-1), xBytes, tileParams.core.useAtomics)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val intOutputNode = tileParams.core.tileControlAddr.map(dummy => IntOutputNode())
|
||||||
|
val busErrorUnit = tileParams.core.tileControlAddr map { a =>
|
||||||
|
val beu = LazyModule(new BusErrorUnit(new L1BusErrors, BusErrorUnitParams(a)))
|
||||||
|
intOutputNode.get := beu.intNode
|
||||||
|
beu
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect any combination of ITIM, DTIM, and BusErrorUnit
|
||||||
|
val slaveNode = TLInputNode()
|
||||||
DisableMonitors { implicit p =>
|
DisableMonitors { implicit p =>
|
||||||
frontend.slaveNode :*= fg.node
|
val xbarPorts =
|
||||||
fg.node :*= ww.node
|
scratch.map(lm => (lm.node, xBytes)) ++
|
||||||
ww.node :*= slaveNode
|
busErrorUnit.map(lm => (lm.node, xBytes)) ++
|
||||||
scratch foreach { lm => lm.node := TLFragmenter(xBytes, cacheBlockBytes, earlyAck=true)(slaveNode) }
|
tileParams.icache.flatMap(icache => icache.itimAddr.map(a => (frontend.slaveNode, tileParams.core.fetchBytes)))
|
||||||
|
|
||||||
|
if (xbarPorts.nonEmpty) {
|
||||||
|
val xbar = LazyModule(new TLXbar)
|
||||||
|
xbar.node := TLFIFOFixer()(TLFragmenter(xBytes, cacheBlockBytes, earlyAck=true)(slaveNode))
|
||||||
|
xbarPorts.foreach { case (port, bytes) =>
|
||||||
|
port := (if (bytes == xBytes) xbar.node else TLFragmenter(bytes, xBytes, earlyAck=true)(TLWidthWidget(xBytes)(xbar.node)))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def findScratchpadFromICache: Option[AddressSet] = scratch.map { s =>
|
def findScratchpadFromICache: Option[AddressSet] = scratch.map { s =>
|
||||||
@ -130,6 +141,7 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend {
|
|||||||
trait CanHaveScratchpadBundle extends HasHellaCacheBundle with HasICacheFrontendBundle {
|
trait CanHaveScratchpadBundle extends HasHellaCacheBundle with HasICacheFrontendBundle {
|
||||||
val outer: CanHaveScratchpad
|
val outer: CanHaveScratchpad
|
||||||
val slave = outer.slaveNode.bundleIn
|
val slave = outer.slaveNode.bundleIn
|
||||||
|
val intOutput = outer.intOutputNode.map(_.bundleOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
trait CanHaveScratchpadModule extends HasHellaCacheModule with HasICacheFrontendModule {
|
trait CanHaveScratchpadModule extends HasHellaCacheModule with HasICacheFrontendModule {
|
||||||
@ -137,4 +149,8 @@ trait CanHaveScratchpadModule extends HasHellaCacheModule with HasICacheFrontend
|
|||||||
val io: CanHaveScratchpadBundle
|
val io: CanHaveScratchpadBundle
|
||||||
|
|
||||||
outer.scratch.foreach { lm => dcachePorts += lm.module.io.dmem }
|
outer.scratch.foreach { lm => dcachePorts += lm.module.io.dmem }
|
||||||
|
outer.busErrorUnit.foreach { lm =>
|
||||||
|
lm.module.io.errors.dcache := outer.dcache.module.io.errors
|
||||||
|
lm.module.io.errors.icache := outer.frontend.module.io.errors
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ trait TileParams {
|
|||||||
val dcache: Option[DCacheParams]
|
val dcache: Option[DCacheParams]
|
||||||
val rocc: Seq[RoCCParams]
|
val rocc: Seq[RoCCParams]
|
||||||
val btb: Option[BTBParams]
|
val btb: Option[BTBParams]
|
||||||
|
val trace: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasTileParameters {
|
trait HasTileParameters {
|
||||||
@ -37,6 +38,7 @@ trait HasTileParameters {
|
|||||||
|
|
||||||
def xLen: Int = p(XLen)
|
def xLen: Int = p(XLen)
|
||||||
def xBytes: Int = xLen / 8
|
def xBytes: Int = xLen / 8
|
||||||
|
def iLen: Int = 32
|
||||||
def pgIdxBits: Int = 12
|
def pgIdxBits: Int = 12
|
||||||
def pgLevelBits: Int = 10 - log2Ceil(xLen / 32)
|
def pgLevelBits: Int = 10 - log2Ceil(xLen / 32)
|
||||||
def vaddrBits: Int = pgIdxBits + pgLevels * pgLevelBits
|
def vaddrBits: Int = pgIdxBits + pgLevels * pgLevelBits
|
||||||
@ -92,6 +94,10 @@ trait HasExternallyDrivenTileConstants extends Bundle with HasTileParameters {
|
|||||||
val reset_vector = UInt(INPUT, resetVectorLen)
|
val reset_vector = UInt(INPUT, resetVectorLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait CanHaveInstructionTracePort extends Bundle with HasTileParameters {
|
||||||
|
val trace = tileParams.trace.option(Vec(tileParams.core.retireWidth, new TracedInstruction).asOutput)
|
||||||
|
}
|
||||||
|
|
||||||
/** Base class for all Tiles that use TileLink */
|
/** Base class for all Tiles that use TileLink */
|
||||||
abstract class BaseTile(tileParams: TileParams)(implicit p: Parameters) extends BareTile
|
abstract class BaseTile(tileParams: TileParams)(implicit p: Parameters) extends BareTile
|
||||||
with HasTileParameters
|
with HasTileParameters
|
||||||
@ -102,6 +108,7 @@ abstract class BaseTile(tileParams: TileParams)(implicit p: Parameters) extends
|
|||||||
class BaseTileBundle[+L <: BaseTile](_outer: L) extends BareTileBundle(_outer)
|
class BaseTileBundle[+L <: BaseTile](_outer: L) extends BareTileBundle(_outer)
|
||||||
with HasTileLinkMasterPortBundle
|
with HasTileLinkMasterPortBundle
|
||||||
with HasExternallyDrivenTileConstants
|
with HasExternallyDrivenTileConstants
|
||||||
|
with CanHaveInstructionTracePort
|
||||||
|
|
||||||
class BaseTileModule[+L <: BaseTile, +B <: BaseTileBundle[L]](_outer: L, _io: () => B) extends BareTileModule(_outer, _io)
|
class BaseTileModule[+L <: BaseTile, +B <: BaseTileBundle[L]](_outer: L, _io: () => B) extends BareTileModule(_outer, _io)
|
||||||
with HasTileParameters
|
with HasTileParameters
|
||||||
|
@ -27,6 +27,7 @@ trait CoreParams {
|
|||||||
val nLocalInterrupts: Int
|
val nLocalInterrupts: Int
|
||||||
val nL2TLBEntries: Int
|
val nL2TLBEntries: Int
|
||||||
val jumpInFrontend: Boolean
|
val jumpInFrontend: Boolean
|
||||||
|
val tileControlAddr: Option[BigInt]
|
||||||
|
|
||||||
def instBytes: Int = instBits / 8
|
def instBytes: Int = instBits / 8
|
||||||
def fetchBytes: Int = fetchWidth * instBytes
|
def fetchBytes: Int = fetchWidth * instBytes
|
||||||
@ -75,5 +76,6 @@ trait HasCoreIO extends HasTileParameters {
|
|||||||
val ptw = new DatapathPTWIO().flip
|
val ptw = new DatapathPTWIO().flip
|
||||||
val fpu = new FPUCoreIO().flip
|
val fpu = new FPUCoreIO().flip
|
||||||
val rocc = new RoCCCoreIO().flip
|
val rocc = new RoCCCoreIO().flip
|
||||||
|
val trace = Vec(coreParams.retireWidth, new TracedInstruction).asOutput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ case class RocketTileParams(
|
|||||||
btb: Option[BTBParams] = Some(BTBParams()),
|
btb: Option[BTBParams] = Some(BTBParams()),
|
||||||
dataScratchpadBytes: Int = 0,
|
dataScratchpadBytes: Int = 0,
|
||||||
boundaryBuffers: Boolean = false,
|
boundaryBuffers: Boolean = false,
|
||||||
|
trace: Boolean = false,
|
||||||
name: Option[String] = Some("tile"),
|
name: Option[String] = Some("tile"),
|
||||||
externalMasterBuffers: Int = 0,
|
externalMasterBuffers: Int = 0,
|
||||||
externalSlaveBuffers: Int = 0) extends TileParams {
|
externalSlaveBuffers: Int = 0) extends TileParams {
|
||||||
@ -139,6 +140,7 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne
|
|||||||
val core = Module(p(BuildCore)(outer.p))
|
val core = Module(p(BuildCore)(outer.p))
|
||||||
decodeCoreInterrupts(core.io.interrupts) // Decode the interrupt vector
|
decodeCoreInterrupts(core.io.interrupts) // Decode the interrupt vector
|
||||||
core.io.hartid := io.hartid // Pass through the hartid
|
core.io.hartid := io.hartid // Pass through the hartid
|
||||||
|
io.trace.foreach { _ := core.io.trace }
|
||||||
outer.frontend.module.io.cpu <> core.io.imem
|
outer.frontend.module.io.cpu <> core.io.imem
|
||||||
outer.frontend.module.io.reset_vector := io.reset_vector
|
outer.frontend.module.io.reset_vector := io.reset_vector
|
||||||
outer.frontend.module.io.hartid := io.hartid
|
outer.frontend.module.io.hartid := io.hartid
|
||||||
@ -168,6 +170,7 @@ abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p:
|
|||||||
val rocket = LazyModule(new RocketTile(rtp, hartid))
|
val rocket = LazyModule(new RocketTile(rtp, hartid))
|
||||||
val masterNode: OutputNode[_,_,_,_,_]
|
val masterNode: OutputNode[_,_,_,_,_]
|
||||||
val slaveNode: InputNode[_,_,_,_,_]
|
val slaveNode: InputNode[_,_,_,_,_]
|
||||||
|
val intOutputNode = rocket.intOutputNode.map(dummy => IntOutputNode())
|
||||||
val asyncIntNode = IntInputNode()
|
val asyncIntNode = IntInputNode()
|
||||||
val periphIntNode = IntInputNode()
|
val periphIntNode = IntInputNode()
|
||||||
val coreIntNode = IntInputNode()
|
val coreIntNode = IntInputNode()
|
||||||
@ -195,10 +198,19 @@ abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def outputInterruptXingLatency: Int
|
||||||
|
|
||||||
|
rocket.intOutputNode.foreach { rocketIntOutputNode =>
|
||||||
|
val outXing = LazyModule(new IntXing(outputInterruptXingLatency))
|
||||||
|
intOutputNode.get := outXing.intnode
|
||||||
|
outXing.intnode := rocketIntOutputNode
|
||||||
|
}
|
||||||
|
|
||||||
lazy val module = new LazyModuleImp(this) {
|
lazy val module = new LazyModuleImp(this) {
|
||||||
val io = new CoreBundle with HasExternallyDrivenTileConstants {
|
val io = new CoreBundle with HasExternallyDrivenTileConstants with CanHaveInstructionTracePort {
|
||||||
val master = masterNode.bundleOut
|
val master = masterNode.bundleOut
|
||||||
val slave = slaveNode.bundleIn
|
val slave = slaveNode.bundleIn
|
||||||
|
val outputInterrupts = intOutputNode.map(_.bundleOut)
|
||||||
val asyncInterrupts = asyncIntNode.bundleIn
|
val asyncInterrupts = asyncIntNode.bundleIn
|
||||||
val periphInterrupts = periphIntNode.bundleIn
|
val periphInterrupts = periphIntNode.bundleIn
|
||||||
val coreInterrupts = coreIntNode.bundleIn
|
val coreInterrupts = coreIntNode.bundleIn
|
||||||
@ -206,6 +218,7 @@ abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p:
|
|||||||
// signals that do not change based on crossing type:
|
// signals that do not change based on crossing type:
|
||||||
rocket.module.io.hartid := io.hartid
|
rocket.module.io.hartid := io.hartid
|
||||||
rocket.module.io.reset_vector := io.reset_vector
|
rocket.module.io.reset_vector := io.reset_vector
|
||||||
|
io.trace.foreach { _ := rocket.module.io.trace.get }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,6 +237,8 @@ class SyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters)
|
|||||||
intXbar.intnode := xing.intnode
|
intXbar.intnode := xing.intnode
|
||||||
intXbar.intnode := periphIntNode
|
intXbar.intnode := periphIntNode
|
||||||
intXbar.intnode := coreIntNode
|
intXbar.intnode := coreIntNode
|
||||||
|
|
||||||
|
def outputInterruptXingLatency = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) {
|
class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) {
|
||||||
@ -251,6 +266,8 @@ class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters
|
|||||||
intXbar.intnode := asyncXing.intnode
|
intXbar.intnode := asyncXing.intnode
|
||||||
intXbar.intnode := periphXing.intnode
|
intXbar.intnode := periphXing.intnode
|
||||||
intXbar.intnode := coreIntNode
|
intXbar.intnode := coreIntNode
|
||||||
|
|
||||||
|
def outputInterruptXingLatency = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) {
|
class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) {
|
||||||
@ -279,4 +296,6 @@ class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Paramet
|
|||||||
intXbar.intnode := asyncXing.intnode
|
intXbar.intnode := asyncXing.intnode
|
||||||
intXbar.intnode := periphXing.intnode
|
intXbar.intnode := periphXing.intnode
|
||||||
intXbar.intnode := coreIntNode
|
intXbar.intnode := coreIntNode
|
||||||
|
|
||||||
|
def outputInterruptXingLatency = 1
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,9 @@ abstract class Decoding
|
|||||||
|
|
||||||
abstract class Code
|
abstract class Code
|
||||||
{
|
{
|
||||||
|
def canDetect: Boolean
|
||||||
|
def canCorrect: Boolean
|
||||||
|
|
||||||
def width(w0: Int): Int
|
def width(w0: Int): Int
|
||||||
def encode(x: UInt): UInt
|
def encode(x: UInt): UInt
|
||||||
def decode(x: UInt): Decoding
|
def decode(x: UInt): Decoding
|
||||||
@ -29,6 +32,9 @@ abstract class Code
|
|||||||
|
|
||||||
class IdentityCode extends Code
|
class IdentityCode extends Code
|
||||||
{
|
{
|
||||||
|
def canDetect = false
|
||||||
|
def canCorrect = false
|
||||||
|
|
||||||
def width(w0: Int) = w0
|
def width(w0: Int) = w0
|
||||||
def encode(x: UInt) = x
|
def encode(x: UInt) = x
|
||||||
def swizzle(x: UInt) = x
|
def swizzle(x: UInt) = x
|
||||||
@ -42,6 +48,9 @@ class IdentityCode extends Code
|
|||||||
|
|
||||||
class ParityCode extends Code
|
class ParityCode extends Code
|
||||||
{
|
{
|
||||||
|
def canDetect = true
|
||||||
|
def canCorrect = false
|
||||||
|
|
||||||
def width(w0: Int) = w0+1
|
def width(w0: Int) = w0+1
|
||||||
def encode(x: UInt) = Cat(x.xorR, x)
|
def encode(x: UInt) = Cat(x.xorR, x)
|
||||||
def swizzle(x: UInt) = Cat(false.B, x)
|
def swizzle(x: UInt) = Cat(false.B, x)
|
||||||
@ -55,6 +64,9 @@ class ParityCode extends Code
|
|||||||
|
|
||||||
class SECCode extends Code
|
class SECCode extends Code
|
||||||
{
|
{
|
||||||
|
def canDetect = true
|
||||||
|
def canCorrect = true
|
||||||
|
|
||||||
def width(k: Int) = {
|
def width(k: Int) = {
|
||||||
val m = log2Floor(k) + 1
|
val m = log2Floor(k) + 1
|
||||||
k + m + (if((1 << m) < m+k+1) 1 else 0)
|
k + m + (if((1 << m) < m+k+1) 1 else 0)
|
||||||
@ -101,6 +113,9 @@ class SECCode extends Code
|
|||||||
|
|
||||||
class SECDEDCode extends Code
|
class SECDEDCode extends Code
|
||||||
{
|
{
|
||||||
|
def canDetect = true
|
||||||
|
def canCorrect = true
|
||||||
|
|
||||||
private val sec = new SECCode
|
private val sec = new SECCode
|
||||||
private val par = new ParityCode
|
private val par = new ParityCode
|
||||||
|
|
||||||
|
@ -125,8 +125,10 @@ class SynchronizerShiftReg(w: Int = 1, sync: Int = 3) extends AbstractPipelineRe
|
|||||||
|
|
||||||
|
|
||||||
object SynchronizerShiftReg {
|
object SynchronizerShiftReg {
|
||||||
def apply [T <: Chisel.Data](in: T, sync: Int = 3, name: Option[String] = None): T =
|
def apply [T <: Chisel.Data](in: T, sync: Int = 3, name: Option[String] = None): T = {
|
||||||
AbstractPipelineReg(new SynchronizerShiftReg(in.getWidth, sync), in, name)
|
if (sync == 0) in
|
||||||
|
else AbstractPipelineReg(new SynchronizerShiftReg(in.getWidth, sync), in, name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SyncResetSynchronizerShiftReg(w: Int = 1, sync: Int = 3, init: Int = 0) extends AbstractPipelineReg(w) {
|
class SyncResetSynchronizerShiftReg(w: Int = 1, sync: Int = 3, init: Int = 0) extends AbstractPipelineReg(w) {
|
||||||
|
Loading…
Reference in New Issue
Block a user