siliconcompiler 0.35.3__py3-none-any.whl → 0.36.0__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/apps/sc_issue.py +18 -2
- siliconcompiler/checklist.py +2 -1
- siliconcompiler/constraints/__init__.py +4 -1
- siliconcompiler/constraints/asic_component.py +49 -11
- siliconcompiler/constraints/asic_floorplan.py +23 -21
- siliconcompiler/constraints/asic_pins.py +55 -17
- siliconcompiler/constraints/asic_timing.py +280 -57
- siliconcompiler/constraints/fpga_timing.py +212 -18
- siliconcompiler/constraints/timing_mode.py +82 -0
- siliconcompiler/data/templates/replay/replay.sh.j2 +27 -14
- 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 +56 -51
- siliconcompiler/project.py +13 -2
- siliconcompiler/scheduler/docker.py +24 -25
- siliconcompiler/scheduler/scheduler.py +143 -100
- siliconcompiler/scheduler/schedulernode.py +138 -22
- siliconcompiler/scheduler/slurm.py +120 -35
- siliconcompiler/scheduler/taskscheduler.py +19 -23
- siliconcompiler/schema/_metadata.py +1 -1
- siliconcompiler/schema/editableschema.py +29 -0
- siliconcompiler/schema/namedschema.py +2 -4
- siliconcompiler/schema/parametervalue.py +14 -2
- siliconcompiler/schema_support/cmdlineschema.py +0 -3
- siliconcompiler/schema_support/dependencyschema.py +0 -6
- siliconcompiler/schema_support/option.py +82 -1
- siliconcompiler/schema_support/pathschema.py +7 -13
- siliconcompiler/schema_support/record.py +4 -3
- siliconcompiler/tool.py +105 -52
- siliconcompiler/tools/_common/tcl/sc_schema_access.tcl +0 -6
- siliconcompiler/tools/keplerformal/__init__.py +7 -0
- siliconcompiler/tools/keplerformal/lec.py +112 -0
- siliconcompiler/tools/klayout/__init__.py +3 -0
- siliconcompiler/tools/klayout/screenshot.py +66 -1
- siliconcompiler/tools/klayout/scripts/klayout_convert_drc_db.py +1 -0
- siliconcompiler/tools/klayout/scripts/klayout_export.py +11 -40
- siliconcompiler/tools/klayout/scripts/klayout_operations.py +1 -0
- siliconcompiler/tools/klayout/scripts/klayout_show.py +5 -4
- siliconcompiler/tools/klayout/scripts/klayout_utils.py +16 -5
- siliconcompiler/tools/montage/tile.py +26 -12
- siliconcompiler/tools/openroad/__init__.py +27 -1
- siliconcompiler/tools/openroad/_apr.py +107 -14
- siliconcompiler/tools/openroad/clock_tree_synthesis.py +1 -0
- siliconcompiler/tools/openroad/global_placement.py +1 -0
- siliconcompiler/tools/openroad/init_floorplan.py +119 -7
- siliconcompiler/tools/openroad/power_grid_analysis.py +174 -0
- siliconcompiler/tools/openroad/repair_design.py +1 -0
- siliconcompiler/tools/openroad/repair_timing.py +1 -0
- siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +1 -1
- siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +91 -18
- siliconcompiler/tools/openroad/scripts/apr/sc_irdrop.tcl +148 -0
- siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +1 -1
- siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +8 -10
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +15 -6
- siliconcompiler/tools/openroad/scripts/common/read_liberty.tcl +2 -2
- siliconcompiler/tools/openroad/scripts/common/reports.tcl +7 -4
- 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/rcx/sc_rcx_bench.tcl +2 -4
- siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +3 -1
- siliconcompiler/tools/openroad/write_data.py +2 -2
- siliconcompiler/tools/opensta/__init__.py +1 -1
- 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 +13 -10
- siliconcompiler/tools/opensta/timing.py +6 -2
- siliconcompiler/tools/vivado/scripts/sc_bitstream.tcl +11 -0
- siliconcompiler/tools/vivado/scripts/sc_place.tcl +11 -0
- siliconcompiler/tools/vivado/scripts/sc_route.tcl +11 -0
- siliconcompiler/tools/vivado/scripts/sc_syn_fpga.tcl +10 -0
- siliconcompiler/tools/vpr/__init__.py +28 -0
- siliconcompiler/tools/yosys/scripts/sc_screenshot.tcl +1 -1
- siliconcompiler/tools/yosys/scripts/sc_synth_asic.tcl +40 -4
- siliconcompiler/tools/yosys/scripts/sc_synth_fpga.tcl +15 -5
- siliconcompiler/tools/yosys/syn_asic.py +42 -0
- siliconcompiler/tools/yosys/syn_fpga.py +8 -0
- siliconcompiler/toolscripts/_tools.json +12 -7
- siliconcompiler/toolscripts/ubuntu22/install-keplerformal.sh +72 -0
- siliconcompiler/toolscripts/ubuntu24/install-keplerformal.sh +72 -0
- siliconcompiler/utils/__init__.py +243 -51
- siliconcompiler/utils/curation.py +89 -56
- siliconcompiler/utils/issue.py +6 -1
- siliconcompiler/utils/multiprocessing.py +46 -2
- siliconcompiler/utils/paths.py +21 -0
- siliconcompiler/utils/settings.py +162 -0
- {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/METADATA +5 -4
- {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/RECORD +96 -87
- {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/licenses/LICENSE +0 -0
- {siliconcompiler-0.35.3.dist-info → siliconcompiler-0.36.0.dist-info}/top_level.txt +0 -0
|
@@ -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)
|
|
@@ -193,6 +193,7 @@ def main():
|
|
|
193
193
|
# SC_ROOT provided by CLI, and is only accessible when this is main module
|
|
194
194
|
sys.path.append(SC_KLAYOUT_ROOT) # noqa: F821
|
|
195
195
|
sys.path.append(SC_TOOLS_ROOT) # noqa: F821
|
|
196
|
+
sys.path.append(SC_ROOT) # noqa: F821
|
|
196
197
|
|
|
197
198
|
from klayout_utils import (
|
|
198
199
|
technology,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import pya
|
|
2
2
|
import json
|
|
3
3
|
import shutil
|
|
4
|
-
import sys
|
|
5
4
|
import os.path
|
|
6
5
|
|
|
7
6
|
|
|
@@ -77,7 +76,7 @@ def technology(design, schema):
|
|
|
77
76
|
|
|
78
77
|
layout_options = tech.load_layout_options
|
|
79
78
|
|
|
80
|
-
layout_options.lefdef_config.macro_resolution_mode =
|
|
79
|
+
layout_options.lefdef_config.macro_resolution_mode = 0
|
|
81
80
|
layout_options.lefdef_config.via_cellname_prefix = "VIA_"
|
|
82
81
|
pathed_files = set()
|
|
83
82
|
for lef_file in layout_options.lefdef_config.lef_files:
|
|
@@ -99,6 +98,18 @@ def technology(design, schema):
|
|
|
99
98
|
for lef_file in layout_options.lefdef_config.lef_files:
|
|
100
99
|
print(f"[INFO] LEF file: {lef_file}")
|
|
101
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
|
+
|
|
102
113
|
# Set layer properties
|
|
103
114
|
layer_properties = tech.layer_properties_file
|
|
104
115
|
if layer_properties:
|
|
@@ -129,8 +140,9 @@ def technology(design, schema):
|
|
|
129
140
|
map_file = os.path.abspath(os.path.join(os.path.dirname(tech_file),
|
|
130
141
|
map_file))
|
|
131
142
|
for s in get_streams(schema):
|
|
132
|
-
if schema.valid('library', sc_pdk, 'layermapfileset', 'klayout', 'def', s):
|
|
133
|
-
for fileset in schema.get('library', sc_pdk, '
|
|
143
|
+
if schema.valid('library', sc_pdk, 'pdk', 'layermapfileset', 'klayout', 'def', s):
|
|
144
|
+
for fileset in schema.get('library', sc_pdk, 'pdk', 'layermapfileset', 'klayout',
|
|
145
|
+
'def', s):
|
|
134
146
|
if schema.valid('library', sc_pdk, "fileset", fileset, "file", "layermap"):
|
|
135
147
|
map_file = schema.get('library', sc_pdk, "fileset", fileset, "file", "layermap")
|
|
136
148
|
if map_file:
|
|
@@ -170,7 +182,6 @@ def get_write_options(filename, timestamps):
|
|
|
170
182
|
|
|
171
183
|
|
|
172
184
|
def get_schema(manifest):
|
|
173
|
-
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
|
174
185
|
from schema.safeschema import SafeSchema
|
|
175
186
|
return SafeSchema.from_manifest(filepath=manifest)
|
|
176
187
|
|
|
@@ -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
|
|
|
@@ -10,7 +10,7 @@ Sources: https://github.com/The-OpenROAD-Project/OpenROAD
|
|
|
10
10
|
|
|
11
11
|
Installation: https://github.com/The-OpenROAD-Project/OpenROAD
|
|
12
12
|
'''
|
|
13
|
-
from typing import List, Union
|
|
13
|
+
from typing import List, Union, Optional
|
|
14
14
|
|
|
15
15
|
from siliconcompiler import StdCellLibrary
|
|
16
16
|
from siliconcompiler import PDK
|
|
@@ -346,12 +346,38 @@ class OpenROADStdCellLibrary(StdCellLibrary):
|
|
|
346
346
|
|
|
347
347
|
|
|
348
348
|
class OpenROADTask(ASICTask):
|
|
349
|
+
"""
|
|
350
|
+
Base class for tasks involving the OpenROAD EDA tool chain.
|
|
351
|
+
|
|
352
|
+
This class provides common functionality for configuring OpenROAD execution,
|
|
353
|
+
such as setting up debug levels for internal tools.
|
|
354
|
+
"""
|
|
349
355
|
def __init__(self):
|
|
350
356
|
super().__init__()
|
|
351
357
|
|
|
352
358
|
self.add_parameter("debug_level", "{(str,str,int)}",
|
|
353
359
|
'list of "tool key level" to enable debugging of OpenROAD')
|
|
354
360
|
|
|
361
|
+
def add_openroad_debuglevel(self, tool: str, category: str, level: int,
|
|
362
|
+
step: Optional[str] = None, index: Optional[str] = None,
|
|
363
|
+
clobber: bool = False) -> None:
|
|
364
|
+
"""
|
|
365
|
+
Configures the debug logging level for a specific OpenROAD tool and category.
|
|
366
|
+
|
|
367
|
+
Args:
|
|
368
|
+
tool: The name of the OpenROAD tool (e.g., "GRT", "PSM").
|
|
369
|
+
category: The specific debug category or keyword within the tool.
|
|
370
|
+
level: The integer verbosity level for the debug output.
|
|
371
|
+
step: The specific step to apply this configuration to.
|
|
372
|
+
index: The specific index to apply this configuration to.
|
|
373
|
+
clobber: If True, overwrites the existing debug level configuration.
|
|
374
|
+
If False, appends this configuration to the existing list.
|
|
375
|
+
"""
|
|
376
|
+
if clobber:
|
|
377
|
+
self.set("var", "debug_level", (tool, category, level), step=step, index=index)
|
|
378
|
+
else:
|
|
379
|
+
self.add("var", "debug_level", (tool, category, level), step=step, index=index)
|
|
380
|
+
|
|
355
381
|
def tool(self):
|
|
356
382
|
return "openroad"
|
|
357
383
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import json
|
|
3
3
|
|
|
4
|
-
from typing import List
|
|
4
|
+
from typing import List, Union, Optional
|
|
5
5
|
|
|
6
6
|
from siliconcompiler import sc_open
|
|
7
7
|
from siliconcompiler import utils
|
|
@@ -374,9 +374,12 @@ class OpenROADDRTParameter(_OpenROADDRTCommonParameter):
|
|
|
374
374
|
self.add_parameter("drt_disable_via_gen", "bool",
|
|
375
375
|
"true/false, when true turns off via generation in detailed router "
|
|
376
376
|
"and only uses the specified tech vias", defvalue=False)
|
|
377
|
-
self.add_parameter("drt_via_in_pin_bottom_layer", "str",
|
|
378
|
-
|
|
379
|
-
self.add_parameter("
|
|
377
|
+
self.add_parameter("drt_via_in_pin_bottom_layer", "str",
|
|
378
|
+
"bottom layer to allow vias inside pins")
|
|
379
|
+
self.add_parameter("drt_via_in_pin_top_layer", "str",
|
|
380
|
+
"top layer to allow vias inside pins")
|
|
381
|
+
self.add_parameter("drt_repair_pdn_vias", "str",
|
|
382
|
+
"layer to repair PDN vias on")
|
|
380
383
|
|
|
381
384
|
self.add_parameter("drt_report_interval", "int",
|
|
382
385
|
"reporting interval in steps for generating a DRC report.", defvalue=5)
|
|
@@ -411,6 +414,14 @@ class OpenROADDRTParameter(_OpenROADDRTCommonParameter):
|
|
|
411
414
|
|
|
412
415
|
|
|
413
416
|
class APRTask(OpenROADTask):
|
|
417
|
+
"""
|
|
418
|
+
Base class for OpenROAD-based Automatic Place and Route (APR) tasks.
|
|
419
|
+
|
|
420
|
+
This task initializes specific configurations for OpenROAD, including
|
|
421
|
+
report filtering, image generation settings, heatmap binning, and
|
|
422
|
+
power analysis corners.
|
|
423
|
+
"""
|
|
424
|
+
|
|
414
425
|
def __init__(self):
|
|
415
426
|
super().__init__()
|
|
416
427
|
|
|
@@ -423,6 +434,7 @@ class APRTask(OpenROADTask):
|
|
|
423
434
|
"fmax",
|
|
424
435
|
"power",
|
|
425
436
|
"check_setup",
|
|
437
|
+
"report_buffers",
|
|
426
438
|
"placement_density",
|
|
427
439
|
"routing_congestion",
|
|
428
440
|
"power_density",
|
|
@@ -456,11 +468,79 @@ class APRTask(OpenROADTask):
|
|
|
456
468
|
self.add_parameter("global_connect_fileset", "[(str,str)]",
|
|
457
469
|
"list of libraries and filesets to generate connects from")
|
|
458
470
|
|
|
459
|
-
def
|
|
471
|
+
def add_openroad_skipreport(self, report_type: Union[List[str], str],
|
|
472
|
+
step: Optional[str] = None, index: Optional[str] = None,
|
|
473
|
+
clobber: bool = False) -> None:
|
|
474
|
+
"""
|
|
475
|
+
Adds or sets report types to be skipped during OpenROAD execution.
|
|
476
|
+
|
|
477
|
+
Args:
|
|
478
|
+
report_type: The name of the report(s) to skip (e.g., 'routing_congestion').
|
|
479
|
+
step: The specific step to apply this configuration to.
|
|
480
|
+
index: The specific index to apply this configuration to.
|
|
481
|
+
clobber: If True, overwrites the existing list of skipped reports.
|
|
482
|
+
If False, appends to the existing list.
|
|
483
|
+
"""
|
|
484
|
+
if clobber:
|
|
485
|
+
self.set("var", "skip_reports", report_type, step=step, index=index)
|
|
486
|
+
else:
|
|
487
|
+
self.add("var", "skip_reports", report_type, step=step, index=index)
|
|
488
|
+
|
|
489
|
+
def set_openroad_enableimages(self, enable: bool,
|
|
490
|
+
step: Optional[str] = None, index: Optional[str] = None) -> None:
|
|
491
|
+
"""
|
|
492
|
+
Enables or disables the generation of design images at the end of the task.
|
|
493
|
+
|
|
494
|
+
Args:
|
|
495
|
+
enable: True to generate images, False to disable.
|
|
496
|
+
step: The specific step to apply this configuration to.
|
|
497
|
+
index: The specific index to apply this configuration to.
|
|
498
|
+
"""
|
|
499
|
+
self.set("var", "ord_enable_images", enable, step=step, index=index)
|
|
500
|
+
|
|
501
|
+
def set_openroad_heatmapbins(self, x: int, y: int,
|
|
502
|
+
step: Optional[str] = None, index: Optional[str] = None) -> None:
|
|
503
|
+
"""
|
|
504
|
+
Configures the resolution of the heatmap images.
|
|
505
|
+
|
|
506
|
+
Args:
|
|
507
|
+
x: The number of bins in the X direction.
|
|
508
|
+
y: The number of bins in the Y direction.
|
|
509
|
+
step: The specific step to apply this configuration to.
|
|
510
|
+
index: The specific index to apply this configuration to.
|
|
511
|
+
"""
|
|
512
|
+
self.set("var", "ord_heatmap_bins", (x, y), step=step, index=index)
|
|
513
|
+
|
|
514
|
+
def set_openroad_powercorner(self, corner: str,
|
|
515
|
+
step: Optional[str] = None, index: Optional[str] = None) -> None:
|
|
516
|
+
"""
|
|
517
|
+
Sets the specific process corner used for power analysis.
|
|
518
|
+
|
|
519
|
+
Args:
|
|
520
|
+
corner: The name of the timing/power corner.
|
|
521
|
+
step: The specific step to apply this configuration to.
|
|
522
|
+
index: The specific index to apply this configuration to.
|
|
523
|
+
"""
|
|
524
|
+
self.set("var", "power_corner", corner, step=step, index=index)
|
|
525
|
+
|
|
526
|
+
def add_openroad_globalconnectfileset(self, library: str, fileset: str,
|
|
527
|
+
step: Optional[str] = None, index: Optional[str] = None,
|
|
528
|
+
clobber: bool = False):
|
|
529
|
+
"""
|
|
530
|
+
Adds a library and fileset pair to the global connect configuration.
|
|
531
|
+
|
|
532
|
+
Args:
|
|
533
|
+
library: The name of the library.
|
|
534
|
+
fileset: The name of the fileset.
|
|
535
|
+
step: The specific step to apply this configuration to.
|
|
536
|
+
index: The specific index to apply this configuration to.
|
|
537
|
+
clobber: If True, overwrites the existing global connect settings.
|
|
538
|
+
If False, appends to the existing settings.
|
|
539
|
+
"""
|
|
460
540
|
if clobber:
|
|
461
|
-
self.set("var", "global_connect_fileset", (library, fileset))
|
|
541
|
+
self.set("var", "global_connect_fileset", (library, fileset), step=step, index=index)
|
|
462
542
|
else:
|
|
463
|
-
self.add("var", "global_connect_fileset", (library, fileset))
|
|
543
|
+
self.add("var", "global_connect_fileset", (library, fileset), step=step, index=index)
|
|
464
544
|
|
|
465
545
|
def setup(self):
|
|
466
546
|
"""
|
|
@@ -558,13 +638,22 @@ class APRTask(OpenROADTask):
|
|
|
558
638
|
def _add_pnr_outputs(self):
|
|
559
639
|
self.add_output_file(ext="sdc")
|
|
560
640
|
self.add_output_file(ext="vg")
|
|
641
|
+
self.add_output_file(ext="lec.vg")
|
|
561
642
|
self.add_output_file(ext="def")
|
|
562
643
|
self.add_output_file(ext="odb")
|
|
563
644
|
|
|
645
|
+
for lib in self.project.get("asic", "asiclib"):
|
|
646
|
+
libobj = self.project.get("library", lib, field="schema")
|
|
647
|
+
for celltype in ["decap", "tie", "filler", "tap", "endcap", "antenna", "physicalonly"]:
|
|
648
|
+
if libobj.valid("asic", "cells", celltype) and \
|
|
649
|
+
libobj.get("asic", "cells", celltype):
|
|
650
|
+
self.add_required_key(libobj, "asic", "cells", celltype)
|
|
651
|
+
|
|
564
652
|
def _get_pex_mapping(self):
|
|
565
653
|
corners = {}
|
|
566
|
-
for constraint in self.project.getkeys('constraint', 'timing'):
|
|
567
|
-
pexcorner = self.project.get('constraint', 'timing',
|
|
654
|
+
for constraint in self.project.getkeys('constraint', 'timing', 'scenario'):
|
|
655
|
+
pexcorner = self.project.get('constraint', 'timing', 'scenario',
|
|
656
|
+
constraint, 'pexcorner',
|
|
568
657
|
step=self.step, index=self.index)
|
|
569
658
|
if pexcorner:
|
|
570
659
|
corners[constraint] = pexcorner
|
|
@@ -572,13 +661,17 @@ class APRTask(OpenROADTask):
|
|
|
572
661
|
return corners
|
|
573
662
|
|
|
574
663
|
def _get_constraint_by_check(self, check: str) -> str:
|
|
575
|
-
for constraint in self.project.getkeys('constraint', 'timing'):
|
|
576
|
-
if check in self.project.get('constraint', 'timing',
|
|
664
|
+
for constraint in self.project.getkeys('constraint', 'timing', 'scenario'):
|
|
665
|
+
if check in self.project.get('constraint', 'timing', 'scenario',
|
|
666
|
+
constraint, 'check',
|
|
577
667
|
step=self.step, index=self.index):
|
|
578
668
|
return constraint
|
|
579
669
|
|
|
580
670
|
# if not specified, just pick the first constraint available
|
|
581
|
-
|
|
671
|
+
scenarios = self.project.getkeys('constraint', 'timing', 'scenario')
|
|
672
|
+
if not scenarios:
|
|
673
|
+
raise ValueError("No timing scenarios defined in project constraints.")
|
|
674
|
+
return scenarios[0]
|
|
582
675
|
|
|
583
676
|
def _build_pex_estimation_file(self):
|
|
584
677
|
corners = self._get_pex_mapping()
|
|
@@ -684,9 +777,9 @@ class APRTask(OpenROADTask):
|
|
|
684
777
|
],
|
|
685
778
|
"peakpower": [
|
|
686
779
|
*[f"power/{corner}.rpt"
|
|
687
|
-
for corner in self.project.getkeys('constraint', 'timing')],
|
|
780
|
+
for corner in self.project.getkeys('constraint', 'timing', 'scenario')],
|
|
688
781
|
*[f"images/heatmap/power_density/{corner}.png"
|
|
689
|
-
for corner in self.project.getkeys('constraint', 'timing')]
|
|
782
|
+
for corner in self.project.getkeys('constraint', 'timing', 'scenario')]
|
|
690
783
|
],
|
|
691
784
|
"drvs": [
|
|
692
785
|
"timing/drv_violators.rpt",
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Union, List, Optional
|
|
2
|
+
|
|
1
3
|
from siliconcompiler.tools.openroad._apr import APRTask
|
|
2
4
|
from siliconcompiler.tools.openroad._apr import OpenROADSTAParameter, OpenROADPPLParameter
|
|
3
5
|
|
|
@@ -5,9 +7,13 @@ from siliconcompiler.tools.openroad._apr import OpenROADSTAParameter, OpenROADPP
|
|
|
5
7
|
class InitFloorplanTask(APRTask,
|
|
6
8
|
OpenROADSTAParameter,
|
|
7
9
|
OpenROADPPLParameter):
|
|
8
|
-
|
|
9
|
-
Perform floorplanning and initial pin placements
|
|
10
|
-
|
|
10
|
+
"""
|
|
11
|
+
Perform floorplanning and initial pin placements.
|
|
12
|
+
|
|
13
|
+
This task handles the initialization of the floorplan, including macro placement
|
|
14
|
+
snapping strategies, cleaning up synthesis artifacts (buffers/dead logic),
|
|
15
|
+
and defining padring or bumpmap configurations.
|
|
16
|
+
"""
|
|
11
17
|
def __init__(self):
|
|
12
18
|
super().__init__()
|
|
13
19
|
|
|
@@ -19,6 +25,79 @@ class InitFloorplanTask(APRTask,
|
|
|
19
25
|
"remove logic which does not drive a primary output", defvalue=True)
|
|
20
26
|
|
|
21
27
|
self.add_parameter("padringfileset", "[str]", "filesets to generate a padring")
|
|
28
|
+
self.add_parameter("bumpmapfileset", "[str]", "filesets to generate a bumpmap")
|
|
29
|
+
|
|
30
|
+
def set_openroad_snapstrategy(self, snap: str,
|
|
31
|
+
step: Optional[str] = None, index: Optional[str] = None):
|
|
32
|
+
"""
|
|
33
|
+
Sets the snapping strategy for macro placement.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
snap: The snapping mode. Options are typically 'none', 'site', or 'grid'.
|
|
37
|
+
step: The specific step to apply this configuration to.
|
|
38
|
+
index: The specific index to apply this configuration to.
|
|
39
|
+
"""
|
|
40
|
+
self.set("var", "ifp_snap_strategy", snap, step=step, index=index)
|
|
41
|
+
|
|
42
|
+
def set_openroad_removebuffers(self, enable: bool,
|
|
43
|
+
step: Optional[str] = None, index: Optional[str] = None):
|
|
44
|
+
"""
|
|
45
|
+
Enables or disables the removal of buffers inserted during synthesis.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
enable: True to remove synthesis buffers, False to keep them.
|
|
49
|
+
step: The specific step to apply this configuration to.
|
|
50
|
+
index: The specific index to apply this configuration to.
|
|
51
|
+
"""
|
|
52
|
+
self.set("var", "remove_synth_buffers", enable, step=step, index=index)
|
|
53
|
+
|
|
54
|
+
def set_openroad_removedeadlogic(self, enable: bool,
|
|
55
|
+
step: Optional[str] = None, index: Optional[str] = None):
|
|
56
|
+
"""
|
|
57
|
+
Enables or disables the removal of logic that does not drive a primary output.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
enable: True to remove dead logic, False to keep it.
|
|
61
|
+
step: The specific step to apply this configuration to.
|
|
62
|
+
index: The specific index to apply this configuration to.
|
|
63
|
+
"""
|
|
64
|
+
self.set("var", "remove_dead_logic", enable, step=step, index=index)
|
|
65
|
+
|
|
66
|
+
def add_openroad_padringfileset(self, fileset: Union[str, List[str]],
|
|
67
|
+
step: Optional[str] = None, index: Optional[str] = None,
|
|
68
|
+
clobber: bool = False):
|
|
69
|
+
"""
|
|
70
|
+
Adds fileset(s) used to generate the I/O pad ring.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
fileset: A string name or list of names representing the padring filesets.
|
|
74
|
+
step: The specific step to apply this configuration to.
|
|
75
|
+
index: The specific index to apply this configuration to.
|
|
76
|
+
clobber: If True, overwrites the existing padring fileset list.
|
|
77
|
+
If False, appends to the existing list.
|
|
78
|
+
"""
|
|
79
|
+
if clobber:
|
|
80
|
+
self.set("var", "padringfileset", fileset, step=step, index=index)
|
|
81
|
+
else:
|
|
82
|
+
self.add("var", "padringfileset", fileset, step=step, index=index)
|
|
83
|
+
|
|
84
|
+
def add_openroad_bumpmapfileset(self, fileset: Union[str, List[str]],
|
|
85
|
+
step: Optional[str] = None, index: Optional[str] = None,
|
|
86
|
+
clobber: bool = False):
|
|
87
|
+
"""
|
|
88
|
+
Adds fileset(s) used to generate the bump map for flip-chip or 3D designs.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
fileset: A string name or list of names representing the bumpmap filesets.
|
|
92
|
+
step: The specific step to apply this configuration to.
|
|
93
|
+
index: The specific index to apply this configuration to.
|
|
94
|
+
clobber: If True, overwrites the existing bumpmap fileset list.
|
|
95
|
+
If False, appends to the existing list.
|
|
96
|
+
"""
|
|
97
|
+
if clobber:
|
|
98
|
+
self.set("var", "bumpmapfileset", fileset, step=step, index=index)
|
|
99
|
+
else:
|
|
100
|
+
self.add("var", "bumpmapfileset", fileset, step=step, index=index)
|
|
22
101
|
|
|
23
102
|
def task(self):
|
|
24
103
|
return "init_floorplan"
|
|
@@ -62,8 +141,41 @@ class InitFloorplanTask(APRTask,
|
|
|
62
141
|
for fileset in self.get("var", "padringfileset"):
|
|
63
142
|
self.add_required_key(self.project.design, "fileset", fileset, "file", "tcl")
|
|
64
143
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
144
|
+
if self.get("var", "bumpmapfileset"):
|
|
145
|
+
self.add_required_key("var", "bumpmapfileset")
|
|
146
|
+
|
|
147
|
+
for fileset in self.get("var", "bumpmapfileset"):
|
|
148
|
+
self.add_required_key(self.project.design, "fileset", fileset, "file", "bmap")
|
|
149
|
+
|
|
150
|
+
# Mark requires for components, pin, and floorplan placements
|
|
151
|
+
for component in self.project.constraint.component.get_component().values():
|
|
152
|
+
if component.get_placement(step=self.step, index=self.index) is not None:
|
|
153
|
+
self.add_required_key(component, "placement")
|
|
154
|
+
self.add_required_key(component, "rotation")
|
|
155
|
+
if component.get_halo(step=self.step, index=self.index) is not None:
|
|
156
|
+
self.add_required_key(component, "halo")
|
|
157
|
+
if component.get_partname(step=self.step, index=self.index):
|
|
158
|
+
self.add_required_key(component, "partname")
|
|
159
|
+
|
|
160
|
+
for pin in self.project.constraint.pin.get_pinconstraint().values():
|
|
161
|
+
if pin.get_placement(step=self.step, index=self.index) is not None:
|
|
162
|
+
self.add_required_key(pin, "placement")
|
|
163
|
+
if pin.get_layer(step=self.step, index=self.index) is not None:
|
|
164
|
+
self.add_required_key(pin, "layer")
|
|
165
|
+
if pin.get_side(step=self.step, index=self.index) is not None:
|
|
166
|
+
self.add_required_key(pin, "side")
|
|
167
|
+
if pin.get_order(step=self.step, index=self.index) is not None:
|
|
168
|
+
self.add_required_key(pin, "order")
|
|
169
|
+
|
|
170
|
+
self.add_required_key(self.mainlib, "asic", "site")
|
|
171
|
+
if self.project.constraint.area.get_diearea(step=self.step, index=self.index) and \
|
|
172
|
+
self.project.constraint.area.get_corearea(step=self.step, index=self.index):
|
|
173
|
+
self.add_required_key(self.project.constraint.area, "diearea")
|
|
174
|
+
self.add_required_key(self.project.constraint.area, "corearea")
|
|
68
175
|
else:
|
|
69
|
-
self.
|
|
176
|
+
self.add_required_key(self.project.constraint.area, "aspectratio")
|
|
177
|
+
self.add_required_key(self.project.constraint.area, "density")
|
|
178
|
+
self.add_required_key(self.project.constraint.area, "coremargin")
|
|
179
|
+
|
|
180
|
+
if self.mainlib.get("tool", "openroad", "tracks"):
|
|
181
|
+
self.add_required_key(self.mainlib, "tool", "openroad", "tracks")
|