feat: enhance synthesis and metrics handling with recipe-specific outputs and configurations

This commit is contained in:
maksyuki committed 2026-08-20 12:38:28 +08:00
1 parent faa6769fd4
commit 25e911a503
13 files changed
+175 -60

No files matched your search

+14 -8
View File
@@ -102,13 +102,18 @@ VARIANT_ROOT := $(abspath $(BUILD_ROOT))/$(VARIANT_ID)
SW_BUILD_DIR := $(VARIANT_ROOT)/sw
SIM_TOOL_NAME := $(shell printf '%s' '$(SIMU)' | tr '[:upper:]' '[:lower:]')
SIM_BUILD_ROOT := $(VARIANT_ROOT)/sim/$(SIM_TOOL_NAME)
ifeq ($(SYNTH_RECIPE),balanced)
SYN_BUILD_ROOT := $(VARIANT_ROOT)/syn/yosys
else
SYN_BUILD_ROOT := $(VARIANT_ROOT)/syn/yosys-$(SYNTH_RECIPE)
endif
STA_BUILD_ROOT := $(VARIANT_ROOT)/sta/opensta
META_DIR := $(VARIANT_ROOT)/meta
ifeq ($(SYNTH_RECIPE),balanced)
SYN_BUILD_ROOT := $(VARIANT_ROOT)/syn/yosys
STA_BUILD_ROOT := $(VARIANT_ROOT)/sta/opensta
NETLIST_SIM_ROOT := $(SIM_BUILD_ROOT)/netl
METRICS_OUTPUT := $(META_DIR)/metrics.json
else
SYN_BUILD_ROOT := $(VARIANT_ROOT)/syn/yosys-$(SYNTH_RECIPE)
STA_BUILD_ROOT := $(VARIANT_ROOT)/sta/opensta-$(SYNTH_RECIPE)
NETLIST_SIM_ROOT := $(SIM_BUILD_ROOT)/netl-$(SYNTH_RECIPE)
METRICS_OUTPUT := $(META_DIR)/metrics-$(SYNTH_RECIPE).json
endif
ifeq ($(SYNTH),YOSYS)
FLOW_FILELIST_DIR := $(SYN_BUILD_ROOT)/filelists
else
@@ -407,10 +412,11 @@ check-warnings:
metrics:
python3 $(ROOT_PATH)/scripts/metrics.py collect --variant-root $(VARIANT_ROOT) \
--output $(META_DIR)/metrics.json
--synth-root $(SYN_BUILD_ROOT) --sta-root $(STA_BUILD_ROOT) \
--recipe $(SYNTH_RECIPE) --output $(METRICS_OUTPUT)
check-metrics: metrics
python3 $(ROOT_PATH)/scripts/metrics.py check --metrics $(META_DIR)/metrics.json \
python3 $(ROOT_PATH)/scripts/metrics.py check --metrics $(METRICS_OUTPUT) \
--policy $(ROOT_PATH)/quality/metrics/policy.json \
--baseline $(ROOT_PATH)/quality/metrics/baseline.json
+32 -9
View File
@@ -121,19 +121,42 @@ build/<variant>/
sw/
sim/<simulator>/
formal/<proof>/
syn/yosys/
syn/yosys-area/ (optional SYNTH_RECIPE=area)
syn/yosys-speed/ (optional SYNTH_RECIPE=speed)
sta/opensta/
syn/yosys/ (balanced)
syn/yosys-area/ (SYNTH_RECIPE=area)
syn/yosys-speed/ (SYNTH_RECIPE=speed)
sta/opensta/ (balanced)
sta/opensta-area/ (SYNTH_RECIPE=area)
sta/opensta-speed/ (SYNTH_RECIPE=speed)
meta/manifest.json
meta/warnings.json
meta/metrics.json
meta/metrics.json (balanced)
meta/metrics-area.json (SYNTH_RECIPE=area)
meta/metrics-speed.json (SYNTH_RECIPE=speed)
```
The default Yosys recipe writes `syn/yosys/`. Optional `SYNTH_RECIPE=area` and
`SYNTH_RECIPE=speed` jobs write sibling directories; STA, netlist simulation, warning analysis,
and metrics read only `syn/yosys/`. `SYNTH_RECIPE` is a flow selector and does not change the
configuration hash.
`SYNTH_RECIPE` is a flow selector and does not change the configuration hash.
The selected recipe determines the synthesis netlist consumed by OpenSTA and
netlist simulation, and determines which metrics file is written. `balanced`
is the default PR flow. Nightly IHP130 runs `area` and `speed` through synth,
STA, and metrics; their netlist simulation remains an explicit, on-demand
validation because of its runtime.
Use the same commit, PDK, `BUILD_TIMESTAMP`, and `YOSYS_TARGET_PERIOD_PS` for
all recipes in a QoR comparison:
```sh
make CONFIG=configs/ci/ihp130.mk SYNTH=YOSYS SYNTH_RECIPE=balanced synth
make CONFIG=configs/ci/ihp130.mk SYNTH=YOSYS SYNTH_RECIPE=area synth
make CONFIG=configs/ci/ihp130.mk SYNTH=YOSYS SYNTH_RECIPE=speed synth
make CONFIG=configs/ci/ihp130.mk SYNTH_RECIPE=area STA=OPENSTA sta
make CONFIG=configs/ci/ihp130.mk SYNTH_RECIPE=area metrics
```
Recipe optimization is evaluated using top area, cell count, WNS/TNS, flow
duration, warning signatures, and netlist simulation verdict together. The
`area` recipe is area-first and the `speed` recipe is timing-first; a single
improved metric is not sufficient to replace `balanced`. Metrics policy remains
in `observe` mode while recipe baselines are collected and reviewed.
Generated filelists and MPW output are flow-local. Make depfiles track expanded RTL sources and
included headers. The shared MPW generator is protected by a file lock. Default tool parallelism is
+2 -2
View File
@@ -1,11 +1,11 @@
OPENSTA ?= sta
OPENSTA_THREADS ?= $(JOBS)
OPENSTA_NETLIST ?= $(VARIANT_ROOT)/syn/yosys/out/retrosoc_asic_yosys.v
OPENSTA_NETLIST ?= $(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v
OPENSTA_REPORT ?= $(STA_BUILD_ROOT)/retrosoc_sta.log
OPENSTA_LOG ?= $(STA_BUILD_ROOT)/opensta.log
OPENSTA_METRICS ?= $(STA_BUILD_ROOT)/timing_metrics.rpt
OPENSTA_CONFIG ?= $(VARIANT_ROOT)/syn/yosys/out/retrosoc_asic_yosys.config
OPENSTA_CONFIG ?= $(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.config
OPENSTA_SDC ?= $(STA_BUILD_ROOT)/retrosoc_core.sdc
OPENSTA_SDC_GEN := $(ROOT_PATH)/physical/smoke/sta/opensta/generate_sdc.py
OPENSTA_DOMAIN_MAP := $(ROOT_PATH)/rtl/mini/integration/clock_reset_domains.json
+25 -8
View File
@@ -10,25 +10,42 @@ Use a committed profile and run the supported flow:
make CONFIG=configs/ci/ihp130.mk SYNTH=YOSYS synth
```
`SYNTH_RECIPE` selects the ABC mapping recipe without changing the variant hash:
`SYNTH_RECIPE` selects the ABC mapping recipe without changing the variant hash.
The recipe also selects the synthesis-derived output roots so timing, netlist
simulation, and metrics cannot accidentally consume the `balanced` netlist:
- `balanced` (default) writes `build/<variant>/syn/yosys/`
- `area` writes `build/<variant>/syn/yosys-area/`
- `speed` writes `build/<variant>/syn/yosys-speed/`
- `balanced` (default): `syn/yosys/`, `sta/opensta/`, `sim/<tool>/netl/`, and `meta/metrics.json`
- `area`: `syn/yosys-area/`, `sta/opensta-area/`, `sim/<tool>/netl-area/`, and `meta/metrics-area.json`
- `speed`: `syn/yosys-speed/`, `sta/opensta-speed/`, `sim/<tool>/netl-speed/`, and `meta/metrics-speed.json`
STA, netlist simulation, warning analysis, and metrics consume the default
`syn/yosys/` slot. Nightly IHP130 regression also runs the `area` and `speed`
recipes as synth-only extra jobs.
`balanced` remains the PR and default CI recipe. Nightly IHP130 runs `area`
and `speed` through synthesis, OpenSTA, and metrics; their long netlist
simulation is available on demand but is not part of nightly-extra.
```sh
make CONFIG=configs/ci/ihp130.mk SYNTH=YOSYS SYNTH_RECIPE=area synth
make CONFIG=configs/ci/ihp130.mk SYNTH=YOSYS SYNTH_RECIPE=speed synth
make CONFIG=configs/ci/ihp130.mk SYNTH_RECIPE=area STA=OPENSTA sta
make CONFIG=configs/ci/ihp130.mk SYNTH_RECIPE=area metrics
make CONFIG=configs/ci/ihp130.mk SYNTH_RECIPE=area SIMU=IVERILOG netsim
```
Replace `area` with `speed` for the corresponding recipe. Run all three
recipes with the same commit, PDK, `BUILD_TIMESTAMP`, and
`YOSYS_TARGET_PERIOD_PS` when collecting a comparable QoR baseline.
Compare top area, cell count, WNS/TNS, synthesis and STA duration, warning
signatures, and the netlist simulation verdict. Area is an area-first mapping
recipe and speed is a timing-first exploration recipe; neither is promoted to
the default solely from one area or timing result. Metrics remain in observe
mode until the documented baseline review is complete.
The default ABC target period is derived from the `external` STA period in
`rtl/mini/integration/clock_reset_domains.json`. Override it with
`YOSYS_TARGET_PERIOD_PS=<ps>` when needed.
Synthesis outputs are generated below `build/` and must not be committed.
Review warning and metric changes with `make check-warnings check-metrics` for
the affected profile.
the affected profile. `make metrics` writes the recipe-specific file listed
above; `make check-metrics` checks that same file.
-11
View File
@@ -28,16 +28,6 @@ source $script_dir/init_tech.tcl
yosys read_slang --top $top_design -F $sv_flist \
--keep-hierarchy --allow-use-before-declare --ignore-initial --ignore-timing
# # blackbox requested modules
# if { [info exists ::env(YOSYS_BLACKBOX_MODULES)] } {
# foreach sel $::env(YOSYS_BLACKBOX_MODULES) {
# puts "Blackboxing the module ${sel}"
# yosys select -list {*}$sel
# yosys blackbox {*}$sel
# yosys setattr -set keep_hierarchy 1 {*}$sel
# }
# }
# # preserve hierarchy of selected modules/instances
if { [info exists ::env(YOSYS_KEEP_HIER_INST)] } {
foreach sel $::env(YOSYS_KEEP_HIER_INST) {
@@ -116,7 +106,6 @@ yosys select -write ${report_dir}/${proj_name}_registers.rpt t:*DFF*
yosys clean -purge
# print paths to important instances
yosys select -write ${report_dir}/${proj_name}_registers.rpt t:*DFF*
set report [open ${report_dir}/${proj_name}_instances.rpt "w"]
close $report
if { [info exists ::env(YOSYS_REPORT_INSTS)] } {
-3
View File
@@ -5,9 +5,6 @@
# Authors:
# - Philippe Sauter <phsauter@iis.ee.ethz.ch>
# modules Yosys will treat as blackboxes
export YOSYS_BLACKBOX_MODULES := "*tc_sram_blackbox*"
# flatten hierarchy (except for below selections)
export YOSYS_FLATTEN_HIER := 1
+2 -1
View File
@@ -21,6 +21,7 @@ FORMAL_I2C_TIMEOUT ?= 300
FORMAL_OPIPSRAM_TIMEOUT ?= 300
FORMAL_DMA_TIMEOUT ?= 120
FORMAL_SDIO_TIMEOUT ?= 120
FORMAL_COMPACT_COVER_TARGETS := i2c opipsram
FORMAL_TARGETS := bus rib_adapter rib2apb sysctrl pll_rcu gpio ws2812 uart i2c timer clint dvp i2s psram opipsram dma sdio
FORMAL_FILELIST_GENERATOR := $(RTL_PATH)/formal/generate_formal_filelist.py
FORMAL_SBY_GENERATOR := $(RTL_PATH)/formal/generate_sby_config.py
@@ -186,7 +187,7 @@ $(FORMAL_DIR)/%/cover.sby: $(FORMAL_DIR)/%/design.v $(RTL_PATH)/formal/%_formal_
python3 $(FORMAL_SBY_GENERATOR) --top $*_formal --input $< \
--properties $(RTL_PATH)/formal/$*_formal_props.sv --solver $(FORMAL_SOLVER) \
--mode cover --depth $(if $(filter dma,$*),$(FORMAL_DMA_COVER_DEPTH),$(if $(filter sdio,$*),$(FORMAL_SDIO_COVER_DEPTH),$(if $(filter opipsram,$*),$(FORMAL_OPIPSRAM_DEPTH),$(if $(filter ws2812,$*),$(FORMAL_WS2812_DEPTH),$(if $(filter i2c,$*),$(FORMAL_I2C_DEPTH),$(if $(filter clint,$*),$(FORMAL_CLINT_DEPTH),$(if $(filter psram,$*),$(FORMAL_PSRAM_DEPTH),$(FORMAL_DEPTH)))))))) \
$(if $(filter i2c,$*),--no-vcd) --output $@
$(if $(filter $(FORMAL_COMPACT_COVER_TARGETS),$*),--no-vcd) --output $@
@if [ "$*" = opipsram ]; then sed -i '/^async2sync/i clk2fflogic' $@; fi
$(FORMAL_DIR)/opipsram/bmc.sby: $(FORMAL_DIR)/opipsram/design.v \
+2 -2
View File
@@ -2,14 +2,14 @@ IVERILOG ?= iverilog
VVP ?= vvp
GTKWAVE ?= gtkwave
NETLIST_PATH ?= $(VARIANT_ROOT)/syn/yosys/out/retrosoc_asic_yosys.v
NETLIST_PATH ?= $(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v
POST_PATH ?= $(ROOT_PATH)/physical/sdf/retrosoc_asic.v
SDF_PATH ?= $(ROOT_PATH)/physical/sdf/retrosoc_asic_CTS_MIN.sdf.gz
SDF_SCOPE ?= $(RTL_TOP).u_retrosoc_asic
IVERILOG_ROOT := $(SIM_BUILD_ROOT)
IVERILOG_BEHV_DIR := $(IVERILOG_ROOT)/behv
IVERILOG_NETL_DIR := $(IVERILOG_ROOT)/netl
IVERILOG_NETL_DIR := $(NETLIST_SIM_ROOT)
IVERILOG_POST_DIR := $(IVERILOG_ROOT)/post
IVERILOG_BEHV_FLIST := $(IVERILOG_BEHV_DIR)/iverilog.fl
IVERILOG_NETL_FLIST := $(IVERILOG_NETL_DIR)/iverilog.fl
+5 -5
View File
@@ -10,7 +10,7 @@ VCS_FLOW_PYTHON := $(strip $(VCS_RUNNER) $(PYTHON))
COMP_LOG := -l compile.log
SIM_LOG := -l sim.log
# netlist file path
NETLIST_PATH := -v $(VARIANT_ROOT)/syn/yosys/out/retrosoc_asic_yosys.v
NETLIST_PATH := -v $(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v
POST_PATH := -v $(ROOT_PATH)/physical/sdf/retrosoc_asic.v
SDF_PATH := "$(ROOT_PATH)/physical/sdf/retrosoc_asic_CTS_MIN.sdf.gz"
# testbench filelist
@@ -48,7 +48,7 @@ SIM_OPTS := +vcs+loopreport+1000 -suppress=ASLR_DETECTED_INFO \
+sim_timeout=$(RTL_SIM_TIMEOUT) +wave_$(WAVE)
VCS_BEHV_DIR := $(SIM_BUILD_ROOT)/behv
VCS_NETL_DIR := $(SIM_BUILD_ROOT)/netl
VCS_NETL_DIR := $(NETLIST_SIM_ROOT)
VCS_POST_DIR := $(SIM_BUILD_ROOT)/post
VCS_BEHV_SIMV := $(VCS_BEHV_DIR)/simv
VCS_NETL_SIMV := $(VCS_NETL_DIR)/simv
@@ -69,7 +69,7 @@ $(VCS_NETL_SIMV): DIR := $(VCS_NETL_DIR)
$(VCS_NETL_SIMV): FLIST := $(NETLIST_PATH) $(NET_FLIST) $(TB_FLIST)
$(VCS_NETL_SIMV): OPTS := $(TIME_OPTION)
$(VCS_NETL_SIMV): DEPFILE := $(VCS_NETL_DEPFILE)
$(VCS_NETL_SIMV): DEPS_ARGS := $(NET_FLIST) -f $(GENERATED_FL_DIR)/tb.fl --extra $(VARIANT_ROOT)/syn/yosys/out/retrosoc_asic_yosys.v
$(VCS_NETL_SIMV): DEPS_ARGS := $(NET_FLIST) -f $(GENERATED_FL_DIR)/tb.fl --extra $(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v
$(VCS_POST_SIMV): DIR := $(VCS_POST_DIR)
$(VCS_POST_SIMV): FLIST := $(POST_PATH) $(NET_FLIST) $(TB_FLIST)
@@ -82,7 +82,7 @@ netsim: DIR := $(VCS_NETL_DIR)
postsim: DIR := $(VCS_POST_DIR)
wave: DIR := $(SIM_BUILD_ROOT)/behv
netwave: DIR := $(SIM_BUILD_ROOT)/netl
netwave: DIR := $(NETLIST_SIM_ROOT)
postwave: DIR := $(SIM_BUILD_ROOT)/post
comp: $(VCS_BEHV_SIMV)
@@ -101,7 +101,7 @@ $(VCS_BEHV_SIMV) $(VCS_NETL_SIMV) $(VCS_POST_SIMV): $(MPW_VARIANT_STAMP) $(FILEL
$(SIM_TOOL) $(COMMON_OPTS) $(OPTS) $(FLIST) -top $(RTL_TOP) $(COMP_LOG)
$(FLOW_PYTHON) $(RTL_PATH)/script/filelist_deps.py $(DEPS_ARGS) --target $@ --output $(DEPFILE)
$(VCS_NETL_SIMV): $(VARIANT_ROOT)/syn/yosys/out/retrosoc_asic_yosys.v
$(VCS_NETL_SIMV): $(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v
$(VCS_POST_SIMV): $(ROOT_PATH)/physical/sdf/retrosoc_asic.v $(ROOT_PATH)/physical/sdf/retrosoc_asic_CTS_MIN.sdf.gz
sim netsim postsim:
+23 -5
View File
@@ -22,19 +22,21 @@ HIERARCHY_RE = re.compile(r"^\s*(\d+)\s+[0-9.eE+-]+\s+retrosoc_asic\s*$", re.MUL
def collect(args: argparse.Namespace) -> int:
root = args.variant_root.resolve()
synth_root = (args.synth_root or root / "syn/yosys").resolve()
sta_root = (args.sta_root or root / "sta/opensta").resolve()
metrics: dict[str, Any] = {
"schema_version": 1,
"schema_version": 2,
"policy": "observe",
"firmware": {},
"synthesis": {},
"synthesis": {"recipe": args.recipe},
"timing": {},
"flows": {},
}
for binary in sorted((root / "sw").glob("*.bin")):
metrics["firmware"][binary.name] = {"bytes": binary.stat().st_size}
area_json = root / "syn/yosys/rpt/retrosoc_asic_area.json"
area_report = root / "syn/yosys/rpt/retrosoc_asic_area.rpt"
area_json = synth_root / "rpt/retrosoc_asic_area.json"
area_report = synth_root / "rpt/retrosoc_asic_area.rpt"
if area_json.is_file():
design = json.loads(area_json.read_text(encoding="utf-8"))["design"]
metrics["synthesis"]["top_area"] = float(design["area"])
@@ -48,7 +50,7 @@ def collect(args: argparse.Namespace) -> int:
if hierarchy:
metrics["synthesis"]["top_cells"] = int(hierarchy[-1])
timing_report = root / "sta/opensta/timing_metrics.rpt"
timing_report = sta_root / "timing_metrics.rpt"
if timing_report.is_file():
labels = ("wns_min", "wns_max", "tns_min", "tns_max")
timing_text = timing_report.read_text(encoding="utf-8", errors="replace")
@@ -73,6 +75,19 @@ def collect(args: argparse.Namespace) -> int:
"status": data.get("status"),
"duration_seconds": data.get("duration_seconds"),
}
for label, result in (
("synthesis", synth_root / "result-synth.json"),
("sta", sta_root / "result-sta.json"),
):
if result.is_file():
try:
data = json.loads(result.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError):
continue
metrics["flows"][label] = {
"status": data.get("status"),
"duration_seconds": data.get("duration_seconds"),
}
atomic_write(args.output, json.dumps(metrics, indent=2, sort_keys=True) + "\n")
print(f"metrics: {args.output.resolve()}")
return 0
@@ -130,6 +145,9 @@ def parse_args() -> argparse.Namespace:
subparsers = parser.add_subparsers(dest="command", required=True)
collect_parser = subparsers.add_parser("collect")
collect_parser.add_argument("--variant-root", type=Path, required=True)
collect_parser.add_argument("--synth-root", type=Path)
collect_parser.add_argument("--sta-root", type=Path)
collect_parser.add_argument("--recipe", choices=("balanced", "area", "speed"), default="balanced")
collect_parser.add_argument("--output", type=Path, required=True)
baseline_parser = subparsers.add_parser("baseline")
baseline_parser.add_argument("--input", type=Path, action="append", required=True)
+4
View File
@@ -65,7 +65,11 @@ NIGHTLY_EXTRA_COMMANDS = (
("SIMU=VERILATOR", "HAVE_SVA=YES", "coremark-report"),
),
("configs/ci/ihp130.mk", ("SYNTH=YOSYS", "SYNTH_RECIPE=area", "synth")),
("configs/ci/ihp130.mk", ("STA=OPENSTA", "SYNTH_RECIPE=area", "sta")),
("configs/ci/ihp130.mk", ("SYNTH_RECIPE=area", "metrics")),
("configs/ci/ihp130.mk", ("SYNTH=YOSYS", "SYNTH_RECIPE=speed", "synth")),
("configs/ci/ihp130.mk", ("STA=OPENSTA", "SYNTH_RECIPE=speed", "sta")),
("configs/ci/ihp130.mk", ("SYNTH_RECIPE=speed", "metrics")),
)
NIGHTLY_COMMANDS = (
*PR_COMMANDS,
+57 -1
View File
@@ -894,10 +894,26 @@ def test_nightly_regression_runs_optional_yosys_recipes() -> None:
"configs/ci/ihp130.mk",
("SYNTH=YOSYS", "SYNTH_RECIPE=area", "synth"),
) in NIGHTLY_COMMANDS
assert (
"configs/ci/ihp130.mk",
("STA=OPENSTA", "SYNTH_RECIPE=area", "sta"),
) in NIGHTLY_COMMANDS
assert (
"configs/ci/ihp130.mk",
("SYNTH_RECIPE=area", "metrics"),
) in NIGHTLY_COMMANDS
assert (
"configs/ci/ihp130.mk",
("SYNTH=YOSYS", "SYNTH_RECIPE=speed", "synth"),
) in NIGHTLY_COMMANDS
assert (
"configs/ci/ihp130.mk",
("STA=OPENSTA", "SYNTH_RECIPE=speed", "sta"),
) in NIGHTLY_COMMANDS
assert (
"configs/ci/ihp130.mk",
("SYNTH_RECIPE=speed", "metrics"),
) in NIGHTLY_COMMANDS
assert not any(
any(value.startswith("SYNTH_RECIPE=") for value in values) for _, values in PR_COMMANDS
)
@@ -914,7 +930,11 @@ def test_nightly_regression_runs_optional_yosys_recipes() -> None:
"--dry-run",
)
assert "+ make CONFIG=configs/ci/ihp130.mk SYNTH=YOSYS SYNTH_RECIPE=area synth" in nightly.stdout
assert "+ make CONFIG=configs/ci/ihp130.mk STA=OPENSTA SYNTH_RECIPE=area sta" in nightly.stdout
assert "+ make CONFIG=configs/ci/ihp130.mk SYNTH_RECIPE=area metrics" in nightly.stdout
assert "+ make CONFIG=configs/ci/ihp130.mk SYNTH=YOSYS SYNTH_RECIPE=speed synth" in nightly.stdout
assert "+ make CONFIG=configs/ci/ihp130.mk STA=OPENSTA SYNTH_RECIPE=speed sta" in nightly.stdout
assert "+ make CONFIG=configs/ci/ihp130.mk SYNTH_RECIPE=speed metrics" in nightly.stdout
pr = run(
sys.executable,
@@ -953,7 +973,11 @@ def test_nightly_extra_regression_skips_pr_netsim() -> None:
)
assert "+ make CONFIG=configs/benchmark/ihp130-hazard3-coremark.mk SIMU=VERILATOR HAVE_SVA=YES coremark-report" in extra.stdout
assert "+ make CONFIG=configs/ci/ihp130.mk SYNTH=YOSYS SYNTH_RECIPE=area synth" in extra.stdout
assert "+ make CONFIG=configs/ci/ihp130.mk STA=OPENSTA SYNTH_RECIPE=area sta" in extra.stdout
assert "+ make CONFIG=configs/ci/ihp130.mk SYNTH_RECIPE=area metrics" in extra.stdout
assert "+ make CONFIG=configs/ci/ihp130.mk SYNTH=YOSYS SYNTH_RECIPE=speed synth" in extra.stdout
assert "+ make CONFIG=configs/ci/ihp130.mk STA=OPENSTA SYNTH_RECIPE=speed sta" in extra.stdout
assert "+ make CONFIG=configs/ci/ihp130.mk SYNTH_RECIPE=speed metrics" in extra.stdout
assert "netsim" not in extra.stdout
invalid = subprocess.run(
@@ -1522,7 +1546,7 @@ def test_metrics_collection_and_observe_policy(tmp_path: Path) -> None:
)
data = json.loads(metrics.read_text(encoding="utf-8"))
assert data["firmware"]["firmware.bin"]["bytes"] == 4
assert data["synthesis"] == {"top_area": 124.0, "top_cells": 43}
assert data["synthesis"] == {"recipe": "balanced", "top_area": 124.0, "top_cells": 43}
assert data["timing"]["wns_min"] == -1.0
policy = tmp_path / "policy.json"
@@ -1538,6 +1562,38 @@ def test_metrics_collection_and_observe_policy(tmp_path: Path) -> None:
)
def test_metrics_collection_selects_recipe_roots(tmp_path: Path) -> None:
variant = tmp_path / "variant"
synth_root = variant / "syn/yosys-area"
sta_root = variant / "sta/opensta-area"
(synth_root / "rpt").mkdir(parents=True)
sta_root.mkdir(parents=True)
(synth_root / "rpt/retrosoc_asic_area.json").write_text(
json.dumps({"design": {"area": 88.0, "num_cells": 19}}), encoding="utf-8"
)
(sta_root / "timing_metrics.rpt").write_text("wns_max=-0.25\n", encoding="utf-8")
metrics = tmp_path / "metrics-area.json"
run(
sys.executable,
str(ROOT / "scripts/metrics.py"),
"collect",
"--variant-root",
str(variant),
"--synth-root",
str(synth_root),
"--sta-root",
str(sta_root),
"--recipe",
"area",
"--output",
str(metrics),
)
data = json.loads(metrics.read_text(encoding="utf-8"))
assert data["schema_version"] == 2
assert data["synthesis"] == {"recipe": "area", "top_area": 88.0, "top_cells": 19}
assert data["timing"]["wns_max"] == -0.25
def test_safe_extract_rejects_parent_traversal(tmp_path: Path) -> None:
archive = tmp_path / "unsafe.tar"
with tarfile.open(archive, "w") as bundle:
+9 -5
View File
@@ -48,6 +48,9 @@ def test_yosys_recipe_scripts_and_public_slot_are_stable() -> None:
assert "SYNTH_RECIPE ?= balanced" in makefile
assert "VALID_SYNTH_RECIPE := balanced area speed" in makefile
assert "syn/yosys-$(SYNTH_RECIPE)" in makefile
assert "sta/opensta-$(SYNTH_RECIPE)" in makefile
assert "netl-$(SYNTH_RECIPE)" in makefile
assert "metrics-$(SYNTH_RECIPE).json" in makefile
assert "CONFIG_KEY_VARS" in makefile
assert "SYNTH_RECIPE" not in makefile.split("CONFIG_KEY_VARS", 1)[1].split("VARIANT_ID", 1)[0]
assert "--env SYNTH_RECIPE=$(SYNTH_RECIPE)" in yosys_mk
@@ -55,11 +58,12 @@ def test_yosys_recipe_scripts_and_public_slot_are_stable() -> None:
assert "abc_${synth_recipe}.script" in synth_tcl
assert "yosys abc {*}$tech_cells_args -D $period_ps -script $abc_script -constr $abc_constr" in synth_tcl
assert "S110" not in synth_tcl
assert "$(VARIANT_ROOT)/syn/yosys/out/retrosoc_asic_yosys.v" in opensta
assert "$(VARIANT_ROOT)/syn/yosys/out/retrosoc_asic_yosys.v" in iverilog
assert "$(VARIANT_ROOT)/syn/yosys/out/retrosoc_asic_yosys.v" in vcs
assert "SYN_BUILD_ROOT" not in opensta
assert "SYN_BUILD_ROOT" not in iverilog.split("NETLIST_PATH", 1)[1][:200]
assert "$(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v" in opensta
assert "$(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v" in iverilog
assert "$(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v" in vcs
assert "$(NETLIST_SIM_ROOT)" in iverilog
assert "$(NETLIST_SIM_ROOT)" in vcs
assert "$(VARIANT_ROOT)/syn/yosys/out/retrosoc_asic_yosys.v" not in vcs
assert (YOSYS_SCRIPTS / "abc_balanced.script").read_text(encoding="utf-8").count("&nf {D}") == 1
assert "&nf {D}" not in (YOSYS_SCRIPTS / "abc_area.script").read_text(encoding="utf-8")
assert (YOSYS_SCRIPTS / "abc_speed.script").read_text(encoding="utf-8").count("&nf {D}") == 6