siliconcompiler 0.26.1__cp39-cp39-win_amd64.whl → 0.26.3__cp39-cp39-win_amd64.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 (36) hide show
  1. siliconcompiler/_metadata.py +1 -1
  2. siliconcompiler/apps/sc_issue.py +4 -11
  3. siliconcompiler/apps/smake.py +59 -19
  4. siliconcompiler/core.py +92 -32
  5. siliconcompiler/issue.py +3 -0
  6. siliconcompiler/report/report.py +1 -1
  7. siliconcompiler/scheduler/__init__.py +4 -1
  8. siliconcompiler/schema/schema_cfg.py +12 -3
  9. siliconcompiler/templates/tcl/manifest.tcl.j2 +52 -0
  10. siliconcompiler/tools/_common/__init__.py +10 -2
  11. siliconcompiler/tools/_common/asic.py +26 -6
  12. siliconcompiler/tools/klayout/export.py +3 -2
  13. siliconcompiler/tools/klayout/klayout_export.py +4 -4
  14. siliconcompiler/tools/klayout/klayout_utils.py +4 -4
  15. siliconcompiler/tools/magic/sc_drc.tcl +1 -1
  16. siliconcompiler/tools/magic/sc_extspice.tcl +3 -2
  17. siliconcompiler/tools/netgen/sc_lvs.tcl +1 -1
  18. siliconcompiler/tools/openroad/export.py +3 -3
  19. siliconcompiler/tools/openroad/openroad.py +5 -5
  20. siliconcompiler/tools/openroad/scripts/sc_apr.tcl +2 -2
  21. siliconcompiler/tools/openroad/scripts/sc_floorplan.tcl +4 -3
  22. siliconcompiler/tools/openroad/scripts/sc_procs.tcl +1 -1
  23. siliconcompiler/tools/opensta/__init__.py +3 -2
  24. siliconcompiler/tools/opensta/scripts/sc_report_libraries.tcl +2 -2
  25. siliconcompiler/tools/opensta/scripts/sc_timing.tcl +2 -2
  26. siliconcompiler/tools/surelog/bin/surelog.exe +0 -0
  27. siliconcompiler/tools/yosys/sc_lec.tcl +1 -1
  28. siliconcompiler/tools/yosys/syn_asic.py +13 -15
  29. siliconcompiler/tools/yosys/syn_asic.tcl +3 -3
  30. siliconcompiler/use.py +12 -0
  31. {siliconcompiler-0.26.1.dist-info → siliconcompiler-0.26.3.dist-info}/METADATA +38 -38
  32. {siliconcompiler-0.26.1.dist-info → siliconcompiler-0.26.3.dist-info}/RECORD +36 -36
  33. {siliconcompiler-0.26.1.dist-info → siliconcompiler-0.26.3.dist-info}/WHEEL +1 -1
  34. {siliconcompiler-0.26.1.dist-info → siliconcompiler-0.26.3.dist-info}/LICENSE +0 -0
  35. {siliconcompiler-0.26.1.dist-info → siliconcompiler-0.26.3.dist-info}/entry_points.txt +0 -0
  36. {siliconcompiler-0.26.1.dist-info → siliconcompiler-0.26.3.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  # Version number following semver standard.
2
- version = '0.26.1'
2
+ version = '0.26.3'
3
3
 
4
4
  # Default server address for remote runs, if unspecified.
5
5
  default_server = 'https://server.siliconcompiler.com'
@@ -25,13 +25,13 @@ Restricted SC app that generates a sharable testcase from a
25
25
  failed flow or runs an issue generated with this program.
26
26
 
27
27
  To generate a testcase, use:
28
- sc-issue -generate -cfg <stepdir>/outputs/<design>.pkg.json
28
+ sc-issue -cfg <stepdir>/outputs/<design>.pkg.json
29
29
 
30
30
  or include a different step/index than what the cfg_file is pointing to:
31
- sc-issue -generate -cfg <otherdir>/outputs/<design>.pkg.json -arg_step <step> -arg_index <index>
31
+ sc-issue -cfg <otherdir>/outputs/<design>.pkg.json -arg_step <step> -arg_index <index>
32
32
 
33
33
  or include specific libraries while excluding others:
34
- sc-issue -generate -cfg <stepdir>/outputs/<design>.pkg.json -exclude_libraries -add_library sram -add_library gpio
34
+ sc-issue -cfg <stepdir>/outputs/<design>.pkg.json -exclude_libraries -add_library sram -add_library gpio
35
35
 
36
36
  To run a testcase, use:
37
37
  sc-issue -run -file sc_issue_<...>.tar.gz
@@ -39,10 +39,6 @@ To run a testcase, use:
39
39
  """ # noqa E501
40
40
 
41
41
  issue_arguments = {
42
- '-generate': {'action': 'store_true',
43
- 'help': 'generate a testcase',
44
- 'sc_print': False},
45
-
46
42
  '-exclude_libraries': {'action': 'store_true',
47
43
  'help': 'flag to ensure libraries are excluded in the testcase',
48
44
  'sc_print': False},
@@ -88,10 +84,7 @@ To run a testcase, use:
88
84
  chip.logger.error(e)
89
85
  return 1
90
86
 
91
- if switches['generate'] and switches['run']:
92
- raise ValueError('Only one of -generate or -run can be used')
93
-
94
- if switches['generate']:
87
+ if not switches['run']:
95
88
  step = chip.get('arg', 'step')
96
89
  index = chip.get('arg', 'index')
97
90
 
@@ -41,7 +41,20 @@ def __process_file(path):
41
41
  arg_type = str
42
42
  if arg in func_spec.annotations:
43
43
  arg_type = func_spec.annotations[arg]
44
- func_args[arg] = arg_type
44
+ func_args[arg] = {
45
+ "type": arg_type
46
+ }
47
+
48
+ if func_spec.defaults:
49
+ for arg, defval in zip(reversed(func_spec.args), reversed(func_spec.defaults)):
50
+ func_args[arg]["default"] = defval
51
+
52
+ if defval is None:
53
+ continue
54
+
55
+ if type(defval) is not func_args[arg]["type"]:
56
+ if isinstance(defval, (bool, str, float, int)):
57
+ func_args[arg]["type"] = type(defval)
45
58
 
46
59
  args[name] = {
47
60
  "function": func,
@@ -62,7 +75,7 @@ def __process_file(path):
62
75
  return args, default_arg, module_help
63
76
 
64
77
 
65
- def main():
78
+ def main(source_file=None):
66
79
  progname = "smake"
67
80
  description = f"""-----------------------------------------------------------
68
81
  SC app that provides an Makefile like interface to python
@@ -90,16 +103,18 @@ To run a target with supported arguments, use:
90
103
  -----------------------------------------------------------"""
91
104
 
92
105
  # handle source file identification before arg parse
93
- source_file = __default_source_file
94
- file_args = ('--file', '-f')
95
- for file_arg in file_args:
96
- if file_arg in sys.argv:
97
- source_file_idx = sys.argv.index(file_arg) + 1
98
- if source_file_idx < len(sys.argv):
99
- source_file = sys.argv[source_file_idx]
100
- else:
101
- source_file = None
102
- break
106
+ file_args = None
107
+ if not source_file:
108
+ source_file = __default_source_file
109
+ file_args = ('--file', '-f')
110
+ for file_arg in file_args:
111
+ if file_arg in sys.argv:
112
+ source_file_idx = sys.argv.index(file_arg) + 1
113
+ if source_file_idx < len(sys.argv):
114
+ source_file = sys.argv[source_file_idx]
115
+ else:
116
+ source_file = None
117
+ break
103
118
 
104
119
  # handle directory identification before arg parse
105
120
  source_dir = os.getcwd()
@@ -135,10 +150,11 @@ To run a target with supported arguments, use:
135
150
  description=description,
136
151
  formatter_class=argparse.RawDescriptionHelpFormatter)
137
152
 
138
- parser.add_argument(
139
- *file_args,
140
- metavar='<file>',
141
- help=f'Use file as makefile, default is {__default_source_file}')
153
+ if file_args:
154
+ parser.add_argument(
155
+ *file_args,
156
+ metavar='<file>',
157
+ help=f'Use file as makefile, default is {__default_source_file}')
142
158
 
143
159
  parser.add_argument(
144
160
  *dir_args,
@@ -159,14 +175,38 @@ To run a target with supported arguments, use:
159
175
  subparse = targetparsers.add_parser(
160
176
  arg,
161
177
  description=info['full_help'],
162
- help=info['help'])
178
+ help=info['help'],
179
+ formatter_class=argparse.RawDescriptionHelpFormatter)
180
+
181
+ for subarg, subarg_info in info['args'].items():
182
+ # print(subarg, subarg_info)
183
+ add_args = {}
184
+
185
+ if "default" not in subarg_info:
186
+ add_args["required"] = True
187
+ else:
188
+ if type(subarg_info["default"]) is subarg_info["type"]:
189
+ add_args["default"] = subarg_info["default"]
190
+
191
+ if subarg_info["type"] is bool:
192
+ def str2bool(v):
193
+ # modified from:
194
+ # https://github.com/pypa/distutils/blob/8993718731b951ee36d08cb784f02aa13542ce15/distutils/util.py
195
+ val = v.lower()
196
+ if val in ('y', 'yes', 't', 'true', 'on', '1'):
197
+ return True
198
+ elif val in ('n', 'no', 'f', 'false', 'off', '0'):
199
+ return False
200
+ else:
201
+ raise ValueError(f"invalid truth value {val!r}")
202
+ subarg_info["type"] = str2bool
163
203
 
164
- for subarg, subarg_type in info['args'].items():
165
204
  subparse.add_argument(
166
205
  f'--{subarg}',
167
206
  dest=f'sub_{subarg}',
168
207
  metavar=f'<{subarg}>',
169
- type=subarg_type)
208
+ type=subarg_info["type"],
209
+ **add_args)
170
210
 
171
211
  args = parser.parse_args()
172
212
  target = args.target
siliconcompiler/core.py CHANGED
@@ -1001,8 +1001,8 @@ class Chip:
1001
1001
  package (str): Name of package where this file can be found
1002
1002
  '''
1003
1003
 
1004
- self.__add_input_output('input', filename, fileset, filetype, iomap,
1005
- step=step, index=index, package=package)
1004
+ self._add_input_output('input', filename, fileset, filetype, iomap,
1005
+ step=step, index=index, package=package)
1006
1006
  # Replace {iotable} in __doc__ with actual table for fileset/filetype and extension mapping
1007
1007
  input.__doc__ = input.__doc__.replace("{iotable}",
1008
1008
  utils.format_fileset_type_table())
@@ -1012,14 +1012,14 @@ class Chip:
1012
1012
  step=None, index=None, package=None):
1013
1013
  '''Same as input'''
1014
1014
 
1015
- self.__add_input_output('output', filename, fileset, filetype, iomap,
1016
- step=step, index=index, package=package)
1015
+ self._add_input_output('output', filename, fileset, filetype, iomap,
1016
+ step=step, index=index, package=package)
1017
1017
  # Copy input functions __doc__ and replace 'input' with 'output' to make constant
1018
1018
  output.__doc__ = input.__doc__.replace("input", "output")
1019
1019
 
1020
1020
  ###########################################################################
1021
- def __add_input_output(self, category, filename, fileset, filetype, iomap,
1022
- step=None, index=None, package=None):
1021
+ def _add_input_output(self, category, filename, fileset, filetype, iomap,
1022
+ step=None, index=None, package=None, quiet=False):
1023
1023
  '''
1024
1024
  Adds file to input or output groups.
1025
1025
  Performs a lookup in the io map for the fileset and filetype
@@ -1051,12 +1051,13 @@ class Chip:
1051
1051
  if not use_fileset or not use_filetype:
1052
1052
  self.logger.error(f'Unable to infer {category} fileset and/or filetype for '
1053
1053
  f'{filename} based on file extension.')
1054
- elif not fileset and not filetype:
1055
- self.logger.info(f'{filename} inferred as {use_fileset}/{use_filetype}')
1056
- elif not filetype:
1057
- self.logger.info(f'{filename} inferred as filetype {use_filetype}')
1058
- elif not fileset:
1059
- self.logger.info(f'{filename} inferred as fileset {use_fileset}')
1054
+ elif not quiet:
1055
+ if not fileset and not filetype:
1056
+ self.logger.info(f'{filename} inferred as {use_fileset}/{use_filetype}')
1057
+ elif not filetype:
1058
+ self.logger.info(f'{filename} inferred as filetype {use_filetype}')
1059
+ elif not fileset:
1060
+ self.logger.info(f'{filename} inferred as fileset {use_fileset}')
1060
1061
 
1061
1062
  self.add(category, use_fileset, use_filetype, filename,
1062
1063
  step=step, index=index, package=package)
@@ -1946,7 +1947,7 @@ class Chip:
1946
1947
 
1947
1948
  ###########################################################################
1948
1949
  def write_dependencygraph(self, filename, flow=None,
1949
- fillcolor='#ffffff', fontcolor='#000000',
1950
+ fontcolor='#000000', color_scheme=None,
1950
1951
  background='transparent', fontsize='14',
1951
1952
  border=True, landscape=False):
1952
1953
  r'''
@@ -1964,8 +1965,9 @@ class Chip:
1964
1965
  Args:
1965
1966
  filename (filepath): Output filepath
1966
1967
  flow (str): Name of flowgraph to render
1967
- fillcolor(str): Node fill RGB color hex value
1968
1968
  fontcolor (str): Node font RGB color hex value
1969
+ color_scheme (str): Name of the color scheme to apply to the nodes.
1970
+ Valid choices are: "none", "simple", "detailed"
1969
1971
  background (str): Background color
1970
1972
  fontsize (str): Node text font size
1971
1973
  border (bool): Enables node border if True
@@ -1981,6 +1983,33 @@ class Chip:
1981
1983
  fileroot, ext = os.path.splitext(filepath)
1982
1984
  fileformat = ext.replace(".", "")
1983
1985
 
1986
+ color_schemes = {
1987
+ "none": {
1988
+ "design": "white",
1989
+ "library": "white",
1990
+ "logiclib": "white",
1991
+ "macrolib": "white"
1992
+ },
1993
+ "simple": {
1994
+ "design": "lightgreen",
1995
+ "library": "white",
1996
+ "logiclib": "lightgreen",
1997
+ "macrolib": "lightgreen"
1998
+ },
1999
+ "detailed": {
2000
+ "design": "lightgreen",
2001
+ "library": "white",
2002
+ "logiclib": "lightskyblue",
2003
+ "macrolib": "lightgoldenrod2"
2004
+ },
2005
+ }
2006
+
2007
+ if not color_scheme:
2008
+ color_scheme = "none"
2009
+
2010
+ if color_scheme not in color_schemes:
2011
+ raise ValueError(f'{color_scheme} is not a valid color scheme')
2012
+
1984
2013
  # controlling border width
1985
2014
  if border:
1986
2015
  penwidth = '1'
@@ -2006,7 +2035,7 @@ class Chip:
2006
2035
  nodes.add(node)
2007
2036
  dot.node(node, label=node, bordercolor=fontcolor, style='filled',
2008
2037
  fontcolor=fontcolor, fontsize=fontsize, ordering="in",
2009
- penwidth=penwidth, fillcolor=fillcolor)
2038
+ penwidth=penwidth, fillcolor="white")
2010
2039
  return node
2011
2040
 
2012
2041
  nodes = {}
@@ -2019,32 +2048,53 @@ class Chip:
2019
2048
  if root_label in nodes:
2020
2049
  return
2021
2050
 
2022
- in_libs = lib.get('option', 'library',
2023
- step=Schema.GLOBAL_KEY, index=Schema.GLOBAL_KEY) + \
2024
- lib.get('asic', 'logiclib',
2025
- step=Schema.GLOBAL_KEY, index=Schema.GLOBAL_KEY) + \
2026
- lib.get('asic', 'macrolib',
2027
- step=Schema.GLOBAL_KEY, index=Schema.GLOBAL_KEY)
2028
-
2029
2051
  in_labels = []
2030
- for in_lib in in_libs:
2052
+ for in_lib in lib.get('option', 'library',
2053
+ step=Schema.GLOBAL_KEY, index=Schema.GLOBAL_KEY):
2031
2054
  in_labels.append(f'library-{in_lib}')
2055
+ for in_lib in lib.get('asic', 'logiclib',
2056
+ step=Schema.GLOBAL_KEY, index=Schema.GLOBAL_KEY):
2057
+ in_labels.append(f'logiclib-{in_lib}')
2058
+ for in_lib in lib.get('asic', 'macrolib',
2059
+ step=Schema.GLOBAL_KEY, index=Schema.GLOBAL_KEY):
2060
+ in_labels.append(f'macrolib-{in_lib}')
2061
+
2062
+ shape = "oval"
2063
+ if root_type == "logiclib":
2064
+ shape = "box"
2065
+ elif root_type == "macrolib":
2066
+ shape = "box"
2067
+ elif root_type == "design":
2068
+ shape = "box"
2069
+
2070
+ color = color_schemes[color_scheme][root_type]
2032
2071
 
2033
2072
  nodes[root_label] = {
2034
2073
  "text": name,
2035
- "shape": "oval" if root_type == "library" else "box",
2074
+ "shape": shape,
2075
+ "color": color,
2036
2076
  "connects_to": set(in_labels)
2037
2077
  }
2038
2078
 
2039
- for in_lib in in_libs:
2040
- collect_library("library", Schema(cfg=self.getdict('library', in_lib)), name=in_lib)
2079
+ for in_lib in lib.get('option', 'library',
2080
+ step=Schema.GLOBAL_KEY, index=Schema.GLOBAL_KEY):
2081
+ collect_library("library", Schema(cfg=self.getdict('library', in_lib)),
2082
+ name=in_lib)
2083
+ for in_lib in lib.get('asic', 'logiclib',
2084
+ step=Schema.GLOBAL_KEY, index=Schema.GLOBAL_KEY):
2085
+ collect_library("logiclib", Schema(cfg=self.getdict('library', in_lib)),
2086
+ name=in_lib)
2087
+ for in_lib in lib.get('asic', 'macrolib',
2088
+ step=Schema.GLOBAL_KEY, index=Schema.GLOBAL_KEY):
2089
+ collect_library("macrolib", Schema(cfg=self.getdict('library', in_lib)),
2090
+ name=in_lib)
2041
2091
 
2042
2092
  collect_library("design", self)
2043
2093
 
2044
2094
  for label, info in nodes.items():
2045
2095
  dot.node(label, label=info['text'], bordercolor=fontcolor, style='filled',
2046
2096
  fontcolor=fontcolor, fontsize=fontsize, ordering="in",
2047
- penwidth=penwidth, fillcolor=fillcolor, shape=info['shape'])
2097
+ penwidth=penwidth, fillcolor=info["color"], shape=info['shape'])
2048
2098
 
2049
2099
  for conn in info['connects_to']:
2050
2100
  dot.edge(label, conn, dir='back')
@@ -2059,7 +2109,7 @@ class Chip:
2059
2109
  '''
2060
2110
  Recursively changes a library in ['option', 'library'] from a previous
2061
2111
  value to a new value. If the library is not present then nothing is
2062
- changed.
2112
+ changed. If the new library is None, the original library will be removed.
2063
2113
 
2064
2114
  Args:
2065
2115
  org_library (str): Name of old library
@@ -2081,8 +2131,13 @@ class Chip:
2081
2131
  r_index = Schema.GLOBAL_KEY
2082
2132
 
2083
2133
  val = self.get(*key, step=r_step, index=r_index)
2084
- self.set(*key, list(map(lambda x: x.replace(org_library, new_library), val)),
2085
- step=r_step, index=r_index)
2134
+ if new_library is None:
2135
+ self.set(*key, [v for v in val if v != org_library],
2136
+ step=r_step, index=r_index)
2137
+ else:
2138
+ self.set(*key,
2139
+ list(map(lambda x: new_library if x == org_library else x, val)),
2140
+ step=r_step, index=r_index)
2086
2141
  else:
2087
2142
  for val, r_step, r_index in self.schema._getvals(*key):
2088
2143
  if r_step is None:
@@ -2090,8 +2145,13 @@ class Chip:
2090
2145
  if r_index is None:
2091
2146
  r_index = Schema.GLOBAL_KEY
2092
2147
 
2093
- self.set(*key, list(map(lambda x: x.replace(org_library, new_library), val)),
2094
- step=r_step, index=r_index)
2148
+ if new_library is None:
2149
+ self.set(*key, [v for v in val if v != org_library],
2150
+ step=r_step, index=r_index)
2151
+ else:
2152
+ self.set(*key,
2153
+ list(map(lambda x: new_library if x == org_library else x, val)),
2154
+ step=r_step, index=r_index)
2095
2155
 
2096
2156
  swap('option', 'library')
2097
2157
  for lib in all_libraries:
siliconcompiler/issue.py CHANGED
@@ -153,6 +153,8 @@ def generate_testcase(chip,
153
153
  os.chdir(new_work_dir)
154
154
 
155
155
  # Rewrite replay.sh
156
+ prev_quiet = chip.get('option', 'quiet', step=step, index=index)
157
+ chip.set('option', 'quiet', True, step=step, index=index)
156
158
  from siliconcompiler import SiliconCompilerError
157
159
  try:
158
160
  # Rerun setup
@@ -167,6 +169,7 @@ def generate_testcase(chip,
167
169
  pass
168
170
  except SiliconCompilerError:
169
171
  pass
172
+ chip.set('option', 'quiet', prev_quiet, step=step, index=index)
170
173
 
171
174
  flow = chip.get('option', 'flow')
172
175
  is_python_tool = hasattr(chip._get_task_module(step, index, flow=flow), 'run')
@@ -59,7 +59,7 @@ def get_flowgraph_nodes(chip, step, index):
59
59
  if value is not None:
60
60
  if key == 'inputnode':
61
61
  value = ", ".join([f'{step}{index}' for step, index in value])
62
- nodes[key] = value
62
+ nodes[key] = str(value)
63
63
  return nodes
64
64
 
65
65
 
@@ -201,7 +201,10 @@ def _local_process(chip, flow):
201
201
  f'{chip.design}.pkg.json')
202
202
  if os.path.exists(manifest):
203
203
  # ensure we setup these nodes again
204
- extra_setup_nodes[(step, index)] = Schema(manifest=manifest, logger=chip.logger)
204
+ try:
205
+ extra_setup_nodes[(step, index)] = Schema(manifest=manifest, logger=chip.logger)
206
+ except Exception:
207
+ pass
205
208
 
206
209
  # Setup tools for all nodes to run.
207
210
  nodes = nodes_to_execute(chip, flow)
@@ -11,7 +11,7 @@ try:
11
11
  except ImportError:
12
12
  from siliconcompiler.schema.utils import trim
13
13
 
14
- SCHEMA_VERSION = '0.44.2'
14
+ SCHEMA_VERSION = '0.44.3'
15
15
 
16
16
  #############################################################################
17
17
  # PARAM DEFINITION
@@ -1273,12 +1273,21 @@ def schema_datasheet(cfg, name='default', mode='default'):
1273
1273
 
1274
1274
  scparam(cfg, ['datasheet', 'package', name, 'netname', name],
1275
1275
  sctype='str',
1276
- shorthelp="Datasheet: package pin netname",
1276
+ shorthelp="Datasheet: package pin net name",
1277
1277
  switch="-datasheet_package_netname 'name name <str>'",
1278
1278
  example=[
1279
1279
  "cli: -datasheet_package_netname 'abcd B1 VDD'",
1280
1280
  "api: chip.set('datasheet', 'package', 'abcd', 'netname', 'B1', 'VDD')"],
1281
- schelp="""Datsheet: Net name connected to package pin.""")
1281
+ schelp="""Datsheet: Device net connected to the pin.""")
1282
+
1283
+ scparam(cfg, ['datasheet', 'package', name, 'portname', name],
1284
+ sctype='str',
1285
+ shorthelp="Datasheet: package pin port name",
1286
+ switch="-datasheet_package_portname 'name name <str>'",
1287
+ example=[
1288
+ "cli: -datasheet_package_portname 'abcd B1 VDD'",
1289
+ "api: chip.set('datasheet', 'package', 'abcd', 'portname', 'B1', 'VDD')"],
1290
+ schelp="""Datsheet: Device port connected to the pin.""")
1282
1291
 
1283
1292
  ######################
1284
1293
  # Pin Specifications
@@ -83,3 +83,55 @@ proc sc_section_banner { text { method puts } } {
83
83
  $method "| $text"
84
84
  $method "============================================================"
85
85
  }
86
+
87
+ # Get list of soft libraries
88
+ proc sc_get_libraries { {library {}} {libraries {}} } {
89
+ set key []
90
+ if { [llength $library] != 0 } {
91
+ lappend key library $library
92
+ }
93
+ lappend key option library
94
+
95
+ set libs []
96
+ foreach lib [sc_cfg_get {*}$key] {
97
+ if { [lsearch -exact $libs $lib] != -1 || [lsearch -exact $libraries $lib] != -1 } {
98
+ continue
99
+ }
100
+
101
+ lappend libs $lib
102
+
103
+ foreach sublib [sc_get_libraries $lib $libs] {
104
+ lappend libs $sublib
105
+ }
106
+ }
107
+
108
+ return [lsort -unique $libs]
109
+ }
110
+
111
+ # Get list of asic libraries
112
+ proc sc_get_asic_libraries { type } {
113
+ set libs []
114
+
115
+ foreach lib [sc_cfg_get asic ${type}lib] {
116
+ if { [lsearch -exact $libs $lib] != -1 } {
117
+ continue
118
+ }
119
+ lappend libs $lib
120
+ }
121
+
122
+ foreach lib [sc_get_libraries] {
123
+ if { ![sc_cfg_exists library $lib asic ${type}lib] } {
124
+ continue
125
+ }
126
+
127
+ foreach sublib [sc_cfg_get library $lib asic ${type}lib] {
128
+ if { [lsearch -exact $libs $sublib] != -1 } {
129
+ continue
130
+ }
131
+
132
+ lappend libs $sublib
133
+ }
134
+ }
135
+
136
+ return $libs
137
+ }
@@ -1,7 +1,5 @@
1
1
  import os
2
2
  import pkgutil
3
- from siliconcompiler.utils import get_file_ext
4
- from siliconcompiler import units, SiliconCompilerError, NodeStatus
5
3
 
6
4
 
7
5
  def get_libraries(chip, include_asic=True, library=None, libraries=None):
@@ -159,6 +157,8 @@ def __get_keys(chip, *key, include_library_files=True):
159
157
 
160
158
 
161
159
  def __assert_support(chip, opt_keys, supports):
160
+ from siliconcompiler import SiliconCompilerError
161
+
162
162
  if not supports:
163
163
  supports = []
164
164
 
@@ -255,6 +255,8 @@ def get_frontend_options(chip, supports=None):
255
255
 
256
256
 
257
257
  def find_incoming_ext(chip, support_exts, default_ext):
258
+ from siliconcompiler.utils import get_file_ext
259
+
258
260
  step = chip.get('arg', 'step')
259
261
  index = chip.get('arg', 'index')
260
262
  flow = chip.get('option', 'flow')
@@ -302,6 +304,8 @@ def pick_key(chip, check_keys, step=None, index=None):
302
304
 
303
305
 
304
306
  def input_provides(chip, step, index, flow=None):
307
+ from siliconcompiler import NodeStatus
308
+
305
309
  if not flow:
306
310
  flow = chip.get('option', 'flow')
307
311
 
@@ -323,6 +327,8 @@ def input_provides(chip, step, index, flow=None):
323
327
 
324
328
 
325
329
  def input_file_node_name(filename, step, index):
330
+ from siliconcompiler.utils import get_file_ext
331
+
326
332
  file_type = get_file_ext(filename)
327
333
 
328
334
  base = filename
@@ -408,6 +414,8 @@ def record_metric(chip, step, index, metric, value, source, source_unit=None):
408
414
  Records the metric cell area under 'floorplan0' and notes the source as
409
415
  'reports/metrics.json'
410
416
  '''
417
+ from siliconcompiler import units
418
+
411
419
  metric_unit = None
412
420
  if chip.schema.has_field('metric', metric, 'unit'):
413
421
  metric_unit = chip.get('metric', metric, field='unit')
@@ -1,12 +1,32 @@
1
- from siliconcompiler.tools._common import pick_key
2
- from siliconcompiler.tools._common import get_tool_task
1
+ from .. import _common
3
2
 
4
3
 
5
4
  def get_mainlib(chip):
5
+ return get_libraries(chip, 'logic')[0]
6
+
7
+
8
+ def get_libraries(chip, type):
6
9
  step = chip.get('arg', 'step')
7
10
  index = chip.get('arg', 'index')
8
- logiclibs = chip.get('asic', 'logiclib', step=step, index=index)
9
- return logiclibs[0]
11
+
12
+ if type not in ('logic', 'macro'):
13
+ raise ValueError(f'Cannot collect {type} libraries')
14
+
15
+ libs = []
16
+ for lib in chip.get('asic', f'{type}lib', step=step, index=index):
17
+ if lib in libs:
18
+ continue
19
+ libs.append(lib)
20
+
21
+ for lib in _common.get_libraries(chip, include_asic=False):
22
+ if not chip.valid('library', lib, 'asic', f'{type}lib'):
23
+ continue
24
+ for sublib in chip.get('library', lib, 'asic', f'{type}lib', step=step, index=index):
25
+ if sublib in libs:
26
+ continue
27
+ libs.append(sublib)
28
+
29
+ return libs
10
30
 
11
31
 
12
32
  def get_timing_modes(chip):
@@ -33,7 +53,7 @@ def set_tool_task_var(chip,
33
53
  '''
34
54
  step = chip.get('arg', 'step')
35
55
  index = chip.get('arg', 'index')
36
- tool, task = get_tool_task(chip, step, index)
56
+ tool, task = _common.get_tool_task(chip, step, index)
37
57
  pdkname = chip.get('option', 'pdk')
38
58
  stackup = chip.get('option', 'stackup')
39
59
  mainlib = get_mainlib(chip)
@@ -72,7 +92,7 @@ def set_tool_task_var(chip,
72
92
  ','.join(check_keys[-1]),
73
93
  step=step, index=index)
74
94
 
75
- require_key, value = pick_key(chip, reversed(check_keys), step=step, index=index)
95
+ require_key, value = _common.pick_key(chip, reversed(check_keys), step=step, index=index)
76
96
  if not value:
77
97
  value = default_value
78
98
 
@@ -2,6 +2,7 @@
2
2
  from siliconcompiler.tools.klayout.klayout import setup as setup_tool
3
3
  from siliconcompiler.tools.klayout.screenshot import setup_gui_screenshot
4
4
  from siliconcompiler.tools._common import input_provides, get_tool_task
5
+ from siliconcompiler.tools._common.asic import get_libraries
5
6
 
6
7
 
7
8
  def setup(chip):
@@ -23,7 +24,7 @@ def setup(chip):
23
24
  chip.set('tool', tool, 'task', task, 'script', script, step=step, index=index, clobber=clobber)
24
25
  chip.set('tool', tool, 'task', task, 'option', option, step=step, index=index, clobber=clobber)
25
26
 
26
- targetlibs = chip.get('asic', 'logiclib', step=step, index=index)
27
+ targetlibs = get_libraries(chip, 'logic')
27
28
  stackup = chip.get('option', 'stackup')
28
29
  pdk = chip.get('option', 'pdk')
29
30
 
@@ -39,7 +40,7 @@ def setup(chip):
39
40
  sc_stream_order = [default_stream, *[s for s in streams if s != default_stream]]
40
41
 
41
42
  if stackup and targetlibs:
42
- macrolibs = chip.get('asic', 'macrolib', step=step, index=index)
43
+ macrolibs = get_libraries(chip, 'macro')
43
44
 
44
45
  chip.add('tool', tool, 'task', task, 'require', ",".join(['asic', 'logiclib']),
45
46
  step=step, index=index)
@@ -124,7 +124,8 @@ def main():
124
124
  save_technology,
125
125
  get_schema
126
126
  )
127
- from tools.klayout.klayout_show import show # noqa E402
127
+ from tools.klayout.klayout_show import show
128
+ from tools._common.asic import get_libraries
128
129
 
129
130
  schema = get_schema(manifest='sc_manifest.json')
130
131
 
@@ -158,9 +159,8 @@ def main():
158
159
 
159
160
  out_file = os.path.join('outputs', f'{design}.{sc_stream}')
160
161
 
161
- libs = schema.get('asic', 'logiclib', step=sc_step, index=sc_index)
162
- if 'macrolib' in schema.getkeys('asic'):
163
- libs += schema.get('asic', 'macrolib', step=sc_step, index=sc_index)
162
+ libs = get_libraries(schema, 'logic')
163
+ libs += get_libraries(schema, 'macro')
164
164
 
165
165
  in_files = []
166
166
  for lib in libs: