Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
18 changes: 11 additions & 7 deletions flow/test/test_generate_klayout_tech.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,13 @@ def test_basic_generation(self):

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 @@ -159,7 +160,10 @@ def test_with_map_files(self):
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 Down
46 changes: 31 additions & 15 deletions flow/util/generate_klayout_tech.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,42 @@ def generate_klayout_tech(
template_lyt,
output_lyt,
lef_files,
reference_dir,
map_files,
use_relative_paths,
reference_dir=None,
map_files=None,
use_relative_paths=False,
):
"""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.
reference_dir: Unused. Accepted for backward compatibility with
callers (e.g. flow/Makefile) that still pass it from when
paths were resolved relative to this directory.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just remove the unused args and update the Makefile.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like so?

map_files: List of map file paths.
use_relative_paths: If True, compute paths relative to reference_dir.
use_relative_paths: Unused. Same backward-compat rationale as
reference_dir -- paths are always written as plain abspath
now, regardless of this flag.
"""
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. reference_dir and
# use_relative_paths are both ignored.
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 @@ -80,16 +89,23 @@ def main():
)
parser.add_argument(
"--reference-dir",
required=True,
help="Directory for computing relative paths",
required=False,
default=None,
help=(
"Unused; accepted for backward compatibility. LEF / map paths "
"are written as plain abspath regardless of this directory."
),
)
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",
help=(
"Unused; accepted for backward compatibility. LEF / map paths "
"are written as plain abspath regardless of this flag."
),
)
args = parser.parse_args()

Expand Down