from nmigen import Module
from nmigen.cli import rtlil
+from nmutil.latch import SRLatch
+
+
+def create_ports(rf, wr_spec, rd_spec):
+ """create_ports: creates register file ports based on requested specs
+ """
+ rf.r_ports, rf.w_ports = {}, {}
+ # create read ports based on read specs
+ for key, name in rd_spec.items():
+ if hasattr(rf, name): # some regfiles already have a port
+ rf.r_ports[key] = getattr(rf, name)
+ else:
+ rf.r_ports[key] = rf.read_port(name)
+ # create write ports based on write specs
+ for key, name in wr_spec.items():
+ if hasattr(rf, name): # some regfiles already have a port
+ rf.w_ports[key] = getattr(rf, name)
+ else:
+ rf.w_ports[key] = rf.write_port(name)
# "State" Regfile
(d_rd2)
"""
- def __init__(self, svp64_en=False, regreduce_en=False):
- super().__init__(64, StateRegsEnum.N_REGS)
- self.w_ports = {'nia': self.write_port("nia"),
- 'msr': self.write_port("msr"),
- 'svstate': self.write_port("svstate"),
- 'sv': self.write_port("sv"), # writing SVSTATE (issuer)
- '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)
- 'sv': self.read_port("sv"), # reading SV (issuer)
+ def __init__(self, svp64_en=False, regreduce_en=False, resets=None):
+ super().__init__(64, StateRegsEnum.N_REGS, resets=resets)
+ wr_spec, rd_spec = self.get_port_specs()
+ create_ports(self, wr_spec, rd_spec)
+
+ def get_port_specs(self):
+ w_port_spec = { # these 3 allow writing state by Function Units
+ # strictly speaking this should not be allowed,
+ # the information should be passed back to Issuer
+ # to work out what to do
+ 'nia': "nia",
+ 'msr': "msr",
+ 'svstate': "svstate",
+ 'issue': "issue", # writing DEC/TB
+ 'state1': "state1", # SPR pipeline
+ # these 3 allow writing state by Issuer
+ 'sv': "sv", # writing SVSTATE
+ 'd_wr1': "d_wr1", # writing PC
+ 'd_wr2': "d_wr2"} # writing MSR
+ r_port_spec = { # these are for reading state by Issuer but
+ # the FUs do not read them: they are passed in
+ # because of multi-issue / pipelining / etc.
+ # the state could be totally different and is
+ # only known *at* issue time, *by* the issuer
+ 'cia': "cia", # reading PC (issuer)
+ 'msr': "msr", # reading MSR (issuer)
+ 'sv': "sv", # reading SV (issuer)
+ # SPR and DEC/TB FSM
+ 'issue': "issue", # reading DEC/TB
+ 'state1': "state1", # SPR pipeline
}
+ return w_port_spec, r_port_spec
# Integer Regfile
* Array-based unary-indexed (not binary-indexed)
* write-through capability (read on same cycle as write)
"""
- def __init__(self, svp64_en=False, regreduce_en=False):
- super().__init__(64, 32, fwd_bus_mode=not regreduce_en)
- self.w_ports = {'o': self.write_port("dest1"),
+ def __init__(self, svp64_en=False, regreduce_en=False, reg_wid=64):
+ super().__init__(reg_wid, 32, fwd_bus_mode=False)
+ self.svp64_en = svp64_en
+ self.regreduce_en = regreduce_en
+ wr_spec, rd_spec = self.get_port_specs()
+ create_ports(self, wr_spec, rd_spec)
+
+ def get_port_specs(self):
+ w_port_spec = {'o': "dest1",
}
- self.r_ports = {
- 'dmi': self.read_port("dmi")} # needed for Debug (DMI)
- if svp64_en:
- self.r_ports['pred'] = self.read_port("pred") # for predicate mask
- if not regreduce_en:
- self.w_ports['o1'] = self.write_port("dest2") # (LD/ST update)
- self.r_ports['ra'] = self.read_port("src1")
- self.r_ports['rb'] = self.read_port("src2")
- self.r_ports['rc'] = self.read_port("src3")
+ r_port_spec = { 'dmi': "dmi" # needed for Debug (DMI)
+ }
+ if self.svp64_en:
+ r_port_spec['pred'] = "pred" # for predicate mask
+ if not self.regreduce_en:
+ w_port_spec['o1'] = "dest2" # (LD/ST update)
+ r_port_spec['ra'] = "src1"
+ r_port_spec['rb'] = "src2"
+ r_port_spec['rc'] = "src3"
else:
- self.r_ports['rabc'] = self.read_port("src1")
+ r_port_spec['rabc'] = "src1"
+ return w_port_spec, r_port_spec
# Fast SPRs Regfile
class FastRegs(RegFileMem, FastRegsEnum): #RegFileArray):
"""FastRegs
- FAST regfile - CTR, LR, TAR, SRR1, SRR2, XER, TB, DEC, SVSRR0
+ FAST regfile - CTR, LR, TAR, SRR1, SRR2, XER, SVSRR0
* QTY 6of 64-bit registers
* 3R2W
Note: r/w issue are used by issuer to increment/decrement TB/DEC.
"""
def __init__(self, svp64_en=False, regreduce_en=False):
- super().__init__(64, FastRegsEnum.N_REGS, fwd_bus_mode=not regreduce_en)
- self.w_ports = {'fast1': self.write_port("dest1"),
- 'issue': self.write_port("issue"), # writing DEC/TB
+ super().__init__(64, FastRegsEnum.N_REGS, fwd_bus_mode=False)
+ self.svp64_en = svp64_en
+ self.regreduce_en = regreduce_en
+ wr_spec, rd_spec = self.get_port_specs()
+ create_ports(self, wr_spec, rd_spec)
+
+ def get_port_specs(self):
+ w_port_spec = {'fast1': "dest1",
}
- self.r_ports = {'fast1': self.read_port("src1"),
- 'issue': self.read_port("issue"), # reading DEC/TB
+ r_port_spec = {'fast1': "src1",
+ 'dmi': "dmi" # needed for Debug (DMI)
}
- if not regreduce_en:
- self.r_ports['fast2'] = self.read_port("src2")
+ if not self.regreduce_en:
+ r_port_spec['fast2'] = "src2"
+ r_port_spec['fast3'] = "src3"
+ w_port_spec['fast2'] = "dest2"
+ w_port_spec['fast3'] = "dest3"
+
+ return w_port_spec, r_port_spec
# CR Regfile
"""
def __init__(self, svp64_en=False, regreduce_en=False):
super().__init__(32, 8, rd2=True)
- self.w_ports = {'full_cr': self.full_wr, # 32-bit (masked, 8-en lines)
- 'cr_a': self.write_port("dest1"), # 4-bit, unary-indexed
- 'cr_b': self.write_port("dest2")} # 4-bit, unary-indexed
- self.r_ports = {'full_cr': self.full_rd, # 32-bit (masked, 8-en lines)
- 'full_cr_dbg': self.full_rd2, # for DMI
- 'cr_a': self.read_port("src1"),
- 'cr_b': self.read_port("src2"),
- 'cr_c': self.read_port("src3")}
- if svp64_en:
- self.r_ports['cr_pred'] = self.read_port("cr_pred") # for predicate
+ self.svp64_en = svp64_en
+ self.regreduce_en = regreduce_en
+ wr_spec, rd_spec = self.get_port_specs()
+ create_ports(self, wr_spec, rd_spec)
+
+ def get_port_specs(self):
+ w_port_spec = {'full_cr': "full_wr", # 32-bit (masked, 8-en lines)
+ 'cr_a': "dest1", # 4-bit, unary-indexed
+ 'cr_b': "dest2"} # 4-bit, unary-indexed
+ r_port_spec = {'full_cr': "full_rd", # 32-bit (masked, 8-en lines)
+ 'full_cr_dbg': "full_rd2", # for DMI
+ 'cr_a': "src1",
+ 'cr_b': "src2",
+ 'cr_c': "src3"}
+ if self.svp64_en:
+ r_port_spec['cr_pred'] = "cr_pred" # for predicate
+
+ return w_port_spec, r_port_spec
# XER Regfile
OV=2 # OV and OV32
def __init__(self, svp64_en=False, regreduce_en=False):
super().__init__(6, XERRegsEnum.N_REGS)
- self.w_ports = {'full_xer': self.full_wr, # 6-bit (masked, 3-en lines)
- 'xer_so': self.write_port("dest1"),
- 'xer_ca': self.write_port("dest2"),
- 'xer_ov': self.write_port("dest3")}
- self.r_ports = {'full_xer': self.full_rd, # 6-bit (masked, 3-en lines)
- 'xer_so': self.read_port("src1"),
- 'xer_ca': self.read_port("src2"),
- 'xer_ov': self.read_port("src3")}
+ self.svp64_en = svp64_en
+ self.regreduce_en = regreduce_en
+ wr_spec, rd_spec = self.get_port_specs()
+ create_ports(self, wr_spec, rd_spec)
+
+ def get_port_specs(self):
+ w_port_spec = {'full_xer': "full_wr", # 6-bit (masked, 3-en lines)
+ 'xer_so': "dest1",
+ 'xer_ca': "dest2",
+ 'xer_ov': "dest3"}
+ r_port_spec = {'full_xer': "full_rd", # 6-bit (masked, 3-en lines)
+ 'xer_so': "src1",
+ 'xer_ca': "src2",
+ 'xer_ov': "src3"}
+ return w_port_spec, r_port_spec
# SPR Regfile
else:
n_sprs = len(SPRfull)
super().__init__(width=64, depth=n_sprs,
- fwd_bus_mode=not regreduce_en)
- self.w_ports = {'spr1': self.write_port("spr1")}
- self.r_ports = {'spr1': self.read_port("spr1")}
+ fwd_bus_mode=False)
+ self.svp64_en = svp64_en
+ self.regreduce_en = regreduce_en
+ wr_spec, rd_spec = self.get_port_specs()
+ create_ports(self, wr_spec, rd_spec)
+
+ def get_port_specs(self):
+ w_port_spec = {'spr1': "spr1"}
+ r_port_spec = {'spr1': "spr1"}
+ return w_port_spec, r_port_spec
# class containing all regfiles: int, cr, xer, fast, spr
('fast', FastRegs),
('state', StateRegs),
('spr', SPRRegs),]
- def __init__(self, pspec, make_hazard_vecs=False):
+ def __init__(self, pspec, make_hazard_vecs=False,
+ state_resets=None): # state file reset values
# test is SVP64 is to be enabled
svp64_en = hasattr(pspec, "svp64") and (pspec.svp64 == True)
regreduce_en = hasattr(pspec, "regreduce") and \
(pspec.regreduce == True)
+ # get Integer File register width
+ reg_wid = 64
+ if isinstance(pspec.XLEN, int):
+ reg_wid = pspec.XLEN
+
self.rf = {} # register file dict
# create regfiles here, Factory style
for (name, kls) in RegFiles.regkls:
- rf = self.rf[name] = kls(svp64_en, regreduce_en)
+ kwargs = {'svp64_en': svp64_en, 'regreduce_en': regreduce_en}
+ if name == 'state':
+ kwargs['resets'] = state_resets
+ if name == 'int':
+ kwargs['reg_wid'] = reg_wid
+ rf = self.rf[name] = kls(**kwargs)
# also add these as instances, self.state, self.fast, self.cr etc.
setattr(self, name, rf)
self.rv, self.wv = {}, {}
if make_hazard_vecs:
# create a read-hazard and write-hazard vectors for this regfile
- self.wv = make_vecs(self, "wr") # global write vectors
- self.rv = make_vecs(self, "rd") # global read vectors
+ self.wv = self.make_vecs("wr") # global write vectors
+ self.rv = self.make_vecs("rd") # global read vectors
def make_vecs(self, name):
vec = {}
# create regfiles here, Factory style
for (name, kls) in RegFiles.regkls:
+ rf = self.rf[name]
vec[name] = self.make_hazard_vec(rf, name)
return vec
def make_hazard_vec(self, rf, name):
if isinstance(rf, VirtualRegPort):
- vec = RegFileArray(rf.bitwidth, 1)
- else:
- vec = RegFileArray(rf.depth, 1)
- if name in ['int', 'cr', 'xer']:
- n_wrs = 3
- elif name in ['fast']:
- n_wrs = 2
+ vec = SRLatch(sync=False, llen=rf.nregs, name=name)
else:
- n_wrs = 1
- # add write ports
- vec.w_ports = {}
- for i in range(n_wrs):
- pname = "wr%d" % i
- vec.w_ports[pname] = vec.write_port("%s_%s" % (name, pname))
- # add read port
- vec.r_ports = {}
- pname = "rd%d" % 0
- vec.r_ports[pname] = vec.read_port("%s_%s" % (name, pname))
+ vec = SRLatch(sync=False, llen=rf.depth, name=name)
return vec
def elaborate_into(self, m, platform):
if __name__ == '__main__':
m = Module()
from soc.config.test.test_loadstore import TestMemPspec
- pspec = TestMemPspec()
+ pspec = TestMemPspec(regreduce_en=True,
+ XLEN=32) # integer reg width = 32
rf = RegFiles(pspec, make_hazard_vecs=True)
rf.elaborate_into(m, None)
vl = rtlil.convert(m)