Skip to content

Commit

Permalink
Add basic support for poke/expect X
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardt committed May 15, 2019
1 parent 7e117e5 commit 4295e38
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 21 deletions.
46 changes: 25 additions & 21 deletions fault/system_verilog_target.py
Expand Up @@ -67,7 +67,7 @@ def __init__(self, circuit, circuit_name=None, directory="build/",
if simulator is None:
raise ValueError("Must specify simulator when using system-verilog"
" target")
if simulator not in ["vcs", "ncsim"]:
if simulator not in {"vcs", "ncsim", "iverilog"}:
raise ValueError(f"Unsupported simulator {simulator}")
self.simulator = simulator
self.timescale = timescale
Expand All @@ -86,15 +86,27 @@ def make_name(self, port):
name = verilog_name(port.name)
return name

def make_poke(self, i, action):
name = self.make_name(action.port)
# For now we assume that verilog can handle big ints
value = action.value
if isinstance(action.port, m.SIntType) and value < 0:
def process_value(self, port, value):
if isinstance(port, m.SIntType) and value < 0:
# Handle sign extension for verilator since it expects and
# unsigned c type
port_len = len(action.port)
port_len = len(port)
value = BitVector(value, port_len).as_uint()
elif value is fault.UnknownValue:
value = "'X"
elif isinstance(value, actions.Peek):
if isinstance(value.port, fault.WrappedVerilogInternalPort):
value = f"dut.{value.port.path}"
else:
value = f"{value.port.name}"
elif isinstance(value, PortWrapper):
value = f"dut.{value.select_path.system_verilog_path}"
return value

def make_poke(self, i, action):
name = self.make_name(action.port)
# For now we assume that verilog can handle big ints
value = self.process_value(action.port, action.value)
return [f"{name} = {value};", f"#{self.clock_step_delay}"]

def make_print(self, i, action):
Expand Down Expand Up @@ -139,19 +151,7 @@ def make_expect(self, i, action):
debug_name = name
else:
debug_name = action.port.name
value = action.value
if isinstance(value, actions.Peek):
if isinstance(value.port, fault.WrappedVerilogInternalPort):
value = f"dut.{value.port.path}"
else:
value = f"{value.port.name}"
elif isinstance(value, PortWrapper):
value = f"dut.{value.select_path.system_verilog_path}"
elif isinstance(action.port, m.SIntType) and value < 0:
# Handle sign extension for verilator since it expects and
# unsigned c type
port_len = len(action.port)
value = BitVector(value, port_len).as_uint()
value = self.process_value(action.port, action.value)

return [f"if ({name} != {value}) $error(\"Failed on action={i}"
f" checking port {debug_name}. Expected %x, got %x\""
Expand Down Expand Up @@ -246,10 +246,14 @@ def run(self, actions):
cmd = f"""\
irun -top {self.circuit_name}_tb -timescale {self.timescale} -access +rwc -notimingchecks -input {cmd_file} {test_bench_file} {self.verilog_file} {verilog_libraries}
""" # nopep8
else:
elif self.simulator == "vcs":
cmd = f"""\
vcs -sverilog -full64 +v2k -timescale={self.timescale} -LDFLAGS -Wl,--no-as-needed {test_bench_file} {self.verilog_file} {verilog_libraries}
""" # nopep8
elif self.simulator == "iverilog":
cmd = f"iverilog {test_bench_file} {self.verilog_file}"
else:
raise NotImplementedError(self.simulator)

print(f"Running command: {cmd}")
assert not subprocess.call(cmd, cwd=self.directory, shell=True)
Expand Down
8 changes: 8 additions & 0 deletions tests/common.py
Expand Up @@ -70,3 +70,11 @@ def definition(io):
# [io.a + io.b, io.a - io.b, io.a * io.b, io.a / io.b], opcode)
# use arbitrary fourth op
[io.a + io.b, io.a - io.b, io.a * io.b, io.b - io.a], opcode)


class AndCircuit(m.Circuit):
IO = ["I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)]

@classmethod
def definition(io):
io.O <= io.I0 & io.I1
24 changes: 24 additions & 0 deletions tests/test_setattr_interface.py
@@ -1,8 +1,10 @@
import common
import tempfile
import fault
from fault import Tester
import shutil
import random
import pytest


def pytest_generate_tests(metafunc):
Expand All @@ -12,6 +14,8 @@ def pytest_generate_tests(metafunc):
targets.append(("system-verilog", "ncsim"))
if shutil.which("vcs"):
targets.append(("system-verilog", "vcs"))
if shutil.which("iverilog"):
targets.append(("system-verilog", "iverilog"))
metafunc.parametrize("target,simulator", targets)


Expand Down Expand Up @@ -113,3 +117,23 @@ def test_setattr_tuple(target, simulator):
tester.circuit.O.a.expect(5)
tester.circuit.O.b.expect(11)
run_test(target, simulator, tester)


def test_setattr_x(target, simulator):
if target == "verilator":
pytest.skip("X not support with Verilator")
circ = common.AndCircuit
tester = Tester(circ)
tester.circuit.I0 = 0
tester.circuit.I1 = 1
tester.eval()
tester.circuit.O.expect(0)
tester.circuit.I0 = fault.UnknownValue
tester.circuit.I1 = 1
tester.eval()
tester.circuit.O.expect(0)
tester.circuit.I0 = fault.UnknownValue
tester.circuit.I1 = fault.UnknownValue
tester.eval()
tester.circuit.O.expect(fault.UnknownValue)
run_test(target, simulator, tester)

0 comments on commit 4295e38

Please sign in to comment.