Skip to content

Commit

Permalink
Merge pull request ucb-art#12 from hyunjaekwon/support_concurrent_dut…
Browse files Browse the repository at this point in the history
…_creation

Support concurrent dut creation
  • Loading branch information
ayan-biswas authored May 13, 2022
2 parents fd27e8b + 69fba4a commit 0c9cf61
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 8 deletions.
20 changes: 15 additions & 5 deletions src/bag/io/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,19 +140,22 @@ def readlines_iter(fname: Union[str, Path]) -> Iterable[str]:
yield line


def is_valid_file(fname: Union[str, Path], ready_str: Optional[str], timeout: float, wait_intvl: float) -> bool:
def is_valid_file(fname: Union[str, Path], ready_str: Optional[str], timeout: float, wait_intvl: float,
check_nonempty: bool = False) -> bool:
"""Checks if given file is valid by seeing if it exists and optionally contains a string.
Parameters
----------
fname : Union[str, Path]
the file name.
ready_str : Optional[str]
the string to check if file is ready. None if we should only check to see if file exists
the string to check if file is ready. None if we should only check to see if file exists.
timeout : float
Maximum amount of time to wait.
wait_intvl: float
Amount of time in between iterations to check if file is ready
maximum amount of time to wait.
wait_intvl : float
amount of time in between iterations to check if file is ready.
check_nonempty : bool
True to check if file is not empty. Default is False.
Returns
-------
Expand All @@ -168,6 +171,13 @@ def is_valid_file(fname: Union[str, Path], ready_str: Optional[str], timeout: fl
time.sleep(wait_intvl)
iter_cnt += 1

if check_nonempty:
while fname.stat().st_size == 0:
if iter_cnt > max_iter:
return False
time.sleep(wait_intvl)
iter_cnt += 1

if ready_str is None:
return True

Expand Down
15 changes: 12 additions & 3 deletions src/bag/simulation/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import shutil
import filecmp
import tempfile
from pathlib import Path
from dataclasses import dataclass

Expand Down Expand Up @@ -201,13 +202,17 @@ async def _create_dut(self, impl_cell: str,
exact_cell_names = {impl_cell}

obj_cls = import_class(dut_cls)

# Create DUT layout and netlist in unique temporary directory to prevent overwriting of files
# during concurrent DUT creation
tmp_dir = Path(tempfile.mkdtemp('', 'tmp_', dir=self._root_dir))
if issubclass(obj_cls, TemplateBase):
self.log(f'Creating layout: {obj_cls.__name__}')
lay_master = self._lay_db.new_template(obj_cls, params=dut_params)
sch_params = lay_master.sch_params
sch_cls = lay_master.get_schematic_class_inst()
layout_hash = hash(lay_master.key)
gds_file = str(self._root_dir / 'tmp.gds')
gds_file = str(tmp_dir / 'tmp.gds')
if export_lay:
self._lay_db.batch_layout([(lay_master, impl_cell)], output=DesignOutput.LAYOUT,
name_prefix=name_prefix, name_suffix=name_suffix,
Expand All @@ -218,6 +223,7 @@ async def _create_dut(self, impl_cell: str,
fname=gds_file, name_prefix=name_prefix,
name_suffix=name_suffix,
exact_cell_names=exact_cell_names)
assert is_valid_file(gds_file, None, 60, 1, True)
else:
if extract:
raise ValueError('Cannot run extraction without layout.')
Expand All @@ -235,7 +241,7 @@ async def _create_dut(self, impl_cell: str,
sch_master: Module = self._sch_db.new_master(sch_cls, params=sch_params)

# create schematic netlist
cdl_netlist = str(self._root_dir / 'tmp.cdl')
cdl_netlist = str(tmp_dir / 'tmp.cdl')
cv_info_out = []
sch_dut_list = [(sch_master, impl_cell)]
self._sch_db.batch_schematic(sch_dut_list, output=DesignOutput.CDL,
Expand All @@ -247,6 +253,8 @@ async def _create_dut(self, impl_cell: str,
name_prefix=name_prefix, name_suffix=name_suffix,
exact_cell_names=exact_cell_names)

assert is_valid_file(cdl_netlist, None, 60, 1, True)

self.log('Check for existing netlist')
hash_id = combine_hash(layout_hash, hash(sch_master.key))
dir_list = self._cache.get(hash_id, None)
Expand All @@ -271,6 +279,7 @@ async def _create_dut(self, impl_cell: str,
dir_path = self._generate_cell(impl_cell, cdl_netlist, gds_file)
dir_list.append(dir_path.name)
write_yaml(self._info_file, self._info_specs)
shutil.rmtree(tmp_dir) # Remove temporary directory

if extract or (extract is None and self._extract):
ans = dir_path / 'rcx.sp'
Expand Down Expand Up @@ -343,7 +352,7 @@ def _generate_cell(self, impl_cell: str, cdl_netlist: str, gds_file: str) -> Pat
dir_path.mkdir(parents=True, exist_ok=True)

shutil.move(cdl_netlist, str(dir_path / 'netlist.cdl'))
if is_valid_file(gds_file, None, 60, 1):
if gds_file:
shutil.move(gds_file, str(dir_path / 'layout.gds'))
return dir_path

Expand Down

0 comments on commit 0c9cf61

Please sign in to comment.