Skip to content
Draft
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
11 changes: 0 additions & 11 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,6 @@ single_version_override(
version = "3.8.2.bcr.7",
)

# tclZipfs.c's '#include "crypt.h"' picks up glibc's crypt.h instead of
# the vendored minizip one when glibc headers are explicit -isystem
# directories (hermetic-llvm zero-sysroot toolchain). Drop when fixed
# in a tcl_lang BCR release.
single_version_override(
module_name = "tcl_lang",
patch_strip = 1,
patches = [
"//patches/tcl_lang:0001-tclZipfs-include-vendored-minizip-crypt.h-by-path.patch",
],
)

bazel_dep(name = "openroad", dev_dependency = True)
local_path_override(
Expand Down
17 changes: 15 additions & 2 deletions flow/BUILD
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
load("@bazel-orfs//:openroad.bzl", "orfs_pdk")
load("@rules_python//python:defs.bzl", "py_library", "py_test")
load("@rules_python//python:defs.bzl", "py_library", "py_test", "py_binary")

# Expose every individual file under platforms/ as a public source-file
# target, so designs in other packages can refer to e.g.
Expand All @@ -24,7 +24,10 @@ exports_files(
# instead of vendoring its own (drifting) copy at the bazel-orfs repo
# root. See bazel-orfs `private/rules.bzl`.
exports_files(
["scripts/synth.tcl"],
[
"scripts/synth.tcl",
"scripts/place_only_and_measure.tcl",
],
visibility = ["//visibility:public"],
)

Expand Down Expand Up @@ -229,3 +232,13 @@ test_suite(
name = "memories_tests",
tests = ["memories_" + test for test in MEMORIES_TESTS],
)

py_binary(
name = "tune_gpl_magic",
srcs = ["scripts/tune_gpl_magic.py"],
deps = [
"@orfs-pip//optuna",
"@orfs-pip//pyyaml",
],
visibility = ["//visibility:public"],
)
1 change: 1 addition & 0 deletions flow/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ ifeq ($(SYNTH_USE_SYN),1)
$(eval $(call do-step,1_synth,$(VERILOG_FILES) $(SDC_FILE) $(TECH_LEF) $(SC_LEF) $(ADDITIONAL_LEFS) $(LIB_FILES),synth_syn))
else
$(eval $(call do-step,1_synth,$(RESULTS_DIR)/1_2_yosys.v $(RESULTS_DIR)/1_2_yosys.sdc $(TECH_LEF) $(SC_LEF) $(ADDITIONAL_LEFS) $(LIB_FILES),synth_odb))
do-1_synth: $(RESULTS_DIR)/1_2_yosys.sdc
endif

$(RESULTS_DIR)/1_synth.sdc: $(RESULTS_DIR)/1_synth.odb
Expand Down
1 change: 0 additions & 1 deletion flow/designs/asap7/gcd/config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,3 @@ export PLACE_DENSITY = 0.35
# few last gasp iterations
export SKIP_LAST_GASP ?= 1

export SYNTH_USE_SYN = 1
36 changes: 33 additions & 3 deletions flow/designs/design.bzl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""BUILD boilerplate for flow/designs/."""

load("@bazel-orfs//:openroad.bzl", "orfs_flow")
load("@orfs_designs//:designs.bzl", "orfs_design")
load("@bazel-orfs//:openroad.bzl", "orfs_flow", "orfs_run")
load("@orfs_designs//:designs.bzl", "orfs_design", "DESIGNS")

# Per filegroup target: extensions included in the filegroup.
# bazel-orfs's config_mk_parser produces these target names from
Expand All @@ -18,7 +18,7 @@ _GROUPS = {
# cross-package references resolve. Kept tight on purpose: globbing "*"
# silently exposes LICENSE/.gitignore/etc. as the public API surface.
# gds/gds.gz are inputs in hierarchical flows via ADDITIONAL_GDS.
_EXPORTED_EXTS = ["v", "sv", "svh", "tcl", "sdc", "def", "cfg", "lef", "lib", "gds", "gds.gz"]
_EXPORTED_EXTS = ["v", "sv", "svh", "tcl", "sdc", "def", "cfg", "lef", "lib", "gds", "gds.gz", "memories"]

_EXPORTS_SENTINEL = "_orfs_design_exports_sentinel"

Expand Down Expand Up @@ -79,6 +79,36 @@ def design(config = "config.mk", user_arguments = [], user_sources = [], local_a
blender = True,
)

pkg = native.package_name()
if pkg.startswith("flow/designs/"):
design_id = pkg[len("flow/designs/"):]
if design_id in DESIGNS:
design_args = DESIGNS[design_id]["arguments"]
# Find the actual synth target name instantiated by orfs_design
synth_name = None
for rule_name in native.existing_rules().keys():
if rule_name.endswith("_synth"):
synth_name = rule_name
break

if synth_name:
design_name = synth_name[:-6] # Remove "_synth"
args_copy = {k: v for k, v in design_args.items()}
args_copy["FLOW_VARIANT"] = "tune_gpl"
platform = args_copy.get("PLATFORM", design_id.split('/')[0])
real_design_name = args_copy.get("DESIGN_NAME", design_name)
orfs_run(
name = design_name + "_tune_gpl",
src = ":" + synth_name,
data = [":design_config"],
outs = [
"results/{}/{}/tune_gpl/target_function.txt".format(platform, real_design_name),
],
arguments = args_copy,
script = "//flow:scripts/place_only_and_measure.tcl",
variant = "tune_gpl",
)

def files(group, extra_srcs = None):
"""Named filegroup over conventional extensions.

Expand Down
5 changes: 5 additions & 0 deletions flow/platforms/asap7/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"GPL_TIMING_SPAN_CLOCK_PERCENT": 0.22968514538823603,
"GPL_WIRELENGTH_PENALTY": 0.06456297861599444,
"TIGHTEN_CLOCK_PERIOD": 0.018604621846273695
}
5 changes: 5 additions & 0 deletions flow/platforms/sky130hd/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"GPL_TIMING_SPAN_CLOCK_PERCENT": 0.188034183753787,
"GPL_WIRELENGTH_PENALTY": 0.028702330955746383,
"TIGHTEN_CLOCK_PERIOD": 0.04743068706084326
}
15 changes: 15 additions & 0 deletions flow/scripts/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@
with open(json_path, "r") as file:
data = json.load(file)

platform_dir = os.environ.get("PLATFORM_DIR")
if platform_dir:
platform_config_path = os.path.join(platform_dir, "config.json")
if os.path.exists(platform_config_path):
with open(platform_config_path, "r") as file:
try:
platform_data = json.load(file)
for key, value in platform_data.items():
if key in data:
data[key]["default"] = value
else:
data[key] = {"default": value}
except json.JSONDecodeError:
pass

for key, value in data.items():
if value.get("default", None) is None:
continue
Expand Down
8 changes: 8 additions & 0 deletions flow/scripts/global_place.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ append_env_var global_placement_args GPL_ROUTABILITY_DRIVEN -routability_driven

append_env_var global_placement_args GPL_RANDOM_SEED -random_seed 1

if { [info exists ::env(GPL_WIRELENGTH_PENALTY)] } {
lappend global_placement_args -init_wirelength_coef $::env(GPL_WIRELENGTH_PENALTY)
}

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.

remove iffy code default values are guaranteed so env vars here are always set.


if { [info exists ::env(GPL_TIMING_SPAN_CLOCK_PERCENT)] } {
lappend global_placement_args -virtual_cts_max_skew_fraction $::env(GPL_TIMING_SPAN_CLOCK_PERCENT)
}

# Parameters for timing driven mode in global placement
if { $::env(GPL_TIMING_DRIVEN) } {
lappend global_placement_args {-timing_driven}
Expand Down
42 changes: 42 additions & 0 deletions flow/scripts/place_only_and_measure.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Runs OpenROAD flow up to placement and evaluates minimum achievable clock period.

set ::env(KEEP_VARS) 1
set ::env(WRITE_ODB_AND_SDC_EACH_STAGE) 0

if { [info exists ::env(ODB_FILE)] } {
set odb_path $::env(ODB_FILE)
set sdc_path [file rootname $odb_path].sdc
file copy -force $odb_path $::env(RESULTS_DIR)/1_synth.odb
file copy -force $sdc_path $::env(RESULTS_DIR)/1_synth.sdc
}

# The synth_odb stage already canonicalized constraints into 1_synth.sdc.
# Unset SDC_FILE so floorplan.tcl doesn't try to read the original file path
# which might fail inside the bazel sandbox.
unset -nocomplain ::env(SDC_FILE)

set ::flow_expected [glob -nocomplain -directory $::env(RESULTS_DIR) *.odb *.sdc]

proc flow_source { script } {
uplevel #0 [list source $::env(SCRIPTS_DIR)/$script]
foreach f [glob -nocomplain -directory $::env(RESULTS_DIR) *.odb *.sdc] {
if { [lsearch -exact $::flow_expected $f] == -1 } {
error "$script wrote $f: with WRITE_ODB_AND_SDC_EACH_STAGE=0 stage scripts must not write .odb/.sdc files"
}
}
}

# Run the flow up to place

flow_source floorplan.tcl
flow_source macro_place.tcl
flow_source tapcell.tcl
flow_source pdn.tcl
flow_source global_place_skip_io.tcl
flow_source io_placement.tcl
flow_source global_place.tcl
flow_source resize.tcl
flow_source detail_place.tcl

# Evaluate target function (measures clock / WNS)
flow_source target-function.tcl
18 changes: 18 additions & 0 deletions flow/scripts/target-function.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Evaluate placement by tightening clocks and measuring WNS

if { [info exists ::env(TIGHTEN_CLOCK_PERIOD)] } {
foreach clk [all_clocks] {
set period [get_property $clk period]
set uncertainty [expr {$period * $::env(TIGHTEN_CLOCK_PERIOD)}]
set_clock_uncertainty -setup $uncertainty $clk
puts "TIGHTEN_CLOCK_PERIOD: Set setup uncertainty for clock [get_property $clk name] to $uncertainty"
}
}

estimate_parasitics -placement
set wns [sta::time_sta_ui [sta::worst_slack_cmd "max"]]
puts "Target Function WNS: $wns"

set f [open [file join $::env(RESULTS_DIR) "target_function.txt"] w]
puts $f $wns
close $f
Loading