diff --git a/coreblocks/arch/isa_consts.py b/coreblocks/arch/isa_consts.py index 17641f829..abb95cca2 100644 --- a/coreblocks/arch/isa_consts.py +++ b/coreblocks/arch/isa_consts.py @@ -165,6 +165,12 @@ class PrivilegeLevel(IntEnum, shape=2): MACHINE = 0b11 +@unique +class TrapVectorMode(IntEnum, shape=2): + DIRECT = 0b00 + VECTORED = 0b01 + + @unique class InterruptCauseNumber(IntEnum): SSI = 1 # supervisor software interrupt diff --git a/coreblocks/backend/retirement.py b/coreblocks/backend/retirement.py index a084e83f2..5b81b6376 100644 --- a/coreblocks/backend/retirement.py +++ b/coreblocks/backend/retirement.py @@ -214,12 +214,12 @@ def flush_instr(rob_entry): handler_pc = Signal(self.gen_params.isa.xlen) mtvec_offset = Signal(self.gen_params.isa.xlen) - mtvec = m_csr.mtvec.read(m).data + mtvec = m_csr.mtvec._fu_read(m).data mcause = m_csr.mcause.read(m).data # mtvec without mode is [mxlen-1:2], mode is two last bits. # When mode=1 (Vectored), interrupts set pc to base + 4 * cause_number - with m.If(mcause & (mtvec << (self.gen_params.isa.xlen - 1))): + with m.If(mcause[-1] & (mtvec[0:1] == 1)): m.d.av_comb += mtvec_offset.eq(mcause << 2) m.d.av_comb += handler_pc.eq((mtvec & ~(0b11)) + mtvec_offset) diff --git a/coreblocks/priv/csr/csr_instances.py b/coreblocks/priv/csr/csr_instances.py index 15c03c5a0..4fd50bf29 100644 --- a/coreblocks/priv/csr/csr_instances.py +++ b/coreblocks/priv/csr/csr_instances.py @@ -4,7 +4,7 @@ from coreblocks.arch import CSRAddress from coreblocks.arch.csr_address import MstatusFieldOffsets from coreblocks.arch.isa import Extension -from coreblocks.arch.isa_consts import PrivilegeLevel, XlenEncoding +from coreblocks.arch.isa_consts import PrivilegeLevel, XlenEncoding, TrapVectorMode from coreblocks.params.genparams import GenParams from coreblocks.priv.csr.csr_register import CSRRegister from coreblocks.priv.csr.aliased import AliasedCSR @@ -75,7 +75,7 @@ def __init__(self, gen_params: GenParams): self.mcause = CSRRegister(CSRAddress.MCAUSE, gen_params) - self.mtvec = CSRRegister(CSRAddress.MTVEC, gen_params) + self.mtvec = AliasedCSR(CSRAddress.MTVEC, gen_params) mepc_ro_bits = 0b1 if Extension.C in gen_params.isa.extensions else 0b11 # pc alignment (SPEC) self.mepc = CSRRegister(CSRAddress.MEPC, gen_params, ro_bits=mepc_ro_bits) @@ -93,6 +93,7 @@ def __init__(self, gen_params: GenParams): self.priv_mode_public.add_field(0, self.priv_mode) self.mstatus_fields_implementation(gen_params, self.mstatus, self.mstatush) + self.mtvec_fields_implementation(gen_params, self.mtvec) def elaborate(self, platform): m = Module() @@ -103,6 +104,19 @@ def elaborate(self, platform): return m + def mtvec_fields_implementation(self, gen_params: GenParams, mtvec: AliasedCSR): + def filter_legal_mode(m: TModule, v: Value): + legal = Signal(1) + m.d.av_comb += legal.eq((v == TrapVectorMode.DIRECT) | (v == TrapVectorMode.VECTORED)) + return (legal, v) + + self.mtvec_base = CSRRegister(None, gen_params, width=gen_params.isa.xlen - 2) + mtvec.add_field(TrapVectorMode.as_shape().width, self.mtvec_base) + self.mtvec_mode = CSRRegister( + None, gen_params, width=TrapVectorMode.as_shape().width, fu_write_filtermap=filter_legal_mode + ) + mtvec.add_field(0, self.mtvec_mode) + def mstatus_fields_implementation(self, gen_params: GenParams, mstatus: AliasedCSR, mstatush: AliasedCSR): def filter_legal_priv_mode(m: TModule, v: Value): legal = Signal(1) diff --git a/test/asm/interrupt_vectored.asm b/test/asm/interrupt_vectored.asm index b3902046b..b50e4bff6 100644 --- a/test/asm/interrupt_vectored.asm +++ b/test/asm/interrupt_vectored.asm @@ -116,7 +116,6 @@ fail: csrwi 0x7ff, 2 j fail - .org 0x200 nop nop @@ -133,7 +132,7 @@ fail: nop nop nop - nop + j fail j int0_handler j int1_handler li x31, 0xae # should never happen diff --git a/test/test_core.py b/test/test_core.py index d1e1709a4..9a090dd82 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -186,16 +186,6 @@ def test_asm_source(self): ("interrupt.asm", 600, {4: 89, 8: 843}, {2: 89, 7: 843, 31: 0xDE}, 30, 50, False), # interrupts are only inserted on branches, we always have some forward progression. 15 for trigger variantion. ("interrupt.asm", 80, {4: 21, 8: 9349}, {2: 21, 7: 9349, 31: 0xDE}, 0, 15, False), - ("interrupt_vectored.asm", 900, {4: 89, 8: 843, 15: 322}, {2: 89, 7: 843, 14: 322, 31: 0xDE}, 30, 50, False), - ( - "interrupt_vectored.asm", - 1600, - {4: 24157817, 8: 199, 15: 521}, - {2: 24157817, 7: 199, 14: 521, 31: 0xDE}, - 100, - 200, - False, - ), ( "interrupt_vectored.asm", 300,