xref: /XiangShan/src/main/scala/device/TLTimer.scala (revision 618fb109099cc1d271e72520857cee13429b073c)
1package device
2
3import chisel3._
4import chisel3.util._
5import freechips.rocketchip.tilelink._
6import chipsalliance.rocketchip.config
7import chipsalliance.rocketchip.config._
8import chisel3.util.experimental.BoringUtils
9import freechips.rocketchip.diplomacy._
10import freechips.rocketchip.regmapper.{RegField, RegWriteFn}
11import utils.{HoldUnless, MaskExpand, RegMap}
12
13class TLTimer(address: Seq[AddressSet], sim: Boolean)(implicit p: Parameters) extends LazyModule {
14
15  val device = new SimpleDevice("clint", Seq("XiangShan", "clint"))
16  val node = TLRegisterNode(address, device, beatBytes = 8)
17
18  lazy val module = new LazyModuleImp(this){
19    val mtip = IO(Output(Bool()))
20
21    val mtime = RegInit(0.U(64.W))  // unit: us
22    val mtimecmp = RegInit(0.U(64.W))
23
24    val clk = (if (!sim) 40 /* 40MHz / 1000000 */ else 100)
25    val freq = RegInit(clk.U(16.W))
26    val inc = RegInit(1000.U(16.W))
27
28    val cnt = RegInit(0.U(16.W))
29    val nextCnt = cnt + 1.U
30    cnt := Mux(nextCnt < freq, nextCnt, 0.U)
31    val tick = (nextCnt === freq)
32    when (tick) { mtime := mtime + inc }
33
34    if (sim) {
35      val isWFI = WireInit(false.B)
36      BoringUtils.addSink(isWFI, "isWFI")
37      when (isWFI) { mtime := mtime + 100000.U }
38    }
39
40    node.regmap( mapping =
41      0x4000 -> RegField.bytes(mtimecmp),
42      0x8000 -> RegField.bytes(freq),
43      0x8008 -> RegField.bytes(inc),
44      0xbff8 -> RegField.bytes(mtime)
45    )
46
47    printf(p"[Timer] mtime=$mtime cnt=$cnt freq=$freq\n")
48
49    mtip := RegNext(mtime >= mtimecmp)
50  }
51}
52