def assert_formal(spec, mode="bmc", depth=1): functions = [] test_class = None caller_path = "" stack = inspect.stack() for frame in stack[1:]: if "unittest" in frame.filename: filename = "__".join(reversed(functions)) if test_class: filename = f'{test_class}__{filename}' break functions.append(frame.function) try: test_class = frame.frame.f_locals['self'].__class__.__name__ except: pass caller_path = frame.filename target_dir = Path(caller_path).parent / ".sim_results" target_dir.mkdir(exist_ok=True) if (target_dir / filename).exists(): rmtree(target_dir / filename) if mode == "hybrid": # A mix of BMC and k-induction, as per personal communication with Claire Wolf. script = "setattr -unset init w:* a:nmigen.sample_reg %d" mode = "bmc" else: script = "" config = textwrap.dedent("""\ [options] mode {mode} depth {depth} wait on [engines] smtbmc [script] read_ilang top.il prep {script} [file top.il] {rtlil} """).format(mode=mode, depth=depth, script=script, rtlil=rtlil.convert(Fragment.get(spec, platform=FormalPlatform))) with subprocess.Popen([require_tool("sby"), "-f", "-d", filename], cwd=str(target_dir), universal_newlines=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE) as proc: stdout, stderr = proc.communicate(config) if proc.returncode != 0: assert False, "Formal verification failed:\n" + stdout + "\n\n" + f"vcd: {str(target_dir / filename)}/engine_0/trace.vcd"
def assertFormal(self, spec, mode="bmc", depth=1): stack = traceback.extract_stack() for frame in reversed(stack): if os.path.dirname(__file__) not in frame.filename: break caller = frame spec_root, _ = os.path.splitext(caller.filename) spec_dir = os.path.dirname(spec_root) spec_name = "{}_{}".format( os.path.basename(spec_root).replace("test_", "spec_"), caller.name.replace("test_", "")) # The sby -f switch seems not fully functional when sby is reading from stdin. if os.path.exists(os.path.join(spec_dir, spec_name)): shutil.rmtree(os.path.join(spec_dir, spec_name)) if mode == "hybrid": # A mix of BMC and k-induction, as per personal communication with Claire Wolf. script = "setattr -unset init w:* a:nmigen.sample_reg %d" mode = "bmc" else: script = "" config = textwrap.dedent("""\ [options] mode {mode} depth {depth} wait on [engines] smtbmc [script] read_ilang top.il prep {script} [file top.il] {rtlil} """).format(mode=mode, depth=depth, script=script, rtlil=rtlil.convert(Fragment.get(spec, platform="formal"))) with subprocess.Popen([require_tool("sby"), "-f", "-d", spec_name], cwd=spec_dir, env={ **os.environ, "PYTHONWARNINGS": "ignore" }, universal_newlines=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE) as proc: stdout, stderr = proc.communicate(config) if proc.returncode != 0: self.fail("Formal verification failed:\n" + stdout)
def assertFormal(self, spec, mode="bmc", depth=1): """ mode: bmc, prove """ caller, *_ = traceback.extract_stack(limit=2) spec_root, _ = os.path.splitext(caller.filename) spec_dir = os.path.dirname(spec_root) spec_name = "{}_{}".format( os.path.basename(spec_root).replace("test_", "spec_"), caller.name.replace("test_", "")) # The sby -f switch seems not fully functional when sby is reading from stdin. if os.path.exists(os.path.join(spec_dir, spec_name)): shutil.rmtree(os.path.join(spec_dir, spec_name)) config = textwrap.dedent("""\ [options] mode {mode} depth {depth} wait on [engines] smtbmc [script] read_ilang top.il prep [file top.il] {rtlil} """).format(mode=mode, depth=depth, rtlil=rtlil.convert(Fragment.get(spec, platform="formal"))) f = open(os.path.join(spec_dir, spec_name + '.script'), "w") f.write(config) f.close() with subprocess.Popen([require_tool("sby"), "-f", "-d", spec_name], cwd=spec_dir, universal_newlines=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE) as proc: stdout, stderr = proc.communicate(config) if proc.returncode != 0: self.fail("Formal verification failed:\n" + stdout)
def synth(core, ports): plat = EmptyPlatform() frag = Fragment.get(core, plat) rtlil_text = rtlil.convert(frag, ports=ports) yosys_cmd = '' with tempfile.TemporaryDirectory() as temp_dir: with open(temp_dir + '/top.il', 'w') as f: f.write(rtlil_text) for file_name, content in plat.extra_files.items(): with open(temp_dir + '/' + file_name, 'wb') as f: f.write(content) yosys_cmd += "read_verilog {}\n".format(file_name) yosys_cmd += 'read_ilang {}\n'.format('top.il') yosys_cmd += 'synth_xilinx -top top\n' with open(temp_dir + '/top.ys', 'w') as f: f.write(yosys_cmd) subprocess.check_call([require_tool("yosys"), 'top.ys'], cwd=temp_dir)