from nmutil.iocontrol import RecordObject
from nmutil.extend import exts
-from soc.decoder.power_regspec_map import regspec_decode
+from soc.decoder.power_regspec_map import regspec_decode_read
+from soc.decoder.power_regspec_map import regspec_decode_write
from soc.decoder.power_decoder import create_pdecode
from soc.decoder.power_enums import (InternalOp, CryIn, Function,
CRInSel, CROutSel,
comb += e.trapaddr.eq(0x70) # addr=0x700 (strip first nibble)
return m
- def regspecmap(self, regfile, regname):
- """regspecmap: provides PowerDecode2 with an encoding relationship
+ def regspecmap_read(self, regfile, regname):
+ """regspecmap_read: provides PowerDecode2 with an encoding relationship
to Function Unit port regfiles (read-enable, read regnum, write regnum)
regfile and regname arguments are fields 1 and 2 from a given regspec.
"""
- return regspec_decode(self.e, regfile, regname)
+ return regspec_decode_read(self.e, regfile, regname)
+
+ def regspecmap_write(self, regfile, regname):
+ """regspecmap_write: provides PowerDecode2 with an encoding relationship
+ to Function Unit port regfiles (write port, write regnum)
+ regfile and regname arguments are fields 1 and 2 from a given regspec.
+ """
+ return regspec_decode_write(self.e, regfile, regname)
def rdflags(self, cu):
rdl = []
for idx in range(cu.n_src):
regfile, regname, _ = cu.get_in_spec(idx)
- rdflag, read, write = self.regspecmap(regfile, regname)
+ rdflag, read = self.regspecmap_read(regfile, regname)
rdl.append(rdflag)
print ("rdflags", rdl)
return Cat(*rdl)
"""regspec_decode
-function for the relationship between regspecs and Decode2Execute1Type
+functions for the relationship between regspecs and Decode2Execute1Type
+these functions encodes the understanding (relationship) between
+Regfiles, Computation Units, and the Power ISA Decoder (PowerDecoder2).
+
+based on the regspec, which contains the register file name and register
+name, return a tuple of:
+
+* how the decoder should determine whether the Function Unit needs
+ access to a given Regport or not
+* which Regfile number on that port should be read to get that data
+* when it comes to writing: likewise, which Regfile num should be written
+
+Note that some of the port numbering encoding is *unary*. in the case
+of "Full Condition Register", it's a full 8-bit mask of read/write-enables.
+This actually matches directly with the XFX field in MTCR, and at
+some point that 8-bit mask from the instruction could actually be passed directly through to full_cr (TODO).
+
+For the INT and CR numbering, these are expressed in binary in the
+instruction (note however that XFX in MTCR is unary-masked!)
+
+XER is implicitly-encoded based on whether the operation has carry or
+overflow.
+
+FAST regfile is, again, implicitly encoded, back in PowerDecode2, based
+on the type of operation (see DecodeB for an example).
+
+The SPR regfile on the other hand is *binary*-encoded, and, furthermore,
+has to be "remapped".
see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
"""
from nmigen import Const
from soc.decoder.power_enums import CryIn
-def regspec_decode(e, regfile, name):
- """regspec_decode
-
- this function encodes the understanding (relationship) between
- Regfiles, Computation Units, and the Power ISA Decoder (PowerDecoder2).
+def regspec_decode_read(e, regfile, name):
+ """regspec_decode_read
+ """
- based on the regspec, which contains the register file name and register
- name, return a tuple of:
+ if regfile == 'INT':
+ # Int register numbering is *unary* encoded
+ if name == 'ra': # RA
+ return e.read_reg1.ok, 1<<e.read_reg1.data
+ if name == 'rb': # RB
+ return e.read_reg2.ok, 1<<e.read_reg2.data
+ if name == 'rc': # RS
+ return e.read_reg3.ok, 1<<e.read_reg3.data
- * how the decoder should determine whether the Function Unit needs
- access to a given Regport or not
- * which Regfile number on that port should be read to get that data
- * when it comes to writing: likewise, which Regfile num should be written
+ if regfile == 'CR':
+ # CRRegs register numbering is *unary* encoded
+ # *sigh*. numbering inverted on part-CRs. because POWER.
+ if name == 'full_cr': # full CR
+ return e.read_cr_whole, 0b11111111
+ if name == 'cr_a': # CR A
+ return e.read_cr1.ok, 1<<(7-e.read_cr1.data)
+ if name == 'cr_b': # CR B
+ return e.read_cr2.ok, 1<<(7-e.read_cr2.data)
+ if name == 'cr_c': # CR C
+ return e.read_cr3.ok, 1<<(7-e.read_cr3.data)
- Note that some of the port numbering encoding is *unary*. in the case
- of "Full Condition Register", it's a full 8-bit mask of read/write-enables.
- This actually matches directly with the XFX field in MTCR, and at
- some point that 8-bit mask from the instruction could actually be passed directly through to full_cr (TODO).
+ if regfile == 'XER':
+ # XERRegs register numbering is *unary* encoded
+ SO = 1<<XERRegs.SO
+ CA = 1<<XERRegs.CA
+ OV = 1<<XERRegs.OV
+ if name == 'xer_so':
+ return e.oe.oe[0] & e.oe.oe_ok, SO
+ if name == 'xer_ov':
+ return e.oe.oe[0] & e.oe.oe_ok, OV
+ if name == 'xer_ca':
+ return (e.input_carry == CryIn.CA.value), CA
- For the INT and CR numbering, these are expressed in binary in the
- instruction (note however that XFX in MTCR is unary-masked!)
+ 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 == 'spr1':
+ return e.read_fast1.ok, 1<<e.read_fast1.data
+ if name == 'spr2':
+ return e.read_fast2.ok, 1<<e.read_fast2.data
- XER is implicitly-encoded based on whether the operation has carry or
- overflow.
+ if regfile == 'SPR':
+ assert False, "regfile TODO %s %s" % (regfile, name)
+ assert False, "regspec not found %s %s" % (regfile, name)
- FAST regfile is, again, implicitly encoded, back in PowerDecode2, based
- on the type of operation (see DecodeB for an example).
- The SPR regfile on the other hand is *binary*-encoded, and, furthermore,
- has to be "remapped".
+def regspec_decode_write(e, regfile, name):
+ """regspec_decode_write
"""
if regfile == 'INT':
# Int register numbering is *unary* encoded
- if name == 'ra': # RA
- return e.read_reg1.ok, 1<<e.read_reg1.data, None
- if name == 'rb': # RB
- return e.read_reg2.ok, 1<<e.read_reg2.data, None
- if name == 'rc': # RS
- return e.read_reg3.ok, 1<<e.read_reg3.data, None
if name == 'o': # RT
- return e.write_reg.ok, None, 1<<e.write_reg.data
+ return e.write_reg, 1<<e.write_reg.data
if name == 'o1': # RA (update mode: LD/ST EA)
- return e.write_ea.ok, None, 1<<e.write_ea.data
+ return e.write_ea, 1<<e.write_ea.data
if regfile == 'CR':
# CRRegs register numbering is *unary* encoded
# *sigh*. numbering inverted on part-CRs. because POWER.
if name == 'full_cr': # full CR
- return e.read_cr_whole, 0b11111111, 0b11111111
+ return e.write_cr_whole, 0b11111111
if name == 'cr_a': # CR A
- return e.read_cr1.ok, 1<<(7-e.read_cr1.data), 1<<(7-e.write_cr.data)
- if name == 'cr_b': # CR B
- return e.read_cr2.ok, 1<<(7-e.read_cr2.data), None
- if name == 'cr_c': # CR C
- return e.read_cr3.ok, 1<<(7-e.read_cr3.data), None
+ return e.write_cr, 1<<(7-e.write_cr.data)
if regfile == 'XER':
# XERRegs register numbering is *unary* encoded
CA = 1<<XERRegs.CA
OV = 1<<XERRegs.OV
if name == 'xer_so':
- return e.oe.oe[0] & e.oe.oe_ok, SO, SO
+ return None, SO # hmmm
if name == 'xer_ov':
- return e.oe.oe[0] & e.oe.oe_ok, OV, OV
+ return None, OV # hmmm
if name == 'xer_ca':
- return (e.input_carry == CryIn.CA.value), CA, CA
+ return None, CA # hmmm
if regfile == 'FAST':
# FAST register numbering is *unary* encoded
SRR0 = 1<<FastRegs.SRR0
SRR1 = 1<<FastRegs.SRR1
if name in ['cia', 'nia']:
- return Const(1), PC, PC # TODO: detect read-conditions
+ return None, PC # hmmm
if name == 'msr':
- return Const(1), MSR, MS # TODO: detect read-conditions
+ return None, MSR # hmmm
# TODO: remap the SPR numbers to FAST regs
if name == 'spr1':
- return e.read_fast1.ok, 1<<e.read_fast1.data, 1<<e.write_fast1.data
+ return e.write_fast1, 1<<e.write_fast1.data
if name == 'spr2':
- return e.read_fast2.ok, 1<<e.read_fast2.data, 1<<e.write_fast2.data
+ return e.write_fast2, 1<<e.write_fast2.data
if regfile == 'SPR':
- assert False, "regfile TODO %s %s %d" % (refgile, repr(regspec), idx)
- assert False, "regspec not found %s %s %d" % (refgile, repr(regspec), idx)
+ assert False, "regfile TODO %s %s" % (regfile, name)
+ assert False, "regspec not found %s %s" % (regfile, name)
+