Skip to content

Commit

Permalink
Update advanced code
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardt committed Oct 30, 2024
1 parent ea31075 commit 44f0558
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 45 deletions.
104 changes: 104 additions & 0 deletions fault-micro/advanced_pe.py
Original file line number Diff line number Diff line change
@@ -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")
45 changes: 0 additions & 45 deletions fault-micro/pe.py

This file was deleted.

0 comments on commit 44f0558

Please sign in to comment.