From 8af7da55f03031c4ebc902c5aac421f9ab23febd Mon Sep 17 00:00:00 2001 From: Michael Nolan Date: Mon, 2 Mar 2020 10:24:16 -0500 Subject: [PATCH] Add support for hierarchical decoding --- src/decoder/power_decoder.py | 98 +++++++++++++++++++------- src/decoder/test/test_power_decoder.py | 23 +++--- 2 files changed, 86 insertions(+), 35 deletions(-) diff --git a/src/decoder/power_decoder.py b/src/decoder/power_decoder.py index d95facb6..f0d44876 100644 --- a/src/decoder/power_decoder.py +++ b/src/decoder/power_decoder.py @@ -43,6 +43,21 @@ class PowerOp: res.append(sig.eq(int(row.get(bit, 0)))) return res + def eq(self, otherop): + res = [self.function_unit.eq(otherop.function_unit), + self.internal_op.eq(otherop.internal_op), + self.in1_sel.eq(otherop.in1_sel), + self.in2_sel.eq(otherop.in2_sel), + self.in3_sel.eq(otherop.in3_sel), + self.out_sel.eq(otherop.out_sel), + self.rc_sel.eq(otherop.rc_sel), + self.ldst_len.eq(otherop.ldst_len), + self.cry_in.eq(otherop.cry_in)] + for bit in single_bit_flags: + sig = getattr(self, get_signal_name(bit)) + res.append(sig.eq(getattr(otherop, get_signal_name(bit)))) + return res + def ports(self): regular = [self.function_unit, self.in1_sel, @@ -61,41 +76,76 @@ class PowerDecoder(Elaboratable): """PowerDecoder - decodes an incoming opcode into the type of operation """ - def __init__(self, width, csvname, opint=True): - self.opint = opint # true if the opcode needs to be converted to int - self.opcodes = get_csv(csvname) + def __init__(self, width, opcodes, opint=True, suffix=None): + self.opint = opint # true if the opcode needs to be converted to int + self.opcodes = opcodes self.opcode_in = Signal(width, reset_less=True) self.op = PowerOp() + self.suffix = suffix + self.width = width + + def suffix_mask(self): + return ((1 << self.suffix[1]) - 1) - ((1 << self.suffix[0]) - 1) + + def divide_opcodes(self): + divided = {} + mask = self.suffix_mask() + for row in self.opcodes: + opcode = row['opcode'] + if self.opint: + opcode = int(opcode, 0) + key = opcode & mask >> (self.suffix[0]) + opcode = opcode >> self.suffix[1] + if key not in divided: + divided[key] = [] + r = row.copy() + r['opcode'] = opcode + divided[key].append(r) + return divided def elaborate(self, platform): m = Module() comb = m.d.comb - with m.Switch(self.opcode_in): - for row in self.opcodes: - opcode = row['opcode'] - if self.opint: - opcode = int(opcode, 0) - if not row['unit']: - continue - print ("opcode", opcode) - with m.Case(opcode): - comb += self.op._eq(row) - with m.Default(): - comb += self.op._eq(None) + if self.suffix: + opcodes = self.divide_opcodes() + opc_in = Signal(self.suffix[1] - self.suffix[0], reset_less=True) + comb += opc_in.eq(self.opcode_in[self.suffix[0]:self.suffix[1]]) + with m.Switch(opc_in): + for key, row in opcodes.items(): + subdecoder = PowerDecoder(width=self.width - opc_in.width, + opcodes=row, + opint=False) + setattr(m.submodules, "dec%d" % key, subdecoder) + comb += subdecoder.opcode_in.eq(self.opcode_in[self.suffix[1]:]) + with m.Case(key): + comb += self.op.eq(subdecoder.op) + + else: + with m.Switch(self.opcode_in): + for row in self.opcodes: + opcode = row['opcode'] + if self.opint: + opcode = int(opcode, 0) + if not row['unit']: + continue + with m.Case(opcode): + comb += self.op._eq(row) + with m.Default(): + comb += self.op._eq(None) return m def ports(self): return [self.opcode_in] + self.op.ports() # how about this? -if False: - pminor = (0, 6, [(19, "minor_19", (1,11)), # pass to 'splitter' function - (30, "minor_30", (1,4)), - (31, "minor_31", (1,11)), # pass to 'splitter' function - (58, "minor_58", (0,1)), - (62, "minor_62", (0,1)), - ] - - pdecode = PowerDecoder(6, "major", subcoders = pminor) +# if False: +# pminor = (0, 6, [(19, "minor_19", (1,11)), # pass to 'splitter' function +# (30, "minor_30", (1,4)), +# (31, "minor_31", (1,11)), # pass to 'splitter' function +# (58, "minor_58", (0,1)), +# (62, "minor_62", (0,1)), +# ] + +# pdecode = PowerDecoder(6, "major", subcoders = pminor) diff --git a/src/decoder/test/test_power_decoder.py b/src/decoder/test/test_power_decoder.py index 9955b666..b1851c91 100644 --- a/src/decoder/test/test_power_decoder.py +++ b/src/decoder/test/test_power_decoder.py @@ -9,11 +9,11 @@ sys.path.append("../") from power_decoder import (PowerDecoder) from power_enums import (Function, InternalOp, In1Sel, In2Sel, In3Sel, OutSel, RC, LdstLen, CryIn, single_bit_flags, - get_signal_name) + get_signal_name, get_csv) class DecoderTestCase(FHDLTestCase): - def run_test(self, width, csvname, opint=True): + def run_test(self, width, csvname, suffix=None, opint=True): m = Module() comb = m.d.comb opcode = Signal(width) @@ -27,7 +27,8 @@ class DecoderTestCase(FHDLTestCase): ldst_len = Signal(LdstLen) cry_in = Signal(CryIn) - m.submodules.dut = dut = PowerDecoder(width, csvname, opint) + opcodes = get_csv(csvname) + m.submodules.dut = dut = PowerDecoder(width, opcodes, opint, suffix=suffix) comb += [dut.opcode_in.eq(opcode), function_unit.eq(dut.op.function_unit), in1_sel.eq(dut.op.in1_sel), @@ -77,9 +78,9 @@ class DecoderTestCase(FHDLTestCase): in1_sel, in2_sel]): sim.run() - def generate_ilang(self, width, csvname, opint=True): + def generate_ilang(self, width, csvname, opint=True, suffix=None): prefix = os.path.splitext(csvname)[0] - dut = PowerDecoder(width, csvname, opint) + dut = PowerDecoder(width, get_csv(csvname), opint, suffix=suffix) vl = rtlil.convert(dut, ports=dut.ports()) with open("%s_decoder.il" % prefix, "w") as f: f.write(vl) @@ -88,19 +89,19 @@ class DecoderTestCase(FHDLTestCase): self.run_test(6, "major.csv") self.generate_ilang(6, "major.csv") - def test_minor_19(self): - self.run_test(3, "minor_19.csv") - self.generate_ilang(3, "minor_19.csv") + # def test_minor_19(self): + # self.run_test(3, "minor_19.csv") + # self.generate_ilang(3, "minor_19.csv") def test_minor_30(self): self.run_test(4, "minor_30.csv") self.generate_ilang(4, "minor_30.csv") def test_minor_31(self): - self.run_test(10, "minor_31.csv") - self.generate_ilang(10, "minor_31.csv") + self.run_test(10, "minor_31.csv", suffix=(0, 5)) + self.generate_ilang(10, "minor_31.csv", suffix=(0, 5)) - def test_minor_31(self): + def test_extra(self): self.run_test(32, "extra.csv", False) self.generate_ilang(32, "extra.csv", False) -- 2.30.2