class CoreState(RecordObject):
def __init__(self, name):
super().__init__(name=name)
- self.pc = Signal(64) # Program Counter (CIA, NIA)
- self.msr = Signal(64) # Machine Status Register (MSR)
+ self.pc = Signal(64) # Program Counter (CIA, NIA)
+ self.msr = Signal(64) # Machine Status Register (MSR)
+ self.eint = Signal() # External Interrupt
PRIV = 1<<1
TRAP = 1<<2
ADDR = 1<<3
- ILLEG = 1<<4 # currently the max, therefore traptype must be 5 bits
+ EINT = 1<<4 # external interrupt
+ ILLEG = 1<<5 # currently the max, therefore traptype must be 5 bits
# TODO: support for TM_BAD_THING (not included yet in trap main_stage.py)
- size = 5 # MUST update this to contain the full number of Trap Types
+ size = 6 # MUST update this to contain the full number of Trap Types
m = Module()
comb = m.d.comb
e_out, op, do_out = self.e, self.dec.op, self.e.do
- msr, cia = self.state.msr, self.state.pc
+ msr, cia, ext_irq = self.state.msr, self.state.pc, self.state.eint
# fill in for a normal instruction (not an exception)
# copy over if non-exception, non-privileged etc. is detected
# rverything including destroying read of RA and RB.
comb += do.trapaddr.eq(0x70) # addr=0x700 (strip first nibble)
- # TODO: get msr, then can do privileged instruction
- with m.If(instr_is_priv(m, op.internal_op, e.do.insn) & msr[MSR.PR]):
- # privileged instruction trap
+ # check if instruction is privileged
+ is_priv_insn = instr_is_priv(m, op.internal_op, e.do.insn)
+
+ # external interrupt?
+ with m.If(ext_irq & msr[MSR.EE]):
+ self.trap(m, TT.EINT, 0x500)
+
+ # privileged instruction trap
+ with m.Elif(is_priv_insn & msr[MSR.PR]):
self.trap(m, TT.PRIV, 0x700)
# illegal instruction must redirect to trap. this is done by
comb += srr1_o.data[PI.FP].eq(1)
with m.If(traptype & TT.ADDR):
comb += srr1_o.data[PI.ADR].eq(1)
+ with m.If(traptype & TT.EINT):
+ # do nothing unusual? see 3.0B Book III 6.5.7 p1073
+ pass
with m.If(traptype & TT.ILLEG):
comb += srr1_o.data[PI.ILLEG].eq(1)
comb += srr1_o.ok.eq(1)
spec.addr_wid = 30
spec.mask_wid = 4
spec.reg_wid = 32
- self.bus = Record(make_wb_layout(spec))
+ self.bus = Record(make_wb_layout(spec), name="icp_wb")
self.ics_i = ICS2ICP("ics_i")
self.core_irq_o = Signal()
spec.addr_wid = 30
spec.mask_wid = 4
spec.reg_wid = 32
- self.bus = Record(make_wb_layout(spec))
+ self.bus = Record(make_wb_layout(spec), name="ics_wb")
self.int_level_i = Signal(SRC_NUM)
self.icp_o = ICS2ICP("icp_o")
"tests/3.bin"
#ram_fname = "/tmp/test.bin"
#ram_fname = None
+ #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
+ # "micropython/firmware.bin"
ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
"hello_world/hello_world.bin"
class NonProductionCore(Elaboratable):
def __init__(self, pspec):
+
+ # add external interrupt?
+ self.xics = hasattr(pspec, "xics") and pspec.xics == True
+ if self.xics:
+ self.ext_irq_i = Signal()
+
# single LD/ST funnel for memory access
self.l0 = TstL0CacheBuffer(pspec, n_units=1)
pi = self.l0.l0.dports[0]
from soc.decoder.power_enums import MicrOp
from soc.debug.dmi import CoreDebug, DMIInterface
from soc.config.state import CoreState
+from soc.interrupts.xics import XICS_ICP, XICS_ICS
from nmutil.util import rising_edge
efficiency and speed is not the main goal here: functional correctness is.
"""
def __init__(self, pspec):
+
+ # add interrupt controller?
+ self.xics = hasattr(pspec, "xics") and pspec.xics == True
+ if self.xics:
+ self.xics_icp = XICS_ICP()
+ self.xics_ics = XICS_ICS()
+
# main instruction core
self.core = core = NonProductionCore(pspec)
m.submodules.imem = imem = self.imem
m.submodules.dbg = dbg = self.dbg
+ if self.xics:
+ m.submodules.xics_icp = icp = self.xics_icp
+ m.submodules.xics_ics = ics = self.xics_ics
+ comb += icp.ics_i.eq(ics.icp_o) # connect ICS to ICP
+ comb += core.ext_irq_i.eq(icp.core_irq_o) # connect ICP to core
+
# instruction decoder
pdecode = create_pdecode()
m.submodules.dec2 = pdecode2 = self.pdecode2
return list(self)
def external_ports(self):
- return self.pc_i.ports() + [self.pc_o,
- self.memerr_o,
- self.core_bigendian_i,
- ClockSignal(),
- ResetSignal(),
- self.busy_o,
- ] + \
- list(self.dbg.dmi.ports()) + \
- list(self.imem.ibus.fields.values()) + \
- list(self.core.l0.cmpi.lsmem.lsi.slavebus.fields.values())
+ ports = self.pc_i.ports()
+ ports += [self.pc_o, self.memerr_o, self.core_bigendian_i, self.busy_o,
+ ClockSignal(), ResetSignal(),
+ ]
+ ports += list(self.dbg.dmi.ports())
+ ports += list(self.imem.ibus.fields.values())
+ ports += list(self.core.l0.cmpi.lsmem.lsi.slavebus.fields.values())
+
+ if self.xics:
+ ports += list(self.xics_icp.bus.fields.values())
+ ports += list(self.xics_ics.bus.fields.values())
+
+ return ports
def ports(self):
return list(self)
imem_reg_wid=64,
# set to 32 to make data wishbone bus 32-bit
#wb_data_wid=32,
+ xics=True,
units=units)
dut = TestIssuer(pspec)