未验证 提交 eb021a4b 编写于 作者: Y Yinan Xu 提交者: GitHub

Merge pull request #699 from RISCVERS/add-beu

Add bus error unit and connect ecc errors to beu
package system
import chipsalliance.rocketchip.config.Parameters
import device.{AXI4Timer, TLTimer, AXI4Plic}
import device.{AXI4Plic, AXI4Timer, TLTimer}
import chisel3._
import chisel3.util._
import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp}
import freechips.rocketchip.tilelink.{BankBinder, TLBuffer, TLBundleParameters, TLCacheCork, TLClientNode, TLFilter, TLFuzzer, TLIdentityNode, TLToAXI4, TLWidthWidget, TLXbar}
import utils.{DebugIdentityNode, DataDontCareNode}
import utils.{DataDontCareNode, DebugIdentityNode}
import utils.XSInfo
import xiangshan.{HasXSParameter, XSCore, HasXSLog, DifftestBundle}
import xiangshan.{DifftestBundle, HasXSLog, HasXSParameter, XSBundle, XSCore}
import xiangshan.cache.prefetch._
import sifive.blocks.inclusivecache.{CacheParameters, InclusiveCache, InclusiveCacheMicroParameters}
import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp}
import freechips.rocketchip.devices.tilelink.{DevNullParams, TLError}
import freechips.rocketchip.amba.axi4.{AXI4Deinterleaver, AXI4Fragmenter, AXI4IdIndexer, AXI4IdentityNode, AXI4ToTL, AXI4UserYanker}
import freechips.rocketchip.diplomaticobjectmodel.logicaltree.GenericLogicalTreeNode
import freechips.rocketchip.interrupts.{IntSinkNode, IntSinkParameters, IntSinkPortParameters, IntSinkPortSimple}
import freechips.rocketchip.tile.{BusErrorUnit, BusErrorUnitParams, BusErrors, L1BusErrors}
case class SoCParameters
(
......@@ -34,15 +37,26 @@ trait HasSoCParameter extends HasXSParameter{
class ILABundle extends Bundle {}
class DummyCore()(implicit p: Parameters) extends LazyModule {
val mem = TLFuzzer(nOperations = 10)
val mmio = TLFuzzer(nOperations = 10)
lazy val module = new LazyModuleImp(this){
}
class L1CacheErrorInfo extends XSBundle{
val paddr = Valid(UInt(PAddrBits.W))
// for now, we only detect ecc
val ecc_error = Valid(Bool())
}
class XSL1BusErrors(val nCores: Int) extends BusErrors {
val icache = Vec(nCores, new L1CacheErrorInfo)
val dcache = Vec(nCores, new L1CacheErrorInfo)
override def toErrorList: List[Option[(ValidIO[UInt], String, String)]] =
List.tabulate(nCores){i =>
List(
Some(icache(i).paddr, s"IBUS_$i", s"Icache_$i bus error"),
Some(icache(i).ecc_error, s"I_ECC_$i", s"Icache_$i ecc error"),
Some(dcache(i).paddr, s"DBUS_$i", s"Dcache_$i bus error"),
Some(dcache(i).ecc_error, s"D_ECC_$i", s"Dcache_$i ecc error")
)
}.flatten
}
class XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter {
// CPU Cores
......@@ -141,6 +155,7 @@ class XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter {
AXI4UserYanker() :=
TLToAXI4() :=
TLWidthWidget(L3BusWidth / 8) :=
TLBuffer() :=
TLCacheCork() :=
bankedNode
}
......@@ -153,12 +168,27 @@ class XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter {
clint.node := mmioXbar
extDev := AXI4UserYanker() := TLToAXI4() := mmioXbar
val fakeTreeNode = new GenericLogicalTreeNode
val beu = LazyModule(
new BusErrorUnit(new XSL1BusErrors(NumCores), BusErrorUnitParams(0x38010000), fakeTreeNode))
beu.node := mmioXbar
class BeuSinkNode()(implicit p: Parameters) extends LazyModule {
val intSinkNode = IntSinkNode(IntSinkPortSimple())
lazy val module = new LazyModuleImp(this){
val interrupt = IO(Output(Bool()))
interrupt := intSinkNode.in.head._1.head
}
}
val beuSink = LazyModule(new BeuSinkNode())
beuSink.intSinkNode := beu.intNode
val plic = LazyModule(new AXI4Plic(
Seq(AddressSet(0x3c000000L, 0x03ffffffL)),
sim = !env.FPGAPlatform
))
val plicIdentity = AXI4IdentityNode()
plic.node := plicIdentity := AXI4UserYanker() := TLToAXI4() := mmioXbar
plic.node := AXI4UserYanker() := TLToAXI4() := mmioXbar
lazy val module = new LazyModuleImp(this){
val io = IO(new Bundle{
......@@ -174,12 +204,14 @@ class XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter {
val trapIO1 = IO(new xiangshan.TrapIO())
val trapIO = Seq(trapIO0, trapIO1)
plic.module.io.extra.get.intrVec <> RegNext(RegNext(io.extIntrs))
plic.module.io.extra.get.intrVec <> RegNext(beuSink.module.interrupt)
for (i <- 0 until NumCores) {
xs_core(i).module.io.hartId := i.U
xs_core(i).module.io.externalInterrupt.mtip := clint.module.io.mtip(i)
xs_core(i).module.io.externalInterrupt.msip := clint.module.io.msip(i)
beu.module.io.errors.icache(i) := RegNext(xs_core(i).module.io.icache_error)
beu.module.io.errors.dcache(i) := RegNext(xs_core(i).module.io.dcache_error)
// xs_core(i).module.io.externalInterrupt.meip := RegNext(RegNext(io.meip(i)))
xs_core(i).module.io.externalInterrupt.meip := plic.module.io.extra.get.meip(i)
l2prefetcher(i).module.io.enable := RegNext(xs_core(i).module.io.l2_pf_enable)
......
......@@ -6,11 +6,15 @@ import xiangshan._
import system._
import chisel3.stage.ChiselGeneratorAnnotation
import chipsalliance.rocketchip.config
import device.{TLTimer, AXI4Plic}
import chipsalliance.rocketchip.config.Config
import device.{AXI4Plic, TLTimer}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.amba.axi4._
import freechips.rocketchip.devices.tilelink.{DevNullParams, TLError}
import freechips.rocketchip.diplomaticobjectmodel.logicaltree.GenericLogicalTreeNode
import freechips.rocketchip.interrupts.{IntSinkNode, IntSinkPortSimple}
import freechips.rocketchip.tile.{BusErrorUnit, BusErrorUnitParams, XLen}
import sifive.blocks.inclusivecache._
import xiangshan.cache.prefetch.L2Prefetcher
......@@ -48,12 +52,15 @@ class XSCoreWithL2Imp(outer: XSCoreWithL2) extends LazyModuleImp(outer)
val io = IO(new Bundle {
val hartId = Input(UInt(64.W))
val externalInterrupt = new ExternalInterruptIO
val icache_error, dcache_error = new L1CacheErrorInfo
})
outer.core.module.io.hartId := io.hartId
outer.core.module.io.externalInterrupt := io.externalInterrupt
outer.l2prefetcher.module.io.enable := RegNext(outer.core.module.io.l2_pf_enable)
outer.l2prefetcher.module.io.in <> outer.l2cache.module.io
io.icache_error <> outer.core.module.io.icache_error
io.dcache_error <> outer.core.module.io.dcache_error
}
......@@ -126,6 +133,7 @@ trait HaveAXI4MemPort {
AXI4Deinterleaver(L3BlockSize) :=*
TLToAXI4() :=*
TLWidthWidget(L3BusWidth / 8) :=*
TLBuffer() :=*
TLCacheCork() :=*
bankedNode
......@@ -167,7 +175,7 @@ class XSTop()(implicit p: config.Parameters) extends BaseXSSoc()
with HaveAXI4MemPort
with HaveAXI4PeripheralPort
with HaveSlaveAXI4Port
{
{
println(s"FPGASoC cores: $NumCores banks: $L3NBanks block size: $L3BlockSize bus size: $L3BusWidth")
......@@ -185,6 +193,21 @@ class XSTop()(implicit p: config.Parameters) extends BaseXSSoc()
))
clint.node := peripheralXbar
val fakeTreeNode = new GenericLogicalTreeNode
val beu = LazyModule(
new BusErrorUnit(new XSL1BusErrors(NumCores), BusErrorUnitParams(0x38010000), fakeTreeNode))
beu.node := peripheralXbar
class BeuSinkNode()(implicit p: config.Parameters) extends LazyModule {
val intSinkNode = IntSinkNode(IntSinkPortSimple())
lazy val module = new LazyModuleImp(this){
val interrupt = IO(Output(Bool()))
interrupt := intSinkNode.in.head._1.head
}
}
val beuSink = LazyModule(new BeuSinkNode())
beuSink.intSinkNode := beu.intNode
val plic = LazyModule(new AXI4Plic(
Seq(AddressSet(0x3c000000L, 0x03ffffffL)),
sim = !env.FPGAPlatform
......@@ -221,6 +244,8 @@ class XSTop()(implicit p: config.Parameters) extends BaseXSSoc()
core_with_l2(i).module.io.externalInterrupt.mtip := clint.module.io.mtip(i)
core_with_l2(i).module.io.externalInterrupt.msip := clint.module.io.msip(i)
core_with_l2(i).module.io.externalInterrupt.meip := plic.module.io.extra.get.meip(i)
beu.module.io.errors.icache(i) := RegNext(core_with_l2(i).module.io.icache_error)
beu.module.io.errors.dcache(i) := RegNext(core_with_l2(i).module.io.dcache_error)
}
dontTouch(io.extIntrs)
......@@ -236,7 +261,9 @@ object TopMain extends App {
}
)
val otherArgs = args.filterNot(_ == "--dual-core")
implicit val p = config.Parameters.empty
implicit val p = new Config((_, _, _) => {
case XLen => 64
})
XiangShanStage.execute(otherArgs, Seq(
ChiselGeneratorAnnotation(() => {
val soc = LazyModule(new XSTop())
......
......@@ -29,7 +29,8 @@ object AddressSpace {
MemMap("h00_3100_0000", "h00_3111_FFFF", "h0", "MMIO", "RW"),
MemMap("h00_3112_0000", "h00_37FF_FFFF", "h0", "Reserved", ""),
MemMap("h00_3800_0000", "h00_3800_FFFF", "h0", "CLINT", "RW"),
MemMap("h00_3801_0000", "h00_3BFF_FFFF", "h0", "Reserved", ""),
MemMap("h00_3801_0000", "h00_3801_FFFF", "h0", "BEU", "RW"),
MemMap("h00_3802_0000", "h00_3BFF_FFFF", "h0", "Reserved", ""),
MemMap("h00_3C00_0000", "h00_3FFF_FFFF", "h0", "PLIC", "RW"),
MemMap("h00_4000_0000", "h00_7FFF_FFFF", "h0", "PCIe", "RW"),
MemMap("h00_8000_0000", "h1F_FFFF_FFFF", "h0", "DDR", "RWXIDSA"),
......
......@@ -15,6 +15,7 @@ import xiangshan.cache.prefetch._
import chipsalliance.rocketchip.config
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
import freechips.rocketchip.tile.HasFPUParameters
import system.L1CacheErrorInfo
import utils._
object hartIdCore extends (() => Int) {
......@@ -314,22 +315,6 @@ case class EnviromentParameters
DualCore: Boolean = false
)
// object AddressSpace extends HasXSParameter {
// // (start, size)
// // address out of MMIO will be considered as DRAM
// def mmio = List(
// (0x00000000L, 0x40000000L), // internal devices, such as CLINT and PLIC
// (0x40000000L, 0x40000000L) // external devices
// )
// def isMMIO(addr: UInt): Bool = mmio.map(range => {
// require(isPow2(range._2))
// val bits = log2Up(range._2)
// (addr ^ range._1.U)(PAddrBits-1, bits) === 0.U
// }).reduce(_ || _)
// }
class XSCore()(implicit p: config.Parameters) extends LazyModule
with HasXSParameter
with HasExeBlockHelper {
......@@ -355,6 +340,7 @@ class XSCoreImp(outer: XSCore) extends LazyModuleImp(outer)
val hartId = Input(UInt(64.W))
val externalInterrupt = new ExternalInterruptIO
val l2_pf_enable = Output(Bool())
val icache_error, dcache_error = Output(new L1CacheErrorInfo)
})
val difftestIO = IO(new DifftestBundle())
......@@ -391,6 +377,18 @@ class XSCoreImp(outer: XSCore) extends LazyModuleImp(outer)
val l1pluscache = outer.l1pluscache.module
val ptw = outer.ptw.module
//TODO: connect these signals
def errorOR(src1: L1CacheErrorInfo, src2: L1CacheErrorInfo) : L1CacheErrorInfo = {
val out = Wire(new L1CacheErrorInfo)
out.ecc_error.valid := src1.ecc_error.valid || src2.ecc_error.valid
out.ecc_error.bits := true.B
out.paddr.valid := out.ecc_error.valid
out.paddr.bits := Mux(src1.ecc_error.valid, src1.paddr.bits, src2.paddr.bits)
out
}
io.icache_error <> errorOR(src1=frontend.io.error, src2=l1pluscache.io.error)
io.dcache_error <> memBlock.io.error
frontend.io.backend <> ctrlBlock.io.frontend
frontend.io.sfence <> integerBlock.io.fenceio.sfence
frontend.io.tlbCsr <> integerBlock.io.csrio.tlb
......
......@@ -5,14 +5,15 @@ import chisel3.util._
import chipsalliance.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
import freechips.rocketchip.tile.HasFPUParameters
import system.L1CacheErrorInfo
import xiangshan._
import xiangshan.backend.exu.Exu.{loadExuConfigs, storeExuConfigs}
import xiangshan.backend.roq.{RoqPtr, RoqLsqIO}
import xiangshan.backend.roq.{RoqLsqIO, RoqPtr}
import xiangshan.backend.exu._
import xiangshan.cache._
import xiangshan.mem._
import xiangshan.backend.fu.{HasExceptionNO, FenceToSbuffer}
import xiangshan.backend.issue.{ReservationStation}
import xiangshan.backend.fu.{FenceToSbuffer, HasExceptionNO}
import xiangshan.backend.issue.ReservationStation
import xiangshan.backend.regfile.RfReadPort
class LsBlockToCtrlIO extends XSBundle {
......@@ -82,6 +83,7 @@ class MemBlockImp(outer: MemBlock) extends LazyModuleImp(outer)
}
val csrCtrl = Flipped(new CustomCSRCtrlIO)
val error = new L1CacheErrorInfo
})
val difftestIO = IO(new Bundle() {
val fromSbuffer = new Bundle() {
......@@ -110,6 +112,8 @@ class MemBlockImp(outer: MemBlock) extends LazyModuleImp(outer)
val dcache = outer.dcache.module
val uncache = outer.uncache.module
io.error <> dcache.io.error
val redirect = io.fromCtrlBlock.redirect
val loadUnits = Seq.fill(exuParameters.LduCnt)(Module(new LoadUnit))
......
......@@ -3,7 +3,8 @@ package xiangshan.cache
import chisel3._
import chisel3.util._
import freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut}
import utils.{Code, ReplacementPolicy, XSDebug, SRAMTemplate, ParallelOR}
import system.L1CacheErrorInfo
import utils.{Code, ParallelOR, ReplacementPolicy, SRAMTemplate, XSDebug}
import scala.math.max
......@@ -126,6 +127,7 @@ abstract class AbstractDataArray extends DCacheModule {
val write = Flipped(DecoupledIO(new L1DataWriteReq))
val resp = Output(Vec(LoadPipelineWidth, Vec(blockRows, Bits(encRowBits.W))))
val nacks = Output(Vec(LoadPipelineWidth, Bool()))
val errors = Output(Vec(LoadPipelineWidth, new L1CacheErrorInfo))
})
def pipeMap[T <: Data](f: Int => T) = VecInit((0 until LoadPipelineWidth).map(f))
......@@ -265,6 +267,7 @@ class DuplicatedDataArray extends AbstractDataArray {
assert(!(RegNext(io.read(j).fire() && PopCount(io.read(j).bits.way_en) > 1.U)))
val way_en = RegNext(io.read(j).bits.way_en)
val row_error = Wire(Vec(blockRows, Vec(rowWords, Bool())))
for (r <- 0 until blockRows) {
val ecc_array = Module(new SRAMTemplate(
Vec(rowWords, Bits(eccBits.W)),
......@@ -308,8 +311,16 @@ class DuplicatedDataArray extends AbstractDataArray {
ecc_resp_chosen(k) := Mux1H(way_en, ecc_resp(k))
}
io.resp(j)(r) := Cat((0 until rowWords) reverseMap {
k => Cat(ecc_resp_chosen(k), data_resp_chosen(k))
k => {
val data = Cat(ecc_resp_chosen(k), data_resp_chosen(k))
row_error(r)(k) := dcacheParameters.dataCode.decode(data).error && RegNext(rmask(r))
data
}
})
io.errors(j).ecc_error.valid := RegNext(io.read(j).fire()) && Cat(row_error.flatten).orR()
io.errors(j).ecc_error.bits := true.B
io.errors(j).paddr.valid := io.errors(j).ecc_error.valid
io.errors(j).paddr.bits := RegNext(io.read(j).bits.addr)
}
io.nacks(j) := false.B
......@@ -325,6 +336,7 @@ class L1MetadataArray(onReset: () => L1Metadata) extends DCacheModule {
val read = Flipped(Decoupled(new L1MetaReadReq))
val write = Flipped(Decoupled(new L1MetaWriteReq))
val resp = Output(Vec(nWays, UInt(encMetaBits.W)))
val error = Output(new L1CacheErrorInfo)
})
val rst_cnt = RegInit(0.U(log2Up(nSets + 1).W))
val rst = rst_cnt < nSets.U
......@@ -352,6 +364,13 @@ class L1MetadataArray(onReset: () => L1Metadata) extends DCacheModule {
tag_array.io.r.req.valid := ren
tag_array.io.r.req.bits.apply(setIdx = io.read.bits.idx)
io.resp := tag_array.io.r.resp.data
val ecc_errors = tag_array.io.r.resp.data.zipWithIndex.map({ case (d, w) =>
cacheParams.tagCode.decode(d).error && RegNext(io.read.bits.way_en(w))
})
io.error.ecc_error.valid := RegNext(io.read.fire()) && Cat(ecc_errors).orR()
io.error.ecc_error.bits := true.B
io.error.paddr.valid := io.error.ecc_error.valid
io.error.paddr.bits := Cat(io.read.bits.idx, 0.U(pgUntagBits.W))
io.write.ready := !rst
io.read.ready := !wen
......@@ -394,6 +413,7 @@ class DuplicatedMetaArray extends DCacheModule {
val read = Vec(LoadPipelineWidth, Flipped(DecoupledIO(new L1MetaReadReq)))
val write = Flipped(DecoupledIO(new L1MetaWriteReq))
val resp = Output(Vec(LoadPipelineWidth, Vec(nWays, UInt(encMetaBits.W))))
val errors = Output(Vec(LoadPipelineWidth, new L1CacheErrorInfo))
})
val meta = Seq.fill(LoadPipelineWidth) {
Module(new L1MetadataArray(onReset _))
......@@ -405,6 +425,7 @@ class DuplicatedMetaArray extends DCacheModule {
meta(w).io.write.bits := io.write.bits
meta(w).io.read <> io.read(w)
io.resp(w) <> meta(w).io.resp
io.errors(w) <> meta(w).io.error
}
// io.write.ready := VecInit(meta.map(_.io.write.ready)).asUInt.andR
io.write.ready := true.B
......
......@@ -6,8 +6,8 @@ import chisel3.util._
import xiangshan._
import utils._
import freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp, TransferSizes}
import freechips.rocketchip.tilelink.{TLClientNode, TLClientParameters,
TLMasterParameters, TLMasterPortParameters, TLArbiter, TLMessages}
import freechips.rocketchip.tilelink.{TLArbiter, TLClientNode, TLClientParameters, TLMasterParameters, TLMasterPortParameters, TLMessages}
import system.L1CacheErrorInfo
// memory request in word granularity(load, mmio, lr/sc, atomics)
class DCacheWordReq extends DCacheBundle
......@@ -107,6 +107,7 @@ class DCacheToLsuIO extends DCacheBundle {
class DCacheIO extends DCacheBundle {
val lsu = new DCacheToLsuIO
val error = new L1CacheErrorInfo
}
......@@ -141,7 +142,8 @@ class DCacheImp(outer: DCache) extends LazyModuleImp(outer) with HasDCacheParame
dataArray.dump()
metaArray.dump()
*/
val errors = dataArray.io.errors ++ metaArray.io.errors
io.error <> RegNext(Mux1H(errors.map(e => e.ecc_error.valid -> e)))
//----------------------------------------
// core modules
......
......@@ -8,6 +8,8 @@ import xiangshan.frontend._
import utils._
import chisel3.ExcitingUtils._
import bus.tilelink.TLParameters
import system.L1CacheErrorInfo
case class ICacheParameters(
nSets: Int = 64,
......@@ -119,6 +121,7 @@ class ICacheIO extends ICacheBundle
val prev_pc = Input(UInt(VAddrBits.W))
val prev_ipf = Input(Bool())
val pd_out = Output(new PreDecodeResp)
val error = new L1CacheErrorInfo
}
class ICacheMetaReadBundle extends ICacheBundle
......@@ -182,7 +185,6 @@ class ICacheMetaArray extends ICacheArray
// read
//do Parity decoding after way choose
// do not read and write in the same cycle: when write SRAM disable read
val readNextReg = RegNext(io.read.fire())
val rtags = metaArray.io.r.resp.asTypeOf(Vec(nWays,UInt(encMetaBits.W)))
val rtags_decoded = rtags.map{ wtag =>cacheParams.dataCode.decode(wtag)}
val rtags_wrong = rtags_decoded.map{ wtag_decoded => wtag_decoded.error}
......@@ -192,7 +194,7 @@ class ICacheMetaArray extends ICacheArray
metaArray.io.r.req.bits.apply(setIdx=io.read.bits)
io.read.ready := !io.write.valid
io.readResp.tags := rtags_corrected.asTypeOf(Vec(nWays,UInt(tagBits.W)))
(0 until nWays).map{ w => io.readResp.errors(w) := readNextReg && rtags_wrong(w)}
(0 until nWays).map{ w => io.readResp.errors(w) := RegNext(io.read.fire()) && rtags_wrong(w)}
//write
val write = io.write.bits
......@@ -223,7 +225,6 @@ class ICacheDataArray extends ICacheArray
// read
// do Parity decoding after way choose
// do not read and write in the same cycle: when write SRAM disable read
val readNextReg = RegNext(io.read.fire())
val rdata_wrong = Wire(Vec(nWays, UInt((nBanks * bankUnitNum).W)))
val rdatas = VecInit((0 until nWays).map( w =>
VecInit( (0 until nBanks).map( b =>
......@@ -263,7 +264,7 @@ class ICacheDataArray extends ICacheArray
}
io.read.ready := !io.write.valid
(0 until nWays).map{ w => io.readResp.errors(w) := readNextReg && rdata_wrong(w).orR }
(0 until nWays).map{ w => io.readResp.errors(w) := RegNext(io.read.fire()) && rdata_wrong(w).orR }
//write
val write = io.write.bits
......@@ -291,6 +292,26 @@ class ICacheDataArray extends ICacheArray
io.write.ready := DontCare
}
class ICacheErrorAbiter extends ICacheModule
{
val io = IO(new Bundle{
val meta_ways_error = Flipped(Valid(Vec(nWays,Bool())))
val data_ways_error = Flipped(Valid(Vec(nWays,Bool())))
val way_enable = Input(UInt(nWays.W))
val paddr = Input(UInt(VAddrBits.W))
val output = Output(new L1CacheErrorInfo)
})
val pipe_enable = io.meta_ways_error.valid //only state 2 can generate error
val meta_error = Mux1H(io.way_enable, io.meta_ways_error.bits)
val data_error = Mux1H(io.way_enable, io.data_ways_error.bits)
io.output.ecc_error.valid := (meta_error || data_error) && pipe_enable
io.output.ecc_error.bits := true.B
io.output.paddr.valid := io.output.ecc_error.valid
io.output.paddr.bits := io.paddr
}
/* ------------------------------------------------------------
* This module is a SRAM with 4-way associated mapping
* The hardware implementation of ICache
......@@ -388,6 +409,18 @@ class ICache extends ICacheModule
val waymask = Mux(hasIcacheException,1.U(nWays.W),Mux(s2_hit, hitVec.asUInt, Mux(hasInvalidWay, refillInvalidWaymask, victimWayMask)))
//Parity/ECC error output
val errorArbiter = Module(new ICacheErrorAbiter)
errorArbiter.io.meta_ways_error.valid := RegNext(s2_hit)
errorArbiter.io.meta_ways_error.bits := RegNext(metaArray.io.readResp.errors)
errorArbiter.io.data_ways_error.valid := RegNext(s2_hit)
errorArbiter.io.data_ways_error.bits := RegNext(dataArray.io.readResp.errors)
errorArbiter.io.way_enable := RegNext(hitVec.asUInt)
errorArbiter.io.paddr := RegNext(s2_tlb_resp.paddr)
io.error <> errorArbiter.io.output
assert(!(s2_hit && s2_mmio),"MMIO address should not hit in icache")
//----------------------------
......@@ -406,12 +439,8 @@ class ICache extends ICacheModule
val s3_has_exception = RegEnable(next= hasIcacheException,init=false.B,enable=s2_fire)
val s3_idx = get_idx(s3_req_pc)
val s3_data = datas
val s3_meta_errors = RegEnable(next=metaArray.io.readResp.errors, init= 0.U.asTypeOf(Vec(nWays,Bool())), enable=s2_fire)
val s3_data_errors = RegEnable(next=dataArray.io.readResp.errors, init= 0.U.asTypeOf(Vec(nWays,Bool())), enable=s2_fire)
val s3_meta_wrong = Mux1H(s3_wayMask, s3_meta_errors) && s3_hit
val s3_data_wrong = Mux1H(s3_wayMask, s3_data_errors) && s3_hit
val exception = (s3_has_exception || s3_meta_wrong || s3_data_wrong) && s3_valid
val exception = s3_has_exception && s3_valid
when(s3_flush) { s3_valid := false.B }
......@@ -524,35 +553,11 @@ class ICache extends ICacheModule
s3_miss := s3_valid && !s3_hit && !s3_mmio && !exception && !useRefillReg
/* mmio response output
* cut the mmio response data cacheline into a fetch packet for responsing to predecoder
* TODO: no need to wait for a whole fetch packet(once per beat)?
*/
def cutHelperMMIO(sourceVec: Vec[UInt], pc: UInt, mask: UInt) = {
val sourceVec_inst = Wire(Vec(mmioBeats * mmioBusBytes/instBytes,UInt(insLen.W)))
(0 until mmioBeats).foreach{ i =>
(0 until mmioBusBytes/instBytes).foreach{ j =>
sourceVec_inst(i*mmioBusBytes/instBytes + j) := sourceVec(i)(j*insLen+insLen-1, j*insLen)
}
}
val cutPacket = WireInit(VecInit(Seq.fill(PredictWidth){0.U(insLen.W)}))
val insLenLog = log2Ceil(insLen/8)
val start = Cat(0.U(2.W),(pc >> insLenLog.U)(log2Ceil(mmioBusBytes/instBytes) -1, 0)) //4bit
val outMask = mask >> start
(0 until PredictWidth ).foreach{ i =>
cutPacket(i) := Mux(outMask(i).asBool,sourceVec_inst(start + i.U),0.U)
}
(cutPacket.asUInt, outMask.asUInt)
}
val mmioDataVec = io.mmio_grant.bits.data.asTypeOf(Vec(mmioBeats,UInt(mmioBusWidth.W)))
val mmio_packet = io.mmio_grant.bits.data//cutHelperMMIO(mmioDataVec, s3_req_pc, mmioMask)
XSDebug("mmio data %x\n", mmio_packet)
val pds = Seq.fill(nWays)(Module(new PreDecode))
for (i <- 0 until nWays) {
val wayResp = Wire(new ICacheResp)
......@@ -562,8 +567,7 @@ class ICache extends ICacheModule
wayResp.data := Mux(s3_valid && s3_hit, wayData, Mux(s3_mmio ,mmio_packet ,refillData))
wayResp.mask := s3_req_mask
wayResp.ipf := s3_exception_vec(pageFault)
wayResp.acf := s3_exception_vec(accessFault) || s3_meta_wrong || s3_data_wrong
//|| (icacheMissQueue.io.resp.valid && icacheMissQueue.io.resp.bits.eccWrong)
wayResp.acf := s3_exception_vec(accessFault)
wayResp.mmio := s3_mmio
pds(i).io.in := wayResp
pds(i).io.prev <> io.prev
......@@ -587,8 +591,7 @@ class ICache extends ICacheModule
io.resp.bits.pc := s3_req_pc
io.resp.bits.data := DontCare
io.resp.bits.ipf := s3_tlb_resp.excp.pf.instr
io.resp.bits.acf := s3_exception_vec(accessFault) || s3_meta_wrong || s3_data_wrong
//|| (icacheMissQueue.io.resp.valid && icacheMissQueue.io.resp.bits.eccWrong)
io.resp.bits.acf := s3_exception_vec(accessFault)
io.resp.bits.mmio := s3_mmio
//to itlb
......
......@@ -60,7 +60,6 @@ class IcacheMissReq extends ICacheBundle
class IcacheMissResp extends ICacheBundle
{
val data = UInt(blockBits.W)
val eccWrong = Bool()
val clientID = UInt(2.W)
}
......@@ -95,7 +94,6 @@ class IcacheMissEntry extends ICacheMissQueueModule
val readBeatCnt = Counter(refillCycles)
//val respDataReg = Reg(Vec(refillCycles,UInt(beatBits.W)))
val respDataReg = Reg(UInt(blockBits.W))
val eccWrongReg = RegInit(false.B)
//initial
io.resp.bits := DontCare
......@@ -131,7 +129,6 @@ class IcacheMissEntry extends ICacheMissQueueModule
is(s_memReadResp){
when (io.mem_grant.bits.id === io.id && io.mem_grant.fire()) {
respDataReg := io.mem_grant.bits.data
eccWrongReg := io.mem_grant.bits.eccWrong
state := Mux(needFlush || io.flush,s_wait_resp,s_write_back)
}
}
......@@ -145,7 +142,6 @@ class IcacheMissEntry extends ICacheMissQueueModule
is(s_wait_resp){
io.resp.bits.data := respDataReg.asUInt
io.resp.bits.eccWrong := eccWrongReg
io.resp.bits.clientID := req.clientID
when(io.resp.fire() || needFlush ){ state := s_idle }
}
......
......@@ -4,6 +4,7 @@ import chisel3._
import chisel3.util._
import utils.{Code, ReplacementPolicy, HasTLDump, XSDebug, SRAMTemplate, XSPerf}
import xiangshan.{HasXSLog}
import system.L1CacheErrorInfo
import chipsalliance.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, IdRange}
......@@ -82,13 +83,15 @@ abstract class L1plusCacheBundle extends L1CacheBundle
class L1plusCacheMetadata extends L1plusCacheBundle {
val valid = Bool()
val tag = UInt(tagBits.W)
val error = Bool()
}
object L1plusCacheMetadata {
def apply(tag: Bits, valid: Bool) = {
def apply(tag: Bits, valid: Bool, error :Bool) = {
val meta = Wire(new L1plusCacheMetadata)
meta.tag := tag
meta.valid := valid
meta.error := error
meta
}
}
......@@ -271,10 +274,14 @@ class L1plusCacheMetadataArray extends L1plusCacheModule {
tag_array.io.r.req.bits.apply(setIdx=io.read.bits.tagIdx)
val rtags = tag_array.io.r.resp.data.map(rdata =>
cacheParams.tagCode.decode(rdata).corrected)
val rtag_errors = tag_array.io.r.resp.data.map(rdata =>
cacheParams.tagCode.decode(rdata).error)
for (i <- 0 until nWays) {
io.resp(i).valid := valid_array(io.read.bits.validIdx)(i)
io.resp(i).tag := rtags(i)
io.resp(i).error := rtag_errors(i)
}
// we use single port SRAM
......@@ -324,11 +331,10 @@ class L1plusCacheReq extends L1plusCacheBundle
class L1plusCacheResp extends L1plusCacheBundle
{
val data = UInt((cfg.blockBytes * 8).W)
val eccWrong = Bool()
val id = UInt(idWidth.W)
override def toPrintable: Printable = {
p"id=${Binary(id)} data=${Hexadecimal(data)} eccWrong=${Binary(eccWrong)}"
p"id=${Binary(id)} data=${Hexadecimal(data)} "
}
}
......@@ -338,6 +344,7 @@ class L1plusCacheIO extends L1plusCacheBundle
val resp = Flipped(DecoupledIO(new L1plusCacheResp))
val flush = Output(Bool())
val empty = Input(Bool())
val error = Flipped(new L1CacheErrorInfo)
override def toPrintable: Printable = {
p"req: v=${req.valid} r=${req.ready} ${req.bits} " +
......@@ -401,6 +408,7 @@ class L1plusCacheImp(outer: L1plusCache) extends LazyModuleImp(outer) with HasL1
// response
io.resp <> resp_arb.io.out
io.error <> pipe.io.error
resp_arb.io.in(0) <> pipe.io.resp
resp_arb.io.in(1) <> missQueue.io.resp
......@@ -490,6 +498,7 @@ class L1plusCachePipe extends L1plusCacheModule
val miss_meta_write = Flipped(ValidIO(new L1plusCacheMetaWriteReq))
val inflight_req_idxes = Output(Vec(2, Valid(UInt())))
val empty = Output(Bool())
val error = new L1CacheErrorInfo
})
val s0_passdown = Wire(Bool())
......@@ -548,11 +557,14 @@ class L1plusCachePipe extends L1plusCacheModule
val s1_tag_eq_way = wayMap((w: Int) => meta_resp(w).tag === (get_tag(s1_addr))).asUInt
val s1_tag_match_way = wayMap((w: Int) => s1_tag_eq_way(w) && meta_resp(w).valid).asUInt
val s1_meta_ecc = VecInit(meta_resp.map{ w => w.error})
s1_passdown := s1_valid && (!s2_valid || s2_passdown)
// stage 2
val s2_req = RegEnable(s1_req, s1_passdown)
val s2_valid_reg = RegEnable(s1_valid, init=false.B, enable=s1_passdown)
val s2_meta_ecc = RegEnable(s1_meta_ecc, init=0.U.asTypeOf(Vec(nWays, Bool())), enable=s1_passdown)
when (s2_passdown && !s1_passdown) {
s2_valid_reg := false.B
}
......@@ -587,15 +599,23 @@ class L1plusCachePipe extends L1plusCacheModule
val s2_data_wrong = Cat((0 until blockRows).reverse map { r =>
val data = s2_data(r)
val decoded = cacheParams.dataCode.decode(data)
assert(!(s2_valid && s2_hit && decoded.error))
//assert(!(s2_valid && s2_hit && decoded.error))
decoded.error
})
io.resp.valid := s2_valid && s2_hit
io.resp.bits.data := s2_data_decoded
io.resp.bits.eccWrong := s2_data_wrong.asUInt.orR
io.resp.bits.id := s2_req.id
val meta_error = s2_meta_ecc(s2_hit_way)
val data_error = s2_data_wrong.asUInt.orR
val pipe_enable = s2_valid && s2_hit
io.error.ecc_error.valid := (meta_error || data_error) && pipe_enable
io.error.ecc_error.bits := true.B
io.error.paddr.valid := io.error.ecc_error.valid
io.error.paddr.bits := s2_req.addr
// replacement policy
val replaced_way_en = UIntToOH(replacer.way(get_idx(s2_req.addr)))
......
......@@ -8,6 +8,8 @@ import xiangshan._
import xiangshan.cache._
import xiangshan.cache.prefetch.L1plusPrefetcher
import xiangshan.backend.fu.HasExceptionNO
import system.L1CacheErrorInfo
class Frontend()(implicit p: Parameters) extends LazyModule with HasXSParameter{
......@@ -33,6 +35,7 @@ class FrontendImp (outer: Frontend) extends LazyModuleImp(outer)
val sfence = Input(new SfenceBundle)
val tlbCsr = Input(new TlbCsrBundle)
val csrCtrl = Input(new CustomCSRCtrlIO)
val error = new L1CacheErrorInfo
})
val ifu = Module(new IFU)
......@@ -93,6 +96,8 @@ class FrontendImp (outer: Frontend) extends LazyModuleImp(outer)
// ifu to backend
io.backend.fetchInfo <> ifu.io.toFtq
io.error <> ifu.io.error
// for(out <- ibuffer.io.out){
// XSInfo(out.fire(),
// p"inst:${Hexadecimal(out.bits.instr)} pc:${Hexadecimal(out.bits.pc)}\n"
......
......@@ -11,6 +11,7 @@ import freechips.rocketchip.tile.HasLazyRoCC
import chisel3.ExcitingUtils._
import xiangshan.backend.ftq.FtqPtr
import xiangshan.backend.decode.WaitTableParameters
import system.L1CacheErrorInfo
trait HasInstrMMIOConst extends HasXSParameter with HasIFUConst{
def mmioBusWidth = 64
......@@ -79,6 +80,7 @@ class IFUIO extends XSBundle
val icacheMemAcq = DecoupledIO(new L1plusCacheReq)
val l1plusFlush = Output(Bool())
val prefetchTrainReq = ValidIO(new IcacheMissReq)
val error = new L1CacheErrorInfo
// to tlb
val sfence = Input(new SfenceBundle)
val tlbCsr = Input(new TlbCsrBundle)
......@@ -480,6 +482,7 @@ class IFU extends XSModule with HasIFUConst with HasCircularQueuePtrHelper with
io.icacheMemAcq <> icache.io.mem_acquire
io.l1plusFlush := icache.io.l1plusflush
io.prefetchTrainReq := icache.io.prefetchTrainReq
io.error <> icache.io.error
bpu.io.ctrl := RegNext(io.bp_ctrl)
bpu.io.commit <> io.commitUpdate
......
......@@ -12,6 +12,8 @@ import freechips.rocketchip.tilelink.TLToAXI4
import xiangshan._
import utils._
import ExcitingUtils.Debug
import chipsalliance.rocketchip.config.Config
import freechips.rocketchip.tile.XLen
class DiffTestIO extends XSBundle {
val r = Output(Vec(64, UInt(XLEN.W)))
......@@ -303,7 +305,9 @@ object TestMain extends App {
)
val otherArgs = socArgs.filterNot(_ == "--disable-log").filterNot(_ == "--fpga-platform").filterNot(_ == "--dual-core")
implicit val p = config.Parameters.empty
implicit val p = new Config((_, _, _) => {
case XLen => 64
})
// generate verilog
XiangShanStage.execute(
otherArgs,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册