Skip to content

Commit 26ed934

Browse files
authored
Merge pull request #36 from siliconcompiler/generate
helper functions to support building a lambdalib compatible stdlib
2 parents e09fff9 + 7b00fda commit 26ed934

File tree

3 files changed

+163
-1
lines changed

3 files changed

+163
-1
lines changed

lambdalib/__init__.py

Lines changed: 127 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
from siliconcompiler import Chip
2+
from siliconcompiler.package import path as sc_package
3+
import glob
14
import os
2-
5+
import shutil
36
__version__ = "0.1.2"
47

58

@@ -17,3 +20,126 @@ def register_data_source(chip):
1720
chip.register_package_source(name='lambdalib',
1821
path=path,
1922
ref=ref)
23+
24+
25+
def __get_lambdalib_dir(la_lib):
26+
path_assert = Chip('lambdalib')
27+
register_data_source(path_assert)
28+
lambdalib_path = sc_package(path_assert, 'lambdalib')
29+
return f'{lambdalib_path}/lambdalib/{la_lib}/rtl'
30+
31+
32+
def check(outputpath, la_lib='stdlib'):
33+
cells_dir = __get_lambdalib_dir(la_lib)
34+
35+
lambda_cells = set()
36+
for cell in glob.glob(f'{cells_dir}/la_*.v'):
37+
lambda_cells.add(os.path.basename(cell))
38+
39+
lib_cells = set()
40+
for cell in glob.glob(f'{outputpath}/la_*.v'):
41+
lib_cells.add(os.path.basename(cell))
42+
43+
if lambda_cells == lib_cells:
44+
return True
45+
46+
missing_cells = lambda_cells - lib_cells
47+
extra_cells = lib_cells - lambda_cells
48+
49+
if missing_cells:
50+
for cell in missing_cells:
51+
print(f'Missing: {cell}')
52+
if extra_cells:
53+
for cell in extra_cells:
54+
print(f'Excess cell: {cell}')
55+
56+
return False
57+
58+
59+
def copy(outputpath, la_lib='stdlib', exclude=None):
60+
cells_dir = __get_lambdalib_dir(la_lib)
61+
62+
if not exclude:
63+
exclude = []
64+
65+
os.makedirs(outputpath, exist_ok=True)
66+
67+
# Generate list of cells to produce
68+
for cell in glob.glob(f'{cells_dir}/la_*.v'):
69+
cell_file = os.path.basename(cell)
70+
cell_name, _ = os.path.splitext(cell_file)
71+
72+
if cell_name in exclude:
73+
continue
74+
75+
shutil.copy(cell, os.path.join(outputpath, cell_file))
76+
77+
78+
def generate(target, logiclib, outputpath, la_lib='stdlib', exclude=None):
79+
exclude_default = (
80+
'la_decap',
81+
'la_keeper',
82+
'la_footer',
83+
'la_header',
84+
'la_antenna'
85+
)
86+
87+
full_exclude = []
88+
if exclude:
89+
full_exclude.extend(exclude)
90+
91+
full_exclude.extend(exclude_default)
92+
93+
# Ensure files are loaded
94+
cells_dir = __get_lambdalib_dir(la_lib)
95+
96+
# Generate list of cells to produce
97+
org_cells = set()
98+
cells = []
99+
for cell in glob.glob(f'{cells_dir}/la_*.v'):
100+
cell_name, _ = os.path.splitext(os.path.basename(cell))
101+
102+
if cell_name in full_exclude:
103+
continue
104+
105+
cells.append(cell)
106+
org_cells.add(cell_name)
107+
108+
# Remove old implementations
109+
for cell in cells:
110+
new_path = os.path.join(outputpath, os.path.basename(cell))
111+
try:
112+
os.remove(new_path)
113+
except FileNotFoundError:
114+
pass
115+
116+
os.makedirs(outputpath, exist_ok=True)
117+
118+
if isinstance(target, str):
119+
target_name = target
120+
else:
121+
target_name = target.__name__
122+
123+
for cell in cells:
124+
cell_file = os.path.basename(cell)
125+
cell_name, _ = os.path.splitext(cell_file)
126+
127+
chip = Chip(cell_name)
128+
chip.input(cell)
129+
chip.load_target(target)
130+
chip.set('asic', 'logiclib', logiclib)
131+
chip.set('option', 'flow', 'asicflow')
132+
chip.set('option', 'to', 'syn')
133+
chip.set('option', 'quiet', True)
134+
chip.set('option', 'resume', True)
135+
chip.set('option', 'jobname', f"{target_name}-{logiclib}")
136+
137+
chip.add('option', 'ydir', cells_dir)
138+
chip.run()
139+
140+
result = chip.find_result("vg", step="syn", index=0)
141+
shutil.copy(result, os.path.join(outputpath, cell_file))
142+
143+
if exclude:
144+
org_cells.update(exclude)
145+
copy(outputpath, la_lib, org_cells)

tests/conftest.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import pytest
2+
import os
3+
4+
5+
@pytest.fixture(autouse=True)
6+
def test_wrapper(tmp_path):
7+
topdir = os.getcwd()
8+
os.chdir(tmp_path)
9+
# Run the test.
10+
yield
11+
os.chdir(topdir)

tests/test_generate.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import os
2+
import lambdalib
3+
4+
5+
def test_check():
6+
lambdalib.copy('./lambda')
7+
assert lambdalib.check('./lambda')
8+
9+
10+
def test_check_missing_file():
11+
lambdalib.copy('./lambda', exclude=('la_and3',))
12+
assert not lambdalib.check('./lambda')
13+
14+
15+
def test_copy():
16+
lambdalib.copy('./lambda')
17+
18+
assert os.path.exists('./lambda/la_and2.v')
19+
20+
21+
def test_copy_with_exclude():
22+
lambdalib.copy('./lambda', exclude=('la_and3',))
23+
24+
assert os.path.exists('./lambda/la_and2.v')
25+
assert not os.path.exists('./lambda/la_and3.v')

0 commit comments

Comments
 (0)