siliconcompiler 0.34.1__py3-none-any.whl → 0.34.2__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 (46) hide show
  1. siliconcompiler/__init__.py +14 -2
  2. siliconcompiler/_metadata.py +1 -1
  3. siliconcompiler/apps/sc_show.py +1 -1
  4. siliconcompiler/constraints/__init__.py +17 -0
  5. siliconcompiler/constraints/asic_component.py +378 -0
  6. siliconcompiler/constraints/asic_floorplan.py +449 -0
  7. siliconcompiler/constraints/asic_pins.py +489 -0
  8. siliconcompiler/constraints/asic_timing.py +517 -0
  9. siliconcompiler/core.py +3 -3
  10. siliconcompiler/dependencyschema.py +10 -174
  11. siliconcompiler/design.py +235 -118
  12. siliconcompiler/flowgraph.py +27 -14
  13. siliconcompiler/library.py +133 -0
  14. siliconcompiler/metric.py +94 -72
  15. siliconcompiler/metrics/__init__.py +7 -0
  16. siliconcompiler/metrics/asic.py +245 -0
  17. siliconcompiler/metrics/fpga.py +220 -0
  18. siliconcompiler/package/__init__.py +138 -35
  19. siliconcompiler/package/github.py +6 -10
  20. siliconcompiler/packageschema.py +256 -12
  21. siliconcompiler/pathschema.py +226 -0
  22. siliconcompiler/project.py +459 -0
  23. siliconcompiler/scheduler/docker.py +2 -3
  24. siliconcompiler/scheduler/run_node.py +2 -1
  25. siliconcompiler/scheduler/scheduler.py +4 -13
  26. siliconcompiler/scheduler/schedulernode.py +25 -17
  27. siliconcompiler/scheduler/taskscheduler.py +2 -1
  28. siliconcompiler/schema/__init__.py +0 -2
  29. siliconcompiler/schema/baseschema.py +147 -24
  30. siliconcompiler/schema/editableschema.py +14 -6
  31. siliconcompiler/schema/journal.py +23 -15
  32. siliconcompiler/schema/namedschema.py +6 -4
  33. siliconcompiler/schema/parameter.py +34 -19
  34. siliconcompiler/schema/parametertype.py +2 -0
  35. siliconcompiler/schema/parametervalue.py +198 -15
  36. siliconcompiler/schema/schema_cfg.py +18 -14
  37. siliconcompiler/schema_obj.py +5 -3
  38. siliconcompiler/tool.py +199 -10
  39. siliconcompiler/toolscripts/_tools.json +4 -4
  40. {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/METADATA +3 -3
  41. {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/RECORD +45 -35
  42. siliconcompiler/schema/packageschema.py +0 -101
  43. {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/WHEEL +0 -0
  44. {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/entry_points.txt +0 -0
  45. {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/licenses/LICENSE +0 -0
  46. {siliconcompiler-0.34.1.dist-info → siliconcompiler-0.34.2.dist-info}/top_level.txt +0 -0
@@ -68,6 +68,11 @@ class FlowgraphSchema(NamedSchema):
68
68
  if index in (Schema.GLOBAL_KEY, 'default'):
69
69
  raise ValueError(f"{index} is a reserved name")
70
70
 
71
+ if '/' in step:
72
+ raise ValueError(f"{step} is not a valid step, it cannot contain '/'")
73
+ if '/' in index:
74
+ raise ValueError(f"{index} is not a valid index, it cannot contain '/'")
75
+
71
76
  # Determine task name and module
72
77
  task_module = None
73
78
  if isinstance(task, str):
@@ -83,11 +88,6 @@ class FlowgraphSchema(NamedSchema):
83
88
  raise ValueError(f"{task} is not a valid task, it must be associated with "
84
89
  "a tool '<tool>.<task>'.")
85
90
 
86
- if '/' in step:
87
- raise ValueError(f"{step} is not a valid step, it cannot contain '/'")
88
- if '/' in index:
89
- raise ValueError(f"{index} is not a valid index, it cannot contain '/'")
90
-
91
91
  tool_name, task_name = task_parts[-2:]
92
92
 
93
93
  # bind tool to node
@@ -504,6 +504,17 @@ class FlowgraphSchema(NamedSchema):
504
504
 
505
505
  return not error
506
506
 
507
+ def __get_task_module(self, name):
508
+ # Create cache
509
+ if self.__cache_tasks is None:
510
+ self.__cache_tasks = {}
511
+
512
+ if name in self.__cache_tasks:
513
+ return self.__cache_tasks[name]
514
+
515
+ self.__cache_tasks[name] = importlib.import_module(name)
516
+ return self.__cache_tasks[name]
517
+
507
518
  def get_task_module(self, step, index):
508
519
  """
509
520
  Returns the module for a given task
@@ -518,17 +529,19 @@ class FlowgraphSchema(NamedSchema):
518
529
  if (step, index) not in self.get_nodes():
519
530
  raise ValueError(f"{step}/{index} is not a valid node in {self.name()}.")
520
531
 
521
- taskmodule = self.get(step, index, 'taskmodule')
532
+ return self.__get_task_module(self.get(step, index, 'taskmodule'))
522
533
 
523
- # Create cache
524
- if self.__cache_tasks is None:
525
- self.__cache_tasks = {}
526
-
527
- if taskmodule in self.__cache_tasks:
528
- return self.__cache_tasks[taskmodule]
534
+ def get_all_tasks(self):
535
+ '''
536
+ Returns all the task modules used in this flow
529
537
 
530
- self.__cache_tasks[taskmodule] = importlib.import_module(taskmodule)
531
- return self.__cache_tasks[taskmodule]
538
+ Returns:
539
+ set of modules
540
+ '''
541
+ tasks = set()
542
+ for step, index in self.get_nodes():
543
+ tasks.add(self.get_task_module(step, index))
544
+ return tasks
532
545
 
533
546
 
534
547
  class RuntimeFlowgraph:
@@ -0,0 +1,133 @@
1
+ from typing import final, Union, List
2
+
3
+ from siliconcompiler.design import DesignSchema
4
+
5
+ from siliconcompiler.schema import EditableSchema, Parameter, Scope, PerNode
6
+ from siliconcompiler.schema.utils import trim
7
+
8
+
9
+ class LibrarySchema(DesignSchema):
10
+ def __init__(self, name: str = None):
11
+ super().__init__()
12
+ self.set_name(name)
13
+
14
+ @final
15
+ def define_tool_parameter(self, tool: str, name: str, type: str, help: str, **kwargs):
16
+ """
17
+ Define a new tool parameter for the library
18
+
19
+ Args:
20
+ tool (str): name of the tool
21
+ name (str): name of the parameter
22
+ type (str): type of parameter, see :class:`.Parameter`.
23
+ help (str): help information for this parameter
24
+ kwargs: passthrough for :class:`.Parameter`.
25
+ """
26
+ if isinstance(help, str):
27
+ # grab first line for short help
28
+ help = trim(help)
29
+ shorthelp = help.splitlines()[0].strip()
30
+ else:
31
+ raise TypeError("help must be a string")
32
+
33
+ kwargs["scope"] = Scope.GLOBAL
34
+ kwargs["pernode"] = PerNode.NEVER
35
+ kwargs["shorthelp"] = shorthelp
36
+ kwargs["help"] = help
37
+
38
+ EditableSchema(self).insert(
39
+ "tool", tool, name,
40
+ Parameter(type, **kwargs)
41
+ )
42
+
43
+
44
+ class StdCellLibrarySchema(LibrarySchema):
45
+ def __init__(self, name: str = None):
46
+ super().__init__()
47
+ self.set_name(name)
48
+
49
+ schema = EditableSchema(self)
50
+
51
+ schema.insert(
52
+ 'asic', 'cornerfilesets', 'default',
53
+ Parameter(
54
+ '[str]',
55
+ scope=Scope.GLOBAL,
56
+ shorthelp="ASIC: map of filesets to timing or pex corners",
57
+ example=["api: schema.set('asic', 'cornerfilesets', 'slow', 'timing.slow')"],
58
+ help=trim("""Map between filesets and timing or pex corners.""")))
59
+
60
+ # TODO: Expand on the exact definitions of these types of cells.
61
+ # minimize typing
62
+ for item in [
63
+ 'decap',
64
+ 'tie',
65
+ 'hold',
66
+ 'clkbuf',
67
+ 'clkgate',
68
+ 'clklogic',
69
+ 'dontuse',
70
+ 'filler',
71
+ 'tap',
72
+ 'endcap',
73
+ 'antenna']:
74
+ schema.insert(
75
+ 'asic', 'cells', item,
76
+ Parameter(
77
+ '[str]',
78
+ scope=Scope.GLOBAL,
79
+ shorthelp=f"ASIC: {item} cell list",
80
+ example=[f"api: schema.set('asic', 'cells', '{item}', '*eco*')"],
81
+ help=trim("""
82
+ List of cells grouped by a property that can be accessed
83
+ directly by the designer and tools. The example below shows how
84
+ all cells containing the string 'eco' could be marked as dont use
85
+ for the tool.""")))
86
+
87
+ schema.insert(
88
+ 'asic', 'site',
89
+ Parameter(
90
+ '[str]',
91
+ scope=Scope.GLOBAL,
92
+ shorthelp="ASIC: library sites",
93
+ example=["api: schema.set('asic', 'site', 'Site_12T')"],
94
+ help="Site names for a given library architecture."))
95
+
96
+ def add_asic_corner_fileset(self, corner: str, fileset: str = None):
97
+ """
98
+ Adds a mapping between filesets a corners defined in the library
99
+
100
+ Args:
101
+ corner (str): name of the timing or parasitic corner
102
+ fileset (str): name of the fileset
103
+ """
104
+ if not fileset:
105
+ fileset = self._get_active("fileset")
106
+
107
+ if not isinstance(fileset, str):
108
+ raise TypeError("fileset must be a string")
109
+
110
+ if fileset not in self.getkeys("fileset"):
111
+ raise ValueError(f"{fileset} is not defined")
112
+
113
+ return self.add("asic", "cornerfilesets", corner, fileset)
114
+
115
+ def add_asic_cell_list(self, type: str, cells: Union[List[str], str]):
116
+ """
117
+ Adds a standard cell library to the specified type.
118
+
119
+ Args:
120
+ type (str): category of cell type
121
+ cells (list of str): cells to add
122
+ """
123
+ return self.add("asic", "cells", type, cells)
124
+
125
+ def add_asic_site(self, site: Union[List[str], str]):
126
+ """
127
+ Adds a standard site to the library
128
+
129
+ Args:
130
+ type (str): category of cell type
131
+ cells (list of str): cells to add
132
+ """
133
+ return self.add("asic", "site", site)
siliconcompiler/metric.py CHANGED
@@ -10,7 +10,91 @@ class MetricSchema(BaseSchema):
10
10
  def __init__(self):
11
11
  super().__init__()
12
12
 
13
- schema_metric(self)
13
+ schema = EditableSchema(self)
14
+
15
+ for item, description in [
16
+ ('errors', 'errors'),
17
+ ('warnings', 'warnings')]:
18
+ schema.insert(
19
+ item,
20
+ Parameter(
21
+ 'int',
22
+ scope=Scope.JOB,
23
+ shorthelp=f"Metric: total {item}",
24
+ switch=f"-metric_{item} 'step index <int>'",
25
+ example=[
26
+ f"cli: -metric_{item} 'dfm 0 0'",
27
+ f"api: chip.set('metric', '{item}', 0, step='dfm', index=0)"],
28
+ pernode=PerNode.REQUIRED,
29
+ help=trim(f"""Metric tracking the total number of {description} on a
30
+ per step and index basis.""")))
31
+
32
+ schema.insert(
33
+ 'memory',
34
+ Parameter(
35
+ 'float',
36
+ unit='B',
37
+ scope=Scope.JOB,
38
+ shorthelp="Metric: memory",
39
+ switch="-metric_memory 'step index <float>'",
40
+ example=[
41
+ "cli: -metric_memory 'dfm 0 10e9'",
42
+ "api: chip.set('metric', 'memory', 10e9, step='dfm', index=0)"],
43
+ pernode=PerNode.REQUIRED,
44
+ help=trim("""
45
+ Metric tracking total peak program memory footprint on a per
46
+ step and index basis.""")))
47
+
48
+ schema.insert(
49
+ 'exetime',
50
+ Parameter(
51
+ 'float',
52
+ unit='s',
53
+ scope=Scope.JOB,
54
+ shorthelp="Metric: exetime",
55
+ switch="-metric_exetime 'step index <float>'",
56
+ example=[
57
+ "cli: -metric_exetime 'dfm 0 10.0'",
58
+ "api: chip.set('metric', 'exetime', 10.0, step='dfm', index=0)"],
59
+ pernode=PerNode.REQUIRED,
60
+ help=trim("""
61
+ Metric tracking time spent by the EDA executable :keypath:`tool,<tool>,exe` on a
62
+ per step and index basis. It does not include the SiliconCompiler
63
+ runtime overhead or time waiting for I/O operations and
64
+ inter-processor communication to complete.""")))
65
+
66
+ schema.insert(
67
+ 'tasktime',
68
+ Parameter(
69
+ 'float',
70
+ unit='s',
71
+ scope=Scope.JOB,
72
+ shorthelp="Metric: tasktime",
73
+ switch="-metric_tasktime 'step index <float>'",
74
+ example=[
75
+ "cli: -metric_tasktime 'dfm 0 10.0'",
76
+ "api: chip.set('metric', 'tasktime', 10.0, step='dfm', index=0)"],
77
+ pernode=PerNode.REQUIRED,
78
+ help=trim("""
79
+ Metric tracking the total amount of time spent on a task from
80
+ beginning to end, including data transfers and pre/post
81
+ processing.""")))
82
+
83
+ schema.insert(
84
+ 'totaltime',
85
+ Parameter(
86
+ 'float',
87
+ unit='s',
88
+ scope=Scope.JOB,
89
+ shorthelp="Metric: totaltime",
90
+ switch="-metric_totaltime 'step index <float>'",
91
+ example=[
92
+ "cli: -metric_totaltime 'dfm 0 10.0'",
93
+ "api: chip.set('metric', 'totaltime', 10.0, step='dfm', index=0)"],
94
+ pernode=PerNode.REQUIRED,
95
+ help=trim("""
96
+ Metric tracking the total amount of time spent from the beginning
97
+ of the run up to and including the current step and index.""")))
14
98
 
15
99
  def clear(self, step, index):
16
100
  '''
@@ -122,15 +206,20 @@ class MetricSchema(BaseSchema):
122
206
  return self.record(step, index, "totaltime", total_time, unit="s")
123
207
 
124
208
 
209
+ class MetricSchemaTmp(MetricSchema):
210
+ def __init__(self):
211
+ super().__init__()
212
+
213
+ schema_metric_tmp(self)
214
+
215
+
125
216
  ###########################################################################
126
217
  # Metrics to Track
127
218
  ###########################################################################
128
- def schema_metric(schema):
219
+ def schema_metric_tmp(schema):
129
220
  schema = EditableSchema(schema)
130
221
 
131
- metrics = {'errors': 'errors',
132
- 'warnings': 'warnings',
133
- 'drvs': 'design rule violations',
222
+ metrics = {'drvs': 'design rule violations',
134
223
  'drcs': 'physical design rule violations',
135
224
  'unconstrained': 'unconstrained timing paths'}
136
225
 
@@ -429,70 +518,3 @@ def schema_metric(schema):
429
518
  congested design. To analyze where the congestion is occurring
430
519
  inspect the router log files for detailed per metal overflow
431
520
  reporting and open up the design to find routing hotspots.""")))
432
-
433
- schema.insert(
434
- 'memory',
435
- Parameter(
436
- 'float',
437
- unit='B',
438
- scope=Scope.JOB,
439
- shorthelp="Metric: memory",
440
- switch="-metric_memory 'step index <float>'",
441
- example=[
442
- "cli: -metric_memory 'dfm 0 10e9'",
443
- "api: chip.set('metric', 'memory', 10e9, step='dfm', index=0)"],
444
- pernode=PerNode.REQUIRED,
445
- help=trim("""
446
- Metric tracking total peak program memory footprint on a per
447
- step and index basis.""")))
448
-
449
- schema.insert(
450
- 'exetime',
451
- Parameter(
452
- 'float',
453
- unit='s',
454
- scope=Scope.JOB,
455
- shorthelp="Metric: exetime",
456
- switch="-metric_exetime 'step index <float>'",
457
- example=[
458
- "cli: -metric_exetime 'dfm 0 10.0'",
459
- "api: chip.set('metric', 'exetime', 10.0, step='dfm', index=0)"],
460
- pernode=PerNode.REQUIRED,
461
- help=trim("""
462
- Metric tracking time spent by the EDA executable :keypath:`tool,<tool>,exe` on a
463
- per step and index basis. It does not include the SiliconCompiler
464
- runtime overhead or time waiting for I/O operations and
465
- inter-processor communication to complete.""")))
466
-
467
- schema.insert(
468
- 'tasktime',
469
- Parameter(
470
- 'float',
471
- unit='s',
472
- scope=Scope.JOB,
473
- shorthelp="Metric: tasktime",
474
- switch="-metric_tasktime 'step index <float>'",
475
- example=[
476
- "cli: -metric_tasktime 'dfm 0 10.0'",
477
- "api: chip.set('metric', 'tasktime', 10.0, step='dfm', index=0)"],
478
- pernode=PerNode.REQUIRED,
479
- help=trim("""
480
- Metric tracking the total amount of time spent on a task from
481
- beginning to end, including data transfers and pre/post
482
- processing.""")))
483
-
484
- schema.insert(
485
- 'totaltime',
486
- Parameter(
487
- 'float',
488
- unit='s',
489
- scope=Scope.JOB,
490
- shorthelp="Metric: totaltime",
491
- switch="-metric_totaltime 'step index <float>'",
492
- example=[
493
- "cli: -metric_totaltime 'dfm 0 10.0'",
494
- "api: chip.set('metric', 'totaltime', 10.0, step='dfm', index=0)"],
495
- pernode=PerNode.REQUIRED,
496
- help=trim("""
497
- Metric tracking the total amount of time spent from the beginning
498
- of the run up to and including the current step and index.""")))
@@ -0,0 +1,7 @@
1
+ from siliconcompiler.metrics.asic import ASICMetricsSchema
2
+ from siliconcompiler.metrics.fpga import FPGAMetricsSchema
3
+
4
+ __all__ = [
5
+ "ASICMetricsSchema",
6
+ "FPGAMetricsSchema"
7
+ ]
@@ -0,0 +1,245 @@
1
+ from siliconcompiler import MetricSchema
2
+
3
+ from siliconcompiler.schema import EditableSchema, Parameter, Scope, PerNode
4
+ from siliconcompiler.schema.utils import trim
5
+
6
+
7
+ class ASICMetricsSchema(MetricSchema):
8
+ def __init__(self):
9
+ super().__init__()
10
+
11
+ schema = EditableSchema(self)
12
+
13
+ for item, description in [
14
+ ('drvs', 'design rule violations'),
15
+ ('drcs', 'physical design rule violations'),
16
+ ('unconstrained', 'unconstrained timing paths')]:
17
+ schema.insert(
18
+ item,
19
+ Parameter(
20
+ 'int',
21
+ scope=Scope.JOB,
22
+ shorthelp=f"Metric: total {item}",
23
+ switch=f"-metric_{item} 'step index <int>'",
24
+ example=[
25
+ f"cli: -metric_{item} 'dfm 0 0'",
26
+ f"api: chip.set('metric', '{item}', 0, step='dfm', index=0)"],
27
+ pernode=PerNode.REQUIRED,
28
+ help=trim(f"""Metric tracking the total number of {description} on a
29
+ per step and index basis.""")))
30
+
31
+ for item, description in [
32
+ ('cellarea', 'cell area (ignoring fillers)'),
33
+ ('totalarea', 'physical die area'),
34
+ ('macroarea', 'macro cell area'),
35
+ ('padcellarea', 'io pad cell area'),
36
+ ('stdcellarea', 'standard cell area')]:
37
+ schema.insert(
38
+ item,
39
+ Parameter(
40
+ 'float',
41
+ unit='um^2',
42
+ scope=Scope.JOB,
43
+ shorthelp=f"Metric: {item}",
44
+ switch=f"-metric_{item} 'step index <float>'",
45
+ example=[
46
+ f"cli: -metric_{item} 'place 0 100.00'",
47
+ f"api: chip.set('metric', '{item}', 100.00, step='place', index=0)"],
48
+ pernode=PerNode.REQUIRED,
49
+ help=trim(f"""
50
+ Metric tracking the total {description} occupied by the design.""")))
51
+
52
+ schema.insert(
53
+ 'utilization',
54
+ Parameter(
55
+ 'float',
56
+ unit='%',
57
+ scope=Scope.JOB,
58
+ shorthelp="Metric: area utilization",
59
+ switch="-metric_utilization 'step index <float>'",
60
+ example=[
61
+ "cli: -metric_utilization 'place 0 50.00'",
62
+ "api: chip.set('metric', 'utilization', 50.00, step='place', index=0)"],
63
+ pernode=PerNode.REQUIRED,
64
+ help=trim("""
65
+ Metric tracking the area utilization of the design calculated as
66
+ 100 * (cellarea/totalarea).""")))
67
+
68
+ schema.insert(
69
+ 'logicdepth',
70
+ Parameter(
71
+ 'int',
72
+ scope=Scope.JOB,
73
+ shorthelp="Metric: logic depth",
74
+ switch="-metric_logicdepth 'step index <int>'",
75
+ example=[
76
+ "cli: -metric_logicdepth 'place 0 8'",
77
+ "api: chip.set('metric', 'logicdepth', 8, step='place', index=0)"],
78
+ pernode=PerNode.REQUIRED,
79
+ help=trim("""
80
+ Metric tracking the logic depth of the design. This is determined
81
+ by the number of logic gates between the start of the critital timing
82
+ path to the end of the path.""")))
83
+
84
+ for item, description in [
85
+ ('peakpower', 'worst case total peak power'),
86
+ ('averagepower', 'average workload power'),
87
+ ('leakagepower', 'leakage power with rails active but without any dynamic '
88
+ 'switching activity')]:
89
+ schema.insert(
90
+ item,
91
+ Parameter(
92
+ 'float',
93
+ unit='mw',
94
+ scope=Scope.JOB,
95
+ shorthelp=f"Metric: {item}",
96
+ switch=f"-metric_{item} 'step index <float>'",
97
+ example=[
98
+ f"cli: -metric_{item} 'place 0 0.01'",
99
+ f"api: chip.set('metric', '{item}', 0.01, step='place', index=0)"],
100
+ pernode=PerNode.REQUIRED,
101
+ help=trim(f"""
102
+ Metric tracking the {description} of the design specified on a per step
103
+ and index basis. Power metric depend heavily on the method
104
+ being used for extraction: dynamic vs static, workload
105
+ specification (vcd vs saif), power models, process/voltage/temperature.
106
+ The power {item} metric tries to capture the data that would
107
+ usually be reflected inside a datasheet given the appropriate
108
+ footnote conditions.""")))
109
+
110
+ schema.insert(
111
+ 'irdrop',
112
+ Parameter(
113
+ 'float',
114
+ unit='mv',
115
+ scope=Scope.JOB,
116
+ shorthelp="Metric: peak IR drop",
117
+ switch="-metric_irdrop 'step index <float>'",
118
+ example=[
119
+ "cli: -metric_irdrop 'place 0 0.05'",
120
+ "api: chip.set('metric', 'irdrop', 0.05, step='place', index=0)"],
121
+ pernode=PerNode.REQUIRED,
122
+ help=trim("""
123
+ Metric tracking the peak IR drop in the design based on extracted
124
+ power and ground rail parasitics, library power models, and
125
+ switching activity. The switching activity calculated on a per
126
+ node basis is taken from one of three possible sources, in order
127
+ of priority: VCD file, SAIF file, 'activityfactor' parameter.""")))
128
+
129
+ for item, description in [
130
+ ('holdpaths', 'hold'),
131
+ ('setuppaths', 'setup')]:
132
+ schema.insert(
133
+ item,
134
+ Parameter(
135
+ 'int',
136
+ scope=Scope.JOB,
137
+ shorthelp=f"Metric: {item}",
138
+ switch=f"-metric_{item} 'step index <int>'",
139
+ example=[
140
+ f"cli: -metric_{item} 'place 0 10'",
141
+ f"api: chip.set('metric', '{item}', 10, step='place', index=0)"],
142
+ pernode=PerNode.REQUIRED,
143
+ help=trim(f"""
144
+ Metric tracking the total number of timing paths violating {description}
145
+ constraints.""")))
146
+
147
+ for item, description in [
148
+ ('holdslack', 'worst hold slack (positive or negative)'),
149
+ ('holdwns', 'worst negative hold slack (positive values truncated to zero)'),
150
+ ('holdtns', 'total negative hold slack (TNS)'),
151
+ ('holdskew', 'hold clock skew'),
152
+ ('setupslack', 'worst setup slack (positive or negative)'),
153
+ ('setupwns', 'worst negative setup slack (positive values truncated to zero)'),
154
+ ('setuptns', 'total negative setup slack (TNS)'),
155
+ ('setupskew', 'setup clock skew')]:
156
+ schema.insert(
157
+ item,
158
+ Parameter(
159
+ 'float',
160
+ unit='ns',
161
+ scope=Scope.JOB,
162
+ shorthelp=f"Metric: {item}",
163
+ switch=f"-metric_{item} 'step index <float>'",
164
+ example=[
165
+ f"cli: -metric_{item} 'place 0 0.01'",
166
+ f"api: chip.set('metric', '{item}', 0.01, step='place', index=0)"],
167
+ pernode=PerNode.REQUIRED,
168
+ help=trim(f"""
169
+ Metric tracking the {description} on a per step and index basis.""")))
170
+
171
+ for item, description in [
172
+ ('fmax', 'maximum clock frequency')]:
173
+ schema.insert(
174
+ item,
175
+ Parameter(
176
+ 'float',
177
+ unit='Hz',
178
+ scope=Scope.JOB,
179
+ shorthelp=f"Metric: {item}",
180
+ switch=f"-metric_{item} 'step index <float>'",
181
+ example=[
182
+ f"cli: -metric_{item} 'place 0 100e6'",
183
+ f"api: chip.set('metric', '{item}', 100e6, step='place', index=0)"],
184
+ pernode=PerNode.REQUIRED,
185
+ help=trim(f"""
186
+ Metric tracking the {description} on a per step and index basis.""")))
187
+
188
+ for item, description in [
189
+ ('macros', 'macros'),
190
+ ('cells', 'cell instances'),
191
+ ('registers', 'register instances'),
192
+ ('buffers', 'buffer instances'),
193
+ ('inverters', 'inverter instances'),
194
+ ('transistors', 'transistors'),
195
+ ('pins', 'pins'),
196
+ ('nets', 'nets'),
197
+ ('vias', 'vias')]:
198
+ schema.insert(
199
+ item,
200
+ Parameter(
201
+ 'int',
202
+ scope=Scope.JOB,
203
+ shorthelp=f"Metric: {item}",
204
+ switch=f"-metric_{item} 'step index <int>'",
205
+ example=[
206
+ f"cli: -metric_{item} 'place 0 100'",
207
+ f"api: chip.set('metric', '{item}', 50, step='place', index=0)"],
208
+ pernode=PerNode.REQUIRED,
209
+ help=trim(f"""
210
+ Metric tracking the total number of {description} in the design
211
+ on a per step and index basis.""")))
212
+
213
+ schema.insert(
214
+ 'wirelength',
215
+ Parameter(
216
+ 'float',
217
+ unit='um',
218
+ scope=Scope.JOB,
219
+ shorthelp="Metric: wirelength",
220
+ switch="-metric_wirelength 'step index <float>'",
221
+ example=[
222
+ "cli: -metric_wirelength 'place 0 100.0'",
223
+ "api: chip.set('metric', 'wirelength', 50.0, step='place', index=0)"],
224
+ pernode=PerNode.REQUIRED,
225
+ help=trim("""
226
+ Metric tracking the total wirelength of the design on a per step
227
+ and index basis.""")))
228
+
229
+ schema.insert(
230
+ 'overflow',
231
+ Parameter(
232
+ 'int',
233
+ scope=Scope.JOB,
234
+ shorthelp="Metric: overflow",
235
+ switch="-metric_overflow 'step index <int>'",
236
+ example=[
237
+ "cli: -metric_overflow 'place 0 0'",
238
+ "api: chip.set('metric', 'overflow', 50, step='place', index=0)"],
239
+ pernode=PerNode.REQUIRED,
240
+ help=trim("""
241
+ Metric tracking the total number of overflow tracks for the routing
242
+ on per step and index basis. Any non-zero number suggests an over
243
+ congested design. To analyze where the congestion is occurring
244
+ inspect the router log files for detailed per metal overflow
245
+ reporting and open up the design to find routing hotspots.""")))