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,242 @@
|
|
|
1
|
+
import pya
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def show(schema, tech, input_path, output_path, screenshot=False):
|
|
7
|
+
# Extract info from manifest
|
|
8
|
+
flow = schema.get('option', 'flow')
|
|
9
|
+
step = schema.get('arg', 'step')
|
|
10
|
+
index = schema.get('arg', 'index')
|
|
11
|
+
task = schema.get('flowgraph', flow, step, index, 'task')
|
|
12
|
+
|
|
13
|
+
if 'hide_layers' in schema.getkeys('tool', 'klayout', 'task', task, 'var'):
|
|
14
|
+
sc_hide_layers = schema.get('tool', 'klayout', 'task', task, 'var', 'hide_layers',
|
|
15
|
+
step=step, index=index)
|
|
16
|
+
else:
|
|
17
|
+
sc_hide_layers = []
|
|
18
|
+
|
|
19
|
+
# Load KLayout technology file
|
|
20
|
+
layoutOptions = tech.load_layout_options
|
|
21
|
+
|
|
22
|
+
# These may be disabled in our KLayout tech file for reasons relating to GDS
|
|
23
|
+
# export, but for the purposes of viewing we'll hardcode them to True.
|
|
24
|
+
layoutOptions.lefdef_config.produce_blockages = True
|
|
25
|
+
layoutOptions.lefdef_config.produce_cell_outlines = True
|
|
26
|
+
layoutOptions.lefdef_config.produce_obstructions = True
|
|
27
|
+
|
|
28
|
+
# Always use LEF geometry even when LEF file contains FOREIGN statement.
|
|
29
|
+
layoutOptions.lefdef_config.macro_resolution_mode = 1
|
|
30
|
+
|
|
31
|
+
tech.load_layout_options = layoutOptions
|
|
32
|
+
|
|
33
|
+
app = pya.Application.instance()
|
|
34
|
+
main_window = pya.MainWindow.instance()
|
|
35
|
+
if not main_window:
|
|
36
|
+
print('[WARNING] unable to show layout as the main window is not available')
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
# Opinionated default KLayout configuration
|
|
40
|
+
# see ~/.klayout/klayoutrc for a list of configuration keys
|
|
41
|
+
|
|
42
|
+
# show all cells
|
|
43
|
+
app.set_config('full-hierarchy-new-cell', 'true')
|
|
44
|
+
# no tip pop-ups
|
|
45
|
+
app.set_config('tip-window-hidden', ','.join(['only-top-level-shown-by-default=3',
|
|
46
|
+
'editor-mode=4',
|
|
47
|
+
'editor-mode=0']))
|
|
48
|
+
# hide text
|
|
49
|
+
app.set_config('text-visible', 'false')
|
|
50
|
+
# dark background
|
|
51
|
+
app.set_config('background-color', '#212121')
|
|
52
|
+
|
|
53
|
+
# Display the file!
|
|
54
|
+
print(f"[INFO] Opening {input_path}")
|
|
55
|
+
cell_view = main_window.load_layout(input_path, tech.name)
|
|
56
|
+
layout_view = cell_view.view()
|
|
57
|
+
|
|
58
|
+
# Hide layers that shouldn't be shown in the current view.
|
|
59
|
+
for layer in layout_view.each_layer():
|
|
60
|
+
layer_ldt = f'{layer.source_layer}/{layer.source_datatype}'
|
|
61
|
+
layer_name = layer.source_name
|
|
62
|
+
if not layer_name:
|
|
63
|
+
layer_name = layer.name
|
|
64
|
+
print_layer = layer_name
|
|
65
|
+
if ' ' in layer_name:
|
|
66
|
+
layer_name = layer_name.split()[0]
|
|
67
|
+
if (layer_name in sc_hide_layers) or \
|
|
68
|
+
(layer_ldt in sc_hide_layers):
|
|
69
|
+
print(f"[INFO] Turning off layer: {print_layer} : {layer_ldt}")
|
|
70
|
+
layer.visible = False
|
|
71
|
+
|
|
72
|
+
# If 'screenshot' mode is set, save image and exit.
|
|
73
|
+
if screenshot:
|
|
74
|
+
xbins = int(schema.get('tool', 'klayout', 'task', task, 'var', 'xbins',
|
|
75
|
+
step=step, index=index)[0])
|
|
76
|
+
ybins = int(schema.get('tool', 'klayout', 'task', task, 'var', 'ybins',
|
|
77
|
+
step=step, index=index)[0])
|
|
78
|
+
|
|
79
|
+
if xbins == 1 and ybins == 1:
|
|
80
|
+
__screenshot(schema, layout_view, output_path)
|
|
81
|
+
else:
|
|
82
|
+
__screenshot_montage(schema, layout_view, xbins, ybins)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def __screenshot(schema, layout_view, output_path):
|
|
86
|
+
flow = schema.get('option', 'flow')
|
|
87
|
+
step = schema.get('arg', 'step')
|
|
88
|
+
index = schema.get('arg', 'index')
|
|
89
|
+
task = schema.get('flowgraph', flow, step, index, 'task')
|
|
90
|
+
|
|
91
|
+
# Save a screenshot. TODO: Get aspect ratio from sc_cfg?
|
|
92
|
+
horizontal_resolution = int(schema.get('tool', 'klayout', 'task', task, 'var',
|
|
93
|
+
'show_horizontal_resolution',
|
|
94
|
+
step=step, index=index)[0])
|
|
95
|
+
vertical_resolution = int(schema.get('tool', 'klayout', 'task', task, 'var',
|
|
96
|
+
'show_vertical_resolution',
|
|
97
|
+
step=step, index=index)[0])
|
|
98
|
+
|
|
99
|
+
print(f'[INFO] Saving screenshot to {output_path}')
|
|
100
|
+
layout_view.save_image(output_path, horizontal_resolution, vertical_resolution)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def __screenshot_montage(schema, view, xbins, ybins):
|
|
104
|
+
flow = schema.get('option', 'flow')
|
|
105
|
+
step = schema.get('arg', 'step')
|
|
106
|
+
index = schema.get('arg', 'index')
|
|
107
|
+
task = schema.get('flowgraph', flow, step, index, 'task')
|
|
108
|
+
|
|
109
|
+
app = pya.Application.instance()
|
|
110
|
+
options = (
|
|
111
|
+
"grid-show-ruler",
|
|
112
|
+
"grid-visible",
|
|
113
|
+
"text-visible"
|
|
114
|
+
)
|
|
115
|
+
for option in options:
|
|
116
|
+
app.set_config(option, "false")
|
|
117
|
+
|
|
118
|
+
app.set_config("background-color", "#000000") # Black
|
|
119
|
+
|
|
120
|
+
design = schema.get('option', 'entrypoint')
|
|
121
|
+
if not design:
|
|
122
|
+
design = schema.get('design')
|
|
123
|
+
|
|
124
|
+
horizontal_resolution = int(schema.get('tool', 'klayout', 'task', task, 'var',
|
|
125
|
+
'show_horizontal_resolution',
|
|
126
|
+
step=step, index=index)[0])
|
|
127
|
+
vertical_resolution = int(schema.get('tool', 'klayout', 'task', task, 'var',
|
|
128
|
+
'show_vertical_resolution',
|
|
129
|
+
step=step, index=index)[0])
|
|
130
|
+
margin = float(schema.get('tool', 'klayout', 'task', task, 'var',
|
|
131
|
+
'margin',
|
|
132
|
+
step=step, index=index)[0])
|
|
133
|
+
linewidth = int(schema.get('tool', 'klayout', 'task', task, 'var',
|
|
134
|
+
'linewidth',
|
|
135
|
+
step=step, index=index)[0])
|
|
136
|
+
oversampling = int(schema.get('tool', 'klayout', 'task', task, 'var',
|
|
137
|
+
'oversampling',
|
|
138
|
+
step=step, index=index)[0])
|
|
139
|
+
|
|
140
|
+
view.zoom_fit()
|
|
141
|
+
cell = view.active_cellview().cell
|
|
142
|
+
|
|
143
|
+
view_box = cell.dbbox()
|
|
144
|
+
view_box.left -= margin
|
|
145
|
+
view_box.bottom -= margin
|
|
146
|
+
view_box.right += margin
|
|
147
|
+
view_box.top += margin
|
|
148
|
+
|
|
149
|
+
x_incr = int(view_box.width() / xbins)
|
|
150
|
+
y_incr = int(view_box.height() / ybins)
|
|
151
|
+
|
|
152
|
+
if (view_box.width() > view_box.height()):
|
|
153
|
+
y_px = vertical_resolution
|
|
154
|
+
x_px = int((float(x_incr) / y_incr) * y_px)
|
|
155
|
+
else:
|
|
156
|
+
x_px = horizontal_resolution
|
|
157
|
+
y_px = int((float(y_incr) / x_incr) * x_px)
|
|
158
|
+
|
|
159
|
+
for x in range(xbins):
|
|
160
|
+
for y in range(ybins):
|
|
161
|
+
yidx = ybins - y - 1
|
|
162
|
+
output_file = f"{design}_X{x}_Y{yidx}.png"
|
|
163
|
+
|
|
164
|
+
x_start = view_box.left + x_incr * x
|
|
165
|
+
y_start = view_box.bottom + y_incr * y
|
|
166
|
+
|
|
167
|
+
subbox = pya.DBox(
|
|
168
|
+
x_start,
|
|
169
|
+
y_start,
|
|
170
|
+
x_start + x_incr,
|
|
171
|
+
y_start + y_incr)
|
|
172
|
+
|
|
173
|
+
sub_img_spec = {
|
|
174
|
+
"width": x_px,
|
|
175
|
+
"height": y_px,
|
|
176
|
+
"linewidth": linewidth,
|
|
177
|
+
"oversampling": oversampling,
|
|
178
|
+
"resolution": 0,
|
|
179
|
+
"target_box": subbox,
|
|
180
|
+
"monochrome": False
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
img_path = os.path.join('outputs', output_file)
|
|
184
|
+
print(f'[INFO] Saving screenshot (({subbox.left}, {subbox.bottom}), '
|
|
185
|
+
f'({subbox.right}, {subbox.top})) to {img_path}')
|
|
186
|
+
view.save_image_with_options(
|
|
187
|
+
img_path,
|
|
188
|
+
sub_img_spec["width"],
|
|
189
|
+
sub_img_spec["height"],
|
|
190
|
+
sub_img_spec["linewidth"],
|
|
191
|
+
sub_img_spec["oversampling"],
|
|
192
|
+
sub_img_spec["resolution"],
|
|
193
|
+
sub_img_spec["target_box"],
|
|
194
|
+
sub_img_spec["monochrome"]
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def main():
|
|
199
|
+
# SC_ROOT provided by CLI, and is only accessible when this is main module
|
|
200
|
+
sys.path.append(SC_ROOT) # noqa: F821
|
|
201
|
+
|
|
202
|
+
from tools.klayout.klayout_utils import (
|
|
203
|
+
technology,
|
|
204
|
+
get_schema
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
schema = get_schema(manifest='sc_manifest.json')
|
|
208
|
+
|
|
209
|
+
flow = schema.get('option', 'flow')
|
|
210
|
+
step = schema.get('arg', 'step')
|
|
211
|
+
index = schema.get('arg', 'index')
|
|
212
|
+
task = schema.get('flowgraph', flow, step, index, 'task')
|
|
213
|
+
|
|
214
|
+
design = schema.get('option', 'entrypoint')
|
|
215
|
+
if not design:
|
|
216
|
+
design = schema.get('design')
|
|
217
|
+
|
|
218
|
+
if 'show_filepath' in schema.getkeys('tool', 'klayout', 'task', task, 'var') and \
|
|
219
|
+
schema.get('tool', 'klayout', 'task', task, 'var', 'show_filepath',
|
|
220
|
+
step=step, index=index):
|
|
221
|
+
sc_filename = schema.get('tool', 'klayout', 'task', task, 'var', 'show_filepath',
|
|
222
|
+
step=step, index=index)[0]
|
|
223
|
+
else:
|
|
224
|
+
sc_fileext = schema.get('tool', 'klayout', 'task', task, 'var', 'show_filetype',
|
|
225
|
+
step=step, index=index)[0]
|
|
226
|
+
for ext in (f'{sc_fileext}.gz', sc_fileext):
|
|
227
|
+
sc_filename = f"inputs/{design}.{ext}"
|
|
228
|
+
if os.path.exists(sc_filename):
|
|
229
|
+
break
|
|
230
|
+
|
|
231
|
+
sc_exit = schema.get('tool', 'klayout', 'task', task, 'var', 'show_exit',
|
|
232
|
+
step=step, index=index) == ["true"]
|
|
233
|
+
|
|
234
|
+
show(schema, technology(design, schema), sc_filename, f'outputs/{design}.png',
|
|
235
|
+
screenshot=(task == 'screenshot'))
|
|
236
|
+
|
|
237
|
+
if sc_exit:
|
|
238
|
+
pya.Application.instance().exit(0)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
if __name__ == '__main__':
|
|
242
|
+
main()
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import pya
|
|
2
|
+
import importlib.util as importlib_util
|
|
3
|
+
import os
|
|
4
|
+
import shutil
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_streams(schema):
|
|
9
|
+
sc_step = schema.get('arg', 'step')
|
|
10
|
+
sc_index = schema.get('arg', 'index')
|
|
11
|
+
sc_flow = schema.get('option', 'flow')
|
|
12
|
+
sc_task = schema.get('flowgraph', sc_flow, sc_step, sc_index, 'task')
|
|
13
|
+
|
|
14
|
+
streams = ('gds', 'oas')
|
|
15
|
+
if schema.valid('tool', 'klayout', 'task', sc_task, 'var', 'stream'):
|
|
16
|
+
sc_stream = schema.get('tool', 'klayout', 'task', sc_task, 'var', 'stream',
|
|
17
|
+
step=sc_step, index=sc_index)[0]
|
|
18
|
+
else:
|
|
19
|
+
sc_stream = streams[0]
|
|
20
|
+
return [sc_stream, *[s for s in streams if s != sc_stream]]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def technology(design, schema):
|
|
24
|
+
from tools._common.asic import get_libraries
|
|
25
|
+
|
|
26
|
+
sc_step = schema.get('arg', 'step')
|
|
27
|
+
sc_index = schema.get('arg', 'index')
|
|
28
|
+
sc_pdk = schema.get('option', 'pdk')
|
|
29
|
+
|
|
30
|
+
if schema.valid('option', 'stackup'):
|
|
31
|
+
sc_stackup = schema.get('option', 'stackup')
|
|
32
|
+
else:
|
|
33
|
+
sc_stackup = schema.get('pdk', sc_pdk, 'stackup')[0]
|
|
34
|
+
sc_mainlib = schema.get('asic', 'logiclib', step=sc_step, index=sc_index)[0]
|
|
35
|
+
sc_libtype = schema.get('library', sc_mainlib, 'asic', 'libarch', step=sc_step, index=sc_index)
|
|
36
|
+
|
|
37
|
+
sc_libs = []
|
|
38
|
+
sc_libs += get_libraries(schema, 'logic')
|
|
39
|
+
sc_libs += get_libraries(schema, 'macro')
|
|
40
|
+
|
|
41
|
+
local_files = {
|
|
42
|
+
'lyt': f'inputs/{design}.lyt',
|
|
43
|
+
'lyp': f'inputs/{design}.lyp'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
tech = pya.Technology.create_technology('sc_tech')
|
|
47
|
+
# Load technology file
|
|
48
|
+
tech_file = None
|
|
49
|
+
if os.path.exists(local_files['lyt']):
|
|
50
|
+
tech_file = local_files['lyt']
|
|
51
|
+
elif schema.valid('pdk', sc_pdk, 'layermap', 'klayout', 'def', 'klayout', sc_stackup):
|
|
52
|
+
tech_file = schema.get('pdk', sc_pdk, 'layermap', 'klayout', 'def', 'klayout', sc_stackup)
|
|
53
|
+
if tech_file:
|
|
54
|
+
tech_file = tech_file[0]
|
|
55
|
+
|
|
56
|
+
if tech_file:
|
|
57
|
+
print(f"[INFO] Loading technology file: {tech_file}")
|
|
58
|
+
tech.load(tech_file)
|
|
59
|
+
else:
|
|
60
|
+
tech.name = f'{sc_pdk} for {sc_stackup}'
|
|
61
|
+
tech.description = f'{", ".join(sc_libs)}'
|
|
62
|
+
|
|
63
|
+
if schema.valid('pdk', sc_pdk, 'var', 'klayout', 'units', sc_stackup):
|
|
64
|
+
units = float(schema.get('pdk', sc_pdk, 'var', 'klayout', 'units', sc_stackup)[0])
|
|
65
|
+
tech.dbu = units
|
|
66
|
+
print(f"[INFO] Technology database units are: {tech.dbu}um")
|
|
67
|
+
|
|
68
|
+
lefs = []
|
|
69
|
+
|
|
70
|
+
foundry_lef = schema.get('pdk', sc_pdk, 'aprtech', 'klayout', sc_stackup, sc_libtype, 'lef')
|
|
71
|
+
if foundry_lef:
|
|
72
|
+
foundry_lef = foundry_lef[0]
|
|
73
|
+
lefs.append(foundry_lef)
|
|
74
|
+
else:
|
|
75
|
+
foundry_lef = None
|
|
76
|
+
|
|
77
|
+
for lib in sc_libs:
|
|
78
|
+
lefs.extend(schema.get('library', lib, 'output', sc_stackup, 'lef',
|
|
79
|
+
step=sc_step, index=sc_index))
|
|
80
|
+
|
|
81
|
+
layoutOptions = tech.load_layout_options
|
|
82
|
+
|
|
83
|
+
layoutOptions.lefdef_config.macro_resolution_mode = 1
|
|
84
|
+
layoutOptions.lefdef_config.via_cellname_prefix = "VIA_"
|
|
85
|
+
pathed_files = set()
|
|
86
|
+
for lef_file in layoutOptions.lefdef_config.lef_files:
|
|
87
|
+
if foundry_lef and not os.path.isabs(lef_file):
|
|
88
|
+
lef_file = os.path.join(os.path.dirname(foundry_lef), lef_file)
|
|
89
|
+
lef_file = os.path.abspath(lef_file)
|
|
90
|
+
if os.path.isfile(lef_file):
|
|
91
|
+
pathed_files.add(os.path.abspath(lef_file))
|
|
92
|
+
|
|
93
|
+
for lef in lefs:
|
|
94
|
+
pathed_files.add(os.path.abspath(lef))
|
|
95
|
+
|
|
96
|
+
layoutOptions.lefdef_config.lef_files = list(pathed_files)
|
|
97
|
+
layoutOptions.lefdef_config.read_lef_with_def = False
|
|
98
|
+
layoutOptions.lefdef_config.dbu = tech.dbu
|
|
99
|
+
|
|
100
|
+
layoutOptions.lefdef_config.produce_fills = True
|
|
101
|
+
|
|
102
|
+
for lef_file in layoutOptions.lefdef_config.lef_files:
|
|
103
|
+
print(f"[INFO] LEF file: {lef_file}")
|
|
104
|
+
|
|
105
|
+
# Set layer properties
|
|
106
|
+
layer_properties = tech.layer_properties_file
|
|
107
|
+
if layer_properties:
|
|
108
|
+
layer_properties = layer_properties[0]
|
|
109
|
+
if not os.path.isabs(layer_properties):
|
|
110
|
+
layer_properties = os.path.abspath(os.path.join(os.path.dirname(tech_file),
|
|
111
|
+
layer_properties))
|
|
112
|
+
if os.path.exists(local_files['lyp']):
|
|
113
|
+
layer_properties = os.path.abspath(local_files['lyp'])
|
|
114
|
+
elif schema.valid('pdk', sc_pdk, 'display', 'klayout', sc_stackup):
|
|
115
|
+
pdk_layer_props = schema.get('pdk', sc_pdk, 'display', 'klayout', sc_stackup)
|
|
116
|
+
if pdk_layer_props:
|
|
117
|
+
layer_properties = pdk_layer_props[0]
|
|
118
|
+
|
|
119
|
+
if layer_properties and os.path.exists(layer_properties):
|
|
120
|
+
tech.layer_properties_file = layer_properties
|
|
121
|
+
print(f"[INFO] Layer properties: {layer_properties}")
|
|
122
|
+
|
|
123
|
+
# Set layer map
|
|
124
|
+
map_file = layoutOptions.lefdef_config.map_file
|
|
125
|
+
if map_file:
|
|
126
|
+
map_file = map_file[0]
|
|
127
|
+
if not os.path.isabs(map_file):
|
|
128
|
+
map_file = os.path.abspath(os.path.join(os.path.dirname(tech_file),
|
|
129
|
+
map_file))
|
|
130
|
+
for s in get_streams(schema):
|
|
131
|
+
if schema.valid('pdk', sc_pdk, 'layermap', 'klayout', 'def', s, sc_stackup):
|
|
132
|
+
map_file = schema.get('pdk', sc_pdk, 'layermap', 'klayout', 'def', s, sc_stackup)
|
|
133
|
+
if map_file:
|
|
134
|
+
map_file = map_file[0]
|
|
135
|
+
break
|
|
136
|
+
|
|
137
|
+
if map_file and os.path.exists(map_file):
|
|
138
|
+
layoutOptions.lefdef_config.map_file = map_file
|
|
139
|
+
print(f"[INFO] Layer map: {map_file}")
|
|
140
|
+
|
|
141
|
+
tech.load_layout_options = layoutOptions
|
|
142
|
+
|
|
143
|
+
return tech
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def save_technology(design, tech):
|
|
147
|
+
tech.default_base_path = '.'
|
|
148
|
+
tech.base_path = '.'
|
|
149
|
+
|
|
150
|
+
if tech.layer_properties_file:
|
|
151
|
+
layer_file = f'{design}.lyp'
|
|
152
|
+
shutil.copyfile(tech.layer_properties_file,
|
|
153
|
+
f'outputs/{layer_file}')
|
|
154
|
+
tech.layer_properties_file = layer_file
|
|
155
|
+
|
|
156
|
+
tech.save(f'outputs/{design}.lyt')
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def get_write_options(filename, timestamps):
|
|
160
|
+
write_options = pya.SaveLayoutOptions()
|
|
161
|
+
write_options.gds2_write_timestamps = timestamps
|
|
162
|
+
write_options.set_format_from_filename(filename)
|
|
163
|
+
|
|
164
|
+
return write_options
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def get_schema(manifest):
|
|
168
|
+
scroot = os.path.join(os.path.dirname(__file__), '..', '..')
|
|
169
|
+
module_name = 'schema'
|
|
170
|
+
schema_base = os.path.join(scroot, module_name, '__init__.py')
|
|
171
|
+
spec = importlib_util.spec_from_file_location(module_name, schema_base)
|
|
172
|
+
module = importlib_util.module_from_spec(spec)
|
|
173
|
+
sys.modules[module_name] = module
|
|
174
|
+
spec.loader.exec_module(module)
|
|
175
|
+
# Return schema
|
|
176
|
+
return module.Schema(manifest=manifest)
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
from siliconcompiler import SiliconCompilerError
|
|
2
|
+
from siliconcompiler.tools.klayout.klayout import setup as setup_tool
|
|
3
|
+
from siliconcompiler.tools._common import input_provides, get_tool_task
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def setup(chip):
|
|
7
|
+
'''
|
|
8
|
+
Perform unit operations on stream files. Currently supports:
|
|
9
|
+
|
|
10
|
+
* rotating (rotate)
|
|
11
|
+
* renaming (rename)
|
|
12
|
+
* merging streams (merge)
|
|
13
|
+
* adding streams together (add)
|
|
14
|
+
* adding outline to top (outline)
|
|
15
|
+
* swapping cells (swap)
|
|
16
|
+
* adding new top cell (add_top)
|
|
17
|
+
* renaming cells (rename_cell)
|
|
18
|
+
* flatten
|
|
19
|
+
* deleting layers
|
|
20
|
+
* merging shapes
|
|
21
|
+
* writing (write)
|
|
22
|
+
* converting properties into text labels on design (convert_property)
|
|
23
|
+
|
|
24
|
+
To rotate:
|
|
25
|
+
|
|
26
|
+
>>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', 'rotate')
|
|
27
|
+
|
|
28
|
+
To rename:
|
|
29
|
+
|
|
30
|
+
>>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
|
|
31
|
+
'rename:tool,klayout,task,operations,var,new_name')
|
|
32
|
+
>>> chip.set('tool', 'klayout, 'task', 'operations', 'var', 'new_name', \\
|
|
33
|
+
'chip_top')
|
|
34
|
+
|
|
35
|
+
To merge streams:
|
|
36
|
+
|
|
37
|
+
>>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
|
|
38
|
+
'merge:tool,klayout,task,operations,file,fill_stream')
|
|
39
|
+
>>> chip.set('tool', 'klayout, 'task', 'operations', 'file', 'fill_stream', \\
|
|
40
|
+
'./fill.gds')
|
|
41
|
+
|
|
42
|
+
or to get it from the inputs to this task:
|
|
43
|
+
|
|
44
|
+
>>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
|
|
45
|
+
'merge:fill.gds')
|
|
46
|
+
|
|
47
|
+
To add streams:
|
|
48
|
+
|
|
49
|
+
>>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
|
|
50
|
+
'add:tool,klayout,task,operations,file,fill_stream')
|
|
51
|
+
>>> chip.set('tool', 'klayout, 'task', 'operations', 'file', 'fill_stream', \\
|
|
52
|
+
'./fill.gds')
|
|
53
|
+
|
|
54
|
+
or to get it from the inputs to this task:
|
|
55
|
+
|
|
56
|
+
>>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
|
|
57
|
+
'add:fill.gds')
|
|
58
|
+
|
|
59
|
+
To add outline:
|
|
60
|
+
|
|
61
|
+
>>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
|
|
62
|
+
'outline:tool,klayout,task,operations,var,outline')
|
|
63
|
+
>>> chip.set('tool', 'klayout, 'task', 'operations', 'var', 'outline', \\
|
|
64
|
+
['10', '1']) # layer / purpose pair
|
|
65
|
+
|
|
66
|
+
To swap layout cells:
|
|
67
|
+
|
|
68
|
+
>>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
|
|
69
|
+
'swap:tool,klayout,task,operations,var,cell_swap')
|
|
70
|
+
>>> chip.set('tool', 'klayout, 'task', 'operations', 'var', 'cell_swap', \\
|
|
71
|
+
['dummy_ANDX2=ANDX2', 'dummy_NANDX2=NANDX2'])
|
|
72
|
+
|
|
73
|
+
To rename cells:
|
|
74
|
+
|
|
75
|
+
>>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
|
|
76
|
+
'rename_cell:tool,klayout,task,operations,var,rename_cell')
|
|
77
|
+
>>> chip.set('tool', 'klayout, 'task', 'operations', 'var', 'rename_cell', \\
|
|
78
|
+
['dummy_ANDX2=ANDX2', 'dummy_NANDX2=NANDX2'])
|
|
79
|
+
|
|
80
|
+
To add new top cell:
|
|
81
|
+
|
|
82
|
+
>>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
|
|
83
|
+
'add_top:tool,klayout,task,operations,var,new_name')
|
|
84
|
+
>>> chip.set('tool', 'klayout, 'task', 'operations', 'var', 'new_name', \\
|
|
85
|
+
'chip_top')
|
|
86
|
+
|
|
87
|
+
To write out a new file:
|
|
88
|
+
|
|
89
|
+
>>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
|
|
90
|
+
'write:combined.gds')
|
|
91
|
+
|
|
92
|
+
To convert stream properties to text labels:
|
|
93
|
+
|
|
94
|
+
>>> chip.add('tool', 'klayout, 'task', 'operations', 'var', 'operations', \\
|
|
95
|
+
'convert_property:tool,klayout,task,operations,var,convert_c4_bumps')
|
|
96
|
+
>>> chip.set('tool', 'klayout, 'task', 'operations', 'var', 'convert_c4_bumps', \\
|
|
97
|
+
['10', '2', \\ # layer / purpose pair for the source of the labels
|
|
98
|
+
'3' \\ # stream property number
|
|
99
|
+
'85', '5']) # (optional) destination layer / purpose pair, if not provided
|
|
100
|
+
# the source pair will be used instead.
|
|
101
|
+
'''
|
|
102
|
+
|
|
103
|
+
# Generic tool setup.
|
|
104
|
+
setup_tool(chip)
|
|
105
|
+
|
|
106
|
+
tool = 'klayout'
|
|
107
|
+
step = chip.get('arg', 'step')
|
|
108
|
+
index = chip.get('arg', 'index')
|
|
109
|
+
_, task = get_tool_task(chip, step, index)
|
|
110
|
+
clobber = False
|
|
111
|
+
|
|
112
|
+
script = 'klayout_operations.py'
|
|
113
|
+
option = ['-z', '-nc', '-rx', '-r']
|
|
114
|
+
chip.set('tool', tool, 'task', task, 'script', script, step=step, index=index, clobber=clobber)
|
|
115
|
+
chip.set('tool', tool, 'task', task, 'option', option, step=step, index=index, clobber=clobber)
|
|
116
|
+
|
|
117
|
+
# Set stream extension
|
|
118
|
+
streams = ('gds', 'oas')
|
|
119
|
+
chip.set('tool', tool, 'task', task, 'var', 'stream', 'gds',
|
|
120
|
+
step=step, index=index, clobber=False)
|
|
121
|
+
chip.set('tool', tool, 'task', task, 'var', 'stream',
|
|
122
|
+
f'Extension to use for stream generation ({streams})',
|
|
123
|
+
field='help')
|
|
124
|
+
default_stream = chip.get('tool', tool, 'task', task, 'var', 'stream',
|
|
125
|
+
step=step, index=index)[0]
|
|
126
|
+
# Input/Output requirements for default flow
|
|
127
|
+
design = chip.top()
|
|
128
|
+
if f'{design}.{default_stream}' in input_provides(chip, step, index):
|
|
129
|
+
chip.add('tool', tool, 'task', task, 'input', f'{design}.{default_stream}',
|
|
130
|
+
step=step, index=index)
|
|
131
|
+
else:
|
|
132
|
+
chip.add('tool', tool, 'task', task, 'require', f'input,layout,{default_stream}')
|
|
133
|
+
chip.add('tool', tool, 'task', task, 'output', f'{design}.{default_stream}',
|
|
134
|
+
step=step, index=index)
|
|
135
|
+
|
|
136
|
+
# Export GDS with timestamps by default.
|
|
137
|
+
chip.set('tool', tool, 'task', task, 'var', 'timestamps', 'true',
|
|
138
|
+
step=step, index=index, clobber=False)
|
|
139
|
+
chip.set('tool', tool, 'task', task, 'var', 'timestamps',
|
|
140
|
+
'Export GDSII with timestamps',
|
|
141
|
+
field='help')
|
|
142
|
+
|
|
143
|
+
klayout_ops = ('merge',
|
|
144
|
+
'add',
|
|
145
|
+
'rotate',
|
|
146
|
+
'outline',
|
|
147
|
+
'rename',
|
|
148
|
+
'swap',
|
|
149
|
+
'add_top',
|
|
150
|
+
'write',
|
|
151
|
+
'convert_property',
|
|
152
|
+
'flatten',
|
|
153
|
+
'merge_shapes',
|
|
154
|
+
'delete_layers',
|
|
155
|
+
'rename_cell')
|
|
156
|
+
ops = chip.get('tool', tool, 'task', task, 'var', 'operations', step=step, index=index)
|
|
157
|
+
for op in ops:
|
|
158
|
+
klayout_op = op.split(':', 1)
|
|
159
|
+
if len(klayout_op) == 1:
|
|
160
|
+
klayout_op = klayout_op[0]
|
|
161
|
+
args = ""
|
|
162
|
+
else:
|
|
163
|
+
klayout_op, args = klayout_op
|
|
164
|
+
|
|
165
|
+
if klayout_op not in klayout_ops:
|
|
166
|
+
raise SiliconCompilerError(
|
|
167
|
+
f'{klayout_op} is not a supported operation in klayout: {klayout_ops}',
|
|
168
|
+
chip=chip)
|
|
169
|
+
|
|
170
|
+
if klayout_op in ('add', 'merge'):
|
|
171
|
+
if ',' in args:
|
|
172
|
+
chip.add('tool', tool, 'task', task, 'require', args, step=step, index=index)
|
|
173
|
+
elif args:
|
|
174
|
+
chip.add('tool', tool, 'task', task, 'input', args, step=step, index=index)
|
|
175
|
+
else:
|
|
176
|
+
raise SiliconCompilerError(
|
|
177
|
+
f'{klayout_op} requires a filename to read or a keypath', chip=chip)
|
|
178
|
+
elif klayout_op in ('outline',
|
|
179
|
+
'rename',
|
|
180
|
+
'swap',
|
|
181
|
+
'add_top',
|
|
182
|
+
'convert_property',
|
|
183
|
+
'merge_shapes',
|
|
184
|
+
'delete_layers',
|
|
185
|
+
'rename_cell'):
|
|
186
|
+
chip.add('tool', tool, 'task', task, 'require', args, step=step, index=index)
|
|
187
|
+
elif klayout_op in ('rotate', 'flatten'):
|
|
188
|
+
if args:
|
|
189
|
+
raise SiliconCompilerError('rotate does not take any arguments', chip=chip)
|
|
190
|
+
elif klayout_op in ('write'):
|
|
191
|
+
if not args:
|
|
192
|
+
raise SiliconCompilerError('write requires a filename to save to', chip=chip)
|
|
193
|
+
chip.add('tool', tool, 'task', task, 'output', args,
|
|
194
|
+
step=step, index=index)
|