[not tested] lab2 codes updated:

- added environment instruction tests
- removed useless classes in CLINT.scala
- rename and comments
This commit is contained in:
PurplePower
2025-07-19 21:21:21 +08:00
parent fb2a030f07
commit 2caaf3d9f5
2 changed files with 78 additions and 37 deletions

View File

@@ -18,7 +18,7 @@ import chisel3._
import chisel3.util.MuxLookup
import riscv.Parameters
object InterruptStatus {
object InterruptCode {
val None = 0x0.U(8.W)
val Timer0 = 0x1.U(8.W)
val Ret = 0xFF.U(8.W)
@@ -28,18 +28,6 @@ object InterruptEntry {
val Timer0 = 0x4.U(8.W)
}
object InterruptState {
val Idle = 0x0.U
val SyncAssert = 0x1.U
val AsyncAssert = 0x2.U
val MRET = 0x3.U
}
object CSRState {
val Idle = 0x0.U
val Traping = 0x1.U
val Mret = 0x2.U
}
class CSRDirectAccessBundle extends Bundle {
val mstatus = Input(UInt(Parameters.DataWidth))
@@ -88,20 +76,14 @@ class CLINT extends Module {
io.csr_bundle.direct_write_enable :=
io.interrupt_assert :=
io.interrupt_handler_address :=
}.elsewhen(io.instruction === InstructionsRet.mret) {
io.csr_bundle.mstatus_write_data :=
io.csr_bundle.mepc_write_data :=
io.csr_bundle.mcause_write_data :=
io.csr_bundle.direct_write_enable :=
io.interrupt_assert :=
io.interrupt_handler_address :=
}
.elsewhen(io.instruction === InstructionsEnv.ebreak || io.instruction === InstructionsEnv.ecall) {
......
}
.elsewhen(io.instruction === InstructionsRet.mret) {
......
}.otherwise {
io.csr_bundle.mstatus_write_data :=
io.csr_bundle.mepc_write_data :=
io.csr_bundle.mcause_write_data :=
io.csr_bundle.direct_write_enable :=
io.interrupt_assert :=
io.interrupt_handler_address :=
......
}
*/
}

View File

@@ -18,7 +18,8 @@ import chisel3._
import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec
import riscv.{Parameters, TestAnnotations}
import riscv.core.{ALUOp1Source, ALUOp2Source, CLINT, CSR, CSRRegister, InstructionDecode, InstructionsNop, InstructionsRet}
import riscv.core.{ALUOp1Source, ALUOp2Source, CLINT, CSR, CSRRegister, InstructionDecode, InstructionsNop, InstructionsRet, InstructionsEnv}
import riscv.core.InterruptCode
class CLINTCSRTestTopModule extends Module {
val io = IO( new Bundle{
@@ -63,10 +64,9 @@ class CLINTCSRTestTopModule extends Module {
class CLINTCSRTest extends AnyFlatSpec with ChiselScalatestTester{
behavior of "CLINTCSRTest of Single Cycle CPU"
it should "process " in {
it should "handle external interrupt" in {
test(new CLINTCSRTestTopModule).withAnnotations(TestAnnotations.annos) { c =>
//
c.io.jump_flag.poke(false.B)
c.io.csr_regs_write_enable.poke(false.B)
c.io.interrupt_flag.poke(0.U)
@@ -79,15 +79,18 @@ class CLINTCSRTest extends AnyFlatSpec with ChiselScalatestTester{
c.io.csr_regs_write_data.poke(0x1888L.U)
c.clock.step()
c.io.csr_regs_write_enable.poke(false.B)
// handle interrupt when not jumping
c.io.jump_flag.poke(false.B)
c.io.instruction_address.poke(0x1900L.U)
c.io.instruction.poke(InstructionsNop.nop)
c.io.interrupt_flag.poke(1.U)
c.io.interrupt_flag.poke(InterruptCode.Timer0)
c.io.interrupt_assert.expect(true.B)
c.io.interrupt_handler_address.expect(0x1144L.U)
c.clock.step()
c.io.interrupt_flag.poke(0.U)
c.io.interrupt_flag.poke(InterruptCode.None)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MEPC)
c.io.csr_regs_debug_read_data.expect(0x1904L.U)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MCAUSE)
@@ -112,7 +115,7 @@ class CLINTCSRTest extends AnyFlatSpec with ChiselScalatestTester{
c.io.interrupt_assert.expect(true.B)
c.io.interrupt_handler_address.expect(0x1144L.U)
c.clock.step()
c.io.interrupt_flag.poke(0.U)
c.io.interrupt_flag.poke(InterruptCode.None)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MEPC)
c.io.csr_regs_debug_read_data.expect(0x1990L.U)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MCAUSE)
@@ -139,4 +142,60 @@ class CLINTCSRTest extends AnyFlatSpec with ChiselScalatestTester{
c.io.interrupt_assert.expect(false.B)
}
}
it should "handle environmental instructions" in {
test(new CLINTCSRTestTopModule).withAnnotations(TestAnnotations.annos) { c =>
val interrupt_entry = 0x1144L.U
c.io.jump_flag.poke(false.B)
c.io.csr_regs_write_enable.poke(true.B)
c.io.csr_regs_write_address.poke(CSRRegister.MSTATUS)
c.io.csr_regs_write_data.poke(0x1888L.U) // write mstatus MIE = 1, MPIE = 1
c.clock.step()
c.io.csr_regs_write_address.poke(CSRRegister.MTVEC)
c.io.csr_regs_write_data.poke(interrupt_entry) // write mtvec to 0x1144
c.clock.step()
c.io.csr_regs_write_enable.poke(false.B)
// ecall
c.io.instruction.poke(InstructionsEnv.ecall)
c.io.instruction_address.poke(0x2000L.U)
c.io.interrupt_flag.poke(InterruptCode.None)
c.clock.step() // poking ecall instruction at address 0x2000, expect CLINT to handle it
c.io.interrupt_assert.expect(true.B)
c.io.interrupt_handler_address.expect(interrupt_entry)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MEPC)
c.io.csr_regs_debug_read_data.expect(0x2004L.U)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MCAUSE)
c.io.csr_regs_debug_read_data.expect(0x0000_000BL.U) // ecall from M-mode
c.io.csr_regs_debug_read_address.poke(CSRRegister.MSTATUS)
c.io.csr_regs_debug_read_data.expect(0x1880L.U)
// mret from ecall handler
c.io.instruction.poke(InstructionsRet.mret)
c.io.interrupt_assert.expect(true.B)
c.io.interrupt_handler_address.expect(0x2004L.U)
c.clock.step()
c.io.csr_regs_debug_read_address.poke(CSRRegister.MSTATUS)
c.io.csr_regs_debug_read_data.expect(0x1888L.U)
// ebreak
c.clock.step()
c.io.instruction.poke(InstructionsEnv.ebreak)
c.io.instruction_address.poke(0x2004L.U)
c.clock.step()
c.io.interrupt_assert.expect(true.B)
c.io.interrupt_handler_address.expect(interrupt_entry)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MEPC)
c.io.csr_regs_debug_read_data.expect(0x2008L.U)
c.io.csr_regs_debug_read_address.poke(CSRRegister.MCAUSE)
c.io.csr_regs_debug_read_data.expect(0x0000_0003L.U) // breakpoint
}
}
}