xref: /XiangShan/src/main/scala/device/AXI4Timer.scala (revision 5844fcf02181bcf3a22ac080465d35f0ecc1d0e2)
1package device
2
3import chisel3._
4import chisel3.util._
5import chisel3.util.experimental.BoringUtils
6
7import bus.axi4._
8import utils._
9
10class TimerIO extends Bundle {
11  val mtip = Output(Bool())
12}
13
14class AXI4Timer(sim: Boolean = false) extends AXI4SlaveModule(new AXI4Lite, new TimerIO) {
15  val mtime = RegInit(0.U(64.W))  // unit: us
16  val mtimecmp = RegInit(0.U(64.W))
17
18  val clk = (if (!sim) 40 /* 40MHz / 1000000 */ else 10000)
19  val freq = RegInit(clk.U(16.W))
20  val inc = RegInit(1.U(16.W))
21
22  val cnt = RegInit(0.U(16.W))
23  val nextCnt = cnt + 1.U
24  cnt := Mux(nextCnt < freq, nextCnt, 0.U)
25  val tick = (nextCnt === freq)
26  when (tick) { mtime := mtime + inc }
27
28  if (sim) {
29    val isWFI = WireInit(false.B)
30    BoringUtils.addSink(isWFI, "isWFI")
31    when (isWFI) { mtime := mtime + 100000.U }
32  }
33
34  val mapping = Map(
35    RegMap(0x4000, mtimecmp),
36    RegMap(0x8000, freq),
37    RegMap(0x8008, inc),
38    RegMap(0xbff8, mtime)
39  )
40  def getOffset(addr: UInt) = addr(15,0)
41
42  RegMap.generate(mapping, getOffset(raddr), in.r.bits.data,
43    getOffset(waddr), in.w.fire(), in.w.bits.data, MaskExpand(in.w.bits.strb))
44
45  io.extra.get.mtip := RegNext(mtime >= mtimecmp)
46}
47