LdstLen, In1Sel, In2Sel, In3Sel,
OutSel, SPR, RC)
+from soc.regfile.regfiles import FastRegs
class DecodeA(Elaboratable):
"""DecodeA from instruction
with m.If((op.internal_op == InternalOp.OP_BC) |
(op.internal_op == InternalOp.OP_BCREG)):
with m.If(~self.dec.BO[2]): # 3.0B p38 BO2=0, use CTR reg
- comb += self.spr_out.data.eq(SPR.CTR) # constant: CTR
+ comb += self.spr_out.data.eq(FastRegs.CTR) # constant: CTR
comb += self.spr_out.ok.eq(1)
# MFSPR or MTSPR: move-from / move-to SPRs
with m.If((op.internal_op == InternalOp.OP_MFSPR) |
(op.internal_op == InternalOp.OP_MTSPR)):
+ # XXX TODO: fast/slow SPR decoding and mapping
comb += self.spr_out.data.eq(self.dec.SPR) # SPR field, XFX
comb += self.spr_out.ok.eq(1)
# BCREG implicitly uses CTR or LR for 2nd reg
with m.If(op.internal_op == InternalOp.OP_BCREG):
with m.If(self.dec.FormXL.XO[9]): # 3.0B p38 top bit of XO
- comb += self.spr_out.data.eq(SPR.CTR)
+ comb += self.spr_out.data.eq(FastRegs.CTR)
with m.Else():
- comb += self.spr_out.data.eq(SPR.LR)
+ comb += self.spr_out.data.eq(FastRegs.LR)
comb += self.spr_out.ok.eq(1)
return m
import unittest
-from soc.decoder.power_enums import (XER_bits, Function, spr_dict)
+from soc.decoder.power_enums import (XER_bits, Function, spr_dict, SPR)
# XXX bad practice: use of global variables
from soc.fu.branch.test.test_pipe_caller import BranchTestCase
from soc.fu.compunits.compunits import BranchFunctionUnit
from soc.fu.compunits.test.test_compunit import TestRunner
+from soc.regfile.regfiles import FastRegs
"""
def assert_outputs(self, branch, dec2, sim, prev_nia, code):
"""
+def fast_reg_to_spr(spr_num):
+ if spr_num == FastRegs.CTR:
+ return SPR.CTR.value
+ elif spr_num == FastRegs.LR:
+ return SPR.LR.value
+ elif spr_num == FastRegs.TAR:
+ return SPR.TAR.value
+
class BranchTestRunner(TestRunner):
def __init__(self, test_data):
# SPR1
spr_ok = yield dec2.e.read_spr1.ok
spr_num = yield dec2.e.read_spr1.data
+ # HACK
+ spr_num = fast_reg_to_spr(spr_num)
if spr_ok:
res['spr1'] = sim.spr[spr_dict[spr_num].SPR].value
# SPR2
spr_ok = yield dec2.e.read_spr2.ok
spr_num = yield dec2.e.read_spr2.data
+ # HACK
+ spr_num = fast_reg_to_spr(spr_num)
if spr_ok:
res['spr2'] = sim.spr[spr_dict[spr_num].SPR].value
"""
from nmigen import Const
+from soc.regfile.regfiles import XERRegs, FastRegs
def get_regspec_bitwidth(regspec, srcdest, idx):
print ("get_regspec_bitwidth", regspec, srcdest, idx)
# function for the relationship between regspecs and Decode2Execute1Type
-def regspec_rdmask(e, regspec, idx):
- (regfile, name, _) = regspec[idx]
+def regspec_decode(e, regfile, name):
+ """regspec_decode
+
+ this function 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
+ a Regport or not
+ * which Regfile port should be read to get that data
+ * when it comes to writing: likewise, which Regfile port 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".
+ """
+
if regfile == 'INT':
+ # Int register numbering is *unary* encoded
if name == 'ra': # RA
- return e.read_reg1.ok
+ return e.read_reg1.ok, 1<<e.read_reg1.data, None
if name == 'rb': # RB
- return e.read_reg2.ok
+ return e.read_reg2.ok, 1<<e.read_reg2.data, None
if name == 'rc': # RS
- return e.read_reg3.ok
+ return e.read_reg3.ok, 1<<e.read_reg3.data, None
+
if regfile == 'CR':
+ # CRRegs register numbering is *unary* encoded
if name == 'full_cr': # full CR
- return e.read_cr_whole
+ return e.read_cr_whole, 0b11111111, 0b11111111
if name == 'cr_a': # CR A
- return e.read_cr1.ok
+ return e.read_cr1.ok, 1<<e.read_cr1.data, 1<<e.write_cr.data
if name == 'cr_b': # CR B
- return e.read_cr2.ok
+ return e.read_cr2.ok, 1<<e.read_cr2.data, None
if name == 'cr_c': # CR C
- return e.read_cr3.ok
+ return e.read_cr3.ok, 1<<e.read_cr2.data, None
+
if regfile == 'XER':
- if name in ['xer_so', 'xer_ov']:
- return e.oe.oe & e.oe.oe_ok
+ # 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 & e.oe.oe_ok, SO, SO
+ if name == 'xer_ov':
+ return e.oe.oe & e.oe.oe_ok, OV, OV
if name == 'xer_ca':
- return e.input_carry
-
- assert False, "regspec rdmask not found %s %d" % (repr(regspec), idx)
+ return e.input_carry, CA, CA
+
+ 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
+ SRR1 = 1<<FastRegs.SRR1
+ SRR2 = 1<<FastRegs.SRR2
+ if name in ['cia', 'nia']:
+ return Const(1), PC, PC
+ if name == 'msr':
+ return Const(1), MSR, MSR
+ # TODO: remap the SPR numbers to FAST regs
+ if name == 'spr1':
+ return e.read_spr1.ok, 1<<e.read_spr1.data, 1<<e.write_spr.data
+ if name == 'spr2':
+ return e.read_spr2.ok, 1<<e.read_spr2.data, 1<<e.write_spr.data
+
+ assert False, "regspec not found %s %d" % (repr(regspec), idx)