From 65f1492b3d3531687ba90c5c537453cde0e6e5fd Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Mon, 7 Sep 2020 22:14:36 +0100 Subject: [PATCH] add per-FU PowerDecoders. should now be subsettable --- src/soc/simple/core.py | 39 +++++++++++++++++++++++++++++++++------ src/soc/simple/issuer.py | 7 +++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/soc/simple/core.py b/src/soc/simple/core.py index cba01c7b..a4c81621 100644 --- a/src/soc/simple/core.py +++ b/src/soc/simple/core.py @@ -22,6 +22,7 @@ before allowing a new instruction to proceed. 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 @@ -36,6 +37,8 @@ from soc.decoder.decode2execute1 import Data 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 @@ -78,6 +81,9 @@ class NonProductionCore(Elaboratable): # 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 @@ -89,8 +95,18 @@ class NonProductionCore(Elaboratable): 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 @@ -106,6 +122,13 @@ class NonProductionCore(Elaboratable): # 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): @@ -122,7 +145,6 @@ class NonProductionCore(Elaboratable): """ 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) @@ -136,7 +158,7 @@ class NonProductionCore(Elaboratable): 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 @@ -146,7 +168,7 @@ class NonProductionCore(Elaboratable): 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) @@ -158,15 +180,20 @@ class NonProductionCore(Elaboratable): 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 diff --git a/src/soc/simple/issuer.py b/src/soc/simple/issuer.py index 1f4e798e..215a6a98 100644 --- a/src/soc/simple/issuer.py +++ b/src/soc/simple/issuer.py @@ -216,6 +216,8 @@ class TestIssuer(Elaboratable): 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 @@ -255,6 +257,9 @@ class TestIssuer(Elaboratable): 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" @@ -280,6 +285,8 @@ class TestIssuer(Elaboratable): comb += self.state_w_pc.wen.eq(1<