rewrite functional backend test code in python

This commit is contained in:
Emily Schmidt 2024-07-12 11:07:33 +01:00
parent 9ad859fc0a
commit 674e6d201d
57 changed files with 554 additions and 1238 deletions

View File

@ -0,0 +1,19 @@
Tests for the functional backend use pytest as a testrunner.
Run with `pytest -v`
Pytest options you might want:
- `-v`: More progress indication.
- `--basetemp tmp`: Store test files (including vcd results) in tmp.
CAREFUL: contents of tmp will be deleted
- `-k <pattern>`: Run only tests that contain the pattern, e.g.
`-k cxx` or `-k smt` or `-k demux` or `-k 'cxx[demux`
- `-s`: Don't hide stdout/stderr from the test code.
Custom options for functional backend tests:
- `--per-cell N`: Run only N tests for each cell.

View File

@ -0,0 +1,14 @@
import pytest
from rtlil_cells import generate_test_cases
def pytest_addoption(parser):
parser.addoption(
"--per-cell", type=int, default=None, help="run only N tests per cell"
)
def pytest_generate_tests(metafunc):
if "cell" in metafunc.fixturenames:
print(dir(metafunc.config))
per_cell = metafunc.config.getoption("per_cell", default=None)
names, cases = generate_test_cases(per_cell)
metafunc.parametrize("cell,parameters", cases, ids=names)

View File

@ -0,0 +1,275 @@
from itertools import chain
import random
widths = [
(16, 32, 48, True),
(16, 32, 48, False),
(32, 16, 48, True),
(32, 16, 48, False),
(32, 32, 16, True),
(32, 32, 16, False)
]
shift_widths = [
(32, 6, 32, True, False),
(32, 6, 32, False, False),
(32, 6, 64, True, False),
(32, 6, 64, False, False),
(32, 32, 16, True, False),
(32, 32, 16, False, False),
(32, 6, 32, True, True),
(32, 6, 32, False, True),
(32, 6, 64, True, True),
(32, 6, 64, False, True),
(32, 32, 16, True, True),
(32, 32, 16, False, True),
]
def write_rtlil_cell(f, cell_type, inputs, outputs, parameters):
f.write('autoidx 1\n')
f.write('module \\gold\n')
idx = 1
for name, width in inputs.items():
f.write(f'\twire width {width} input {idx} \\{name}\n')
idx += 1
for name, width in outputs.items():
f.write(f'\twire width {width} output {idx} \\{name}\n')
idx += 1
f.write(f'\tcell ${cell_type} \\UUT\n')
for (name, value) in parameters.items():
f.write(f'\t\tparameter \\{name} {value}\n')
for name in chain(inputs.keys(), outputs.keys()):
f.write(f'\t\tconnect \\{name} \\{name}\n')
f.write(f'\tend\nend\n')
class BaseCell:
def __init__(self, name):
self.name = name
class UnaryCell(BaseCell):
def __init__(self, name):
super().__init__(name)
def generate_tests(self):
for (a_width, _, y_width, signed) in widths:
yield (f'{a_width}-{y_width}-{'S' if signed else 'U'}',
{'A_WIDTH' : a_width,
'A_SIGNED' : int(signed),
'Y_WIDTH' : y_width})
def write_rtlil_file(self, f, parameters):
write_rtlil_cell(f, self.name, {'A': parameters['A_WIDTH']}, {'Y': parameters['Y_WIDTH']}, parameters)
class BinaryCell(BaseCell):
def __init__(self, name):
super().__init__(name)
def generate_tests(self):
for (a_width, b_width, y_width, signed) in widths:
yield (f'{a_width}-{b_width}-{y_width}-{'S' if signed else 'U'}',
{'A_WIDTH' : a_width,
'A_SIGNED' : int(signed),
'B_WIDTH' : b_width,
'B_SIGNED' : int(signed),
'Y_WIDTH' : y_width})
def write_rtlil_file(self, f, parameters):
write_rtlil_cell(f, self.name, {'A': parameters['A_WIDTH'], 'B': parameters['B_WIDTH']}, {'Y': parameters['Y_WIDTH']}, parameters)
class ShiftCell(BaseCell):
def __init__(self, name):
super().__init__(name)
def generate_tests(self):
for (a_width, b_width, y_width, a_signed, b_signed) in shift_widths:
if not self.name in ('shift', 'shiftx') and b_signed: continue
if self.name == 'shiftx' and a_signed: continue
yield (f'{a_width}-{b_width}-{y_width}-{'S' if a_signed else 'U'}{'S' if b_signed else 'U'}',
{'A_WIDTH' : a_width,
'A_SIGNED' : int(a_signed),
'B_WIDTH' : b_width,
'B_SIGNED' : int(b_signed),
'Y_WIDTH' : y_width})
def write_rtlil_file(self, f, parameters):
write_rtlil_cell(f, self.name, {'A': parameters['A_WIDTH'], 'B': parameters['B_WIDTH']}, {'Y': parameters['Y_WIDTH']}, parameters)
class MuxCell(BaseCell):
def __init__(self, name):
super().__init__(name)
def generate_tests(self):
for width in [10, 20, 40]:
yield (f'{width}', {'WIDTH' : width})
def write_rtlil_file(self, f, parameters):
write_rtlil_cell(f, self.name, {'A': parameters['WIDTH'], 'B': parameters['WIDTH'], 'S': 1}, {'Y': parameters['WIDTH']}, parameters)
class BWCell(BaseCell):
def __init__(self, name):
super().__init__(name)
def generate_tests(self):
for width in [10, 20, 40]:
yield (f'{width}', {'WIDTH' : width})
def write_rtlil_file(self, f, parameters):
inputs = {'A': parameters['WIDTH'], 'B': parameters['WIDTH']}
if self.name == "bwmux": inputs['S'] = parameters['WIDTH']
write_rtlil_cell(f, self.name, inputs, {'Y': parameters['WIDTH']}, parameters)
class PMuxCell(BaseCell):
def __init__(self, name):
super().__init__(name)
def generate_tests(self):
for (width, s_width) in [(10, 1), (10, 4), (20, 4)]:
yield (f'{width}-{s_width}',
{'WIDTH' : width,
'S_WIDTH' : s_width})
def write_rtlil_file(self, f, parameters):
s_width = parameters['S_WIDTH']
b_width = parameters['WIDTH'] * s_width
write_rtlil_cell(f, self.name, {'A': parameters['WIDTH'], 'B': b_width, 'S': s_width}, {'Y': parameters['WIDTH']}, parameters)
class BMuxCell(BaseCell):
def __init__(self, name):
super().__init__(name)
def generate_tests(self):
for (width, s_width) in [(10, 1), (10, 2), (10, 4)]:
yield (f'{width}-{s_width}', {'WIDTH' : width, 'S_WIDTH' : s_width})
def write_rtlil_file(self, f, parameters):
write_rtlil_cell(f, self.name, {'A': parameters['WIDTH'] << parameters['S_WIDTH'], 'S': parameters['S_WIDTH']}, {'Y': parameters['WIDTH']}, parameters)
class DemuxCell(BaseCell):
def __init__(self, name):
super().__init__(name)
def generate_tests(self):
for (width, s_width) in [(10, 1), (32, 2), (16, 4)]:
yield (f'{width}-{s_width}', {'WIDTH' : width, 'S_WIDTH' : s_width})
def write_rtlil_file(self, f, parameters):
write_rtlil_cell(f, self.name, {'A': parameters['WIDTH'], 'S': parameters['S_WIDTH']}, {'Y': parameters['WIDTH'] << parameters['S_WIDTH']}, parameters)
def seeded_randint(seed, a, b):
r = random.getstate()
random.seed(seed)
n = random.randint(a, b)
random.setstate(r)
return n
class LUTCell(BaseCell):
def __init__(self, name):
super().__init__(name)
def generate_tests(self):
for width in [4, 6, 8]:
lut = seeded_randint(width, 0, 2**width - 1)
yield (f'{width}', {'WIDTH' : width, 'LUT' : lut})
def write_rtlil_file(self, f, parameters):
write_rtlil_cell(f, self.name, {'A': parameters['WIDTH']}, {'Y': 1}, parameters)
class ConcatCell(BaseCell):
def __init__(self, name):
super().__init__(name)
def generate_tests(self):
for (a_width, b_width) in [(16, 16), (8, 14), (20, 10)]:
yield (f'{a_width}-{b_width}', {'A_WIDTH' : a_width, 'B_WIDTH' : b_width})
def write_rtlil_file(self, f, parameters):
write_rtlil_cell(f, self.name, {'A': parameters['A_WIDTH'], 'B' : parameters['B_WIDTH']}, {'Y': parameters['A_WIDTH'] + parameters['B_WIDTH']}, parameters)
class SliceCell(BaseCell):
def __init__(self, name):
super().__init__(name)
def generate_tests(self):
for (a_width, offset, y_width) in [(32, 10, 15), (8, 0, 4), (10, 0, 10)]:
yield (f'{a_width}-{offset}-{y_width}', {'A_WIDTH' : a_width, 'OFFSET' : offset, 'Y_WIDTH': y_width})
def write_rtlil_file(self, f, parameters):
write_rtlil_cell(f, self.name, {'A': parameters['A_WIDTH']}, {'Y': parameters['Y_WIDTH']}, parameters)
class FailCell(BaseCell):
def __init__(self, name):
super().__init__(name)
def generate_tests(self):
yield ('', {})
def write_rtlil_file(self, f, parameters):
raise Exception(f'\'{self.name}\' cell unimplemented in test generator')
rtlil_cells = [
UnaryCell("not"),
UnaryCell("pos"),
UnaryCell("neg"),
BinaryCell("and"),
BinaryCell("or"),
BinaryCell("xor"),
BinaryCell("xnor"),
UnaryCell("reduce_and"),
UnaryCell("reduce_or"),
UnaryCell("reduce_xor"),
UnaryCell("reduce_xnor"),
UnaryCell("reduce_bool"),
ShiftCell("shl"),
ShiftCell("shr"),
ShiftCell("sshl"),
ShiftCell("sshr"),
ShiftCell("shift"),
ShiftCell("shiftx"),
# ("fa", ["A", "B", "C", "X", "Y"]),
# ("lcu", ["P", "G", "CI", "CO"]),
# ("alu", ["A", "B", "CI", "BI", "X", "Y", "CO"]),
BinaryCell("lt"),
BinaryCell("le"),
BinaryCell("eq"),
BinaryCell("ne"),
BinaryCell("eqx"),
BinaryCell("nex"),
BinaryCell("ge"),
BinaryCell("gt"),
BinaryCell("add"),
BinaryCell("sub"),
BinaryCell("mul"),
# BinaryCell("macc"),
BinaryCell("div"),
BinaryCell("mod"),
BinaryCell("divfloor"),
BinaryCell("modfloor"),
BinaryCell("pow"),
UnaryCell("logic_not"),
BinaryCell("logic_and"),
BinaryCell("logic_or"),
SliceCell("slice"),
ConcatCell("concat"),
MuxCell("mux"),
BMuxCell("bmux"),
PMuxCell("pmux"),
DemuxCell("demux"),
LUTCell("lut"),
# ("sop", ["A", "Y"]),
# ("tribuf", ["A", "EN", "Y"]),
# ("specify2", ["EN", "SRC", "DST"]),
# ("specify3", ["EN", "SRC", "DST", "DAT"]),
# ("specrule", ["EN_SRC", "EN_DST", "SRC", "DST"]),
BWCell("bweqx"),
BWCell("bwmux"),
# ("assert", ["A", "EN"]),
# ("assume", ["A", "EN"]),
# ("live", ["A", "EN"]),
# ("fair", ["A", "EN"]),
# ("cover", ["A", "EN"]),
# ("initstate", ["Y"]),
# ("anyconst", ["Y"]),
# ("anyseq", ["Y"]),
# ("anyinit", ["D", "Q"]),
# ("allconst", ["Y"]),
# ("allseq", ["Y"]),
# ("equiv", ["A", "B", "Y"]),
# ("print", ["EN", "TRG", "ARGS"]),
# ("check", ["A", "EN", "TRG", "ARGS"]),
# ("set_tag", ["A", "SET", "CLR", "Y"]),
# ("get_tag", ["A", "Y"]),
# ("overwrite_tag", ["A", "SET", "CLR"]),
# ("original_tag", ["A", "Y"]),
# ("future_ff", ["A", "Y"]),
# ("scopeinfo", []),
]
def generate_test_cases(per_cell):
tests = []
names = []
for cell in rtlil_cells:
seen_names = set()
for (name, parameters) in cell.generate_tests():
if not name in seen_names:
seen_names.add(name)
tests.append((cell, parameters))
names.append(f'{cell.name}-{name}' if name != '' else cell.name)
if per_cell is not None and len(seen_names) >= per_cell:
break
return (names, tests)

2
tests/functional/run-test.sh Executable file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env bash
pytest -v "$@"

View File

@ -1,2 +0,0 @@
# Creation of test files
yosys -p "test_cell -n 1 -w test_cell all"

View File

@ -1,83 +0,0 @@
# Generated by Yosys 0.40+7 (git sha1 4fd5b29f9, g++ 13.2.0 -Og -fPIC)
autoidx 19
attribute \cells_not_processed 1
attribute \src "dff.v:1.1-16.10"
module \gold
attribute \src "dff.v:8.5-14.8"
wire $0\q[0:0]
attribute \init 1'0
wire $auto$clk2fflogic.cc:65:sample_control$\reset#sampled$13
attribute \init 1'1
wire $auto$clk2fflogic.cc:77:sample_control_edge$\clk#sampled$7
attribute \init 1'0
wire $auto$clk2fflogic.cc:91:sample_data$\d#sampled$5
attribute \init 1'x
wire $auto$clk2fflogic.cc:91:sample_data$\q#sampled$3
wire $auto$rtlil.cc:2525:Eqx$10
wire $auto$rtlil.cc:2582:Mux$12
wire $auto$rtlil.cc:2582:Mux$16
wire $auto$rtlil.cc:2582:Mux$18
attribute \src "dff.v:2.16-2.19"
wire input 1 \clk
attribute \src "dff.v:4.16-4.17"
wire input 3 \d
attribute \keep 1
attribute \src "dff.v:5.16-5.17"
wire output 4 \q
attribute \src "dff.v:3.16-3.21"
wire input 2 \reset
cell $mux $auto$clk2fflogic.cc:113:mux$11
parameter \WIDTH 1
connect \A $auto$clk2fflogic.cc:91:sample_data$\q#sampled$3
connect \B $auto$clk2fflogic.cc:91:sample_data$\d#sampled$5
connect \S $auto$rtlil.cc:2525:Eqx$10
connect \Y $auto$rtlil.cc:2582:Mux$12
end
cell $mux $auto$clk2fflogic.cc:113:mux$15
parameter \WIDTH 1
connect \A $auto$rtlil.cc:2582:Mux$12
connect \B 1'0
connect \S $auto$clk2fflogic.cc:65:sample_control$\reset#sampled$13
connect \Y $auto$rtlil.cc:2582:Mux$16
end
cell $mux $auto$clk2fflogic.cc:113:mux$17
parameter \WIDTH 1
connect \A $auto$rtlil.cc:2582:Mux$16
connect \B 1'0
connect \S \reset
connect \Y $auto$rtlil.cc:2582:Mux$18
end
cell $ff $auto$clk2fflogic.cc:70:sample_control$14
parameter \WIDTH 1
connect \D \reset
connect \Q $auto$clk2fflogic.cc:65:sample_control$\reset#sampled$13
end
cell $ff $auto$clk2fflogic.cc:82:sample_control_edge$8
parameter \WIDTH 1
connect \D \clk
connect \Q $auto$clk2fflogic.cc:77:sample_control_edge$\clk#sampled$7
end
cell $eqx $auto$clk2fflogic.cc:83:sample_control_edge$9
parameter \A_SIGNED 0
parameter \A_WIDTH 2
parameter \B_SIGNED 0
parameter \B_WIDTH 2
parameter \Y_WIDTH 1
connect \A { $auto$clk2fflogic.cc:77:sample_control_edge$\clk#sampled$7 \clk }
connect \B 2'01
connect \Y $auto$rtlil.cc:2525:Eqx$10
end
attribute \clk2fflogic 1
cell $ff $auto$clk2fflogic.cc:98:sample_data$4
parameter \WIDTH 1
connect \D \q
connect \Q $auto$clk2fflogic.cc:91:sample_data$\q#sampled$3
end
cell $ff $auto$clk2fflogic.cc:98:sample_data$6
parameter \WIDTH 1
connect \D \d
connect \Q $auto$clk2fflogic.cc:91:sample_data$\d#sampled$5
end
connect $0\q[0:0] \d
connect \q $auto$rtlil.cc:2582:Mux$18
end

View File

@ -1,69 +0,0 @@
# Generated by Yosys 0.40+7 (git sha1 cc795a3f5, g++ 13.2.0 -Og -fPIC)
autoidx 5
attribute \cells_not_processed 1
attribute \src "multiple_outputs.v:1.1-15.10"
module \gold
attribute \src "multiple_outputs.v:11.12-11.20"
wire $and$multiple_outputs.v:11$2_Y
attribute \src "multiple_outputs.v:10.12-10.14"
wire $not$multiple_outputs.v:10$1_Y
attribute \src "multiple_outputs.v:12.12-12.20"
wire $or$multiple_outputs.v:12$3_Y
attribute \src "multiple_outputs.v:13.12-13.20"
wire $xor$multiple_outputs.v:13$4_Y
attribute \src "multiple_outputs.v:2.16-2.17"
wire input 1 \a
attribute \src "multiple_outputs.v:3.17-3.18"
wire output 2 \b
attribute \src "multiple_outputs.v:4.17-4.18"
wire output 3 \c
attribute \src "multiple_outputs.v:5.17-5.18"
wire output 4 \d
attribute \src "multiple_outputs.v:6.17-6.18"
wire output 5 \e
attribute \src "multiple_outputs.v:11.12-11.20"
cell $and $and$multiple_outputs.v:11$2
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B 1'1
connect \Y $and$multiple_outputs.v:11$2_Y
end
attribute \src "multiple_outputs.v:10.12-10.14"
cell $not $not$multiple_outputs.v:10$1
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \Y $not$multiple_outputs.v:10$1_Y
end
attribute \src "multiple_outputs.v:12.12-12.20"
cell $or $or$multiple_outputs.v:12$3
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B 1'0
connect \Y $or$multiple_outputs.v:12$3_Y
end
attribute \src "multiple_outputs.v:13.12-13.20"
cell $xor $xor$multiple_outputs.v:13$4
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B 1'1
connect \Y $xor$multiple_outputs.v:13$4_Y
end
connect \b $not$multiple_outputs.v:10$1_Y
connect \c $and$multiple_outputs.v:11$2_Y
connect \d $or$multiple_outputs.v:12$3_Y
connect \e $xor$multiple_outputs.v:13$4_Y
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 5 input 1 \A
wire width 4 input 2 \B
wire width 6 output 3 \Y
cell $add \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 5
parameter \B_SIGNED 1
parameter \B_WIDTH 4
parameter \Y_WIDTH 6
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,25 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 8 input 1 \A
wire width 7 input 2 \B
wire input 3 \BI
wire input 4 \CI
wire width 6 output 5 \CO
wire width 6 output 6 \X
wire width 6 output 7 \Y
cell $alu \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 8
parameter \B_SIGNED 0
parameter \B_WIDTH 7
parameter \Y_WIDTH 6
connect \A \A
connect \B \B
connect \BI \BI
connect \CI \CI
connect \CO \CO
connect \X \X
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 2 input 1 \A
wire width 3 input 2 \B
wire width 2 output 3 \Y
cell $and \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 2
parameter \B_SIGNED 1
parameter \B_WIDTH 3
parameter \Y_WIDTH 2
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,14 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 8 input 1 \A
wire input 2 \S
wire width 4 output 3 \Y
cell $bmux \UUT
parameter \S_WIDTH 1
parameter \WIDTH 4
connect \A \A
connect \S \S
connect \Y \Y
end
end

View File

@ -1,14 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 6 input 1 \A
wire width 5 input 2 \S
wire width 192 output 3 \Y
cell $demux \UUT
parameter \S_WIDTH 5
parameter \WIDTH 6
connect \A \A
connect \S \S
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 4 input 1 \A
wire width 6 input 2 \B
wire output 3 \Y
cell $div \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 4
parameter \B_SIGNED 0
parameter \B_WIDTH 6
parameter \Y_WIDTH 1
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 4 input 1 \A
wire width 4 input 2 \B
wire width 6 output 3 \Y
cell $divfloor \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 4
parameter \B_SIGNED 0
parameter \B_WIDTH 4
parameter \Y_WIDTH 6
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 5 input 1 \A
wire input 2 \B
wire width 4 output 3 \Y
cell $eq \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 4
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire input 1 \A
wire input 2 \B
wire input 3 \C
wire output 4 \X
wire output 5 \Y
cell $fa \UUT
parameter \WIDTH 1
connect \A \A
connect \B \B
connect \C \C
connect \X \X
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 3 input 1 \A
wire width 7 input 2 \B
wire width 6 output 3 \Y
cell $ge \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 3
parameter \B_SIGNED 1
parameter \B_WIDTH 7
parameter \Y_WIDTH 6
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 7 input 1 \A
wire width 3 input 2 \B
wire width 4 output 3 \Y
cell $gt \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 7
parameter \B_SIGNED 1
parameter \B_WIDTH 3
parameter \Y_WIDTH 4
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,15 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire input 1 \CI
wire width 2 output 2 \CO
wire width 2 input 3 \G
wire width 2 input 4 \P
cell $lcu \UUT
parameter \WIDTH 2
connect \CI \CI
connect \CO \CO
connect \G \G
connect \P \P
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 5 input 1 \A
wire width 4 input 2 \B
wire width 6 output 3 \Y
cell $le \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 5
parameter \B_SIGNED 1
parameter \B_WIDTH 4
parameter \Y_WIDTH 6
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 2 input 1 \A
wire width 7 input 2 \B
wire output 3 \Y
cell $logic_and \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 2
parameter \B_SIGNED 0
parameter \B_WIDTH 7
parameter \Y_WIDTH 1
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,13 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 3 input 1 \A
wire width 8 output 2 \Y
cell $logic_not \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 3
parameter \Y_WIDTH 8
connect \A \A
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 8 input 1 \A
wire width 7 input 2 \B
wire width 2 output 3 \Y
cell $logic_or \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 8
parameter \B_SIGNED 0
parameter \B_WIDTH 7
parameter \Y_WIDTH 2
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 8 input 1 \A
wire width 5 input 2 \B
wire width 6 output 3 \Y
cell $lt \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 8
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 6
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,12 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 2 input 1 \A
wire output 2 \Y
cell $lut \UUT
parameter \LUT 4'1111
parameter \WIDTH 2
connect \A \A
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 3 input 1 \A
wire width 0 input 2 \B
wire width 2 output 3 \Y
cell $macc \UUT
parameter \A_WIDTH 3
parameter \B_WIDTH 0
parameter \CONFIG 10'0110000010
parameter \CONFIG_WIDTH 10
parameter \Y_WIDTH 2
connect \A \A
connect \B { }
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 6 input 1 \A
wire width 8 input 2 \B
wire width 2 output 3 \Y
cell $mod \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 6
parameter \B_SIGNED 0
parameter \B_WIDTH 8
parameter \Y_WIDTH 2
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 5 input 1 \A
wire width 7 input 2 \B
wire width 4 output 3 \Y
cell $modfloor \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 7
parameter \Y_WIDTH 4
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 6 input 1 \A
wire width 2 input 2 \B
wire width 5 output 3 \Y
cell $mul \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 6
parameter \B_SIGNED 0
parameter \B_WIDTH 2
parameter \Y_WIDTH 5
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,15 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 4 input 1 \A
wire width 4 input 2 \B
wire input 3 \S
wire width 4 output 4 \Y
cell $mux \UUT
parameter \WIDTH 4
connect \A \A
connect \B \B
connect \S \S
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 7 input 1 \A
wire width 5 input 2 \B
wire width 4 output 3 \Y
cell $ne \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 7
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 4
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,13 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 2 input 1 \A
wire width 5 output 2 \Y
cell $neg \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 2
parameter \Y_WIDTH 5
connect \A \A
connect \Y \Y
end
end

View File

@ -1,13 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 7 input 1 \A
wire width 7 output 2 \Y
cell $not \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 7
parameter \Y_WIDTH 7
connect \A \A
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 7 input 1 \A
wire input 2 \B
wire width 2 output 3 \Y
cell $or \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 7
parameter \B_SIGNED 1
parameter \B_WIDTH 1
parameter \Y_WIDTH 2
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,13 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire input 1 \A
wire width 3 output 2 \Y
cell $pos \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 1
parameter \Y_WIDTH 3
connect \A \A
connect \Y \Y
end
end

View File

@ -1,13 +0,0 @@
# Generated by Yosys 0.40+7 (git sha1 d8b5b90e7, g++ 13.2.0 -Og -fPIC)
autoidx 1
module \gold
wire width 6 input 1 \A
wire width 6 output 2 \Y
cell $pos \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 6
parameter \Y_WIDTH 6
connect \A \A
connect \Y \Y
end
end

View File

@ -1,13 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 4 input 1 \A
wire width 5 output 2 \Y
cell $reduce_and \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 4
parameter \Y_WIDTH 5
connect \A \A
connect \Y \Y
end
end

View File

@ -1,13 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire input 1 \A
wire width 2 output 2 \Y
cell $reduce_bool \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 1
parameter \Y_WIDTH 2
connect \A \A
connect \Y \Y
end
end

View File

@ -1,13 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 2 input 1 \A
wire width 7 output 2 \Y
cell $reduce_or \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 2
parameter \Y_WIDTH 7
connect \A \A
connect \Y \Y
end
end

View File

@ -1,13 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 4 input 1 \A
wire width 4 output 2 \Y
cell $reduce_xnor \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 4
parameter \Y_WIDTH 4
connect \A \A
connect \Y \Y
end
end

View File

@ -1,13 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 4 input 1 \A
wire output 2 \Y
cell $reduce_xor \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 4
parameter \Y_WIDTH 1
connect \A \A
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire input 1 \A
wire width 6 input 2 \B
wire width 4 output 3 \Y
cell $shift \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 1
parameter \B_SIGNED 1
parameter \B_WIDTH 6
parameter \Y_WIDTH 4
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire input 1 \A
wire width 5 input 2 \B
wire width 3 output 3 \Y
cell $shiftx \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 5
parameter \Y_WIDTH 3
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 8 input 1 \A
wire width 2 input 2 \B
wire width 3 output 3 \Y
cell $shl \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 8
parameter \B_SIGNED 0
parameter \B_WIDTH 2
parameter \Y_WIDTH 3
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 7 input 1 \A
wire width 6 input 2 \B
wire width 4 output 3 \Y
cell $shr \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 7
parameter \B_SIGNED 0
parameter \B_WIDTH 6
parameter \Y_WIDTH 4
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,13 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 8 input 1 \A
wire output 2 \Y
cell $sop \UUT
parameter \DEPTH 8
parameter \TABLE 128'10010000100100000101101010001001101000101010010100010000010100000101010100000001001010010110101010101010101000100100011001000110
parameter \WIDTH 8
connect \A \A
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 5 input 1 \A
wire width 3 input 2 \B
wire width 6 output 3 \Y
cell $sshl \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 5
parameter \B_SIGNED 0
parameter \B_WIDTH 3
parameter \Y_WIDTH 6
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 3 input 1 \A
wire width 2 input 2 \B
wire width 2 output 3 \Y
cell $sshr \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 3
parameter \B_SIGNED 0
parameter \B_WIDTH 2
parameter \Y_WIDTH 2
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 6 input 1 \A
wire width 6 input 2 \B
wire width 6 output 3 \Y
cell $sub \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 6
parameter \B_SIGNED 0
parameter \B_WIDTH 6
parameter \Y_WIDTH 6
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 7 input 1 \A
wire width 8 input 2 \B
wire width 7 output 3 \Y
cell $xnor \UUT
parameter \A_SIGNED 1
parameter \A_WIDTH 7
parameter \B_SIGNED 1
parameter \B_WIDTH 8
parameter \Y_WIDTH 7
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,17 +0,0 @@
# Generated by Yosys 0.41+101 (git sha1 83a8e5de4, g++ 13.2.0 -fPIC -Os)
autoidx 1
module \gold
wire width 6 input 1 \A
wire width 2 input 2 \B
wire width 8 output 3 \Y
cell $xor \UUT
parameter \A_SIGNED 0
parameter \A_WIDTH 6
parameter \B_SIGNED 0
parameter \B_WIDTH 2
parameter \Y_WIDTH 8
connect \A \A
connect \B \B
connect \Y \Y
end
end

View File

@ -1,172 +0,0 @@
#!/bin/bash
declare -A cxx_failing_files
declare -A smt_failing_files
declare -A cxx_successful_files
declare -A smt_successful_files
run_cxx_test() {
BASE_PATH="../../../"
local rtlil_file=$1
local base_name=$(basename "$rtlil_file" .v)
if ${BASE_PATH}yosys -p "read_rtlil $rtlil_file; write_functional_cxx my_module_functional_cxx.cc"; then
echo "Yosys processed $rtlil_file successfully."
if ${CXX:-g++} -g -fprofile-arcs -ftest-coverage vcd_harness.cc -I ${BASE_PATH}backends/functional/cxx_runtime/ -std=c++17 -o vcd_harness; then
echo "Compilation successful."
if ./vcd_harness ${base_name}_functional_cxx.vcd; then
if ${BASE_PATH}yosys -p "read_rtlil $rtlil_file; sim -r ${base_name}_functional_cxx.vcd -scope gold -vcd ${base_name}_yosys_sim.vcd -timescale 1us -sim-gold"; then
echo "Yosys sim $rtlil_file successfully."
cxx_successful_files["$rtlil_file"]="Success"
else
${BASE_PATH}yosys -p "read_rtlil $rtlil_file; sim -vcd ${base_name}_yosys_sim.vcd -r ${base_name}_functional_cxx.vcd -scope gold -timescale 1us"
echo "Yosys simulation of $rtlil_file failed. There is a discrepancy with functional cxx"
cxx_failing_files["$rtlil_file"]="Yosys sim failure"
fi
else
echo "Failed to generate VCD files for $rtlil_file."
cxx_failing_files["$rtlil_file"]="VCD generation failure"
fi
else
echo "Failed to compile harness for $rtlil_file."
cxx_failing_files["$rtlil_file"]="Compilation failure"
fi
else
echo "Yosys failed to process $rtlil_file."
cxx_failing_files["$rtlil_file"]="Yosys failure"
fi
}
run_smt_test() {
BASE_PATH="../../../"
local rtlil_file=$1
local base_name=$(basename "$rtlil_file" .il)
if ${BASE_PATH}yosys -p "read_rtlil $rtlil_file; write_functional_smt2 ${base_name}.smt2"; then
echo "Yosys processed $rtlil_file successfully."
# TODO: which SMT solver should be run?
if z3 "${base_name}.smt2"; then
echo "SMT file ${base_name}.smt2 is valid ."
if python3 vcd_harness_smt.py "${base_name}.smt2"; then
echo "Python script generated VCD file for $rtlil_file successfully."
if [ -f "${base_name}.smt2.vcd" ]; then
echo "VCD file ${base_name}.vcd generated successfully by Python."
if ${BASE_PATH}yosys -p "read_rtlil $rtlil_file; sim -vcd ${base_name}_yosys.vcd -r ${base_name}.smt2.vcd -scope gold -timescale 1us"; then
echo "Yosys simulation for $rtlil_file completed successfully."
smt_successful_files["$rtlil_file"]="Success"
else
echo "Yosys simulation failed for $rtlil_file."
smt_failing_files["$rtlil_file"]="Yosys simulation failure"
fi
else
echo "Failed to generate VCD file (${base_name}.vcd) for $rtlil_file. "
smt_failing_files["$rtlil_file"]="VCD generation failure"
fi
else
echo "Failed to run Python script for $rtlil_file."
smt_failing_files["$rtlil_file"]="Python script failure"
fi
else
echo "SMT file for $rtlil_file is invalid"
smt_failing_files["$rtlil_file"]="Invalid SMT"
fi
else
echo "Yosys failed to process $rtlil_file."
smt_failing_files["$rtlil_file"]="Yosys failure"
fi
}
run_all_tests() {
declare -A cxx_failing_files
declare -A smt_failing_files
declare -A cxx_successful_files
declare -A smt_successful_files
return_code=0
for rtlil_file in rtlil/*.il; do
run_cxx_test "$rtlil_file"
run_smt_test "$rtlil_file"
done
echo "C++ tests results:"
if [ ${#cxx_failing_files[@]} -eq 0 ]; then
echo "All files passed."
echo "The following files passed:"
for file in "${!cxx_successful_files[@]}"; do
echo "$file"
done
else
echo "The following files failed:"
for file in "${!cxx_failing_files[@]}"; do
echo "$file: ${cxx_failing_files[$file]}"
done
echo "The following files passed:"
for file in "${!cxx_successful_files[@]}"; do
echo "$file"
done
return_code=1
fi
echo "SMT tests results:"
if [ ${#smt_failing_files[@]} -eq 0 ]; then
echo "All files passed."
echo "The following files passed:"
for file in "${!smt_successful_files[@]}"; do
echo "$file"
done
else
echo "The following files failed:"
for file in "${!smt_failing_files[@]}"; do
echo "$file: ${smt_failing_files[$file]}"
done
echo "The following files passed:"
for file in "${!smt_successful_files[@]}"; do
echo "$file"
done
return_code=1
fi
return $return_code
}
run_smt_tests() {
declare -A smt_failing_files
declare -A smt_successful_files
return_code=0
for rtlil_file in rtlil/*.il; do
run_smt_test "$rtlil_file"
done
echo "SMT tests results:"
if [ ${#smt_failing_files[@]} -eq 0 ]; then
echo "All files passed."
echo "The following files passed:"
for file in "${!smt_successful_files[@]}"; do
echo "$file"
done
else
echo "The following files failed:"
for file in "${!smt_failing_files[@]}"; do
echo "$file: ${smt_failing_files[$file]}"
done
echo "The following files passed:"
for file in "${!smt_successful_files[@]}"; do
echo "$file"
done
return_code=1
fi
return $return_code
}
# If the script is being sourced, do not execute the tests
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
run_all_tests
fi

View File

@ -1,214 +0,0 @@
import sys
import argparse
import random
import os
# Parse command line arguments
parser = argparse.ArgumentParser(description='Process SMT file for simulation.')
parser.add_argument('smt_file', help='Path to the SMT file to simulate.')
args = parser.parse_args()
# Get the SMT file path from the command line argument
smt_file_path = args.smt_file
current_file_path = os.path.abspath(__file__)
# Navigate to the directory you need relative to the current script
# Assuming 'backends/smt2' is located three directories up from the current script
desired_path = os.path.join(os.path.dirname(current_file_path), '..', '..', '..', 'backends', 'functional')
# Normalize the path to resolve any '..'
normalized_path = os.path.normpath(desired_path)
# Append the directory to the Python path
sys.path.append(normalized_path)
# Import the module
import smtio
# Assuming the SmtIo class and other dependencies are available in your environment
# You may need to include the entire script provided above in your script or have it available as a module
# Step 1: Initialize an SmtIo object
so = smtio.SmtOpts()
so.solver = "z3"
so.logic = "BV"
so.debug_print = True
# so.debug_file = "my_debug"
smt_io = smtio.SmtIo(opts=so)
# List to store the parsed results
parsed_results = []
# Load and execute the SMT file
with open(smt_file_path, 'r') as smt_file:
for line in smt_file:
smt_io.write(line.strip())
smt_io.check_sat()
# Read and parse the SMT file line by line
with open(smt_file_path, 'r') as smt_file:
for line in smt_file:
# Strip leading/trailing whitespace
stripped_line = line.strip()
# Ignore empty lines
if not stripped_line:
continue
# comments
if stripped_line.startswith(';'):
smt_io.info(stripped_line)
# Parse the line using SmtIo's parse method
parsed_line = smt_io.parse(stripped_line)
# Append the parsed result to the list
parsed_results.append(parsed_line)
# Display the parsed results
for result in parsed_results:
print(result)
inputs = {}
outputs = {}
for lst in parsed_results:
if lst[0] == 'declare-datatypes':
for datatype_group in lst[2]: # Navigate into the nested lists
datatype_name = datatype_group[0]
declarations = datatype_group[1][1:] # Skip the first item (e.g., 'mk_inputs')
if datatype_name == 'Inputs':
for declaration in declarations:
print("My declaration")
print(declaration)
input_name = declaration[0]
bitvec_size = declaration[1][2]
inputs[input_name] = int(bitvec_size)
elif datatype_name == 'Outputs':
for declaration in declarations:
output_name = declaration[0]
bitvec_size = declaration[1][2]
outputs[output_name] = int(bitvec_size)
print(inputs)
print(outputs)
def set_step(inputs, step):
# This function assumes 'inputs' is a dictionary like {"A": 5, "B": 4}
# and 'input_values' is a dictionary like {"A": 5, "B": 13} specifying the concrete values for each input.
# Construct input definitions
mk_inputs_parts = []
for input_name, width in inputs.items():
value = random.getrandbits(width) # Generate a random number up to the maximum value for the bit size
binary_string = format(value, '0{}b'.format(width)) # Convert value to binary with leading zeros
mk_inputs_parts.append(f"#b{binary_string}")
# Join all parts for the mk_inputs constructor
mk_inputs_call = "mk_inputs " + " ".join(mk_inputs_parts)
define_inputs = f"(define-const test_inputs_step_n{step} Inputs ({mk_inputs_call}))\n"
# Create the output definition by calling the gold_step function
define_output = f"(define-const test_outputs_step_n{step} Outputs (gold_step test_inputs_step_n{step}))\n"
smt_commands = []
smt_commands.append(define_inputs)
smt_commands.append(define_output)
return smt_commands
num_steps = 10
smt_commands = []
# Loop to generate SMT commands for each step
for step in range(num_steps):
for step_command in set_step(inputs, step):
smt_commands.append(step_command)
# Print or write the SMT commands to a file
smt_file_content = ''.join(smt_commands)
print(smt_file_content) # Print to console
# Optionally, write to a file
with open('dynamic_commands.smt2', 'w') as smt_file:
smt_file.write(smt_file_content)
# Execute the SMT commands
for command in smt_commands:
print(command)
smt_io.write(command.strip())
# Check for satisfiability
# smt_io.setup()
result = smt_io.check_sat()
print(f'SAT result: {result}')
if result != 'sat':
smt_io.p_close()
sys.exit(1)
# Store signal values
signals = {name: [] for name in list(inputs.keys()) + list(outputs.keys())}
# Retrieve and print values for each state
def hex_to_bin(value):
if value.startswith('x'):
hex_value = value[1:] # Remove the 'x' prefix
bin_value = bin(int(hex_value, 16))[2:] # Convert to binary and remove the '0b' prefix
return f'b{bin_value.zfill(len(hex_value) * 4)}' # Add 'b' prefix and pad with zeros
return value
combined_assertions = []
for step in range(num_steps):
print(f"Values for step {step + 1}:")
for input_name, width in inputs.items():
value = smt_io.get(f'({input_name} test_inputs_step_n{step})')
value = hex_to_bin(value[1:])
print(f" {input_name}: {value}")
signals[input_name].append((step, value))
for output_name, width in outputs.items():
value = smt_io.get(f'({output_name} test_outputs_step_n{step})')
value = hex_to_bin(value[1:])
print(f" {output_name}: {value}")
signals[output_name].append((step, value))
combined_assertions.append(f'(= ({output_name} test_outputs_step_n{step}) #{value})')
# Create a single assertion covering all timesteps
combined_condition = " ".join(combined_assertions)
smt_io.write(f'(assert (not (and {combined_condition})))')
# Check the combined assertion
result = smt_io.check_sat(["unsat"])
if result != 'unsat':
smt_io.p_close()
sys.exit(1)
smt_io.p_close()
def write_vcd(filename, signals, timescale='1 ns', date='today'):
with open(filename, 'w') as f:
# Write the header
f.write(f"$date\n {date}\n$end\n")
f.write(f"$timescale {timescale} $end\n")
# Declare signals
f.write("$scope module gold $end\n")
for signal_name, changes in signals.items():
signal_size = len(changes[0][1])
f.write(f"$var wire {signal_size - 1} {signal_name} {signal_name} $end\n")
f.write("$upscope $end\n")
f.write("$enddefinitions $end\n")
# Collect all unique timestamps
timestamps = sorted(set(time for changes in signals.values() for time, _ in changes))
# Write initial values
f.write("#0\n")
for signal_name, changes in signals.items():
for time, value in changes:
if time == 0:
f.write(f"{value} {signal_name}\n")
# Write value changes
for time in timestamps:
if time != 0:
f.write(f"#{time}\n")
for signal_name, changes in signals.items():
for change_time, value in changes:
if change_time == time:
f.write(f"b{value} {signal_name}\n")
# Write the VCD file
write_vcd(smt_file_path + '.vcd', signals)
sys.exit(0)

180
tests/functional/smt_vcd.py Normal file
View File

@ -0,0 +1,180 @@
import sys
import argparse
import random
import os
import smtio
import re
class SExprParserError(Exception):
pass
class SExprParser:
def __init__(self):
self.peekbuf = None
self.stack = [[]]
self.atom_pattern = re.compile(r'[a-zA-Z0-9~!@$%^&*_\-+=<>.?/#]+')
def parse_line(self, line):
ptr = 0
while ptr < len(line):
if line[ptr].isspace():
ptr += 1
elif line[ptr] == ';':
break
elif line[ptr] == '(':
ptr += 1
self.stack.append([])
elif line[ptr] == ')':
ptr += 1
assert len(self.stack) > 1, "too many closed parentheses"
v = self.stack.pop()
self.stack[-1].append(v)
else:
match = self.atom_pattern.match(line, ptr)
if match is None:
raise SExprParserError(f"invalid character '{line[ptr]}' in line '{line}'")
start, ptr = match.span()
self.stack[-1].append(line[start:ptr])
def finish(self):
assert len(self.stack) == 1, "too many open parentheses"
def retrieve(self):
rv, self.stack[0] = self.stack[0], []
return rv
def simulate_smt_with_smtio(smt_file_path, vcd_path, smt_io):
inputs = {}
outputs = {}
def handle_datatype(lst):
print(lst)
datatype_name = lst[1]
declarations = lst[2][0][1:] # Skip the first item (e.g., 'mk_inputs')
if datatype_name.endswith("_Inputs"):
for declaration in declarations:
input_name = declaration[0]
bitvec_size = declaration[1][2]
assert input_name.startswith("gold_Inputs_")
inputs[input_name[len("gold_Inputs_"):]] = int(bitvec_size)
elif datatype_name.endswith("_Outputs"):
for declaration in declarations:
output_name = declaration[0]
bitvec_size = declaration[1][2]
assert output_name.startswith("gold_Outputs_")
outputs[output_name[len("gold_Outputs_"):]] = int(bitvec_size)
parser = SExprParser()
with open(smt_file_path, 'r') as smt_file:
for line in smt_file:
parser.parse_line(line)
for expr in parser.retrieve():
smt_io.write(smt_io.unparse(expr))
if expr[0] == "declare-datatype":
handle_datatype(expr)
parser.finish()
assert smt_io.check_sat() == 'sat'
def set_step(inputs, step):
# This function assumes 'inputs' is a dictionary like {"A": 5, "B": 4}
# and 'input_values' is a dictionary like {"A": 5, "B": 13} specifying the concrete values for each input.
mk_inputs_parts = []
for input_name, width in inputs.items():
value = random.getrandbits(width) # Generate a random number up to the maximum value for the bit size
binary_string = format(value, '0{}b'.format(width)) # Convert value to binary with leading zeros
mk_inputs_parts.append(f"#b{binary_string}")
mk_inputs_call = "gold_Inputs " + " ".join(mk_inputs_parts)
define_inputs = f"(define-const test_inputs_step_n{step} gold_Inputs ({mk_inputs_call}))\n"
define_outputs = f"(define-const test_outputs_step_n{step} gold_Outputs (first (gold test_inputs_step_n{step} gold_State)))\n"
smt_commands = [define_inputs, define_outputs]
return smt_commands
num_steps = 1000
smt_commands = []
for step in range(num_steps):
for step_command in set_step(inputs, step):
smt_commands.append(step_command)
for command in smt_commands:
smt_io.write(command)
assert smt_io.check_sat() == 'sat'
# Store signal values
signals = {name: [] for name in list(inputs.keys()) + list(outputs.keys())}
# Retrieve and print values for each state
def hex_to_bin(value):
if value.startswith('x'):
hex_value = value[1:] # Remove the 'x' prefix
bin_value = bin(int(hex_value, 16))[2:] # Convert to binary and remove the '0b' prefix
return f'b{bin_value.zfill(len(hex_value) * 4)}' # Add 'b' prefix and pad with zeros
return value
combined_assertions = []
for step in range(num_steps):
print(f"Values for step {step + 1}:")
for input_name, width in inputs.items():
value = smt_io.get(f'(gold_Inputs_{input_name} test_inputs_step_n{step})')
value = hex_to_bin(value[1:])
print(f" {input_name}: {value}")
signals[input_name].append((step, value))
for output_name, width in outputs.items():
value = smt_io.get(f'(gold_Outputs_{output_name} test_outputs_step_n{step})')
value = hex_to_bin(value[1:])
print(f" {output_name}: {value}")
signals[output_name].append((step, value))
combined_assertions.append(f'(= (gold_Outputs_{output_name} test_outputs_step_n{step}) #{value})')
# Create a single assertion covering all timesteps
combined_condition = " ".join(combined_assertions)
smt_io.write(f'(assert (not (and {combined_condition})))')
# Check the combined assertion
assert smt_io.check_sat(["unsat"]) == "unsat"
def write_vcd(filename, signals, timescale='1 ns', date='today'):
with open(filename, 'w') as f:
# Write the header
f.write(f"$date\n {date}\n$end\n")
f.write(f"$timescale {timescale} $end\n")
# Declare signals
f.write("$scope module gold $end\n")
for signal_name, changes in signals.items():
signal_size = len(changes[0][1])
f.write(f"$var wire {signal_size - 1} {signal_name} {signal_name} $end\n")
f.write("$upscope $end\n")
f.write("$enddefinitions $end\n")
# Collect all unique timestamps
timestamps = sorted(set(time for changes in signals.values() for time, _ in changes))
# Write initial values
f.write("#0\n")
for signal_name, changes in signals.items():
for time, value in changes:
if time == 0:
f.write(f"{value} {signal_name}\n")
# Write value changes
for time in timestamps:
if time != 0:
f.write(f"#{time}\n")
for signal_name, changes in signals.items():
for change_time, value in changes:
if change_time == time:
f.write(f"{value} {signal_name}\n")
write_vcd(vcd_path, signals)
def simulate_smt(smt_file_path, vcd_path):
so = smtio.SmtOpts()
so.solver = "z3"
so.logic = "BV"
so.debug_print = True
smt_io = smtio.SmtIo(opts=so)
try:
simulate_smt_with_smtio(smt_file_path, vcd_path, smt_io)
finally:
smt_io.p_close()

View File

@ -0,0 +1,63 @@
import subprocess
import pytest
import sys
import shlex
from pathlib import Path
base_path = Path(__file__).resolve().parent.parent.parent
def quote(path):
return shlex.quote(str(path))
def run(cmd, **kwargs):
print(' '.join([shlex.quote(str(x)) for x in cmd]))
status = subprocess.run(cmd, **kwargs)
assert status.returncode == 0, f"{cmd[0]} failed"
def yosys(script):
run([base_path / 'yosys', '-Q', '-p', script])
def compile_cpp(in_path, out_path, args):
run(['g++', '-g', '-std=c++17'] + args + [str(in_path), '-o', str(out_path)])
def test_cxx(cell, parameters, tmp_path):
rtlil_file = tmp_path / 'rtlil.il'
vcdharness_cc_file = base_path / 'tests/functional/vcd_harness.cc'
cc_file = tmp_path / 'my_module_functional_cxx.cc'
vcdharness_exe_file = tmp_path / 'a.out'
vcd_functional_file = tmp_path / 'functional.vcd'
vcd_yosys_sim_file = tmp_path / 'yosys.vcd'
with open(rtlil_file, 'w') as f:
cell.write_rtlil_file(f, parameters)
yosys(f"read_rtlil {quote(rtlil_file)} ; write_functional_cxx {quote(cc_file)}")
compile_cpp(vcdharness_cc_file, vcdharness_exe_file, ['-I', tmp_path, '-I', str(base_path / 'backends/functional/cxx_runtime')])
run([str(vcdharness_exe_file.resolve()), str(vcd_functional_file)])
try:
yosys(f"read_rtlil {quote(rtlil_file)}; sim -r {quote(vcd_functional_file)} -scope gold -vcd {quote(vcd_yosys_sim_file)} -timescale 1us -sim-gold")
except:
subprocess.run([base_path / 'yosys', '-Q', '-p',
f'read_rtlil {quote(rtlil_file)}; sim -vcd {quote(vcd_yosys_sim_file)} -r {quote(vcd_functional_file)} -scope gold -timescale 1us'],
capture_output=True, check=False)
raise
def test_smt(cell, parameters, tmp_path):
import smt_vcd
rtlil_file = tmp_path / 'rtlil.il'
smt_file = tmp_path / 'smtlib.smt'
vcd_functional_file = tmp_path / 'functional.vcd'
vcd_yosys_sim_file = tmp_path / 'yosys.vcd'
with open(rtlil_file, 'w') as f:
cell.write_rtlil_file(f, parameters)
yosys(f"read_rtlil {quote(rtlil_file)} ; write_functional_smt2 {quote(smt_file)}")
run(['z3', smt_file])
smt_vcd.simulate_smt(smt_file, vcd_functional_file)
try:
yosys(f"read_rtlil {quote(rtlil_file)}; sim -r {quote(vcd_functional_file)} -scope gold -vcd {quote(vcd_yosys_sim_file)} -timescale 1us -sim-gold")
except:
subprocess.run([base_path / 'yosys', '-Q', '-p',
f'read_rtlil {quote(rtlil_file)}; sim -vcd {quote(vcd_yosys_sim_file)} -r {quote(vcd_functional_file)} -scope gold -timescale 1us'],
capture_output=True, check=False)
raise

View File

@ -68,7 +68,7 @@ int main(int argc, char **argv)
const std::string functional_vcd_filename = argv[1]; const std::string functional_vcd_filename = argv[1];
constexpr int steps = 10; constexpr int steps = 1000;
constexpr int number_timescale = 1; constexpr int number_timescale = 1;
const std::string units_timescale = "us"; const std::string units_timescale = "us";
gold::Inputs inputs; gold::Inputs inputs;