siliconcompiler 0.26.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- siliconcompiler/__init__.py +24 -0
- siliconcompiler/__main__.py +12 -0
- siliconcompiler/_common.py +49 -0
- siliconcompiler/_metadata.py +36 -0
- siliconcompiler/apps/__init__.py +0 -0
- siliconcompiler/apps/_common.py +76 -0
- siliconcompiler/apps/sc.py +92 -0
- siliconcompiler/apps/sc_dashboard.py +94 -0
- siliconcompiler/apps/sc_issue.py +178 -0
- siliconcompiler/apps/sc_remote.py +199 -0
- siliconcompiler/apps/sc_server.py +39 -0
- siliconcompiler/apps/sc_show.py +142 -0
- siliconcompiler/apps/smake.py +232 -0
- siliconcompiler/checklists/__init__.py +0 -0
- siliconcompiler/checklists/oh_tapeout.py +41 -0
- siliconcompiler/core.py +3221 -0
- siliconcompiler/data/RobotoMono/LICENSE.txt +202 -0
- siliconcompiler/data/RobotoMono/RobotoMono-Regular.ttf +0 -0
- siliconcompiler/data/heartbeat.v +18 -0
- siliconcompiler/data/logo.png +0 -0
- siliconcompiler/flowgraph.py +570 -0
- siliconcompiler/flows/__init__.py +0 -0
- siliconcompiler/flows/_common.py +67 -0
- siliconcompiler/flows/asicflow.py +180 -0
- siliconcompiler/flows/asictopflow.py +38 -0
- siliconcompiler/flows/dvflow.py +86 -0
- siliconcompiler/flows/fpgaflow.py +202 -0
- siliconcompiler/flows/generate_openroad_rcx.py +66 -0
- siliconcompiler/flows/lintflow.py +35 -0
- siliconcompiler/flows/screenshotflow.py +51 -0
- siliconcompiler/flows/showflow.py +59 -0
- siliconcompiler/flows/signoffflow.py +53 -0
- siliconcompiler/flows/synflow.py +128 -0
- siliconcompiler/fpgas/__init__.py +0 -0
- siliconcompiler/fpgas/lattice_ice40.py +42 -0
- siliconcompiler/fpgas/vpr_example.py +109 -0
- siliconcompiler/issue.py +300 -0
- siliconcompiler/libs/__init__.py +0 -0
- siliconcompiler/libs/asap7sc7p5t.py +8 -0
- siliconcompiler/libs/gf180mcu.py +8 -0
- siliconcompiler/libs/nangate45.py +8 -0
- siliconcompiler/libs/sky130hd.py +8 -0
- siliconcompiler/libs/sky130io.py +8 -0
- siliconcompiler/package.py +412 -0
- siliconcompiler/pdks/__init__.py +0 -0
- siliconcompiler/pdks/asap7.py +8 -0
- siliconcompiler/pdks/freepdk45.py +8 -0
- siliconcompiler/pdks/gf180.py +8 -0
- siliconcompiler/pdks/skywater130.py +8 -0
- siliconcompiler/remote/__init__.py +36 -0
- siliconcompiler/remote/client.py +891 -0
- siliconcompiler/remote/schema.py +106 -0
- siliconcompiler/remote/server.py +507 -0
- siliconcompiler/remote/server_schema/requests/cancel_job.json +51 -0
- siliconcompiler/remote/server_schema/requests/check_progress.json +61 -0
- siliconcompiler/remote/server_schema/requests/check_server.json +38 -0
- siliconcompiler/remote/server_schema/requests/delete_job.json +51 -0
- siliconcompiler/remote/server_schema/requests/get_results.json +48 -0
- siliconcompiler/remote/server_schema/requests/remote_run.json +40 -0
- siliconcompiler/remote/server_schema/responses/cancel_job.json +18 -0
- siliconcompiler/remote/server_schema/responses/check_progress.json +30 -0
- siliconcompiler/remote/server_schema/responses/check_server.json +32 -0
- siliconcompiler/remote/server_schema/responses/delete_job.json +18 -0
- siliconcompiler/remote/server_schema/responses/get_results.json +21 -0
- siliconcompiler/remote/server_schema/responses/remote_run.json +25 -0
- siliconcompiler/report/__init__.py +13 -0
- siliconcompiler/report/html_report.py +74 -0
- siliconcompiler/report/report.py +355 -0
- siliconcompiler/report/streamlit_report.py +137 -0
- siliconcompiler/report/streamlit_viewer.py +944 -0
- siliconcompiler/report/summary_image.py +117 -0
- siliconcompiler/report/summary_table.py +105 -0
- siliconcompiler/report/utils.py +163 -0
- siliconcompiler/scheduler/__init__.py +2092 -0
- siliconcompiler/scheduler/docker_runner.py +253 -0
- siliconcompiler/scheduler/run_node.py +138 -0
- siliconcompiler/scheduler/send_messages.py +178 -0
- siliconcompiler/scheduler/slurm.py +208 -0
- siliconcompiler/scheduler/validation/email_credentials.json +54 -0
- siliconcompiler/schema/__init__.py +7 -0
- siliconcompiler/schema/schema_cfg.py +4014 -0
- siliconcompiler/schema/schema_obj.py +1841 -0
- siliconcompiler/schema/utils.py +93 -0
- siliconcompiler/sphinx_ext/__init__.py +0 -0
- siliconcompiler/sphinx_ext/dynamicgen.py +1006 -0
- siliconcompiler/sphinx_ext/schemagen.py +221 -0
- siliconcompiler/sphinx_ext/utils.py +166 -0
- siliconcompiler/targets/__init__.py +0 -0
- siliconcompiler/targets/asap7_demo.py +68 -0
- siliconcompiler/targets/asic_demo.py +38 -0
- siliconcompiler/targets/fpgaflow_demo.py +47 -0
- siliconcompiler/targets/freepdk45_demo.py +59 -0
- siliconcompiler/targets/gf180_demo.py +77 -0
- siliconcompiler/targets/skywater130_demo.py +70 -0
- siliconcompiler/templates/email/general.j2 +66 -0
- siliconcompiler/templates/email/summary.j2 +43 -0
- siliconcompiler/templates/issue/README.txt +26 -0
- siliconcompiler/templates/issue/run.sh +6 -0
- siliconcompiler/templates/report/bootstrap.min.css +7 -0
- siliconcompiler/templates/report/bootstrap.min.js +7 -0
- siliconcompiler/templates/report/bootstrap_LICENSE.md +24 -0
- siliconcompiler/templates/report/sc_report.j2 +427 -0
- siliconcompiler/templates/slurm/run.sh +9 -0
- siliconcompiler/templates/tcl/manifest.tcl.j2 +137 -0
- siliconcompiler/tools/__init__.py +0 -0
- siliconcompiler/tools/_common/__init__.py +432 -0
- siliconcompiler/tools/_common/asic.py +115 -0
- siliconcompiler/tools/_common/sdc/sc_constraints.sdc +76 -0
- siliconcompiler/tools/_common/tcl/sc_pin_constraints.tcl +63 -0
- siliconcompiler/tools/bambu/bambu.py +32 -0
- siliconcompiler/tools/bambu/convert.py +77 -0
- siliconcompiler/tools/bluespec/bluespec.py +40 -0
- siliconcompiler/tools/bluespec/convert.py +103 -0
- siliconcompiler/tools/builtin/_common.py +155 -0
- siliconcompiler/tools/builtin/builtin.py +26 -0
- siliconcompiler/tools/builtin/concatenate.py +85 -0
- siliconcompiler/tools/builtin/join.py +27 -0
- siliconcompiler/tools/builtin/maximum.py +46 -0
- siliconcompiler/tools/builtin/minimum.py +57 -0
- siliconcompiler/tools/builtin/mux.py +70 -0
- siliconcompiler/tools/builtin/nop.py +38 -0
- siliconcompiler/tools/builtin/verify.py +83 -0
- siliconcompiler/tools/chisel/SCDriver.scala +10 -0
- siliconcompiler/tools/chisel/build.sbt +27 -0
- siliconcompiler/tools/chisel/chisel.py +37 -0
- siliconcompiler/tools/chisel/convert.py +140 -0
- siliconcompiler/tools/execute/exec_input.py +41 -0
- siliconcompiler/tools/execute/execute.py +17 -0
- siliconcompiler/tools/genfasm/bitstream.py +61 -0
- siliconcompiler/tools/genfasm/genfasm.py +40 -0
- siliconcompiler/tools/ghdl/convert.py +87 -0
- siliconcompiler/tools/ghdl/ghdl.py +41 -0
- siliconcompiler/tools/icarus/compile.py +87 -0
- siliconcompiler/tools/icarus/icarus.py +36 -0
- siliconcompiler/tools/icepack/bitstream.py +20 -0
- siliconcompiler/tools/icepack/icepack.py +43 -0
- siliconcompiler/tools/klayout/export.py +117 -0
- siliconcompiler/tools/klayout/klayout.py +119 -0
- siliconcompiler/tools/klayout/klayout_export.py +205 -0
- siliconcompiler/tools/klayout/klayout_operations.py +363 -0
- siliconcompiler/tools/klayout/klayout_show.py +242 -0
- siliconcompiler/tools/klayout/klayout_utils.py +176 -0
- siliconcompiler/tools/klayout/operations.py +194 -0
- siliconcompiler/tools/klayout/screenshot.py +98 -0
- siliconcompiler/tools/klayout/show.py +101 -0
- siliconcompiler/tools/magic/drc.py +49 -0
- siliconcompiler/tools/magic/extspice.py +19 -0
- siliconcompiler/tools/magic/magic.py +85 -0
- siliconcompiler/tools/magic/sc_drc.tcl +96 -0
- siliconcompiler/tools/magic/sc_extspice.tcl +54 -0
- siliconcompiler/tools/magic/sc_magic.tcl +47 -0
- siliconcompiler/tools/montage/montage.py +30 -0
- siliconcompiler/tools/montage/tile.py +66 -0
- siliconcompiler/tools/netgen/count_lvs.py +132 -0
- siliconcompiler/tools/netgen/lvs.py +90 -0
- siliconcompiler/tools/netgen/netgen.py +36 -0
- siliconcompiler/tools/netgen/sc_lvs.tcl +46 -0
- siliconcompiler/tools/nextpnr/apr.py +24 -0
- siliconcompiler/tools/nextpnr/nextpnr.py +59 -0
- siliconcompiler/tools/openfpgaloader/openfpgaloader.py +39 -0
- siliconcompiler/tools/openroad/__init__.py +0 -0
- siliconcompiler/tools/openroad/cts.py +45 -0
- siliconcompiler/tools/openroad/dfm.py +66 -0
- siliconcompiler/tools/openroad/export.py +131 -0
- siliconcompiler/tools/openroad/floorplan.py +70 -0
- siliconcompiler/tools/openroad/openroad.py +977 -0
- siliconcompiler/tools/openroad/physyn.py +27 -0
- siliconcompiler/tools/openroad/place.py +41 -0
- siliconcompiler/tools/openroad/rcx_bench.py +95 -0
- siliconcompiler/tools/openroad/rcx_extract.py +34 -0
- siliconcompiler/tools/openroad/route.py +45 -0
- siliconcompiler/tools/openroad/screenshot.py +60 -0
- siliconcompiler/tools/openroad/scripts/sc_apr.tcl +499 -0
- siliconcompiler/tools/openroad/scripts/sc_cts.tcl +64 -0
- siliconcompiler/tools/openroad/scripts/sc_dfm.tcl +20 -0
- siliconcompiler/tools/openroad/scripts/sc_export.tcl +98 -0
- siliconcompiler/tools/openroad/scripts/sc_floorplan.tcl +413 -0
- siliconcompiler/tools/openroad/scripts/sc_metrics.tcl +158 -0
- siliconcompiler/tools/openroad/scripts/sc_physyn.tcl +7 -0
- siliconcompiler/tools/openroad/scripts/sc_place.tcl +84 -0
- siliconcompiler/tools/openroad/scripts/sc_procs.tcl +423 -0
- siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +63 -0
- siliconcompiler/tools/openroad/scripts/sc_rcx_bench.tcl +20 -0
- siliconcompiler/tools/openroad/scripts/sc_rcx_extract.tcl +12 -0
- siliconcompiler/tools/openroad/scripts/sc_route.tcl +133 -0
- siliconcompiler/tools/openroad/scripts/sc_screenshot.tcl +21 -0
- siliconcompiler/tools/openroad/scripts/sc_write.tcl +5 -0
- siliconcompiler/tools/openroad/scripts/sc_write_images.tcl +361 -0
- siliconcompiler/tools/openroad/show.py +94 -0
- siliconcompiler/tools/openroad/templates/pex.tcl +8 -0
- siliconcompiler/tools/opensta/__init__.py +101 -0
- siliconcompiler/tools/opensta/report_libraries.py +28 -0
- siliconcompiler/tools/opensta/scripts/sc_procs.tcl +47 -0
- siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +74 -0
- siliconcompiler/tools/opensta/scripts/sc_timing.tcl +268 -0
- siliconcompiler/tools/opensta/timing.py +214 -0
- siliconcompiler/tools/slang/__init__.py +49 -0
- siliconcompiler/tools/slang/lint.py +101 -0
- siliconcompiler/tools/surelog/__init__.py +123 -0
- siliconcompiler/tools/surelog/parse.py +183 -0
- siliconcompiler/tools/surelog/templates/output.v +7 -0
- siliconcompiler/tools/sv2v/convert.py +46 -0
- siliconcompiler/tools/sv2v/sv2v.py +37 -0
- siliconcompiler/tools/template/template.py +125 -0
- siliconcompiler/tools/verilator/compile.py +139 -0
- siliconcompiler/tools/verilator/lint.py +19 -0
- siliconcompiler/tools/verilator/parse.py +27 -0
- siliconcompiler/tools/verilator/verilator.py +172 -0
- siliconcompiler/tools/vivado/__init__.py +7 -0
- siliconcompiler/tools/vivado/bitstream.py +21 -0
- siliconcompiler/tools/vivado/place.py +21 -0
- siliconcompiler/tools/vivado/route.py +21 -0
- siliconcompiler/tools/vivado/scripts/sc_bitstream.tcl +6 -0
- siliconcompiler/tools/vivado/scripts/sc_place.tcl +2 -0
- siliconcompiler/tools/vivado/scripts/sc_route.tcl +4 -0
- siliconcompiler/tools/vivado/scripts/sc_run.tcl +45 -0
- siliconcompiler/tools/vivado/scripts/sc_syn_fpga.tcl +25 -0
- siliconcompiler/tools/vivado/syn_fpga.py +20 -0
- siliconcompiler/tools/vivado/vivado.py +147 -0
- siliconcompiler/tools/vpr/_json_constraint.py +63 -0
- siliconcompiler/tools/vpr/_xml_constraint.py +109 -0
- siliconcompiler/tools/vpr/place.py +137 -0
- siliconcompiler/tools/vpr/route.py +124 -0
- siliconcompiler/tools/vpr/screenshot.py +54 -0
- siliconcompiler/tools/vpr/show.py +88 -0
- siliconcompiler/tools/vpr/vpr.py +357 -0
- siliconcompiler/tools/xyce/xyce.py +36 -0
- siliconcompiler/tools/yosys/lec.py +56 -0
- siliconcompiler/tools/yosys/prepareLib.py +59 -0
- siliconcompiler/tools/yosys/sc_lec.tcl +84 -0
- siliconcompiler/tools/yosys/sc_syn.tcl +79 -0
- siliconcompiler/tools/yosys/syn_asic.py +565 -0
- siliconcompiler/tools/yosys/syn_asic.tcl +377 -0
- siliconcompiler/tools/yosys/syn_asic_fpga_shared.tcl +31 -0
- siliconcompiler/tools/yosys/syn_fpga.py +146 -0
- siliconcompiler/tools/yosys/syn_fpga.tcl +233 -0
- siliconcompiler/tools/yosys/syn_strategies.tcl +81 -0
- siliconcompiler/tools/yosys/techmaps/lcu_kogge_stone.v +39 -0
- siliconcompiler/tools/yosys/templates/abc.const +2 -0
- siliconcompiler/tools/yosys/yosys.py +147 -0
- siliconcompiler/units.py +259 -0
- siliconcompiler/use.py +177 -0
- siliconcompiler/utils/__init__.py +423 -0
- siliconcompiler/utils/asic.py +158 -0
- siliconcompiler/utils/showtools.py +25 -0
- siliconcompiler-0.26.5.dist-info/LICENSE +190 -0
- siliconcompiler-0.26.5.dist-info/METADATA +195 -0
- siliconcompiler-0.26.5.dist-info/RECORD +251 -0
- siliconcompiler-0.26.5.dist-info/WHEEL +5 -0
- siliconcompiler-0.26.5.dist-info/entry_points.txt +12 -0
- siliconcompiler-0.26.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,977 @@
|
|
|
1
|
+
'''
|
|
2
|
+
OpenROAD is an automated physical design platform for
|
|
3
|
+
integrated circuit design with a complete set of features
|
|
4
|
+
needed to translate a synthesized netlist to a tapeout ready
|
|
5
|
+
GDSII.
|
|
6
|
+
|
|
7
|
+
Documentation: https://openroad.readthedocs.io/
|
|
8
|
+
|
|
9
|
+
Sources: https://github.com/The-OpenROAD-Project/OpenROAD
|
|
10
|
+
|
|
11
|
+
Installation: https://github.com/The-OpenROAD-Project/OpenROAD
|
|
12
|
+
'''
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
import json
|
|
16
|
+
from siliconcompiler import sc_open
|
|
17
|
+
from siliconcompiler import utils
|
|
18
|
+
from siliconcompiler.tools._common import input_provides, add_common_file, \
|
|
19
|
+
get_tool_task, record_metric
|
|
20
|
+
from siliconcompiler.tools._common.asic import get_mainlib, set_tool_task_var, get_libraries
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
####################################################################
|
|
24
|
+
# Make Docs
|
|
25
|
+
####################################################################
|
|
26
|
+
def make_docs(chip):
|
|
27
|
+
chip.load_target("asap7_demo")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
################################
|
|
31
|
+
# Setup Tool (pre executable)
|
|
32
|
+
################################
|
|
33
|
+
def setup_tool(chip, exit=True, clobber=True):
|
|
34
|
+
step = chip.get('arg', 'step')
|
|
35
|
+
index = chip.get('arg', 'index')
|
|
36
|
+
tool, task = get_tool_task(chip, step, index)
|
|
37
|
+
|
|
38
|
+
chip.set('tool', tool, 'exe', tool)
|
|
39
|
+
chip.set('tool', tool, 'vswitch', '-version')
|
|
40
|
+
chip.set('tool', tool, 'version', '>=v2.0-13145', clobber=clobber)
|
|
41
|
+
chip.set('tool', tool, 'format', 'tcl', clobber=clobber)
|
|
42
|
+
|
|
43
|
+
# exit automatically in batch mode and not breakpoint
|
|
44
|
+
option = ''
|
|
45
|
+
if exit and not chip.get('option', 'breakpoint', step=step, index=index):
|
|
46
|
+
option += " -exit"
|
|
47
|
+
|
|
48
|
+
option += " -metrics reports/metrics.json"
|
|
49
|
+
chip.set('tool', tool, 'task', task, 'option', option, step=step, index=index, clobber=clobber)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def setup(chip):
|
|
53
|
+
|
|
54
|
+
# default tool settings, note, not additive!
|
|
55
|
+
|
|
56
|
+
tool = 'openroad'
|
|
57
|
+
script = 'sc_apr.tcl'
|
|
58
|
+
refdir = os.path.join('tools', tool, 'scripts')
|
|
59
|
+
|
|
60
|
+
step = chip.get('arg', 'step')
|
|
61
|
+
index = chip.get('arg', 'index')
|
|
62
|
+
_, task = get_tool_task(chip, step, index)
|
|
63
|
+
pdkname = chip.get('option', 'pdk')
|
|
64
|
+
targetlibs = get_libraries(chip, 'logic')
|
|
65
|
+
mainlib = get_mainlib(chip)
|
|
66
|
+
macrolibs = get_libraries(chip, 'macro')
|
|
67
|
+
stackup = chip.get('option', 'stackup')
|
|
68
|
+
delaymodel = chip.get('asic', 'delaymodel', step=step, index=index)
|
|
69
|
+
libtype = chip.get('library', mainlib, 'asic', 'libarch', step=step, index=index)
|
|
70
|
+
|
|
71
|
+
is_screenshot = task == 'screenshot'
|
|
72
|
+
is_show_screenshot = task == 'show' or is_screenshot
|
|
73
|
+
|
|
74
|
+
if is_show_screenshot:
|
|
75
|
+
clobber = True
|
|
76
|
+
else:
|
|
77
|
+
clobber = False
|
|
78
|
+
|
|
79
|
+
# Fixed for tool
|
|
80
|
+
setup_tool(chip, exit=task != 'show', clobber=clobber)
|
|
81
|
+
|
|
82
|
+
# Input/Output requirements for default asicflow steps
|
|
83
|
+
|
|
84
|
+
chip.set('tool', tool, 'task', task, 'refdir', refdir,
|
|
85
|
+
step=step, index=index,
|
|
86
|
+
package='siliconcompiler', clobber=clobber)
|
|
87
|
+
chip.set('tool', tool, 'task', task, 'script', script,
|
|
88
|
+
step=step, index=index, clobber=clobber)
|
|
89
|
+
chip.set('tool', tool, 'task', task, 'threads', os.cpu_count(),
|
|
90
|
+
step=step, index=index, clobber=clobber)
|
|
91
|
+
|
|
92
|
+
if chip.get('option', 'nodisplay'):
|
|
93
|
+
# Tells QT to use the offscreen platform if nodisplay is used
|
|
94
|
+
chip.set('tool', tool, 'task', task, 'env', 'QT_QPA_PLATFORM', 'offscreen',
|
|
95
|
+
step=step, index=index)
|
|
96
|
+
|
|
97
|
+
if delaymodel != 'nldm':
|
|
98
|
+
chip.logger.error(f'{delaymodel} delay model is not supported by {tool}, only nldm')
|
|
99
|
+
|
|
100
|
+
if stackup and targetlibs:
|
|
101
|
+
# Note: only one footprint supported in mainlib
|
|
102
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
103
|
+
",".join(['asic', 'logiclib']),
|
|
104
|
+
step=step, index=index)
|
|
105
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
106
|
+
",".join(['option', 'stackup']),
|
|
107
|
+
step=step, index=index)
|
|
108
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
109
|
+
",".join(['library', mainlib, 'asic', 'site', libtype]),
|
|
110
|
+
step=step, index=index)
|
|
111
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
112
|
+
",".join(['pdk', pdkname, 'aprtech', 'openroad', stackup, libtype, 'lef']),
|
|
113
|
+
step=step, index=index)
|
|
114
|
+
|
|
115
|
+
for lib in targetlibs:
|
|
116
|
+
for timing_key in get_library_timing_keypaths(chip, lib).values():
|
|
117
|
+
chip.add('tool', tool, 'task', task, 'require', ",".join(timing_key),
|
|
118
|
+
step=step, index=index)
|
|
119
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
120
|
+
",".join(['library', lib, 'output', stackup, 'lef']),
|
|
121
|
+
step=step, index=index)
|
|
122
|
+
for lib in macrolibs:
|
|
123
|
+
for timing_key in get_library_timing_keypaths(chip, lib).values():
|
|
124
|
+
if chip.valid(*timing_key):
|
|
125
|
+
chip.add('tool', tool, 'task', task, 'require', ",".join(timing_key),
|
|
126
|
+
step=step, index=index)
|
|
127
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
128
|
+
",".join(['library', lib, 'output', stackup, 'lef']),
|
|
129
|
+
step=step, index=index)
|
|
130
|
+
else:
|
|
131
|
+
chip.error('Stackup and logiclib parameters required for OpenROAD.')
|
|
132
|
+
|
|
133
|
+
# Set required keys
|
|
134
|
+
for var0, var1 in [('openroad_tielow_cell', 'openroad_tielow_port'),
|
|
135
|
+
('openroad_tiehigh_cell', 'openroad_tiehigh_port')]:
|
|
136
|
+
key0 = ['library', mainlib, 'option', 'var', tool, var0]
|
|
137
|
+
key1 = ['library', mainlib, 'option', 'var', tool, var1]
|
|
138
|
+
if chip.valid(*key0):
|
|
139
|
+
chip.add('tool', tool, 'task', task, 'require', ",".join(key1), step=step, index=index)
|
|
140
|
+
if chip.valid(*key1):
|
|
141
|
+
chip.add('tool', tool, 'task', task, 'require', ",".join(key0), step=step, index=index)
|
|
142
|
+
|
|
143
|
+
for key in (['pdk', pdkname, 'var', 'openroad', 'rclayer_signal', stackup],
|
|
144
|
+
['pdk', pdkname, 'var', 'openroad', 'rclayer_clock', stackup],
|
|
145
|
+
['pdk', pdkname, 'var', 'openroad', 'pin_layer_horizontal', stackup],
|
|
146
|
+
['pdk', pdkname, 'var', 'openroad', 'pin_layer_vertical', stackup]):
|
|
147
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
148
|
+
",".join(key),
|
|
149
|
+
step=step, index=index)
|
|
150
|
+
|
|
151
|
+
# set default values for openroad
|
|
152
|
+
_define_ord_params(chip)
|
|
153
|
+
_define_sta_params(chip)
|
|
154
|
+
_define_sdc_params(chip)
|
|
155
|
+
_define_ifp_params(chip)
|
|
156
|
+
_define_pad_params(chip)
|
|
157
|
+
_define_ppl_params(chip)
|
|
158
|
+
_define_mpl_params(chip)
|
|
159
|
+
_define_pdn_params(chip)
|
|
160
|
+
_define_psm_params(chip)
|
|
161
|
+
_define_gpl_params(chip)
|
|
162
|
+
_define_dpl_params(chip)
|
|
163
|
+
_define_dpo_params(chip)
|
|
164
|
+
_define_cts_params(chip)
|
|
165
|
+
_define_rsz_params(chip)
|
|
166
|
+
_define_grt_params(chip)
|
|
167
|
+
_define_ant_params(chip)
|
|
168
|
+
_define_drt_params(chip)
|
|
169
|
+
_define_fin_params(chip)
|
|
170
|
+
_define_pex_params(chip)
|
|
171
|
+
|
|
172
|
+
add_common_file(chip, 'opensta_generic_sdc', 'sdc/sc_constraints.sdc')
|
|
173
|
+
|
|
174
|
+
# basic warning and error grep check on logfile
|
|
175
|
+
chip.set('tool', tool, 'task', task, 'regex', 'warnings', r'^\[WARNING|^Warning',
|
|
176
|
+
step=step, index=index, clobber=False)
|
|
177
|
+
chip.set('tool', tool, 'task', task, 'regex', 'errors', r'^\[ERROR',
|
|
178
|
+
step=step, index=index, clobber=False)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
################################
|
|
182
|
+
# Version Check
|
|
183
|
+
################################
|
|
184
|
+
def parse_version(stdout):
|
|
185
|
+
# stdout will be in one of the following forms:
|
|
186
|
+
# - 1 08de3b46c71e329a10aa4e753dcfeba2ddf54ddd
|
|
187
|
+
# - 1 v2.0-880-gd1c7001ad
|
|
188
|
+
# - v2.0-1862-g0d785bd84
|
|
189
|
+
|
|
190
|
+
# strip off the "1" prefix if it's there
|
|
191
|
+
version = stdout.split()[-1]
|
|
192
|
+
|
|
193
|
+
pieces = version.split('-')
|
|
194
|
+
if len(pieces) > 1:
|
|
195
|
+
# strip off the hash in the new version style
|
|
196
|
+
return '-'.join(pieces[:-1])
|
|
197
|
+
else:
|
|
198
|
+
return pieces[0]
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def normalize_version(version):
|
|
202
|
+
if '.' in version:
|
|
203
|
+
return version.lstrip('v')
|
|
204
|
+
else:
|
|
205
|
+
return '0'
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def pre_process(chip):
|
|
209
|
+
step = chip.get('arg', 'step')
|
|
210
|
+
index = chip.get('arg', 'index')
|
|
211
|
+
tool, task = get_tool_task(chip, step, index)
|
|
212
|
+
pdkname = chip.get('option', 'pdk')
|
|
213
|
+
targetlibs = get_libraries(chip, 'logic')
|
|
214
|
+
macrolibs = get_libraries(chip, 'macro')
|
|
215
|
+
mainlib = get_mainlib(chip)
|
|
216
|
+
stackup = chip.get('option', 'stackup')
|
|
217
|
+
libtype = chip.get('library', mainlib, 'asic', 'libarch', step=step, index=index)
|
|
218
|
+
|
|
219
|
+
# set tapcell file
|
|
220
|
+
tapfile = None
|
|
221
|
+
if chip.valid('library', mainlib, 'option', 'file', 'openroad_tapcells'):
|
|
222
|
+
tapfile = chip.find_files('library', mainlib, 'option', 'file', 'openroad_tapcells')
|
|
223
|
+
elif chip.valid('pdk', pdkname, 'aprtech', tool, stackup, libtype, 'tapcells'):
|
|
224
|
+
tapfile = chip.find_files('pdk', pdkname, 'aprtech', tool, stackup, libtype, 'tapcells')
|
|
225
|
+
if tapfile:
|
|
226
|
+
chip.set('tool', tool, 'task', task, 'file', 'ifp_tapcell', tapfile,
|
|
227
|
+
step=step, index=index, clobber=False)
|
|
228
|
+
|
|
229
|
+
for libvar, openroadvar in [('openroad_pdngen', 'pdn_config'),
|
|
230
|
+
('openroad_global_connect', 'global_connect')]:
|
|
231
|
+
if chip.valid('tool', tool, 'task', task, 'file', openroadvar) and \
|
|
232
|
+
chip.get('tool', tool, 'task', task, 'file', openroadvar, step=step, index=index):
|
|
233
|
+
# value already set
|
|
234
|
+
continue
|
|
235
|
+
|
|
236
|
+
# copy from libs
|
|
237
|
+
for lib in targetlibs + macrolibs:
|
|
238
|
+
if chip.valid('library', lib, 'option', 'file', libvar):
|
|
239
|
+
for vfile in chip.find_files('library', lib, 'option', 'file', libvar):
|
|
240
|
+
chip.add('tool', tool, 'task', task, 'file', openroadvar, vfile,
|
|
241
|
+
step=step, index=index)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
################################
|
|
245
|
+
# Post_process (post executable)
|
|
246
|
+
################################
|
|
247
|
+
def post_process(chip):
|
|
248
|
+
''' Tool specific function to run after step execution
|
|
249
|
+
'''
|
|
250
|
+
|
|
251
|
+
# Check log file for errors and statistics
|
|
252
|
+
step = chip.get('arg', 'step')
|
|
253
|
+
index = chip.get('arg', 'index')
|
|
254
|
+
tool, task = get_tool_task(chip, step, index)
|
|
255
|
+
|
|
256
|
+
metric_reports = {
|
|
257
|
+
"setuptns": ["timing/total_negative_slack.rpt"],
|
|
258
|
+
"setupslack": ["timing/worst_slack.setup.rpt", "timing/setup.rpt", "timing/setup.topN.rpt"],
|
|
259
|
+
"setupskew": ["timing/skew.setup.rpt",
|
|
260
|
+
"timing/worst_slack.setup.rpt",
|
|
261
|
+
"timing/setup.rpt",
|
|
262
|
+
"timing/setup.topN.rpt"],
|
|
263
|
+
"setuppaths": ["timing/setup.topN.rpt"],
|
|
264
|
+
"holdslack": ["timing/worst_slack.hold.rpt", "timing/hold.rpt", "timing/hold.topN.rpt"],
|
|
265
|
+
"holdskew": ["timing/skew.hold.rpt",
|
|
266
|
+
"timing/worst_slack.hold.rpt",
|
|
267
|
+
"timing/hold.rpt",
|
|
268
|
+
"timing/hold.topN.rpt"],
|
|
269
|
+
"holdpaths": ["timing/hold.topN.rpt"],
|
|
270
|
+
"unconstrained": ["timing/unconstrained.topN.rpt"],
|
|
271
|
+
"peakpower": [f"power/{corner}.rpt" for corner in chip.getkeys('constraint', 'timing')],
|
|
272
|
+
"drvs": ["timing/drv_violators.rpt",
|
|
273
|
+
"floating_nets.rpt",
|
|
274
|
+
f"{chip.design}_antenna.rpt",
|
|
275
|
+
f"{chip.design}_antenna_post_repair.rpt"],
|
|
276
|
+
"drcs": [f"{chip.design}_drc.rpt"]
|
|
277
|
+
}
|
|
278
|
+
metric_reports["leakagepower"] = metric_reports["peakpower"]
|
|
279
|
+
|
|
280
|
+
metrics_file = "reports/metrics.json"
|
|
281
|
+
|
|
282
|
+
def get_metric_sources(metric):
|
|
283
|
+
metric_sources = [metrics_file]
|
|
284
|
+
if metric in metric_reports:
|
|
285
|
+
for metric_file in metric_reports[metric]:
|
|
286
|
+
metric_path = f'reports/{metric_file}'
|
|
287
|
+
if os.path.exists(metric_path):
|
|
288
|
+
metric_sources.append(metric_path)
|
|
289
|
+
return metric_sources
|
|
290
|
+
|
|
291
|
+
# parsing log file
|
|
292
|
+
with sc_open(metrics_file) as f:
|
|
293
|
+
try:
|
|
294
|
+
metrics = json.load(f)
|
|
295
|
+
except json.decoder.JSONDecodeError as e:
|
|
296
|
+
chip.logger.error(f'Unable to parse metrics from OpenROAD: {e}')
|
|
297
|
+
metrics = {}
|
|
298
|
+
|
|
299
|
+
or_units = {}
|
|
300
|
+
for unit, or_unit in [('time', 'run__flow__platform__time_units'),
|
|
301
|
+
('capacitance', 'run__flow__platform__capacitance_units'),
|
|
302
|
+
('resistance', 'run__flow__platform__resistance_units'),
|
|
303
|
+
('volt', 'run__flow__platform__voltage_units'),
|
|
304
|
+
('amp', 'run__flow__platform__current_units'),
|
|
305
|
+
('power', 'run__flow__platform__power_units'),
|
|
306
|
+
('distance', 'run__flow__platform__distance_units')]:
|
|
307
|
+
if or_unit in metrics:
|
|
308
|
+
# Remove first digit
|
|
309
|
+
metric_unit = metrics[or_unit][1:]
|
|
310
|
+
or_units[unit] = metric_unit
|
|
311
|
+
|
|
312
|
+
or_units['distance'] = 'um' # always microns
|
|
313
|
+
or_units['power'] = 'W' # always watts
|
|
314
|
+
or_units['area'] = f"{or_units['distance']}^2"
|
|
315
|
+
or_units['frequency'] = 'Hz' # always hertz
|
|
316
|
+
|
|
317
|
+
has_timing = True
|
|
318
|
+
if 'sc__metric__timing__clocks' in metrics:
|
|
319
|
+
has_timing = metrics['sc__metric__timing__clocks'] > 0
|
|
320
|
+
|
|
321
|
+
for metric, or_metric, or_use, or_unit in [
|
|
322
|
+
('vias', 'sc__step__route__vias', True, None),
|
|
323
|
+
('wirelength', 'sc__step__route__wirelength', True, 'distance'),
|
|
324
|
+
('cellarea', 'sc__metric__design__instance__area', True, 'area'),
|
|
325
|
+
('totalarea', 'sc__metric__design__core__area', True, 'area'),
|
|
326
|
+
('utilization', 'sc__metric__design__instance__utilization', True, 100.0),
|
|
327
|
+
('setuptns', 'sc__metric__timing__setup__tns', has_timing, 'time'),
|
|
328
|
+
('holdtns', 'sc__metric__timing__hold__tns', has_timing, 'time'),
|
|
329
|
+
('setupslack', 'sc__metric__timing__setup__ws', has_timing, 'time'),
|
|
330
|
+
('holdslack', 'sc__metric__timing__hold__ws', has_timing, 'time'),
|
|
331
|
+
('setupskew', 'sc__metric__clock__skew__setup', has_timing, 'time'),
|
|
332
|
+
('holdskew', 'sc__metric__clock__skew__hold', has_timing, 'time'),
|
|
333
|
+
('fmax', 'sc__metric__timing__fmax', has_timing, 'frequency'),
|
|
334
|
+
('setuppaths', 'sc__metric__timing__drv__setup_violation_count', True, None),
|
|
335
|
+
('holdpaths', 'sc__metric__timing__drv__hold_violation_count', True, None),
|
|
336
|
+
('unconstrained', 'sc__metric__timing__unconstrained', True, None),
|
|
337
|
+
('peakpower', 'sc__metric__power__total', True, 'power'),
|
|
338
|
+
('leakagepower', 'sc__metric__power__leakage__total', True, 'power'),
|
|
339
|
+
('pins', 'sc__metric__design__io', True, None),
|
|
340
|
+
('cells', 'sc__metric__design__instance__count', True, None),
|
|
341
|
+
('macros', 'sc__metric__design__instance__count__macros', True, None),
|
|
342
|
+
('nets', 'sc__metric__design__nets', True, None),
|
|
343
|
+
('registers', 'sc__metric__design__registers', True, None),
|
|
344
|
+
('inverters', 'sc__metric__design__inverters', True, None),
|
|
345
|
+
('buffers', 'sc__metric__design__buffers', True, None),
|
|
346
|
+
('logicdepth', 'sc__metric__design__logic__depth', True, None)
|
|
347
|
+
]:
|
|
348
|
+
if or_metric in metrics:
|
|
349
|
+
value = metrics[or_metric]
|
|
350
|
+
|
|
351
|
+
# Check for INF timing
|
|
352
|
+
if or_unit == 'time' and abs(value) > 1e24:
|
|
353
|
+
or_use = False
|
|
354
|
+
|
|
355
|
+
if or_unit:
|
|
356
|
+
if or_unit in or_units:
|
|
357
|
+
or_unit = or_units[or_unit]
|
|
358
|
+
else:
|
|
359
|
+
value *= or_unit
|
|
360
|
+
or_unit = None
|
|
361
|
+
|
|
362
|
+
if or_use:
|
|
363
|
+
record_metric(chip, step, index, metric, value,
|
|
364
|
+
get_metric_sources(metric),
|
|
365
|
+
source_unit=or_unit)
|
|
366
|
+
|
|
367
|
+
ir_drop = None
|
|
368
|
+
for or_metric, value in metrics.items():
|
|
369
|
+
if or_metric.startswith("sc__step__design_powergrid__drop__worst__net") or \
|
|
370
|
+
or_metric.startswith("sc__image__design_powergrid__drop__worst__net"):
|
|
371
|
+
if not ir_drop:
|
|
372
|
+
ir_drop = value
|
|
373
|
+
else:
|
|
374
|
+
ir_drop = max(value, ir_drop)
|
|
375
|
+
|
|
376
|
+
if ir_drop is not None:
|
|
377
|
+
record_metric(chip, step, index, 'irdrop', ir_drop,
|
|
378
|
+
get_metric_sources('irdrop'),
|
|
379
|
+
source_unit='V')
|
|
380
|
+
|
|
381
|
+
# setup wns and hold wns can be computed from setup slack and hold slack
|
|
382
|
+
if 'sc__metric__timing__setup__ws' in metrics and \
|
|
383
|
+
has_timing and \
|
|
384
|
+
chip.get('metric', 'setupslack', step=step, index=index) is not None:
|
|
385
|
+
wns = min(0.0, chip.get('metric', 'setupslack', step=step, index=index))
|
|
386
|
+
wns_units = chip.get('metric', 'setupslack', field='unit')
|
|
387
|
+
record_metric(chip, step, index, 'setupwns', wns,
|
|
388
|
+
get_metric_sources('setupslack'),
|
|
389
|
+
source_unit=wns_units)
|
|
390
|
+
|
|
391
|
+
if 'sc__metric__timing__hold__ws' in metrics and \
|
|
392
|
+
has_timing and \
|
|
393
|
+
chip.get('metric', 'holdslack', step=step, index=index) is not None:
|
|
394
|
+
wns = min(0.0, chip.get('metric', 'holdslack', step=step, index=index))
|
|
395
|
+
wns_units = chip.get('metric', 'holdslack', field='unit')
|
|
396
|
+
record_metric(chip, step, index, 'holdwns', wns,
|
|
397
|
+
get_metric_sources('holdslack'),
|
|
398
|
+
source_unit=wns_units)
|
|
399
|
+
|
|
400
|
+
drvs = None
|
|
401
|
+
for metric in ['sc__metric__timing__drv__max_slew',
|
|
402
|
+
'sc__metric__timing__drv__max_cap',
|
|
403
|
+
'sc__metric__timing__drv__max_fanout',
|
|
404
|
+
'sc__metric__antenna__violating__nets',
|
|
405
|
+
'sc__metric__antenna__violating__pins']:
|
|
406
|
+
if metric in metrics:
|
|
407
|
+
if drvs is None:
|
|
408
|
+
drvs = int(metrics[metric])
|
|
409
|
+
else:
|
|
410
|
+
drvs += int(metrics[metric])
|
|
411
|
+
|
|
412
|
+
if drvs is not None:
|
|
413
|
+
record_metric(chip, step, index, 'drvs', drvs, get_metric_sources('drvs'))
|
|
414
|
+
|
|
415
|
+
if 'sc__step__route__drc_errors' in metrics:
|
|
416
|
+
drcs = int(metrics['sc__step__route__drc_errors'])
|
|
417
|
+
record_metric(chip, step, index, 'drcs', drcs, get_metric_sources('drcs'))
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
######
|
|
421
|
+
def get_library_timing_keypaths(chip, lib):
|
|
422
|
+
step = chip.get('arg', 'step')
|
|
423
|
+
index = chip.get('arg', 'index')
|
|
424
|
+
|
|
425
|
+
delaymodel = chip.get('asic', 'delaymodel', step=step, index=index)
|
|
426
|
+
keypaths = {}
|
|
427
|
+
for constraint in chip.getkeys('constraint', 'timing'):
|
|
428
|
+
corners = chip.get('constraint', 'timing', constraint, 'libcorner', step=step, index=index)
|
|
429
|
+
for corner in corners:
|
|
430
|
+
if chip.valid('library', lib, 'output', corner, delaymodel):
|
|
431
|
+
keypaths[constraint] = ('library', lib, 'output', corner, delaymodel)
|
|
432
|
+
|
|
433
|
+
if constraint not in keypaths:
|
|
434
|
+
keypaths[constraint] = ('library', lib, 'output', corners[0], delaymodel)
|
|
435
|
+
return keypaths
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def get_pex_corners(chip):
|
|
439
|
+
|
|
440
|
+
step = chip.get('arg', 'step')
|
|
441
|
+
index = chip.get('arg', 'index')
|
|
442
|
+
|
|
443
|
+
corners = set()
|
|
444
|
+
for constraint in chip.getkeys('constraint', 'timing'):
|
|
445
|
+
pexcorner = chip.get('constraint', 'timing', constraint, 'pexcorner',
|
|
446
|
+
step=step, index=index)
|
|
447
|
+
if pexcorner:
|
|
448
|
+
corners.add(pexcorner)
|
|
449
|
+
|
|
450
|
+
return list(corners)
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
def get_constraint_by_check(chip, check):
|
|
454
|
+
step = chip.get('arg', 'step')
|
|
455
|
+
index = chip.get('arg', 'index')
|
|
456
|
+
|
|
457
|
+
for constraint in chip.getkeys('constraint', 'timing'):
|
|
458
|
+
if check in chip.get('constraint', 'timing', constraint, 'check',
|
|
459
|
+
step=step, index=index):
|
|
460
|
+
return constraint
|
|
461
|
+
|
|
462
|
+
# if not specified, just pick the first constraint available
|
|
463
|
+
return chip.getkeys('constraint', 'timing')[0]
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
def get_power_corner(chip):
|
|
467
|
+
return get_constraint_by_check(chip, "power")
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
def get_setup_corner(chip):
|
|
471
|
+
return get_constraint_by_check(chip, "setup")
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def build_pex_corners(chip):
|
|
475
|
+
step = chip.get('arg', 'step')
|
|
476
|
+
index = chip.get('arg', 'index')
|
|
477
|
+
tool, task = get_tool_task(chip, step, index)
|
|
478
|
+
|
|
479
|
+
pdkname = chip.get('option', 'pdk')
|
|
480
|
+
stackup = chip.get('option', 'stackup')
|
|
481
|
+
|
|
482
|
+
corners = {}
|
|
483
|
+
for constraint in chip.getkeys('constraint', 'timing'):
|
|
484
|
+
pexcorner = chip.get('constraint', 'timing', constraint, 'pexcorner',
|
|
485
|
+
step=step, index=index)
|
|
486
|
+
|
|
487
|
+
if not pexcorner:
|
|
488
|
+
continue
|
|
489
|
+
corners[constraint] = pexcorner
|
|
490
|
+
|
|
491
|
+
default_corner = get_setup_corner(chip)
|
|
492
|
+
if default_corner in corners:
|
|
493
|
+
corners[None] = corners[default_corner]
|
|
494
|
+
|
|
495
|
+
chip.set('tool', tool, 'task', task, 'file', 'parasitics',
|
|
496
|
+
os.path.join(chip.getworkdir(step=step, index=index), 'inputs', 'sc_parasitics.tcl'),
|
|
497
|
+
step=step, index=index, clobber=True)
|
|
498
|
+
|
|
499
|
+
with open(chip.get('tool', tool, 'task', task, 'file', 'parasitics',
|
|
500
|
+
step=step, index=index)[0], 'w') as f:
|
|
501
|
+
for constraint, pexcorner in corners.items():
|
|
502
|
+
if chip.valid('pdk', pdkname, 'pexmodel', tool, stackup, pexcorner):
|
|
503
|
+
pex_source_file = chip.find_files('pdk', pdkname,
|
|
504
|
+
'pexmodel',
|
|
505
|
+
tool,
|
|
506
|
+
stackup,
|
|
507
|
+
pexcorner)[0]
|
|
508
|
+
if not pex_source_file:
|
|
509
|
+
continue
|
|
510
|
+
|
|
511
|
+
corner_pex_template = utils.get_file_template(pex_source_file)
|
|
512
|
+
pex_template = utils.get_file_template('pex.tcl',
|
|
513
|
+
root=os.path.join(os.path.dirname(__file__),
|
|
514
|
+
'templates'))
|
|
515
|
+
|
|
516
|
+
if not pex_template:
|
|
517
|
+
continue
|
|
518
|
+
|
|
519
|
+
if constraint is None:
|
|
520
|
+
constraint = "default"
|
|
521
|
+
corner_specification = ""
|
|
522
|
+
else:
|
|
523
|
+
corner_specification = f"-corner {constraint}"
|
|
524
|
+
|
|
525
|
+
f.write(pex_template.render(
|
|
526
|
+
constraint=constraint,
|
|
527
|
+
pexcorner=pexcorner,
|
|
528
|
+
source=pex_source_file,
|
|
529
|
+
pex=corner_pex_template.render({"corner": corner_specification})
|
|
530
|
+
))
|
|
531
|
+
f.write('\n')
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
def _define_ifp_params(chip):
|
|
535
|
+
tool, task = get_tool_task(chip, chip.get('arg', 'step'),
|
|
536
|
+
chip.get('arg', 'index'))
|
|
537
|
+
set_tool_task_var(chip, param_key='ifp_tie_separation',
|
|
538
|
+
default_value='0',
|
|
539
|
+
schelp='maximum distance between tie high/low cells in microns')
|
|
540
|
+
set_tool_task_var(chip, param_key='ifp_snap_strategy',
|
|
541
|
+
default_value='site',
|
|
542
|
+
schelp='Snapping strategy to use when placing macros. '
|
|
543
|
+
'Allowed values: none, site, manufacturing_grid')
|
|
544
|
+
|
|
545
|
+
# Files
|
|
546
|
+
chip.set('tool', tool, 'task', task, 'file', 'ifp_tapcell',
|
|
547
|
+
'tap cell insertion script',
|
|
548
|
+
field='help')
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
def _define_ppl_params(chip):
|
|
552
|
+
set_tool_task_var(chip, param_key='ppl_arguments',
|
|
553
|
+
default_value=[],
|
|
554
|
+
schelp='additional arguments to pass along to the pin placer.')
|
|
555
|
+
|
|
556
|
+
tool, task = get_tool_task(chip, chip.get('arg', 'step'),
|
|
557
|
+
chip.get('arg', 'index'))
|
|
558
|
+
chip.set('tool', tool, 'task', task, 'file', 'ppl_constraints',
|
|
559
|
+
'script constrain pin placement',
|
|
560
|
+
field='help')
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
def _define_pdn_params(chip):
|
|
564
|
+
tool, task = get_tool_task(chip, chip.get('arg', 'step'),
|
|
565
|
+
chip.get('arg', 'index'))
|
|
566
|
+
set_tool_task_var(chip, param_key='pdn_enable',
|
|
567
|
+
default_value='true',
|
|
568
|
+
schelp='true/false, when true enables power grid generation')
|
|
569
|
+
|
|
570
|
+
# Files
|
|
571
|
+
chip.set('tool', tool, 'task', task, 'file', 'pdn_config',
|
|
572
|
+
'list of files to use for power grid generation',
|
|
573
|
+
field='help')
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
def _define_pad_params(chip):
|
|
577
|
+
tool, task = get_tool_task(chip, chip.get('arg', 'step'),
|
|
578
|
+
chip.get('arg', 'index'))
|
|
579
|
+
chip.set('tool', tool, 'task', task, 'file', 'padring',
|
|
580
|
+
'script to generate a padring using ICeWall in OpenROAD',
|
|
581
|
+
field='help')
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def _define_rsz_params(chip):
|
|
585
|
+
set_tool_task_var(chip, param_key='rsz_setup_slack_margin',
|
|
586
|
+
default_value='0.0',
|
|
587
|
+
schelp='specifies the margin to apply when performing setup repair '
|
|
588
|
+
'in library timing units')
|
|
589
|
+
set_tool_task_var(chip, param_key='rsz_hold_slack_margin',
|
|
590
|
+
default_value='0.0',
|
|
591
|
+
schelp='specifies the margin to apply when performing setup repair '
|
|
592
|
+
'in library timing units')
|
|
593
|
+
set_tool_task_var(chip, param_key='rsz_slew_margin',
|
|
594
|
+
default_value='0.0',
|
|
595
|
+
schelp='specifies the amount of margin to apply to max slew repairs '
|
|
596
|
+
'in percent (0 - 100)')
|
|
597
|
+
set_tool_task_var(chip, param_key='rsz_cap_margin',
|
|
598
|
+
default_value='0.0',
|
|
599
|
+
schelp='specifies the amount of margin to apply to max capacitance repairs '
|
|
600
|
+
'in percent (0 - 100)')
|
|
601
|
+
set_tool_task_var(chip, param_key='rsz_buffer_inputs',
|
|
602
|
+
default_value='false',
|
|
603
|
+
schelp='true/false, when true enables adding buffers to the input ports')
|
|
604
|
+
set_tool_task_var(chip, param_key='rsz_buffer_outputs',
|
|
605
|
+
default_value='false',
|
|
606
|
+
schelp='true/false, when true enables adding buffers to the output ports')
|
|
607
|
+
|
|
608
|
+
set_tool_task_var(chip, param_key='rsz_skip_pin_swap',
|
|
609
|
+
default_value='true',
|
|
610
|
+
schelp='true/false, skip pin swap optimization')
|
|
611
|
+
set_tool_task_var(chip, param_key='rsz_skip_gate_cloning',
|
|
612
|
+
default_value='true',
|
|
613
|
+
schelp='true/false, skip gate cloning optimization')
|
|
614
|
+
set_tool_task_var(chip, param_key='rsz_repair_tns',
|
|
615
|
+
default_value='100',
|
|
616
|
+
schelp='percentage of violating nets to attempt to repair (0 - 100)')
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
def _define_gpl_params(chip):
|
|
620
|
+
set_tool_task_var(chip, param_key='place_density',
|
|
621
|
+
require=['key'],
|
|
622
|
+
schelp='global placement density (0.0 - 1.0)')
|
|
623
|
+
set_tool_task_var(chip, param_key='pad_global_place',
|
|
624
|
+
require=['key'],
|
|
625
|
+
schelp='global placement cell padding in number of sites')
|
|
626
|
+
|
|
627
|
+
set_tool_task_var(chip, param_key='gpl_routability_driven',
|
|
628
|
+
default_value='true',
|
|
629
|
+
schelp='true/false, when true global placement will consider the '
|
|
630
|
+
'routability of the design')
|
|
631
|
+
set_tool_task_var(chip, param_key='gpl_timing_driven',
|
|
632
|
+
default_value='true',
|
|
633
|
+
schelp='true/false, when true global placement will consider the '
|
|
634
|
+
'timing performance of the design')
|
|
635
|
+
set_tool_task_var(chip, param_key='gpl_uniform_placement_adjustment',
|
|
636
|
+
default_value='0.00',
|
|
637
|
+
schelp='percent of remaining area density to apply above '
|
|
638
|
+
'uniform density (0.00 - 0.99)')
|
|
639
|
+
set_tool_task_var(chip, param_key='gpl_enable_skip_io',
|
|
640
|
+
default_value='true',
|
|
641
|
+
schelp='true/false, when enabled a global placement is performed without '
|
|
642
|
+
'considering the impact of the pin placements')
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
def _define_dpo_params(chip):
|
|
646
|
+
set_tool_task_var(chip, param_key='dpo_enable',
|
|
647
|
+
default_value='true',
|
|
648
|
+
schelp='true/false, when true the detailed placement optimization '
|
|
649
|
+
'will be performed')
|
|
650
|
+
set_tool_task_var(chip, param_key='dpo_max_displacement',
|
|
651
|
+
default_value='0',
|
|
652
|
+
schelp='maximum cell movement in detailed placement optimization in microns, '
|
|
653
|
+
'0 will result in the tool default maximum displacement')
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
def _define_dpl_params(chip):
|
|
657
|
+
set_tool_task_var(chip, param_key='pad_detail_place',
|
|
658
|
+
require=['key'],
|
|
659
|
+
schelp='detailed placement cell padding in number of sites')
|
|
660
|
+
|
|
661
|
+
set_tool_task_var(chip, param_key='dpl_max_displacement',
|
|
662
|
+
default_value='0',
|
|
663
|
+
schelp='maximum cell movement in detailed placement in microns, '
|
|
664
|
+
'0 will result in the tool default maximum displacement')
|
|
665
|
+
set_tool_task_var(chip, param_key='dpl_disallow_one_site',
|
|
666
|
+
default_value='false',
|
|
667
|
+
schelp='true/false, disallow single site gaps in detail placement')
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
def _define_cts_params(chip):
|
|
671
|
+
step = chip.get('arg', 'step')
|
|
672
|
+
index = chip.get('arg', 'index')
|
|
673
|
+
mainlib = get_mainlib(chip)
|
|
674
|
+
|
|
675
|
+
set_tool_task_var(chip, param_key='cts_clock_buffer',
|
|
676
|
+
default_value=chip.get('library', mainlib, 'asic', 'cells', 'clkbuf',
|
|
677
|
+
step=step, index=index)[-1],
|
|
678
|
+
schelp='buffer to use during clock tree synthesis')
|
|
679
|
+
set_tool_task_var(chip, param_key='cts_distance_between_buffers',
|
|
680
|
+
default_value='100',
|
|
681
|
+
schelp='maximum distance between buffers during clock tree synthesis '
|
|
682
|
+
'in microns')
|
|
683
|
+
set_tool_task_var(chip, param_key='cts_cluster_diameter',
|
|
684
|
+
default_value='100',
|
|
685
|
+
schelp='clustering distance to use during clock tree synthesis in microns')
|
|
686
|
+
set_tool_task_var(chip, param_key='cts_cluster_size',
|
|
687
|
+
default_value='30',
|
|
688
|
+
schelp='number of instances in a cluster to use during clock tree synthesis')
|
|
689
|
+
set_tool_task_var(chip, param_key='cts_balance_levels',
|
|
690
|
+
default_value='true',
|
|
691
|
+
schelp='perform level balancing in clock tree synthesis')
|
|
692
|
+
set_tool_task_var(chip, param_key='cts_obstruction_aware',
|
|
693
|
+
default_value='true',
|
|
694
|
+
schelp='make clock tree synthesis aware of obstructions')
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
def _define_grt_params(chip):
|
|
698
|
+
pdkname = chip.get('option', 'pdk')
|
|
699
|
+
stackup = chip.get('option', 'stackup')
|
|
700
|
+
|
|
701
|
+
pdk_min_layer = chip.get('pdk', pdkname, 'minlayer', stackup)
|
|
702
|
+
pdk_max_layer = chip.get('pdk', pdkname, 'maxlayer', stackup)
|
|
703
|
+
|
|
704
|
+
set_tool_task_var(chip, param_key='grt_use_pin_access',
|
|
705
|
+
default_value='false',
|
|
706
|
+
schelp='true/false, when true perform pin access before global routing')
|
|
707
|
+
set_tool_task_var(chip, param_key='grt_overflow_iter',
|
|
708
|
+
default_value='100',
|
|
709
|
+
schelp='maximum number of iterations to use in global routing when '
|
|
710
|
+
'attempting to solve overflow')
|
|
711
|
+
set_tool_task_var(chip, param_key='grt_macro_extension',
|
|
712
|
+
default_value='0',
|
|
713
|
+
schelp='macro extension distance in number of gcells, this can be useful '
|
|
714
|
+
'when the detailed router needs additional space to avoid DRCs')
|
|
715
|
+
set_tool_task_var(chip, param_key='grt_allow_congestion',
|
|
716
|
+
default_value='false',
|
|
717
|
+
schelp='true/false, when true allow global routing to finish with congestion')
|
|
718
|
+
set_tool_task_var(chip, param_key='grt_allow_overflow',
|
|
719
|
+
default_value='false',
|
|
720
|
+
schelp='true/false, when true allow global routing to finish with overflow')
|
|
721
|
+
set_tool_task_var(chip, param_key='grt_signal_min_layer',
|
|
722
|
+
default_value=pdk_min_layer,
|
|
723
|
+
schelp='minimum layer to use for global routing of signals')
|
|
724
|
+
set_tool_task_var(chip, param_key='grt_signal_max_layer',
|
|
725
|
+
default_value=pdk_max_layer,
|
|
726
|
+
schelp='maximum layer to use for global routing of signals')
|
|
727
|
+
set_tool_task_var(chip, param_key='grt_clock_min_layer',
|
|
728
|
+
default_value=pdk_min_layer,
|
|
729
|
+
schelp='minimum layer to use for global routing of clock nets')
|
|
730
|
+
set_tool_task_var(chip, param_key='grt_clock_max_layer',
|
|
731
|
+
default_value=pdk_max_layer,
|
|
732
|
+
schelp='maximum layer to use for global routing of clock nets')
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
def _define_ant_params(chip):
|
|
736
|
+
set_tool_task_var(chip, param_key='ant_iterations',
|
|
737
|
+
default_value='3',
|
|
738
|
+
schelp='maximum number of repair iterations to use during antenna repairs')
|
|
739
|
+
set_tool_task_var(chip, param_key='ant_margin',
|
|
740
|
+
default_value='0',
|
|
741
|
+
schelp='adds a margin to the antenna ratios (0 - 100)')
|
|
742
|
+
set_tool_task_var(chip, param_key='ant_check',
|
|
743
|
+
default_value='true',
|
|
744
|
+
schelp='true/false, flag to indicate whether to check for antenna violations')
|
|
745
|
+
set_tool_task_var(chip, param_key='ant_repair',
|
|
746
|
+
default_value='true',
|
|
747
|
+
schelp='true/false, flag to indicate whether to repair antenna violations')
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
def _define_drt_params(chip):
|
|
751
|
+
set_tool_task_var(chip, param_key='drt_disable_via_gen',
|
|
752
|
+
default_value='false',
|
|
753
|
+
schelp='true/false, when true turns off via generation in detailed router '
|
|
754
|
+
'and only uses the specified tech vias')
|
|
755
|
+
set_tool_task_var(chip, param_key='drt_process_node',
|
|
756
|
+
schelp='when set this specifies to the detailed router the '
|
|
757
|
+
'specific process node')
|
|
758
|
+
set_tool_task_var(chip, param_key='drt_via_in_pin_bottom_layer',
|
|
759
|
+
schelp='TODO')
|
|
760
|
+
set_tool_task_var(chip, param_key='drt_via_in_pin_top_layer',
|
|
761
|
+
schelp='TODO')
|
|
762
|
+
set_tool_task_var(chip, param_key='drt_repair_pdn_vias',
|
|
763
|
+
schelp='TODO')
|
|
764
|
+
# TODO: This parameter maybe deprecated in favor of drt_repair_pdn_vias
|
|
765
|
+
set_tool_task_var(chip, param_key='drt_via_repair_post_route',
|
|
766
|
+
default_value='false',
|
|
767
|
+
schelp='true/false, when true performs a via ripup step after detailed '
|
|
768
|
+
'routing to remove power vias that are causing DRC violations')
|
|
769
|
+
|
|
770
|
+
set_tool_task_var(chip, param_key='detailed_route_default_via',
|
|
771
|
+
schelp='list of default vias to use for detail routing')
|
|
772
|
+
set_tool_task_var(chip, param_key='detailed_route_unidirectional_layer',
|
|
773
|
+
schelp='list of layers to treat as unidirectional regardless of '
|
|
774
|
+
'what the tech lef specifies')
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
def _define_sta_params(chip):
|
|
778
|
+
step = chip.get('arg', 'step')
|
|
779
|
+
index = chip.get('arg', 'index')
|
|
780
|
+
tool, task = get_tool_task(chip, step, index)
|
|
781
|
+
|
|
782
|
+
set_tool_task_var(chip, param_key='sta_early_timing_derate',
|
|
783
|
+
default_value='0.0',
|
|
784
|
+
schelp='timing derating factor to use for hold corners')
|
|
785
|
+
set_tool_task_var(chip, param_key='sta_late_timing_derate',
|
|
786
|
+
default_value='0.0',
|
|
787
|
+
schelp='timing derating factor to use for setup corners')
|
|
788
|
+
set_tool_task_var(chip, param_key='sta_top_n_paths',
|
|
789
|
+
default_value='10',
|
|
790
|
+
schelp='number of paths to report timing for')
|
|
791
|
+
|
|
792
|
+
chip.set('tool', tool, 'task', task, 'var', 'power_corner', get_power_corner(chip),
|
|
793
|
+
step=step, index=index, clobber=False)
|
|
794
|
+
chip.set('tool', tool, 'task', task, 'var', 'power_corner',
|
|
795
|
+
'corner to use for power analysis',
|
|
796
|
+
field='help')
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
def _define_sdc_params(chip):
|
|
800
|
+
set_tool_task_var(chip, param_key='sdc_buffer',
|
|
801
|
+
schelp='buffer cell to use when auto generating timing constraints')
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
def _define_psm_params(chip):
|
|
805
|
+
step = chip.get('arg', 'step')
|
|
806
|
+
index = chip.get('arg', 'index')
|
|
807
|
+
tool, task = get_tool_task(chip, step, index)
|
|
808
|
+
|
|
809
|
+
set_tool_task_var(chip, param_key='psm_enable',
|
|
810
|
+
default_value='true',
|
|
811
|
+
schelp='true/false, when true enables IR drop analysis')
|
|
812
|
+
|
|
813
|
+
chip.set('tool', tool, 'task', task, 'var', 'psm_skip_nets',
|
|
814
|
+
'list of nets to skip power grid analysis on',
|
|
815
|
+
field='help')
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
def _define_fin_params(chip):
|
|
819
|
+
set_tool_task_var(chip, param_key='fin_add_fill',
|
|
820
|
+
default_value='true',
|
|
821
|
+
schelp='true/false, when true enables adding fill, '
|
|
822
|
+
'if enabled by the PDK, to the design')
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
def _define_mpl_params(chip):
|
|
826
|
+
set_tool_task_var(chip, param_key='macro_place_halo',
|
|
827
|
+
require=['key'],
|
|
828
|
+
schelp='macro halo to use when performing automated '
|
|
829
|
+
'macro placement ([x, y] in microns)')
|
|
830
|
+
set_tool_task_var(chip, param_key='macro_place_channel',
|
|
831
|
+
require=['key'],
|
|
832
|
+
schelp='macro channel to use when performing automated '
|
|
833
|
+
'macro placement ([x, y] in microns)')
|
|
834
|
+
|
|
835
|
+
set_tool_task_var(chip, param_key='rtlmp_enable',
|
|
836
|
+
default_value='false',
|
|
837
|
+
schelp='true/false, enables the RTLMP macro placement')
|
|
838
|
+
set_tool_task_var(chip, param_key='rtlmp_min_instances',
|
|
839
|
+
schelp='minimum number of instances to use while clustering for '
|
|
840
|
+
'macro placement')
|
|
841
|
+
set_tool_task_var(chip, param_key='rtlmp_max_instances',
|
|
842
|
+
schelp='maximum number of instances to use while clustering for '
|
|
843
|
+
'macro placement')
|
|
844
|
+
set_tool_task_var(chip, param_key='rtlmp_min_macros',
|
|
845
|
+
schelp='minimum number of macros to use while clustering for macro placement')
|
|
846
|
+
set_tool_task_var(chip, param_key='rtlmp_max_macros',
|
|
847
|
+
schelp='maximum number of macros to use while clustering for macro placement')
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
def _define_ord_params(chip):
|
|
851
|
+
step = chip.get('arg', 'step')
|
|
852
|
+
index = chip.get('arg', 'index')
|
|
853
|
+
tool, task = get_tool_task(chip, step, index)
|
|
854
|
+
|
|
855
|
+
# Parameters without pdk/lib dependencies
|
|
856
|
+
chip.set('tool', tool, 'task', task, 'var', 'debug_level',
|
|
857
|
+
'list of "tool key level" to enable debugging of OpenROAD',
|
|
858
|
+
field='help')
|
|
859
|
+
|
|
860
|
+
chip.set('tool', tool, 'task', task, 'file', 'global_connect',
|
|
861
|
+
'list of files to use for specifying global connections',
|
|
862
|
+
field='help')
|
|
863
|
+
|
|
864
|
+
set_tool_task_var(chip, param_key='ord_abstract_lef_bloat_factor',
|
|
865
|
+
default_value='10',
|
|
866
|
+
require=['key'],
|
|
867
|
+
schelp='Factor to apply when writing the abstract lef')
|
|
868
|
+
|
|
869
|
+
set_tool_task_var(chip, param_key='ord_abstract_lef_bloat_layers',
|
|
870
|
+
default_value='true',
|
|
871
|
+
require=['key'],
|
|
872
|
+
schelp='true/false, fill all layers when writing the abstract lef')
|
|
873
|
+
|
|
874
|
+
set_tool_task_var(chip, param_key='ord_enable_images',
|
|
875
|
+
default_value='true',
|
|
876
|
+
require=['key'],
|
|
877
|
+
schelp='true/false, enable generating images of the design at the '
|
|
878
|
+
'end of the task')
|
|
879
|
+
|
|
880
|
+
set_tool_task_var(chip, param_key='ord_heatmap_bins_x',
|
|
881
|
+
default_value='16',
|
|
882
|
+
require=['key'],
|
|
883
|
+
schelp='number of X bins to use for heatmap image generation')
|
|
884
|
+
set_tool_task_var(chip, param_key='ord_heatmap_bins_y',
|
|
885
|
+
default_value='16',
|
|
886
|
+
require=['key'],
|
|
887
|
+
schelp='number of Y bins to use for heatmap image generation')
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
def _define_pex_params(chip):
|
|
891
|
+
step = chip.get('arg', 'step')
|
|
892
|
+
index = chip.get('arg', 'index')
|
|
893
|
+
tool, task = get_tool_task(chip, step, index)
|
|
894
|
+
|
|
895
|
+
chip.set('tool', tool, 'task', task, 'var', 'pex_corners', get_pex_corners(chip),
|
|
896
|
+
step=step, index=index, clobber=False)
|
|
897
|
+
chip.set('tool', tool, 'task', task, 'var', 'pex_corners',
|
|
898
|
+
'list of parasitic extraction corners to use',
|
|
899
|
+
field='help')
|
|
900
|
+
|
|
901
|
+
# Auto generated file
|
|
902
|
+
chip.set('tool', tool, 'task', task, 'file', 'parasitics',
|
|
903
|
+
'file used to specify the parasitics for estimation',
|
|
904
|
+
field='help')
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
def _set_reports(chip, reports):
|
|
908
|
+
step = chip.get('arg', 'step')
|
|
909
|
+
index = chip.get('arg', 'index')
|
|
910
|
+
tool, task = get_tool_task(chip, step, index)
|
|
911
|
+
|
|
912
|
+
chip.set('tool', tool, 'task', task, 'var', 'reports',
|
|
913
|
+
'list of reports and images to generate',
|
|
914
|
+
field='help')
|
|
915
|
+
|
|
916
|
+
chip.set('tool', tool, 'task', task, 'var', 'reports', [],
|
|
917
|
+
step=step, index=index)
|
|
918
|
+
|
|
919
|
+
def check_enabled(type):
|
|
920
|
+
for key in (('tool', tool, 'task', task, 'var', f'skip_{type}'),
|
|
921
|
+
('option', 'var', f'openroad_skip_{type}')):
|
|
922
|
+
if chip.valid(*key) and \
|
|
923
|
+
chip.get(*key, step=step, index=index) == ["true"]:
|
|
924
|
+
return False
|
|
925
|
+
return True
|
|
926
|
+
|
|
927
|
+
for report in reports:
|
|
928
|
+
if check_enabled(report):
|
|
929
|
+
chip.add('tool', tool, 'task', task, 'var', 'reports', report,
|
|
930
|
+
step=step, index=index)
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
def set_pnr_inputs(chip):
|
|
934
|
+
step = chip.get('arg', 'step')
|
|
935
|
+
index = chip.get('arg', 'index')
|
|
936
|
+
tool, task = get_tool_task(chip, step, index)
|
|
937
|
+
|
|
938
|
+
design = chip.top()
|
|
939
|
+
|
|
940
|
+
if f'{design}.sdc' in input_provides(chip, step, index):
|
|
941
|
+
chip.add('tool', tool, 'task', task, 'input', design + '.sdc',
|
|
942
|
+
step=step, index=index)
|
|
943
|
+
elif chip.valid('input', 'constraint', 'sdc') and \
|
|
944
|
+
chip.get('input', 'constraint', 'sdc', step=step, index=index):
|
|
945
|
+
chip.add('tool', tool, 'task', task, 'require', 'input,constraint,sdc',
|
|
946
|
+
step=step, index=index)
|
|
947
|
+
|
|
948
|
+
if f'{design}.odb' in input_provides(chip, step, index):
|
|
949
|
+
chip.add('tool', tool, 'task', task, 'input', design + '.odb',
|
|
950
|
+
step=step, index=index)
|
|
951
|
+
elif f'{design}.def' in input_provides(chip, step, index):
|
|
952
|
+
chip.add('tool', tool, 'task', task, 'input', design + '.def',
|
|
953
|
+
step=step, index=index)
|
|
954
|
+
elif chip.valid('input', 'layout', 'def') and \
|
|
955
|
+
chip.get('input', 'layout', 'def', step=step, index=index):
|
|
956
|
+
chip.add('tool', tool, 'task', task, 'require', 'input,layout,def',
|
|
957
|
+
step=step, index=index)
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
def set_pnr_outputs(chip):
|
|
961
|
+
step = chip.get('arg', 'step')
|
|
962
|
+
index = chip.get('arg', 'index')
|
|
963
|
+
tool, task = get_tool_task(chip, step, index)
|
|
964
|
+
|
|
965
|
+
design = chip.top()
|
|
966
|
+
|
|
967
|
+
chip.add('tool', tool, 'task', task, 'output', design + '.sdc', step=step, index=index)
|
|
968
|
+
chip.add('tool', tool, 'task', task, 'output', design + '.vg', step=step, index=index)
|
|
969
|
+
chip.add('tool', tool, 'task', task, 'output', design + '.def', step=step, index=index)
|
|
970
|
+
chip.add('tool', tool, 'task', task, 'output', design + '.odb', step=step, index=index)
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
##################################################
|
|
974
|
+
if __name__ == "__main__":
|
|
975
|
+
|
|
976
|
+
chip = make_docs()
|
|
977
|
+
chip.write_manifest("openroad.json")
|