Skip to content

Commit

Permalink
add timer
Browse files Browse the repository at this point in the history
  • Loading branch information
LoveLonelyTime committed Feb 5, 2024
1 parent 36d39a6 commit 3bd44c6
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 27 deletions.
17 changes: 17 additions & 0 deletions src/main/scala/lltriscv/core/Core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import lltriscv.bus.AXIMaster
import lltriscv.cache.CacheLineRequest2SMA
import lltriscv.bus.AXIMasterIO
import lltriscv.interconnect.SkipCacheSMAReaderInterconnect
import lltriscv.core.debug.DebugIO

/*
* LLT RISC-V Core Exquisite integration
Expand Down Expand Up @@ -100,6 +101,11 @@ object CoreConfig {
class LLTRISCVCoreExq(config: CoreConfig) extends Module {
val io = IO(new Bundle {
val axi = new AXIMasterIO()

val mtime = Input(UInt(64.W))
val mtimeIRQ = Input(Bool())

val debug = new DebugIO()
})

private val coreFrontend = Module(new CoreFrontend(config))
Expand Down Expand Up @@ -148,6 +154,9 @@ class LLTRISCVCoreExq(config: CoreConfig) extends Module {
coreBackend.io.updateLoadReservation <> coreExecute.io.updateLoadReservation
coreBackend.io.predictorUpdate <> coreFrontend.io.predictorUpdate
coreBackend.io.store <> coreExecute.io.retire
coreBackend.io.mtime := io.mtime
coreBackend.io.mtimeIRQ := io.mtimeIRQ
coreBackend.io.debug <> io.debug

// TLBFlusher
tlbFlusher.io.out1 <> coreFrontend.io.iTLBFlush
Expand Down Expand Up @@ -401,6 +410,11 @@ class CoreBackend(config: CoreConfig) extends Module {
val tlbFlush = new FlushCacheIO()

val updateLoadReservation = new LoadReservationUpdateIO()

val mtime = Input(UInt(64.W))
val mtimeIRQ = Input(Bool())

val debug = new DebugIO()
})
private val broadcaster = Module(new RoundRobinBroadcaster(config.executeQueueWidth))
private val instructionRetire = Module(new InstructionRetire(config.robDepth))
Expand All @@ -427,6 +441,7 @@ class CoreBackend(config: CoreConfig) extends Module {
instructionRetire.io.iCacheFlush <> io.iCacheFlush
instructionRetire.io.dCacheFlush <> io.dCacheFlush
instructionRetire.io.tlbFlush <> io.tlbFlush
instructionRetire.io.debug <> io.debug

instructionRetire.io.l2DCacheFlush.empty := true.B

Expand All @@ -440,4 +455,6 @@ class CoreBackend(config: CoreConfig) extends Module {
io.privilege := csr.io.privilege
io.mstatus := csr.io.mstatus
io.satp := csr.io.satp
csr.io.mtime := io.mtime
csr.io.mtimeIRQ := io.mtimeIRQ
}
7 changes: 7 additions & 0 deletions src/main/scala/lltriscv/core/debug/Debug.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package lltriscv.core.debug

import chisel3._

class DebugIO extends Bundle {
val hit = Output(Bool())
}
6 changes: 5 additions & 1 deletion src/main/scala/lltriscv/core/execute/Memory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,11 @@ class MemoryReadWriteStage extends Module {
}

// Alloc ID
when(inReg.op in MemoryOperationType.writeValues) {
when(inReg.op === MemoryOperationType.sc) { // Advance judgment
when(scSuccess(inReg.vaddress)) {
io.out.bits.resultMemory(allocID)
}
}.elsewhen(inReg.op in MemoryOperationType.writeValues) {
io.out.bits.resultMemory(allocID)
}

Expand Down
25 changes: 18 additions & 7 deletions src/main/scala/lltriscv/core/record/CSRs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,18 @@ class CSRs extends Module {
val satp = Output(DataType.operation)

val monitor = Flipped(new MonitorIO())

val mtime = Input(UInt(64.W))
val mtimeIRQ = Input(Bool())
})

// Registers
private val coreRegister = new CoreRegister()
private val statusReg = new StatusRegister()
private val exceptionReg = new ExceptionRegister()
private val interruptsReg = new InterruptsRegister(false.B, false.B, false.B, false.B)
private val interruptsReg = new InterruptsRegister(io.mtimeIRQ, false.B, false.B, false.B)
private val virtualReg = new VirtualRegister(statusReg.mstatus.value(20), statusReg.privilege)
private val monitorRegister = new MonitorRegister(statusReg.privilege, io.monitor.instret)
private val monitorRegister = new MonitorRegister(statusReg.privilege, io.monitor.instret, io.mtime)

// Fixed output
io.satp := virtualReg.satp.value
Expand All @@ -54,9 +57,12 @@ class CSRs extends Module {
private val csrMappingTable = Seq(
// Unprivileged
"hc00".U -> monitorRegister.cycle,
"hc01".U -> monitorRegister.time,
"hc02".U -> monitorRegister.instret,
"hc80".U -> monitorRegister.cycleh,
"hc81".U -> monitorRegister.timeh,
"hc82".U -> monitorRegister.instreth,

// S-Level
"h100".U -> statusReg.sstatus,
"h104".U -> interruptsReg.sie,
Expand Down Expand Up @@ -183,6 +189,7 @@ class CSRs extends Module {

when(io.trap.interruptTrigger) {
val delegation = interruptsReg.mideleg.value(pendingInterruptCode)
printf("Pending code = %d\n", pendingInterruptCode)
when(!delegation) { // M-Handler
io.trap.handlerPC := exceptionReg.interruptMLevel(io.trap.trapPC, pendingInterruptCode, io.trap.trapVal)
statusReg.trapToMLevel()
Expand Down Expand Up @@ -517,7 +524,7 @@ class CoreRegister {
}

// TODO: mtime
class MonitorRegister(privilege: PrivilegeType.Type, instretVal: UInt) {
class MonitorRegister(privilege: PrivilegeType.Type, instretVal: UInt, mtime: UInt) {
private val mcountinhibitReg = RegInit(DataType.operation.zeroAsUInt)
private val mcounterenReg = RegInit(DataType.operation.zeroAsUInt)
private val scounterenReg = RegInit(DataType.operation.zeroAsUInt)
Expand Down Expand Up @@ -546,9 +553,13 @@ class MonitorRegister(privilege: PrivilegeType.Type, instretVal: UInt) {
(privilege === PrivilegeType.S && !mcounterenReg(bit)) ||
(privilege === PrivilegeType.U && (!mcounterenReg(bit) || !scounterenReg(bit)))

val cycle = ReadAndWriteRegister(() => cycleCounter(31, 0), data => cycleCounter := cycleCounter(63, 32) ## data, () => guard(0))
val cycleh = ReadAndWriteRegister(() => cycleCounter(63, 32), data => cycleCounter := data ## cycleCounter(31, 0), () => guard(0))
// Read-only
val cycle = ReadAndWriteRegister(() => cycleCounter(31, 0), _ => (), () => guard(0))
val cycleh = ReadAndWriteRegister(() => cycleCounter(63, 32), _ => (), () => guard(0))

val instret = ReadAndWriteRegister(() => instretCounter(31, 0), _ => (), () => guard(2))
val instreth = ReadAndWriteRegister(() => instretCounter(63, 32), _ => (), () => guard(2))

val instret = ReadAndWriteRegister(() => instretCounter(31, 0), data => instretCounter := instretCounter(63, 32) ## data, () => guard(2))
val instreth = ReadAndWriteRegister(() => instretCounter(63, 32), data => instretCounter := data ## instretCounter(31, 0), () => guard(2))
val time = ReadAndWriteRegister(() => mtime(31, 0), _ => (), () => guard(0))
val timeh = ReadAndWriteRegister(() => mtime(63, 32), _ => (), () => guard(0))
}
42 changes: 26 additions & 16 deletions src/main/scala/lltriscv/core/retire/InstructionRetire.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import lltriscv.cache.FlushCacheIO
import lltriscv.utils.CoreUtils._
import lltriscv.utils.ChiselUtils._
import lltriscv.core.record.MonitorIO
import lltriscv.core.debug.DebugIO

/*
* Instruction retire
Expand Down Expand Up @@ -66,7 +67,12 @@ class InstructionRetire(depth: Int) extends Module {
val l2DCacheFlush = new FlushCacheIO()
val iCacheFlush = new FlushCacheIO()
val tlbFlush = new FlushCacheIO()

// Debug
val debug = new DebugIO()
})
private val debugBreakpoint = RegInit(false.B)
io.debug.hit := debugBreakpoint

private object Status extends ChiselEnum {
val retire, dCache, l2DCache, iCache, tlb = Value
Expand Down Expand Up @@ -126,6 +132,7 @@ class InstructionRetire(depth: Int) extends Module {
io.correctPC := io.trap.handlerPC

io.retired.ready := true.B

when(entry.pc >= "h80400000".U) {
printf("Exception!!!! pc = %x, cause = %d,to = %x\n", entry.pc, entry.executeResult.exceptionCode, io.trap.handlerPC)
}
Expand All @@ -148,14 +155,14 @@ class InstructionRetire(depth: Int) extends Module {

io.retired.ready := true.B

// when(entry.pc >= "h80400000".U) {
// printf(
// "spec violate!!!: pc = %x, sepc = %x, real = %x\n",
// entry.pc,
// entry.spec,
// entry.executeResult.real
// )
// }
when(debugBreakpoint) {
printf(
"spec violate!!!: pc = %x, sepc = %x, real = %x\n",
entry.pc,
entry.spec,
entry.executeResult.real
)
}
}

private def gotoXRetPath(entry: ROBTableEntry) = {
Expand Down Expand Up @@ -203,14 +210,17 @@ class InstructionRetire(depth: Int) extends Module {
io.predictorUpdate.entries(id).address := retireEntries(id).executeResult.real
}

// when(retireEntries(id).pc >= "h80400000".U) {
// printf(
// "retired instruction: pc = %x , r = %x, v = %d\n",
// retireEntries(id).pc,
// retireEntries(id).executeResult.result,
// retireEntries(id).valid
// )
// }
when(retireEntries(id).pc === "hc0002a44".U) {
debugBreakpoint := true.B
}
when(debugBreakpoint) {
printf(
"retired instruction: pc = %x , r = %x, v = %d\n",
retireEntries(id).pc,
retireEntries(id).executeResult.result,
retireEntries(id).valid
)
}
}

private def retireStoreQueue(id: Int) = {
Expand Down
86 changes: 86 additions & 0 deletions src/main/scala/lltriscv/peripheral/MachineTimer.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package lltriscv.peripheral

import chisel3._
import chisel3.util._

import lltriscv.bus.AXIMasterIO

import lltriscv.utils.ChiselUtils._
import lltriscv.utils.CoreUtils._

class MachineTimer(base: String) extends Module {
val io = IO(new Bundle {
val axi = Flipped(new AXIMasterIO())
val irq = Output(Bool())
val mtime = Output(UInt(64.W))
})

private val mtimeReg = RegInit(0.U(64.W))
mtimeReg := mtimeReg + 1.U
io.mtime := mtimeReg

private val mtimecmpReg = RegInit(0.U(64.W))
io.irq := mtimeReg >= mtimecmpReg

io.axi <> new AXIMasterIO().zero

// AXI logic
private val readAddressReg = RegInit(0.U(32.W))

when(io.axi.ARVALID) {
io.axi.ARREADY := true.B
readAddressReg := io.axi.ARADDR - base.U
}

io.axi.RVALID := true.B
io.axi.RRESP := 0.U

switch(readAddressReg) {
is("h4000".U) { // mtimecmpl
io.axi.RDATA := mtimecmpReg(31, 0)
}
is("h4004".U) { // mtimecmph
io.axi.RDATA := mtimecmpReg(63, 32)
}
is("hbff8".U) { // mtimel
io.axi.RDATA := mtimeReg(31, 0)
}
is("hbffc".U) { // mtimeh
io.axi.RDATA := mtimeReg(63, 32)
}
}

private val writeAddressReg = RegInit(0.U(32.W))

when(io.axi.AWVALID) {
io.axi.AWREADY := true.B
writeAddressReg := io.axi.AWADDR - base.U
}

when(io.axi.WVALID) {
io.axi.WREADY := true.B
val data = io.axi.WDATA
printf("Current time: %d\n", mtimeReg)
switch(writeAddressReg) {
is("h4000".U) { // mtimecmpl
mtimecmpReg := mtimecmpReg(63, 32) ## data
printf("MTIMER: set mtimecmp = %d\n", mtimecmpReg(63, 32) ## data)
}
is("h4004".U) { // mtimecmph
mtimecmpReg := data ## mtimecmpReg(31, 0)
printf("MTIMER: set mtimecmp = %d\n", data ## mtimecmpReg(31, 0))
}
is("hbff8".U) { // mtimel
mtimeReg := mtimeReg(63, 32) ## data
printf("MTIMER: set mtime = %d\n", mtimeReg(63, 32) ## data)
}
is("hbffc".U) { // mtimeh
mtimeReg := data ## mtimeReg(31, 0)
printf("MTIMER: set mtime = %d\n", data ## mtimeReg(31, 0))
}
}
}

io.axi.BVALID := true.B
io.axi.BRESP := 0.U
}
17 changes: 14 additions & 3 deletions src/test/scala/lltriscv/test/NormalTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import lltriscv.peripheral.VirtualWriteHost
import lltriscv.peripheral.VirtualUART
import lltriscv.peripheral.MemoryHole
import lltriscv.peripheral.VirtualRAM
import lltriscv.peripheral.MachineTimer
import lltriscv.core.debug.DebugIO

class NormalTest extends AnyFlatSpec with ChiselScalatestTester {
// WriteVcdAnnotation
Expand All @@ -40,6 +42,8 @@ class NormalTest extends AnyFlatSpec with ChiselScalatestTester {

val dataOut = Output(UInt(8.W))
val send = Output(Bool())

val debug = new DebugIO()
})

private val core = Module(new LLTRISCVCoreExq(config))
Expand All @@ -48,6 +52,7 @@ class NormalTest extends AnyFlatSpec with ChiselScalatestTester {
new AXIInterconnect(
Seq(
"h00000000", // hole
"h2000000", // mtime
"h10000000", // uart
"h80000000", // ram
"hffff0000" // rom
Expand All @@ -56,6 +61,7 @@ class NormalTest extends AnyFlatSpec with ChiselScalatestTester {
)
private val hole = Module(new MemoryHole())
private val uart = Module(new VirtualUART("h10000000"))
private val mtimer = Module(new MachineTimer("h2000000"))
private val rom = Module(new ROM(32, "hffff0000", "boot.hex"))
private val ram = Module(new VirtualRAM("h80000000"))

Expand All @@ -69,11 +75,16 @@ class NormalTest extends AnyFlatSpec with ChiselScalatestTester {
io.send := uart.io.send

interconnect.io.slaves(0) <> hole.io.axi
interconnect.io.slaves(1) <> uart.io.axi
interconnect.io.slaves(2) <> ram.io.axi
interconnect.io.slaves(3) <> rom.io.axi
interconnect.io.slaves(1) <> mtimer.io.axi
interconnect.io.slaves(2) <> uart.io.axi
interconnect.io.slaves(3) <> ram.io.axi
interconnect.io.slaves(4) <> rom.io.axi

core.io.mtime := mtimer.io.mtime
core.io.mtimeIRQ := mtimer.io.irq
core.io.axi <> interconnect.io.master

core.io.debug <> io.debug
}

"Normal test" should "pass" in {
Expand Down

0 comments on commit 3bd44c6

Please sign in to comment.