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.
Files changed (89) hide show
  1. siliconcompiler/_metadata.py +1 -1
  2. siliconcompiler/constraints/__init__.py +4 -1
  3. siliconcompiler/constraints/asic_timing.py +230 -38
  4. siliconcompiler/constraints/fpga_timing.py +209 -14
  5. siliconcompiler/constraints/timing_mode.py +82 -0
  6. siliconcompiler/data/templates/tcl/manifest.tcl.j2 +0 -6
  7. siliconcompiler/flowgraph.py +95 -42
  8. siliconcompiler/flows/generate_openroad_rcx.py +2 -2
  9. siliconcompiler/flows/highresscreenshotflow.py +37 -0
  10. siliconcompiler/library.py +2 -1
  11. siliconcompiler/package/__init__.py +39 -45
  12. siliconcompiler/project.py +4 -1
  13. siliconcompiler/scheduler/scheduler.py +64 -35
  14. siliconcompiler/scheduler/schedulernode.py +5 -2
  15. siliconcompiler/scheduler/slurm.py +7 -6
  16. siliconcompiler/scheduler/taskscheduler.py +19 -16
  17. siliconcompiler/schema/_metadata.py +1 -1
  18. siliconcompiler/schema/namedschema.py +2 -4
  19. siliconcompiler/schema_support/cmdlineschema.py +0 -3
  20. siliconcompiler/schema_support/dependencyschema.py +0 -6
  21. siliconcompiler/schema_support/record.py +4 -3
  22. siliconcompiler/tool.py +58 -27
  23. siliconcompiler/tools/_common/tcl/sc_schema_access.tcl +0 -6
  24. siliconcompiler/tools/chisel/convert.py +44 -0
  25. siliconcompiler/tools/ghdl/convert.py +37 -2
  26. siliconcompiler/tools/icarus/compile.py +14 -0
  27. siliconcompiler/tools/keplerformal/__init__.py +7 -0
  28. siliconcompiler/tools/keplerformal/lec.py +112 -0
  29. siliconcompiler/tools/klayout/drc.py +14 -0
  30. siliconcompiler/tools/klayout/export.py +40 -0
  31. siliconcompiler/tools/klayout/operations.py +40 -0
  32. siliconcompiler/tools/klayout/screenshot.py +66 -1
  33. siliconcompiler/tools/klayout/scripts/klayout_export.py +10 -40
  34. siliconcompiler/tools/klayout/scripts/klayout_show.py +4 -4
  35. siliconcompiler/tools/klayout/scripts/klayout_utils.py +13 -1
  36. siliconcompiler/tools/montage/tile.py +26 -12
  37. siliconcompiler/tools/openroad/__init__.py +11 -0
  38. siliconcompiler/tools/openroad/_apr.py +780 -11
  39. siliconcompiler/tools/openroad/antenna_repair.py +26 -0
  40. siliconcompiler/tools/openroad/fillmetal_insertion.py +14 -0
  41. siliconcompiler/tools/openroad/global_placement.py +67 -0
  42. siliconcompiler/tools/openroad/global_route.py +15 -0
  43. siliconcompiler/tools/openroad/init_floorplan.py +19 -2
  44. siliconcompiler/tools/openroad/macro_placement.py +252 -0
  45. siliconcompiler/tools/openroad/power_grid.py +43 -0
  46. siliconcompiler/tools/openroad/power_grid_analysis.py +1 -1
  47. siliconcompiler/tools/openroad/rcx_bench.py +28 -0
  48. siliconcompiler/tools/openroad/rcx_extract.py +14 -0
  49. siliconcompiler/tools/openroad/rdlroute.py +14 -0
  50. siliconcompiler/tools/openroad/repair_design.py +41 -0
  51. siliconcompiler/tools/openroad/repair_timing.py +54 -0
  52. siliconcompiler/tools/openroad/screenshot.py +31 -1
  53. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +8 -0
  54. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +54 -15
  55. siliconcompiler/tools/openroad/scripts/apr/sc_irdrop.tcl +6 -4
  56. siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +4 -4
  57. siliconcompiler/tools/openroad/scripts/common/procs.tcl +14 -5
  58. siliconcompiler/tools/openroad/scripts/common/read_liberty.tcl +2 -2
  59. siliconcompiler/tools/openroad/scripts/common/reports.tcl +6 -3
  60. siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +1 -1
  61. siliconcompiler/tools/openroad/scripts/common/write_data_physical.tcl +8 -0
  62. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +16 -12
  63. siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +3 -1
  64. siliconcompiler/tools/openroad/write_data.py +78 -2
  65. siliconcompiler/tools/opensta/scripts/sc_check_library.tcl +2 -2
  66. siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +2 -2
  67. siliconcompiler/tools/opensta/scripts/sc_timing.tcl +12 -14
  68. siliconcompiler/tools/opensta/timing.py +42 -3
  69. siliconcompiler/tools/slang/elaborate.py +16 -1
  70. siliconcompiler/tools/surelog/parse.py +54 -0
  71. siliconcompiler/tools/verilator/compile.py +120 -0
  72. siliconcompiler/tools/vivado/syn_fpga.py +27 -0
  73. siliconcompiler/tools/vpr/route.py +40 -0
  74. siliconcompiler/tools/xdm/convert.py +14 -0
  75. siliconcompiler/tools/xyce/simulate.py +26 -0
  76. siliconcompiler/tools/yosys/lec_asic.py +13 -0
  77. siliconcompiler/tools/yosys/syn_asic.py +332 -3
  78. siliconcompiler/tools/yosys/syn_fpga.py +32 -0
  79. siliconcompiler/toolscripts/_tools.json +9 -4
  80. siliconcompiler/toolscripts/ubuntu22/install-keplerformal.sh +72 -0
  81. siliconcompiler/toolscripts/ubuntu24/install-keplerformal.sh +72 -0
  82. siliconcompiler/utils/multiprocessing.py +11 -0
  83. siliconcompiler/utils/settings.py +70 -49
  84. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/METADATA +4 -4
  85. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/RECORD +89 -83
  86. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/WHEEL +0 -0
  87. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/entry_points.txt +0 -0
  88. {siliconcompiler-0.35.4.dist-info → siliconcompiler-0.36.1.dist-info}/licenses/LICENSE +0 -0
  89. {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
- self.set("var", "use_fsynopsys", value)
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
- self.set("var", "use_latches", value)
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'", defvalue=2)
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, in_files, out_file, tech, allow_missing, config_file='',
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
- main_layout.read(in_def, tech.load_layout_options)
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 def_cell in main_layout.each_cell():
55
- def_cells.append(def_cell.name)
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
- def_cells = sorted([cell for cell in def_cells if not cell.startswith("VIA_")])
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
- print("[INFO] Merging GDS/OAS files...")
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 libs:
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, in_files, out_file, sc_tech, allow_missing,
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 = 1
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
- design = schema.get('option', 'entrypoint')
122
- if not design:
123
- design = schema.get('design')
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 = 1
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 siliconcompiler import Task
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
  """