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,137 @@
|
|
|
1
|
+
#############################################
|
|
2
|
+
#!!!! AUTO-GENERATED FILE. DO NOT EDIT!!!!!!
|
|
3
|
+
#############################################
|
|
4
|
+
|
|
5
|
+
#############################################
|
|
6
|
+
# Manifest
|
|
7
|
+
#############################################
|
|
8
|
+
{{ manifest_dict }}
|
|
9
|
+
|
|
10
|
+
#############################################
|
|
11
|
+
# Helper functions
|
|
12
|
+
#############################################
|
|
13
|
+
|
|
14
|
+
# Shortcut to get values from configuration
|
|
15
|
+
proc sc_cfg_get { args } {
|
|
16
|
+
# Refer to global sc_cfg dictionary
|
|
17
|
+
global sc_cfg
|
|
18
|
+
|
|
19
|
+
if { ![sc_cfg_exists {*}$args] } {
|
|
20
|
+
throw {FLOW KEYERROR} "key \"$args\" is not in the siliconcompiler configuration"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return [dict get $sc_cfg {*}$args]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
proc sc_cfg_exists { args } {
|
|
27
|
+
# Refer to global sc_cfg dictionary
|
|
28
|
+
global sc_cfg
|
|
29
|
+
|
|
30
|
+
return [dict exists $sc_cfg {*}$args]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
proc sc_top {} {
|
|
34
|
+
set sc_entrypoint [sc_cfg_get option entrypoint]
|
|
35
|
+
if {$sc_entrypoint == ""} {
|
|
36
|
+
return [sc_cfg_get design]
|
|
37
|
+
}
|
|
38
|
+
return $sc_entrypoint
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
proc sc_root {} {
|
|
42
|
+
return "{{ scroot }}"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# Shortcut to get tool vars
|
|
46
|
+
proc sc_cfg_tool_task_get { args } {
|
|
47
|
+
set sc_step [sc_cfg_get arg step]
|
|
48
|
+
set sc_index [sc_cfg_get arg index]
|
|
49
|
+
|
|
50
|
+
set sc_flow [sc_cfg_get option flow]
|
|
51
|
+
|
|
52
|
+
set sc_task [sc_cfg_get flowgraph $sc_flow $sc_step $sc_index task]
|
|
53
|
+
set sc_tool [sc_cfg_get flowgraph $sc_flow $sc_step $sc_index tool]
|
|
54
|
+
|
|
55
|
+
return [sc_cfg_get tool $sc_tool task $sc_task {*}$args]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
proc sc_cfg_tool_task_exists { args } {
|
|
59
|
+
set sc_step [sc_cfg_get arg step]
|
|
60
|
+
set sc_index [sc_cfg_get arg index]
|
|
61
|
+
|
|
62
|
+
set sc_flow [sc_cfg_get option flow]
|
|
63
|
+
|
|
64
|
+
set sc_task [sc_cfg_get flowgraph $sc_flow $sc_step $sc_index task]
|
|
65
|
+
set sc_tool [sc_cfg_get flowgraph $sc_flow $sc_step $sc_index tool]
|
|
66
|
+
|
|
67
|
+
return [sc_cfg_exists tool $sc_tool task $sc_task {*}$args]
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Check if an item is present in a list
|
|
71
|
+
proc sc_cfg_tool_task_check_in_list { item args } {
|
|
72
|
+
set result [sc_cfg_tool_task_get {*}$args]
|
|
73
|
+
|
|
74
|
+
if { [lsearch -exact $result $item] != -1 } {
|
|
75
|
+
return 1
|
|
76
|
+
} else {
|
|
77
|
+
return 0
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
proc sc_section_banner { text { method puts } } {
|
|
82
|
+
$method "============================================================"
|
|
83
|
+
$method "| $text"
|
|
84
|
+
$method "============================================================"
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# Get list of soft libraries
|
|
88
|
+
proc sc_get_libraries { {library {}} {libraries {}} } {
|
|
89
|
+
set key []
|
|
90
|
+
if { [llength $library] != 0 } {
|
|
91
|
+
lappend key library $library
|
|
92
|
+
}
|
|
93
|
+
lappend key option library
|
|
94
|
+
|
|
95
|
+
set libs []
|
|
96
|
+
foreach lib [sc_cfg_get {*}$key] {
|
|
97
|
+
if { [lsearch -exact $libs $lib] != -1 || [lsearch -exact $libraries $lib] != -1 } {
|
|
98
|
+
continue
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
lappend libs $lib
|
|
102
|
+
|
|
103
|
+
foreach sublib [sc_get_libraries $lib $libs] {
|
|
104
|
+
lappend libs $sublib
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return [lsort -unique $libs]
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
# Get list of asic libraries
|
|
112
|
+
proc sc_get_asic_libraries { type } {
|
|
113
|
+
set libs []
|
|
114
|
+
|
|
115
|
+
foreach lib [sc_cfg_get asic ${type}lib] {
|
|
116
|
+
if { [lsearch -exact $libs $lib] != -1 } {
|
|
117
|
+
continue
|
|
118
|
+
}
|
|
119
|
+
lappend libs $lib
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
foreach lib [sc_get_libraries] {
|
|
123
|
+
if { ![sc_cfg_exists library $lib asic ${type}lib] } {
|
|
124
|
+
continue
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
foreach sublib [sc_cfg_get library $lib asic ${type}lib] {
|
|
128
|
+
if { [lsearch -exact $libs $sublib] != -1 } {
|
|
129
|
+
continue
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
lappend libs $sublib
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return $libs
|
|
137
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pkgutil
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def get_libraries(chip, include_asic=True, library=None, libraries=None):
|
|
6
|
+
'''
|
|
7
|
+
Returns a list of libraries included in this step/index
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
chip (Chip): Chip object
|
|
11
|
+
include_asic (bool): include the asic libraries.
|
|
12
|
+
'''
|
|
13
|
+
step = chip.get('arg', 'step')
|
|
14
|
+
index = chip.get('arg', 'index')
|
|
15
|
+
|
|
16
|
+
libs = []
|
|
17
|
+
|
|
18
|
+
if not libraries:
|
|
19
|
+
libraries = set()
|
|
20
|
+
|
|
21
|
+
pref_key = []
|
|
22
|
+
if library:
|
|
23
|
+
pref_key = ['library', library]
|
|
24
|
+
|
|
25
|
+
def get_libs(*key):
|
|
26
|
+
if chip.valid(*key) and chip.get(*key, step=step, index=index):
|
|
27
|
+
return chip.get(*key, step=step, index=index)
|
|
28
|
+
return []
|
|
29
|
+
|
|
30
|
+
if include_asic:
|
|
31
|
+
libs.extend(get_libs(*pref_key, 'asic', 'logiclib'))
|
|
32
|
+
libs.extend(get_libs(*pref_key, 'asic', 'macrolib'))
|
|
33
|
+
|
|
34
|
+
for lib in get_libs(*pref_key, 'option', 'library'):
|
|
35
|
+
if lib in libs or lib in libraries:
|
|
36
|
+
continue
|
|
37
|
+
libs.append(lib)
|
|
38
|
+
libs.extend(get_libraries(chip, include_asic=include_asic, library=lib, libraries=libs))
|
|
39
|
+
|
|
40
|
+
return set(libs)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def add_require_input(chip, *key, include_library_files=True):
|
|
44
|
+
'''
|
|
45
|
+
Adds input files to the require list of the task.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
chip (Chip): Chip object
|
|
49
|
+
key (list): Key to check for requirements
|
|
50
|
+
add_library_files (bool): When True, files from library keys
|
|
51
|
+
will be included
|
|
52
|
+
'''
|
|
53
|
+
step = chip.get('arg', 'step')
|
|
54
|
+
index = chip.get('arg', 'index')
|
|
55
|
+
tool, task = get_tool_task(chip, step, index)
|
|
56
|
+
|
|
57
|
+
keys = []
|
|
58
|
+
for key in __get_keys(chip, *key, include_library_files=False):
|
|
59
|
+
keys.append(key)
|
|
60
|
+
|
|
61
|
+
if include_library_files:
|
|
62
|
+
for item in get_libraries(chip, include_asic=False):
|
|
63
|
+
lib_key = ('library', item, *key)
|
|
64
|
+
if __is_key_valid(chip, *lib_key):
|
|
65
|
+
keys.append(lib_key)
|
|
66
|
+
|
|
67
|
+
for key in keys:
|
|
68
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
69
|
+
",".join(key),
|
|
70
|
+
step=step, index=index)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def get_input_files(chip, *key, add_library_files=True):
|
|
74
|
+
'''
|
|
75
|
+
Returns a list of files from the key input and includes files
|
|
76
|
+
from libraries if requested.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
chip (Chip): Chip object
|
|
80
|
+
key (list): Key to collect files from
|
|
81
|
+
add_library_files (bool): When True, files from library keys
|
|
82
|
+
will be included
|
|
83
|
+
'''
|
|
84
|
+
step = chip.get('arg', 'step')
|
|
85
|
+
index = chip.get('arg', 'index')
|
|
86
|
+
|
|
87
|
+
files = []
|
|
88
|
+
for key in __get_keys(chip, *key, include_library_files=False):
|
|
89
|
+
files.extend(chip.find_files(*key, step=step, index=index))
|
|
90
|
+
|
|
91
|
+
if add_library_files:
|
|
92
|
+
for item in get_libraries(chip, include_asic=False):
|
|
93
|
+
lib_key = ('library', item, *key)
|
|
94
|
+
if __is_key_valid(chip, *lib_key):
|
|
95
|
+
files.extend(chip.find_files(*lib_key, step=step, index=index))
|
|
96
|
+
|
|
97
|
+
return __remove_duplicates(chip, files, list(key))
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def has_input_files(chip, *key, check_library_files=True):
|
|
101
|
+
'''
|
|
102
|
+
Returns true if the specified key is set.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
chip (Chip): Chip object
|
|
106
|
+
key (list): Key to check
|
|
107
|
+
check_library_files (bool): When True, files from library keys
|
|
108
|
+
will be checked
|
|
109
|
+
'''
|
|
110
|
+
if __get_keys(chip, *key, include_library_files=check_library_files):
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
return False
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def __remove_duplicates(chip, values, type):
|
|
117
|
+
new_values = []
|
|
118
|
+
for v in values:
|
|
119
|
+
if v not in new_values:
|
|
120
|
+
new_values.append(v)
|
|
121
|
+
else:
|
|
122
|
+
chip.logger.warning(f"Removing duplicate {type}: {v}")
|
|
123
|
+
return new_values
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def __get_step_index(chip, *key):
|
|
127
|
+
step = chip.get('arg', 'step')
|
|
128
|
+
index = chip.get('arg', 'index')
|
|
129
|
+
|
|
130
|
+
if chip.get(*key, field='pernode') == 'never':
|
|
131
|
+
step = None
|
|
132
|
+
index = None
|
|
133
|
+
|
|
134
|
+
return step, index
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def __is_key_valid(chip, *key):
|
|
138
|
+
if chip.valid(*key):
|
|
139
|
+
step, index = __get_step_index(chip, *key)
|
|
140
|
+
if chip.get(*key, step=step, index=index):
|
|
141
|
+
return True
|
|
142
|
+
return False
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def __get_keys(chip, *key, include_library_files=True):
|
|
146
|
+
keys = []
|
|
147
|
+
if __is_key_valid(chip, *key):
|
|
148
|
+
keys.append(key)
|
|
149
|
+
|
|
150
|
+
if include_library_files:
|
|
151
|
+
for item in get_libraries(chip):
|
|
152
|
+
lib_key = ['library', item, *key]
|
|
153
|
+
if __is_key_valid(chip, *lib_key):
|
|
154
|
+
keys.append(tuple(lib_key))
|
|
155
|
+
|
|
156
|
+
return keys
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def __assert_support(chip, opt_keys, supports):
|
|
160
|
+
from siliconcompiler import SiliconCompilerError
|
|
161
|
+
|
|
162
|
+
if not supports:
|
|
163
|
+
supports = []
|
|
164
|
+
|
|
165
|
+
step = chip.get('arg', 'step')
|
|
166
|
+
index = chip.get('arg', 'index')
|
|
167
|
+
tool, task = get_tool_task(chip, step, index)
|
|
168
|
+
for opt, vals in opt_keys.items():
|
|
169
|
+
val_list = ', '.join([str(list(v)) for v in vals])
|
|
170
|
+
if opt not in supports and val_list:
|
|
171
|
+
msg = f'{tool}/{task} does not support [\'option\', \'{opt}\']'
|
|
172
|
+
if len(vals) != 1 or len(vals[0]) != 2:
|
|
173
|
+
msg += f', the following values will be ignored: {val_list}'
|
|
174
|
+
pass
|
|
175
|
+
chip.logger.warning(msg)
|
|
176
|
+
|
|
177
|
+
for opt in supports:
|
|
178
|
+
if opt not in opt_keys:
|
|
179
|
+
raise SiliconCompilerError(
|
|
180
|
+
f'{tool}/{task} is requesting support for {opt}, which does not exist',
|
|
181
|
+
chip=chip)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def __get_frontend_option_keys(chip):
|
|
185
|
+
opts = {
|
|
186
|
+
'ydir': __get_keys(chip, 'option', 'ydir'),
|
|
187
|
+
'vlib': __get_keys(chip, 'option', 'vlib'),
|
|
188
|
+
'idir': __get_keys(chip, 'option', 'idir'),
|
|
189
|
+
'define': __get_keys(chip, 'option', 'define'),
|
|
190
|
+
'libext': __get_keys(chip, 'option', 'libext'),
|
|
191
|
+
'param': [] # Only from 'option', no libraries
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
for param in chip.getkeys('option', 'param'):
|
|
195
|
+
opts['param'].append(('option', 'param', param))
|
|
196
|
+
|
|
197
|
+
return opts
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def add_frontend_requires(chip, supports=None):
|
|
201
|
+
'''
|
|
202
|
+
Adds keys to the require list for the frontend task and checks if
|
|
203
|
+
options are set, which the current frontend does not support.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
chip (Chip): Chip object
|
|
207
|
+
supports (list): List of ['option', '*'] which the frontend supports
|
|
208
|
+
'''
|
|
209
|
+
opt_keys = __get_frontend_option_keys(chip)
|
|
210
|
+
__assert_support(chip, opt_keys, supports)
|
|
211
|
+
|
|
212
|
+
step = chip.get('arg', 'step')
|
|
213
|
+
index = chip.get('arg', 'index')
|
|
214
|
+
tool, task = get_tool_task(chip, step, index)
|
|
215
|
+
for opt in supports:
|
|
216
|
+
for key in opt_keys[opt]:
|
|
217
|
+
chip.add('tool', tool, 'task', task, 'require', ','.join(key), step=step, index=index)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def get_frontend_options(chip, supports=None):
|
|
221
|
+
'''
|
|
222
|
+
Returns a dictionary of options set for the frontend and checks if
|
|
223
|
+
options are set, which the current frontend does not support.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
chip (Chip): Chip object
|
|
227
|
+
supports (list): List of ['option', '*'] which the frontend supports
|
|
228
|
+
'''
|
|
229
|
+
opt_keys = __get_frontend_option_keys(chip)
|
|
230
|
+
__assert_support(chip, opt_keys, supports)
|
|
231
|
+
|
|
232
|
+
params = opt_keys['param']
|
|
233
|
+
del opt_keys['param']
|
|
234
|
+
|
|
235
|
+
opts = {}
|
|
236
|
+
for opt, keys in opt_keys.items():
|
|
237
|
+
opts[opt] = []
|
|
238
|
+
for key in keys:
|
|
239
|
+
sc_type = chip.get(*key, field='type')
|
|
240
|
+
step, index = __get_step_index(chip, *key)
|
|
241
|
+
if 'file' in sc_type or 'dir' in sc_type:
|
|
242
|
+
opts[opt].extend(chip.find_files(*key, step=step, index=index))
|
|
243
|
+
else:
|
|
244
|
+
opts[opt].extend(chip.get(*key, step=step, index=index))
|
|
245
|
+
|
|
246
|
+
opts[opt] = __remove_duplicates(chip, opts[opt], ['option', opt])
|
|
247
|
+
|
|
248
|
+
opts['param'] = []
|
|
249
|
+
for key in params:
|
|
250
|
+
param = key[-1]
|
|
251
|
+
value = chip.get(*key)
|
|
252
|
+
opts['param'].append((param, value))
|
|
253
|
+
|
|
254
|
+
return opts
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def find_incoming_ext(chip, support_exts, default_ext):
|
|
258
|
+
from siliconcompiler.utils import get_file_ext
|
|
259
|
+
|
|
260
|
+
step = chip.get('arg', 'step')
|
|
261
|
+
index = chip.get('arg', 'index')
|
|
262
|
+
flow = chip.get('option', 'flow')
|
|
263
|
+
|
|
264
|
+
for input_step, input_index in chip.get('flowgraph', flow, step, index, 'input'):
|
|
265
|
+
tool, task = get_tool_task(chip, input_step, input_index, flow=flow)
|
|
266
|
+
output_exts = {get_file_ext(f): f for f in chip.get('tool', tool, 'task', task, 'output',
|
|
267
|
+
step=input_step, index=input_index)}
|
|
268
|
+
# Search the supported order
|
|
269
|
+
for ext in support_exts:
|
|
270
|
+
if ext in output_exts:
|
|
271
|
+
if output_exts[ext].lower().endswith('.gz'):
|
|
272
|
+
return f'{ext}.gz'
|
|
273
|
+
return ext
|
|
274
|
+
|
|
275
|
+
for ext in support_exts:
|
|
276
|
+
for fileset in chip.getkeys('input'):
|
|
277
|
+
if chip.valid('input', fileset, ext):
|
|
278
|
+
return ext
|
|
279
|
+
|
|
280
|
+
# Nothing found return the default
|
|
281
|
+
return default_ext
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def pick_key(chip, check_keys, step=None, index=None):
|
|
285
|
+
if not step:
|
|
286
|
+
step = chip.get('arg', 'step')
|
|
287
|
+
if not index:
|
|
288
|
+
index = chip.get('arg', 'index')
|
|
289
|
+
|
|
290
|
+
for key in check_keys:
|
|
291
|
+
if chip.valid(*key):
|
|
292
|
+
check_step = step
|
|
293
|
+
check_index = index
|
|
294
|
+
|
|
295
|
+
if chip.get(*key, field='pernode') == 'never':
|
|
296
|
+
check_step = None
|
|
297
|
+
check_index = None
|
|
298
|
+
|
|
299
|
+
check_value = chip.get(*key, step=check_step, index=check_index)
|
|
300
|
+
if check_value:
|
|
301
|
+
return key, check_value
|
|
302
|
+
|
|
303
|
+
return None, None
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def input_provides(chip, step, index, flow=None):
|
|
307
|
+
from siliconcompiler import NodeStatus
|
|
308
|
+
|
|
309
|
+
if not flow:
|
|
310
|
+
flow = chip.get('option', 'flow')
|
|
311
|
+
|
|
312
|
+
nodes = chip.get('flowgraph', flow, step, index, 'input')
|
|
313
|
+
inputs = {}
|
|
314
|
+
for in_step, in_index in nodes:
|
|
315
|
+
if chip.get('record', 'status', step=in_step, index=in_index) == \
|
|
316
|
+
NodeStatus.SKIPPED:
|
|
317
|
+
for file, nodes in input_provides(chip, in_step, in_index, flow=flow).items():
|
|
318
|
+
inputs.setdefault(file, []).extend(nodes)
|
|
319
|
+
continue
|
|
320
|
+
tool, task = get_tool_task(chip, in_step, in_index, flow=flow)
|
|
321
|
+
|
|
322
|
+
for output in chip.get('tool', tool, 'task', task, 'output',
|
|
323
|
+
step=in_step, index=in_index):
|
|
324
|
+
inputs.setdefault(output, []).append((in_step, in_index))
|
|
325
|
+
|
|
326
|
+
return inputs
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def input_file_node_name(filename, step, index):
|
|
330
|
+
from siliconcompiler.utils import get_file_ext
|
|
331
|
+
|
|
332
|
+
file_type = get_file_ext(filename)
|
|
333
|
+
|
|
334
|
+
base = filename
|
|
335
|
+
total_ext = []
|
|
336
|
+
ext = None
|
|
337
|
+
while ext != file_type:
|
|
338
|
+
base, ext = os.path.splitext(base)
|
|
339
|
+
ext = ext[1:].lower()
|
|
340
|
+
total_ext.append(ext)
|
|
341
|
+
|
|
342
|
+
total_ext.reverse()
|
|
343
|
+
|
|
344
|
+
return f'{base}.{step}{index}.{".".join(total_ext)}'
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def add_common_file(chip, key, file):
|
|
348
|
+
step = chip.get('arg', 'step')
|
|
349
|
+
index = chip.get('arg', 'index')
|
|
350
|
+
tool, task = get_tool_task(chip, step, index)
|
|
351
|
+
|
|
352
|
+
chip.set('tool', tool, 'task', task, 'file', key,
|
|
353
|
+
f'tools/_common/{file}',
|
|
354
|
+
step=step, index=index,
|
|
355
|
+
package='siliconcompiler')
|
|
356
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
357
|
+
','.join(['tool', tool, 'task', task, 'file', key]),
|
|
358
|
+
step=step, index=index)
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
###########################################################################
|
|
362
|
+
def get_tool_task(chip, step, index, flow=None):
|
|
363
|
+
'''
|
|
364
|
+
Helper function to get the name of the tool and task associated with a given step/index.
|
|
365
|
+
'''
|
|
366
|
+
if not flow:
|
|
367
|
+
flow = chip.get('option', 'flow')
|
|
368
|
+
|
|
369
|
+
tool = chip.get('flowgraph', flow, step, index, 'tool')
|
|
370
|
+
task = chip.get('flowgraph', flow, step, index, 'task')
|
|
371
|
+
return tool, task
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def get_tool_tasks(chip, tool):
|
|
375
|
+
tool_dir = os.path.dirname(tool.__file__)
|
|
376
|
+
tool_base_module = tool.__name__.split('.')[0:-1]
|
|
377
|
+
tool_name = tool.__name__.split('.')[-1]
|
|
378
|
+
|
|
379
|
+
task_candidates = []
|
|
380
|
+
for task_mod in pkgutil.iter_modules([tool_dir]):
|
|
381
|
+
if task_mod.name == tool_name:
|
|
382
|
+
continue
|
|
383
|
+
task_candidates.append(task_mod.name)
|
|
384
|
+
|
|
385
|
+
tasks = []
|
|
386
|
+
for task in sorted(task_candidates):
|
|
387
|
+
task_module = '.'.join([*tool_base_module, task])
|
|
388
|
+
if getattr(chip._load_module(task_module), 'setup', None):
|
|
389
|
+
tasks.append(task)
|
|
390
|
+
|
|
391
|
+
return tasks
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
#######################################
|
|
395
|
+
def record_metric(chip, step, index, metric, value, source, source_unit=None):
|
|
396
|
+
'''
|
|
397
|
+
Records a metric from a given step and index.
|
|
398
|
+
|
|
399
|
+
This function ensures the metrics are recorded in the correct units
|
|
400
|
+
as specified in the schema, additionally, this will record the source
|
|
401
|
+
of the value if provided.
|
|
402
|
+
|
|
403
|
+
Args:
|
|
404
|
+
step (str): step to record the metric into
|
|
405
|
+
index (str): index to record the metric into
|
|
406
|
+
metric (str): metric to record
|
|
407
|
+
value (float/int): value of the metric that is being recorded
|
|
408
|
+
source (str): file the value came from
|
|
409
|
+
source_unit (str): unit of the value, if not provided it is assumed to have no units
|
|
410
|
+
|
|
411
|
+
Examples:
|
|
412
|
+
>>> record_metric(chip, 'floorplan', '0', 'cellarea', 500.0, 'reports/metrics.json', \\
|
|
413
|
+
source_units='um^2')
|
|
414
|
+
Records the metric cell area under 'floorplan0' and notes the source as
|
|
415
|
+
'reports/metrics.json'
|
|
416
|
+
'''
|
|
417
|
+
from siliconcompiler import units
|
|
418
|
+
|
|
419
|
+
metric_unit = None
|
|
420
|
+
if chip.schema.has_field('metric', metric, 'unit'):
|
|
421
|
+
metric_unit = chip.get('metric', metric, field='unit')
|
|
422
|
+
|
|
423
|
+
if metric_unit:
|
|
424
|
+
value = units.convert(value, from_unit=source_unit, to_unit=metric_unit)
|
|
425
|
+
|
|
426
|
+
chip.set('metric', metric, value, step=step, index=index)
|
|
427
|
+
|
|
428
|
+
if source:
|
|
429
|
+
flow = chip.get('option', 'flow')
|
|
430
|
+
tool, task = get_tool_task(chip, step, index, flow=flow)
|
|
431
|
+
|
|
432
|
+
chip.add('tool', tool, 'task', task, 'report', metric, source, step=step, index=index)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
from .. import _common
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_mainlib(chip):
|
|
5
|
+
return get_libraries(chip, 'logic')[0]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_libraries(chip, type):
|
|
9
|
+
step = chip.get('arg', 'step')
|
|
10
|
+
index = chip.get('arg', 'index')
|
|
11
|
+
|
|
12
|
+
if type not in ('logic', 'macro'):
|
|
13
|
+
raise ValueError(f'Cannot collect {type} libraries')
|
|
14
|
+
|
|
15
|
+
libs = []
|
|
16
|
+
for lib in chip.get('asic', f'{type}lib', step=step, index=index):
|
|
17
|
+
if lib in libs:
|
|
18
|
+
continue
|
|
19
|
+
libs.append(lib)
|
|
20
|
+
|
|
21
|
+
for lib in _common.get_libraries(chip, include_asic=False):
|
|
22
|
+
if not chip.valid('library', lib, 'asic', f'{type}lib'):
|
|
23
|
+
continue
|
|
24
|
+
for sublib in chip.get('library', lib, 'asic', f'{type}lib', step=step, index=index):
|
|
25
|
+
if sublib in libs:
|
|
26
|
+
continue
|
|
27
|
+
libs.append(sublib)
|
|
28
|
+
|
|
29
|
+
return libs
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_timing_modes(chip):
|
|
33
|
+
step = chip.get('arg', 'step')
|
|
34
|
+
index = chip.get('arg', 'index')
|
|
35
|
+
|
|
36
|
+
modes = set()
|
|
37
|
+
for scenario in chip.getkeys('constraint', 'timing'):
|
|
38
|
+
modes.add(chip.get('constraint', 'timing', scenario, 'mode',
|
|
39
|
+
step=step, index=index))
|
|
40
|
+
return sorted(modes)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def set_tool_task_var(chip,
|
|
44
|
+
param_key,
|
|
45
|
+
default_value=None,
|
|
46
|
+
schelp=None,
|
|
47
|
+
option_key=None,
|
|
48
|
+
pdk_key=None,
|
|
49
|
+
lib_key=None,
|
|
50
|
+
require=None):
|
|
51
|
+
'''
|
|
52
|
+
Set parameter from PDK -> main library -> option -> default_value
|
|
53
|
+
'''
|
|
54
|
+
step = chip.get('arg', 'step')
|
|
55
|
+
index = chip.get('arg', 'index')
|
|
56
|
+
tool, task = _common.get_tool_task(chip, step, index)
|
|
57
|
+
pdkname = chip.get('option', 'pdk')
|
|
58
|
+
stackup = chip.get('option', 'stackup')
|
|
59
|
+
mainlib = get_mainlib(chip)
|
|
60
|
+
|
|
61
|
+
if not require:
|
|
62
|
+
require = []
|
|
63
|
+
if not isinstance(require, (list, tuple)):
|
|
64
|
+
require = [require]
|
|
65
|
+
|
|
66
|
+
check_keys = []
|
|
67
|
+
|
|
68
|
+
# Add PDK key
|
|
69
|
+
if not pdk_key:
|
|
70
|
+
pdk_key = param_key
|
|
71
|
+
check_keys.append(['pdk', pdkname, 'var', tool, stackup, pdk_key])
|
|
72
|
+
if 'pdk' in require:
|
|
73
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
74
|
+
','.join(check_keys[-1]),
|
|
75
|
+
step=step, index=index)
|
|
76
|
+
|
|
77
|
+
# Add library key
|
|
78
|
+
if not lib_key:
|
|
79
|
+
lib_key = f'{tool}_{param_key}'
|
|
80
|
+
check_keys.append(['library', mainlib, 'option', 'var', lib_key])
|
|
81
|
+
if 'lib' in require:
|
|
82
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
83
|
+
','.join(check_keys[-1]),
|
|
84
|
+
step=step, index=index)
|
|
85
|
+
|
|
86
|
+
# Add option key
|
|
87
|
+
if not option_key:
|
|
88
|
+
option_key = f'{tool}_{param_key}'
|
|
89
|
+
check_keys.append(['option', 'var', option_key])
|
|
90
|
+
if 'option' in require:
|
|
91
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
92
|
+
','.join(check_keys[-1]),
|
|
93
|
+
step=step, index=index)
|
|
94
|
+
|
|
95
|
+
require_key, value = _common.pick_key(chip, reversed(check_keys), step=step, index=index)
|
|
96
|
+
if not value:
|
|
97
|
+
value = default_value
|
|
98
|
+
|
|
99
|
+
if value:
|
|
100
|
+
chip.set('tool', tool, 'task', task, 'var', param_key, value,
|
|
101
|
+
step=step, index=index, clobber=False)
|
|
102
|
+
|
|
103
|
+
if require_key:
|
|
104
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
105
|
+
','.join(require_key),
|
|
106
|
+
step=step, index=index)
|
|
107
|
+
|
|
108
|
+
if value or 'key' in require:
|
|
109
|
+
chip.add('tool', tool, 'task', task, 'require',
|
|
110
|
+
','.join(['tool', tool, 'task', task, 'var', param_key]),
|
|
111
|
+
step=step, index=index)
|
|
112
|
+
|
|
113
|
+
if schelp:
|
|
114
|
+
chip.set('tool', tool, 'task', task, 'var', param_key,
|
|
115
|
+
schelp, field='help')
|