From: Luke Kenneth Casson Leighton Date: Wed, 2 Sep 2020 11:32:38 +0000 (+0100) Subject: series of extensive modifications to fix long-standing bug in CR handling X-Git-Tag: semi_working_ecp5~218 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=58496f2cd13b168ddfae4c788334c5a595f9de71;p=soc.git series of extensive modifications to fix long-standing bug in CR handling cr as a FieldSelectableInt is being removed --- diff --git a/src/soc/decoder/isa/caller.py b/src/soc/decoder/isa/caller.py index dd4ed1e1..028fcd38 100644 --- a/src/soc/decoder/isa/caller.py +++ b/src/soc/decoder/isa/caller.py @@ -314,8 +314,9 @@ class ISACaller: # 3.2.3 p46 p232 VRSAVE (actually SPR #256) # create CR then allow portions of it to be "selectable" (below) - self._cr = SelectableInt(initial_cr, 64) # underlying reg - self.cr = FieldSelectableInt(self._cr, list(range(32, 64))) + #rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2) + self.cr = SelectableInt(initial_cr, 64) # underlying reg + #self.cr = FieldSelectableInt(self._cr, list(range(32, 64))) # "undefined", just set to variable-bit-width int (use exts "max") self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256! @@ -341,7 +342,7 @@ class ISACaller: # field-selectable versions of Condition Register TODO check bitranges? self.crl = [] for i in range(8): - bits = tuple(range(i*4, (i+1)*4)) # errr... maybe? + bits = tuple(range(i*4+32, (i+1)*4+32)) # errr... maybe? _cr = FieldSelectableInt(self.cr, bits) self.crl.append(_cr) self.namespace["CR%d" % i] = _cr @@ -396,7 +397,10 @@ class ISACaller: else: sig = getattr(fields, name) val = yield sig - if name in ['BF', 'BFA']: + # these are all opcode fields involved in index-selection of CR, + # and need to do "standard" arithmetic. CR[BA+32] for example + # would, if using SelectableInt, only be 5-bit. + if name in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT']: self.namespace[name] = val else: self.namespace[name] = SelectableInt(val, sig.width) diff --git a/src/soc/decoder/isa/comparefixed.patch b/src/soc/decoder/isa/comparefixed.patch index b80e7be4..f20f4c0e 100644 --- a/src/soc/decoder/isa/comparefixed.patch +++ b/src/soc/decoder/isa/comparefixed.patch @@ -1,41 +1,5 @@ --- comparefixed.py.orig 2020-05-15 10:02:00.087668937 -0400 +++ comparefixed.py 2020-05-15 12:32:36.834556205 -0400 -@@ -21,7 +21,7 @@ - c = SelectableInt(value=0x2, bits=3) - else: - c = SelectableInt(value=0x1, bits=3) -- CR[4 * BF + 32:4 * BF + 35 + 1] = concat(c, XER[SO]) -+ CR.si[4 * BF + 32:4 * BF + 35 + 1] = concat(c, XER[SO]) - return (CR,) - - @inject() -@@ -38,7 +38,7 @@ - c = SelectableInt(value=0x2, bits=3) - else: - c = SelectableInt(value=0x1, bits=3) -- CR[4 * BF + 32:4 * BF + 35 + 1] = concat(c, XER[SO]) -+ CR.si[4 * BF + 32:4 * BF + 35 + 1] = concat(c, XER[SO]) - return (CR,) - - @inject() -@@ -53,7 +53,7 @@ - c = SelectableInt(value=0x2, bits=3) - else: - c = SelectableInt(value=0x1, bits=3) -- CR[4 * BF + 32:4 * BF + 35 + 1] = concat(c, XER[SO]) -+ CR.si[4 * BF + 32:4 * BF + 35 + 1] = concat(c, XER[SO]) - return (CR,) - - @inject() -@@ -70,7 +70,7 @@ - c = SelectableInt(value=0x2, bits=3) - else: - c = SelectableInt(value=0x1, bits=3) -- CR[4 * BF + 32:4 * BF + 35 + 1] = concat(c, XER[SO]) -+ CR.si[4 * BF + 32:4 * BF + 35 + 1] = concat(c, XER[SO]) - return (CR,) - - @inject() @@ -85,23 +85,22 @@ else: in_range = le(src21lo, src1) & le(src1, src21hi) | le(src22lo, src1) & le( @@ -44,10 +8,10 @@ - CR[4 * BF + 33] = in_range - CR[4 * BF + 34] = SelectableInt(value=0x0, bits=1) - CR[4 * BF + 35] = SelectableInt(value=0x0, bits=1) -+ CR.si[4 * BF + 32] = SelectableInt(value=0x0, bits=1) -+ CR.si[4 * BF + 33] = in_range -+ CR.si[4 * BF + 34] = SelectableInt(value=0x0, bits=1) -+ CR.si[4 * BF + 35] = SelectableInt(value=0x0, bits=1) ++ CR[4 * BF + 32] = SelectableInt(value=0x0, bits=1) ++ CR[4 * BF + 33] = in_range ++ CR[4 * BF + 34] = SelectableInt(value=0x0, bits=1) ++ CR[4 * BF + 35] = SelectableInt(value=0x0, bits=1) return (CR,) @inject() @@ -63,10 +27,10 @@ - CR[4 * BF + 33] = match - CR[4 * BF + 34] = SelectableInt(value=0x0, bits=1) - CR[4 * BF + 35] = SelectableInt(value=0x0, bits=1) -+ CR.si[4 * BF + 32] = SelectableInt(value=0x0, bits=1) -+ CR.si[4 * BF + 33] = match -+ CR.si[4 * BF + 34] = SelectableInt(value=0x0, bits=1) -+ CR.si[4 * BF + 35] = SelectableInt(value=0x0, bits=1) ++ CR[4 * BF + 32] = SelectableInt(value=0x0, bits=1) ++ CR[4 * BF + 33] = match ++ CR[4 * BF + 34] = SelectableInt(value=0x0, bits=1) ++ CR[4 * BF + 35] = SelectableInt(value=0x0, bits=1) return (CR,) comparefixed_instrs = {} diff --git a/src/soc/decoder/isa/condition.patch b/src/soc/decoder/isa/condition.patch deleted file mode 100644 index a5e38d89..00000000 --- a/src/soc/decoder/isa/condition.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- condition.py.orig 2020-05-16 09:37:19.676855312 -0400 -+++ condition.py 2020-05-16 09:37:24.643575782 -0400 -@@ -51,7 +51,7 @@ - - @inject() - def op_mcrf(self, CR): -- CR[4 * BF + 32:4 * BF + 35 + 1] = CR[4 * BFA + 32:4 * BFA + 35 + 1] -+ CR.si[4 * BF + 32:4 * BF + 35 + 1] = CR.si[4 * BFA + 32:4 * BFA + 35 + 1] - return (CR,) - - condition_instrs = {} diff --git a/src/soc/decoder/isa/sprset.patch b/src/soc/decoder/isa/sprset.patch deleted file mode 100644 index 2a115ae2..00000000 --- a/src/soc/decoder/isa/sprset.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- sprset.py.orig 2020-05-20 09:27:57.035248195 -0400 -+++ sprset.py 2020-05-28 11:02:47.754983231 -0400 -@@ -54,7 +54,7 @@ - n = i - count = count + 1 - if eq(count, 1): -- CR[4 * n + 32:4 * n + 35 + 1] = RS[4 * n + 32:4 * n + 35 + 1] -+ CR.si[4 * n + 32:4 * n + 35 + 1] = RS[4 * n + 32:4 * n + 35 + 1] - else: - CR = undefined - return (CR,) -@@ -78,7 +78,7 @@ - count = count + 1 - if eq(count, 1): - RT = concat(0, repeat=64) -- RT[4 * n + 32:4 * n + 35 + 1] = CR[4 * n + 32:4 * n + 35 + 1] -+ RT[4 * n + 32:4 * n + 35 + 1] = CR.si[4 * n + 32:4 * n + 35 + 1] - return (RT, CR,) - - @inject() -@@ -88,9 +88,9 @@ - - @inject() - def op_setb(self, CR): -- if eq(CR[4 * BFA + 32], 1): -+ if eq(CR.si[4 * BFA + 32], 1): - RT = SelectableInt(value=0xffffffffffffffff, bits=64) -- elif eq(CR[4 * BFA + 33], 1): -+ elif eq(CR.si[4 * BFA + 33], 1): - RT = SelectableInt(value=0x1, bits=64) - else: - RT = SelectableInt(value=0x0, bits=64) diff --git a/src/soc/decoder/power_decoder2.py b/src/soc/decoder/power_decoder2.py index 4405cf2c..8ef8959a 100644 --- a/src/soc/decoder/power_decoder2.py +++ b/src/soc/decoder/power_decoder2.py @@ -509,7 +509,7 @@ class DecodeCRIn(Elaboratable): with m.Case(CRInSel.NONE): pass # No bitfield activated with m.Case(CRInSel.CR0): - comb += self.cr_bitfield.data.eq(0) + comb += self.cr_bitfield.data.eq(0) # CR0 (MSB0 numbering) comb += self.cr_bitfield.ok.eq(1) with m.Case(CRInSel.BI): comb += self.cr_bitfield.data.eq(self.dec.BI[2:5]) @@ -570,7 +570,7 @@ class DecodeCROut(Elaboratable): with m.Case(CROutSel.NONE): pass # No bitfield activated with m.Case(CROutSel.CR0): - comb += self.cr_bitfield.data.eq(0) + comb += self.cr_bitfield.data.eq(0) # CR0 (MSB0 numbering) comb += self.cr_bitfield.ok.eq(self.rc_in) # only when RC=1 with m.Case(CROutSel.BF): comb += self.cr_bitfield.data.eq(self.dec.FormX.BF) diff --git a/src/soc/decoder/pseudo/parser.py b/src/soc/decoder/pseudo/parser.py index 04bd736f..34c8aae8 100644 --- a/src/soc/decoder/pseudo/parser.py +++ b/src/soc/decoder/pseudo/parser.py @@ -25,7 +25,7 @@ import ast def Assign(autoassign, assignname, left, right, iea_mode): names = [] - print("Assign", left, right) + print("Assign", assignname, left, right) if isinstance(left, ast.Name): # Single assignment on left # XXX when doing IntClass, which will have an "eq" function, @@ -205,6 +205,9 @@ def apply_trailer(atom, trailer): idx = subs[0] else: idx = ast.Slice(subs[0], subs[1], None) + #if isinstance(atom, ast.Name) and atom.id == 'CR': + #atom.id = 'CR' # bad hack + #print ("apply_trailer Subscript", atom.id, idx) return ast.Subscript(atom, idx, ast.Load()) ########## Parser (tokens -> AST) ###### diff --git a/src/soc/fu/compunits/test/test_cr_compunit.py b/src/soc/fu/compunits/test/test_cr_compunit.py index ee9c5512..4e59fe3e 100644 --- a/src/soc/fu/compunits/test/test_cr_compunit.py +++ b/src/soc/fu/compunits/test/test_cr_compunit.py @@ -36,7 +36,7 @@ class CRTestRunner(TestRunner): cr_en = yield dec2.e.write_cr.ok if whole_reg_ok: full_cr = res['full_cr'] - expected_cr = sim.cr.get_range().value + expected_cr = sim.cr.value print("CR whole: expected %x, actual: %x mask: %x" % \ (expected_cr, full_cr, full_cr_mask)) self.assertEqual(expected_cr & full_cr_mask, diff --git a/src/soc/fu/cr/main_stage.py b/src/soc/fu/cr/main_stage.py index eced9c34..43296aef 100644 --- a/src/soc/fu/cr/main_stage.py +++ b/src/soc/fu/cr/main_stage.py @@ -75,9 +75,9 @@ class CRMainStage(PipeModBase): # instruction. This operation takes in the little CR # bitfields, so these fields need to get truncated to # the least significant 2 bits - BT = xl_fields.BT[0:-1] - BA = xl_fields.BA[0:-1] - BB = xl_fields.BB[0:-1] + BT = xl_fields.BT + BA = xl_fields.BA + BB = xl_fields.BB bt = Signal(2, reset_less=True) ba = Signal(2, reset_less=True) bb = Signal(2, reset_less=True) @@ -128,7 +128,8 @@ class CRMainStage(PipeModBase): # just like in branch, CR0-7 is incoming into cr_a, we # need to select from the last 2 bits of BC a_fields = self.fields.FormA - BC = a_fields.BC[0:2] + BC = Signal(2, reset_less=True) + comb += BC.eq(a_fields.BC[0:2]) cr_bits = Array([cr_a[3-i] for i in range(4)]) # The bit of (cr_a=CR0-7) selected by BC diff --git a/src/soc/fu/cr/test/test_pipe_caller.py b/src/soc/fu/cr/test/test_pipe_caller.py index fe794f89..8e71a3a8 100644 --- a/src/soc/fu/cr/test/test_pipe_caller.py +++ b/src/soc/fu/cr/test/test_pipe_caller.py @@ -97,6 +97,16 @@ class CRTestCase(TestAccumulatorBase): cr = random.randint(0, (1 << 32)-1) self.add_case(Program(lst, bigendian), initial_cr=cr) + def case_cror_regression(self): + """another bad hack! + """ + dis = ["cror 28, 5, 11"] + lst = bytes([0x83, 0x5b, 0x75, 0x4f]) # 4f855b83 + cr = 0x35055058 + p = Program(lst, bigendian) + p.assembly = '\n'.join(dis)+'\n' + self.add_case(p, initial_cr=cr) + def case_mfocrf_regression(self): """bit of a bad hack. comes from microwatt 1.bin instruction 0x106d0 as the mask is non-standard, gnu-as barfs. so we fake it up directly @@ -136,16 +146,57 @@ class CRTestCase(TestAccumulatorBase): cr = random.randint(0, (1 << 32)-1) self.add_case(Program(lst, bigendian), initial_cr=cr) + def case_isel_0(self): + lst = [ "isel 4, 1, 2, 31" + ] + initial_regs = [0] * 32 + initial_regs[1] = 0x1004 + initial_regs[2] = 0x1008 + cr= 0x1ee + self.add_case(Program(lst, bigendian), + initial_regs=initial_regs, initial_cr=cr) + + def case_isel_1(self): + lst = [ "isel 4, 1, 2, 30" + ] + initial_regs = [0] * 32 + initial_regs[1] = 0x1004 + initial_regs[2] = 0x1008 + cr= 0x1ee + self.add_case(Program(lst, bigendian), + initial_regs=initial_regs, initial_cr=cr) + + def case_isel_2(self): + lst = [ "isel 4, 1, 2, 2" + ] + initial_regs = [0] * 32 + initial_regs[1] = 0x1004 + initial_regs[2] = 0x1008 + cr= 0x1ee + self.add_case(Program(lst, bigendian), + initial_regs=initial_regs, initial_cr=cr) + + def case_isel_3(self): + lst = [ "isel 1, 2, 3, 13" + ] + initial_regs = [0] * 32 + initial_regs[2] = 0x1004 + initial_regs[3] = 0x1008 + cr= 0x5d677571b8229f1 + cr= 0x1b8229f1 + self.add_case(Program(lst, bigendian), + initial_regs=initial_regs, initial_cr=cr) + def case_isel(self): for i in range(20): bc = random.randint(0, 31) lst = [f"isel 1, 2, 3, {bc}"] cr = random.randint(0, (1 << 64)-1) initial_regs = [0] * 32 - initial_regs[2] = random.randint(0, (1 << 64)-1) - initial_regs[3] = random.randint(0, (1 << 64)-1) - #initial_regs[2] = i*2 - #initial_regs[3] = i*2+1 + #initial_regs[2] = random.randint(0, (1 << 64)-1) + #initial_regs[3] = random.randint(0, (1 << 64)-1) + initial_regs[2] = i*2+1 + initial_regs[3] = i*2+2 self.add_case(Program(lst, bigendian), initial_regs=initial_regs, initial_cr=cr) @@ -178,37 +229,16 @@ def get_cu_inputs(dec2, sim): full_cr_mask = mask_extend(full_reg, 8, 4) # full CR - print(sim.cr.get_range().value) + print(sim.cr.value) if full_reg_ok: - res['full_cr'] = sim.cr.get_range().value & full_cr_mask + res['full_cr'] = sim.cr.value & full_cr_mask else: - # CR A - cr1_en = yield dec2.e.read_cr1.ok - if cr1_en: - cr1_sel = yield dec2.e.read_cr1.data - res['cr_a'] = sim.crl[cr1_sel].get_range().value - cr2_en = yield dec2.e.read_cr2.ok - # CR B - if cr2_en: - cr2_sel = yield dec2.e.read_cr2.data - res['cr_b'] = sim.crl[cr2_sel].get_range().value - cr3_en = yield dec2.e.read_cr3.ok - # CR C - if cr3_en: - cr3_sel = yield dec2.e.read_cr3.data - res['cr_c'] = sim.crl[cr3_sel].get_range().value - - # RA/RC - reg1_ok = yield dec2.e.read_reg1.ok - if reg1_ok: - data1 = yield dec2.e.read_reg1.data - res['ra'] = sim.gpr(data1).value - - # RB (or immediate) - reg2_ok = yield dec2.e.read_reg2.ok - if reg2_ok: - data2 = yield dec2.e.read_reg2.data - res['rb'] = sim.gpr(data2).value + yield from ALUHelpers.get_sim_cr_a(res, sim, dec2) # CR A + yield from ALUHelpers.get_sim_cr_b(res, sim, dec2) # CR B + yield from ALUHelpers.get_sim_cr_c(res, sim, dec2) # CR C + + yield from ALUHelpers.get_sim_int_ra(res, sim, dec2) # RA + yield from ALUHelpers.get_sim_int_rb(res, sim, dec2) # RB print("get inputs", res) return res @@ -236,14 +266,14 @@ class TestRunner(unittest.TestCase): cr_en = yield dec2.e.write_cr.ok if whole_reg_ok: full_cr = yield alu.n.data_o.full_cr.data & full_cr_mask - expected_cr = simulator.cr.get_range().value + expected_cr = simulator.cr.value print("CR whole: expected %x, actual: %x mask: %x" % \ (expected_cr, full_cr, full_cr_mask)) # HACK: only look at the bits that we expected to change self.assertEqual(expected_cr & full_cr_mask, full_cr, code) elif cr_en: cr_sel = yield dec2.e.write_cr.data - expected_cr = simulator.cr.get_range().value + expected_cr = simulator.cr.value print(f"CR whole: {expected_cr:x}, sel {cr_sel}") expected_cr = simulator.crl[cr_sel].get_range().value real_cr = yield alu.n.data_o.cr.data diff --git a/src/soc/fu/test/common.py b/src/soc/fu/test/common.py index 1631747c..0dd1d4f7 100644 --- a/src/soc/fu/test/common.py +++ b/src/soc/fu/test/common.py @@ -181,6 +181,18 @@ class ALUHelpers: cridx = yield dec2.e.read_cr1.data res['cr_a'] = sim.crl[cridx].get_range().value + def get_sim_cr_b(res, sim, dec2): + cridx_ok = yield dec2.e.read_cr2.ok + if cridx_ok: + cridx = yield dec2.e.read_cr2.data + res['cr_b'] = sim.crl[cridx].get_range().value + + def get_sim_cr_c(res, sim, dec2): + cridx_ok = yield dec2.e.read_cr3.ok + if cridx_ok: + cridx = yield dec2.e.read_cr3.data + res['cr_c'] = sim.crl[cridx].get_range().value + def get_sim_int_ra(res, sim, dec2): # TODO: immediate RA zero reg1_ok = yield dec2.e.read_reg1.ok diff --git a/src/soc/simulator/test_sim.py b/src/soc/simulator/test_sim.py index 522559b9..2fcd3e6c 100644 --- a/src/soc/simulator/test_sim.py +++ b/src/soc/simulator/test_sim.py @@ -49,6 +49,7 @@ class GeneralTestCases(FHDLTestCase): super().__init__(name) self.test_name = name + @unittest.skip("disable") def test_0_litex_bios_ctr_loop(self): """ 32a4: ff ff 63 38 addi r3,r3,-1 @@ -244,7 +245,40 @@ class GeneralTestCases(FHDLTestCase): with Program(lst, bigendian) as program: self.run_tst_program(program, [1]) + #@unittest.skip("disable") def test_crxor(self): + lst = ["addi 1, 0, 0x1004", + "addi 2, 0, 0x1008", + "addi 3, 0, 0x01ee", + "mtcrf 0b1111111, 3", + "crxor 3, 30, 4", + "mfcr 3", + ] + initial_regs = [0] * 32 + initial_regs[1] = 0x1004 + initial_regs[2] = 0x1008 + initial_regs[3] = 0x01ee + with Program(lst, bigendian) as program: + self.run_tst_program(program, [3, 4]) + + #@unittest.skip("disable") + def test_crxor_2(self): + lst = ["addi 1, 0, 0x1004", + "addi 2, 0, 0x1008", + "addi 3, 0, 0x01ee", + "mtcrf 0b1111111, 3", + "crxor 29, 30, 29", + "mfcr 3", + ] + initial_regs = [0] * 32 + initial_regs[1] = 0x1004 + initial_regs[2] = 0x1008 + initial_regs[3] = 0x01ee + with Program(lst, bigendian) as program: + self.run_tst_program(program, [3, 4]) + + #@unittest.skip("disable") + def test_crnand(self): lst = ["addi 1, 0, 0x1004", "addi 2, 0, 0x1008", "addi 3, 0, 0x01ee", @@ -259,6 +293,22 @@ class GeneralTestCases(FHDLTestCase): with Program(lst, bigendian) as program: self.run_tst_program(program, [3, 4]) + #@unittest.skip("disable") + def test_crnand_2(self): + lst = ["addi 1, 0, 0x1004", + "addi 2, 0, 0x1008", + "addi 3, 0, 0x01ee", + "mtcrf 0b1111111, 3", + "crnand 28, 30, 29", + "mfcr 3", + ] + initial_regs = [0] * 32 + initial_regs[1] = 0x1004 + initial_regs[2] = 0x1008 + initial_regs[3] = 0x01ee + with Program(lst, bigendian) as program: + self.run_tst_program(program, [3, 4]) + @unittest.skip("disable") def test_isel_1(self): lst = ["addi 1, 0, 0x1004", @@ -274,7 +324,7 @@ class GeneralTestCases(FHDLTestCase): with Program(lst, bigendian) as program: self.run_tst_program(program, [3, 4]) - @unittest.skip("disable") + #@unittest.skip("disable") def test_isel_2(self): lst = ["addi 1, 0, 0x1004", "addi 2, 0, 0x1008", @@ -289,6 +339,21 @@ class GeneralTestCases(FHDLTestCase): with Program(lst, bigendian) as program: self.run_tst_program(program, [3, 4]) + @unittest.skip("disable") + def test_isel_3(self): + lst = ["addi 1, 0, 0x1004", + "addi 2, 0, 0x1008", + "addi 3, 0, 0x01ee", + "mtcrf 0b1111111, 3", + "isel 4, 1, 2, 31" + ] + initial_regs = [0] * 32 + initial_regs[1] = 0x1004 + initial_regs[2] = 0x1008 + initial_regs[3] = 0x00ee + with Program(lst, bigendian) as program: + self.run_tst_program(program, [3, 4]) + @unittest.skip("disable") def test_2_load_store(self): lst = ["addi 1, 0, 0x1004", @@ -363,7 +428,7 @@ class GeneralTestCases(FHDLTestCase): lst = ["addi 9, 0, 0x10", # i = 16 "addi 9,9,-1", # i = i - 1 "cmpi 0,1,9,12", # compare 9 to value 0, store in CR2 - "bc 4,0,-8" # branch if CR2 "test was != 0" + "bc 2,0,-8" # branch if CR2 "test was != 0" ] with Program(lst, bigendian) as program: self.run_tst_program(program, [9], initial_mem={}) @@ -477,7 +542,7 @@ class DecoderBase: def qemu_register_compare(self, sim, qemu, regs): qpc, qxer, qcr = qemu.get_pc(), qemu.get_xer(), qemu.get_cr() - sim_cr = sim.cr.get_range().value + sim_cr = sim.cr.value sim_pc = sim.pc.CIA.value sim_xer = sim.spr['XER'].value print("qemu pc", hex(qpc))