add in branch speculation recorder, link to branch
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 24 May 2019 14:41:39 +0000 (15:41 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 24 May 2019 14:41:39 +0000 (15:41 +0100)
src/experiment/score6600.py
src/scoreboard/shadow.py

index 9966e9ac06f4a07615923e5a49d21adc886999c0..c8360316219a6243ea1420d38e4777e3e9cf3f38 100644 (file)
@@ -9,7 +9,7 @@ from scoreboard.fu_reg_matrix import FURegDepMatrix
 from scoreboard.global_pending import GlobalPending
 from scoreboard.group_picker import GroupPicker
 from scoreboard.issue_unit import IntFPIssueUnit, RegDecode
-from scoreboard.shadow import ShadowMatrix, WaWGrid
+from scoreboard.shadow import ShadowMatrix, BranchSpeculationRecord
 
 from compalu import ComputationUnitNoDelay
 
@@ -51,8 +51,9 @@ class CompUnits(Elaboratable):
         self.src1_data_i = Signal(rwid, reset_less=True)
         self.src2_data_i = Signal(rwid, reset_less=True)
 
-        # Branch ALU
+        # Branch ALU and CU
         self.bgt = BranchALU(self.rwid)
+        self.br1 = ComputationUnitNoDelay(self.rwid, 2, self.bgt)
 
     def elaborate(self, platform):
         m = Module()
@@ -68,7 +69,7 @@ class CompUnits(Elaboratable):
         m.submodules.comp2 = comp2 = ComputationUnitNoDelay(self.rwid, 2, sub)
         m.submodules.comp3 = comp3 = ComputationUnitNoDelay(self.rwid, 2, mul)
         m.submodules.comp4 = comp4 = ComputationUnitNoDelay(self.rwid, 2, shf)
-        m.submodules.br1 = br1 = ComputationUnitNoDelay(self.rwid, 2, bgt)
+        m.submodules.br1 = br1 = self.br1
         int_alus = [comp1, comp2, comp3, comp4, br1]
 
         m.d.comb += comp1.oper_i.eq(Const(0, 2)) # op=add
@@ -269,6 +270,7 @@ class Scoreboard(Elaboratable):
         # write-after-write hazards.  NOTE: there is one extra for branches,
         # so the shadow width is increased by 1
         m.submodules.shadows = shadows = ShadowMatrix(n_int_fus, n_int_fus+1)
+
         # combined go_rd/wr + go_die (go_die used to reset latches)
         go_rd_rst = Signal(n_int_fus, reset_less=True)
         go_wr_rst = Signal(n_int_fus, reset_less=True)
@@ -276,6 +278,11 @@ class Scoreboard(Elaboratable):
         fn_issue_prev = Signal(n_int_fus)
         prev_shadow = Signal(n_int_fus)
 
+        # Branch Speculation recorder.  tracks the success/fail state as
+        # each instruction is issued, so that when the branch occurs the
+        # allow/cancel can be issued as appropriate.
+        m.submodules.specrec = bspec = BranchSpeculationRecord(n_int_fus)
+
         #---------
         # ok start wiring things together...
         # "now hear de word of de looord... dem bones dem bones dem dryy bones"
@@ -344,6 +351,9 @@ class Scoreboard(Elaboratable):
         m.d.comb += go_rd_rst.eq(go_rd_o | shadows.go_die_o)
         m.d.comb += go_wr_rst.eq(go_wr_o | shadows.go_die_o)
 
+        #---------
+        # NOTE; this setup is for the instruction order preservation...
+
         # connect shadows / go_dies to Computation Units
         m.d.comb += cu.shadown_i[0:n_int_fus].eq(shadows.shadown_o[0:n_int_fus])
         m.d.comb += cu.go_die_i[0:n_int_fus].eq(shadows.go_die_o[0:n_int_fus])
@@ -366,6 +376,31 @@ class Scoreboard(Elaboratable):
         for i in range(n_int_fus):
             m.d.comb += shadows.shadow_i[i][0:n_int_fus].eq(prev_shadow)
 
+        #---------
+        # ... and this is for branch speculation.  it uses the extra bit
+        # tacked onto the ShadowMatrix (hence shadow_wid=n_int_fus+1)
+        # only needs to set shadow_i, s_fail_i and s_good_i
+
+        m.d.comb += shadows.s_good_i[n_int_fus].eq(bspec.good_o[i])
+        m.d.comb += shadows.s_fail_i[n_int_fus].eq(bspec.fail_o[i])
+
+        with m.If(self.branch_succ_i | self.branch_fail_i):
+            for i in range(n_int_fus):
+                m.d.comb +=  shadows.shadow_i[i][n_int_fus].eq(1)
+
+        # finally, we need an indicator to the test infrastructure as to
+        # whether the branch succeeded or failed, plus, link up to the
+        # "recorder" of whether the instruction was under shadow or not
+
+        m.d.comb += bspec.issue_i.eq(fn_issue_o)
+        m.d.comb += bspec.good_i.eq(self.branch_succ_i)
+        m.d.comb += bspec.fail_i.eq(self.branch_fail_i)
+        # branch is active (TODO: a better signal: this is over-using the
+        # go_write signal - actually the branch should not be "writing")
+        with m.If(cu.br1.go_wr_i):
+            m.d.sync += self.branch_direction_o.eq(cu.br1.data_o+Const(1, 2))
+            m.d.comb += bspec.branch_i.eq(1)
+
         #---------
         # Connect Register File(s)
         #---------
index aaee56cc9de5b8393a84ca5c0b658b79874fe608..c1d77a0229835913fbf334416b27850837dcadbf 100644 (file)
@@ -203,16 +203,15 @@ class BranchSpeculationRecord(Elaboratable):
         # ANDing and ORing...
         for i in range(self.n_fus):
             with m.If(self.branch_i):
+                with m.If(good_r[i] | fail_r[i]):
+                    m.d.comb += self.good_o[i].eq(good_r[i] | ~fail_r[i])
+                    m.d.comb += self.fail_o[i].eq(fail_r[i] | ~good_r[i])
                 m.d.sync += good_r[i].eq(0) # might be set if issue set as well
                 m.d.sync += fail_r[i].eq(0) # might be set if issue set as well
             with m.If(self.issue_i[i]):
                 m.d.sync += good_r[i].eq(self.good_i[i])
                 m.d.sync += fail_r[i].eq(self.fail_i[i])
 
-        with m.If(self.branch_i):
-            m.d.comb += self.good_o.eq(good_r | ~fail_r)
-            m.d.comb += self.fail_o.eq(fail_r | ~good_r)
-
         return m
 
     def __iter__(self):