From 56e0f7224c5e85c5b4d6956440b8d2e0dfc4c0f2 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Tue, 2 Jun 2020 17:32:12 +0100 Subject: [PATCH] add read-write register numbering detection --- src/soc/decoder/power_decoder2.py | 8 +- .../fu/compunits/test/test_branch_compunit.py | 15 +++- src/soc/fu/regspec.py | 88 ++++++++++++++++--- 3 files changed, 93 insertions(+), 18 deletions(-) diff --git a/src/soc/decoder/power_decoder2.py b/src/soc/decoder/power_decoder2.py index b1352048..09cad542 100644 --- a/src/soc/decoder/power_decoder2.py +++ b/src/soc/decoder/power_decoder2.py @@ -15,6 +15,7 @@ from soc.decoder.power_enums import (InternalOp, CryIn, Function, LdstLen, In1Sel, In2Sel, In3Sel, OutSel, SPR, RC) +from soc.regfile.regfiles import FastRegs class DecodeA(Elaboratable): """DecodeA from instruction @@ -60,11 +61,12 @@ class DecodeA(Elaboratable): 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) @@ -154,9 +156,9 @@ class DecodeB(Elaboratable): # 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 diff --git a/src/soc/fu/compunits/test/test_branch_compunit.py b/src/soc/fu/compunits/test/test_branch_compunit.py index d0d00f7f..c8d02b67 100644 --- a/src/soc/fu/compunits/test/test_branch_compunit.py +++ b/src/soc/fu/compunits/test/test_branch_compunit.py @@ -1,5 +1,5 @@ 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 @@ -8,11 +8,20 @@ from soc.fu.branch.test.test_pipe_caller import test_data 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): @@ -36,12 +45,16 @@ class BranchTestRunner(TestRunner): # 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 diff --git a/src/soc/fu/regspec.py b/src/soc/fu/regspec.py index 0aa2842c..632c19fc 100644 --- a/src/soc/fu/regspec.py +++ b/src/soc/fu/regspec.py @@ -17,6 +17,7 @@ which MultiCompUnit port, how wide the connection is, and so on. """ 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) @@ -90,28 +91,87 @@ class RegSpecALUAPI: # 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<