Skip to content

Commit ed40258

Browse files
authored
Merge pull request #4001 from Pinata-Consulting/klayout-dependency
Klayout dependency
2 parents b9f42fe + f234bb1 commit ed40258

File tree

9 files changed

+1290
-104
lines changed

9 files changed

+1290
-104
lines changed

.github/workflows/github-actions-cron-util-test.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ on:
44
- cron: "0 8 * * SUN"
55
push:
66
paths:
7-
- 'flow/util/genElapsedTime.py'
8-
- 'flow/test/test_genElapsedTime.py'
7+
- 'flow/util/*.py'
8+
- 'flow/test/test_*.py'
99
pull_request:
1010
paths:
11-
- 'flow/util/genElapsedTime.py'
12-
- 'flow/test/test_genElapsedTime.py'
11+
- 'flow/util/*.py'
12+
- 'flow/test/test_*.py'
1313
# Allows you to run this workflow manually from the Actions tab
1414
workflow_dispatch:
1515

flow/Makefile

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -195,21 +195,25 @@ $(OBJECTS_DIR)/klayout.lyt: $(KLAYOUT_TECH_FILE) $(OBJECTS_DIR)/klayout_tech.lef
195195

196196
.PHONY: do-klayout
197197
do-klayout:
198-
ifeq ($(KLAYOUT_ENV_VAR_IN_PATH),valid)
199-
SC_LEF_RELATIVE_PATH="$(shell realpath --relative-to=$(RESULTS_DIR) $(SC_LEF))"; \
200-
OTHER_LEFS_RELATIVE_PATHS=$$(echo "$(foreach file, $(OBJECTS_DIR)/klayout_tech.lef $(ADDITIONAL_LEFS),<lef-files>$$(realpath --relative-to=$(RESULTS_DIR) $(file))</lef-files>)"); \
201-
sed 's,<lef-files>.*</lef-files>,<lef-files>'"$$SC_LEF_RELATIVE_PATH"'</lef-files>'"$$OTHER_LEFS_RELATIVE_PATHS"',g' $(KLAYOUT_TECH_FILE) > $(OBJECTS_DIR)/klayout.lyt
202-
else
203-
sed 's,<lef-files>.*</lef-files>,$(foreach file, $(OBJECTS_DIR)/klayout_tech.lef $(SC_LEF) $(ADDITIONAL_LEFS),<lef-files>$(shell realpath --relative-to=$(RESULTS_DIR) $(file))</lef-files>),g' $(KLAYOUT_TECH_FILE) > $(OBJECTS_DIR)/klayout.lyt
204-
endif
205-
sed -i 's,<map-file>.*</map-file>,$(foreach file, $(FLOW_HOME)/platforms/$(PLATFORM)/*map,<map-file>$(shell realpath $(file))</map-file>),g' $(OBJECTS_DIR)/klayout.lyt
198+
@mkdir -p $(dir $(OBJECTS_DIR)/klayout.lyt)
199+
$(PYTHON_EXE) $(UTILS_DIR)/generate_klayout_tech.py \
200+
--template $(KLAYOUT_TECH_FILE) \
201+
--output $(OBJECTS_DIR)/klayout.lyt \
202+
--lef-files $(OBJECTS_DIR)/klayout_tech.lef $(SC_LEF) $(ADDITIONAL_LEFS) \
203+
--reference-dir $(RESULTS_DIR) \
204+
--map-files $(wildcard $(FLOW_HOME)/platforms/$(PLATFORM)/*map)
206205

207206
$(OBJECTS_DIR)/klayout_wrap.lyt: $(KLAYOUT_TECH_FILE) $(OBJECTS_DIR)/klayout_tech.lef
208207
$(UNSET_AND_MAKE) do-klayout_wrap
209208

210209
.PHONY: do-klayout_wrap
211210
do-klayout_wrap:
212-
sed 's,<lef-files>.*</lef-files>,$(foreach file, $(OBJECTS_DIR)/klayout_tech.lef $(WRAP_LEFS),<lef-files>$(shell realpath --relative-to=$(OBJECTS_DIR)/def $(file))</lef-files>),g' $(KLAYOUT_TECH_FILE) > $(OBJECTS_DIR)/klayout_wrap.lyt
211+
@mkdir -p $(dir $(OBJECTS_DIR)/klayout_wrap.lyt)
212+
$(PYTHON_EXE) $(UTILS_DIR)/generate_klayout_tech.py \
213+
--template $(KLAYOUT_TECH_FILE) \
214+
--output $(OBJECTS_DIR)/klayout_wrap.lyt \
215+
--lef-files $(OBJECTS_DIR)/klayout_tech.lef $(WRAP_LEFS) \
216+
--reference-dir $(OBJECTS_DIR)/def
213217

214218
$(WRAPPED_LEFS):
215219
mkdir -p $(OBJECTS_DIR)/lef $(OBJECTS_DIR)/def
@@ -627,7 +631,7 @@ final: finish
627631

628632
.PHONY: do-finish
629633
do-finish:
630-
$(UNSET_AND_MAKE) do-6_1_fill do-6_1_fill.sdc do-6_final.sdc do-6_report do-gds elapsed
634+
$(UNSET_AND_MAKE) do-6_1_fill do-6_1_fill.sdc do-6_final.sdc do-6_report elapsed
631635

632636
.PHONY: generate_abstract
633637
generate_abstract: $(RESULTS_DIR)/6_final.gds $(RESULTS_DIR)/6_final.def $(RESULTS_DIR)/6_final.v $(RESULTS_DIR)/6_final.sdc
@@ -643,6 +647,17 @@ do-generate_abstract:
643647
clean_abstract:
644648
rm -f $(RESULTS_DIR)/$(DESIGN_NAME).lib $(RESULTS_DIR)/$(DESIGN_NAME).lef
645649

650+
.PHONY: check-klayout
651+
check-klayout:
652+
@if [ -z "$(KLAYOUT_CMD)" ]; then \
653+
echo "Error: KLayout not found. Install KLayout or set KLAYOUT_CMD."; \
654+
echo "Hint: KLayout is needed for GDS/DRC/LVS targets."; \
655+
exit 1; \
656+
fi
657+
658+
.PHONY: gds
659+
gds: $(GDS_FINAL_FILE)
660+
646661
# Merge wrapped macros using Klayout
647662
#-------------------------------------------------------------------------------
648663
$(WRAPPED_GDSOAS): $(OBJECTS_DIR)/klayout_wrap.lyt $(WRAPPED_LEFS)
@@ -658,7 +673,7 @@ $(WRAPPED_GDSOAS): $(OBJECTS_DIR)/klayout_wrap.lyt $(WRAPPED_LEFS)
658673

659674
# Merge GDS using Klayout
660675
#-------------------------------------------------------------------------------
661-
$(GDS_MERGED_FILE): $(RESULTS_DIR)/6_final.def $(OBJECTS_DIR)/klayout.lyt $(GDSOAS_FILES) $(WRAPPED_GDSOAS) $(SEAL_GDSOAS)
676+
$(GDS_MERGED_FILE): check-klayout $(RESULTS_DIR)/6_final.def $(OBJECTS_DIR)/klayout.lyt $(GDSOAS_FILES) $(WRAPPED_GDSOAS) $(SEAL_GDSOAS)
662677
$(UNSET_AND_MAKE) do-gds-merged
663678

664679
.PHONY: do-gds-merged
@@ -768,7 +783,7 @@ nuke: clean_test clean_issues
768783
# DEF/GDS/OAS viewer shortcuts
769784
#-------------------------------------------------------------------------------
770785
.PHONY: $(foreach file,$(RESULTS_DEF) $(RESULTS_GDS) $(RESULTS_OAS),klayout_$(file))
771-
$(foreach file,$(RESULTS_DEF) $(RESULTS_GDS) $(RESULTS_OAS),klayout_$(file)): klayout_%: $(OBJECTS_DIR)/klayout.lyt
786+
$(foreach file,$(RESULTS_DEF) $(RESULTS_GDS) $(RESULTS_OAS),klayout_$(file)): klayout_%: check-klayout $(OBJECTS_DIR)/klayout.lyt
772787
$(SCRIPTS_DIR)/klayout.sh -nn $(OBJECTS_DIR)/klayout.lyt $(RESULTS_DIR)/$*
773788

774789
$(eval $(call OPEN_GUI_SHORTCUT,synth,1_synth.odb))
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# KLayout as an Optional Dependency
2+
3+
KLayout is only required for GDS/OAS stream generation, DRC, and LVS
4+
verification. All other ORFS functionality — synthesis, floorplanning,
5+
placement, CTS, routing, timing reports, and abstract generation — works
6+
without KLayout installed.
7+
8+
## Makefile Targets
9+
10+
| Target | Requires KLayout | Description |
11+
|---|---|---|
12+
| `make finish` | Yes | Complete flow including GDS generation |
13+
| `make gds` | Yes | Generate GDS/OAS from finished design |
14+
| `make drc` | Yes | Run DRC checks (requires GDS) |
15+
| `make lvs` | Yes | Run LVS checks (requires GDS) |
16+
| `make gallery` | Yes | Generate layout screenshots |
17+
| `make klayout_<file>` | Yes | Open result in KLayout viewer |
18+
| `make generate_abstract` | No | Generate LEF/LIB abstracts |
19+
20+
A `check-klayout` guard produces a clear error message when KLayout is
21+
missing and a KLayout-dependent target is invoked:
22+
23+
```
24+
Error: KLayout not found. Install KLayout or set KLAYOUT_CMD.
25+
Hint: KLayout is needed for GDS/DRC/LVS targets.
26+
```
27+
28+
## bazel-orfs Integration
29+
30+
bazel-orfs uses the `do-` prefixed targets which bypass Make's dependency
31+
management. `do-finish` / `do-final` only run the finish stage recipe
32+
itself, while `make finish` also pulls in the GDS target as a Make
33+
dependency. `do-gds` runs GDS generation separately (requires KLayout).
34+
35+
An `orfs_gds()` Bazel rule can call `do-gds` independently from
36+
`orfs_flow()`, making KLayout an optional toolchain dependency configured
37+
in `MODULE.bazel`.
38+
39+
## KLayout Tech File Generation
40+
41+
The `do-klayout` and `do-klayout_wrap` targets generate `.lyt` technology
42+
files by substituting LEF and map file paths into platform templates.
43+
This is implemented in `util/generate_klayout_tech.py` using stdlib XML
44+
processing — no KLayout dependency required.
45+
46+
## Testing Without KLayout
47+
48+
Unit tests for all KLayout-related Python scripts use `unittest.mock` to
49+
mock the `pya` API:
50+
51+
```
52+
cd flow/test
53+
python -m unittest test_generate_klayout_tech test_def2stream test_convertDrc
54+
```
55+
56+
These tests cover:
57+
- `.lyt` tech file generation (`test_generate_klayout_tech.py`)
58+
- DEF-to-GDS merging logic (`test_def2stream.py`)
59+
- DRC report conversion (`test_convertDrc.py`)

0 commit comments

Comments
 (0)