"""simple core issuer not in any way intended for production use. this runs a FSM that: * 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 * increments the PC * does it all over again the purpose of this module is to verify the functional correctness of the Function Units in the absolute simplest and clearest possible way, and to at provide something that can be further incrementally improved. """ from nmigen import (Elaboratable, Module, Signal, ClockSignal, ResetSignal, ClockDomain, DomainRenamer) from nmigen.cli import rtlil from nmigen.cli import main import sys from soc.decoder.decode2execute1 import Data from soc.experiment.testmem import TestMemory # test only for instructions from soc.regfile.regfiles import StateRegs 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.config.state import CoreState from nmutil.util import rising_edge class TestIssuer(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 self.core = core = NonProductionCore(pspec) # Test Instruction memory self.imem = ConfigFetchUnit(pspec).fu # one-row cache of instruction read self.iline = Signal(64) # one instruction line self.iprev_adr = Signal(64) # previous address: if different, do read # DMI interface self.dbg = CoreDebug() # 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" self.core_bigendian_i = Signal() self.busy_o = Signal(reset_less=True) self.memerr_o = Signal(reset_less=True) # FAST regfile read /write ports for PC and MSR self.state_r_pc = self.core.regs.rf['state'].r_ports['cia'] # PC rd self.state_w_pc = self.core.regs.rf['state'].w_ports['d_wr1'] # PC wr self.state_r_msr = self.core.regs.rf['state'].r_ports['msr'] # MSR rd # DMI interface access self.int_r = self.core.regs.rf['int'].r_ports['dmi'] # INT read # hack method of keeping an eye on whether branch/trap set the PC 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() comb, sync = m.d.comb, m.d.sync m.submodules.core = core = DomainRenamer("coresync")(self.core) m.submodules.imem = imem = self.imem m.submodules.dbg = dbg = self.dbg # convenience dmi = dbg.dmi d_reg = dbg.dbg_gpr # clock delay power-on reset cd_por = ClockDomain(reset_less=True) cd_sync = ClockDomain() core_sync = ClockDomain("coresync") m.domains += cd_por, cd_sync, core_sync delay = Signal(range(4), reset=1) 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) # 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") # 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.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) # next instruction (+4 on current) nia = Signal(64, reset_less=True) comb += nia.eq(cur_state.pc + 4) # read the PC pc = Signal(64, reset_less=True) 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 StateRegs regfile for PC comb += self.state_r_pc.ren.eq(1<