From 5b9f938263083a30def1536889866a20f84d60fa Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 6 Jan 2013 05:18:33 -0800 Subject: [PATCH] correctly sign-extend badvaddr, epc, and ebase --- rocket/src/main/scala/dpath_util.scala | 30 ++++++++++++-------------- rocket/src/main/scala/util.scala | 26 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/rocket/src/main/scala/dpath_util.scala b/rocket/src/main/scala/dpath_util.scala index 131ae28c..4aa220f1 100644 --- a/rocket/src/main/scala/dpath_util.scala +++ b/rocket/src/main/scala/dpath_util.scala @@ -132,9 +132,9 @@ class PCR(implicit conf: RocketConfiguration) extends Component } import PCR._ - val reg_epc = Reg{Fix(width = VADDR_BITS+1)} - val reg_badvaddr = Reg{Fix(width = VADDR_BITS+1)} - val reg_ebase = Reg{Fix(width = VADDR_BITS)} + val reg_epc = Reg{Bits(width = conf.xprlen)} + val reg_badvaddr = Reg{Bits(width = conf.xprlen)} + val reg_ebase = Reg{Bits(width = conf.xprlen)} val reg_count = WideCounter(32) val reg_compare = Reg{Bits(width = 32)} val reg_cause = Reg{Bits(width = io.cause.getWidth)} @@ -189,24 +189,22 @@ class PCR(implicit conf: RocketConfiguration) extends Component cnt = cnt + reg_vecbank(i) io.vecbankcnt := cnt(3,0) - val badvaddr_sign = Mux(io.w.data(VADDR_BITS-1), io.w.data(conf.xprlen-1,VADDR_BITS).andR, io.w.data(conf.xprlen-1,VADDR_BITS).orR) - when (io.badvaddr_wen) { - reg_badvaddr := Cat(badvaddr_sign, io.w.data(VADDR_BITS-1,0)).toUFix; - } - when (io.vec_irq_aux_wen) { - reg_badvaddr := io.vec_irq_aux.toUFix + when (io.badvaddr_wen || io.vec_irq_aux_wen) { + val wdata = Mux(io.badvaddr_wen, io.w.data, io.vec_irq_aux) + val (upper, lower) = Split(wdata, VADDR_BITS) + val sign = Mux(lower.toFix < Fix(0), upper.andR, upper.orR) + reg_badvaddr := Cat(sign, lower).toFix } when (io.exception) { when (!reg_status.et) { reg_error_mode := true - }.otherwise { - reg_status.s := true - reg_status.ps := reg_status.s - reg_status.et := false - reg_epc := io.pc - reg_cause := io.cause } + reg_status.s := true + reg_status.ps := reg_status.s + reg_status.et := false + reg_epc := io.pc.toFix + reg_cause := io.cause } when (io.eret) { @@ -250,7 +248,7 @@ class PCR(implicit conf: RocketConfiguration) extends Component if (!conf.rvc) reg_status.ec := false } when (waddr === EPC) { reg_epc := wdata(VADDR_BITS,0).toFix } - when (waddr === EVEC) { reg_ebase := wdata(VADDR_BITS-1,0).toUFix; } + when (waddr === EVEC) { reg_ebase := wdata(VADDR_BITS-1,0).toFix } when (waddr === COUNT) { reg_count := wdata.toUFix } when (waddr === COMPARE) { reg_compare := wdata(31,0).toUFix; r_irq_timer := Bool(false); } when (waddr === COREID) { reg_coreid := wdata(15,0) } diff --git a/rocket/src/main/scala/util.scala b/rocket/src/main/scala/util.scala index 60b0b595..183621a6 100644 --- a/rocket/src/main/scala/util.scala +++ b/rocket/src/main/scala/util.scala @@ -24,6 +24,32 @@ object AVec tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) } +object Split +{ + // is there a better way to do do this? + def apply(x: Bits, n0: Int) = { + val w = checkWidth(x, n0) + (x(w-1,n0), x(n0-1,0)) + } + def apply(x: Bits, n1: Int, n0: Int) = { + val w = checkWidth(x, n1, n0) + (x(w-1,n1), x(n1-1,n0), x(n0-1,0)) + } + def apply(x: Bits, n2: Int, n1: Int, n0: Int) = { + val w = checkWidth(x, n2, n1, n0) + (x(w-1,n2), x(n2-1,n1), x(n1-1,n0), x(n0-1,0)) + } + + private def checkWidth(x: Bits, n: Int*) = { + val w = x.getWidth + def decreasing(x: Seq[Int]): Boolean = + if (x.tail.isEmpty) true + else x.head > x.tail.head && decreasing(x.tail) + require(decreasing(w :: n.toList)) + w + } +} + // a counter that clock gates most of its MSBs using the LSB carry-out case class WideCounter(width: Int, inc: Bool = Bool(true)) {