reduce regfile ports by creating separate STATE regfile
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 11 Aug 2020 13:13:13 +0000 (14:13 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 11 Aug 2020 13:13:13 +0000 (14:13 +0100)
src/soc/decoder/power_regspec_map.py
src/soc/fu/branch/pipe_data.py
src/soc/fu/spr/pipe_data.py
src/soc/fu/trap/pipe_data.py
src/soc/regfile/regfiles.py
src/soc/simple/issuer.py

index 7413cdd68edc4563e02eed48d1f31b8a7fc7d0fd..1dd3f0e442457b8639b9e00160eabcd1031759ed 100644 (file)
@@ -35,7 +35,7 @@ has to be "remapped" to internal SPR Enum indices (see SPRMap in PowerDecode2)
 see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
 """
 from nmigen import Const
-from soc.regfile.regfiles import XERRegs, FastRegs
+from soc.regfile.regfiles import XERRegs, FastRegs, StateRegs
 from soc.decoder.power_enums import CryIn
 
 
@@ -82,22 +82,26 @@ def regspec_decode_read(e, regfile, name):
         if name == 'xer_ca':
             return (e.do.input_carry == CryIn.CA.value) | e.xer_in, CA
 
+    # STATE regfile
+
+    if regfile == 'STATE':
+        # STATE register numbering is *unary* encoded
+        PC = 1<<StateRegs.PC
+        MSR = 1<<Stateegs.MSR
+        if name in ['cia', 'nia']:
+            return Const(1), PC # TODO: detect read-conditions
+        if name == 'msr':
+            return Const(1), MSR # TODO: detect read-conditions
+
     # FAST regfile
 
     if regfile == 'FAST':
         # FAST register numbering is *unary* encoded
-        PC = 1<<FastRegs.PC
-        MSR = 1<<FastRegs.MSR
         CTR = 1<<FastRegs.CTR
         LR = 1<<FastRegs.LR
         TAR = 1<<FastRegs.TAR
         SRR0 = 1<<FastRegs.SRR0
         SRR1 = 1<<FastRegs.SRR1
-        if name in ['cia', 'nia']:
-            return Const(1), PC # TODO: detect read-conditions
-        if name == 'msr':
-            return Const(1), MSR # TODO: detect read-conditions
-        # TODO: remap the SPR numbers to FAST regs
         if name == 'fast1':
             return e.read_fast1.ok, 1<<e.read_fast1.data
         if name == 'fast2':
@@ -150,22 +154,26 @@ def regspec_decode_write(e, regfile, name):
         if name == 'xer_ca':
             return e.xer_out, CA # hmmm
 
+    # STATE regfile
+
+    if regfile == 'STATE':
+        # STATE register numbering is *unary* encoded
+        PC = 1<<StateRegs.PC
+        MSR = 1<<StateRegs.MSR
+        if name in ['cia', 'nia']:
+            return None, PC # hmmm
+        if name == 'msr':
+            return None, MSR # hmmm
+
     # FAST regfile
 
     if regfile == 'FAST':
         # FAST register numbering is *unary* encoded
-        PC = 1<<FastRegs.PC
-        MSR = 1<<FastRegs.MSR
         CTR = 1<<FastRegs.CTR
         LR = 1<<FastRegs.LR
         TAR = 1<<FastRegs.TAR
         SRR0 = 1<<FastRegs.SRR0
         SRR1 = 1<<FastRegs.SRR1
-        if name in ['cia', 'nia']:
-            return None, PC # hmmm
-        if name == 'msr':
-            return None, MSR # hmmm
-        # TODO: remap the SPR numbers to FAST regs
         if name == 'fast1':
             return e.write_fast1, 1<<e.write_fast1.data
         if name == 'fast2':
index 9bbe0552243c7035076eb11d001ff96519ab7f10..9b62246f00e4f75daf2d6caa5fb4fcb584e0388e 100644 (file)
@@ -47,7 +47,7 @@ class BranchInputData(IntegerData):
 class BranchOutputData(IntegerData):
     regspec = [('FAST', 'fast1', '0:63'),
                ('FAST', 'fast2', '0:63'),
-               ('FAST', 'nia', '0:63')]
+               ('STATE', 'nia', '0:63')]
     def __init__(self, pspec):
         super().__init__(pspec, True)
 
index f7b28a259e287f8d78a7d2b8212adcc1eb5a821a..b66c35a0aba2b7144fbac66bab3cb93e74436ff8 100644 (file)
@@ -18,7 +18,7 @@ from soc.fu.alu.pipe_data import CommonPipeSpec
 class SPRInputData(IntegerData):
     regspec = [('INT', 'ra', '0:63'),        # RA
                ('SPR', 'spr1', '0:63'),      # SPR (slow)
-               ('FAST', 'fast1', '0:63'),    # SPR (fast: MSR, LR, CTR etc)
+               ('FAST', 'fast1', '0:63'),    # SPR (fast: LR, CTR etc)
                ('XER', 'xer_so', '32'),      # XER bit 32: SO
                ('XER', 'xer_ov', '33,44'),   # XER bit 34/45: CA/CA32
                ('XER', 'xer_ca', '34,45')]   # bit0: ov, bit1: ov32
@@ -31,7 +31,7 @@ class SPRInputData(IntegerData):
 class SPROutputData(IntegerData):
     regspec = [('INT', 'o', '0:63'),        # RT
                ('SPR', 'spr1', '0:63'),     # SPR (slow)
-               ('FAST', 'fast1', '0:63'),   # SPR (fast: MSR, LR, CTR etc)
+               ('FAST', 'fast1', '0:63'),   # SPR (fast: LR, CTR etc)
                ('XER', 'xer_so', '32'),     # XER bit 32: SO
                ('XER', 'xer_ov', '33,44'),  # XER bit 34/45: CA/CA32
                ('XER', 'xer_ca', '34,45')]  # bit0: ov, bit1: ov32
index de55cf2e57072bf35623581603a60373d459e4d9..863710c5879c91f958b6bfcbef5bb3aa26658684 100644 (file)
@@ -7,6 +7,8 @@ class TrapInputData(IntegerData):
                ('INT', 'rb', '0:63'),  # RB/immediate
                ('FAST', 'fast1', '0:63'), # SRR0
                ('FAST', 'fast2', '0:63'), # SRR1
+                # note here that neither MSR nor CIA are read as regs: they are
+                # passed in as incoming "State", via the CompTrapOpSubset
                ] 
     def __init__(self, pspec):
         super().__init__(pspec, False)
@@ -19,8 +21,8 @@ class TrapOutputData(IntegerData):
     regspec = [('INT', 'o', '0:63'),     # RA
                ('FAST', 'fast1', '0:63'), # SRR0 SPR
                ('FAST', 'fast2', '0:63'), # SRR1 SPR
-               ('FAST', 'nia', '0:63'),  # NIA (Next PC)
-               ('FAST', 'msr', '0:63')]  # MSR
+               ('STATE', 'nia', '0:63'),  # NIA (Next PC)
+               ('STATE', 'msr', '0:63')]  # MSR
     def __init__(self, pspec):
         super().__init__(pspec, True)
         # convenience
index 124fb03205f2c0c32819a9577a51cf53c642ddd5..20826b76dbeb4c70187a1a26ab04f5b178a4302d 100644 (file)
@@ -7,7 +7,8 @@ Defines the following register files:
     * SPR regfile   - 110x 64-bit
     * CR regfile    - CR0-7
     * XER regfile   - XER.so, XER.ca/ca32, XER.ov/ov32
-    * FAST regfile  - PC, MSR, CTR, LR, TAR, SRR1, SRR2
+    * FAST regfile  - CTR, LR, TAR, SRR1, SRR2
+    * STATE regfile  - PC, MSR, (SimpleV VL later)
 
 Note: this should NOT have name conventions hard-coded (dedicated ports per
 regname).  However it is convenient for now.
@@ -28,6 +29,33 @@ from soc.decoder.power_enums import SPR
 from nmigen import Memory, Elaboratable
 
 
+# "State" Regfile
+class StateRegs(RegFileArray):
+    """StateRegs
+
+    State regfile  - PC, MSR and later SimpleV VL
+
+    * QTY 2of 64-bit registers
+    * 3R2W
+    * Array-based unary-indexed (not binary-indexed)
+    * write-through capability (read on same cycle as write)
+
+    Note: d_wr1 d_rd1 are for use by the decoder, to get at the PC.
+    will probably have to also add one so it can get at the MSR as well.
+    (d_rd2)
+    """
+    PC = 0
+    MSR = 1
+    def __init__(self):
+        super().__init__(64, 2)
+        self.w_ports = {'nia': self.write_port("nia"),
+                        'msr': self.write_port("msr"),
+                        'd_wr1': self.write_port("d_wr1")} # writing PC (issuer)
+        self.r_ports = {'cia': self.read_port("cia"), # reading PC (issuer)
+                        'msr': self.read_port("msr"), # reading MSR (issuer)
+                        }
+
+
 # Integer Regfile
 class IntRegs(RegFileArray):
     """IntRegs
@@ -50,34 +78,24 @@ class IntRegs(RegFileArray):
 class FastRegs(RegFileArray):
     """FastRegs
 
-    FAST regfile  - PC, MSR, CTR, LR, TAR, SRR1, SRR2
+    FAST regfile  - CTR, LR, TAR, SRR1, SRR2
 
-    * QTY 8of 64-bit registers
-    * 3R2W
+    * QTY 5of 64-bit registers
+    * 2R1W
     * Array-based unary-indexed (not binary-indexed)
     * write-through capability (read on same cycle as write)
-
-    Note: d_wr1 d_rd1 are for use by the decoder, to get at the PC.
-    will probably have to also add one so it can get at the MSR as well.
-    (d_rd2)
     """
-    PC = 0
-    MSR = 1
-    CTR = 2
-    LR = 3
-    TAR = 4
-    SRR0 = 5
-    SRR1 = 6
+    CTR = 0
+    LR = 1
+    TAR = 2
+    SRR0 = 3
+    SRR1 = 4
     def __init__(self):
-        super().__init__(64, 8)
-        self.w_ports = {'nia': self.write_port("nia"),
-                        'msr': self.write_port("dest2"),
-                        'fast1': self.write_port("dest3"),
+        super().__init__(64, 5)
+        self.w_ports = {'fast1': self.write_port("dest3"),
                         'fast2': self.write_port("dest4"),
-                        'd_wr1': self.write_port("d_wr1")} # writing PC (issuer)
-        self.r_ports = {'cia': self.read_port("cia"), # reading PC (issuer)
-                        'msr': self.read_port("msr"), # reading MSR (issuer)
-                        'fast1': self.read_port("src1"),
+                       }
+        self.r_ports = {'fast1': self.read_port("src1"),
                         }
 
 
@@ -140,6 +158,7 @@ class SPRRegs(Memory, Elaboratable):
         self.w_ports = {'spr1': self.write_port()}
         self.r_ports = {'spr1': self.read_port()}
 
+        # make read/write ports look like RegFileArray
         self.w_ports['spr1'].wen = self.w_ports['spr1'].en
         self.w_ports['spr1'].data_i = self.w_ports['spr1'].data
 
@@ -155,6 +174,7 @@ class RegFiles:
                             ('cr', CRRegs),
                             ('xer', XERRegs),
                             ('fast', FastRegs),
+                            ('state', StateRegs),
                             ('spr', SPRRegs),]:
             rf = self.rf[name] = kls()
             setattr(self, name, rf)
index 558ee51ed92c1727fcc2fdac1fefd419cc09e5e6..64f203088ee74072a6810f2d9f9a4d6566085641 100644 (file)
@@ -2,7 +2,7 @@
 
 not in any way intended for production use.  this runs a FSM that:
 
-* reads the Program Counter from FastRegs
+* reads the Program Counter from StateRegs
 * reads an instruction from a fixed-size Test Memory
 * issues it to the Simple Core
 * waits for it to complete
@@ -23,7 +23,7 @@ import sys
 
 from soc.decoder.decode2execute1 import Data
 from soc.experiment.testmem import TestMemory # test only for instructions
-from soc.regfile.regfiles import FastRegs
+from soc.regfile.regfiles import StateRegs
 from soc.simple.core import NonProductionCore
 from soc.config.test.test_loadstore import TestMemPspec
 from soc.config.ifetch import ConfigFetchUnit
@@ -60,16 +60,16 @@ class TestIssuer(Elaboratable):
         self.memerr_o = Signal(reset_less=True)
 
         # FAST regfile read /write ports for PC and MSR
-        self.fast_r_pc = self.core.regs.rf['fast'].r_ports['cia'] # PC rd
-        self.fast_w_pc = self.core.regs.rf['fast'].w_ports['d_wr1'] # PC wr
-        self.fast_r_msr = self.core.regs.rf['fast'].r_ports['msr'] # MSR rd
+        self.state_r_pc = self.core.regs.rf['state'].r_ports['cia'] # PC rd
+        self.state_w_pc = self.core.regs.rf['state'].w_ports['d_wr1'] # PC wr
+        self.state_r_msr = self.core.regs.rf['state'].r_ports['msr'] # MSR rd
 
         # DMI interface access
         self.int_r = self.core.regs.rf['int'].r_ports['dmi'] # INT read
 
         # hack method of keeping an eye on whether branch/trap set the PC
-        self.fast_nia = self.core.regs.rf['fast'].w_ports['nia']
-        self.fast_nia.wen.name = 'fast_nia_wen'
+        self.state_nia = self.core.regs.rf['state'].w_ports['nia']
+        self.state_nia.wen.name = 'state_nia_wen'
 
     def elaborate(self, platform):
         m = Module()
@@ -127,9 +127,9 @@ class TestIssuer(Elaboratable):
             # incoming override (start from pc_i)
             comb += pc.eq(self.pc_i.data)
         with m.Else():
-            # otherwise read FastRegs regfile for PC
-            comb += self.fast_r_pc.ren.eq(1<<FastRegs.PC)
-            comb += pc.eq(self.fast_r_pc.data_o)
+            # otherwise read StateRegs regfile for PC
+            comb += self.state_r_pc.ren.eq(1<<StateRegs.PC)
+            comb += pc.eq(self.state_r_pc.data_o)
 
         # connect up debug signals
         # TODO comb += core.icache_rst_i.eq(dbg.icache_rst_o)
@@ -150,7 +150,7 @@ class TestIssuer(Elaboratable):
         insn_state = core.pdecode2.state
 
         # don't read msr every cycle
-        sync += self.fast_r_msr.ren.eq(0)
+        sync += self.state_r_msr.ren.eq(0)
 
         # actually use a nmigen FSM for the first time (w00t)
         # this FSM is perhaps unusual in that it detects conditions
@@ -173,8 +173,8 @@ class TestIssuer(Elaboratable):
                     sync += cur_state.pc.eq(pc)
 
                     # read MSR, latch it, and put it in decode "state"
-                    sync += self.fast_r_msr.ren.eq(1<<FastRegs.MSR)
-                    sync += cur_state.msr.eq(self.fast_r_msr.data_o)
+                    sync += self.state_r_msr.ren.eq(1<<StateRegs.MSR)
+                    sync += cur_state.msr.eq(self.state_r_msr.data_o)
 
                     m.next = "INSN_READ" # move to "wait for bus" phase
 
@@ -208,15 +208,15 @@ class TestIssuer(Elaboratable):
                     comb += core_ivalid_i.eq(1) # instruction is valid
                 comb += core_opcode_i.eq(ilatch) # actual opcode
                 comb += insn_state.eq(cur_state)     # and MSR and PC
-                with m.If(self.fast_nia.wen):
+                with m.If(self.state_nia.wen):
                     sync += pc_changed.eq(1)
                 with m.If(~core_busy_o): # instruction done!
                     # ok here we are not reading the branch unit.  TODO
                     # this just blithely overwrites whatever pipeline
                     # updated the PC
                     with m.If(~pc_changed):
-                        comb += self.fast_w_pc.wen.eq(1<<FastRegs.PC)
-                        comb += self.fast_w_pc.data_i.eq(nia)
+                        comb += self.state_w_pc.wen.eq(1<<StateRegs.PC)
+                        comb += self.state_w_pc.data_i.eq(nia)
                     m.next = "IDLE" # back to idle
 
         # this bit doesn't have to be in the FSM: connect up to read