Implement bus error unit
This commit is contained in:
parent
ed18acaae0
commit
79dab487fc
75
src/main/scala/rocket/BusErrorUnit.scala
Normal file
75
src/main/scala/rocket/BusErrorUnit.scala
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// 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, None, dcache.correctable, dcache.uncorrectable)
|
||||||
|
}
|
||||||
|
|
||||||
|
class BusErrorUnit[T <: BusErrors](t: => T, addr: BigInt)(implicit p: Parameters) extends LazyModule {
|
||||||
|
val regWidth = 64
|
||||||
|
val size = 64
|
||||||
|
val device = new SimpleDevice("bus-error-unit", Seq("sifive,buserror0"))
|
||||||
|
val intNode = IntSourceNode(IntSourcePortSimple(resources = device.int))
|
||||||
|
val node = TLRegisterNode(
|
||||||
|
address = Seq(AddressSet(addr, 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(_.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)))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user