Skip to content

Commit d2c3cf3

Browse files
committed
Add regression testing script and simple tests
Larger test are not kept in the repository and are downloaded externally.
1 parent f4cf719 commit d2c3cf3

File tree

7 files changed

+2478
-0
lines changed

7 files changed

+2478
-0
lines changed

scripts/reg_test.py

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
import sys
5+
import argparse
6+
import tempfile
7+
import tarfile
8+
import glob
9+
import urllib.request
10+
import math
11+
import subprocess
12+
import shutil
13+
14+
TATUM_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
15+
16+
17+
tests = {
18+
'basic': [os.path.join(TATUM_ROOT, 'test', 'basic')],
19+
'mcnc20': ["http://www.eecg.utoronto.ca/~kmurray/tatum/golden_results/mcnc20_tatum_golden.tar.gz"],
20+
#'vtr': [
21+
22+
#],
23+
#'titan_other': [
24+
25+
#],
26+
#'titan': [
27+
28+
#],
29+
#'tau15_unit_delay': [
30+
31+
#],
32+
}
33+
34+
def parse_args():
35+
parser = argparse.ArgumentParser()
36+
37+
parser.add_argument("test_names",
38+
help="Test to run",
39+
nargs='+',
40+
choices=tests.keys())
41+
42+
parser.add_argument("--tatum_test_exec",
43+
help="Path to tatum test executable (Default: from path)",
44+
default=None)
45+
46+
parser.add_argument("--tatum_nworkers",
47+
help="How many parallel workers each tatum invokation should use. (Default: tatum default)",
48+
type=int,
49+
default=None)
50+
51+
parser.add_argument("--tatum_nserial",
52+
help="How serial runs tatum should perform per test. (Default: %(default))",
53+
type=int,
54+
default=3)
55+
56+
parser.add_argument("--tatum_nparallel",
57+
help="How parallel runs tatum should perform per test. (Default: %(default))",
58+
type=int,
59+
default=6)
60+
61+
parser.add_argument("--debug",
62+
help="Show directory path and don't clean-up",
63+
default=False,
64+
action='store_true')
65+
66+
return parser.parse_args()
67+
68+
def main():
69+
args = parse_args()
70+
71+
if args.tatum_test_exec:
72+
args.tatum_test_exec = os.path.abspath(args.tatum_test_exec)
73+
else:
74+
args.tatum_test_exec = "tatum_test" #From path
75+
76+
num_failures = 0
77+
for test_name in args.test_names:
78+
for test_url in tests[test_name]:
79+
work_dir = tempfile.mkdtemp(prefix="tatum_reg_test")
80+
try:
81+
test_files = download_extract_test(args, work_dir, test_url)
82+
num_failures += run_test(args, work_dir, test_name, test_files)
83+
finally:
84+
if not args.debug:
85+
shutil.rmtree(work_dir)
86+
else:
87+
print(work_dir)
88+
89+
sys.exit(num_failures)
90+
91+
def run_test(args, work_dir, test_name, test_files):
92+
num_failed = 0
93+
94+
os.chdir(work_dir)
95+
96+
print("Running {} ({} tests)".format(test_name, len(test_files)))
97+
for test_file in test_files:
98+
99+
num_failed += run_single_test(args, work_dir, test_file)
100+
101+
return num_failed;
102+
103+
def run_single_test(args, work_dir, test_file):
104+
num_failed = 0
105+
106+
benchmark_name, ext = os.path.splitext(os.path.basename(test_file))
107+
108+
log = benchmark_name + '.log'
109+
110+
cmd = []
111+
cmd += [args.tatum_test_exec]
112+
cmd += ['--verify', "1"]
113+
114+
cmd += ['--num_serial', str(args.tatum_nserial)]
115+
cmd += ['--num_parallel', str(args.tatum_nparallel)]
116+
117+
if args.tatum_nworkers:
118+
cmd += ['--num_workers', str(args.tatum_nworkers)]
119+
120+
cmd += [test_file]
121+
122+
print(" {}".format(test_file), end='')
123+
124+
if args.debug:
125+
print()
126+
print(" cmd: {} log: {}".format(' '.join(cmd), log))
127+
128+
with open(log, 'w') as outfile:
129+
retcode = subprocess.call(cmd, stdout=outfile, stderr=outfile)
130+
131+
if retcode == 0:
132+
print(" PASSED")
133+
else:
134+
num_failed += 1
135+
print(" FAILED")
136+
137+
#Print log if failed
138+
with open(log, 'r') as log_file:
139+
for line in log:
140+
print("\t{}".format(line), end='')
141+
142+
return num_failed
143+
144+
def download_extract_test(args, work_dir, test_url):
145+
146+
test_files = []
147+
148+
if '.tar' in test_url:
149+
#A tar file of benchmark files
150+
benchmark_tar = os.path.join(work_dir, os.path.basename(test_url))
151+
152+
get_url(test_url, benchmark_tar)
153+
154+
with tarfile.TarFile.open(benchmark_tar, mode="r|*") as tar_file:
155+
tar_file.extractall(path=work_dir)
156+
157+
test_files += glob.glob("{}/*.tatum".format(work_dir))
158+
test_files += glob.glob("{}/*/*.tatum".format(work_dir))
159+
else:
160+
#A directory of benchmark files
161+
162+
test_files += glob.glob("{}/*.tatum".format(test_url))
163+
test_files += glob.glob("{}/*/*.tatum".format(test_url))
164+
165+
return test_files
166+
167+
def get_url(url, filename):
168+
if '://' in url:
169+
download_url(url, filename)
170+
else:
171+
shutl.copytree(url, filename)
172+
173+
def download_url(url, filename):
174+
"""
175+
Downloads the specifed url to filename
176+
"""
177+
print("Downloading {} to {}".format(url, filename))
178+
urllib.request.urlretrieve(url, filename, reporthook=download_progress_callback)
179+
180+
def download_progress_callback(block_num, block_size, expected_size):
181+
"""
182+
Callback for urllib.urlretrieve which prints a dot for every percent of a file downloaded
183+
"""
184+
total_blocks = int(math.ceil(expected_size / block_size))
185+
progress_increment = int(math.ceil(total_blocks / 100))
186+
187+
if block_num % progress_increment == 0:
188+
print(".", end='', flush=False)
189+
if block_num*block_size >= expected_size:
190+
print("")
191+
192+
if __name__ == "__main__":
193+
main()

test/basic/simple_comb.blif

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.model top
2+
.inputs i_a i_b
3+
.outputs o_c
4+
5+
#Combinational logic
6+
.names i_a i_b o_c
7+
11 1
8+
9+
.end

test/basic/simple_comb.tatum

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
timing_graph:
2+
node: 0 \
3+
type: SOURCE \
4+
in_edges: \
5+
out_edges: 0
6+
node: 1 \
7+
type: SOURCE \
8+
in_edges: \
9+
out_edges: 1
10+
node: 2 \
11+
type: IPIN \
12+
in_edges: 0 \
13+
out_edges: 2
14+
node: 3 \
15+
type: IPIN \
16+
in_edges: 1 \
17+
out_edges: 3
18+
node: 4 \
19+
type: OPIN \
20+
in_edges: 2 3 \
21+
out_edges: 4
22+
node: 5 \
23+
type: SINK \
24+
in_edges: 4 \
25+
out_edges:
26+
edge: 0 \
27+
type: INTERCONNECT \
28+
src_node: 0 \
29+
sink_node: 2 \
30+
disabled: false
31+
edge: 1 \
32+
type: INTERCONNECT \
33+
src_node: 1 \
34+
sink_node: 3 \
35+
disabled: false
36+
edge: 2 \
37+
type: PRIMITIVE_COMBINATIONAL \
38+
src_node: 2 \
39+
sink_node: 4 \
40+
disabled: false
41+
edge: 3 \
42+
type: PRIMITIVE_COMBINATIONAL \
43+
src_node: 3 \
44+
sink_node: 4 \
45+
disabled: false
46+
edge: 4 \
47+
type: INTERCONNECT \
48+
src_node: 4 \
49+
sink_node: 5 \
50+
disabled: false
51+
52+
timing_constraints:
53+
type: CLOCK domain: 0 name: "virtual_io_clock"
54+
type: MAX_INPUT_CONSTRAINT node: 0 domain: 0 constraint: 0
55+
type: MAX_INPUT_CONSTRAINT node: 1 domain: 0 constraint: 0
56+
type: MIN_INPUT_CONSTRAINT node: 0 domain: 0 constraint: 0
57+
type: MIN_INPUT_CONSTRAINT node: 1 domain: 0 constraint: 0
58+
type: MAX_OUTPUT_CONSTRAINT node: 5 domain: 0 constraint: 0
59+
type: MIN_OUTPUT_CONSTRAINT node: 5 domain: 0 constraint: 0
60+
type: SETUP_CONSTRAINT launch_domain: 0 capture_domain: 0 constraint: 0
61+
type: HOLD_CONSTRAINT launch_domain: 0 capture_domain: 0 constraint: 0
62+
63+
delay_model:
64+
edge: 0 min_delay: 2.60726e-10 max_delay: 2.86956e-10
65+
edge: 1 min_delay: 2.6161e-10 max_delay: 2.8784e-10
66+
edge: 2 min_delay: 1.74e-10 max_delay: 2.35e-10
67+
edge: 3 min_delay: 1.74e-10 max_delay: 2.35e-10
68+
edge: 4 min_delay: 2.65659e-10 max_delay: 2.67289e-10
69+
70+
analysis_result:
71+
type: SETUP_DATA_ARRIVAL node: 0 launch_domain: 0 capture_domain: -1 time: 0
72+
type: SETUP_DATA_ARRIVAL node: 1 launch_domain: 0 capture_domain: -1 time: 0
73+
type: SETUP_DATA_ARRIVAL node: 2 launch_domain: 0 capture_domain: -1 time: 2.86956e-10
74+
type: SETUP_DATA_ARRIVAL node: 3 launch_domain: 0 capture_domain: -1 time: 2.8784e-10
75+
type: SETUP_DATA_ARRIVAL node: 4 launch_domain: 0 capture_domain: -1 time: 5.2284e-10
76+
type: SETUP_DATA_ARRIVAL node: 5 launch_domain: 0 capture_domain: -1 time: 7.90129e-10
77+
type: SETUP_DATA_REQUIRED node: 0 launch_domain: 0 capture_domain: 0 time: -7.89245e-10
78+
type: SETUP_DATA_REQUIRED node: 1 launch_domain: 0 capture_domain: 0 time: -7.90129e-10
79+
type: SETUP_DATA_REQUIRED node: 2 launch_domain: 0 capture_domain: 0 time: -5.02289e-10
80+
type: SETUP_DATA_REQUIRED node: 3 launch_domain: 0 capture_domain: 0 time: -5.02289e-10
81+
type: SETUP_DATA_REQUIRED node: 4 launch_domain: 0 capture_domain: 0 time: -2.67289e-10
82+
type: SETUP_DATA_REQUIRED node: 5 launch_domain: 0 capture_domain: 0 time: 0
83+
type: SETUP_SLACK edge: 0 launch_domain: 0 capture_domain: 0 slack: -7.89245e-10
84+
type: SETUP_SLACK edge: 1 launch_domain: 0 capture_domain: 0 slack: -7.90129e-10
85+
type: SETUP_SLACK edge: 2 launch_domain: 0 capture_domain: 0 slack: -7.89245e-10
86+
type: SETUP_SLACK edge: 3 launch_domain: 0 capture_domain: 0 slack: -7.90129e-10
87+
type: SETUP_SLACK edge: 4 launch_domain: 0 capture_domain: 0 slack: -7.90129e-10
88+
type: SETUP_SLACK node: 0 launch_domain: 0 capture_domain: 0 slack: -7.89245e-10
89+
type: SETUP_SLACK node: 1 launch_domain: 0 capture_domain: 0 slack: -7.90129e-10
90+
type: SETUP_SLACK node: 2 launch_domain: 0 capture_domain: 0 slack: -7.89245e-10
91+
type: SETUP_SLACK node: 3 launch_domain: 0 capture_domain: 0 slack: -7.90129e-10
92+
type: SETUP_SLACK node: 4 launch_domain: 0 capture_domain: 0 slack: -7.90129e-10
93+
type: SETUP_SLACK node: 5 launch_domain: 0 capture_domain: 0 slack: -7.90129e-10
94+
type: HOLD_DATA_ARRIVAL node: 0 launch_domain: 0 capture_domain: -1 time: 0
95+
type: HOLD_DATA_ARRIVAL node: 1 launch_domain: 0 capture_domain: -1 time: 0
96+
type: HOLD_DATA_ARRIVAL node: 2 launch_domain: 0 capture_domain: -1 time: 2.60726e-10
97+
type: HOLD_DATA_ARRIVAL node: 3 launch_domain: 0 capture_domain: -1 time: 2.6161e-10
98+
type: HOLD_DATA_ARRIVAL node: 4 launch_domain: 0 capture_domain: -1 time: 4.34726e-10
99+
type: HOLD_DATA_ARRIVAL node: 5 launch_domain: 0 capture_domain: -1 time: 7.00385e-10
100+
type: HOLD_DATA_REQUIRED node: 0 launch_domain: 0 capture_domain: 0 time: -7.00385e-10
101+
type: HOLD_DATA_REQUIRED node: 1 launch_domain: 0 capture_domain: 0 time: -7.01269e-10
102+
type: HOLD_DATA_REQUIRED node: 2 launch_domain: 0 capture_domain: 0 time: -4.39659e-10
103+
type: HOLD_DATA_REQUIRED node: 3 launch_domain: 0 capture_domain: 0 time: -4.39659e-10
104+
type: HOLD_DATA_REQUIRED node: 4 launch_domain: 0 capture_domain: 0 time: -2.65659e-10
105+
type: HOLD_DATA_REQUIRED node: 5 launch_domain: 0 capture_domain: 0 time: 0
106+
type: HOLD_SLACK edge: 0 launch_domain: 0 capture_domain: 0 slack: -7.00385e-10
107+
type: HOLD_SLACK edge: 1 launch_domain: 0 capture_domain: 0 slack: -7.01269e-10
108+
type: HOLD_SLACK edge: 2 launch_domain: 0 capture_domain: 0 slack: -7.00385e-10
109+
type: HOLD_SLACK edge: 3 launch_domain: 0 capture_domain: 0 slack: -7.01269e-10
110+
type: HOLD_SLACK edge: 4 launch_domain: 0 capture_domain: 0 slack: -7.00385e-10
111+
type: HOLD_SLACK node: 0 launch_domain: 0 capture_domain: 0 slack: 7.00385e-10
112+
type: HOLD_SLACK node: 1 launch_domain: 0 capture_domain: 0 slack: 7.01269e-10
113+
type: HOLD_SLACK node: 2 launch_domain: 0 capture_domain: 0 slack: 7.00385e-10
114+
type: HOLD_SLACK node: 3 launch_domain: 0 capture_domain: 0 slack: 7.01269e-10
115+
type: HOLD_SLACK node: 4 launch_domain: 0 capture_domain: 0 slack: 7.00385e-10
116+
type: HOLD_SLACK node: 5 launch_domain: 0 capture_domain: 0 slack: 7.00385e-10
117+

test/basic/simple_multiclock.blif

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
.model top
2+
.inputs i_a i_b i_c clka clkb clkc clkd
3+
.outputs o_d o_e o_f o_g o_h o_i
4+
5+
#Input logic
6+
.names i_a i_b w_d
7+
11 1
8+
9+
#Input latches
10+
.latch i_a l_a re clka 0
11+
.latch i_b l_b re clkb 0
12+
.latch i_c l_c re clkc 0
13+
.latch w_d l_d re clkd 0
14+
15+
#Internal logic
16+
.names l_a l_b l_c l_d w_and
17+
1111 1
18+
19+
#Output latches
20+
.latch w_and l_e re clka 0
21+
.latch w_and l_f re clkb 0
22+
.latch w_and l_g re clkc 0
23+
.latch w_and l_h re clkd 0
24+
25+
#Output logic
26+
.names w_d o_d
27+
1 1
28+
29+
.names l_e o_e
30+
1 1
31+
32+
.names l_f o_f
33+
1 1
34+
35+
.names l_g o_g
36+
1 1
37+
38+
.names l_h o_h
39+
1 1
40+
41+
.names w_d l_e l_f l_g l_h o_i
42+
11111 1
43+
44+
.end

0 commit comments

Comments
 (0)