summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/sim/devices/irq.py
blob: 7ce63fbc52f833e90a7ef167c09d4778ad3a4330 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
"""IRQ routing seam.

Evidence kind: **hardware register/field header + observed access pattern.**

The GSP boot handshake sets the falcon ``IRQSSET`` HALT bit (bit 4) after
writing MAILBOX0/DEBUGINFO, and the boot code reads ``FALCON_IRQSTAT``; the
libos kernel owns the RISC-V-local ``RISCV_IRQMSET``/``IRQMCLR``/``IRQMASK``
group.  This module aggregates those two sources behind one object so a
future core-interrupt model can consume a single ``pending()`` surface.

It does **not** deliver interrupts to the machine's hart: mstatus/mie/mip/
mtvec trap entry is not modelled (documented unknown).  It only makes the
routing state explicit and serialisable.
"""
from __future__ import annotations

# Falcon IRQSSET/IRQSCLR bit positions used by the boot handshake (header
# field list; only the ones with proven firmware use are named).
FALCON_IRQ_GPTMR = 1 << 0
FALCON_IRQ_WDTMR = 1 << 1
FALCON_IRQ_MTHD = 1 << 2
FALCON_IRQ_CTXSW = 1 << 3
FALCON_IRQ_HALT = 1 << 4
FALCON_IRQ_EXTERR = 1 << 5
FALCON_IRQ_SWGEN0 = 1 << 6
FALCON_IRQ_SWGEN1 = 1 << 7
FALCON_IRQ_DMA = 1 << 16
FALCON_IRQ_SHA = 1 << 17


class IrqRouter:
    """Aggregate falcon + RISC-V-local interrupt state."""

    name = "irq"

    def __init__(self, *, falcon=None, priscv=None):
        self.falcon = falcon
        self.priscv = priscv

    def falcon_status(self) -> int:
        return self.falcon.irq_status if self.falcon is not None else 0

    def riscv_mask(self) -> int:
        return self.priscv.irq_mask if self.priscv is not None else 0

    def pending(self) -> dict:
        """Raw pending state; delivery is deliberately not modelled."""
        return {
            "falcon_irq_status": self.falcon_status(),
            "falcon_halt": bool(self.falcon_status() & FALCON_IRQ_HALT),
            "riscv_irq_mask": self.riscv_mask(),
        }

    def state(self) -> dict:
        return self.pending()

    def reset(self) -> None:
        pass