-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Add `btor2aig_yw.py` to wrap btor2aiger calls, splitting the symbol map into a `.aim` file and building (and approximation of) the `.ywa` file. - Currently not tracking asserts/assumes in the `.ywa`, and yosys-witness isn't the biggest fan of the btor2aiger style of unitialised latches. As such, the latches are declared but the `.yw` output doesn't do anything with them so it's incomplete. But the vcd output seems fine (for `vcd_sim=on|off`). - Add a try/except to catch property matching with an incomplete property list. - Add `-x` flag to `write_btor` call since aiw2yw gets confused without them. - Includes some TODO reminders for me to fix things, but as far as I can tell it is working.
- Loading branch information
1 parent
5483df5
commit ed8f6e0
Showing
3 changed files
with
131 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
from __future__ import annotations | ||
|
||
import argparse | ||
import asyncio | ||
import json | ||
import re | ||
from pathlib import Path | ||
|
||
def arg_parser(): | ||
parser = argparse.ArgumentParser() | ||
|
||
parser.add_argument( | ||
"btor_file", | ||
type=Path | ||
) | ||
|
||
parser.add_argument( | ||
"-d", "--dest", | ||
dest="dest", | ||
required=False, | ||
type=Path | ||
) | ||
|
||
return parser | ||
|
||
async def main() -> None: | ||
args = arg_parser().parse_args() | ||
|
||
work_dir: Path = args.dest or Path() | ||
|
||
proc = await asyncio.create_subprocess_shell( | ||
f"btor2aiger {args.btor_file}", | ||
stdout=asyncio.subprocess.PIPE | ||
) | ||
|
||
data = True | ||
|
||
# output aig | ||
aig_file = work_dir / "design_aiger.aig" | ||
aigf = open(aig_file, mode="wb") | ||
data = await proc.stdout.readline() | ||
aig_header = data.decode() | ||
while data: | ||
aigf.write(data) | ||
data = await proc.stdout.readline() | ||
if b'i0' in data: | ||
break | ||
end_pos = data.find(b'i0') | ||
aigf.write(data[:end_pos]) | ||
aigf.close() | ||
|
||
# initialize yw aiger map | ||
aig_MILOA = aig_header.split() | ||
ywa = { | ||
"version": "Yosys Witness Aiger map", | ||
"generator": "btor2aig_yw.py", | ||
"latch_count": int(aig_MILOA[3]), | ||
"input_count": int(aig_MILOA[2]), | ||
"clocks": [], | ||
"inputs": [], | ||
"seqs": [], | ||
"inits": [], | ||
"latches": [], | ||
"asserts": [], | ||
"assumes": [] | ||
} | ||
|
||
# output aim & build ywa | ||
aim_file = work_dir / "design_aiger.aim" | ||
aimf = open(aim_file, mode="w") | ||
data = data[end_pos:] | ||
while data: | ||
# decode data | ||
string = data.decode().rstrip() | ||
pattern = r"(?P<type>[cil])(?P<input>\d+) (?P<path>.*?)(\[(?P<offset>\d+)\])?$" | ||
m = re.match(pattern, string) | ||
md = m.groupdict() | ||
if md['type'] == 'i': | ||
md['type'] = 'input' | ||
elif md['type'] == 'c': | ||
md['type'] = 'clk' | ||
elif md['type'] == 'l': | ||
md['type'] = 'latch' | ||
else: | ||
raise ValueError(f"Unknown type identifier {md['type']!r}") | ||
for k in ['input', 'offset']: | ||
if md[k]: | ||
md[k] = int(md[k]) | ||
else: | ||
md[k] = 0 | ||
|
||
# output to aim | ||
if md['type'] in ['input', 'latch']: | ||
print("{type} {input} {offset} {path}".format(**md), file=aimf) | ||
|
||
# update ywa | ||
md_type = md.pop('type') | ||
if md['path'][0] == '$': | ||
md['path'] = [md['path']] | ||
else: | ||
md['path'] = [f"\\{s}" for s in md['path'].replace('[','.[').split('.')] | ||
if md_type == 'clk': | ||
md['edge'] = "posedge" # always? | ||
ywa['clocks'].append(md) | ||
elif md_type == 'input': | ||
ywa['inputs'].append(md) | ||
elif md_type == 'latch': | ||
ywa['latches'].append(md) | ||
|
||
# get next line | ||
data = await proc.stdout.readline() | ||
aimf.close() | ||
|
||
with open(work_dir / "design_aiger.ywa", mode="w") as f: | ||
json.dump(ywa, f, indent=2) | ||
|
||
if __name__ == "__main__": | ||
asyncio.run(main()) |