siliconcompiler 0.29.4__py3-none-any.whl → 0.30.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.
Files changed (35) hide show
  1. siliconcompiler/_metadata.py +1 -1
  2. siliconcompiler/apps/sc.py +1 -1
  3. siliconcompiler/apps/sc_install.py +28 -0
  4. siliconcompiler/core.py +15 -4
  5. siliconcompiler/schema/schema_cfg.py +149 -92
  6. siliconcompiler/tools/__init__.py +3 -1
  7. siliconcompiler/tools/bluespec/__init__.py +35 -0
  8. siliconcompiler/tools/bluespec/convert.py +44 -5
  9. siliconcompiler/tools/graphviz/__init__.py +12 -0
  10. siliconcompiler/tools/graphviz/screenshot.py +48 -0
  11. siliconcompiler/tools/graphviz/show.py +20 -0
  12. siliconcompiler/tools/openroad/_apr.py +6 -0
  13. siliconcompiler/tools/openroad/macro_placement.py +9 -0
  14. siliconcompiler/tools/openroad/power_grid.py +6 -0
  15. siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +2 -0
  16. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +2 -0
  17. siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +15 -5
  18. siliconcompiler/tools/openroad/scripts/apr/sc_macro_placement.tcl +9 -1
  19. siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +53 -0
  20. siliconcompiler/tools/openroad/scripts/common/procs.tcl +26 -5
  21. siliconcompiler/tools/openroad/scripts/common/reports.tcl +10 -3
  22. siliconcompiler/toolscripts/_tools.json +4 -4
  23. siliconcompiler/toolscripts/rhel9/install-openroad.sh +1 -1
  24. siliconcompiler/toolscripts/ubuntu20/install-openroad.sh +1 -1
  25. siliconcompiler/toolscripts/ubuntu22/install-openroad.sh +1 -1
  26. siliconcompiler/toolscripts/ubuntu24/install-openroad.sh +1 -1
  27. siliconcompiler/utils/__init__.py +11 -0
  28. siliconcompiler/utils/showtools.py +7 -0
  29. {siliconcompiler-0.29.4.dist-info → siliconcompiler-0.30.0.dist-info}/METADATA +5 -5
  30. {siliconcompiler-0.29.4.dist-info → siliconcompiler-0.30.0.dist-info}/RECORD +34 -32
  31. siliconcompiler/tools/bluespec/bluespec.py +0 -40
  32. {siliconcompiler-0.29.4.dist-info → siliconcompiler-0.30.0.dist-info}/LICENSE +0 -0
  33. {siliconcompiler-0.29.4.dist-info → siliconcompiler-0.30.0.dist-info}/WHEEL +0 -0
  34. {siliconcompiler-0.29.4.dist-info → siliconcompiler-0.30.0.dist-info}/entry_points.txt +0 -0
  35. {siliconcompiler-0.29.4.dist-info → siliconcompiler-0.30.0.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  # Version number following semver standard.
2
- version = '0.29.4'
2
+ version = '0.30.0'
3
3
 
4
4
  # Default server address for remote runs, if unspecified.
5
5
  default_server = 'https://server.siliconcompiler.com'
@@ -95,7 +95,7 @@ def main():
95
95
 
96
96
  try:
97
97
  # Run flow
98
- chip.run()
98
+ chip.run(raise_exception=True)
99
99
 
100
100
  # Print Job Summary
101
101
  chip.summary()
@@ -248,6 +248,34 @@ To system debugging information (this should only be used to debug):
248
248
  if not install_tool(tool, tools[tool], args.build_dir, args.prefix):
249
249
  return 1
250
250
 
251
+ if not args.show:
252
+ msgs = []
253
+ for env, path in (
254
+ ("PATH", "bin"),
255
+ ("LD_LIBRARY_PATH", "lib")):
256
+ check_path = os.path.join(args.prefix, path)
257
+ envs = [
258
+ os.path.expandvars(os.path.expanduser(p))
259
+ for p in os.getenv(env, "").split(":")
260
+ ]
261
+ print(envs)
262
+ if check_path not in envs:
263
+ msgs.extend([
264
+ "",
265
+ f"{check_path} not found in {env}",
266
+ "you may need to add it the following your shell",
267
+ "initialization script:",
268
+ f'export {env}="{check_path}:${env}"'
269
+ ])
270
+ if msgs:
271
+ center_len = max(len(msg) for msg in msgs)
272
+ max_len = center_len + 4
273
+ print("#"*max_len)
274
+ for msg in msgs:
275
+ print(f"# {msg:<{center_len}} #")
276
+ print(f"# {' '*center_len} #")
277
+ print("#"*max_len)
278
+
251
279
  return 0
252
280
 
253
281
 
siliconcompiler/core.py CHANGED
@@ -67,7 +67,7 @@ class Chip:
67
67
  except FileNotFoundError:
68
68
  raise SiliconCompilerError(
69
69
  "SiliconCompiler must be run from a directory that exists. "
70
- "If you are sure that your working directory is valid, try running `cd $(pwd)`.""")
70
+ "If you are sure that your working directory is valid, try running `cd $(pwd)`.")
71
71
 
72
72
  # Initialize custom error handling for codecs. This has to be called
73
73
  # by each spawned (as opposed to forked) subprocess
@@ -3153,7 +3153,7 @@ class Chip:
3153
3153
  self.add('flowgraph', flow, newstep, index, 'input', (newin, in_index))
3154
3154
 
3155
3155
  ###########################################################################
3156
- def run(self):
3156
+ def run(self, raise_exception=False):
3157
3157
  '''
3158
3158
  Executes tasks in a flowgraph.
3159
3159
 
@@ -3177,12 +3177,23 @@ class Chip:
3177
3177
  processes to exit before start, returning control to the the main
3178
3178
  program which can then exit.
3179
3179
 
3180
+ Args:
3181
+ raise_exception (bool): if True, will rethrow errors that the flow raises,
3182
+ otherwise will report the error and return False
3183
+
3180
3184
  Examples:
3181
3185
  >>> run()
3182
3186
  Runs the execution flow defined by the flowgraph dictionary.
3183
3187
  '''
3184
3188
 
3185
- sc_runner(self)
3189
+ try:
3190
+ sc_runner(self)
3191
+ except Exception as e:
3192
+ if raise_exception:
3193
+ raise e
3194
+ self.logger.error(str(e))
3195
+ return False
3196
+ return True
3186
3197
 
3187
3198
  ###########################################################################
3188
3199
  def show(self, filename=None, screenshot=False, extension=None):
@@ -3320,7 +3331,7 @@ class Chip:
3320
3331
 
3321
3332
  # run show flow
3322
3333
  try:
3323
- self.run()
3334
+ self.run(raise_exception=True)
3324
3335
  if screenshot:
3325
3336
  step, index = _get_flowgraph_exit_nodes(self, flow='showflow')[0]
3326
3337
  success = self.find_result('png', step=step, index=index)
@@ -10,7 +10,7 @@ try:
10
10
  except ImportError:
11
11
  from siliconcompiler.schema.utils import trim
12
12
 
13
- SCHEMA_VERSION = '0.48.6'
13
+ SCHEMA_VERSION = '0.49.0'
14
14
 
15
15
  #############################################################################
16
16
  # PARAM DEFINITION
@@ -1260,17 +1260,35 @@ def schema_datasheet(cfg, name='default', mode='default'):
1260
1260
  example=[
1261
1261
  "cli: -datasheet_package_type 'abcd bga'",
1262
1262
  "api: chip.set('datasheet', 'package', 'abcd', 'type', 'bga')"],
1263
- schelp="""Package type specified on a named package basis.""")
1263
+ schelp="""Package type.""")
1264
1264
 
1265
1265
  scparam(cfg, ['datasheet', 'package', name, 'footprint'],
1266
- sctype='str',
1266
+ sctype='[file]',
1267
1267
  shorthelp="Datasheet: package footprint",
1268
- switch="-datasheet_package_footprint 'name <str>'",
1268
+ switch="-datasheet_package_footprint 'name <file>'",
1269
+ example=[
1270
+ "cli: -datasheet_package_footprint 'abcd ./soic8.kicad_mod'",
1271
+ "api: chip.set('datasheet', 'package', 'abcd', 'footprint', './soic8.kicad_mod')"],
1272
+ schelp="""Package footprint file. Supported 3D model file formats include:
1273
+
1274
+ * (KICAD_MOD) KiCad Standard Footprint Format
1275
+
1276
+ """)
1277
+
1278
+ scparam(cfg, ['datasheet', 'package', name, '3dmodel'],
1279
+ sctype='[file]',
1280
+ shorthelp="Datasheet: package 3D model",
1281
+ switch="-datasheet_package_3dmodel 'name <file>'",
1269
1282
  example=[
1270
- "cli: -datasheet_package_footprint 'abcd soic8'",
1271
- "api: chip.set('datasheet', 'package', 'abcd', 'footprint', 'soic8')"],
1272
- schelp="""Package footprint name. The name of the footprint can be a standard
1273
- footprint name or a reference designator from a footprint library.""")
1283
+ "cli: -datasheet_package_3dmodel 'abcd ./soic8.step'",
1284
+ "api: chip.set('datasheet', 'package', 'abcd', '3dmodel', './soic8.step')"],
1285
+ schelp="""Package 3D model file. Supported 3D model file formats include:
1286
+
1287
+ * (STEP) Standard for the Exchange of Product Data Format
1288
+ * (STL) Stereolithography Format
1289
+ * (WRL) Virtually Reality Modeling Language Format
1290
+
1291
+ """)
1274
1292
 
1275
1293
  scparam(cfg, ['datasheet', 'package', name, 'drawing'],
1276
1294
  sctype='[file]',
@@ -1279,38 +1297,14 @@ def schema_datasheet(cfg, name='default', mode='default'):
1279
1297
  example=[
1280
1298
  "cli: -datasheet_package_drawing 'abcd p484.pdf'",
1281
1299
  "api: chip.set('datasheet', 'package', 'abcd', 'drawing', 'p484.pdf')"],
1282
- schelp="""Mechanical package outline for documentation purposes.
1283
- Common file formats include PDF, DOC, SVG, and PNG.""")
1300
+ schelp="""Mechanical drawing for documentation purposes.
1301
+ Supported file formats include: PDF, DOC, SVG, and PNG.""")
1284
1302
 
1285
- scparam(cfg, ['datasheet', 'package', name, 'pincount'],
1286
- sctype='int',
1287
- shorthelp="Datasheet: package total pincount",
1288
- switch="-datasheet_package_pincount 'name <int>'",
1289
- example=[
1290
- "cli: -datasheet_package_pincount 'abcd 484'",
1291
- "api: chip.set('datasheet', 'package', 'abcd', 'pincount', '484')"],
1292
- schelp="""Total number package pins of the named package.""")
1293
-
1294
- scparam(cfg, ['datasheet', 'package', name, 'anchor'],
1295
- sctype='(float,float)',
1296
- defvalue=(0.0, 0.0),
1297
- unit='um',
1298
- shorthelp="Datasheeet: package anchor",
1299
- switch="-datasheet_package_anchor 'name <(float,float)>'",
1300
- example=[
1301
- "cli: -datasheet_package_anchor 'i0 (3.0,3.0)'",
1302
- "api: chip.set('datasheet', 'package', 'i0', 'anchor', (3.0, 3.0))"],
1303
- schelp="""
1304
- Package anchor point with respect to the lower left corner of the package.
1305
- When placing a component on a substrate, the placement location specifies
1306
- the distance from the substrate origin to the anchor point of the placed
1307
- object.""")
1308
-
1309
- # critical dimensions
1303
+ # key package metrics
1310
1304
  metrics = {'length': ['length', (4000, 4000, 4000), 'um'],
1311
1305
  'width': ['width', (4000, 4000, 4000), 'um'],
1312
1306
  'thickness': ['thickness', (900, 1000, 1100), 'um'],
1313
- 'pitch': ['pitch', (800, 850, 900), 'um']
1307
+ 'pinpitch': ['pin pitch', (800, 850, 900), 'um']
1314
1308
  }
1315
1309
 
1316
1310
  for i, v in metrics.items():
@@ -1322,63 +1316,46 @@ def schema_datasheet(cfg, name='default', mode='default'):
1322
1316
  example=[
1323
1317
  f"cli: -datasheet_package_{i} 'abcd {v[1]}'",
1324
1318
  f"api: chip.set('datasheet', 'package', 'abcd', '{i}', {v[1]}"],
1325
- schelp=f"""Datasheet: package {v[0]}. Values are tuples of
1319
+ schelp=f"""Package {v[0]}. Values are tuples of
1326
1320
  (min, nominal, max).""")
1327
1321
 
1328
- # pinout diagram
1329
- pinnumber = 'default'
1330
- scparam(cfg, ['datasheet', 'package', name, 'pin', pinnumber, 'shape'],
1331
- sctype='enum',
1332
- enum=['circle', 'rectangle', 'square', 'octagon'],
1333
- shorthelp="Datasheet: package pin shape",
1334
- switch="-datasheet_package_pin_shape 'name pinnumber <str>'",
1322
+ # pin
1323
+ scparam(cfg, ['datasheet', 'package', name, 'pincount'],
1324
+ sctype='int',
1325
+ shorthelp="Datasheet: package pin count",
1326
+ switch="-datasheet_package_pincount 'name <int>'",
1335
1327
  example=[
1336
- "cli: -datasheet_package_pin_shape 'abcd B1 circle'",
1337
- "api: chip.set('datasheet', 'package', 'abcd', 'pin', 'B1', 'shape', 'circle')"],
1338
- schelp="""Datasheet: package pin shape specified on a per package
1339
- and per pin number basis.""")
1340
-
1341
- metrics = {'width': ['width', (200, 250, 300), 'um'],
1342
- 'length': ['length', (200, 250, 300), 'um']
1343
- }
1328
+ "cli: -datasheet_package_pincount 'abcd 484'",
1329
+ "api: chip.set('datasheet', 'package', 'abcd', 'pincount', '484')"],
1330
+ schelp="""Total number package pins.""")
1344
1331
 
1345
- for i, v in metrics.items():
1346
- scparam(cfg, ['datasheet', 'package', name, 'pin', pinnumber, i],
1347
- unit=v[2],
1348
- sctype='(float,float,float)',
1349
- shorthelp=f"Datasheet: package pin {v[0]}",
1350
- switch=f"-datasheet_package_pin_{i} 'name pinnumber <(float,float,float)>'",
1351
- example=[
1352
- f"cli: -datasheet_package_pin_{i} 'abcd B1 {v[1]}'",
1353
- f"api: chip.set('datasheet', 'package', 'abcd', 'pin', 'B1', '{i}', {v[1]}"],
1354
- schelp=f"""Datsheet: {v[0]} specified on a per package and per pin number
1355
- basis. Values are tuples of (min, nominal, max).""")
1332
+ number = 'default'
1333
+ scparam(cfg, ['datasheet', 'package', name, 'pin', number, 'signal'],
1334
+ sctype='str',
1335
+ shorthelp="Datasheet: package pin signal map",
1336
+ switch="-datasheet_package_pin_signal 'name number <str>'",
1337
+ example=[
1338
+ "cli: -datasheet_package_pin_signal 'abcd B1 clk'",
1339
+ "api: chip.set('datasheet', 'package', 'abcd', 'pin', 'B1', 'signal', 'clk')"],
1340
+ schelp="""Mapping between the package physical pin name ("1", "2", "A1", "B3", ...)
1341
+ and the corresponding device signal name ("VDD", "CLK", "NRST") found in the
1342
+ :keypath:`datasheet,pin`.""")
1356
1343
 
1357
- scparam(cfg, ['datasheet', 'package', name, 'pin', pinnumber, 'loc'],
1344
+ # anchor
1345
+ scparam(cfg, ['datasheet', 'package', name, 'anchor'],
1358
1346
  sctype='(float,float)',
1347
+ defvalue=(0.0, 0.0),
1359
1348
  unit='um',
1360
- shorthelp="Datasheet: package pin location",
1361
- switch="-datasheet_package_pin_loc 'name pinnumber <(float,float)>'",
1349
+ shorthelp="Datasheet: package anchor",
1350
+ switch="-datasheet_package_anchor 'name <(float,float)>'",
1362
1351
  example=[
1363
- "cli: -datasheet_package_pin_loc 'abcd B1 (500,500)'",
1364
- "api: chip.set('datasheet', 'package', 'abcd', 'pin', 'B1', 'loc', (500,500)"],
1365
- schelp="""Datsheet: Package pin location specified as an (x,y) tuple on a per
1366
- package and per pin number basis. Locations specify the center of the pin with
1367
- respect to the center of the package.""")
1368
-
1369
- scparam(cfg, ['datasheet', 'package', name, 'pin', pinnumber, 'name'],
1370
- sctype='str',
1371
- shorthelp="Datasheet: package pin name",
1372
- switch="-datasheet_package_pin_name 'name pinnumber <str>'",
1373
- example=[
1374
- "cli: -datasheet_package_pin_name 'abcd B1 clk'",
1375
- "api: chip.set('datasheet', 'package', 'abcd', 'pin', 'B1', 'name', 'clk')"],
1376
- schelp="""Datsheet: Package pin name specified on a per package and per pin
1377
- number basis. The pin number is generally an integer starting at '1' in the case of
1378
- packages like qfn, qfp and an array index ('A1', 'A2') in the case of array packages
1379
- like bgas. The pin name refers to the logical function assigned to the physical
1380
- pin number (e.g clk, vss, in). Details regarding the logical pin is stored in
1381
- the :keypath:`datasheet,pin`.""")
1352
+ "cli: -datasheet_package_anchor 'i0 (3.0, 3.0)'",
1353
+ "api: chip.set('datasheet', 'package', 'i0', 'anchor', (3.0, 3.0))"],
1354
+ schelp="""
1355
+ Package anchor point with respect to the lower left corner of the package.
1356
+ When placing a component on a substrate, the placement location specifies
1357
+ the distance from the substrate origin to the anchor point of the placed
1358
+ object.""")
1382
1359
 
1383
1360
  ######################
1384
1361
  # Pin Specifications
@@ -3784,10 +3761,11 @@ def schema_constraint(cfg):
3784
3761
  "api: chip.set('constraint', 'component', 'i0', 'halo', (1, 1))"],
3785
3762
  schelp="""
3786
3763
  Placement keepout halo around the named component, specified as a
3787
- (horizontal, vertical) tuple represented in microns.""")
3764
+ (horizontal, vertical) tuple.""")
3788
3765
 
3789
3766
  scparam(cfg, ['constraint', 'component', inst, 'rotation'],
3790
3767
  sctype='enum',
3768
+ pernode='optional',
3791
3769
  defvalue='R0',
3792
3770
  enum=['R0', 'R90', 'R180', 'R270',
3793
3771
  'MX', 'MX_R90', 'MX_R180', 'MX_R270',
@@ -3795,7 +3773,6 @@ def schema_constraint(cfg):
3795
3773
  'MZ', 'MZ_R90', 'MZ_R180', 'MZ_R270',
3796
3774
  'MZ_MX', 'MZ_MX_R90', 'MZ_MX_R180', 'MZ_MX_R270',
3797
3775
  'MZ_MY', 'MZ_MY_R90', 'MZ_MY_R180', 'MZ_MY_R270'],
3798
- pernode='optional',
3799
3776
  shorthelp="Constraint: component rotation",
3800
3777
  switch="-constraint_component_rotation 'inst <str>'",
3801
3778
  example=[
@@ -3829,6 +3806,49 @@ def schema_constraint(cfg):
3829
3806
  * ``MZ_MX_R270``, ``MZ_MY_R90``: Reverse metal stack, flip on x-axis and rotate 270 deg ccw
3830
3807
  """)
3831
3808
 
3809
+ scparam(cfg, ['constraint', 'component', inst, 'substrate'],
3810
+ sctype='str',
3811
+ pernode='optional',
3812
+ shorthelp="Constraint: component substrate",
3813
+ switch="-constraint_component_substrate 'inst <str>'",
3814
+ example=[
3815
+ "cli: -constraint_component_substrate 'i0 pcb0'",
3816
+ "api: chip.set('constraint', 'component', 'i0', 'substrate', 'pcb0')"],
3817
+ schelp="""
3818
+ Substrates are supporting material that components are placed upon.
3819
+ List of supported substrates includes (but not limited to):
3820
+ wafers, dies, panels, PCBs.""")
3821
+
3822
+ scparam(cfg, ['constraint', 'component', inst, 'side'],
3823
+ sctype='enum',
3824
+ enum=['left', 'right', 'front', 'back', 'top', 'bottom'],
3825
+ pernode='optional',
3826
+ shorthelp="Constraint: component side",
3827
+ switch="-constraint_component_side 'inst <str>'",
3828
+ example=[
3829
+ "cli: -constraint_component_side 'i0 top'",
3830
+ "api: chip.set('constraint', 'component', 'i0', 'side', 'top')"],
3831
+ schelp="""
3832
+ Side of the substrate where the component should be placed. The `side`
3833
+ definitions are with respect to a viewer looking sideways at an object.
3834
+ Top is towards the sky, front is the side closest to the viewer, and
3835
+ right is right. The maximum number of sides per substrate is six""")
3836
+
3837
+ scparam(cfg, ['constraint', 'component', inst, 'zheight'],
3838
+ sctype='float',
3839
+ pernode='optional',
3840
+ unit='um',
3841
+ shorthelp="Constraint: component placement zheight",
3842
+ switch="-constraint_component_zheight 'inst <float>'",
3843
+ example=[
3844
+ "cli: -constraint_component_zheight 'i0 100.0'",
3845
+ "api: chip.set('constraint', 'component', 'i0', 'zheight', 100.0)"],
3846
+ schelp="""
3847
+ Height above the substrate for component placement. The space
3848
+ between the component and substrate is occupied by material,
3849
+ supporting scaffolding, and electrical connections (eg. bumps,
3850
+ vias, pillars).""")
3851
+
3832
3852
  # PINS
3833
3853
  name = 'default'
3834
3854
  scparam(cfg, ['constraint', 'pin', name, 'placement'],
@@ -3848,6 +3868,44 @@ def schema_constraint(cfg):
3848
3868
  may adjust sizes to meet competing goals such as manufacturing design
3849
3869
  rules and grid placement guidelines.""")
3850
3870
 
3871
+ metrics = {'width': ['width', 1.0],
3872
+ 'length': ['length', 1.0],
3873
+ 'height': ['height', 1.0]
3874
+ }
3875
+
3876
+ for i, v in metrics.items():
3877
+ scparam(cfg, ['constraint', 'pin', name, i],
3878
+ sctype='float',
3879
+ unit='um',
3880
+ pernode='optional',
3881
+ shorthelp=f"Constraint: pin {i}",
3882
+ switch=f"-constraint_pin_{i} 'name <float>'",
3883
+ example=[
3884
+ f"cli: -constraint_pin_{i} 'nreset {v[1]}'",
3885
+ f"api: chip.set('constraint', 'pin', 'nreset', {i}, {v[1]})"],
3886
+ schelp=f"""
3887
+ Pin {i} constraint. This parameter represents goal/intent, not an exact
3888
+ specification. The layout system may adjust sizes to meet
3889
+ competing goals such as manufacturing design rules and grid placement
3890
+ guidelines.""")
3891
+
3892
+ scparam(cfg, ['constraint', 'pin', name, 'shape'],
3893
+ sctype='enum',
3894
+ enum=['circle', 'rectangle', 'square',
3895
+ 'hexagon', 'octagon', 'oval', 'pill', 'polygon'],
3896
+ pernode='optional',
3897
+ shorthelp="Constraint: pin shape",
3898
+ switch="-constraint_pin_shape 'name <str>'",
3899
+ example=[
3900
+ "cli: -constraint_pin_shape 'nreset circle'",
3901
+ "api: chip.set('constraint', 'pin', 'nreset', 'shape', 'circle')"],
3902
+ schelp="""
3903
+ Pin shape constraint specified on a per pin basis. In 3D design systems,
3904
+ the pin shape represents the cross section of the pin in the direction
3905
+ orthogonal to the signal flow direction. The 'pill' (aka stadium) shape,
3906
+ is rectangle with semicircles at a pair of opposite sides. The other
3907
+ pin shapes represent common geometric shape definitions.""")
3908
+
3851
3909
  scparam(cfg, ['constraint', 'pin', name, 'layer'],
3852
3910
  sctype='str',
3853
3911
  pernode='optional',
@@ -3903,8 +3961,8 @@ def schema_constraint(cfg):
3903
3961
  "cli: -constraint_net_maxlength 'nreset 1000'",
3904
3962
  "api: chip.set('constraint', 'net', 'nreset', 'maxlength', '1000')"],
3905
3963
  schelp="""
3906
- Maximum total length of a net, specified in microns.
3907
- Wildcards ('*') can be used for net names.""")
3964
+ Maximum total length of a net. Wildcards ('*') can be used for
3965
+ net names.""")
3908
3966
 
3909
3967
  scparam(cfg, ['constraint', 'net', name, 'maxresistance'],
3910
3968
  sctype='float',
@@ -3930,9 +3988,8 @@ def schema_constraint(cfg):
3930
3988
  "api: chip.set('constraint', 'net', 'nreset', 'ndr', (0.4, 0.4))"],
3931
3989
  schelp="""
3932
3990
  Definitions of non-default routing rule specified on a per
3933
- net basis. Constraints are entered as a (width, space) tuples
3934
- specified in microns. Wildcards ('*') can be used
3935
- for net names.""")
3991
+ net basis. Constraints are entered as a (width, space) tuples.
3992
+ Wildcards ('*') can be used for net names.""")
3936
3993
 
3937
3994
  scparam(cfg, ['constraint', 'net', name, 'minlayer'],
3938
3995
  sctype='str',
@@ -1,11 +1,12 @@
1
1
  from siliconcompiler.tools import bambu
2
- from siliconcompiler.tools.bluespec import bluespec
2
+ from siliconcompiler.tools import bluespec
3
3
  from siliconcompiler.tools.builtin import builtin
4
4
  from siliconcompiler.tools.chisel import chisel
5
5
  from siliconcompiler.tools.execute import execute
6
6
  from siliconcompiler.tools.genfasm import genfasm
7
7
  from siliconcompiler.tools.ghdl import ghdl
8
8
  from siliconcompiler.tools import gtkwave
9
+ from siliconcompiler.tools import graphviz
9
10
  from siliconcompiler.tools.icarus import icarus
10
11
  from siliconcompiler.tools.icepack import icepack
11
12
  from siliconcompiler.tools.klayout import klayout
@@ -39,6 +40,7 @@ def get_tools():
39
40
  execute,
40
41
  genfasm,
41
42
  ghdl,
43
+ graphviz,
42
44
  gtkwave,
43
45
  icarus,
44
46
  icepack,
@@ -0,0 +1,35 @@
1
+ '''
2
+ Bluespec is a high-level hardware description language. It has a variety of
3
+ advanced features including a powerful type system that can prevent errors
4
+ prior to synthesis time, and its most distinguishing feature, Guarded Atomic
5
+ Actions, allow you to define hardware components in a modular manner based
6
+ on their invariants, and let the compiler pick a scheduler.
7
+
8
+ Documentation: https://github.com/B-Lang-org/bsc#documentation
9
+
10
+ Sources: https://github.com/B-Lang-org/bsc
11
+
12
+ Installation: https://github.com/B-Lang-org/bsc#download
13
+ '''
14
+
15
+ from siliconcompiler.tools.bluespec import convert
16
+
17
+
18
+ ####################################################################
19
+ # Make Docs
20
+ ####################################################################
21
+ def make_docs(chip):
22
+ convert.setup(chip)
23
+ return chip
24
+
25
+
26
+ ################################
27
+ # Setup Tool (pre executable)
28
+ ################################
29
+ def parse_version(stdout):
30
+ # Examples:
31
+ # Bluespec Compiler, version 2021.12.1-27-g9a7d5e05 (build 9a7d5e05)
32
+ # Bluespec Compiler, version 2021.07 (build 4cac6eba)
33
+
34
+ long_version = stdout.split()[3]
35
+ return long_version.split('-')[0]
@@ -8,6 +8,7 @@ from siliconcompiler import sc_open
8
8
 
9
9
  # Directory inside step/index dir to store bsc intermediate results.
10
10
  VLOG_DIR = 'verilog'
11
+ BSC_DIR = 'bluespec'
11
12
 
12
13
 
13
14
  def setup(chip):
@@ -39,6 +40,7 @@ def setup(chip):
39
40
 
40
41
  # Input/Output requirements
41
42
  chip.add('tool', tool, 'task', task, 'output', chip.top() + '.v', step=step, index=index)
43
+ chip.add('tool', tool, 'task', task, 'output', chip.top() + '.dot', step=step, index=index)
42
44
 
43
45
  # Schema requirements
44
46
  add_require_input(chip, 'input', 'hll', 'bsv')
@@ -50,9 +52,10 @@ def setup(chip):
50
52
  ################################
51
53
  def pre_process(chip):
52
54
  # bsc requires its output directory exists before being called.
53
- if os.path.isdir(VLOG_DIR):
54
- shutil.rmtree(VLOG_DIR)
55
- os.makedirs(VLOG_DIR)
55
+ for path in (VLOG_DIR, BSC_DIR):
56
+ if os.path.isdir(path):
57
+ shutil.rmtree(path)
58
+ os.makedirs(path)
56
59
 
57
60
 
58
61
  ################################
@@ -68,7 +71,13 @@ def runtime_options(chip):
68
71
 
69
72
  cmdlist.append('-verilog')
70
73
  cmdlist.append(f'-vdir {VLOG_DIR}')
74
+ cmdlist.append(f'-bdir {BSC_DIR}')
75
+ cmdlist.append('-info-dir reports')
71
76
  cmdlist.append('-u')
77
+ cmdlist.append('-v')
78
+
79
+ cmdlist.append('-show-module-use')
80
+ cmdlist.append('-sched-dot')
72
81
 
73
82
  cmdlist.append(f'-g {chip.top(step, index)}')
74
83
 
@@ -95,10 +104,40 @@ def post_process(chip):
95
104
  ''' Tool specific function to run after step execution
96
105
  '''
97
106
 
107
+ step = chip.get('arg', 'step')
108
+ index = chip.get('arg', 'index')
109
+
110
+ shutil.copyfile(f"reports/{chip.top(step, index)}_combined_full.dot",
111
+ f"outputs/{chip.top()}.dot")
112
+
113
+ extra_modules = set()
114
+ use_file = os.path.join(VLOG_DIR, f"{chip.top(step, index)}.use")
115
+ if os.path.exists(use_file):
116
+ BSC_BASE = os.path.dirname(
117
+ os.path.dirname(
118
+ chip.get('record', 'toolpath', step=step, index=index)))
119
+ BSC_LIB = os.path.join(BSC_BASE, "lib", "Verilog")
120
+
121
+ with sc_open(use_file) as f:
122
+ for module in f:
123
+ module = module.strip()
124
+ mod_path = os.path.join(BSC_LIB, f"{module}.v")
125
+ if os.path.exists(mod_path):
126
+ extra_modules.add(mod_path)
127
+ else:
128
+ chip.logger.warn(f"Unable to find module {module} source files at: {BSC_LIB}")
129
+
98
130
  # bsc outputs each compiled module to its own Verilog file, so we
99
131
  # concatenate them all to create a pickled output we can pass along.
100
132
  design = chip.top()
101
133
  with open(os.path.join('outputs', f'{design}.v'), 'w') as pickled_vlog:
102
134
  for src in os.listdir(VLOG_DIR):
103
- with sc_open(os.path.join(VLOG_DIR, src)) as vlog_mod:
104
- pickled_vlog.write(vlog_mod.read())
135
+ if src.endswith(".v"):
136
+ with sc_open(os.path.join(VLOG_DIR, src)) as vlog_mod:
137
+ pickled_vlog.write(vlog_mod.read())
138
+
139
+ pickled_vlog.write("\n")
140
+ pickled_vlog.write("// Bluespec imports\n\n")
141
+ for vfile in extra_modules:
142
+ with sc_open(os.path.join(BSC_LIB, vfile)) as vlog_mod:
143
+ pickled_vlog.write(vlog_mod.read() + "\n")
@@ -0,0 +1,12 @@
1
+ '''
2
+ Graphviz is open source graph visualization software.
3
+ Graph visualization is a way of representing structural information as diagrams
4
+ of abstract graphs and networks.
5
+ It has important applications in networking, bioinformatics, software engineering,
6
+ database and web design, machine learning, and in visual interfaces for other
7
+ technical domains.
8
+ '''
9
+
10
+
11
+ def make_docs(chip):
12
+ return chip
@@ -0,0 +1,48 @@
1
+ import graphviz
2
+ import os
3
+
4
+ from siliconcompiler import sc_open
5
+ from siliconcompiler.tools._common import get_tool_task
6
+
7
+
8
+ def setup(chip):
9
+ '''
10
+ Generate a screenshot of a dot file
11
+ '''
12
+
13
+ step = chip.get('arg', 'step')
14
+ index = chip.get('arg', 'index')
15
+ tool, task = get_tool_task(chip, step, index)
16
+
17
+ chip.set('tool', tool, 'task', task, 'threads', 1, step=step, index=index)
18
+
19
+ chip.add('tool', tool, 'task', task, 'output', chip.top() + '.png', step=step, index=index)
20
+
21
+
22
+ def run(chip):
23
+ step = chip.get('arg', 'step')
24
+ index = chip.get('arg', 'index')
25
+ tool, task = get_tool_task(chip, step, index)
26
+
27
+ if os.path.exists(f'inputs/{chip.top()}.dot'):
28
+ file = f'inputs/{chip.top()}.dot'
29
+ elif os.path.exists(f'inputs/{chip.top()}.xdot'):
30
+ file = f'inputs/{chip.top()}.xdot'
31
+ elif chip.valid('tool', tool, 'task', task, 'var', 'show_filepath') and \
32
+ chip.get('tool', tool, 'task', task, 'var', 'show_filepath', step=step, index=index):
33
+ file = chip.get('tool', tool, 'task', task, 'var', 'show_filepath',
34
+ step=step, index=index)[0]
35
+ else:
36
+ file = chip.find_files('input', 'image', 'dot', step=step, index=index)[0]
37
+
38
+ with sc_open(file) as dot:
39
+ dot_content = dot.read()
40
+
41
+ try:
42
+ dot = graphviz.Source(dot_content, format="png")
43
+ dot.render(filename=f"outputs/{chip.top()}", cleanup=True)
44
+ pass
45
+ except graphviz.ExecutableNotFound:
46
+ return 1
47
+
48
+ return 0