示例#1
0
def test_regression():
    io_core = IOCore()
    io_core_circuit = io_core.circuit()
    tester = Tester(io_core_circuit)

    for _glb2io_16, _f2io_16 in \
            [(random_bv(16), random_bv(16)) for _ in range(100)]:
        tester.poke(io_core_circuit.glb2io_16, _glb2io_16)
        tester.poke(io_core_circuit.f2io_16, _f2io_16)
        tester.eval()
        tester.expect(io_core_circuit.io2glb_16, _f2io_16)
        tester.expect(io_core_circuit.io2f_16, _glb2io_16)

    for _glb2io_1, _f2io_1 in \
            [(random_bv(1), random_bv(1)) for _ in range(100)]:
        tester.poke(io_core_circuit.glb2io_1, _glb2io_1)
        tester.poke(io_core_circuit.f2io_1, _f2io_1)
        tester.eval()
        tester.expect(io_core_circuit.io2glb_1, _f2io_1)
        tester.expect(io_core_circuit.io2f_1, _glb2io_1)

    with tempfile.TemporaryDirectory() as tempdir:
        tester.compile_and_run(target="verilator",
                               magma_output="coreir-verilog",
                               directory=tempdir,
                               flags=["-Wno-fatal"])
def test_valid_generation():
    io_core = IOCoreValid()
    io_core_circuit = io_core.circuit()
    tester = BasicTester(io_core_circuit, io_core_circuit.clk,
                         io_core_circuit.reset)

    max_cycle = 16

    # mode set to 1
    # max cycle set to 16
    config_data = [
        io_core.get_config_data("mode", 1),
        io_core.get_config_data("max_cycle", max_cycle)
    ]
    config_data = compress_config_data(config_data)

    tester.zero_inputs()
    tester.poke(io_core_circuit.stall, 1)

    for addr, data in config_data:
        tester.configure(addr, data)
        tester.config_read(addr)
        tester.eval()
        tester.expect(io_core_circuit.read_config_data, data)

    # un-stall
    tester.poke(io_core_circuit.stall, 0)

    # it should stay low regardless of the IO as long as the reset signal is never high
    for _f2io_16 in [random_bv(16) for _ in range(10)]:
        tester.poke(io_core_circuit.f2io_16, _f2io_16)
        tester.eval()
        tester.expect(io_core_circuit.io2glb_16, _f2io_16)
        tester.expect(io_core_circuit.io2glb_1, 0)

    # hit the start  signal
    tester.poke(io_core_circuit.glb2io_1, 1)
    tester.eval()
    # rising clock edge
    tester.step(2)
    # de-assert the reset/start signal
    tester.poke(io_core_circuit.glb2io_1, 0)
    tester.eval()

    # from now on it should output 1 until it reaches max cycle
    for _ in range(max_cycle):
        tester.expect(io_core_circuit.io2glb_1, 1)
        tester.step(2)

    # then stay low
    for _ in range(max_cycle):
        tester.expect(io_core_circuit.io2glb_1, 0)
        tester.step(2)

    with tempfile.TemporaryDirectory() as tempdir:
        tester.compile_and_run(target="verilator",
                               magma_output="coreir-verilog",
                               directory=tempdir,
                               flags=["-Wno-fatal"])
示例#3
0
def test_magma_simulator_target_nested_arrays_bulk(backend):
    circ = common.TestNestedArraysCircuit
    expected = [random_bv(4) for i in range(3)]
    actions = []
    actions.append(Poke(circ.I, expected))
    actions.append(Eval())
    actions.append(Expect(circ.O, expected))
    run(circ, actions, None, backend)
示例#4
0
def test_target_peek(target, simulator):
    circ = TestPeekCircuit
    actions = []
    for i in range(3):
        x = random_bv(3)
        actions.append(Poke(circ.I, x))
        actions.append(Eval())
        actions.append(Expect(circ.O0, Peek(circ.O1)))
    run(circ, actions, target, simulator)
示例#5
0
def test_magma_simulator_target_peek(backend):
    circ = common.TestPeekCircuit
    actions = []
    for i in range(3):
        x = random_bv(3)
        actions.append(Poke(circ.I, x))
        actions.append(Eval())
        actions.append(Expect(circ.O0, Peek(circ.O1)))
    run(circ, actions, None, backend)
示例#6
0
def test_magma_simulator_target_nested_arrays_by_element(backend):
    circ = common.TestNestedArraysCircuit
    expected = [random_bv(4) for i in range(3)]
    actions = []
    for i, val in enumerate(expected):
        actions.append(Poke(circ.I[i], val))
    actions.append(Eval())
    for i, val in enumerate(expected):
        actions.append(Expect(circ.O[i], val))
    run(circ, actions, None, backend)
示例#7
0
def test_regression(default_value, num_tracks, has_constant):
    feedthrough_outputs = "1111101111"
    params = {
        "width": 16,
        "num_tracks": num_tracks,
        "feedthrough_outputs": feedthrough_outputs,
        "has_constant": has_constant,
        "default_value": default_value.as_uint()
    }

    magma_cb = define_cb(**params)
    m.compile(f"test_cb/build/{magma_cb.name}",
              magma_cb,
              output="coreir-verilog")

    genesis_cb = cb_wrapper.generator()(**params,
                                        input_files=["cb/genesis/cb.vp"])
    genesis_verilog = "genesis_verif/cb.v"

    check_interfaces(magma_cb, genesis_cb)
    shutil.copy(genesis_verilog, "test_cb/build")

    config_addr = BitVector(0, 32)

    cb_functional_model = gen_cb(**params)()

    class CBTester(ResetTester, ConfigurationTester):
        pass

    tester = CBTester(genesis_cb, genesis_cb.clk, cb_functional_model)
    for config_data in [BitVector(x, 32) for x in range(0, num_tracks)]:
        tester.zero_inputs()
        tester.reset()
        tester.configure(config_addr, config_data)

        tester.actions += \
            generate_actions_from_streams(
                # Interesting example of Python's dynamic scoping, observe how
                # the following code is incorrect because of when the string
                # argument to getattr is evaluated
                # genesis_cb, cb_functional_model, dict(**{
                #   f"in_{i}": lambda name, port: random_bv(
                #     len(getattr(genesis_cb, f"in_i{i}")))
                #   for i in range(num_tracks) if feedthrough_outputs[i] == "1"
                # }, **{
                genesis_cb, cb_functional_model, {
                    f"in_{i}": lambda name, port: random_bv(
                        len(port))
                    for i in range(num_tracks) if feedthrough_outputs[i] == "1"
                })

    for cb, output in [(genesis_cb, "verilog"), (magma_cb, "coreir-verilog")]:
        tester.retarget(cb, cb.clk) \
              .compile_and_run(directory="test_cb/build", target="verilator",
                               flags=["-Wno-fatal"], magma_output=output)
示例#8
0
def test_valid_generation(run_tb):
    io_core = IOCoreValid()
    io_core_circuit = io_core.circuit()
    tester = BasicTester(io_core_circuit, io_core_circuit.clk, io_core_circuit.reset)

    max_cycle = 16

    # mode set to 1
    # max cycle set to 16
    config_data = [io_core.get_config_data("mode", 1), io_core.get_config_data("max_cycle", max_cycle)]
    config_data = compress_config_data(config_data)

    tester.zero_inputs()
    tester.reset()
    tester.poke(io_core_circuit.stall, 1)

    for addr, data in config_data:
        tester.configure(addr, data)
        tester.config_read(addr)
        tester.eval()
        tester.expect(io_core_circuit.read_config_data, data)

    # un-stall
    tester.poke(io_core_circuit.stall, 0)

    # it should stay low regardless of the IO as long as the reset signal is never high
    for _f2io_16 in [random_bv(16) for _ in range(10)]:
        tester.poke(io_core_circuit.f2io_16, _f2io_16)
        tester.eval()
        tester.expect(io_core_circuit.io2glb_16, _f2io_16)
        tester.expect(io_core_circuit.io2glb_1, 0)

    # hit the start  signal
    tester.poke(io_core_circuit.glb2io_1, 1)
    tester.eval()
    # rising clock edge
    tester.step(2)
    # de-assert the reset/start signal
    tester.poke(io_core_circuit.glb2io_1, 0)
    tester.eval()

    # from now on it should output 1 until it reaches max cycle
    for _ in range(max_cycle):
        tester.expect(io_core_circuit.io2glb_1, 1)
        tester.step(2)

    # then stay low
    for _ in range(max_cycle):
        tester.expect(io_core_circuit.io2glb_1, 0)
        tester.step(2)

    run_tb(tester)
示例#9
0
def test_regression(run_tb):
    io_core = IOCore()
    io_core_circuit = io_core.circuit()
    tester = Tester(io_core_circuit)

    for _glb2io_16, _f2io_16 in \
            [(random_bv(16), random_bv(16)) for _ in range(100)]:
        tester.poke(io_core_circuit.glb2io_16, _glb2io_16)
        tester.poke(io_core_circuit.f2io_16, _f2io_16)
        tester.eval()
        tester.expect(io_core_circuit.io2glb_16, _f2io_16)
        tester.expect(io_core_circuit.io2f_16, _glb2io_16)

    for _glb2io_1, _f2io_1 in \
            [(random_bv(1), random_bv(1)) for _ in range(100)]:
        tester.poke(io_core_circuit.glb2io_1, _glb2io_1)
        tester.poke(io_core_circuit.f2io_1, _f2io_1)
        tester.eval()
        tester.expect(io_core_circuit.io2glb_1, _f2io_1)
        tester.expect(io_core_circuit.io2f_1, _glb2io_1)

    run_tb(tester)
示例#10
0
def get_random_arr(name, port):
    if issubclass(port, m.Bits) or issubclass(port.T, m.Digital):
        # TODO: Hack, check the name and don't twiddle config ports, we
        # should add a config type
        if "config_" in name:
            return BitVector[len(port)](0)
        else:
            return random_bv(len(port))
    else:
        if issubclass(port.T, m.Array):
            return fault.array.Array([
                get_random_arr(name + f"_{i}", port.T)
                for i in range(len(port))
            ], len(port))
    raise NotImplementedError()  # pragma: nocover
示例#11
0
 def add_assumptions(self, circuit, actions, i):
     main_body = ""
     for port in circuit.interface.ports.values():
         if port.isoutput():
             for assumption in self.assumptions:
                 # TODO: Chained assumptions?
                 assume_port = assumption.port
                 if isinstance(assume_port, SelectPath):
                     assume_port = assume_port[-1]
                 if assume_port is port:
                     pred = assumption.value
                     while True:
                         randval = random_bv(len(assume_port))
                         if pred(randval):
                             break
                     code = self.make_poke(
                         len(actions) + i, Poke(port, randval))
                     for line in code:
                         main_body += f"  {line}\n"
                     break
     return main_body
示例#12
0
import pytest

from fault.action_generators import generate_actions_from_streams
from common.testers import ResetTester, ConfigurationTester
from common.regression_test import check_interfaces
from fault.random import random_bv


def teardown_function():
    for item in glob.glob('genesis_*'):
        os.system(f"rm -r {item}")


# Test 10 random default values with has_constant
default_params = [(random_bv(16), 1) for _ in range(2)]
# Include one test with no constant
default_params += [(random_bv(16), 0)]


@pytest.mark.parametrize('default_value,has_constant', default_params)
# FIXME: this fails
# @pytest.mark.parametrize('num_tracks', range(2,10))
@pytest.mark.parametrize('num_tracks', [10])
def test_regression(default_value, num_tracks, has_constant):
    feedthrough_outputs = "1111101111"
    params = {
        "width": 16,
        "num_tracks": num_tracks,
        "feedthrough_outputs": feedthrough_outputs,
        "has_constant": has_constant,
示例#13
0
def test_tile():
    core = DummyCore()
    tile = Tile(core)
    tile_circ = tile.circuit()
    # No functional model for tile yet, so we have to use the
    # standard fault tester for now
    tester = BasicTester(tile_circ, tile_circ.clk, tile_circ.reset)
    # assign the tile a random ID for configuration
    tile_id = random_bv(16)
    tester.poke(tile_circ.tile_id, tile_id)
    tester.reset()

    # Connect random vals to all tile inputs
    inputs_applied = {}
    for side_in in (tile_circ.north.I, tile_circ.south.I, tile_circ.east.I,
                    tile_circ.west.I):
        for i in range(len(side_in.layer1)):
            port = side_in.layer1[i]
            rand_input = random_bv(1)
            inputs_applied[port] = rand_input
            tester.poke(port, rand_input)
        for j in range(len(side_in.layer16)):
            port = side_in.layer16[j]
            rand_input = random_bv(16)
            inputs_applied[port] = rand_input
            tester.poke(port, rand_input)

    # Write to all configuration registers in the tile
    # This test should be applicapable to any tile, regardless
    # of the core it's using
    data_written = {}
    for i, feat in enumerate(tile.features()):
        feat_addr = BitVector(i, 8)
        for reg in feat.registers.values():
            reg_addr = BitVector(reg.addr, 8)
            upper_config_addr = BitVector.concat(reg_addr, feat_addr)
            config_addr = BitVector.concat(upper_config_addr, tile_id)
            # Ensure the register is wide enough to contain the random value
            rand_data = random_bv(reg.width)
            # Further restrict random config data values based on feature
            # Only 0-3 valid for SB config_data
            if (feat == tile.sb):
                if ((reg_addr % 2) == 0):
                    rand_data = rand_data % 4
                # Only 0-1 valid for SB regs
                else:
                    rand_data = rand_data % 2
            # Only 0-9 valid for CB config_data
            elif (feat in tile.cbs):
                rand_data = rand_data % 10
            # Make sure we pass 32 bits of config data to configure
            config_data = BitVector(rand_data, 32)
            tester.configure(config_addr, config_data)
            # Keep track of data written so we know what to expect to read back
            data_written[config_addr] = config_data

    # Now, read back all the configuration we just wrote
    for addr in data_written:
        tester.config_read(addr)
        expected_data = data_written[addr]
        tester.expect(tile_circ.read_config_data, expected_data)
        feat_addr = addr[16:24]
        reg_addr = addr[24:32]

    check_all_config(tester, tile_circ, tile, data_written, inputs_applied)

    # Try writing to tile with wrong tile id
    for config_addr in data_written:
        new_tile_id = config_addr[0:16] + 1
        upper_config_addr = config_addr[16:32]
        new_config_addr = BitVector.concat(upper_config_addr, new_tile_id)
        random_data = random_bv(32)
        tester.configure(new_config_addr, random_data)

    # Read all the config back again to make sure nothing changed
    check_all_config(tester, tile_circ, tile, data_written, inputs_applied)

    with tempfile.TemporaryDirectory() as tempdir:
        tester.compile_and_run(target="verilator",
                               magma_output="coreir-verilog",
                               directory=tempdir,
                               flags=["-Wno-fatal"])
def test_regression(num_tracks):
    params = {
        "width": 16,
        "num_tracks": num_tracks,
    }

    # Create magma circuit.
    magma_simple_cb = define_simple_cb(**params)
    m.compile(f"test_simple_cb/build/{magma_simple_cb.name}", magma_simple_cb,
              output="coreir-verilog")

    # Create genesis circuit.
    genesis_simple_cb = simple_cb_wrapper.generator()(
        **params, input_files=["simple_cb/genesis/simple_cb.vp"])
    genesis_verilog = "genesis_verif/simple_cb.v"
    shutil.copy(genesis_verilog, "test_simple_cb/build/")

    # TODO: Do we need this extra instantiation, could the function do it for
    # us?
    simple_cb_functional_model = gen_simple_cb(**params)()

    class MappedCB:
        def __init__(self, circuit):
            self.circuit = circuit
            self.renamed_ports = {
                "clk": "CLK",
                "reset": "ASYNCRESET",
                "out": "O"
            }

        def __getattr__(self, field):
            if self.circuit is magma_simple_cb:
                if field in self.renamed_ports:
                    field = self.renamed_ports[field]
                elif "in_" in field:
                    return self.circuit.I[int(field.split("_")[-1])]
            return getattr(self.circuit, field)

    check_interfaces(MappedCB(magma_simple_cb), genesis_simple_cb)

    class SimpleCBTester(ResetTester, ConfigurationTester):
        pass

    for simple_cb, clock, reset, output, streams in [
            (genesis_simple_cb, genesis_simple_cb.clk, genesis_simple_cb.reset,
             "verilog", {
                 f"in_{i}": lambda name, port: random_bv(len(port))
                 for i in range(num_tracks)
             }),
            (magma_simple_cb, magma_simple_cb.CLK, magma_simple_cb.ASYNCRESET,
             "coreir-verilog", {
                 f"I": lambda name, port: [random_bv(len(port.T)) for i in
                                           range(num_tracks)]
             })
    ]:
        input_mapping = None if simple_cb is genesis_simple_cb else (
            lambda *args: args[0])

        tester = SimpleCBTester(simple_cb, clock, simple_cb_functional_model,
                                reset_port=reset)

        tester.zero_inputs()

        for config_data in [BitVector(x, 32) for x in range(0, 1)]:
            tester.reset()
            tester.configure(BitVector(0, 32), config_data)
            tester.actions += \
                generate_actions_from_streams(
                    simple_cb, simple_cb_functional_model, streams,
                    input_mapping=input_mapping)
        tester.compile_and_run(target="verilator",
                               directory="test_simple_cb/build",
                               flags=["-Wno-fatal"],
                               magma_output=output)
示例#15
0
def test_simple_pe(ops):
    pe = define_pe(ops, T=m.UInt, data_width=16)

    class SimplePETester(ResetTester, ConfigurationTester):
        pass

    pe_functional_model = gen_simple_pe(ops, 16)()

    tester = SimplePETester(pe, pe.clk, pe_functional_model)

    m.compile("test_simple_pe/build/pe",
              pe,
              output="coreir",
              passes=["rungenerators", "flatten", "cullgraph"])

    # For verilator test
    m.compile(f"test_simple_pe/build/{pe.name}", pe, output="coreir-verilog")

    tester.zero_inputs()
    opcode_width = m.bitutils.clog2(len(ops))
    config_addr_width = 1

    for config_data in [
            BitVector(x, opcode_width) for x in range(0, len(ops))
    ]:
        tester.reset()
        tester.configure(BitVector(0, config_addr_width), config_data)
        tester.actions += \
            generate_actions_from_streams(
                pe, pe_functional_model, {
                    f"I{i}": lambda name, port: random_bv(len(port))
                    for i in range(2)
                })
    tester.compile_and_run(directory="test_simple_pe/build",
                           target="verilator",
                           flags=["-Wno-fatal"],
                           magma_output="coreir-verilog")
    opcode_width = m.bitutils.clog2(len(ops))
    op_strs = {
        operator.add: "+",
        operator.sub: "-",
        operator.and_: "&",
        operator.or_: "|"
    }

    for i, op in enumerate(ops):
        with open(f"test_simple_pe/build/conf_{op.__name__}.ets", "w") as ets:
            ets.write(
                config_ets_template.format(config_addr=0,
                                           config_addr_width=1,
                                           config_data=i,
                                           config_data_width=opcode_width))
        with open(f"test_simple_pe/build/conf_{op.__name__}.ets", "r") as f:
            print(f.read())
        problem = f"""\
[GENERAL]
model_file: pe.json,conf_{op.__name__}.ets
add_clock: True
assume_if_true: True

[DEFAULT]
bmc_length: 40
verification: safety

[PE check {op.__name__} configuration]
description: "Check configuring to opcode={i} results in read_data={i}"
formula: (conf_done = 1_1) -> (self.read_data = {i}_{opcode_width})
prove: TRUE
expected: TRUE

[PE check {op.__name__} functionality]
description: "Check configuring to opcode={i} corresponds to {op.__name__}"
formula: (conf_done = 1_1) -> ((self.I0 {op_strs[op]} self.I1) = self.O)
prove: TRUE
expected: TRUE
"""  # noqa
        problem_file = f"test_simple_pe/build/problem_pe_{op.__name__}.txt"
        with open(problem_file, "w") as f:
            f.write(problem)
        assert not os.system(f"CoSA --problem {problem_file} --solver z3")