|
1 | | -# |
2 | | -# This is a python script for testing the blif code generator with |
3 | | -# programs specifically set aside for it. The general pattern is that |
4 | | -# the test program comes in two parts: the test bench and the device |
5 | | -# to be tested. The files blif/*_tb.v are the test benches for the |
6 | | -# corresponding files blif/*.v. |
7 | | -# |
8 | | -# This script requires the "abc" command available here: |
9 | | -# <http://www.eecs.berkeley.edu/~alanmi/abc/> |
10 | | -# |
11 | | -# Run this script with the command: python blif_reg.py |
12 | | -# |
| 1 | +''' This is a python script for testing the blif code generator with |
| 2 | + programs specifically set aside for it. The general pattern is that |
| 3 | + the test program comes in two parts: the test bench and the device |
| 4 | + to be tested. The files blif/*_tb.v are the test benches for the |
| 5 | + corresponding files blif/*.v. |
| 6 | +
|
| 7 | + This script requires the "abc" command available here: |
| 8 | + <http://www.eecs.berkeley.edu/~alanmi/abc/> |
| 9 | +
|
| 10 | + Run this script with the command: python3 blif_reg.py ''' |
13 | 11 |
|
14 | 12 | import os |
15 | 13 | import subprocess |
16 | 14 | import re |
17 | 15 |
|
18 | | -# This is the name of the iverilog command and vvp command. These may |
| 16 | +# This is the name of the iverilog, vvp, and abc command. These may |
19 | 17 | # vary in different installations. |
20 | | -iverilog = "iverilog" |
21 | | -vvp = "vvp" |
22 | | - |
23 | | -list_file = open("blif.list") |
24 | | - |
25 | | -# The list file contains a list of test names. The first word in the |
26 | | -# line is the name of the test. |
27 | | -match_prog = re.compile(r"^([a-zA-Z0-9_.]+).*$") |
28 | | - |
29 | | -tests = [] |
30 | | -for line in list_file: |
31 | | - if line[0] == "#": |
32 | | - continue |
33 | | - match = match_prog.search(line) |
34 | | - if match: |
35 | | - tests.append(match.group(1)) |
36 | | - |
37 | | -list_file.close() |
38 | | - |
39 | | -def run_test(test): |
40 | | - global count_passed, count_failed |
41 | | - |
| 18 | +IVERILOG = "iverilog" |
| 19 | +VVP = "vvp" |
| 20 | +ABC = "berkeley-abc" |
| 21 | + |
| 22 | +def get_tests() -> list: |
| 23 | + '''Get the test names''' |
| 24 | + # The list file contains a list of test names. The first word in the |
| 25 | + # line is the name of the test. |
| 26 | + match_prog = re.compile(r"^([a-zA-Z0-9_.]+).*$") |
| 27 | + |
| 28 | + tests = [] |
| 29 | + with open("blif.list", encoding='ascii') as fd: |
| 30 | + for line in fd: |
| 31 | + if line[0] == "#": |
| 32 | + continue |
| 33 | + match = match_prog.search(line) |
| 34 | + if match: |
| 35 | + tests.append(match.group(1)) |
| 36 | + return tests |
| 37 | + |
| 38 | +def run_test(test_name: str) -> bool: |
| 39 | + '''Run each test using this routine. |
| 40 | + Returns True if the test passes.''' |
42 | 41 | # Assemble the paths for the test-bench and DUT. |
43 | | - dut = "blif/" + test + ".v" |
44 | | - tb = "blif/" + test + "_tb.v" |
| 42 | + dut = "blif/" + test_name + ".v" |
| 43 | + tb = "blif/" + test_name + "_tb.v" |
45 | 44 |
|
46 | | - redirect = "log/" + test + ".log 2>&1" |
| 45 | + redirect = "log/" + test_name + ".log 2>&1" |
47 | 46 |
|
48 | 47 | # Process the DUT into a .blif file |
49 | | - ivl_blif_cmd = iverilog + " -g2009 -tblif -otmp_blif.blif " + dut + " > " + redirect |
| 48 | + ivl_blif_cmd = IVERILOG + " -g2009 -tblif -otmp_blif.blif " + dut + " > " + redirect |
50 | 49 | rc = subprocess.call(ivl_blif_cmd, shell=True) |
51 | 50 |
|
52 | 51 | if rc == 0: |
53 | 52 | # Use ABC to convert the .blif file to Verilog |
54 | | - abc_cmd = "berkeley-abc -c 'read_blif tmp_blif.blif ; write_verilog tmp_blif.v' >> " + redirect |
55 | | - rc = subprocess.call(abc_cmd, shell=True); |
| 53 | + abc_cmd = ABC +" -c 'read_blif tmp_blif.blif ; write_verilog tmp_blif.v' >> " + redirect |
| 54 | + rc = subprocess.call(abc_cmd, shell=True) |
56 | 55 |
|
57 | 56 | if rc == 0: |
58 | 57 | # Compile |
59 | | - ivl_blif_tb_cmd = iverilog + " -g2009 -otmp_blif.vvp " + tb + " tmp_blif.v >> " + redirect |
| 58 | + ivl_blif_tb_cmd = IVERILOG + " -g2009 -otmp_blif.vvp " + tb + " tmp_blif.v >> " + redirect |
60 | 59 | rc = subprocess.call(ivl_blif_tb_cmd, shell=True) |
61 | 60 |
|
62 | 61 | if rc == 0: |
63 | 62 | # Now simulate to make sure the tranlation worked properly. |
64 | | - vvp_cmd = vvp + " tmp_blif.vvp" |
65 | | - output = subprocess.check_output(vvp_cmd, shell=True) |
66 | | - rc = 0 if output == "PASSED\n" else 1 |
67 | | - |
68 | | - if rc == 0: |
69 | | - print(test, "PASSED") |
70 | | - count_passed = count_passed + 1 |
71 | | - else: |
72 | | - print(test, "FAILED") |
73 | | - count_failed = count_failed + 1 |
| 63 | + vvp_cmd = VVP + " tmp_blif.vvp" |
| 64 | + output = subprocess.check_output(vvp_cmd, shell=True, text=True) |
| 65 | + echo_cmd = "echo " + output.rstrip() + " >> " + redirect |
| 66 | + rc = subprocess.call(echo_cmd, shell=True) |
74 | 67 |
|
75 | | - for tmp in ["tmp_blif.blif", "tmp_blif.v", "tmp_blif.vvp"]: |
| 68 | + for tmp in ["tmp_blif.blif", "tmp_blif.v", "tmp_blif.vvp", "abc.history"]: |
76 | 69 | if os.path.exists(tmp): |
77 | 70 | os.remove(tmp) |
78 | 71 |
|
79 | | -count_passed = 0 |
80 | | -count_failed = 0 |
81 | | - |
82 | | -for test in tests: |
83 | | - run_test(test) |
84 | | - |
85 | | -print() |
86 | | -print(count_passed, "tests passed,", count_failed, "tests failed.") |
| 72 | + return not (rc or output != "PASSED\n") |
| 73 | + |
| 74 | +def get_ivl_version() -> list: |
| 75 | + '''Get the iverilog version''' |
| 76 | + text = subprocess.check_output([IVERILOG, "-V"]) |
| 77 | + match = re.search(b'Icarus Verilog version ([0-9]+)\\.([0-9]+)', text) |
| 78 | + if not match: |
| 79 | + return None |
| 80 | + |
| 81 | + items = match.groups() |
| 82 | + return [str(items[0], 'ascii'), str(items[1], 'ascii')] |
| 83 | + |
| 84 | +def get_abc_version() -> list: |
| 85 | + '''Get the berkeley-abc version''' |
| 86 | + res = subprocess.run([ABC, "-h"], capture_output=True, check=False) |
| 87 | + match = re.search(b'UC Berkeley, ABC ([0-9]+)\\.([0-9]+)', res.stdout) |
| 88 | + if not match: |
| 89 | + return None |
| 90 | + |
| 91 | + items = match.groups() |
| 92 | + return [str(items[0], 'ascii'), str(items[1], 'ascii')] |
| 93 | + |
| 94 | +def run_tests(tests: list): |
| 95 | + '''Run all the tests in the test list''' |
| 96 | + ivl_ver = get_ivl_version() |
| 97 | + abc_ver = get_abc_version() |
| 98 | + # pylint: disable-next=consider-using-f-string |
| 99 | + print("Running blif tests for Icarus Verilog version: {ver}.{sver}".format(ver=ivl_ver[0], |
| 100 | + sver=ivl_ver[1])) |
| 101 | + # pylint: disable-next=consider-using-f-string |
| 102 | + print("Using berkely-abc version: {ver}.{sver}".format(ver=abc_ver[0], sver=abc_ver[1])) |
| 103 | + print("=" * 50) |
| 104 | + |
| 105 | + count_passed = 0 |
| 106 | + count_failed = 0 |
| 107 | + |
| 108 | + width = max(len(name) for name in tests) |
| 109 | + |
| 110 | + for test in tests: |
| 111 | + passed = run_test(test) |
| 112 | + if passed: |
| 113 | + res = "Passed" |
| 114 | + count_passed += 1 |
| 115 | + else: |
| 116 | + res = "Failed" |
| 117 | + count_failed += 1 |
| 118 | + # pylint: disable-next=consider-using-f-string |
| 119 | + print("{name:>{width}}: {res}.".format(name=test, width=width, res=res)) |
| 120 | + |
| 121 | + print("=" * 50) |
| 122 | + # pylint: disable-next=consider-using-f-string |
| 123 | + print("Tests results: Passed {passed}, Failed {failed}".format(passed=count_passed, \ |
| 124 | + failed=count_failed)) |
| 125 | + |
| 126 | +if __name__ == "__main__": |
| 127 | + run_tests(get_tests()) |
0 commit comments