fault.symbolic_tester module

Source code
import fault
from fault.tester import Tester
from fault.wrapper import Wrapper, PortWrapper, InstanceWrapper
from fault.cosa_target import CoSATarget
import fault.actions as actions


class SymbolicWrapper(Wrapper):
    def __init__(self, circuit, parent):
        super().__init__(circuit, parent)

    def __setattr__(self, attr, value):
        # Hack to stage this after __init__ has been run, should redefine this
        # method in a metaclass? Could also use a try/except pattern, so the
        # exceptions only occur during object instantiation
        if hasattr(self, "circuit") and hasattr(self, "instance_map"):
            if attr in self.circuit.interface.ports.keys():
                if isinstance(self.parent, fault.Tester):
                    self.parent.poke(self.circuit.interface.ports[attr], value)
                else:
                    exit(1)
            else:
                object.__setattr__(self, attr, value)
        else:
            object.__setattr__(self, attr, value)

    def __getattr__(self, attr):
        # Hack to stage this after __init__ has been run, should redefine this
        # method in a metaclass?
        try:
            if attr in self.circuit.interface.ports.keys():
                return SymbolicPortWrapper(self.circuit.interface.ports[attr],
                                           self)
            elif attr in self.instance_map:
                return SymbolicInstanceWrapper(self.instance_map[attr], self)
            else:
                object.__getattribute__(self, attr)
        except Exception as e:
            object.__getattribute__(self, attr)


class SymbolicCircuitWrapper(SymbolicWrapper):
    pass


class SymbolicPortWrapper(PortWrapper):
    def assume(self, pred):
        select_path = self.select_path
        select_path.tester.assume(select_path, pred)

    def guarantee(self, pred):
        select_path = self.select_path
        select_path.tester.guarantee(select_path, pred)


class SymbolicInstanceWrapper(InstanceWrapper):
    pass


class SymbolicTester(Tester):
    def __init__(self, circuit, clock=None, num_tests=100):
        super().__init__(circuit, clock)
        self.num_tests = num_tests

    def assume(self, port, constraint):
        """
        Place a constraint on an input port by providing a symbolic expression
        as a Python lambda or function

            symbolic_tester_inst.assume(top.I, lambda x : x >= 0)
        """
        self.actions.append(actions.Assume(port, constraint))

    def guarantee(self, port, constraint):
        """
        Assert a property about an output port by providing a symbolic
        expression as a Python lambda or function

            symbolic_tester_inst.assume(top.O, lambda x : x >= 0)
        """
        self.actions.append(actions.Guarantee(port, constraint))

    @property
    def circuit(self):
        return SymbolicCircuitWrapper(self._circuit, self)

    def run(self, target="verilator"):
        if target == "verilator":
            self.targets[target].run(self.actions, self.verilator_includes,
                                     self.num_tests, self._circuit)
        elif target == "cosa":
            self.targets[target].run(self.actions)
        else:
            raise NotImplementedError()

    def make_target(self, target: str, **kwargs):
        if target == "cosa":
            return CoSATarget(self._circuit, **kwargs)
        else:
            return super().make_target(target, **kwargs)}

Classes

class SymbolicCircuitWrapper (ancestors: SymbolicWrapper, Wrapper)

Inherited from: SymbolicWrapper

Source code
class SymbolicCircuitWrapper(SymbolicWrapper):
    pass}

Inherited members

class SymbolicInstanceWrapper (ancestors: InstanceWrapper, Wrapper)

Inherited from: InstanceWrapper

Source code
class SymbolicInstanceWrapper(InstanceWrapper):
    pass}

Inherited members

class SymbolicPortWrapper (ancestors: PortWrapper)

Inherited from: PortWrapper

Source code
class SymbolicPortWrapper(PortWrapper):
    def assume(self, pred):
        select_path = self.select_path
        select_path.tester.assume(select_path, pred)

    def guarantee(self, pred):
        select_path = self.select_path
        select_path.tester.guarantee(select_path, pred)}

Methods

def assume(self, pred)
Source code
def assume(self, pred):
    select_path = self.select_path
    select_path.tester.assume(select_path, pred)}
def guarantee(self, pred)
Source code
def guarantee(self, pred):
    select_path = self.select_path
    select_path.tester.guarantee(select_path, pred)}

Inherited members

class SymbolicTester (ancestors: Tester)

Inherited from: Tester

The fault Tester object provides a mechanism in Python to construct tests for magma circuits. The Tester is instantiated with a specific magma …

Source code
class SymbolicTester(Tester):
    def __init__(self, circuit, clock=None, num_tests=100):
        super().__init__(circuit, clock)
        self.num_tests = num_tests

    def assume(self, port, constraint):
        """
        Place a constraint on an input port by providing a symbolic expression
        as a Python lambda or function

            symbolic_tester_inst.assume(top.I, lambda x : x >= 0)
        """
        self.actions.append(actions.Assume(port, constraint))

    def guarantee(self, port, constraint):
        """
        Assert a property about an output port by providing a symbolic
        expression as a Python lambda or function

            symbolic_tester_inst.assume(top.O, lambda x : x >= 0)
        """
        self.actions.append(actions.Guarantee(port, constraint))

    @property
    def circuit(self):
        return SymbolicCircuitWrapper(self._circuit, self)

    def run(self, target="verilator"):
        if target == "verilator":
            self.targets[target].run(self.actions, self.verilator_includes,
                                     self.num_tests, self._circuit)
        elif target == "cosa":
            self.targets[target].run(self.actions)
        else:
            raise NotImplementedError()

    def make_target(self, target: str, **kwargs):
        if target == "cosa":
            return CoSATarget(self._circuit, **kwargs)
        else:
            return super().make_target(target, **kwargs)}

Instance variables

var circuit
Source code
@property
def circuit(self):
    return SymbolicCircuitWrapper(self._circuit, self)}

Methods

def assume(self, port, constraint)

Place a constraint on an input port by providing a symbolic expression as a Python lambda or function

symbolic_tester_inst.assume(top.I, lambda x : x >= 0)
Source code
def assume(self, port, constraint):
    """
    Place a constraint on an input port by providing a symbolic expression
    as a Python lambda or function

        symbolic_tester_inst.assume(top.I, lambda x : x >= 0)
    """
    self.actions.append(actions.Assume(port, constraint))}
def guarantee(self, port, constraint)

Assert a property about an output port by providing a symbolic expression as a Python lambda or function

symbolic_tester_inst.assume(top.O, lambda x : x >= 0)
Source code
def guarantee(self, port, constraint):
    """
    Assert a property about an output port by providing a symbolic
    expression as a Python lambda or function

        symbolic_tester_inst.assume(top.O, lambda x : x >= 0)
    """
    self.actions.append(actions.Guarantee(port, constraint))}

Inherited members

class SymbolicWrapper (ancestors: Wrapper)

Inherited from: Wrapper

Source code
class SymbolicWrapper(Wrapper):
    def __init__(self, circuit, parent):
        super().__init__(circuit, parent)

    def __setattr__(self, attr, value):
        # Hack to stage this after __init__ has been run, should redefine this
        # method in a metaclass? Could also use a try/except pattern, so the
        # exceptions only occur during object instantiation
        if hasattr(self, "circuit") and hasattr(self, "instance_map"):
            if attr in self.circuit.interface.ports.keys():
                if isinstance(self.parent, fault.Tester):
                    self.parent.poke(self.circuit.interface.ports[attr], value)
                else:
                    exit(1)
            else:
                object.__setattr__(self, attr, value)
        else:
            object.__setattr__(self, attr, value)

    def __getattr__(self, attr):
        # Hack to stage this after __init__ has been run, should redefine this
        # method in a metaclass?
        try:
            if attr in self.circuit.interface.ports.keys():
                return SymbolicPortWrapper(self.circuit.interface.ports[attr],
                                           self)
            elif attr in self.instance_map:
                return SymbolicInstanceWrapper(self.instance_map[attr], self)
            else:
                object.__getattribute__(self, attr)
        except Exception as e:
            object.__getattribute__(self, attr)}

Subclasses

Inherited members