from nmigen import Elaboratable, Module, Signal, ResetSignal, Cat, Mux
from nmigen.cli import rtlil
+from soc.decoder.power_decoder2 import PowerDecode2
from soc.decoder.power_regspec_map import regspec_decode_read
from soc.decoder.power_regspec_map import regspec_decode_write
from soc.experiment.l0_cache import TstL0CacheBuffer # test only
from soc.config.test.test_loadstore import TestMemPspec
from soc.decoder.power_enums import MicrOp
+from soc.config.state import CoreState
+
import operator
from nmutil.util import rising_edge
# instruction decoder
self.e = Decode2ToExecute1Type() # decoded instruction
+ self.state = CoreState("core")
+ self.raw_insn_i = Signal(32) # raw instruction
+ self.bigendian_i = Signal() # bigendian
# issue/valid/busy signalling
self.ivalid_i = Signal(reset_less=True) # instruction is valid
self.core_reset_i = Signal()
self.core_terminate_o = Signal(reset=0) # indicates stopped
+ # create per-FU instruction decoders (subsetted)
+ self.decoders = {}
+
+ for funame, fu in self.fus.fus.items():
+ f_name = fu.fnunit.name
+ fnunit = fu.fnunit.value
+ opkls = fu.opsubsetkls
+ self.decoders[funame] = PowerDecode2(None, opkls, f_name)
+
def elaborate(self, platform):
m = Module()
+ comb = m.d.comb
m.submodules.fus = self.fus
m.submodules.l0 = l0 = self.l0
# connect up reset
m.d.comb += ResetSignal().eq(self.core_reset_i)
+ # connect decoders
+ for k, v in self.decoders.items():
+ setattr(m.submodules, "dec_%s" % v.fn_name, v)
+ comb += v.dec.raw_opcode_in.eq(self.raw_insn_i)
+ comb += v.dec.bigendian.eq(self.bigendian_i)
+ comb += v.state.eq(self.state)
+
return m
def connect_instruction(self, m):
"""
comb, sync = m.d.comb, m.d.sync
fus = self.fus.fus
- e = self.e # to execute
# enable-signals for each FU, get one bit for each FU (by name)
fu_enable = Signal(len(fus), reset_less=True)
for funame, fu in fus.items():
fnunit = fu.fnunit.value
enable = Signal(name="en_%s" % funame, reset_less=True)
- comb += enable.eq((e.do.fn_unit & fnunit).bool())
+ comb += enable.eq((self.e.do.fn_unit & fnunit).bool())
comb += fu_bitdict[funame].eq(enable)
# sigh - need a NOP counter
comb += self.busy_o.eq(1)
with m.If(self.ivalid_i): # run only when valid
- with m.Switch(e.do.insn_type):
+ with m.Switch(self.e.do.insn_type):
# check for ATTN: halt if true
with m.Case(MicrOp.OP_ATTN):
m.d.sync += self.core_terminate_o.eq(1)
with m.Default():
# connect up instructions. only one enabled at a time
for funame, fu in fus.items():
+ e = self.decoders[funame].e
enable = fu_bitdict[funame]
# run this FunctionUnit if enabled
+ # route op, issue, busy, read flags and mask to FU
with m.If(enable):
- # route op, issue, busy, read flags and mask to FU
- comb += fu.oper_i.eq_from_execute1(e)
+ # operand comes from the *local* decoder
+ comb += fu.oper_i.eq_from(e.do)
+ #comb += fu.oper_i.eq_from_execute1(e)
comb += fu.issue_i.eq(self.issue_i)
comb += self.busy_o.eq(fu.busy_o)
- rdmask = get_rdflags(e, fu)
+ # rdmask, which is for registers, needs to come
+ # from the *main* decoder
+ rdmask = get_rdflags(self.e, fu)
comb += fu.rdmaskn.eq(~rdmask)
return fu_bitdict
with m.State("IDLE"):
sync += pc_changed.eq(0)
sync += core.e.eq(0)
+ sync += core.raw_insn_i.eq(0)
+ sync += core.bigendian_i.eq(0)
with m.If(~dbg.core_stop_o & ~core.core_reset_i):
# instruction allowed to go: start by reading the PC
# capture the PC and also drop it into Insn Memory
comb += dec_opcode_i.eq(insn) # actual opcode
comb += dec_state.eq(cur_state)
sync += core.e.eq(pdecode2.e)
+ sync += core.state.eq(cur_state)
+ sync += core.raw_insn_i.eq(dec_opcode_i)
+ sync += core.bigendian_i.eq(self.core_bigendian_i)
sync += ilatch.eq(insn) # latch current insn
# also drop PC and MSR into decode "state"
m.next = "INSN_START" # move to "start"
comb += self.state_w_pc.wen.eq(1<<StateRegs.PC)
comb += self.state_w_pc.data_i.eq(nia)
sync += core.e.eq(0)
+ sync += core.raw_insn_i.eq(0)
+ sync += core.bigendian_i.eq(0)
m.next = "IDLE" # back to idle
# this bit doesn't have to be in the FSM: connect up to read