Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions flow/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ do-klayout:
--template $(KLAYOUT_TECH_FILE) \
--output $(OBJECTS_DIR)/klayout.lyt \
--lef-files $(OBJECTS_DIR)/klayout_tech.lef $(SC_LEF) $(ADDITIONAL_LEFS) \
--reference-dir $(RESULTS_DIR) \
--map-files $(wildcard $(FLOW_HOME)/platforms/$(PLATFORM)/*map)

$(OBJECTS_DIR)/klayout_wrap.lyt: $(KLAYOUT_TECH_FILE) $(OBJECTS_DIR)/klayout_tech.lef
Expand All @@ -212,8 +211,7 @@ do-klayout_wrap:
$(PYTHON_EXE) $(UTILS_DIR)/generate_klayout_tech.py \
--template $(KLAYOUT_TECH_FILE) \
--output $(OBJECTS_DIR)/klayout_wrap.lyt \
--lef-files $(OBJECTS_DIR)/klayout_tech.lef $(WRAP_LEFS) \
--reference-dir $(OBJECTS_DIR)/def
--lef-files $(OBJECTS_DIR)/klayout_tech.lef $(WRAP_LEFS)

$(WRAPPED_LEFS):
mkdir -p $(OBJECTS_DIR)/lef $(OBJECTS_DIR)/def
Expand Down
24 changes: 11 additions & 13 deletions flow/test/test_generate_klayout_tech.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,22 +120,21 @@ def test_basic_generation(self):
template_lyt=self.template,
output_lyt=self.output,
lef_files=[lef_path],
reference_dir=self.results_dir,
map_files=[],
use_relative_paths=True,
)

with open(self.output) as f:
content = f.read()

self.assertIn("<lef-files>", content)
self.assertNotIn("original.lef", content)
# Path should be relative to results_dir
expected_rel = os.path.relpath(
os.path.realpath(lef_path),
os.path.realpath(self.results_dir),
)
self.assertIn(expected_rel, content)
# LEF paths are written as plain abspath (not relpath, not realpath):
# klayout's Layout.read resolves relative <lef-files> entries
# against the realpath of the DEF being merged, which under a
# Bazel sandbox is the bare execroot -- the in-flight sibling
# files only exist in the per-action sandbox. Absolute paths
# bypass the relative-resolution dance.
self.assertIn(os.path.abspath(lef_path), content)

def test_with_map_files(self):
with open(self.template, "w") as f:
Expand All @@ -151,15 +150,16 @@ def test_with_map_files(self):
template_lyt=self.template,
output_lyt=self.output,
lef_files=[lef_path],
reference_dir=self.results_dir,
map_files=[map_path],
use_relative_paths=False,
)

with open(self.output) as f:
content = f.read()

self.assertIn(os.path.realpath(map_path), content)
# Same abspath semantics as LEFs: map files are also written as
# plain absolute paths so klayout doesn't resolve them relative
# to the bare-execroot realpath of the input DEF.
self.assertIn(os.path.abspath(map_path), content)
self.assertNotIn("original.map", content)

def test_multiple_lef_files(self):
Expand All @@ -177,9 +177,7 @@ def test_multiple_lef_files(self):
template_lyt=self.template,
output_lyt=self.output,
lef_files=lef_files,
reference_dir=self.results_dir,
map_files=[],
use_relative_paths=True,
)

with open(self.output) as f:
Expand Down
41 changes: 12 additions & 29 deletions flow/util/generate_klayout_tech.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,37 +30,32 @@ def replace_map_files(content, map_files):
return content


def generate_klayout_tech(
template_lyt,
output_lyt,
lef_files,
reference_dir,
map_files,
use_relative_paths,
):
def generate_klayout_tech(template_lyt, output_lyt, lef_files, map_files=None):
"""Generate a klayout .lyt file from a platform template.

Args:
template_lyt: Path to the platform .lyt template file.
output_lyt: Path to write the generated .lyt file.
lef_files: List of LEF file paths to include.
reference_dir: Directory to compute relative paths from.
map_files: List of map file paths.
use_relative_paths: If True, compute paths relative to reference_dir.
"""
with open(template_lyt, "r") as f:
content = f.read()

# Both modes use relative paths from reference_dir, matching the
# original sed-based behavior which always uses realpath --relative-to.
resolved_lefs = [
os.path.relpath(os.path.realpath(f), os.path.realpath(reference_dir))
for f in lef_files
]
# Write absolute (not relative, not realpath'd) LEF paths into the LYT.
# Klayout's Layout.read(def, layout_options) follows the symlinked input
# DEF to its realpath at the bare execroot and resolves relative
# <lef-files> entries from there. Sibling intermediates like
# objects/klayout_tech.lef don't exist at the bare execroot during
# action execution -- they're only at the per-action sandbox -- so
# resolution fails with errno=2. Plain abspath (NOT realpath, which
# would chase Bazel input-file symlinks back out to the bare execroot)
# keeps klayout pointed at the in-sandbox file.
resolved_lefs = [os.path.abspath(f) for f in lef_files]

content = replace_lef_files(content, resolved_lefs)

resolved_maps = [os.path.realpath(f) for f in map_files]
resolved_maps = [os.path.abspath(f) for f in (map_files or [])]
content = replace_map_files(content, resolved_maps)

with open(output_lyt, "w") as f:
Expand All @@ -78,28 +73,16 @@ def main():
parser.add_argument(
"--lef-files", nargs="*", default=[], help="LEF files to include"
)
parser.add_argument(
"--reference-dir",
required=True,
help="Directory for computing relative paths",
)
parser.add_argument(
"--map-files", nargs="*", default=[], help="Map files to include"
)
parser.add_argument(
"--use-relative-paths",
action="store_true",
help="Use paths relative to reference-dir",
)
args = parser.parse_args()

generate_klayout_tech(
template_lyt=args.template,
output_lyt=args.output,
lef_files=args.lef_files,
reference_dir=args.reference_dir,
map_files=args.map_files,
use_relative_paths=args.use_relative_paths,
)


Expand Down