Merge branch 'master' of ssh://git.libre-riscv.org:922/soc
authorTobias Platen <tplaten@posteo.de>
Wed, 10 Nov 2021 17:58:18 +0000 (18:58 +0100)
committerTobias Platen <tplaten@posteo.de>
Wed, 10 Nov 2021 17:58:18 +0000 (18:58 +0100)
src/soc/simple/core.py
src/soc/simple/issuer.py

index 3dd40c6a990fb42266c3f3c0375222b60cd2d36a..0602691b78419b99dcdb1888f494dc7bc41e6620 100644 (file)
@@ -126,11 +126,13 @@ class CoreInput:
 class CoreOutput:
     def __init__(self):
         # start/stop and terminated signalling
-        self.core_terminate_o = Signal(reset=0)  # indicates stopped
+        self.core_terminate_o = Signal()  # indicates stopped
+        self.busy_o = Signal(name="corebusy_o")  # at least one ALU busy
         self.exc_happened = Signal()             # exception happened
 
     def eq(self, i):
         self.core_terminate_o.eq(i.core_terminate_o)
+        self.busy_o.eq(i.busy_o)
         self.exc_happened.eq(i.exc_happened)
 
 
@@ -282,7 +284,7 @@ class NonProductionCore(ControlBase):
         fus = self.fus.fus
 
         # indicate if core is busy
-        busy_o = Signal(name="corebusy_o", reset_less=True)
+        busy_o = self.o.busy_o
 
         # enable/busy-signals for each FU, get one bit for each FU (by name)
         fu_enable = Signal(len(fus), reset_less=True)
@@ -310,6 +312,7 @@ class NonProductionCore(ControlBase):
         # now create a PriorityPicker per FU-type such that only one
         # non-busy FU will be picked
         issue_pps = {}
+        fu_found = Signal() # take a note if no Function Unit was available
         for fname, fu_list in by_fnunit.items():
             i_pp = PriorityPicker(len(fu_list))
             m.submodules['i_pp_%s' % fname] = i_pp
@@ -331,6 +334,10 @@ class NonProductionCore(ControlBase):
                 comb += po.eq(i_pp.o[i] & i_pp.en_o)
                 comb += fu_bitdict[funame].eq(po)
                 comb += fu_selected[funame].eq(fu.busy_o | po)
+                # if we don't do this, then when there are no FUs available,
+                # the "p.o_ready" signal will go back "ok we accepted this
+                # instruction" which of course isn't true.
+                comb += fu_found.eq(~fnmatch | i_pp.en_o)
             # for each input, Cat them together and drop them into the picker
             comb += i_pp.i.eq(Cat(*i_l))
 
@@ -372,12 +379,14 @@ class NonProductionCore(ControlBase):
         busys = map(lambda fu: fu.busy_o, fus.values())
         comb += busy_o.eq(Cat(*busys).bool())
 
-        # set ready/valid signalling.  if busy, means refuse incoming issue
-        # XXX note: for an in-order core this is far too simple.  busy must
-        # be gated with the *availability* of the incoming (requested)
-        # instruction, where Core must be prepared to store-and-hold
-        # an instruction if no FU is available.
-        comb += self.p.o_ready.eq(~busy_o)
+        # ready/valid signalling.  if busy, means refuse incoming issue.
+        # (this is a global signal, TODO, change to one which allows
+        # overlapping instructions)
+        # also, if there was no fu found we must not send back a valid
+        # indicator.  BUT, of course, when there is no instruction
+        # we must ignore the fu_found flag, otherwise o_ready will never
+        # be set when everything is idle
+        comb += self.p.o_ready.eq(fu_found | ~self.p.i_valid)
 
         # return both the function unit "enable" dict as well as the "busy".
         # the "busy-or-issued" can be passed in to the Read/Write port
index 61e28a7460ffe9f52e53093835a0d930d2d6bf44..24830149a606a981f08e697e489a658fd7cea892 100644 (file)
@@ -861,7 +861,7 @@ class TestIssuerInternal(Elaboratable):
         pdecode2 = self.pdecode2
 
         # temporaries
-        core_busy_o = ~core.p.o_ready                # core is busy
+        core_busy_o = ~core.p.o_ready | core.n.o_data.busy_o # core is busy
         core_ivalid_i = core.p.i_valid              # instruction is valid
 
         with m.FSM(name="exec_fsm"):
@@ -979,7 +979,7 @@ class TestIssuerInternal(Elaboratable):
             comb += dbg_rst.eq(ResetSignal())
 
         # busy/halted signals from core
-        core_busy_o = ~core.p.o_ready                # core is busy
+        core_busy_o = ~core.p.o_ready | core.n.o_data.busy_o # core is busy
         comb += self.busy_o.eq(core_busy_o)
         comb += pdecode2.dec.bigendian.eq(self.core_bigendian_i)