Skip to content

Commit

Permalink
Merge pull request #36 from siliconcompiler/generate
Browse files Browse the repository at this point in the history
helper functions to support building a lambdalib compatible stdlib
  • Loading branch information
gadfort authored Feb 15, 2024
2 parents e09fff9 + 7b00fda commit 26ed934
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 1 deletion.
128 changes: 127 additions & 1 deletion lambdalib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from siliconcompiler import Chip
from siliconcompiler.package import path as sc_package
import glob
import os

import shutil
__version__ = "0.1.2"


Expand All @@ -17,3 +20,126 @@ def register_data_source(chip):
chip.register_package_source(name='lambdalib',
path=path,
ref=ref)


def __get_lambdalib_dir(la_lib):
path_assert = Chip('lambdalib')
register_data_source(path_assert)
lambdalib_path = sc_package(path_assert, 'lambdalib')
return f'{lambdalib_path}/lambdalib/{la_lib}/rtl'


def check(outputpath, la_lib='stdlib'):
cells_dir = __get_lambdalib_dir(la_lib)

lambda_cells = set()
for cell in glob.glob(f'{cells_dir}/la_*.v'):
lambda_cells.add(os.path.basename(cell))

lib_cells = set()
for cell in glob.glob(f'{outputpath}/la_*.v'):
lib_cells.add(os.path.basename(cell))

if lambda_cells == lib_cells:
return True

missing_cells = lambda_cells - lib_cells
extra_cells = lib_cells - lambda_cells

if missing_cells:
for cell in missing_cells:
print(f'Missing: {cell}')
if extra_cells:
for cell in extra_cells:
print(f'Excess cell: {cell}')

return False


def copy(outputpath, la_lib='stdlib', exclude=None):
cells_dir = __get_lambdalib_dir(la_lib)

if not exclude:
exclude = []

os.makedirs(outputpath, exist_ok=True)

# Generate list of cells to produce
for cell in glob.glob(f'{cells_dir}/la_*.v'):
cell_file = os.path.basename(cell)
cell_name, _ = os.path.splitext(cell_file)

if cell_name in exclude:
continue

shutil.copy(cell, os.path.join(outputpath, cell_file))


def generate(target, logiclib, outputpath, la_lib='stdlib', exclude=None):
exclude_default = (
'la_decap',
'la_keeper',
'la_footer',
'la_header',
'la_antenna'
)

full_exclude = []
if exclude:
full_exclude.extend(exclude)

full_exclude.extend(exclude_default)

# Ensure files are loaded
cells_dir = __get_lambdalib_dir(la_lib)

# Generate list of cells to produce
org_cells = set()
cells = []
for cell in glob.glob(f'{cells_dir}/la_*.v'):
cell_name, _ = os.path.splitext(os.path.basename(cell))

if cell_name in full_exclude:
continue

cells.append(cell)
org_cells.add(cell_name)

# Remove old implementations
for cell in cells:
new_path = os.path.join(outputpath, os.path.basename(cell))
try:
os.remove(new_path)
except FileNotFoundError:
pass

os.makedirs(outputpath, exist_ok=True)

if isinstance(target, str):
target_name = target
else:
target_name = target.__name__

for cell in cells:
cell_file = os.path.basename(cell)
cell_name, _ = os.path.splitext(cell_file)

chip = Chip(cell_name)
chip.input(cell)
chip.load_target(target)
chip.set('asic', 'logiclib', logiclib)
chip.set('option', 'flow', 'asicflow')
chip.set('option', 'to', 'syn')
chip.set('option', 'quiet', True)
chip.set('option', 'resume', True)
chip.set('option', 'jobname', f"{target_name}-{logiclib}")

chip.add('option', 'ydir', cells_dir)
chip.run()

result = chip.find_result("vg", step="syn", index=0)
shutil.copy(result, os.path.join(outputpath, cell_file))

if exclude:
org_cells.update(exclude)
copy(outputpath, la_lib, org_cells)
11 changes: 11 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import pytest
import os


@pytest.fixture(autouse=True)
def test_wrapper(tmp_path):
topdir = os.getcwd()
os.chdir(tmp_path)
# Run the test.
yield
os.chdir(topdir)
25 changes: 25 additions & 0 deletions tests/test_generate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os
import lambdalib


def test_check():
lambdalib.copy('./lambda')
assert lambdalib.check('./lambda')


def test_check_missing_file():
lambdalib.copy('./lambda', exclude=('la_and3',))
assert not lambdalib.check('./lambda')


def test_copy():
lambdalib.copy('./lambda')

assert os.path.exists('./lambda/la_and2.v')


def test_copy_with_exclude():
lambdalib.copy('./lambda', exclude=('la_and3',))

assert os.path.exists('./lambda/la_and2.v')
assert not os.path.exists('./lambda/la_and3.v')

0 comments on commit 26ed934

Please sign in to comment.