| #!/usr/bin/env python3 |
| |
| import json |
| import os |
| import pathlib |
| import pprint |
| import subprocess |
| import sys |
| |
| __dir__ = os.path.dirname(os.path.abspath(__file__)) |
| sys.path.append(os.path.abspath(os.path.join(__dir__, ".."))) |
| |
| def main(pdk_path, version): |
| pr_path = pathlib.Path(os.path.join(pdk_path, "libraries", "sky130_fd_pr", version)) |
| |
| devices = [] |
| with open(os.path.join(__dir__, 'devices.txt')) as f: |
| for l in f: |
| if '#' in l: |
| l = l[:l.index('#')] |
| l = l.strip() |
| if not l: |
| continue |
| |
| bits = l.split() |
| devices.append(bits[0]) |
| |
| print() |
| print("Devices:") |
| print('-'*75) |
| pprint.pprint(devices) |
| print('-'*75) |
| |
| print() |
| print("Removing previous runs:") |
| print('-'*75) |
| for f in pr_path.rglob("*_results.json"): |
| f = os.path.abspath(f) |
| print(str(f)) |
| os.unlink(f) |
| print('-'*75) |
| |
| with subprocess.Popen([ |
| 'parallel', '-v', |
| os.path.join(__dir__, 'run_spice_tests_new.py'), |
| pdk_path, |
| version, |
| '{}', |
| ], stdin=subprocess.PIPE, stderr=subprocess.STDOUT) as p: |
| p.communicate('\n'.join(devices).encode('utf-8')) |
| retcode = p.wait() |
| |
| passes = [] |
| fails = [] |
| ignores = [] |
| baseline_entries = [] |
| reasons = {} |
| |
| print() |
| print("Loading results from:") |
| print('-'*75) |
| for f in sorted(pr_path.rglob("*_results.json")): |
| f = os.path.abspath(f) |
| print(str(f)) |
| with open(f) as f: |
| data = json.load(f) |
| assert isinstance(data, dict), data |
| passes.extend(data.pop('passes')) |
| fails.extend(data.pop('fails')) |
| ignores.extend(data.pop('ignores')) |
| baseline_entries.extend(data.pop('baseline_entries')) |
| reasons.update(data.pop('reasons')) |
| print('-'*75) |
| print() |
| |
| output = os.path.join(pr_path, 'simulation_run.log') |
| with open(output, 'w') as of: |
| print(file=of) |
| print('Simulation summary', file=of) |
| print('='*75, file=of) |
| print(file=of) |
| print('Passing devices', file=of) |
| print('-'*75, file=of) |
| for passing in passes: |
| print(passing, file=of) |
| print('-'*75, file=of) |
| |
| print(file=of) |
| print('Ignored (unusable) devices', file=of) |
| print('-'*75, file=of) |
| for ignored in ignores: |
| print(ignored, file=of) |
| print('-'*75, file=of) |
| |
| print(file=of) |
| print('Failing devices', file=of) |
| print('-'*75, file=of) |
| for failing in fails: |
| print(failing, file=of) |
| print(' Reason: ' + reasons[failing], file=of) |
| print('-'*75, file=of) |
| |
| # Output pass / fail / ignore summary |
| |
| print(file=of) |
| print('Final results', file=of) |
| print('#'*75, file=of) |
| print('Passes: ' + str(len(passes)), file=of) |
| print('Fails: ' + str(len(fails)), file=of) |
| print('Ignores: ' + str(len(ignores)), file=of) |
| |
| print() |
| print() |
| print() |
| with open(output) as f: |
| print(f.read()) |
| |
| return retcode |
| |
| |
| |
| if __name__ == "__main__": |
| |
| args = list(sys.argv) |
| args.pop(0) |
| |
| pdk_path = args.pop(0) |
| if args and args[0] and args[0][0] == 'v': |
| version = args.pop(0) |
| else: |
| version = 'v0.20.1' |
| sys.exit(main(pdk_path, version)) |