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
8 changes: 4 additions & 4 deletions .github/workflows/github-actions-cron-util-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ on:
- cron: "0 8 * * SUN"
push:
paths:
- 'flow/util/genElapsedTime.py'
- 'flow/test/test_genElapsedTime.py'
- 'flow/util/*.py'
- 'flow/test/test_*.py'
pull_request:
paths:
- 'flow/util/genElapsedTime.py'
- 'flow/test/test_genElapsedTime.py'
- 'flow/util/*.py'
- 'flow/test/test_*.py'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

Expand Down
39 changes: 27 additions & 12 deletions flow/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -195,21 +195,25 @@ $(OBJECTS_DIR)/klayout.lyt: $(KLAYOUT_TECH_FILE) $(OBJECTS_DIR)/klayout_tech.lef

.PHONY: do-klayout
do-klayout:
ifeq ($(KLAYOUT_ENV_VAR_IN_PATH),valid)
SC_LEF_RELATIVE_PATH="$(shell realpath --relative-to=$(RESULTS_DIR) $(SC_LEF))"; \
OTHER_LEFS_RELATIVE_PATHS=$$(echo "$(foreach file, $(OBJECTS_DIR)/klayout_tech.lef $(ADDITIONAL_LEFS),<lef-files>$$(realpath --relative-to=$(RESULTS_DIR) $(file))</lef-files>)"); \
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
else
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
endif
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
@mkdir -p $(dir $(OBJECTS_DIR)/klayout.lyt)
$(PYTHON_EXE) $(UTILS_DIR)/generate_klayout_tech.py \
--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
$(UNSET_AND_MAKE) do-klayout_wrap

.PHONY: do-klayout_wrap
do-klayout_wrap:
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
@mkdir -p $(dir $(OBJECTS_DIR)/klayout_wrap.lyt)
$(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

$(WRAPPED_LEFS):
mkdir -p $(OBJECTS_DIR)/lef $(OBJECTS_DIR)/def
Expand Down Expand Up @@ -627,7 +631,7 @@ final: finish

.PHONY: do-finish
do-finish:
$(UNSET_AND_MAKE) do-6_1_fill do-6_1_fill.sdc do-6_final.sdc do-6_report do-gds elapsed
$(UNSET_AND_MAKE) do-6_1_fill do-6_1_fill.sdc do-6_final.sdc do-6_report elapsed

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

.PHONY: check-klayout
check-klayout:
@if [ -z "$(KLAYOUT_CMD)" ]; then \
echo "Error: KLayout not found. Install KLayout or set KLAYOUT_CMD."; \
echo "Hint: KLayout is needed for GDS/DRC/LVS targets."; \
exit 1; \
fi

.PHONY: gds
gds: $(GDS_FINAL_FILE)

# Merge wrapped macros using Klayout
#-------------------------------------------------------------------------------
$(WRAPPED_GDSOAS): $(OBJECTS_DIR)/klayout_wrap.lyt $(WRAPPED_LEFS)
Expand All @@ -658,7 +673,7 @@ $(WRAPPED_GDSOAS): $(OBJECTS_DIR)/klayout_wrap.lyt $(WRAPPED_LEFS)

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

.PHONY: do-gds-merged
Expand Down Expand Up @@ -768,7 +783,7 @@ nuke: clean_test clean_issues
# DEF/GDS/OAS viewer shortcuts
#-------------------------------------------------------------------------------
.PHONY: $(foreach file,$(RESULTS_DEF) $(RESULTS_GDS) $(RESULTS_OAS),klayout_$(file))
$(foreach file,$(RESULTS_DEF) $(RESULTS_GDS) $(RESULTS_OAS),klayout_$(file)): klayout_%: $(OBJECTS_DIR)/klayout.lyt
$(foreach file,$(RESULTS_DEF) $(RESULTS_GDS) $(RESULTS_OAS),klayout_$(file)): klayout_%: check-klayout $(OBJECTS_DIR)/klayout.lyt
$(SCRIPTS_DIR)/klayout.sh -nn $(OBJECTS_DIR)/klayout.lyt $(RESULTS_DIR)/$*

$(eval $(call OPEN_GUI_SHORTCUT,synth,1_synth.odb))
Expand Down
59 changes: 59 additions & 0 deletions flow/docs/KLayoutOptionalDependency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# KLayout as an Optional Dependency

KLayout is only required for GDS/OAS stream generation, DRC, and LVS
verification. All other ORFS functionality — synthesis, floorplanning,
placement, CTS, routing, timing reports, and abstract generation — works
without KLayout installed.

## Makefile Targets

| Target | Requires KLayout | Description |
|---|---|---|
| `make finish` | Yes | Complete flow including GDS generation |
| `make gds` | Yes | Generate GDS/OAS from finished design |
| `make drc` | Yes | Run DRC checks (requires GDS) |
| `make lvs` | Yes | Run LVS checks (requires GDS) |
| `make gallery` | Yes | Generate layout screenshots |
| `make klayout_<file>` | Yes | Open result in KLayout viewer |
| `make generate_abstract` | No | Generate LEF/LIB abstracts |

A `check-klayout` guard produces a clear error message when KLayout is
missing and a KLayout-dependent target is invoked:

```
Error: KLayout not found. Install KLayout or set KLAYOUT_CMD.
Hint: KLayout is needed for GDS/DRC/LVS targets.
```

## bazel-orfs Integration

bazel-orfs uses the `do-` prefixed targets which bypass Make's dependency
management. `do-finish` / `do-final` only run the finish stage recipe
itself, while `make finish` also pulls in the GDS target as a Make
dependency. `do-gds` runs GDS generation separately (requires KLayout).

An `orfs_gds()` Bazel rule can call `do-gds` independently from
`orfs_flow()`, making KLayout an optional toolchain dependency configured
in `MODULE.bazel`.

## KLayout Tech File Generation

The `do-klayout` and `do-klayout_wrap` targets generate `.lyt` technology
files by substituting LEF and map file paths into platform templates.
This is implemented in `util/generate_klayout_tech.py` using stdlib XML
processing — no KLayout dependency required.

## Testing Without KLayout

Unit tests for all KLayout-related Python scripts use `unittest.mock` to
mock the `pya` API:

```
cd flow/test
python -m unittest test_generate_klayout_tech test_def2stream test_convertDrc
```

These tests cover:
- `.lyt` tech file generation (`test_generate_klayout_tech.py`)
- DEF-to-GDS merging logic (`test_def2stream.py`)
- DRC report conversion (`test_convertDrc.py`)
Loading