X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsoc%2Fsimple%2Fissuer.py;h=fe0a18a1abfe4010c1afc0c340e0e39bef1f8bdf;hb=2b82f31334a15796fc5f350b3e3722ffe63ff836;hp=4e8a7f16255841e1f2c0bef14fe8afc5c4fa3a24;hpb=405fd8b72de9bed7c8fa29fd7f5c6a14131dea14;p=soc.git diff --git a/src/soc/simple/issuer.py b/src/soc/simple/issuer.py index 4e8a7f16..fe0a18a1 100644 --- a/src/soc/simple/issuer.py +++ b/src/soc/simple/issuer.py @@ -2,7 +2,7 @@ not in any way intended for production use. this runs a FSM that: -* reads the Program Counter from FastRegs +* reads the Program Counter from StateRegs * reads an instruction from a fixed-size Test Memory * issues it to the Simple Core * waits for it to complete @@ -21,28 +21,57 @@ from nmigen.cli import rtlil from nmigen.cli import main import sys +from soc.decoder.power_decoder import create_pdecode +from soc.decoder.power_decoder2 import PowerDecode2 +from soc.decoder.decode2execute1 import IssuerDecode2ToOperand from soc.decoder.decode2execute1 import Data from soc.experiment.testmem import TestMemory # test only for instructions -from soc.regfile.regfiles import FastRegs +from soc.regfile.regfiles import StateRegs, FastRegs from soc.simple.core import NonProductionCore from soc.config.test.test_loadstore import TestMemPspec from soc.config.ifetch import ConfigFetchUnit from soc.decoder.power_enums import MicrOp from soc.debug.dmi import CoreDebug, DMIInterface +from soc.debug.jtag import JTAG +from soc.config.pinouts import get_pinspecs from soc.config.state import CoreState +from soc.interrupts.xics import XICS_ICP, XICS_ICS +from soc.bus.simple_gpio import SimpleGPIO +from soc.clock.select import ClockSelect, DummyPLL + from nmutil.util import rising_edge -class TestIssuer(Elaboratable): +class TestIssuerInternal(Elaboratable): """TestIssuer - reads instructions from TestMemory and issues them efficiency and speed is not the main goal here: functional correctness is. """ def __init__(self, pspec): - # main instruction core + + # 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() + self.int_level_i = self.xics_ics.int_level_i + + # add GPIO peripheral? + self.gpio = hasattr(pspec, "gpio") and pspec.gpio == True + if self.gpio: + self.simple_gpio = SimpleGPIO() + self.gpio_o = self.simple_gpio.gpio_o + + # main instruction core25 self.core = core = NonProductionCore(pspec) + # instruction decoder. goes into Trap Record + pdecode = create_pdecode() + self.cur_state = CoreState("cur") # current state (MSR/PC/EINT) + self.pdecode2 = PowerDecode2(pdecode, state=self.cur_state, + opkls=IssuerDecode2ToOperand) + # Test Instruction memory self.imem = ConfigFetchUnit(pspec).fu # one-row cache of instruction read @@ -52,6 +81,13 @@ class TestIssuer(Elaboratable): # DMI interface self.dbg = CoreDebug() + # JTAG interface + self.jtag_en = hasattr(pspec, "debug") and pspec.debug == 'jtag' + if self.jtag_en: + subset = {'uart', 'mtwi', 'eint', 'gpio', 'mspi0', 'mspi1', + 'pwm', 'sd0'}#, 'sdr'} + self.jtag = JTAG(get_pinspecs(subset=subset)) + # instruction go/monitor self.pc_o = Signal(64, reset_less=True) self.pc_i = Data(64, "pc_i") # set "ok" to indicate "please change me" @@ -59,17 +95,23 @@ class TestIssuer(Elaboratable): self.busy_o = Signal(reset_less=True) self.memerr_o = Signal(reset_less=True) - # FAST regfile read /write ports for PC and MSR - self.fast_r_pc = self.core.regs.rf['fast'].r_ports['cia'] # PC rd - self.fast_w_pc = self.core.regs.rf['fast'].w_ports['d_wr1'] # PC wr - self.fast_r_msr = self.core.regs.rf['fast'].r_ports['msr'] # MSR rd + # FAST regfile read /write ports for PC, MSR, DEC/TB + staterf = self.core.regs.rf['state'] + self.state_r_pc = staterf.r_ports['cia'] # PC rd + self.state_w_pc = staterf.w_ports['d_wr1'] # PC wr + self.state_r_msr = staterf.r_ports['msr'] # MSR rd # DMI interface access - self.int_r = self.core.regs.rf['int'].r_ports['dmi'] # INT read + intrf = self.core.regs.rf['int'] + crrf = self.core.regs.rf['cr'] + xerrf = self.core.regs.rf['xer'] + self.int_r = intrf.r_ports['dmi'] # INT read + self.cr_r = crrf.r_ports['full_cr_dbg'] # CR read + self.xer_r = xerrf.r_ports['full_xer'] # XER read # hack method of keeping an eye on whether branch/trap set the PC - self.fast_nia = self.core.regs.rf['fast'].w_ports['nia'] - self.fast_nia.wen.name = 'fast_nia_wen' + self.state_nia = self.core.regs.rf['state'].w_ports['nia'] + self.state_nia.wen.name = 'state_nia_wen' def elaborate(self, platform): m = Module() @@ -78,10 +120,36 @@ class TestIssuer(Elaboratable): m.submodules.core = core = DomainRenamer("coresync")(self.core) m.submodules.imem = imem = self.imem m.submodules.dbg = dbg = self.dbg + if self.jtag_en: + m.submodules.jtag = jtag = self.jtag + # TODO: UART2GDB mux, here, from external pin + # see https://bugs.libre-soc.org/show_bug.cgi?id=499 + sync += dbg.dmi.connect_to(jtag.dmi) + + cur_state = self.cur_state + + # XICS interrupt handler + 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 + sync += cur_state.eint.eq(icp.core_irq_o) # connect ICP to core + + # GPIO test peripheral + if self.gpio: + m.submodules.simple_gpio = simple_gpio = self.simple_gpio + + # connect one GPIO output to ICS bit 15 (like in microwatt soc.vhdl) + if self.gpio and self.xics: + comb += self.int_level_i[15].eq(simple_gpio.gpio_o[0]) + + # instruction decoder + pdecode = create_pdecode() + m.submodules.dec2 = pdecode2 = self.pdecode2 # convenience - dmi = dbg.dmi - d_reg = dbg.dbg_gpr + dmi, d_reg, d_cr, d_xer, = dbg.dmi, dbg.d_gpr, dbg.d_cr, dbg.d_xer + intrf = self.core.regs.rf['int'] # clock delay power-on reset cd_por = ClockDomain(reset_less=True) @@ -89,30 +157,26 @@ class TestIssuer(Elaboratable): core_sync = ClockDomain("coresync") m.domains += cd_por, cd_sync, core_sync - delay = Signal(range(4), reset=1) + delay = Signal(range(4), reset=3) with m.If(delay != 0): m.d.por += delay.eq(delay - 1) comb += cd_por.clk.eq(ClockSignal()) comb += core_sync.clk.eq(ClockSignal()) - # XXX TODO: power-on reset delay (later) - #comb += core.core_reset_i.eq(delay != 0 | dbg.core_rst_o) + # power-on reset delay + comb += core.core_reset_i.eq(delay != 0 | dbg.core_rst_o) # busy/halted signals from core comb += self.busy_o.eq(core.busy_o) - comb += core.bigendian_i.eq(self.core_bigendian_i) - - # current state (MSR/PC at the moment - cur_state = CoreState("cur") + comb += pdecode2.dec.bigendian.eq(self.core_bigendian_i) # temporary hack: says "go" immediately for both address gen and ST l0 = core.l0 ldst = core.fus.fus['ldst0'] st_go_edge = rising_edge(m, ldst.st.rel_o) m.d.comb += ldst.ad.go_i.eq(ldst.ad.rel_o) # link addr-go direct to rel - m.d.sync += ldst.st.go_i.eq(st_go_edge) # link store-go to rising rel + m.d.comb += ldst.st.go_i.eq(st_go_edge) # link store-go to rising rel # PC and instruction from I-Memory - current_insn = Signal(32) # current fetched instruction (note sync) pc_changed = Signal() # note write to PC comb += self.pc_o.eq(cur_state.pc) ilatch = Signal(32) @@ -123,34 +187,40 @@ class TestIssuer(Elaboratable): # read the PC pc = Signal(64, reset_less=True) + pc_ok_delay = Signal() + sync += pc_ok_delay.eq(~self.pc_i.ok) with m.If(self.pc_i.ok): # incoming override (start from pc_i) comb += pc.eq(self.pc_i.data) with m.Else(): - # otherwise read FastRegs regfile for PC - comb += self.fast_r_pc.ren.eq(1<