siliconcompiler 0.35.4__py3-none-any.whl → 0.36.1__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/_metadata.py +1 -1
- siliconcompiler/constraints/__init__.py +4 -1
- siliconcompiler/constraints/asic_timing.py +230 -38
- siliconcompiler/constraints/fpga_timing.py +209 -14
- siliconcompiler/constraints/timing_mode.py +82 -0
- siliconcompiler/data/templates/tcl/manifest.tcl.j2 +0 -6
- siliconcompiler/flowgraph.py +95 -42
- siliconcompiler/flows/generate_openroad_rcx.py +2 -2
- siliconcompiler/flows/highresscreenshotflow.py +37 -0
- siliconcompiler/library.py +2 -1
- siliconcompiler/package/__init__.py +39 -45
- siliconcompiler/project.py +4 -1
- siliconcompiler/scheduler/scheduler.py +64 -35
- siliconcompiler/scheduler/schedulernode.py +5 -2
- siliconcompiler/scheduler/slurm.py +7 -6
- siliconcompiler/scheduler/taskscheduler.py +19 -16
- siliconcompiler/schema/_metadata.py +1 -1
- siliconcompiler/schema/namedschema.py +2 -4
- siliconcompiler/schema_support/cmdlineschema.py +0 -3
- siliconcompiler/schema_support/dependencyschema.py +0 -6
- siliconcompiler/schema_support/record.py +4 -3
- siliconcompiler/tool.py +58 -27
- siliconcompiler/tools/_common/tcl/sc_schema_access.tcl +0 -6
- siliconcompiler/tools/chisel/convert.py +44 -0
- siliconcompiler/tools/ghdl/convert.py +37 -2
- siliconcompiler/tools/icarus/compile.py +14 -0
- siliconcompiler/tools/keplerformal/__init__.py +7 -0
- siliconcompiler/tools/keplerformal/lec.py +112 -0
- siliconcompiler/tools/klayout/drc.py +14 -0
- siliconcompiler/tools/klayout/export.py +40 -0
- siliconcompiler/tools/klayout/operations.py +40 -0
- siliconcompiler/tools/klayout/screenshot.py +66 -1
- siliconcompiler/tools/klayout/scripts/klayout_export.py +10 -40
- siliconcompiler/tools/klayout/scripts/klayout_show.py +4 -4
- siliconcompiler/tools/klayout/scripts/klayout_utils.py +13 -1
- siliconcompiler/tools/montage/tile.py +26 -12
- siliconcompiler/tools/openroad/__init__.py +11 -0
- siliconcompiler/tools/openroad/_apr.py +780 -11
- siliconcompiler/tools/openroad/antenna_repair.py +26 -0
- siliconcompiler/tools/openroad/fillmetal_insertion.py +14 -0
- siliconcompiler/tools/openroad/global_placement.py +67 -0
- siliconcompiler/tools/openroad/global_route.py +15 -0
- siliconcompiler/tools/openroad/init_floorplan.py +19 -2
- siliconcompiler/tools/openroad/macro_placement.py +252 -0
- siliconcompiler/tools/openroad/power_grid.py +43 -0
- siliconcompiler/tools/openroad/power_grid_analysis.py +1 -1
- siliconcompiler/tools/openroad/rcx_bench.py +28 -0
- siliconcompiler/tools/openroad/rcx_extract.py +14 -0
- siliconcompiler/tools/openroad/rdlroute.py +14 -0
- siliconcompiler/tools/openroad/repair_design.py +41 -0
- siliconcompiler/tools/openroad/repair_timing.py +54 -0
- siliconcompiler/tools/openroad/screenshot.py +31 -1
- siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +8 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +54 -15
- siliconcompiler/tools/openroad/scripts/apr/sc_irdrop.tcl +6 -4
- siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +4 -4
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +14 -5
- siliconcompiler/tools/openroad/scripts/common/read_liberty.tcl +2 -2
- siliconcompiler/tools/openroad/scripts/common/reports.tcl +6 -3
- siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +1 -1
- siliconcompiler/tools/openroad/scripts/common/write_data_physical.tcl +8 -0
- siliconcompiler/tools/openroad/scripts/common/write_images.tcl +16 -12
- siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +3 -1
- siliconcompiler/tools/openroad/write_data.py +78 -2
- siliconcompiler/tools/opensta/scripts/sc_check_library.tcl +2 -2
- siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +2 -2
- siliconcompiler/tools/opensta/scripts/sc_timing.tcl +12 -14
- siliconcompiler/tools/opensta/timing.py +42 -3
- siliconcompiler/tools/slang/elaborate.py +16 -1
- siliconcompiler/tools/surelog/parse.py +54 -0
- siliconcompiler/tools/verilator/compile.py +120 -0
- siliconcompiler/tools/vivado/syn_fpga.py +27 -0
- siliconcompiler/tools/vpr/route.py +40 -0
- siliconcompiler/tools/xdm/convert.py +14 -0
- siliconcompiler/tools/xyce/simulate.py +26 -0
- siliconcompiler/tools/yosys/lec_asic.py +13 -0
- siliconcompiler/tools/yosys/syn_asic.py +332 -3
- siliconcompiler/tools/yosys/syn_fpga.py +32 -0
- siliconcompiler/toolscripts/_tools.json +9 -4
- siliconcompiler/toolscripts/ubuntu22/install-keplerformal.sh +72 -0
- siliconcompiler/toolscripts/ubuntu24/install-keplerformal.sh +72 -0
- siliconcompiler/utils/multiprocessing.py +11 -0
- siliconcompiler/utils/settings.py +70 -49
- {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/METADATA +4 -4
- {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/RECORD +89 -83
- {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/licenses/LICENSE +0 -0
- {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/top_level.txt +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from typing import Optional
|
|
1
2
|
from siliconcompiler import Task
|
|
2
3
|
|
|
3
4
|
|
|
@@ -12,10 +13,44 @@ class ConvertTask(Task):
|
|
|
12
13
|
self.add_parameter("use_latches", "bool", "add the --latches flag", defvalue=False)
|
|
13
14
|
|
|
14
15
|
def set_usefsynopsys(self, value: bool):
|
|
15
|
-
|
|
16
|
+
"""Deprecated: use set_ghdl_usefsynopsys instead."""
|
|
17
|
+
import warnings
|
|
18
|
+
warnings.warn("set_usefsynopsys is deprecated, use set_ghdl_usefsynopsys instead.",
|
|
19
|
+
DeprecationWarning, stacklevel=2)
|
|
20
|
+
self.set_ghdl_usefsynopsys(value)
|
|
21
|
+
|
|
22
|
+
def set_ghdl_usefsynopsys(self, value: bool,
|
|
23
|
+
step: Optional[str] = None,
|
|
24
|
+
index: Optional[str] = None):
|
|
25
|
+
"""
|
|
26
|
+
Adds the -fsynopsys flag to the GHDL command.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
value (bool): Whether to add the flag.
|
|
30
|
+
step (str, optional): The step to associate with this setting.
|
|
31
|
+
index (str, optional): The index to associate with this setting.
|
|
32
|
+
"""
|
|
33
|
+
self.set("var", "use_fsynopsys", value, step=step, index=index)
|
|
16
34
|
|
|
17
35
|
def set_uselatches(self, value: bool):
|
|
18
|
-
|
|
36
|
+
"""Deprecated: use set_ghdl_uselatches instead."""
|
|
37
|
+
import warnings
|
|
38
|
+
warnings.warn("set_uselatches is deprecated, use set_ghdl_uselatches instead.",
|
|
39
|
+
DeprecationWarning, stacklevel=2)
|
|
40
|
+
self.set_ghdl_uselatches(value)
|
|
41
|
+
|
|
42
|
+
def set_ghdl_uselatches(self, value: bool,
|
|
43
|
+
step: Optional[str] = None,
|
|
44
|
+
index: Optional[str] = None):
|
|
45
|
+
"""
|
|
46
|
+
Adds the --latches flag to the GHDL command.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
value (bool): Whether to add the flag.
|
|
50
|
+
step (str, optional): The step to associate with this setting.
|
|
51
|
+
index (str, optional): The index to associate with this setting.
|
|
52
|
+
"""
|
|
53
|
+
self.set("var", "use_latches", value, step=step, index=index)
|
|
19
54
|
|
|
20
55
|
def tool(self):
|
|
21
56
|
return "ghdl"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from typing import Optional
|
|
1
2
|
from siliconcompiler import Task
|
|
2
3
|
|
|
3
4
|
|
|
@@ -14,6 +15,19 @@ class CompileTask(Task):
|
|
|
14
15
|
'See the corresponding "-g" flags in the Icarus manual for more "'
|
|
15
16
|
'"information.')
|
|
16
17
|
|
|
18
|
+
def set_icarus_veriloggeneration(self, gen: str,
|
|
19
|
+
step: Optional[str] = None,
|
|
20
|
+
index: Optional[str] = None):
|
|
21
|
+
"""
|
|
22
|
+
Sets the Verilog language generation for Icarus.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
gen (str): The Verilog generation to use.
|
|
26
|
+
step (str, optional): The specific step to apply this configuration to.
|
|
27
|
+
index (str, optional): The specific index to apply this configuration to.
|
|
28
|
+
"""
|
|
29
|
+
self.set("var", "verilog_generation", gen, step=step, index=index)
|
|
30
|
+
|
|
17
31
|
def tool(self):
|
|
18
32
|
return "icarus"
|
|
19
33
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Kepler-Formal is a logic equivalence checking (LEC) tool that operates on verilog
|
|
3
|
+
and the naja interchange format (https://github.com/najaeda/naja-if) and focuses
|
|
4
|
+
today on combinational equivalence checking only.
|
|
5
|
+
|
|
6
|
+
Sources: https://github.com/keplertech/kepler-formal
|
|
7
|
+
'''
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import os.path
|
|
2
|
+
|
|
3
|
+
from siliconcompiler import Task
|
|
4
|
+
from siliconcompiler.utils import sc_open
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LECTask(Task):
|
|
8
|
+
"""LEC task using Kepler-formal for logical equivalence checking."""
|
|
9
|
+
def tool(self) -> str:
|
|
10
|
+
return "kepler-formal"
|
|
11
|
+
|
|
12
|
+
def task(self) -> str:
|
|
13
|
+
return "lec"
|
|
14
|
+
|
|
15
|
+
def setup(self) -> None:
|
|
16
|
+
super().setup()
|
|
17
|
+
|
|
18
|
+
self.set_exe("kepler-formal")
|
|
19
|
+
|
|
20
|
+
# Log file handled by kepler-formal config
|
|
21
|
+
self.set_logdestination("stdout", "none")
|
|
22
|
+
self.set_logdestination("stderr", "none")
|
|
23
|
+
|
|
24
|
+
if f"{self.design_topmodule}.lec.vg" in self.get_files_from_input_nodes():
|
|
25
|
+
inputnodes = self.get_files_from_input_nodes()[f"{self.design_topmodule}.lec.vg"]
|
|
26
|
+
if len(inputnodes) != 2:
|
|
27
|
+
raise ValueError("LEC requires exactly two input netlists for comparison.")
|
|
28
|
+
for node in inputnodes:
|
|
29
|
+
self.add_input_file(
|
|
30
|
+
self.compute_input_file_node_name(f"{self.design_topmodule}.lec.vg", *node))
|
|
31
|
+
|
|
32
|
+
scenarios = self.project.constraint.timing.get_scenario()
|
|
33
|
+
if not scenarios:
|
|
34
|
+
raise ValueError("LEC requires at least one timing scenario to determine "
|
|
35
|
+
"library corners.")
|
|
36
|
+
scenario = list(scenarios.values())[0]
|
|
37
|
+
libcorners = scenario.get_libcorner(self.step, self.index)
|
|
38
|
+
delay_model = self.project.get("asic", "delaymodel")
|
|
39
|
+
for asiclib in self.project.get("asic", "asiclib"):
|
|
40
|
+
lib = self.project.get("library", asiclib, field="schema")
|
|
41
|
+
for corner in libcorners:
|
|
42
|
+
if not lib.valid("asic", "libcornerfileset", corner, delay_model):
|
|
43
|
+
continue
|
|
44
|
+
self.add_required_key(lib, "asic", "libcornerfileset", corner, delay_model)
|
|
45
|
+
for fileset in lib.get("asic", "libcornerfileset", corner, delay_model):
|
|
46
|
+
self.add_required_key(lib, "fileset", fileset, "file", "liberty")
|
|
47
|
+
|
|
48
|
+
def __config_file(self) -> str:
|
|
49
|
+
return "lec.yaml"
|
|
50
|
+
|
|
51
|
+
def pre_process(self):
|
|
52
|
+
super().pre_process()
|
|
53
|
+
|
|
54
|
+
with open(self.__config_file(), "w") as f:
|
|
55
|
+
f.write("format: verilog\n")
|
|
56
|
+
f.write("input_paths:\n")
|
|
57
|
+
for node in self.get_files_from_input_nodes()[f"{self.design_topmodule}.lec.vg"]:
|
|
58
|
+
filename = self.compute_input_file_node_name(f"{self.design_topmodule}.lec.vg",
|
|
59
|
+
*node)
|
|
60
|
+
f.write(f" - inputs/{filename}\n")
|
|
61
|
+
f.write("liberty_files:\n")
|
|
62
|
+
|
|
63
|
+
scenario = list(self.project.constraint.timing.get_scenario().values())[0]
|
|
64
|
+
libcorners = scenario.get_libcorner(self.step, self.index)
|
|
65
|
+
delay_model = self.project.get("asic", "delaymodel")
|
|
66
|
+
for asiclib in self.project.get("asic", "asiclib"):
|
|
67
|
+
lib = self.project.get("library", asiclib, field="schema")
|
|
68
|
+
for corner in libcorners:
|
|
69
|
+
if not lib.valid("asic", "libcornerfileset", corner, delay_model):
|
|
70
|
+
continue
|
|
71
|
+
for fileset in lib.get("asic", "libcornerfileset", corner, delay_model):
|
|
72
|
+
for file in lib.get_file(fileset=fileset, filetype="liberty"):
|
|
73
|
+
f.write(f" - {file}\n")
|
|
74
|
+
f.write(f"log_file: {self.get_logpath('exe')}\n")
|
|
75
|
+
|
|
76
|
+
def runtime_options(self):
|
|
77
|
+
options = super().runtime_options()
|
|
78
|
+
options.append("--config")
|
|
79
|
+
options.append(self.__config_file())
|
|
80
|
+
return options
|
|
81
|
+
|
|
82
|
+
def post_process(self):
|
|
83
|
+
super().post_process()
|
|
84
|
+
# Kepler-formal writes its own log file; nothing to do here.
|
|
85
|
+
errors = 0
|
|
86
|
+
log = self.get_logpath('exe')
|
|
87
|
+
if os.path.exists(log):
|
|
88
|
+
with sc_open(log, 'r') as f:
|
|
89
|
+
for logline in f:
|
|
90
|
+
if "Found difference " in logline:
|
|
91
|
+
errors += 1
|
|
92
|
+
|
|
93
|
+
self.record_metric("drvs", errors, source_file=log)
|
|
94
|
+
|
|
95
|
+
@classmethod
|
|
96
|
+
def make_docs(cls):
|
|
97
|
+
from siliconcompiler import Flowgraph, Design, ASIC
|
|
98
|
+
from siliconcompiler.scheduler import SchedulerNode
|
|
99
|
+
from siliconcompiler.targets import freepdk45_demo
|
|
100
|
+
design = Design("<design>")
|
|
101
|
+
with design.active_fileset("docs"):
|
|
102
|
+
design.set_topmodule("top")
|
|
103
|
+
proj = ASIC(design)
|
|
104
|
+
proj.add_fileset("docs")
|
|
105
|
+
freepdk45_demo(proj)
|
|
106
|
+
flow = Flowgraph("docsflow")
|
|
107
|
+
flow.node("<step>", cls(), index="<index>")
|
|
108
|
+
proj.set_flow(flow)
|
|
109
|
+
|
|
110
|
+
node = SchedulerNode(proj, "<step>", "<index>")
|
|
111
|
+
node.setup()
|
|
112
|
+
return node.task
|
|
@@ -2,6 +2,7 @@ import shlex
|
|
|
2
2
|
|
|
3
3
|
import os.path
|
|
4
4
|
|
|
5
|
+
from typing import Optional
|
|
5
6
|
from xml.etree import ElementTree
|
|
6
7
|
|
|
7
8
|
from siliconcompiler.tools.klayout import KLayoutTask
|
|
@@ -14,6 +15,19 @@ class DRCTask(KLayoutTask):
|
|
|
14
15
|
|
|
15
16
|
self.add_parameter("drc_name", "str", "name of the DRC deck to run")
|
|
16
17
|
|
|
18
|
+
def set_klayout_drcname(self, name: str,
|
|
19
|
+
step: Optional[str] = None,
|
|
20
|
+
index: Optional[str] = None):
|
|
21
|
+
"""
|
|
22
|
+
Sets the name of the DRC deck to run.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
name (str): The name of the DRC deck.
|
|
26
|
+
step (str, optional): The specific step to apply this configuration to.
|
|
27
|
+
index (str, optional): The specific index to apply this configuration to.
|
|
28
|
+
"""
|
|
29
|
+
self.set("var", "drc_name", name, step=step, index=index)
|
|
30
|
+
|
|
17
31
|
def task(self):
|
|
18
32
|
return "drc"
|
|
19
33
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from typing import Optional
|
|
1
2
|
from siliconcompiler.tools.klayout import KLayoutTask
|
|
2
3
|
from siliconcompiler.tools.klayout.screenshot import ScreenshotParams
|
|
3
4
|
|
|
@@ -13,6 +14,45 @@ class ExportTask(KLayoutTask, ScreenshotParams):
|
|
|
13
14
|
"true/false: true will cause KLayout to generate a screenshot of "
|
|
14
15
|
"the layout", defvalue=True)
|
|
15
16
|
|
|
17
|
+
def set_klayout_stream(self, stream: str,
|
|
18
|
+
step: Optional[str] = None,
|
|
19
|
+
index: Optional[str] = None):
|
|
20
|
+
"""
|
|
21
|
+
Sets the stream format for generation.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
stream (str): The stream format to use.
|
|
25
|
+
step (str, optional): The specific step to apply this configuration to.
|
|
26
|
+
index (str, optional): The specific index to apply this configuration to.
|
|
27
|
+
"""
|
|
28
|
+
self.set("var", "stream", stream, step=step, index=index)
|
|
29
|
+
|
|
30
|
+
def set_klayout_timestamps(self, enable: bool,
|
|
31
|
+
step: Optional[str] = None,
|
|
32
|
+
index: Optional[str] = None):
|
|
33
|
+
"""
|
|
34
|
+
Enables or disables exporting GDSII with timestamps.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
enable (bool): Whether to enable timestamps.
|
|
38
|
+
step (str, optional): The specific step to apply this configuration to.
|
|
39
|
+
index (str, optional): The specific index to apply this configuration to.
|
|
40
|
+
"""
|
|
41
|
+
self.set("var", "timestamps", enable, step=step, index=index)
|
|
42
|
+
|
|
43
|
+
def set_klayout_screenshot(self, enable: bool,
|
|
44
|
+
step: Optional[str] = None,
|
|
45
|
+
index: Optional[str] = None):
|
|
46
|
+
"""
|
|
47
|
+
Enables or disables generating a screenshot of the layout.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
enable (bool): Whether to generate a screenshot.
|
|
51
|
+
step (str, optional): The specific step to apply this configuration to.
|
|
52
|
+
index (str, optional): The specific index to apply this configuration to.
|
|
53
|
+
"""
|
|
54
|
+
self.set("var", "screenshot", enable, step=step, index=index)
|
|
55
|
+
|
|
16
56
|
def task(self):
|
|
17
57
|
return "export"
|
|
18
58
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from typing import Optional, List, Tuple
|
|
1
2
|
from siliconcompiler.tools.klayout import KLayoutTask
|
|
2
3
|
|
|
3
4
|
|
|
@@ -15,6 +16,45 @@ class OperationsTask(KLayoutTask):
|
|
|
15
16
|
self.add_parameter("timestamps", "bool",
|
|
16
17
|
"Export GDSII with timestamps", defvalue=True)
|
|
17
18
|
|
|
19
|
+
def set_klayout_operations(self, operations: List[Tuple[str, str]],
|
|
20
|
+
step: Optional[str] = None,
|
|
21
|
+
index: Optional[str] = None):
|
|
22
|
+
"""
|
|
23
|
+
Sets the list of operations to perform.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
operations (List[Tuple[str, str]]): The list of operations.
|
|
27
|
+
step (str, optional): The specific step to apply this configuration to.
|
|
28
|
+
index (str, optional): The specific index to apply this configuration to.
|
|
29
|
+
"""
|
|
30
|
+
self.set("var", "operations", operations, step=step, index=index)
|
|
31
|
+
|
|
32
|
+
def set_klayout_stream(self, stream: str,
|
|
33
|
+
step: Optional[str] = None,
|
|
34
|
+
index: Optional[str] = None):
|
|
35
|
+
"""
|
|
36
|
+
Sets the stream format for generation.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
stream (str): The stream format to use.
|
|
40
|
+
step (str, optional): The specific step to apply this configuration to.
|
|
41
|
+
index (str, optional): The specific index to apply this configuration to.
|
|
42
|
+
"""
|
|
43
|
+
self.set("var", "stream", stream, step=step, index=index)
|
|
44
|
+
|
|
45
|
+
def set_klayout_timestamps(self, enable: bool,
|
|
46
|
+
step: Optional[str] = None,
|
|
47
|
+
index: Optional[str] = None):
|
|
48
|
+
"""
|
|
49
|
+
Enables or disables exporting GDSII with timestamps.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
enable (bool): Whether to enable timestamps.
|
|
53
|
+
step (str, optional): The specific step to apply this configuration to.
|
|
54
|
+
index (str, optional): The specific index to apply this configuration to.
|
|
55
|
+
"""
|
|
56
|
+
self.set("var", "timestamps", enable, step=step, index=index)
|
|
57
|
+
|
|
18
58
|
def task(self):
|
|
19
59
|
return "operations"
|
|
20
60
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Optional, Union
|
|
2
|
+
|
|
1
3
|
from siliconcompiler import ScreenshotTask, Task
|
|
2
4
|
from siliconcompiler.tools.klayout.show import ShowTask
|
|
3
5
|
|
|
@@ -20,7 +22,70 @@ class ScreenshotParams(Task):
|
|
|
20
22
|
self.add_parameter("show_linewidth", "int",
|
|
21
23
|
"Width of lines in detailed screenshots", defvalue=0, unit="px")
|
|
22
24
|
self.add_parameter("show_oversampling", "int",
|
|
23
|
-
"Image oversampling used in detailed screenshots
|
|
25
|
+
"Image oversampling used in detailed screenshots", defvalue=2)
|
|
26
|
+
|
|
27
|
+
def set_klayout_bins(self, xbins: int, ybins: int,
|
|
28
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
29
|
+
"""
|
|
30
|
+
Set the number of bins for KLayout screenshotting.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
xbins (int): Number of bins along the x-axis.
|
|
34
|
+
ybins (int): Number of bins along the y-axis.
|
|
35
|
+
step (Optional[str]): Flow step to set the parameter for. Defaults to None.
|
|
36
|
+
index (Optional[Union[str, int]]): Index to set the parameter for. Defaults to None.
|
|
37
|
+
"""
|
|
38
|
+
self.set("var", "show_bins", (xbins, ybins), step=step, index=index)
|
|
39
|
+
|
|
40
|
+
def set_klayout_margin(self, margin: float,
|
|
41
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
42
|
+
"""
|
|
43
|
+
Set the margin for KLayout screenshotting.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
margin (float): Margin around the design in microns.
|
|
47
|
+
step (Optional[str]): Flow step to set the parameter for. Defaults to None.
|
|
48
|
+
index (Optional[Union[str, int]]): Index to set the parameter for. Defaults to None.
|
|
49
|
+
"""
|
|
50
|
+
self.set("var", "show_margin", margin, step=step, index=index)
|
|
51
|
+
|
|
52
|
+
def set_klayout_resolution(self, xres: int, yres: int,
|
|
53
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
54
|
+
"""
|
|
55
|
+
Set the resolution for KLayout screenshotting.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
xres (int): Horizontal resolution in pixels.
|
|
59
|
+
yres (int): Vertical resolution in pixels.
|
|
60
|
+
step (Optional[str]): Flow step to set the parameter for. Defaults to None.
|
|
61
|
+
index (Optional[Union[str, int]]): Index to set the parameter for. Defaults to None.
|
|
62
|
+
"""
|
|
63
|
+
self.set("var", "show_resolution", (xres, yres), step=step, index=index)
|
|
64
|
+
|
|
65
|
+
def set_klayout_linewidth(self, linewidth: int,
|
|
66
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
67
|
+
"""
|
|
68
|
+
Set the linewidth for KLayout screenshotting.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
linewidth (int): Width of lines in detailed screenshots.
|
|
72
|
+
step (Optional[str]): Flow step to set the parameter for. Defaults to None.
|
|
73
|
+
index (Optional[Union[str, int]]): Index to set the parameter for. Defaults to None.
|
|
74
|
+
"""
|
|
75
|
+
self.set("var", "show_linewidth", linewidth, step=step, index=index)
|
|
76
|
+
|
|
77
|
+
def set_klayout_oversampling(self, oversampling: int,
|
|
78
|
+
step: Optional[str] = None,
|
|
79
|
+
index: Optional[Union[str, int]] = None):
|
|
80
|
+
"""
|
|
81
|
+
Set the oversampling for KLayout screenshotting.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
oversampling (int): Image oversampling used in detailed screenshots.
|
|
85
|
+
step (Optional[str]): Flow step to set the parameter for. Defaults to None.
|
|
86
|
+
index (Optional[Union[str, int]]): Index to set the parameter for. Defaults to None.
|
|
87
|
+
"""
|
|
88
|
+
self.set("var", "show_oversampling", oversampling, step=step, index=index)
|
|
24
89
|
|
|
25
90
|
def setup(self):
|
|
26
91
|
super().setup()
|
|
@@ -39,24 +39,23 @@ import sys
|
|
|
39
39
|
import fnmatch
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
def gds_export(design_name, in_def,
|
|
43
|
-
seal_file='',
|
|
44
|
-
timestamps=True):
|
|
42
|
+
def gds_export(design_name, in_def, out_file, tech, allow_missing, timestamps=True):
|
|
45
43
|
from klayout_utils import get_write_options # noqa E402
|
|
46
44
|
|
|
47
45
|
# Load def file
|
|
48
46
|
main_layout = pya.Layout()
|
|
49
47
|
main_layout.technology_name = tech.name
|
|
50
|
-
|
|
48
|
+
layout_options = tech.load_layout_options
|
|
49
|
+
main_layout.read(in_def, layout_options)
|
|
51
50
|
|
|
52
51
|
# List cells
|
|
53
52
|
def_cells = []
|
|
54
|
-
for
|
|
55
|
-
def_cells.append(
|
|
53
|
+
for cell_idx in main_layout.cell(design_name).each_child_cell():
|
|
54
|
+
def_cells.append(main_layout.cell_name(cell_idx))
|
|
56
55
|
|
|
57
|
-
def_cells.remove(design_name)
|
|
58
56
|
# Remove vias
|
|
59
|
-
|
|
57
|
+
via_prefix = layout_options.lefdef_config.via_cellname_prefix
|
|
58
|
+
def_cells = sorted([cell for cell in def_cells if not cell.startswith(via_prefix)])
|
|
60
59
|
print(f"[INFO] Read in {len(def_cells)} cells from DEF file")
|
|
61
60
|
for cell in def_cells:
|
|
62
61
|
print(f" [INFO] DEF cell: {cell}")
|
|
@@ -65,16 +64,11 @@ def gds_export(design_name, in_def, in_files, out_file, tech, allow_missing, con
|
|
|
65
64
|
def_cells.remove(f"{design_name}_DEF_FILL")
|
|
66
65
|
|
|
67
66
|
# Load in the gds to merge
|
|
68
|
-
|
|
69
|
-
for fil in in_files:
|
|
67
|
+
for fil in layout_options.lefdef_config.macro_layout_files:
|
|
70
68
|
macro_layout = pya.Layout()
|
|
71
69
|
macro_layout.read(fil)
|
|
72
|
-
print(f"[INFO] Read in {fil}")
|
|
73
70
|
for cell in list(def_cells):
|
|
74
71
|
if macro_layout.has_cell(cell):
|
|
75
|
-
subcell = main_layout.cell(cell)
|
|
76
|
-
print(f" [INFO] Merging in {cell}")
|
|
77
|
-
subcell.copy_tree(macro_layout.cell(cell))
|
|
78
72
|
def_cells.remove(cell)
|
|
79
73
|
|
|
80
74
|
# Copy the top level only to a new layout
|
|
@@ -100,18 +94,6 @@ def gds_export(design_name, in_def, in_files, out_file, tech, allow_missing, con
|
|
|
100
94
|
if i.name != design_name and i.parent_cells() == 0:
|
|
101
95
|
print("[ERROR] Found orphan cell '{0}'".format(i.name))
|
|
102
96
|
|
|
103
|
-
if seal_file:
|
|
104
|
-
top_cell = top_only_layout.top_cell()
|
|
105
|
-
|
|
106
|
-
print("[INFO] Reading seal GDS/OAS file...")
|
|
107
|
-
print("\t{0}".format(seal_file))
|
|
108
|
-
top_only_layout.read(seal_file)
|
|
109
|
-
|
|
110
|
-
for cell in top_only_layout.top_cells():
|
|
111
|
-
if cell != top_cell:
|
|
112
|
-
print("[INFO] Merging '{0}' as child of '{1}'".format(cell.name, top_cell.name))
|
|
113
|
-
top.insert(pya.CellInstArray(cell.cell_index(), pya.Trans()))
|
|
114
|
-
|
|
115
97
|
# Write out the GDS
|
|
116
98
|
print("[INFO] Writing out GDS/OAS '{0}'".format(out_file))
|
|
117
99
|
top_only_layout.write(out_file, get_write_options(out_file, timestamps))
|
|
@@ -125,7 +107,6 @@ def main():
|
|
|
125
107
|
|
|
126
108
|
from klayout_utils import (
|
|
127
109
|
technology,
|
|
128
|
-
get_streams,
|
|
129
110
|
save_technology,
|
|
130
111
|
get_schema,
|
|
131
112
|
generate_metrics
|
|
@@ -155,18 +136,8 @@ def main():
|
|
|
155
136
|
|
|
156
137
|
out_file = os.path.join('outputs', f'{design}.{sc_stream}')
|
|
157
138
|
|
|
158
|
-
in_files = []
|
|
159
|
-
libs = schema.get("asic", "asiclib")
|
|
160
|
-
for lib in libs:
|
|
161
|
-
libobj = schema.get("library", lib, field="schema")
|
|
162
|
-
for s in get_streams(schema):
|
|
163
|
-
for fileset in libobj.get("asic", "aprfileset"):
|
|
164
|
-
if libobj.valid("fileset", fileset, "file", s):
|
|
165
|
-
in_files.extend(libobj.get("fileset", fileset, "file", s))
|
|
166
|
-
break
|
|
167
|
-
|
|
168
139
|
allow_missing = []
|
|
169
|
-
for lib in
|
|
140
|
+
for lib in schema.get("asic", "asiclib"):
|
|
170
141
|
if schema.valid('library', lib, 'tool', 'klayout', 'allow_missing_cell'):
|
|
171
142
|
patterns = [pattern for pattern in schema.get('library', lib, 'tool', 'klayout',
|
|
172
143
|
'allow_missing_cell') if pattern]
|
|
@@ -179,8 +150,7 @@ def main():
|
|
|
179
150
|
|
|
180
151
|
sc_tech = technology(design, schema)
|
|
181
152
|
|
|
182
|
-
gds_export(design, in_def,
|
|
183
|
-
config_file='', seal_file='', timestamps=sc_timestamps)
|
|
153
|
+
gds_export(design, in_def, out_file, sc_tech, allow_missing, timestamps=sc_timestamps)
|
|
184
154
|
|
|
185
155
|
if sc_screenshot:
|
|
186
156
|
show(schema, sc_tech, out_file, f'outputs/{design}.png', screenshot=True)
|
|
@@ -25,7 +25,7 @@ def show(schema, tech, input_path, output_path, screenshot=False, report=None):
|
|
|
25
25
|
layout_options.lefdef_config.produce_obstructions = True
|
|
26
26
|
|
|
27
27
|
# Always use LEF geometry even when LEF file contains FOREIGN statement.
|
|
28
|
-
layout_options.lefdef_config.macro_resolution_mode =
|
|
28
|
+
layout_options.lefdef_config.macro_resolution_mode = 0
|
|
29
29
|
|
|
30
30
|
tech.load_layout_options = layout_options
|
|
31
31
|
|
|
@@ -118,9 +118,9 @@ def __screenshot_montage(schema, view, xbins, ybins):
|
|
|
118
118
|
|
|
119
119
|
app.set_config("background-color", "#000000") # Black
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
design_name = schema.get('option', 'design')
|
|
122
|
+
fileset = schema.get("option", "fileset")[0]
|
|
123
|
+
design = schema.get("library", design_name, "fileset", fileset, "topmodule")
|
|
124
124
|
|
|
125
125
|
horizontal_resolution, vertical_resolution = schema.get(
|
|
126
126
|
'tool', 'klayout', 'task', task, 'var', 'show_resolution', step=step, index=index)
|
|
@@ -76,7 +76,7 @@ def technology(design, schema):
|
|
|
76
76
|
|
|
77
77
|
layout_options = tech.load_layout_options
|
|
78
78
|
|
|
79
|
-
layout_options.lefdef_config.macro_resolution_mode =
|
|
79
|
+
layout_options.lefdef_config.macro_resolution_mode = 0
|
|
80
80
|
layout_options.lefdef_config.via_cellname_prefix = "VIA_"
|
|
81
81
|
pathed_files = set()
|
|
82
82
|
for lef_file in layout_options.lefdef_config.lef_files:
|
|
@@ -98,6 +98,18 @@ def technology(design, schema):
|
|
|
98
98
|
for lef_file in layout_options.lefdef_config.lef_files:
|
|
99
99
|
print(f"[INFO] LEF file: {lef_file}")
|
|
100
100
|
|
|
101
|
+
in_files = layout_options.lefdef_config.macro_layout_files
|
|
102
|
+
for lib in schema.get("asic", "asiclib"):
|
|
103
|
+
libobj = schema.get("library", lib, field="schema")
|
|
104
|
+
for s in get_streams(schema):
|
|
105
|
+
for fileset in libobj.get("asic", "aprfileset"):
|
|
106
|
+
if libobj.valid("fileset", fileset, "file", s):
|
|
107
|
+
in_files.extend(libobj.get("fileset", fileset, "file", s))
|
|
108
|
+
break
|
|
109
|
+
layout_options.lefdef_config.macro_layout_files = in_files
|
|
110
|
+
for lef_file in layout_options.lefdef_config.macro_layout_files:
|
|
111
|
+
print(f"[INFO] Layout file: {lef_file}")
|
|
112
|
+
|
|
101
113
|
# Set layer properties
|
|
102
114
|
layer_properties = tech.layer_properties_file
|
|
103
115
|
if layer_properties:
|
|
@@ -1,20 +1,11 @@
|
|
|
1
|
-
from
|
|
1
|
+
from typing import Optional, Union
|
|
2
|
+
|
|
3
|
+
from siliconcompiler import Task, TaskSkip
|
|
2
4
|
|
|
3
5
|
|
|
4
6
|
class TileTask(Task):
|
|
5
7
|
'''
|
|
6
8
|
Tiles input images into a single output image.
|
|
7
|
-
|
|
8
|
-
Notes:
|
|
9
|
-
Need to make ensure that /etc/ImageMagick-6/policy.xml
|
|
10
|
-
<policy domain="resource" name="memory" value="8GiB"/>
|
|
11
|
-
<policy domain="resource" name="map" value="8GiB"/>
|
|
12
|
-
<policy domain="resource" name="width" value="32KP"/>
|
|
13
|
-
<policy domain="resource" name="height" value="32KP"/>
|
|
14
|
-
<policy domain="resource" name="area" value="1GP"/>
|
|
15
|
-
<policy domain="resource" name="disk" value="8GiB"/>
|
|
16
|
-
This ensures there are enough resources available to generate
|
|
17
|
-
the final image.
|
|
18
9
|
'''
|
|
19
10
|
|
|
20
11
|
def __init__(self):
|
|
@@ -23,6 +14,19 @@ class TileTask(Task):
|
|
|
23
14
|
self.add_parameter("bins", "(int,int)", "Number of bins along the (x, y)-axis",
|
|
24
15
|
defvalue=(2, 2))
|
|
25
16
|
|
|
17
|
+
def set_montage_bins(self, xbins: int, ybins: int,
|
|
18
|
+
step: Optional[str] = None, index: Optional[Union[str, int]] = None):
|
|
19
|
+
"""
|
|
20
|
+
Set the number of bins for Montage tiling.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
xbins (int): Number of bins along the x-axis.
|
|
24
|
+
ybins (int): Number of bins along the y-axis.
|
|
25
|
+
step (Optional[str]): Flow step to set the parameter for. Defaults to None.
|
|
26
|
+
index (Optional[Union[str, int]]): Index to set the parameter for. Defaults to None.
|
|
27
|
+
"""
|
|
28
|
+
self.set("var", "bins", (xbins, ybins), step=step, index=index)
|
|
29
|
+
|
|
26
30
|
def tool(self):
|
|
27
31
|
return "montage"
|
|
28
32
|
|
|
@@ -41,12 +45,22 @@ class TileTask(Task):
|
|
|
41
45
|
|
|
42
46
|
xbins, ybins = self.get("var", "bins")
|
|
43
47
|
|
|
48
|
+
if f"{self.design_topmodule}.png" in self.get_files_from_input_nodes():
|
|
49
|
+
raise TaskSkip("Input provides a single image; skipping tiling.")
|
|
50
|
+
|
|
44
51
|
for x in range(xbins):
|
|
45
52
|
for y in range(ybins):
|
|
46
53
|
self.add_input_file(f'{self.design_topmodule}_X{x}_Y{y}.png')
|
|
47
54
|
|
|
48
55
|
self.add_output_file(ext="png")
|
|
49
56
|
|
|
57
|
+
self.add_commandline_option(['-limit', 'memory', '8GiB'])
|
|
58
|
+
self.add_commandline_option(['-limit', 'map', '8GiB'])
|
|
59
|
+
self.add_commandline_option(['-limit', 'disk', '8GiB'])
|
|
60
|
+
self.add_commandline_option(['-limit', 'width', '32KP'])
|
|
61
|
+
self.add_commandline_option(['-limit', 'height', '32KP'])
|
|
62
|
+
self.add_commandline_option(['-limit', 'area', '1GP'])
|
|
63
|
+
|
|
50
64
|
def runtime_options(self):
|
|
51
65
|
options = super().runtime_options()
|
|
52
66
|
|
|
@@ -51,6 +51,8 @@ class OpenROADPDK(PDK):
|
|
|
51
51
|
"router and only uses the specified tech vias")
|
|
52
52
|
self.define_tool_parameter("openroad", "drt_repair_pdn_vias", "str",
|
|
53
53
|
"Via layer to repair after detailed routing")
|
|
54
|
+
self.define_tool_parameter("openroad", "drt_via_in_pin_layers", "(str,str)",
|
|
55
|
+
"Tuple of layers for vias in pin layers")
|
|
54
56
|
|
|
55
57
|
def set_openroad_rclayers(self, signal: str = None, clock: str = None):
|
|
56
58
|
"""
|
|
@@ -155,6 +157,15 @@ class OpenROADPDK(PDK):
|
|
|
155
157
|
"""
|
|
156
158
|
self.set("tool", "openroad", "drt_repair_pdn_vias", layer)
|
|
157
159
|
|
|
160
|
+
def set_openroad_detailedrouteviainpinlayers(self, layer1: str, layer2: str):
|
|
161
|
+
"""Sets the via layers used in pin layers during detailed routing.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
layer1 (str): The first layer for vias in pin layers.
|
|
165
|
+
layer2 (str): The second layer for vias in pin layers.
|
|
166
|
+
"""
|
|
167
|
+
self.set("tool", "openroad", "drt_via_in_pin_layers", (layer1, layer2))
|
|
168
|
+
|
|
158
169
|
|
|
159
170
|
class OpenROADStdCellLibrary(StdCellLibrary):
|
|
160
171
|
"""
|