xref: /XiangShan/src/main/scala/device/TLTimer.scala (revision e2801f9751af7390b9496601ccf3fda95fb70430)
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.{GTimer, 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//    val gtime = GTimer()
48//    printf(p"[$gtime][Timer] mtime=$mtime cnt=$cnt freq=$freq\n")
49
50    mtip := RegNext(mtime >= mtimecmp)
51  }
52}
53