From 3d2fa1ab5bdaa85e0e7cdc9ddf3e5b7c5ec6874e Mon Sep 17 00:00:00 2001 From: kalina Date: Tue, 12 Nov 2024 09:29:26 +0100 Subject: [PATCH 1/8] mtvec treated differently with interrupts --- coreblocks/backend/retirement.py | 12 ++++- coreblocks/priv/csr/csr_instances.py | 4 +- freeze | 76 ++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 freeze diff --git a/coreblocks/backend/retirement.py b/coreblocks/backend/retirement.py index 38c45040c..a084e83f2 100644 --- a/coreblocks/backend/retirement.py +++ b/coreblocks/backend/retirement.py @@ -213,8 +213,16 @@ def flush_instr(rob_entry): self.perf_trap_latency.stop(m) handler_pc = Signal(self.gen_params.isa.xlen) - # mtvec without mode is [mxlen-1:2], mode is two last bits. Only direct mode is supported - m.d.av_comb += handler_pc.eq(m_csr.mtvec.read(m).data & ~(0b11)) + mtvec_offset = Signal(self.gen_params.isa.xlen) + mtvec = m_csr.mtvec.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))): + m.d.av_comb += mtvec_offset.eq(mcause << 2) + + m.d.av_comb += handler_pc.eq((mtvec & ~(0b11)) + mtvec_offset) resume_pc = Mux(continue_pc_override, continue_pc, handler_pc) m.d.sync += continue_pc_override.eq(0) diff --git a/coreblocks/priv/csr/csr_instances.py b/coreblocks/priv/csr/csr_instances.py index 3215b42ee..15c03c5a0 100644 --- a/coreblocks/priv/csr/csr_instances.py +++ b/coreblocks/priv/csr/csr_instances.py @@ -75,9 +75,7 @@ def __init__(self, gen_params: GenParams): self.mcause = CSRRegister(CSRAddress.MCAUSE, gen_params) - # SPEC: The mtvec register must always be implemented, but can contain a read-only value. - # set `MODE` as fixed to 0 - Direct mode "All exceptions set pc to BASE" - self.mtvec = CSRRegister(CSRAddress.MTVEC, gen_params, ro_bits=0b11) + self.mtvec = CSRRegister(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) diff --git a/freeze b/freeze new file mode 100644 index 000000000..e2e50f20d --- /dev/null +++ b/freeze @@ -0,0 +1,76 @@ + +Usage: + pip3 [options] + +Commands: + install Install packages. + download Download packages. + uninstall Uninstall packages. + freeze Output installed packages in requirements format. + inspect Inspect the python environment. + list List installed packages. + show Show information about installed packages. + check Verify installed packages have compatible dependencies. + config Manage local and global configuration. + search Search PyPI for packages. + cache Inspect and manage pip's wheel cache. + index Inspect information available from package indexes. + wheel Build wheels from your requirements. + hash Compute hashes of package archives. + completion A helper command used for command completion. + debug Show information useful for debugging. + help Show help for commands. + +General Options: + -h, --help Show help. + --debug Let unhandled exceptions propagate outside the + main subroutine, instead of logging them to + stderr. + --isolated Run pip in an isolated mode, ignoring + environment variables and user configuration. + --require-virtualenv Allow pip to only run in a virtual environment; + exit with an error otherwise. + --python Run pip with the specified Python interpreter. + -v, --verbose Give more output. Option is additive, and can be + used up to 3 times. + -V, --version Show version and exit. + -q, --quiet Give less output. Option is additive, and can be + used up to 3 times (corresponding to WARNING, + ERROR, and CRITICAL logging levels). + --log Path to a verbose appending log. + --no-input Disable prompting for input. + --keyring-provider + Enable the credential lookup via the keyring + library if user input is allowed. Specify which + mechanism to use [disabled, import, subprocess]. + (default: disabled) + --proxy Specify a proxy in the form + scheme://[user:passwd@]proxy.server:port. + --retries Maximum number of retries each connection should + attempt (default 5 times). + --timeout Set the socket timeout (default 15 seconds). + --exists-action Default action when a path already exists: + (s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort. + --trusted-host Mark this host or host:port pair as trusted, + even though it does not have valid or any HTTPS. + --cert Path to PEM-encoded CA certificate bundle. If + provided, overrides the default. See 'SSL + Certificate Verification' in pip documentation + for more information. + --client-cert Path to SSL client certificate, a single file + containing the private key and the certificate + in PEM format. + --cache-dir Store the cache data in . + --no-cache-dir Disable the cache. + --disable-pip-version-check + Don't periodically check PyPI to determine + whether a new version of pip is available for + download. Implied with --no-index. + --no-color Suppress colored output. + --no-python-version-warning + Silence deprecation warnings for upcoming + unsupported Pythons. + --use-feature Enable new functionality, that may be backward + incompatible. + --use-deprecated Enable deprecated functionality, that will be + removed in the future. From c79f366adedbc4af70f4bf3c6803494a6d1eaaed Mon Sep 17 00:00:00 2001 From: kalina Date: Tue, 19 Nov 2024 10:43:57 +0100 Subject: [PATCH 2/8] first version of test --- test/asm/interrupt_vectored.asm | 158 ++++++++++++++++++++++++++++++++ test/test_core.py | 19 ++++ 2 files changed, 177 insertions(+) create mode 100644 test/asm/interrupt_vectored.asm diff --git a/test/asm/interrupt_vectored.asm b/test/asm/interrupt_vectored.asm new file mode 100644 index 000000000..0b4adc9e3 --- /dev/null +++ b/test/asm/interrupt_vectored.asm @@ -0,0 +1,158 @@ +.include "init_regs.s" + +_start: + INIT_REGS_LOAD + + # fibonacci spiced with interrupt handler (also with fibonacci) + li x1, 0x201 + csrw mtvec, x1 + li x27, 0 # handler count + li x30, 0 # interrupt count + li x31, 0xde # branch guard + csrsi mstatus, 0x8 # machine interrupt enable + csrr x29, mstatus + li x1, 0x30000 + csrw mie, x1 # enable custom interrupt 0 and 1 + li x1, 0 + li x2, 1 + li x5, 4 + li x6, 7 + li x7, 0 + li x12, 4 + li x13, 7 + li x14, 0 +loop: + add x3, x2, x1 + mv x1, x2 + mv x2, x3 + bne x2, x4, loop +infloop: + j infloop + +int0_handler: + # save main loop register state + mv x9, x1 + mv x10, x2 + mv x11, x3 + + # check cause + li x2, 0x80000010 # cause for 01,11 + csrr x3, mcause + bne x2, x3, fail + + # generate new mie mask + andi x2, x30, 0x3 + bnez x2, fill_skip + li x2, 0x3 + fill_skip: + slli x2, x2, 16 + csrw mie, x2 + + # clear interrupts + csrr x1, mip + srli x1, x1, 16 + addi x30, x30, 1 + li x2, 0x10000 + csrc mip, x2 # clear edge reported interrupt + andi x2, x1, 0x2 + beqz x2, skip_clear_level + addi x30, x30, 1 + csrwi 0x7ff, 1 # clear level reported interrupt via custom csr + skip_clear_level: + addi x27, x27, 1 + + # load state + mv x1, x5 + mv x2, x6 + mv x3, x7 + # fibonacci step + beq x3, x8, skip + add x3, x2, x1 + mv x1, x2 + mv x2, x3 + # store state + mv x5, x1 + mv x6, x2 + mv x7, x3 +skip: + # restore main loop register state + mv x1, x9 + mv x2, x10 + mv x3, x11 + mret + + +int1_handler: + # save main loop register state + mv x9, x1 + mv x10, x2 + mv x11, x3 + + # check cause + li x2, 0x80000011 # cause for 10 + csrr x3, mcause + bne x2, x3, fail + + # generate new mie mask + andi x2, x30, 0x3 + bnez x2, fill1_skip + li x2, 0x3 + fill1_skip: + slli x2, x2, 16 + csrw mie, x2 + + # clear interrupts + csrr x1, mip + srli x1, x1, 16 + andi x2, x1, 0x1 + beqz x2, skip_clear_edge + addi x30, x30, 1 + li x2, 0x10000 + csrc mip, x2 # clear edge reported interrupt + skip_clear_edge: + addi x30, x30, 1 + csrwi 0x7ff, 1 # clear level reported interrupt via custom csr + addi x27, x27, 1 + + # load state + mv x1, x12 + mv x2, x13 + mv x3, x14 + # fibonacci step + beq x3, x15, skip + add x3, x2, x1 + mv x1, x2 + mv x2, x3 + # store state + mv x12, x1 + mv x13, x2 + mv x14, x3 + j skip + +fail: + csrwi 0x7ff, 2 + j fail + + +.org 0x200 + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + j int0_handler + j int1_handler + li x31, 0xae # should never happen + +INIT_REGS_ALLOCATION diff --git a/test/test_core.py b/test/test_core.py index 6825ffd1b..d1e1709a4 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -186,6 +186,25 @@ 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, + {4: 21, 8: 9349, 15: 24476}, + {2: 21, 7: 9349, 14: 24476, 31: 0xDE}, + 0, + 15, + False, + ), ("wfi_int.asm", 80, {2: 10}, {2: 10, 3: 10}, 5, 15, True), ], ) From beaa278676dbddc1d32ed0178f01e28bfa040e79 Mon Sep 17 00:00:00 2001 From: kalina Date: Tue, 19 Nov 2024 11:05:34 +0100 Subject: [PATCH 3/8] common mip and mie changes for both handlers --- test/asm/interrupt_vectored.asm | 59 ++++++++++++--------------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/test/asm/interrupt_vectored.asm b/test/asm/interrupt_vectored.asm index 0b4adc9e3..b3902046b 100644 --- a/test/asm/interrupt_vectored.asm +++ b/test/asm/interrupt_vectored.asm @@ -40,6 +40,21 @@ int0_handler: csrr x3, mcause bne x2, x3, fail + # load state + mv x1, x5 + mv x2, x6 + mv x3, x7 + # fibonacci step + beq x3, x8, skip + add x3, x2, x1 + mv x1, x2 + mv x2, x3 + # store state + mv x5, x1 + mv x6, x2 + mv x7, x3 + +skip: # generate new mie mask andi x2, x30, 0x3 bnez x2, fill_skip @@ -51,9 +66,12 @@ int0_handler: # clear interrupts csrr x1, mip srli x1, x1, 16 - addi x30, x30, 1 - li x2, 0x10000 - csrc mip, x2 # clear edge reported interrupt + andi x2, x1, 0x1 + beqz x2, skip_clear_edge + addi x30, x30, 1 + li x2, 0x10000 + csrc mip, x2 # clear edge reported interrupt + skip_clear_edge: andi x2, x1, 0x2 beqz x2, skip_clear_level addi x30, x30, 1 @@ -61,20 +79,6 @@ int0_handler: skip_clear_level: addi x27, x27, 1 - # load state - mv x1, x5 - mv x2, x6 - mv x3, x7 - # fibonacci step - beq x3, x8, skip - add x3, x2, x1 - mv x1, x2 - mv x2, x3 - # store state - mv x5, x1 - mv x6, x2 - mv x7, x3 -skip: # restore main loop register state mv x1, x9 mv x2, x10 @@ -93,27 +97,6 @@ int1_handler: csrr x3, mcause bne x2, x3, fail - # generate new mie mask - andi x2, x30, 0x3 - bnez x2, fill1_skip - li x2, 0x3 - fill1_skip: - slli x2, x2, 16 - csrw mie, x2 - - # clear interrupts - csrr x1, mip - srli x1, x1, 16 - andi x2, x1, 0x1 - beqz x2, skip_clear_edge - addi x30, x30, 1 - li x2, 0x10000 - csrc mip, x2 # clear edge reported interrupt - skip_clear_edge: - addi x30, x30, 1 - csrwi 0x7ff, 1 # clear level reported interrupt via custom csr - addi x27, x27, 1 - # load state mv x1, x12 mv x2, x13 From 515de1fcaf510bfff0e7a1db76f59f5db9d4c757 Mon Sep 17 00:00:00 2001 From: kalina Date: Tue, 19 Nov 2024 11:37:57 +0100 Subject: [PATCH 4/8] delete a trash freeze file --- freeze | 76 ---------------------------------------------------------- 1 file changed, 76 deletions(-) delete mode 100644 freeze diff --git a/freeze b/freeze deleted file mode 100644 index e2e50f20d..000000000 --- a/freeze +++ /dev/null @@ -1,76 +0,0 @@ - -Usage: - pip3 [options] - -Commands: - install Install packages. - download Download packages. - uninstall Uninstall packages. - freeze Output installed packages in requirements format. - inspect Inspect the python environment. - list List installed packages. - show Show information about installed packages. - check Verify installed packages have compatible dependencies. - config Manage local and global configuration. - search Search PyPI for packages. - cache Inspect and manage pip's wheel cache. - index Inspect information available from package indexes. - wheel Build wheels from your requirements. - hash Compute hashes of package archives. - completion A helper command used for command completion. - debug Show information useful for debugging. - help Show help for commands. - -General Options: - -h, --help Show help. - --debug Let unhandled exceptions propagate outside the - main subroutine, instead of logging them to - stderr. - --isolated Run pip in an isolated mode, ignoring - environment variables and user configuration. - --require-virtualenv Allow pip to only run in a virtual environment; - exit with an error otherwise. - --python Run pip with the specified Python interpreter. - -v, --verbose Give more output. Option is additive, and can be - used up to 3 times. - -V, --version Show version and exit. - -q, --quiet Give less output. Option is additive, and can be - used up to 3 times (corresponding to WARNING, - ERROR, and CRITICAL logging levels). - --log Path to a verbose appending log. - --no-input Disable prompting for input. - --keyring-provider - Enable the credential lookup via the keyring - library if user input is allowed. Specify which - mechanism to use [disabled, import, subprocess]. - (default: disabled) - --proxy Specify a proxy in the form - scheme://[user:passwd@]proxy.server:port. - --retries Maximum number of retries each connection should - attempt (default 5 times). - --timeout Set the socket timeout (default 15 seconds). - --exists-action Default action when a path already exists: - (s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort. - --trusted-host Mark this host or host:port pair as trusted, - even though it does not have valid or any HTTPS. - --cert Path to PEM-encoded CA certificate bundle. If - provided, overrides the default. See 'SSL - Certificate Verification' in pip documentation - for more information. - --client-cert Path to SSL client certificate, a single file - containing the private key and the certificate - in PEM format. - --cache-dir Store the cache data in . - --no-cache-dir Disable the cache. - --disable-pip-version-check - Don't periodically check PyPI to determine - whether a new version of pip is available for - download. Implied with --no-index. - --no-color Suppress colored output. - --no-python-version-warning - Silence deprecation warnings for upcoming - unsupported Pythons. - --use-feature Enable new functionality, that may be backward - incompatible. - --use-deprecated Enable deprecated functionality, that will be - removed in the future. From bd239dd2a79c15ab08f7adf6f7d58dd25c37eedf Mon Sep 17 00:00:00 2001 From: kalina Date: Wed, 20 Nov 2024 01:47:58 +0100 Subject: [PATCH 5/8] mtvec made WARL --- coreblocks/arch/isa_consts.py | 6 ++++++ coreblocks/backend/retirement.py | 4 ++-- coreblocks/priv/csr/csr_instances.py | 18 ++++++++++++++++-- test/asm/interrupt_vectored.asm | 3 +-- test/test_core.py | 10 ---------- 5 files changed, 25 insertions(+), 16 deletions(-) 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, From eea4ac52c049422c9fd9866e2ba0b8c6eed617be Mon Sep 17 00:00:00 2001 From: kalina Date: Sun, 24 Nov 2024 12:21:42 +0100 Subject: [PATCH 6/8] corrections in mtvec test --- test/asm/interrupt_vectored.asm | 58 +++++++++++++++------------------ test/test_core.py | 4 +-- 2 files changed, 29 insertions(+), 33 deletions(-) diff --git a/test/asm/interrupt_vectored.asm b/test/asm/interrupt_vectored.asm index b50e4bff6..19c05042f 100644 --- a/test/asm/interrupt_vectored.asm +++ b/test/asm/interrupt_vectored.asm @@ -6,13 +6,20 @@ _start: # fibonacci spiced with interrupt handler (also with fibonacci) li x1, 0x201 csrw mtvec, x1 - li x27, 0 # handler count - li x30, 0 # interrupt count - li x31, 0xde # branch guard - csrsi mstatus, 0x8 # machine interrupt enable + li x1, 0x203 + csrw mtvec, x1 + csrr x16, mtvec # since mtvec is WARL, should stay 0x201 + ecall # synchronous exception jumps to 0x200 + 0x0 + +interrupts: + li x27, 0 # handler count + li x30, 0 # interrupt count + li x31, 0xde # branch guard + + csrsi mstatus, 0x8 # machine interrupt enable csrr x29, mstatus li x1, 0x30000 - csrw mie, x1 # enable custom interrupt 0 and 1 + csrw mie, x1 # enable custom interrupt 0 and 1 li x1, 0 li x2, 1 li x5, 4 @@ -40,19 +47,11 @@ int0_handler: csrr x3, mcause bne x2, x3, fail - # load state - mv x1, x5 - mv x2, x6 - mv x3, x7 # fibonacci step - beq x3, x8, skip - add x3, x2, x1 - mv x1, x2 - mv x2, x3 - # store state - mv x5, x1 - mv x6, x2 - mv x7, x3 + beq x7, x8, skip + add x7, x6, x5 + mv x5, x6 + mv x6, x7 skip: # generate new mie mask @@ -85,7 +84,6 @@ skip: mv x3, x11 mret - int1_handler: # save main loop register state mv x9, x1 @@ -97,27 +95,25 @@ int1_handler: csrr x3, mcause bne x2, x3, fail - # load state - mv x1, x12 - mv x2, x13 - mv x3, x14 # fibonacci step - beq x3, x15, skip - add x3, x2, x1 - mv x1, x2 - mv x2, x3 - # store state - mv x12, x1 - mv x13, x2 - mv x14, x3 + beq x14, x15, skip + add x14, x13, x12 + mv x12, x13 + mv x13, x14 j skip +ecall_handler: + li x17, 0x111 + la x1, interrupts + csrw mepc, x1 + mret + fail: csrwi 0x7ff, 2 j fail .org 0x200 - nop + j ecall_handler nop nop nop diff --git a/test/test_core.py b/test/test_core.py index 9a090dd82..2ef831535 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -188,9 +188,9 @@ def test_asm_source(self): ("interrupt.asm", 80, {4: 21, 8: 9349}, {2: 21, 7: 9349, 31: 0xDE}, 0, 15, False), ( "interrupt_vectored.asm", - 300, + 200, {4: 21, 8: 9349, 15: 24476}, - {2: 21, 7: 9349, 14: 24476, 31: 0xDE}, + {2: 21, 7: 9349, 14: 24476, 31: 0xDE, 16: 0x201, 17: 0x111}, 0, 15, False, From d66a47c0ac429c833aa2a7276ea5395463c245b3 Mon Sep 17 00:00:00 2001 From: kalina Date: Mon, 25 Nov 2024 22:41:18 +0100 Subject: [PATCH 7/8] read instead of _fu_read --- coreblocks/backend/retirement.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/coreblocks/backend/retirement.py b/coreblocks/backend/retirement.py index 5b81b6376..20f704276 100644 --- a/coreblocks/backend/retirement.py +++ b/coreblocks/backend/retirement.py @@ -10,6 +10,7 @@ from coreblocks.arch import ExceptionCause from coreblocks.interface.keys import CoreStateKey, CSRInstancesKey, InstructionPrecommitKey from coreblocks.priv.csr.csr_instances import CSRAddress, DoubleCounterCSR +from coreblocks.arch.isa_consts import TrapVectorMode class Retirement(Elaboratable): @@ -214,15 +215,16 @@ 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._fu_read(m).data + mtvec_base = m_csr.mtvec_base.read(m).data + mtvec_mode = m_csr.mtvec_mode.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[-1] & (mtvec[0:1] == 1)): + # When mode is Vectored, interrupts set pc to base + 4 * cause_number + with m.If(mcause[-1] & (mtvec_mode == TrapVectorMode.VECTORED)): m.d.av_comb += mtvec_offset.eq(mcause << 2) - m.d.av_comb += handler_pc.eq((mtvec & ~(0b11)) + mtvec_offset) + # (mtvec_base stores base[MXLEN-1:2]) + m.d.av_comb += handler_pc.eq((mtvec_base << 2) + mtvec_offset) resume_pc = Mux(continue_pc_override, continue_pc, handler_pc) m.d.sync += continue_pc_override.eq(0) From 203c12ecbeeed89f25ef0975f058dfdb2f306334 Mon Sep 17 00:00:00 2001 From: kalina Date: Mon, 25 Nov 2024 23:15:44 +0100 Subject: [PATCH 8/8] formatter --- coreblocks/priv/csr/csr_instances.py | 1 - 1 file changed, 1 deletion(-) diff --git a/coreblocks/priv/csr/csr_instances.py b/coreblocks/priv/csr/csr_instances.py index a0edcaf96..33b80f04d 100644 --- a/coreblocks/priv/csr/csr_instances.py +++ b/coreblocks/priv/csr/csr_instances.py @@ -99,7 +99,6 @@ def __init__(self, gen_params: GenParams): self._mstatus_fields_implementation(gen_params, self.mstatus, self.mstatush) self._mtvec_fields_implementation(gen_params, self.mtvec) - def elaborate(self, platform): m = Module()