diff --git a/flow/Makefile b/flow/Makefile index 37712545b7..1bb45047a4 100644 --- a/flow/Makefile +++ b/flow/Makefile @@ -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 @@ -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 diff --git a/flow/test/test_generate_klayout_tech.py b/flow/test/test_generate_klayout_tech.py index 22c6642127..92e884cfc6 100644 --- a/flow/test/test_generate_klayout_tech.py +++ b/flow/test/test_generate_klayout_tech.py @@ -120,9 +120,7 @@ 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: @@ -130,12 +128,13 @@ def test_basic_generation(self): self.assertIn("", 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 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: @@ -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): @@ -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: diff --git a/flow/util/generate_klayout_tech.py b/flow/util/generate_klayout_tech.py index c054945f71..b23a1e0aba 100644 --- a/flow/util/generate_klayout_tech.py +++ b/flow/util/generate_klayout_tech.py @@ -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 + # 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: @@ -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, )