* clarifying core function unit enable
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 11 Jul 2020 22:24:20 +0000 (23:24 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 11 Jul 2020 22:24:20 +0000 (23:24 +0100)
* disabling wrflag based on fu busy
* NOP enabled when not stopped
g

src/soc/experiment/compalu_multi.py
src/soc/simple/core.py

index e2f8683a16fca02d44b73e68355807a0f7e84a9c..d1a4a325d348d3742a9311e782fa906bb283e2fe 100644 (file)
@@ -267,7 +267,7 @@ class MultiCompUnit(RegSpecALUAPI, Elaboratable):
                     ok = data_r[fname]
             else:
                 data_r = Signal.like(lro, name=name, reset_less=True)
-            wrok.append(ok)
+            wrok.append(ok & self.busy_o)
             latchregister(m, lro, data_r, alu_pulsem, name + "_l")
             drl.append(data_r)
 
index f5dd58e352d336285c516d559d6bb7e0fd087083..ebf0e888e696f4dba3db196dc69bc3d3ade4241e 100644 (file)
@@ -121,11 +121,19 @@ class NonProductionCore(Elaboratable):
         fu_bitdict = {}
         for i, funame in enumerate(fus.keys()):
             fu_bitdict[funame] = fu_enable[i]
-
         # only run when allowed and when instruction is valid
         can_run = Signal(reset_less=True)
         comb += can_run.eq(self.ivalid_i & ~core_stopped)
 
+        # enable the required Function Unit based on the opcode decode
+        # note: this *only* works correctly for simple core when one and
+        # *only* one FU is allocated per instruction
+        for funame, fu in fus.items():
+            fnunit = fu.fnunit.value
+            enable = Signal(name="en_%s" % funame, reset_less=True)
+            comb += enable.eq((dec2.e.do.fn_unit & fnunit).bool() & can_run)
+            comb += fu_bitdict[funame].eq(enable)
+
         # sigh - need a NOP counter
         counter = Signal(2)
         with m.If(counter != 0):
@@ -136,16 +144,14 @@ class NonProductionCore(Elaboratable):
         with m.If(self.ivalid_i & (dec2.e.do.insn_type == InternalOp.OP_ATTN)):
             m.d.sync += core_stopped.eq(1)
 
-        with m.Elif(self.ivalid_i & (dec2.e.do.insn_type == InternalOp.OP_NOP)):
+        with m.Elif(can_run & (dec2.e.do.insn_type == InternalOp.OP_NOP)):
             sync += counter.eq(2)
             comb += self.busy_o.eq(1)
 
         with m.Else():
             # connect up instructions.  only one is enabled at any given time
             for funame, fu in fus.items():
-                fnunit = fu.fnunit.value
-                enable = Signal(name="en_%s" % funame, reset_less=True)
-                comb += enable.eq((dec2.e.do.fn_unit & fnunit).bool() & can_run)
+                enable = fu_bitdict[funame]
 
                 # run this FunctionUnit if enabled, except if the instruction
                 # is "attn" in which case we HALT.
@@ -156,7 +162,6 @@ class NonProductionCore(Elaboratable):
                     comb += self.busy_o.eq(fu.busy_o)
                     rdmask = dec2.rdflags(fu)
                     comb += fu.rdmaskn.eq(~rdmask)
-                    comb += fu_bitdict[funame].eq(enable)
 
         return fu_bitdict
 
@@ -273,7 +278,7 @@ class NonProductionCore(Elaboratable):
                     dest = fu.get_out(idx)
                     name = "wrflag_%s_%s_%d" % (funame, regname, idx)
                     wrflag = Signal(name=name, reset_less=True)
-                    comb += wrflag.eq(dest.ok)
+                    comb += wrflag.eq(dest.ok & fu.busy_o)
 
                     # connect request-read to picker input, and output to go-wr
                     fu_active = fu_bitdict[funame]