fault.magma_simulator_target module

Source code
from hwtypes import BitVector
import magma as m
from magma.simulator.python_simulator import PythonSimulator
from magma.simulator.coreir_simulator import CoreIRSimulator
import fault.actions
from fault.target import Target


class MagmaSimulatorTarget(Target):
    def __init__(self, circuit, clock=None, backend="coreir"):
        super().__init__(circuit)
        self.clock = clock
        self.backend_cls = MagmaSimulatorTarget.simulator_cls(backend)

    def simulator_cls(backend):
        if backend == "coreir":
            return CoreIRSimulator
        if backend == "python":
            return PythonSimulator
        raise NotImplementedError(backend)

    @staticmethod
    def check(got, port, expected):
        if isinstance(port, m.ArrayType) and \
                isinstance(port.T, m._BitType) and \
                not isinstance(port, m.BitsType) and \
                isinstance(expected, BitVector):
            # If port is an Array(N, Bit) and **not** a Bits(N), then the
            # Python simulator will return a list of bools. So, if the user
            # provided a BitVector, we unpack it here so the equality check
            # works
            expected = expected.as_bool_list()
        if isinstance(port, m.ArrayType):
            for i in range(port.N):
                MagmaSimulatorTarget.check(got[i], port[i], expected[i])
            return
        assert got == expected, f"Got {got}, expected {expected}"

    def run(self, actions):
        simulator = self.backend_cls(self.circuit, self.clock)
        for action in actions:
            if isinstance(action, fault.actions.Poke):
                value = action.value
                # Python simulator does not support setting Bit with
                # BitVector(1), so do conversion here
                if isinstance(action.port, m.BitType) and \
                        isinstance(value, BitVector):
                    value = value.as_uint()
                simulator.set_value(action.port, value)
            elif isinstance(action, fault.actions.Print):
                got = simulator.get_value(action.port)
                if isinstance(action.port, m.ArrayType) and \
                        isinstance(action.port.T, (m._BitType, m._BitKind)):
                    got = BitVector(got).as_uint()
                elif isinstance(action.port, m.ArrayType):
                    raise NotImplementedError("Printing complex nested arrays")
                print(f'{action.port.debug_name} = {action.format_str}' %
                      got)
            elif isinstance(action, fault.actions.Expect):
                got = simulator.get_value(action.port)
                expected = action.value
                if isinstance(expected, fault.actions.Peek):
                    expected = simulator.get_value(expected.port)
                MagmaSimulatorTarget.check(got, action.port, expected)
            elif isinstance(action, fault.actions.Eval):
                simulator.evaluate()
            elif isinstance(action, fault.actions.Step):
                if self.clock is not action.clock:
                    raise RuntimeError(f"Using different clocks: {self.clock}, "
                                       f"{action.clock}")
                simulator.advance_cycle(action.steps)
            else:
                raise NotImplementedError(action)}

Classes

class MagmaSimulatorTarget (ancestors: Target, abc.ABC)

Inherited from: Target

Helper class that provides a standard way to create an ABC using inheritance.

Source code
class MagmaSimulatorTarget(Target):
    def __init__(self, circuit, clock=None, backend="coreir"):
        super().__init__(circuit)
        self.clock = clock
        self.backend_cls = MagmaSimulatorTarget.simulator_cls(backend)

    def simulator_cls(backend):
        if backend == "coreir":
            return CoreIRSimulator
        if backend == "python":
            return PythonSimulator
        raise NotImplementedError(backend)

    @staticmethod
    def check(got, port, expected):
        if isinstance(port, m.ArrayType) and \
                isinstance(port.T, m._BitType) and \
                not isinstance(port, m.BitsType) and \
                isinstance(expected, BitVector):
            # If port is an Array(N, Bit) and **not** a Bits(N), then the
            # Python simulator will return a list of bools. So, if the user
            # provided a BitVector, we unpack it here so the equality check
            # works
            expected = expected.as_bool_list()
        if isinstance(port, m.ArrayType):
            for i in range(port.N):
                MagmaSimulatorTarget.check(got[i], port[i], expected[i])
            return
        assert got == expected, f"Got {got}, expected {expected}"

    def run(self, actions):
        simulator = self.backend_cls(self.circuit, self.clock)
        for action in actions:
            if isinstance(action, fault.actions.Poke):
                value = action.value
                # Python simulator does not support setting Bit with
                # BitVector(1), so do conversion here
                if isinstance(action.port, m.BitType) and \
                        isinstance(value, BitVector):
                    value = value.as_uint()
                simulator.set_value(action.port, value)
            elif isinstance(action, fault.actions.Print):
                got = simulator.get_value(action.port)
                if isinstance(action.port, m.ArrayType) and \
                        isinstance(action.port.T, (m._BitType, m._BitKind)):
                    got = BitVector(got).as_uint()
                elif isinstance(action.port, m.ArrayType):
                    raise NotImplementedError("Printing complex nested arrays")
                print(f'{action.port.debug_name} = {action.format_str}' %
                      got)
            elif isinstance(action, fault.actions.Expect):
                got = simulator.get_value(action.port)
                expected = action.value
                if isinstance(expected, fault.actions.Peek):
                    expected = simulator.get_value(expected.port)
                MagmaSimulatorTarget.check(got, action.port, expected)
            elif isinstance(action, fault.actions.Eval):
                simulator.evaluate()
            elif isinstance(action, fault.actions.Step):
                if self.clock is not action.clock:
                    raise RuntimeError(f"Using different clocks: {self.clock}, "
                                       f"{action.clock}")
                simulator.advance_cycle(action.steps)
            else:
                raise NotImplementedError(action)}

Static methods

def check(got, port, expected)
Source code
@staticmethod
def check(got, port, expected):
    if isinstance(port, m.ArrayType) and \
            isinstance(port.T, m._BitType) and \
            not isinstance(port, m.BitsType) and \
            isinstance(expected, BitVector):
        # If port is an Array(N, Bit) and **not** a Bits(N), then the
        # Python simulator will return a list of bools. So, if the user
        # provided a BitVector, we unpack it here so the equality check
        # works
        expected = expected.as_bool_list()
    if isinstance(port, m.ArrayType):
        for i in range(port.N):
            MagmaSimulatorTarget.check(got[i], port[i], expected[i])
        return
    assert got == expected, f"Got {got}, expected {expected}"}

Methods

def run(self, actions)
Source code
def run(self, actions):
    simulator = self.backend_cls(self.circuit, self.clock)
    for action in actions:
        if isinstance(action, fault.actions.Poke):
            value = action.value
            # Python simulator does not support setting Bit with
            # BitVector(1), so do conversion here
            if isinstance(action.port, m.BitType) and \
                    isinstance(value, BitVector):
                value = value.as_uint()
            simulator.set_value(action.port, value)
        elif isinstance(action, fault.actions.Print):
            got = simulator.get_value(action.port)
            if isinstance(action.port, m.ArrayType) and \
                    isinstance(action.port.T, (m._BitType, m._BitKind)):
                got = BitVector(got).as_uint()
            elif isinstance(action.port, m.ArrayType):
                raise NotImplementedError("Printing complex nested arrays")
            print(f'{action.port.debug_name} = {action.format_str}' %
                  got)
        elif isinstance(action, fault.actions.Expect):
            got = simulator.get_value(action.port)
            expected = action.value
            if isinstance(expected, fault.actions.Peek):
                expected = simulator.get_value(expected.port)
            MagmaSimulatorTarget.check(got, action.port, expected)
        elif isinstance(action, fault.actions.Eval):
            simulator.evaluate()
        elif isinstance(action, fault.actions.Step):
            if self.clock is not action.clock:
                raise RuntimeError(f"Using different clocks: {self.clock}, "
                                   f"{action.clock}")
            simulator.advance_cycle(action.steps)
        else:
            raise NotImplementedError(action)}
def simulator_cls(backend)
Source code
def simulator_cls(backend):
    if backend == "coreir":
        return CoreIRSimulator
    if backend == "python":
        return PythonSimulator
    raise NotImplementedError(backend)}

Inherited members