|
| 1 | +#!/usr/bin/env python3 |
| 2 | + |
| 3 | +# This file is part of the replication artifact for |
| 4 | +# difference verification with conditions: |
| 5 | +# https://gitlab.com/sosy-lab/research/data/difference-data |
| 6 | +# |
| 7 | +# SPDX-FileCopyrightText: 2020 Dirk Beyer <https://sosy-lab.org> |
| 8 | +# |
| 9 | +# SPDX-License-Identifier: Apache-2.0 |
| 10 | + |
| 11 | +import argparse |
| 12 | +from pathlib import Path |
| 13 | +import yaml |
| 14 | +import sys |
| 15 | + |
| 16 | + |
| 17 | +class TaskError(Exception): |
| 18 | + pass |
| 19 | + |
| 20 | + |
| 21 | +def get_tasks(benchmark_dir: Path, glob_pattern): |
| 22 | + for file1 in benchmark_dir.glob(glob_pattern): |
| 23 | + input_file = _get_input_file(file1) |
| 24 | + try: |
| 25 | + verdict = _get_verdict(file1) |
| 26 | + except TaskError: |
| 27 | + print( |
| 28 | + "INFO: Ignoring %s because of missing verdict" % str(file1), |
| 29 | + file=sys.stderr, |
| 30 | + ) |
| 31 | + continue |
| 32 | + else: |
| 33 | + yield input_file, verdict |
| 34 | + |
| 35 | + |
| 36 | +def _get_input_file(yml_task_def): |
| 37 | + with yml_task_def.open() as inp: |
| 38 | + yml_content = yaml.safe_load(inp) |
| 39 | + return yml_task_def.parent / Path(yml_content["input_files"]) |
| 40 | + |
| 41 | + |
| 42 | +def _get_verdict(yml_task_def): |
| 43 | + with yml_task_def.open() as inp: |
| 44 | + yml_content = yaml.safe_load(inp) |
| 45 | + try: |
| 46 | + return next( |
| 47 | + p["expected_verdict"] |
| 48 | + for p in yml_content["properties"] |
| 49 | + if p["property_file"].endswith("unreach-call.prp") |
| 50 | + ) |
| 51 | + except StopIteration: |
| 52 | + raise TaskError() |
| 53 | + |
| 54 | + |
| 55 | +def _create_combo( |
| 56 | + file1: Path, file2: Path, replacement1=None, replacement2=None |
| 57 | +) -> str: |
| 58 | + if replacement1: |
| 59 | + repl1 = replacement1 |
| 60 | + else: |
| 61 | + repl1 = lambda x: x |
| 62 | + if replacement2: |
| 63 | + repl2 = replacement2 |
| 64 | + else: |
| 65 | + repl2 = lambda x: x |
| 66 | + with file1.open() as inp: |
| 67 | + content1 = "".join( |
| 68 | + repl1(line.replace("main(", "main1(")) for line in inp.readlines() |
| 69 | + ) |
| 70 | + with file2.open() as inp: |
| 71 | + content2 = "".join( |
| 72 | + repl2(line.replace("main(", "main2(")) |
| 73 | + for line in inp.readlines() |
| 74 | + if not line.startswith("extern ") |
| 75 | + and not line.startswith("void reach_error") |
| 76 | + ) |
| 77 | + |
| 78 | + additional_defs = """extern unsigned int __VERIFIER_nondet_uint(); |
| 79 | +extern char __VERIFIER_nondet_char(); |
| 80 | +extern int __VERIFIER_nondet_int(); |
| 81 | +extern long __VERIFIER_nondet_long(); |
| 82 | +extern unsigned long __VERIFIER_nondet_ulong(); |
| 83 | +extern float __VERIFIER_nondet_float(); |
| 84 | +extern void exit(int); |
| 85 | +""" |
| 86 | + |
| 87 | + return ( |
| 88 | + additional_defs |
| 89 | + + content1 |
| 90 | + + content2 |
| 91 | + + """int main() |
| 92 | +{ |
| 93 | + if(__VERIFIER_nondet_int()) |
| 94 | + main1(); |
| 95 | + else |
| 96 | + main2(); |
| 97 | +}""" |
| 98 | + ) |
| 99 | + |
| 100 | + |
| 101 | +def _get_yml_content(verdict1, verdict2, input_file: str): |
| 102 | + verdict = verdict1 == verdict2 == True |
| 103 | + return """format_version: '1.0' |
| 104 | +
|
| 105 | +input_files: '%s' |
| 106 | +
|
| 107 | +properties: |
| 108 | + - property_file: ../properties/unreach-call.prp |
| 109 | + expected_verdict: %s""" % ( |
| 110 | + input_file, |
| 111 | + verdict, |
| 112 | + ) |
| 113 | + |
| 114 | + |
| 115 | +def create_combos( |
| 116 | + pattern1, pattern2, replacement1=None, replacement2=None, output_dir=None |
| 117 | +): |
| 118 | + tasks1 = list(get_tasks(args.benchmark_dir, pattern1)) |
| 119 | + tasks2 = list(get_tasks(args.benchmark_dir, pattern2)) |
| 120 | + |
| 121 | + output_dir.mkdir(parents=True, exist_ok=True) |
| 122 | + |
| 123 | + for file1, verdict1 in tasks1: |
| 124 | + for file2, verdict2 in tasks2: |
| 125 | + assert isinstance(verdict1, bool) |
| 126 | + assert isinstance(verdict2, bool) |
| 127 | + if verdict1 == verdict2 == False: |
| 128 | + continue |
| 129 | + basename = file1.name[:-2] + "+" + file2.name |
| 130 | + c_file = output_dir / Path(basename) |
| 131 | + c_content = _create_combo(file1, file2, replacement1, replacement2) |
| 132 | + yml_content = _get_yml_content(verdict1, verdict2, c_file.name) |
| 133 | + yml_file = output_dir / Path(basename[:-2] + ".yml") |
| 134 | + |
| 135 | + with c_file.open("w") as outp: |
| 136 | + outp.write(c_content) |
| 137 | + with yml_file.open("w") as outp: |
| 138 | + outp.write(yml_content) |
| 139 | + |
| 140 | + |
| 141 | +def _systemc_replacements1(line) -> str: |
| 142 | + return ( |
| 143 | + line.replace("error(", "error1(") |
| 144 | + .replace("init_threads(", "init_threads1(") |
| 145 | + .replace("exists_runnable_thread(", "exists_runnable_thread1(") |
| 146 | + .replace("eval(", "eval1(") |
| 147 | + .replace("init_model(", "init_model1(") |
| 148 | + .replace("stop_simulation(", "stop_simulation1(") |
| 149 | + .replace("start_simulation(", "start_simulation1(") |
| 150 | + .replace("reach_error1(", "reach_error(") |
| 151 | + .replace("update_channels(", "update_channels1(") |
| 152 | + .replace("fire_delta_events(", "fire_delta_events1(") |
| 153 | + .replace("reset_delta_events(", "reset_delta_events1(") |
| 154 | + .replace("activate_threads(", "activate_threads1(") |
| 155 | + .replace("fire_time_events(", "fire_time_events1(") |
| 156 | + .replace("reset_time_events(", "reset_time_events1(") |
| 157 | + ) |
| 158 | + |
| 159 | + |
| 160 | +def _systemc_replacements2(line) -> str: |
| 161 | + return ( |
| 162 | + line.replace("error(", "error2(") |
| 163 | + .replace("init_threads(", "init_threads2(") |
| 164 | + .replace("exists_runnable_thread(", "exists_runnable_thread2(") |
| 165 | + .replace("eval(", "eval2(") |
| 166 | + .replace("init_model(", "init_model2(") |
| 167 | + .replace("stop_simulation(", "stop_simulation2(") |
| 168 | + .replace("start_simulation(", "start_simulation2(") |
| 169 | + .replace("reach_error2(", "reach_error(") |
| 170 | + .replace("update_channels(", "update_channels2(") |
| 171 | + .replace("fire_delta_events(", "fire_delta_events2(") |
| 172 | + .replace("reset_delta_events(", "reset_delta_events2(") |
| 173 | + .replace("activate_threads(", "activate_threads2(") |
| 174 | + .replace("fire_time_events(", "fire_time_events2(") |
| 175 | + .replace("reset_time_events(", "reset_time_events2(") |
| 176 | + ) |
| 177 | + |
| 178 | + |
| 179 | +if __name__ == "__main__": |
| 180 | + parser = argparse.ArgumentParser() |
| 181 | + parser.add_argument( |
| 182 | + "--benchmark-dir", required=True, help="sv-benchmarks directory" |
| 183 | + ) |
| 184 | + parser.add_argument( |
| 185 | + "--output-dir", required=True, help="output directory for created files" |
| 186 | + ) |
| 187 | + |
| 188 | + args = parser.parse_args() |
| 189 | + args.benchmark_dir = Path(args.benchmark_dir) |
| 190 | + args.output_dir = Path(args.output_dir) |
| 191 | + |
| 192 | + create_combos( |
| 193 | + "c/eca-rers2012/Problem05_label4*.yml", |
| 194 | + "c/systemc/token_ring*.yml", |
| 195 | + output_dir=args.output_dir, |
| 196 | + ) |
| 197 | + create_combos( |
| 198 | + "c/bitvector/gcd_*.yml", |
| 199 | + "c/floats-cdfpl/newton_*.yml", |
| 200 | + output_dir=args.output_dir, |
| 201 | + ) |
| 202 | + create_combos( |
| 203 | + "c/seq-mthreaded/pals_lcr.*.yml", |
| 204 | + "c/eca-rers2012/Problem12_label0*.yml", |
| 205 | + output_dir=args.output_dir, |
| 206 | + ) |
| 207 | + create_combos( |
| 208 | + "c/floats-cdfpl/square*.yml", |
| 209 | + "c/bitvector/soft_float_*.yml", |
| 210 | + output_dir=args.output_dir, |
| 211 | + ) |
| 212 | + create_combos( |
| 213 | + "c/systemc/pc_sfifo*.yml", |
| 214 | + "c/systemc/token_ring*.yml", |
| 215 | + replacement1=_systemc_replacements1, |
| 216 | + replacement2=_systemc_replacements2, |
| 217 | + output_dir=args.output_dir, |
| 218 | + ) |
0 commit comments