From 44f0558a67967b891c7bf149ca01e7b266472559 Mon Sep 17 00:00:00 2001 From: Lenny Truong Date: Wed, 30 Oct 2024 12:39:00 -0700 Subject: [PATCH] Update advanced code --- fault-micro/advanced_pe.py | 104 +++++++++++++++++++++++++++++++++++++ fault-micro/pe.py | 45 ---------------- 2 files changed, 104 insertions(+), 45 deletions(-) create mode 100644 fault-micro/advanced_pe.py delete mode 100644 fault-micro/pe.py diff --git a/fault-micro/advanced_pe.py b/fault-micro/advanced_pe.py new file mode 100644 index 00000000..0c93d2b8 --- /dev/null +++ b/fault-micro/advanced_pe.py @@ -0,0 +1,104 @@ +import magma as m +import fault as f +import hwtypes as ht + +import operator + + +class AdvancedPE(m.Generator2): + def __init__(self, addr, instr_op_map): + n_cfg_bits = max(x.bit_length() for x in instr_op_map.keys()) + self.io = io = m.IO( + a=m.In(m.UInt[16]), + b=m.In(m.UInt[16]), + c=m.Out(m.UInt[16]), + config_addr=m.In(m.Bits[8]), + config_data=m.In(m.Bits[n_cfg_bits]), + config_en=m.In(m.Enable) + ) + m.ClockIO(has_reset=True) + + opcode = m.Register( + m.Bits[n_cfg_bits], has_enable=True, reset_type=m.Reset + )()(io.config_data, CE=io.config_en & (io.config_addr == addr)) + curr = None + for instr, op in instr_op_map.items(): + next = op(self.io.a, self.io.b) + if curr is not None: + next = m.mux([curr, next], opcode == instr) + curr = next + self.io.c @= curr + + +class ResetTester: + def __init__(self, circuit): + for port in circuit.interface.ports.values(): + if isinstance(port, m.Reset): + self.reset_port = port + break + + def reset(self): + self.poke(self.reset_port, 1) + self.step(2) + self.poke(self.reset_port, 0) + self.step(2) + + +class ConfigurationTester: + def __init__(self, circuit, config_addr_port, config_data_port, + config_en_port): + self.config_addr_port = config_addr_port + self.config_data_port = config_data_port + self.config_en_port = config_en_port + + def configure(self, addr, data): + self.poke(self.clock, 0) + self.poke(self.config_addr_port, addr) + self.poke(self.config_data_port, data) + self.poke(self.config_en_port, 1) + self.step(2) + self.poke(self.config_en_port, 0) + + +class ResetAndConfigurationTester( + f.SynchronousTester, ResetTester, ConfigurationTester +): + def __init__(self, circuit, clock, config_addr_port, config_data_port, + config_en_port): + # Note the explicit calls to `__init__` to manage the multiple + # inheritance, rather than the standard use of `super` + f.SynchronousTester.__init__(self, circuit, clock) + ResetTester.__init__(self, circuit) + ConfigurationTester.__init__(self, circuit, config_addr_port, + config_data_port, config_en_port) + + +addr = 0xDE +ops = m.common.ParamDict({ + 0xDE: operator.add, + 0xAD: operator.sub, + 0xBE: operator.mul, + 0xEF: operator.xor +}) +PE = AdvancedPE(addr, ops) +tester = ResetAndConfigurationTester( + PE, PE.CLK, PE.config_addr, PE.config_data, PE.config_en +) +tester.circuit.config_en = 1 +tester.circuit.config_addr = addr +tester.circuit.RESET = 0 +for inst, op in ops.items(): + tester.circuit.config_data = inst + tester.circuit.a = a = ht.BitVector.random(16) + tester.circuit.b = b = ht.BitVector.random(16) + tester.step(2) + tester.circuit.c.expect(op(a, b)) + +tester.circuit.config_en = 0 +tester.reset() +tester.circuit.a = a = ht.BitVector.random(16) +tester.circuit.b = b = ht.BitVector.random(16) +tester.step(2) +tester.circuit.c.expect(ops[0xDE](a, b)) + +tester.compile_and_run("verilator", flags=["-Wno-fatal"], + directory="build") diff --git a/fault-micro/pe.py b/fault-micro/pe.py deleted file mode 100644 index adaddf9c..00000000 --- a/fault-micro/pe.py +++ /dev/null @@ -1,45 +0,0 @@ -import magma as m -import fault as f -import hwtypes as ht - -import operator - - -class PE(m.Generator2): - def __init__(self, instr_op_map: dict): - n_cfg_bits = max(x.bit_length() for x in instr_op_map.keys()) - self.io = m.IO( - a=m.In(m.UInt[16]), b=m.In(m.UInt[16]), c=m.Out(m.UInt[16]), - config_data=m.In(m.Bits[n_cfg_bits]), config_en=m.In(m.Enable) - ) + m.ClockIO() - - opcode = m.Register(m.Bits[n_cfg_bits], has_enable=True)()( - self.io.config_data, CE=self.io.config_en - ) - curr = None - for instr, op in instr_op_map.items(): - next = op(self.io.a, self.io.b) - if curr is not None: - next = m.mux([curr, next], opcode == instr) - curr = next - self.io.c @= curr - - -ops = m.common.ParamDict({ - 0xDE: operator.add, - 0xAD: operator.sub, - 0xBE: operator.mul, - 0xEF: operator.xor -}) -tester = f.SynchronousTester(PE(ops)) -tester.circuit.config_en = 1 -for inst, op in ops.items(): - tester.circuit.config_data = inst - tester.circuit.a = a = ht.BitVector.random(16) - tester.circuit.b = b = ht.BitVector.random(16) - tester.step(2) - tester.circuit.c.expect(op(a, b)) - -tester.compile_and_run("verilator", flags=["-Wno-fatal"], - directory="build") -