siliconcompiler 0.32.3__py3-none-any.whl → 0.33.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 (154) hide show
  1. siliconcompiler/__init__.py +19 -2
  2. siliconcompiler/_metadata.py +1 -1
  3. siliconcompiler/apps/sc.py +2 -2
  4. siliconcompiler/apps/sc_install.py +3 -3
  5. siliconcompiler/apps/sc_issue.py +1 -1
  6. siliconcompiler/apps/sc_remote.py +4 -4
  7. siliconcompiler/apps/sc_show.py +2 -2
  8. siliconcompiler/apps/utils/replay.py +5 -3
  9. siliconcompiler/asic.py +120 -0
  10. siliconcompiler/checklist.py +150 -0
  11. siliconcompiler/core.py +267 -289
  12. siliconcompiler/flowgraph.py +803 -515
  13. siliconcompiler/fpga.py +84 -0
  14. siliconcompiler/metric.py +420 -0
  15. siliconcompiler/optimizer/vizier.py +2 -3
  16. siliconcompiler/package/__init__.py +29 -6
  17. siliconcompiler/pdk.py +415 -0
  18. siliconcompiler/record.py +449 -0
  19. siliconcompiler/remote/client.py +6 -3
  20. siliconcompiler/remote/schema.py +116 -112
  21. siliconcompiler/remote/server.py +3 -5
  22. siliconcompiler/report/dashboard/cli/__init__.py +13 -722
  23. siliconcompiler/report/dashboard/cli/board.py +895 -0
  24. siliconcompiler/report/dashboard/web/__init__.py +10 -10
  25. siliconcompiler/report/dashboard/web/components/__init__.py +5 -4
  26. siliconcompiler/report/dashboard/web/components/flowgraph.py +3 -3
  27. siliconcompiler/report/dashboard/web/components/graph.py +6 -3
  28. siliconcompiler/report/dashboard/web/state.py +1 -1
  29. siliconcompiler/report/dashboard/web/utils/__init__.py +4 -3
  30. siliconcompiler/report/html_report.py +2 -3
  31. siliconcompiler/report/report.py +13 -7
  32. siliconcompiler/report/summary_image.py +1 -1
  33. siliconcompiler/report/summary_table.py +3 -3
  34. siliconcompiler/report/utils.py +11 -10
  35. siliconcompiler/scheduler/__init__.py +145 -280
  36. siliconcompiler/scheduler/run_node.py +2 -1
  37. siliconcompiler/scheduler/send_messages.py +4 -4
  38. siliconcompiler/scheduler/slurm.py +2 -2
  39. siliconcompiler/schema/__init__.py +19 -2
  40. siliconcompiler/schema/baseschema.py +493 -0
  41. siliconcompiler/schema/cmdlineschema.py +250 -0
  42. siliconcompiler/{sphinx_ext → schema/docs}/__init__.py +3 -1
  43. siliconcompiler/{sphinx_ext → schema/docs}/dynamicgen.py +63 -81
  44. siliconcompiler/{sphinx_ext → schema/docs}/schemagen.py +73 -85
  45. siliconcompiler/{sphinx_ext → schema/docs}/utils.py +12 -13
  46. siliconcompiler/schema/editableschema.py +136 -0
  47. siliconcompiler/schema/journalingschema.py +238 -0
  48. siliconcompiler/schema/namedschema.py +41 -0
  49. siliconcompiler/schema/packageschema.py +101 -0
  50. siliconcompiler/schema/parameter.py +791 -0
  51. siliconcompiler/schema/parametertype.py +323 -0
  52. siliconcompiler/schema/parametervalue.py +736 -0
  53. siliconcompiler/schema/safeschema.py +37 -0
  54. siliconcompiler/schema/schema_cfg.py +109 -1789
  55. siliconcompiler/schema/utils.py +5 -68
  56. siliconcompiler/schema_obj.py +119 -0
  57. siliconcompiler/tool.py +1308 -0
  58. siliconcompiler/tools/_common/__init__.py +6 -10
  59. siliconcompiler/tools/_common/sdc/sc_constraints.sdc +1 -1
  60. siliconcompiler/tools/bluespec/convert.py +7 -7
  61. siliconcompiler/tools/builtin/_common.py +1 -1
  62. siliconcompiler/tools/builtin/concatenate.py +2 -2
  63. siliconcompiler/tools/builtin/minimum.py +1 -1
  64. siliconcompiler/tools/builtin/mux.py +2 -1
  65. siliconcompiler/tools/builtin/nop.py +1 -1
  66. siliconcompiler/tools/builtin/verify.py +6 -4
  67. siliconcompiler/tools/chisel/convert.py +4 -4
  68. siliconcompiler/tools/genfasm/bitstream.py +3 -3
  69. siliconcompiler/tools/ghdl/convert.py +1 -1
  70. siliconcompiler/tools/icarus/compile.py +4 -4
  71. siliconcompiler/tools/icepack/bitstream.py +6 -1
  72. siliconcompiler/tools/klayout/convert_drc_db.py +5 -0
  73. siliconcompiler/tools/klayout/klayout_export.py +0 -1
  74. siliconcompiler/tools/klayout/klayout_utils.py +3 -10
  75. siliconcompiler/tools/nextpnr/apr.py +6 -1
  76. siliconcompiler/tools/nextpnr/nextpnr.py +4 -4
  77. siliconcompiler/tools/openroad/_apr.py +13 -0
  78. siliconcompiler/tools/openroad/rdlroute.py +3 -3
  79. siliconcompiler/tools/openroad/scripts/apr/postamble.tcl +1 -1
  80. siliconcompiler/tools/openroad/scripts/apr/preamble.tcl +5 -5
  81. siliconcompiler/tools/openroad/scripts/apr/sc_antenna_repair.tcl +2 -2
  82. siliconcompiler/tools/openroad/scripts/apr/sc_clock_tree_synthesis.tcl +2 -2
  83. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_placement.tcl +2 -2
  84. siliconcompiler/tools/openroad/scripts/apr/sc_detailed_route.tcl +2 -2
  85. siliconcompiler/tools/openroad/scripts/apr/sc_endcap_tapcell_insertion.tcl +2 -2
  86. siliconcompiler/tools/openroad/scripts/apr/sc_fillercell_insertion.tcl +2 -2
  87. siliconcompiler/tools/openroad/scripts/apr/sc_fillmetal_insertion.tcl +2 -2
  88. siliconcompiler/tools/openroad/scripts/apr/sc_global_placement.tcl +2 -2
  89. siliconcompiler/tools/openroad/scripts/apr/sc_global_route.tcl +2 -2
  90. siliconcompiler/tools/openroad/scripts/apr/sc_init_floorplan.tcl +2 -2
  91. siliconcompiler/tools/openroad/scripts/apr/sc_macro_placement.tcl +3 -3
  92. siliconcompiler/tools/openroad/scripts/apr/sc_metrics.tcl +2 -2
  93. siliconcompiler/tools/openroad/scripts/apr/sc_pin_placement.tcl +2 -2
  94. siliconcompiler/tools/openroad/scripts/apr/sc_power_grid.tcl +2 -2
  95. siliconcompiler/tools/openroad/scripts/apr/sc_repair_design.tcl +2 -2
  96. siliconcompiler/tools/openroad/scripts/apr/sc_repair_timing.tcl +2 -2
  97. siliconcompiler/tools/openroad/scripts/apr/sc_write_data.tcl +2 -2
  98. siliconcompiler/tools/openroad/scripts/common/procs.tcl +57 -1
  99. siliconcompiler/tools/openroad/scripts/common/screenshot.tcl +2 -2
  100. siliconcompiler/tools/openroad/scripts/common/write_images.tcl +28 -3
  101. siliconcompiler/tools/openroad/scripts/sc_rcx.tcl +1 -1
  102. siliconcompiler/tools/openroad/scripts/sc_rdlroute.tcl +3 -3
  103. siliconcompiler/tools/openroad/scripts/sc_show.tcl +6 -6
  104. siliconcompiler/tools/slang/__init__.py +10 -10
  105. siliconcompiler/tools/surelog/parse.py +4 -4
  106. siliconcompiler/tools/sv2v/convert.py +20 -3
  107. siliconcompiler/tools/verilator/compile.py +2 -2
  108. siliconcompiler/tools/verilator/verilator.py +3 -3
  109. siliconcompiler/tools/vpr/place.py +1 -1
  110. siliconcompiler/tools/vpr/route.py +4 -4
  111. siliconcompiler/tools/vpr/screenshot.py +1 -1
  112. siliconcompiler/tools/vpr/show.py +5 -5
  113. siliconcompiler/tools/vpr/vpr.py +24 -24
  114. siliconcompiler/tools/xdm/convert.py +2 -2
  115. siliconcompiler/tools/xyce/simulate.py +1 -1
  116. siliconcompiler/tools/yosys/sc_synth_asic.tcl +74 -68
  117. siliconcompiler/tools/yosys/syn_asic.py +2 -2
  118. siliconcompiler/toolscripts/_tools.json +7 -7
  119. siliconcompiler/toolscripts/ubuntu22/install-vpr.sh +0 -2
  120. siliconcompiler/toolscripts/ubuntu24/install-vpr.sh +0 -2
  121. siliconcompiler/utils/__init__.py +8 -112
  122. siliconcompiler/utils/flowgraph.py +339 -0
  123. siliconcompiler/{issue.py → utils/issue.py} +4 -3
  124. siliconcompiler/utils/logging.py +1 -2
  125. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.0.dist-info}/METADATA +9 -8
  126. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.0.dist-info}/RECORD +151 -134
  127. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.0.dist-info}/WHEEL +1 -1
  128. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.0.dist-info}/entry_points.txt +8 -8
  129. siliconcompiler/schema/schema_obj.py +0 -1936
  130. siliconcompiler/toolscripts/ubuntu20/install-vpr.sh +0 -29
  131. siliconcompiler/toolscripts/ubuntu20/install-yosys-parmys.sh +0 -61
  132. /siliconcompiler/{templates → data/templates}/__init__.py +0 -0
  133. /siliconcompiler/{templates → data/templates}/email/__init__.py +0 -0
  134. /siliconcompiler/{templates → data/templates}/email/general.j2 +0 -0
  135. /siliconcompiler/{templates → data/templates}/email/summary.j2 +0 -0
  136. /siliconcompiler/{templates → data/templates}/issue/README.txt +0 -0
  137. /siliconcompiler/{templates → data/templates}/issue/__init__.py +0 -0
  138. /siliconcompiler/{templates → data/templates}/issue/run.sh +0 -0
  139. /siliconcompiler/{templates → data/templates}/replay/replay.py.j2 +0 -0
  140. /siliconcompiler/{templates → data/templates}/replay/replay.sh.j2 +0 -0
  141. /siliconcompiler/{templates → data/templates}/replay/requirements.txt +0 -0
  142. /siliconcompiler/{templates → data/templates}/replay/setup.sh +0 -0
  143. /siliconcompiler/{templates → data/templates}/report/__init__.py +0 -0
  144. /siliconcompiler/{templates → data/templates}/report/bootstrap.min.css +0 -0
  145. /siliconcompiler/{templates → data/templates}/report/bootstrap.min.js +0 -0
  146. /siliconcompiler/{templates → data/templates}/report/bootstrap_LICENSE.md +0 -0
  147. /siliconcompiler/{templates → data/templates}/report/sc_report.j2 +0 -0
  148. /siliconcompiler/{templates → data/templates}/slurm/__init__.py +0 -0
  149. /siliconcompiler/{templates → data/templates}/slurm/run.sh +0 -0
  150. /siliconcompiler/{templates → data/templates}/tcl/__init__.py +0 -0
  151. /siliconcompiler/{templates → data/templates}/tcl/manifest.tcl.j2 +0 -0
  152. /siliconcompiler/{units.py → utils/units.py} +0 -0
  153. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.0.dist-info}/licenses/LICENSE +0 -0
  154. {siliconcompiler-0.32.3.dist-info → siliconcompiler-0.33.0.dist-info}/top_level.txt +0 -0
@@ -1,12 +1,8 @@
1
1
  import contextlib
2
- import distro
3
- import getpass
4
2
  import multiprocessing
5
3
  import logging
6
4
  import os
7
- import platform
8
5
  import psutil
9
- import socket
10
6
  import re
11
7
  import shlex
12
8
  import shutil
@@ -17,25 +13,25 @@ import packaging.version
17
13
  import packaging.specifiers
18
14
  from io import StringIO
19
15
  import traceback
20
- from datetime import datetime
21
16
  from logging.handlers import QueueHandler, QueueListener
22
17
  from siliconcompiler import sc_open
23
18
  from siliconcompiler import utils
24
- from siliconcompiler import _metadata
25
19
  from siliconcompiler.remote import Client
26
- from siliconcompiler.schema import Schema
20
+ from siliconcompiler import Schema
21
+ from siliconcompiler.schema import JournalingSchema
22
+ from siliconcompiler.record import RecordTime, RecordTool
27
23
  from siliconcompiler.scheduler import slurm
28
24
  from siliconcompiler.scheduler import docker_runner
29
25
  from siliconcompiler import NodeStatus, SiliconCompilerError
30
- from siliconcompiler.flowgraph import _get_flowgraph_nodes, _get_flowgraph_execution_order, \
31
- _get_pruned_node_inputs, _get_flowgraph_entry_nodes, \
32
- _unreachable_steps_to_execute, _nodes_to_execute, \
26
+ from siliconcompiler.utils.flowgraph import _get_flowgraph_execution_order, \
27
+ _get_pruned_node_inputs, \
33
28
  get_nodes_from, nodes_to_execute, _check_flowgraph
34
29
  from siliconcompiler.utils.logging import SCBlankLoggerFormatter
35
30
  from siliconcompiler.tools._common import input_file_node_name
36
31
  import lambdapdk
37
32
  from siliconcompiler.tools._common import get_tool_task, record_metric
38
33
  from siliconcompiler.scheduler import send_messages
34
+ from siliconcompiler.flowgraph import RuntimeFlowgraph
39
35
 
40
36
  try:
41
37
  import resource
@@ -61,6 +57,14 @@ def _get_callback(hook):
61
57
  _failed_log_lines = 20
62
58
 
63
59
 
60
+ #######################################
61
+ def _do_record_access():
62
+ '''
63
+ Determine if Schema should record calls to .get
64
+ '''
65
+ return False
66
+
67
+
64
68
  ###############################################################################
65
69
  class SiliconCompilerTimeout(Exception):
66
70
  ''' Minimal Exception wrapper used to raise sc timeout errors.
@@ -101,7 +105,7 @@ def run(chip):
101
105
  copy_old_run_dir(chip, org_jobname)
102
106
  clean_build_dir(chip)
103
107
  _reset_flow_nodes(chip, flow, nodes_to_execute(chip, flow))
104
- __record_packages(chip)
108
+ chip.schema.get("record", field='schema').record_python_packages()
105
109
 
106
110
  if chip.get('option', 'remote'):
107
111
  client = Client(chip)
@@ -175,18 +179,17 @@ def _local_process(chip, flow):
175
179
  extra_setup_nodes = {}
176
180
 
177
181
  if chip.get('option', 'clean') or not chip.get('option', 'from'):
178
- load_nodes = _get_flowgraph_nodes(chip, flow)
182
+ load_nodes = list(chip.schema.get("flowgraph", flow, field="schema").get_nodes())
179
183
  else:
180
184
  for step in chip.get('option', 'from'):
181
185
  from_nodes.extend(
182
186
  [(step, index) for index in chip.getkeys('flowgraph', flow, step)])
183
187
 
184
- load_nodes = _nodes_to_execute(
185
- chip,
186
- flow,
187
- _get_flowgraph_entry_nodes(chip, flow),
188
- from_nodes,
189
- chip.get('option', 'prune'))
188
+ runtime = RuntimeFlowgraph(
189
+ chip.schema.get("flowgraph", flow, field="schema"),
190
+ to_steps=chip.get('option', 'from'),
191
+ prune_nodes=chip.get('option', 'prune'))
192
+ load_nodes = list(runtime.get_nodes())
190
193
 
191
194
  for node_level in _get_flowgraph_execution_order(chip, flow):
192
195
  for step, index in node_level:
@@ -201,12 +204,14 @@ def _local_process(chip, flow):
201
204
  if os.path.exists(manifest):
202
205
  # ensure we setup these nodes again
203
206
  try:
204
- extra_setup_nodes[(step, index)] = Schema(manifest=manifest, logger=chip.logger)
207
+ journal = JournalingSchema(Schema())
208
+ journal.read_manifest(manifest)
209
+ extra_setup_nodes[(step, index)] = journal
205
210
  except Exception:
206
211
  pass
207
212
 
208
213
  # Setup tools for all nodes to run.
209
- nodes = nodes_to_execute(chip, flow)
214
+ nodes = list(nodes_to_execute(chip, flow))
210
215
  all_setup_nodes = nodes + load_nodes + list(extra_setup_nodes.keys())
211
216
  for layer_nodes in _get_flowgraph_execution_order(chip, flow):
212
217
  for step, index in layer_nodes:
@@ -222,19 +227,28 @@ def _local_process(chip, flow):
222
227
  except: # noqa E722
223
228
  pass
224
229
  if node_status:
225
- chip.set('record', 'status', node_status, step=step, index=index)
230
+ chip.schema.get("record", field='schema').set('status', node_status,
231
+ step=step, index=index)
226
232
 
227
233
  def mark_pending(step, index):
228
- chip.set('record', 'status', NodeStatus.PENDING, step=step, index=index)
234
+ chip.schema.get("record", field='schema').set('status', NodeStatus.PENDING,
235
+ step=step, index=index)
229
236
  for next_step, next_index in get_nodes_from(chip, flow, [(step, index)]):
230
237
  if chip.get('record', 'status', step=next_step, index=next_index) == \
231
238
  NodeStatus.SKIPPED:
232
239
  continue
233
240
 
234
241
  # Mark following steps as pending
235
- chip.set('record', 'status', NodeStatus.PENDING, step=next_step, index=next_index)
242
+ chip.schema.get("record", field='schema').set('status', NodeStatus.PENDING,
243
+ step=next_step, index=next_index)
236
244
 
237
245
  # Check if nodes have been modified from previous data
246
+ runtimeflow = RuntimeFlowgraph(
247
+ chip.schema.get("flowgraph", flow, field="schema"),
248
+ from_steps=chip.get('option', 'from'),
249
+ to_steps=chip.get('option', 'to'),
250
+ prune_nodes=chip.get('option', 'prune'))
251
+
238
252
  for layer_nodes in _get_flowgraph_execution_order(chip, flow):
239
253
  for step, index in layer_nodes:
240
254
  # Only look at successful nodes
@@ -242,12 +256,14 @@ def _local_process(chip, flow):
242
256
  (NodeStatus.SUCCESS, NodeStatus.SKIPPED):
243
257
  continue
244
258
 
245
- if not check_node_inputs(chip, step, index):
259
+ if (step, index) in runtimeflow.get_nodes() and \
260
+ not check_node_inputs(chip, step, index):
246
261
  # change failing nodes to pending
247
262
  mark_pending(step, index)
248
263
  elif (step, index) in extra_setup_nodes:
249
264
  # import old information
250
- chip.schema._import_journal(extra_setup_nodes[(step, index)])
265
+ JournalingSchema(chip.schema).import_journal(
266
+ schema=extra_setup_nodes[(step, index)])
251
267
 
252
268
  # Ensure pending nodes cause following nodes to be run
253
269
  for step, index in nodes:
@@ -344,7 +360,8 @@ def _setup_node(chip, step, index, flow=None):
344
360
 
345
361
  if setup_ret is not None:
346
362
  chip.logger.warning(f'Removing {step}{index} due to {setup_ret}')
347
- chip.set('record', 'status', NodeStatus.SKIPPED, step=step, index=index)
363
+ chip.schema.get("record", field='schema').set('status', NodeStatus.SKIPPED,
364
+ step=step, index=index)
348
365
 
349
366
  return False
350
367
 
@@ -457,17 +474,17 @@ def _runtask(chip, flow, step, index, exec_func, pipe=None, queue=None, replay=F
457
474
  chip.set('arg', 'step', step, clobber=True)
458
475
  chip.set('arg', 'index', index, clobber=True)
459
476
 
460
- chip.schema._start_journal()
477
+ chip.schema = JournalingSchema(chip.schema)
478
+ chip.schema.start_journal()
461
479
 
462
480
  # Make record of sc version and machine
463
- __record_version(chip, step, index)
481
+ chip.schema.get("record", field='schema').record_version(step, index)
464
482
  # Record user information if enabled
465
483
  if chip.get('option', 'track', step=step, index=index):
466
- __record_usermachine(chip, step, index)
484
+ chip.schema.get("record", field='schema').record_userinformation(step, index)
467
485
 
468
486
  # Start wall timer
469
- wall_start = time.time()
470
- __record_time(chip, step, index, wall_start, 'start')
487
+ chip.schema.get("record", field='schema').record_time(step, index, RecordTime.START)
471
488
 
472
489
  workdir = _setup_workdir(chip, step, index, replay)
473
490
  cwd = os.getcwd()
@@ -485,7 +502,8 @@ def _runtask(chip, flow, step, index, exec_func, pipe=None, queue=None, replay=F
485
502
 
486
503
  # return to original directory
487
504
  os.chdir(cwd)
488
- chip.schema._stop_journal()
505
+ chip.schema.stop_journal()
506
+ chip.schema = chip.schema.get_base_schema()
489
507
 
490
508
  if pipe:
491
509
  pipe.send(chip._packages)
@@ -493,7 +511,8 @@ def _runtask(chip, flow, step, index, exec_func, pipe=None, queue=None, replay=F
493
511
 
494
512
  ###########################################################################
495
513
  def _haltstep(chip, flow, step, index, log=True):
496
- chip.set('record', 'status', NodeStatus.ERROR, step=step, index=index)
514
+ chip.schema.get("record", field='schema').set('status', NodeStatus.ERROR,
515
+ step=step, index=index)
497
516
  chip.write_manifest(os.path.join("outputs", f"{chip.get('design')}.pkg.json"))
498
517
 
499
518
  if log:
@@ -566,12 +585,14 @@ def _select_inputs(chip, step, index, trial=False):
566
585
  else:
567
586
  sel_inputs = _get_pruned_node_inputs(chip, flow, (step, index))
568
587
 
569
- if (step, index) not in _get_flowgraph_entry_nodes(chip, flow) and not sel_inputs:
588
+ if (step, index) not in chip.schema.get("flowgraph", flow, field="schema").get_entry_nodes() \
589
+ and not sel_inputs:
570
590
  chip.logger.error(f'No inputs selected after running {tool}')
571
591
  _haltstep(chip, flow, step, index)
572
592
 
573
593
  if not trial:
574
- chip.set('record', 'inputnode', sel_inputs, step=step, index=index)
594
+ chip.schema.get("record", field='schema').set('inputnode', sel_inputs,
595
+ step=step, index=index)
575
596
 
576
597
  return sel_inputs
577
598
 
@@ -661,15 +682,15 @@ def __read_std_streams(chip, quiet,
661
682
  # Chip helper Functions
662
683
  ############################################################################
663
684
  def _getexe(chip, tool, step, index):
664
- path = chip.get('tool', tool, 'path', step=step, index=index)
665
685
  exe = chip.get('tool', tool, 'exe')
666
686
  if exe is None:
667
687
  return None
688
+ path = chip.find_files('tool', tool, 'path', step=step, index=index)
668
689
 
669
690
  syspath = os.getenv('PATH', os.defpath)
670
691
  if path:
671
692
  # Prepend 'path' schema var to system path
672
- syspath = utils._resolve_env_vars(chip, path, step, index) + os.pathsep + syspath
693
+ syspath = path + os.pathsep + syspath
673
694
 
674
695
  fullexe = shutil.which(exe, path=syspath)
675
696
 
@@ -714,20 +735,12 @@ def _makecmd(chip, tool, task, step, index, script_name='replay.sh', include_pat
714
735
 
715
736
  fullexe = _getexe(chip, tool, step, index)
716
737
 
717
- is_posix = __is_posix()
718
-
719
738
  def parse_options(options):
720
739
  if not options:
721
740
  return []
722
741
  shlex_opts = []
723
742
  for option in options:
724
- option = option.strip()
725
- if (option.startswith("\"") and option.endswith("\"")) or \
726
- (option.startswith("'") and option.endswith("'")):
727
- # Make sure strings are quoted in double quotes
728
- shlex_opts.append(f'"{option[1:-1]}"')
729
- else:
730
- shlex_opts.extend(shlex.split(option, posix=is_posix))
743
+ shlex_opts.append(str(option).strip())
731
744
  return shlex_opts
732
745
 
733
746
  # Add scripts files
@@ -743,9 +756,10 @@ def _makecmd(chip, tool, task, step, index, script_name='replay.sh', include_pat
743
756
  runtime_options = getattr(chip._get_tool_module(step, index), 'runtime_options', None)
744
757
  if runtime_options:
745
758
  try:
746
- chip.schema._start_record_access()
759
+ if _do_record_access():
760
+ chip.schema.add_journaling_type("get")
747
761
  cmdlist.extend(parse_options(runtime_options(chip)))
748
- chip.schema._stop_record_access()
762
+ chip.schema.remove_journaling_type("get")
749
763
  except Exception as e:
750
764
  chip.logger.error(f'Failed to get runtime options for {tool}/{task}')
751
765
  raise e
@@ -753,14 +767,7 @@ def _makecmd(chip, tool, task, step, index, script_name='replay.sh', include_pat
753
767
  # Separate variables to be able to display nice name of executable
754
768
  cmd = os.path.basename(cmdlist[0])
755
769
  cmd_args = cmdlist[1:]
756
- print_cmd = " ".join([cmd, *cmd_args])
757
- cmdlist = [cmdlist[0]]
758
- for arg in cmd_args:
759
- if arg.startswith("\"") and arg.endswith("\""):
760
- # Remove quoting since subprocess will handle that for us
761
- cmdlist.append(arg[1:-1])
762
- else:
763
- cmdlist.append(arg)
770
+ print_cmd = shlex.join([cmd, *cmd_args])
764
771
 
765
772
  # create replay file
766
773
  with open(script_name, 'w') as f:
@@ -793,9 +800,9 @@ def _makecmd(chip, tool, task, step, index, script_name='replay.sh', include_pat
793
800
  add_new_line = True
794
801
 
795
802
  if add_new_line:
796
- format_cmd.append(cmdarg)
803
+ format_cmd.append(shlex.quote(cmdarg))
797
804
  else:
798
- format_cmd[-1] += f' {cmdarg}'
805
+ format_cmd[-1] += f' {shlex.quote(cmdarg)}'
799
806
 
800
807
  replay_opts["cmds"] = format_cmd
801
808
 
@@ -915,9 +922,8 @@ def _run_executable_or_builtin(chip, step, index, version, toolpath, workdir, ru
915
922
  ##################
916
923
  # Make record of tool options
917
924
  if cmd_args is not None:
918
- chip.set('record', 'toolargs',
919
- ' '.join(f'"{arg}"' if ' ' in arg else arg for arg in cmd_args),
920
- step=step, index=index)
925
+ chip.schema.get("record", field='schema').record_tool(
926
+ step, index, cmd_args, RecordTool.ARGS)
921
927
 
922
928
  chip.logger.info('%s', printable_cmd)
923
929
  timeout = chip.get('option', 'timeout', step=step, index=index)
@@ -962,7 +968,6 @@ def _run_executable_or_builtin(chip, step, index, version, toolpath, workdir, ru
962
968
  if nice:
963
969
  preexec_fn = set_nice
964
970
 
965
- cmd_start_time = time.time()
966
971
  proc = subprocess.Popen(cmdlist,
967
972
  stdin=subprocess.DEVNULL,
968
973
  stdout=stdout_writer,
@@ -1004,7 +1009,7 @@ def _run_executable_or_builtin(chip, step, index, version, toolpath, workdir, ru
1004
1009
  is_stdout_log, stdout_reader, stdout_print,
1005
1010
  is_stderr_log, stderr_reader, stderr_print)
1006
1011
 
1007
- if timeout is not None and time.time() - cmd_start_time > timeout:
1012
+ if timeout is not None and time.time() - cpu_start > timeout:
1008
1013
  chip.logger.error(f'Step timed out after {timeout} seconds')
1009
1014
  utils.terminate_process(proc.pid)
1010
1015
  raise SiliconCompilerTimeout(f'{step}{index} timeout')
@@ -1024,7 +1029,7 @@ def _run_executable_or_builtin(chip, step, index, version, toolpath, workdir, ru
1024
1029
  is_stderr_log, stderr_reader, stderr_print)
1025
1030
  retcode = proc.returncode
1026
1031
 
1027
- chip.set('record', 'toolexitcode', retcode, step=step, index=index)
1032
+ chip.schema.get("record", field='schema').record_tool(step, index, retcode, RecordTool.EXITCODE)
1028
1033
  if retcode != 0:
1029
1034
  msg = f'Command failed with code {retcode}.'
1030
1035
  if logfile:
@@ -1056,9 +1061,10 @@ def _post_process(chip, step, index):
1056
1061
  func = getattr(chip._get_task_module(step, index, flow=flow), 'post_process', None)
1057
1062
  if func:
1058
1063
  try:
1059
- chip.schema._start_record_access()
1064
+ if _do_record_access():
1065
+ chip.schema.add_journaling_type("get")
1060
1066
  func(chip)
1061
- chip.schema._stop_record_access()
1067
+ chip.schema.remove_journaling_type("get")
1062
1068
  except Exception as e:
1063
1069
  chip.logger.error(f'Failed to run post-process for {tool}/{task}.')
1064
1070
  print_traceback(chip, e)
@@ -1123,10 +1129,12 @@ def _executenode(chip, step, index, replay):
1123
1129
  toolpath, version = _check_tool_version(chip, step, index, run_func)
1124
1130
 
1125
1131
  if version:
1126
- chip.set('record', 'toolversion', version, step=step, index=index)
1132
+ chip.schema.get("record", field='schema').record_tool(
1133
+ step, index, version, RecordTool.VERSION)
1127
1134
 
1128
1135
  if toolpath:
1129
- chip.set('record', 'toolpath', toolpath, step=step, index=index)
1136
+ chip.schema.get("record", field='schema').record_tool(
1137
+ step, index, toolpath, RecordTool.PATH)
1130
1138
 
1131
1139
  # Write manifest (tool interface) (Don't move this!)
1132
1140
  _write_task_manifest(chip, tool)
@@ -1151,9 +1159,10 @@ def _pre_process(chip, step, index):
1151
1159
  func = getattr(chip._get_task_module(step, index, flow=flow), 'pre_process', None)
1152
1160
  if func:
1153
1161
  try:
1154
- chip.schema._start_record_access()
1162
+ if _do_record_access():
1163
+ chip.schema.add_journaling_type("get")
1155
1164
  func(chip)
1156
- chip.schema._stop_record_access()
1165
+ chip.schema.remove_journaling_type("get")
1157
1166
  except Exception as e:
1158
1167
  chip.logger.error(f"Pre-processing failed for '{tool}/{task}'.")
1159
1168
  raise e
@@ -1167,11 +1176,10 @@ def _set_env_vars(chip, step, index):
1167
1176
 
1168
1177
  tool, task = get_tool_task(chip, step, index)
1169
1178
 
1170
- chip.schema._start_record_access()
1171
-
1179
+ if _do_record_access():
1180
+ chip.schema.add_journaling_type("get")
1172
1181
  os.environ.update(_get_run_env_vars(chip, tool, task, step, index, include_path=True))
1173
-
1174
- chip.schema._stop_record_access()
1182
+ chip.schema.remove_journaling_type("get")
1175
1183
 
1176
1184
  return org_env
1177
1185
 
@@ -1265,7 +1273,8 @@ def _hash_files(chip, step, index, setup=False):
1265
1273
 
1266
1274
 
1267
1275
  def _finalizenode(chip, step, index, replay):
1268
- if chip.schema._do_record_access():
1276
+ if chip.schema.is_journaling() and any(
1277
+ [record["type"] == "get" for record in chip.schema.get_journal()]):
1269
1278
  assert_required_accesses(chip, step, index)
1270
1279
 
1271
1280
  flow = chip.get('option', 'flow')
@@ -1290,12 +1299,11 @@ def _finalizenode(chip, step, index, replay):
1290
1299
  _hash_files(chip, step, index)
1291
1300
 
1292
1301
  # Capture wall runtime and cpu cores
1293
- wall_end = time.time()
1294
- __record_time(chip, step, index, wall_end, 'end')
1302
+ end_time = chip.schema.get("record", field='schema').record_time(step, index, RecordTime.END)
1295
1303
 
1296
1304
  # calculate total time
1297
1305
  total_times = []
1298
- for check_step, check_index in _get_flowgraph_nodes(chip, flow):
1306
+ for check_step, check_index in chip.schema.get("flowgraph", flow, field="schema").get_nodes():
1299
1307
  total_time = chip.get('metric', 'totaltime', step=check_step, index=check_index)
1300
1308
  if total_time is not None:
1301
1309
  total_times.append(total_time)
@@ -1304,7 +1312,8 @@ def _finalizenode(chip, step, index, replay):
1304
1312
  else:
1305
1313
  total_time = 0.0
1306
1314
 
1307
- walltime = wall_end - get_record_time(chip, step, index, 'starttime')
1315
+ walltime = end_time - chip.schema.get("record", field='schema').get_recorded_time(
1316
+ step, index, RecordTime.START)
1308
1317
  record_metric(chip, step, index, 'tasktime', walltime,
1309
1318
  source=None, source_unit='s')
1310
1319
  record_metric(chip, step, index, 'totaltime', total_time + walltime,
@@ -1313,7 +1322,9 @@ def _finalizenode(chip, step, index, replay):
1313
1322
 
1314
1323
  # Save a successful manifest
1315
1324
  if not is_skipped:
1316
- chip.set('record', 'status', NodeStatus.SUCCESS, step=step, index=index)
1325
+ chip.schema.get("record", field='schema').set('status', NodeStatus.SUCCESS,
1326
+ step=step, index=index)
1327
+
1317
1328
  chip.write_manifest(os.path.join("outputs", f"{chip.get('design')}.pkg.json"))
1318
1329
 
1319
1330
  if chip._error and not replay:
@@ -1335,7 +1346,7 @@ def _finalizenode(chip, step, index, replay):
1335
1346
 
1336
1347
  def _make_testcase(chip, step, index):
1337
1348
  # Import here to avoid circular import
1338
- from siliconcompiler.issue import generate_testcase
1349
+ from siliconcompiler.utils.issue import generate_testcase
1339
1350
 
1340
1351
  generate_testcase(
1341
1352
  chip,
@@ -1378,7 +1389,8 @@ def assert_required_accesses(chip, step, index):
1378
1389
  if tool == 'builtin':
1379
1390
  return
1380
1391
 
1381
- gets = chip.schema._get_record_access()
1392
+ gets = set([tuple(record["key"]) for record in chip.schema.get_journal()
1393
+ if record["type"] == "get"])
1382
1394
  logfile = os.path.join(
1383
1395
  chip.getworkdir(jobname=jobname, step=step, index=index),
1384
1396
  f'{step}.log')
@@ -1457,20 +1469,20 @@ def _reset_flow_nodes(chip, flow, nodes_to_execute):
1457
1469
 
1458
1470
  def clear_node(step, index):
1459
1471
  # Reset metrics and records
1472
+ chip.schema.get("metric", field='schema').clear(step, index)
1460
1473
  for metric in chip.getkeys('metric'):
1461
1474
  _clear_metric(chip, step, index, metric)
1462
- for record in chip.getkeys('record'):
1463
- _clear_record(chip, step, index, record, preserve=[
1464
- 'remoteid',
1465
- 'status',
1466
- 'pythonpackage'])
1475
+
1476
+ chip.schema.get("record", field='schema').clear(
1477
+ step, index, keep=['remoteid', 'status', 'pythonpackage'])
1467
1478
 
1468
1479
  # Mark all nodes as pending
1469
- for step, index in _get_flowgraph_nodes(chip, flow):
1470
- chip.set('record', 'status', NodeStatus.PENDING, step=step, index=index)
1480
+ for step, index in chip.schema.get("flowgraph", flow, field="schema").get_nodes():
1481
+ chip.schema.get("record", field='schema').set('status', NodeStatus.PENDING,
1482
+ step=step, index=index)
1471
1483
 
1472
1484
  should_resume = not chip.get('option', 'clean')
1473
- for step, index in _get_flowgraph_nodes(chip, flow):
1485
+ for step, index in chip.schema.get("flowgraph", flow, field="schema").get_nodes():
1474
1486
  stepdir = chip.getworkdir(step=step, index=index)
1475
1487
  cfg = f"{stepdir}/outputs/{chip.get('design')}.pkg.json"
1476
1488
 
@@ -1484,12 +1496,14 @@ def _reset_flow_nodes(chip, flow, nodes_to_execute):
1484
1496
  try:
1485
1497
  old_status = Schema(manifest=cfg).get('record', 'status', step=step, index=index)
1486
1498
  if old_status:
1487
- chip.set('record', 'status', old_status, step=step, index=index)
1499
+ chip.schema.get("record", field='schema').set('status', old_status,
1500
+ step=step, index=index)
1488
1501
  except Exception:
1489
1502
  # unable to load so leave it default
1490
1503
  pass
1491
1504
  else:
1492
- chip.set('record', 'status', NodeStatus.ERROR, step=step, index=index)
1505
+ chip.schema.get("record", field='schema').set('status', NodeStatus.ERROR,
1506
+ step=step, index=index)
1493
1507
 
1494
1508
  for step in chip.getkeys('flowgraph', flow):
1495
1509
  all_indices_failed = True
@@ -1577,13 +1591,15 @@ def _check_node_dependencies(chip, node, deps, deps_was_successful):
1577
1591
  # Fail if any dependency failed for non-builtin task
1578
1592
  if tool != 'builtin':
1579
1593
  deps.clear()
1580
- chip.set('record', 'status', NodeStatus.ERROR, step=step, index=index)
1594
+ chip.schema.get("record", field='schema').set('status', NodeStatus.ERROR,
1595
+ step=step, index=index)
1581
1596
  return
1582
1597
 
1583
1598
  # Fail if no dependency successfully finished for builtin task
1584
1599
  if had_deps and len(deps) == 0 \
1585
1600
  and tool == 'builtin' and not deps_was_successful.get(node):
1586
- chip.set('record', 'status', NodeStatus.ERROR, step=step, index=index)
1601
+ chip.schema.get("record", field='schema').set('status', NodeStatus.ERROR,
1602
+ step=step, index=index)
1587
1603
 
1588
1604
 
1589
1605
  def _launch_nodes(chip, nodes_to_run, processes, local_processes):
@@ -1653,7 +1669,8 @@ def _launch_nodes(chip, nodes_to_run, processes, local_processes):
1653
1669
  if _get_callback('pre_node'):
1654
1670
  _get_callback('pre_node')(chip, *node)
1655
1671
 
1656
- chip.set('record', 'status', NodeStatus.RUNNING, step=node[0], index=node[1])
1672
+ chip.schema.get("record", field='schema').set('status', NodeStatus.RUNNING,
1673
+ step=node[0], index=node[1])
1657
1674
  start_times[node] = time.time()
1658
1675
  changed = True
1659
1676
 
@@ -1693,7 +1710,7 @@ def _process_completed_nodes(chip, processes, running_nodes):
1693
1710
  f'{chip.design}.pkg.json')
1694
1711
  chip.logger.debug(f'{step}{index} is complete merging: {manifest}')
1695
1712
  if os.path.exists(manifest):
1696
- chip.schema.read_journal(manifest)
1713
+ JournalingSchema(chip.schema).read_journal(manifest)
1697
1714
 
1698
1715
  if processes[node]["parent_pipe"] and processes[node]["parent_pipe"].poll(1):
1699
1716
  try:
@@ -1711,7 +1728,7 @@ def _process_completed_nodes(chip, processes, running_nodes):
1711
1728
  if not status or status == NodeStatus.PENDING:
1712
1729
  status = NodeStatus.ERROR
1713
1730
 
1714
- chip.set('record', 'status', status, step=step, index=index)
1731
+ chip.schema.get("record", field='schema').set('status', status, step=step, index=index)
1715
1732
 
1716
1733
  changed = True
1717
1734
 
@@ -1722,156 +1739,27 @@ def _process_completed_nodes(chip, processes, running_nodes):
1722
1739
 
1723
1740
 
1724
1741
  def _check_nodes_status(chip, flow):
1725
- def success(node):
1726
- return chip.get('record', 'status', step=node[0], index=node[1]) in \
1727
- (NodeStatus.SUCCESS, NodeStatus.SKIPPED)
1728
-
1729
- unreachable_steps = _unreachable_steps_to_execute(chip, flow, cond=success)
1730
- if unreachable_steps:
1742
+ flowgraph = chip.schema.get("flowgraph", flow, field="schema")
1743
+ runtime = RuntimeFlowgraph(
1744
+ flowgraph,
1745
+ from_steps=chip.get('option', 'from'),
1746
+ to_steps=chip.get('option', 'to'),
1747
+ prune_nodes=chip.get('option', 'prune'))
1748
+ runtime_no_prune = RuntimeFlowgraph(
1749
+ flowgraph,
1750
+ from_steps=chip.get('option', 'from'),
1751
+ to_steps=chip.get('option', 'to'))
1752
+
1753
+ all_steps = [step for step, index in runtime_no_prune.get_exit_nodes()
1754
+ if (step, index) not in chip.get('option', 'prune')]
1755
+ complete_steps = [step for step, _ in runtime.get_completed_nodes(
1756
+ record=chip.schema.get("record", field='schema'))]
1757
+
1758
+ unreached = set(all_steps).difference(complete_steps)
1759
+
1760
+ if unreached:
1731
1761
  raise SiliconCompilerError(
1732
- f'These final steps could not be reached: {list(unreachable_steps)}', chip=chip)
1733
-
1734
-
1735
- #######################################
1736
- def __record_version(chip, step, index):
1737
- chip.set('record', 'scversion', _metadata.version, step=step, index=index)
1738
- chip.set('record', 'pythonversion', platform.python_version(), step=step, index=index)
1739
-
1740
-
1741
- #######################################
1742
- def __record_packages(chip):
1743
- try:
1744
- from pip._internal.operations.freeze import freeze
1745
- except: # noqa E722
1746
- freeze = None
1747
-
1748
- if freeze:
1749
- # clear record
1750
- chip.set('record', 'pythonpackage', [])
1751
-
1752
- for pkg in freeze():
1753
- chip.add('record', 'pythonpackage', pkg)
1754
-
1755
-
1756
- #######################################
1757
- def __record_time(chip, step, index, record_time, timetype):
1758
- formatted_time = datetime.fromtimestamp(record_time).strftime('%Y-%m-%d %H:%M:%S')
1759
-
1760
- if timetype == 'start':
1761
- key = 'starttime'
1762
- elif timetype == 'end':
1763
- key = 'endtime'
1764
- else:
1765
- raise ValueError(f'{timetype} is not a valid time record')
1766
-
1767
- chip.set('record', key, formatted_time, step=step, index=index)
1768
-
1769
-
1770
- def get_record_time(chip, step, index, timetype):
1771
- return datetime.strptime(
1772
- chip.get('record', timetype, step=step, index=index),
1773
- '%Y-%m-%d %H:%M:%S').timestamp()
1774
-
1775
-
1776
- #######################################
1777
- def _get_cloud_region():
1778
- # TODO: add logic to figure out if we're running on a remote cluster and
1779
- # extract the region in a provider-specific way.
1780
- return 'local'
1781
-
1782
-
1783
- #######################################
1784
- def __record_usermachine(chip, step, index):
1785
- machine_info = _get_machine_info()
1786
- chip.set('record', 'platform', machine_info['system'], step=step, index=index)
1787
-
1788
- if machine_info['distro']:
1789
- chip.set('record', 'distro', machine_info['distro'], step=step, index=index)
1790
-
1791
- chip.set('record', 'osversion', machine_info['osversion'], step=step, index=index)
1792
-
1793
- if machine_info['kernelversion']:
1794
- chip.set('record', 'kernelversion', machine_info['kernelversion'], step=step, index=index)
1795
-
1796
- chip.set('record', 'arch', machine_info['arch'], step=step, index=index)
1797
-
1798
- chip.set('record', 'userid', getpass.getuser(), step=step, index=index)
1799
-
1800
- chip.set('record', 'machine', platform.node(), step=step, index=index)
1801
-
1802
- chip.set('record', 'region', _get_cloud_region(), step=step, index=index)
1803
-
1804
- try:
1805
- for interface, addrs in psutil.net_if_addrs().items():
1806
- if interface == 'lo':
1807
- # don't consider loopback device
1808
- continue
1809
-
1810
- if not addrs:
1811
- # skip missing addrs
1812
- continue
1813
-
1814
- use_addr = False
1815
- for addr in addrs:
1816
- if addr.family == socket.AF_INET:
1817
- if not addr.address.startswith('127.'):
1818
- use_addr = True
1819
- break
1820
-
1821
- if use_addr:
1822
- ipaddr = None
1823
- macaddr = None
1824
- for addr in addrs:
1825
- if not ipaddr and addr.family == socket.AF_INET:
1826
- ipaddr = addr.address
1827
- if not ipaddr and addr.family == socket.AF_INET6:
1828
- ipaddr = addr.address
1829
- if not macaddr and addr.family == psutil.AF_LINK:
1830
- macaddr = addr.address
1831
-
1832
- chip.set('record', 'ipaddr', ipaddr, step=step, index=index)
1833
- chip.set('record', 'macaddr', macaddr, step=step, index=index)
1834
- break
1835
- except: # noqa E722
1836
- chip.logger.warning('Could not find default network interface info')
1837
-
1838
-
1839
- #######################################
1840
- def _get_machine_info():
1841
- system = platform.system()
1842
- if system == 'Darwin':
1843
- lower_sys_name = 'macos'
1844
- else:
1845
- lower_sys_name = system.lower()
1846
-
1847
- if system == 'Linux':
1848
- distro_name = distro.id()
1849
- else:
1850
- distro_name = None
1851
-
1852
- if system == 'Darwin':
1853
- osversion, _, _ = platform.mac_ver()
1854
- elif system == 'Linux':
1855
- osversion = distro.version()
1856
- else:
1857
- osversion = platform.release()
1858
-
1859
- if system == 'Linux':
1860
- kernelversion = platform.release()
1861
- elif system == 'Windows':
1862
- kernelversion = platform.version()
1863
- elif system == 'Darwin':
1864
- kernelversion = platform.release()
1865
- else:
1866
- kernelversion = None
1867
-
1868
- arch = platform.machine()
1869
-
1870
- return {'system': lower_sys_name,
1871
- 'distro': distro_name,
1872
- 'osversion': osversion,
1873
- 'kernelversion': kernelversion,
1874
- 'arch': arch}
1762
+ f'These final steps could not be reached: {",".join(sorted(unreached))}', chip=chip)
1875
1763
 
1876
1764
 
1877
1765
  def print_traceback(chip, exception):
@@ -2146,12 +2034,11 @@ def copy_old_run_dir(chip, org_jobname):
2146
2034
  return
2147
2035
 
2148
2036
  # Copy nodes forward
2149
- org_nodes = set(_nodes_to_execute(
2150
- chip,
2151
- flow,
2152
- _get_flowgraph_entry_nodes(chip, flow),
2153
- from_nodes,
2154
- chip.get('option', 'prune')))
2037
+ runtime = RuntimeFlowgraph(
2038
+ chip.schema.get("flowgraph", flow, field="schema"),
2039
+ to_steps=chip.get('option', 'from'),
2040
+ prune_nodes=chip.get('option', 'prune'))
2041
+ org_nodes = set(runtime.get_nodes())
2155
2042
 
2156
2043
  copy_nodes = org_nodes.difference(from_nodes)
2157
2044
 
@@ -2197,8 +2084,7 @@ def copy_old_run_dir(chip, org_jobname):
2197
2084
  # delete file as it might be a hard link
2198
2085
  os.remove(manifest)
2199
2086
  schema.set('option', 'jobname', chip.get('option', 'jobname'))
2200
- with open(manifest, 'w') as f:
2201
- schema.write_json(f)
2087
+ schema.write_manifest(manifest)
2202
2088
 
2203
2089
 
2204
2090
  def clean_node_dir(chip, step, index):
@@ -2228,7 +2114,8 @@ def clean_build_dir(chip):
2228
2114
  for step, index in nodes_to_execute(chip):
2229
2115
  clean_node_dir(chip, step, index)
2230
2116
 
2231
- all_nodes = set(_get_flowgraph_nodes(chip, flow=chip.get('option', 'flow')))
2117
+ all_nodes = set(chip.schema.get("flowgraph", chip.get('option', 'flow'),
2118
+ field="schema").get_nodes())
2232
2119
  old_nodes = __collect_nodes_in_workdir(chip)
2233
2120
  node_mismatch = old_nodes.difference(all_nodes)
2234
2121
  if node_mismatch:
@@ -2291,7 +2178,8 @@ def _check_manifest_dynamic(chip, step, index):
2291
2178
  paramtype = chip.get(*keypath, field='type')
2292
2179
  is_perstep = not chip.get(*keypath, field='pernode').is_never()
2293
2180
  if ('file' in paramtype) or ('dir' in paramtype):
2294
- for val, check_step, check_index in chip.schema._getvals(*keypath):
2181
+ for val, check_step, check_index in chip.schema.get(*keypath,
2182
+ field=None).getvalues():
2295
2183
  if is_perstep:
2296
2184
  if check_step is None:
2297
2185
  check_step = Schema.GLOBAL_KEY
@@ -2315,35 +2203,12 @@ def _check_manifest_dynamic(chip, step, index):
2315
2203
 
2316
2204
 
2317
2205
  #######################################
2318
- def _clear_metric(chip, step, index, metric, preserve=None):
2206
+ def _clear_metric(chip, step, index, metric):
2319
2207
  '''
2320
2208
  Helper function to clear metrics records
2321
2209
  '''
2322
2210
 
2323
- # This function is often called in a loop; don't clear
2324
- # metrics which the caller wants to preserve.
2325
- if preserve and metric in preserve:
2326
- return
2327
-
2328
2211
  flow = chip.get('option', 'flow')
2329
2212
  tool, task = get_tool_task(chip, step, index, flow=flow)
2330
2213
 
2331
- chip.unset('metric', metric, step=step, index=index)
2332
2214
  chip.unset('tool', tool, 'task', task, 'report', metric, step=step, index=index)
2333
-
2334
-
2335
- #######################################
2336
- def _clear_record(chip, step, index, record, preserve=None):
2337
- '''
2338
- Helper function to clear record parameters
2339
- '''
2340
-
2341
- # This function is often called in a loop; don't clear
2342
- # records which the caller wants to preserve.
2343
- if preserve and record in preserve:
2344
- return
2345
-
2346
- if chip.get('record', record, field='pernode').is_never():
2347
- chip.unset('record', record)
2348
- else:
2349
- chip.unset('record', record, step=step, index=index)