CSR.scala 5.9 KB
Newer Older
Z
Zihao Yu 已提交
1
package noop
Z
Zihao Yu 已提交
2 3 4

import chisel3._
import chisel3.util._
5
import chisel3.util.experimental.BoringUtils
Z
Zihao Yu 已提交
6

7 8
import utils._

Z
Zihao Yu 已提交
9 10 11 12 13
object CSROpType {
  def jmp  = "b00".U
  def wrt  = "b01".U
  def set  = "b10".U
  def clr  = "b11".U
14 15
}

Z
Zihao Yu 已提交
16
object CSRInstr extends HasInstrType {
17 18 19 20
  def CSRRW   = BitPat("b????????????_?????_001_?????_1110011")
  def CSRRS   = BitPat("b????????????_?????_010_?????_1110011")
  def ECALL   = BitPat("b001100000010_00000_000_00000_1110011")
  def MRET    = BitPat("b000000000000_00000_000_00000_1110011")
21
  def SRET    = BitPat("b000100000010_00000_000_00000_1110011")
22

23
  val table = Array(
Z
Zihao Yu 已提交
24 25 26
    CSRRW          -> List(InstrI, FuType.csr, CSROpType.wrt),
    CSRRS          -> List(InstrI, FuType.csr, CSROpType.set),
    ECALL          -> List(InstrI, FuType.csr, CSROpType.jmp),
27 28
    MRET           -> List(InstrI, FuType.csr, CSROpType.jmp),
    SRET           -> List(InstrI, FuType.csr, CSROpType.jmp)
29 30 31 32
  )
}

trait HasCSRConst {
33 34 35 36 37
  // these are actually S-mode CSRs to match riscv32-nemu
  val Mstatus       = 0x100
  val Mtvec         = 0x105
  val Mepc          = 0x141
  val Mcause        = 0x142
38

39
  def privEcall = 0x000.U
40
  def privMret  = 0x102.U
Z
Zihao Yu 已提交
41 42
}

Z
Zihao Yu 已提交
43
class CSRIO extends FunctionUnitIO {
Z
Zihao Yu 已提交
44 45
  val cfIn = Flipped(new CtrlFlowIO)
  val redirect = new RedirectIO
Z
Zihao Yu 已提交
46 47
  // exception
  val isInvOpcode = Input(Bool())
Z
Zihao Yu 已提交
48 49
}

Z
Zihao Yu 已提交
50
class CSR(implicit val p: NOOPConfig) extends Module with HasCSRConst {
Z
Zihao Yu 已提交
51 52 53 54 55 56 57 58 59 60 61
  val io = IO(new CSRIO)

  val (valid, src1, src2, func) = (io.in.valid, io.in.bits.src1, io.in.bits.src2, io.in.bits.func)
  def access(valid: Bool, src1: UInt, src2: UInt, func: UInt): UInt = {
    this.valid := valid
    this.src1 := src1
    this.src2 := src2
    this.func := func
    io.out.bits
  }

Z
Zihao Yu 已提交
62 63
  val mtvec = Reg(UInt(32.W))
  val mcause = Reg(UInt(32.W))
64
  val mstatus = RegInit("h000c0100".U)
Z
Zihao Yu 已提交
65
  val mepc = Reg(UInt(32.W))
66

67
  val hasPerfCnt = !p.FPGAPlatform
68 69 70 71
  val nrPerfCnts = if (hasPerfCnt) 0x80 else 0x3
  val perfCnts = List.fill(nrPerfCnts)(RegInit(0.U(64.W)))
  val perfCntsLoMapping = (0 until nrPerfCnts).map { case i => (0xb00 + i, perfCnts(i)) }
  val perfCntsHiMapping = (0 until nrPerfCnts).map { case i => (0xb80 + i, perfCnts(i)(63, 32)) }
Z
Zihao Yu 已提交
72

73
  val scalaMapping = Map(
Z
Zihao Yu 已提交
74 75 76
    Mtvec   -> mtvec,
    Mcause  -> mcause,
    Mepc    -> mepc,
77 78
    Mstatus -> mstatus
  ) ++ perfCntsLoMapping ++ perfCntsHiMapping
Z
Zihao Yu 已提交
79 80 81

  val chiselMapping = scalaMapping.map { case (x, y) => (x.U -> y) }

82
  def readWithScala(addr: Int): UInt = scalaMapping(addr)
Z
Zihao Yu 已提交
83

Z
Zihao Yu 已提交
84
  val addr = src2(11, 0)
85 86
  val rdata = LookupTree(addr, chiselMapping)(31, 0)
  val wdata = LookupTree(func, List(
Z
Zihao Yu 已提交
87 88 89
    CSROpType.wrt -> src1,
    CSROpType.set -> (rdata | src1),
    CSROpType.clr -> (rdata & ~src1)
Z
Zihao Yu 已提交
90 91
  ))

Z
Zihao Yu 已提交
92
  when (valid && func =/= CSROpType.jmp) {
Z
Zihao Yu 已提交
93 94 95 96
    when (addr === Mtvec.U) { mtvec := wdata }
    when (addr === Mstatus.U) { mstatus := wdata }
    when (addr === Mepc.U) { mepc := wdata }
    when (addr === Mcause.U) { mcause := wdata }
Z
Zihao Yu 已提交
97 98
  }

Z
Zihao Yu 已提交
99 100
  io.out.bits := rdata

Z
Zihao Yu 已提交
101
  val isMret = addr === privMret
Z
Zihao Yu 已提交
102
  val isException = io.isInvOpcode && valid
Z
Zihao Yu 已提交
103 104 105
  val isEcall = (addr === privEcall) && !isException
  val exceptionNO = Mux1H(List(
    io.isInvOpcode -> 2.U,
106
    isEcall -> 9.U //11.U
Z
Zihao Yu 已提交
107 108
  ))

Z
Zihao Yu 已提交
109 110
  io.redirect.valid := (valid && func === CSROpType.jmp) || isException
  io.redirect.target := Mux(isMret, mepc, mtvec)
Z
Zihao Yu 已提交
111

Z
Zihao Yu 已提交
112 113
  when (io.redirect.valid && !isMret) {
    mepc := io.cfIn.pc
Z
Zihao Yu 已提交
114
    mcause := exceptionNO
Z
Zihao Yu 已提交
115
  }
116

Z
Zihao Yu 已提交
117 118
  io.in.ready := true.B
  io.out.valid := valid
Z
Zihao Yu 已提交
119

120
  // perfcnt
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
  val perfCntList = Map(
    "Mcycle"      -> (0xb00, "perfCntCondMcycle"     ),
    "Minstret"    -> (0xb02, "perfCntCondMinstret"   ),
    "MimemStall"  -> (0xb03, "perfCntCondMimemStall" ),
    "MaluInstr"   -> (0xb04, "perfCntCondMaluInstr"  ),
    "MbruInstr"   -> (0xb05, "perfCntCondMbruInstr"  ),
    "MlsuInstr"   -> (0xb06, "perfCntCondMlsuInstr"  ),
    "MmduInstr"   -> (0xb07, "perfCntCondMmduInstr"  ),
    "McsrInstr"   -> (0xb08, "perfCntCondMcsrInstr"  ),
    "MloadInstr"  -> (0xb09, "perfCntCondMloadInstr" ),
    "MloadStall"  -> (0xb0a, "perfCntCondMloadStall" ),
    "MstoreStall" -> (0xb0b, "perfCntCondMstoreStall"),
    "MmmioInstr"  -> (0xb0c, "perfCntCondMmmioInstr" ),
    "MicacheHit"  -> (0xb0d, "perfCntCondMicacheHit" ),
    "MdcacheHit"  -> (0xb0e, "perfCntCondMdcacheHit" ),
    "MmulInstr"   -> (0xb0f, "perfCntCondMmulInstr"  ),
    "MifuFlush"   -> (0xb10, "perfCntCondMifuFlush"  ),
    "MrawStall"   -> (0xb11, "perfCntCondMrawStall"  ),
139 140 141 142 143 144 145 146 147
    "MexuBusy"    -> (0xb12, "perfCntCondMexuBusy"   ),
    "MbpBRight"   -> (0xb13, "MbpBRight"             ),
    "MbpBWrong"   -> (0xb14, "MbpBWrong"             ),
    "MbpJRight"   -> (0xb15, "MbpJRight"             ),
    "MbpJWrong"   -> (0xb16, "MbpJWrong"             ),
    "MbpIRight"   -> (0xb17, "MbpIRight"             ),
    "MbpIWrong"   -> (0xb18, "MbpIWrong"             ),
    "MbpRRight"   -> (0xb19, "MbpRRight"             ),
    "MbpRWrong"   -> (0xb1a, "MbpRWrong"             )
148
  )
149

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
  val perfCntCond = List.fill(0x80)(WireInit(false.B))
  (perfCnts zip perfCntCond).map { case (c, e) => { when (e) { c := c + 1.U } } }

  BoringUtils.addSource(WireInit(true.B), "perfCntCondMcycle")
  perfCntList.map { case (name, (addr, boringId)) => {
    BoringUtils.addSink(perfCntCond(addr & 0x7f), boringId)
    if (!hasPerfCnt) {
      // do not enable perfcnts except for Mcycle and Minstret
      if (addr != perfCntList("Mcycle")._1 && addr != perfCntList("Minstret")._1) {
        perfCntCond(addr & 0x7f) := false.B
      }
    }
  }}

  val nooptrap = WireInit(false.B)
  BoringUtils.addSink(nooptrap, "nooptrap")
Z
Zihao Yu 已提交
166 167 168 169 170
  if (!p.FPGAPlatform) {
    // to monitor
    BoringUtils.addSource(readWithScala(perfCntList("Mcycle")._1), "simCycleCnt")
    BoringUtils.addSource(readWithScala(perfCntList("Minstret")._1), "simInstrCnt")

171 172 173
    // display all perfcnt when nooptrap is executed
    when (nooptrap) {
      printf("======== PerfCnt =========\n")
174 175
      perfCntList.toSeq.sortBy(_._2._1).map { case (name, (addr, boringId)) =>
        printf("%d <- " + name + "\n", readWithScala(addr)) }
176 177
    }
  }
Z
Zihao Yu 已提交
178
}