files: # Copyright 2020 Silicon Compiler Authors. All Rights Reserved.
  
  import argparse
  import base64
  import time
  import datetime
  import multiprocessing
  import tarfile
  import traceback
  import asyncio
  from subprocess import run, PIPE
  import os
  import glob
  import pathlib
  import sys
  import gzip
  import re
  import json
  import logging
  import hashlib
  import shutil
  import copy
  import importlib
  import textwrap
  import math
  import pandas
  import yaml
  import graphviz
  import time
  import uuid
  import shlex
  import platform
  import getpass
  import csv
  import distro
  import netifaces
  import webbrowser
  import packaging.version
  import packaging.specifiers
  from jinja2 import Environment, FileSystemLoader
  from pathlib import Path
  from timeit import default_timer as timer
  from siliconcompiler.client import *
  from siliconcompiler.schema import *
  from siliconcompiler.scheduler import _deferstep
  from siliconcompiler import leflib
  from siliconcompiler import utils
  from siliconcompiler import _metadata
  import psutil
  
  class TaskStatus():
      # Could use Python 'enum' class here, but that doesn't work nicely with
      # schema.
      PENDING = 'pending'
      SUCCESS = 'success'
      ERROR = 'error'
  
  class Chip:
      """Object for configuring and executing hardware design flows.
  
      This is the main object used for configuration, data, and
      execution within the SiliconCompiler platform.
  
      Args:
          design (string): Name of the top level chip design module.
  
      Examples:
          >>> siliconcompiler.Chip(design="top")
          Creates a chip object with name "top".
      """
  
      ###########################################################################
      def __init__(self, design, loglevel=None):
          # version numbers
          self.scversion = _metadata.version
          self.schemaversion = SCHEMA_VERSION
  
          # Local variables
          self.scroot = os.path.dirname(os.path.abspath(__file__))
          self.cwd = os.getcwd()
          self.error = 0
          self.cfg = schema_cfg()
          # The 'status' dictionary can be used to store ephemeral config values.
          # Its contents will not be saved, and can be set by parent scripts
          # such as a web server or supervisor process. Currently supported keys:
          # * 'jobhash': A hash or UUID which can identify jobs in a larger system.
          # * 'remote_cfg': Dictionary containing remote server configurations
          #                 (address, credentials, etc.)
          # * 'slurm_account': User account ID in a connected slurm HPC cluster.
          # * 'slurm_partition': Name of the partition in which a task should run
          #                      on a connected slurm HPC cluster.
          # * 'watchdog': Activity-monitoring semaphore for jobs scheduled on an
          #               HPC cluster; expects a 'threading.Event'-like object.
          # * 'max_fs_bytes': A limit on how much disk space a job is allowed
          #                   to consume in a connected HPC cluster's storage.
          self.status = {}
  
          self.builtin = ['minimum','maximum',
                          'nop', 'mux', 'join', 'verify']
  
          # We set 'design' and 'loglevel' directly in the config dictionary
          # because of a chicken-and-egg problem: self.set() relies on the logger,
          # but the logger relies on these values.
          self.cfg['design']['value'] = design
          if loglevel:
              self.cfg['option']['loglevel']['value'] = loglevel
  
          self._init_logger()
  
          self._loaded_modules = {
              'flows': [],
              'pdks': [],
              'libs': [],
              'checklists': []
          }
  
      ###########################################################################
      @property
      def design(self):
          '''Design name of chip object.
  
          This is an immutable property.'''
          return self.get('design')
  
      ###########################################################################
      def _init_logger(self, step=None, index=None, in_run=False):
  
          self.logger = logging.getLogger(uuid.uuid4().hex)
  
          # Don't propagate log messages to "root" handler (we get duplicate
          # messages without this)
          # TODO: this prevents us from being able to capture logs with pytest:
          # we should revisit it
          self.logger.propagate = False
  
          loglevel = self.get('option', 'loglevel')
  
          if loglevel=='DEBUG':
              prefix = '| %(levelname)-7s | %(funcName)-10s | %(lineno)-4s'
          else:
              prefix = '| %(levelname)-7s'
  
          if in_run:
              flow = self.get('option', 'flow')
  
              # Figure out how wide to make step and index fields
              max_step_len = 2
              max_index_len = 2
              for future_step in self.getkeys('flowgraph', flow):
                  max_step_len = max(len(future_step) + 1, max_step_len)
                  for future_index in self.getkeys('flowgraph', flow, future_step):
                      max_index_len = max(len(future_index) + 1, max_index_len)
  
              jobname = self.get('option', 'jobname')
  
              if step is None:
                  step = '-' * max(max_step_len // 4, 1)
              if index is None:
                  index = '-' * max(max_index_len // 4, 1)
  
              run_info = f'%s  | %-{max_step_len}s | %-{max_index_len}s' % (jobname, step, index)
              logformat = ' | '.join([prefix, run_info, '%(message)s'])
          else:
              logformat = ' | '.join([prefix, '%(message)s'])
  
          handler = logging.StreamHandler()
          formatter = logging.Formatter(logformat)
  
          handler.setFormatter(formatter)
  
          # Clear any existing handlers so we don't end up with duplicate messages
          # if repeat calls to _init_logger are made
          if len(self.logger.handlers
  
  [... the rest is omitted ...]
files: siliconcompiler/core.py
files: # Copyright 2020 Silicon Compiler Authors. All Rights Reserved.
  
  import argparse
  import base64
  import time
  import datetime
  import multiprocessing
  import tarfile
  import traceback
  import asyncio
  from subprocess import run, PIPE
  import os
  import glob
  import pathlib
  import sys
  import gzip
  import re
  import json
  import logging
  import hashlib
  import shutil
  import copy
  import importlib
  import textwrap
  import math
  import pandas
  import yaml
  import graphviz
  import time
  import uuid
  import shlex
  import platform
  import getpass
  import csv
  import distro
  import netifaces
  import webbrowser
  import packaging.version
  import packaging.specifiers
  from jinja2 import Environment, FileSystemLoader
  from pathlib import Path
  from timeit import default_timer as timer
  from siliconcompiler.client import *
  from siliconcompiler.schema import *
  from siliconcompiler.scheduler import _deferstep
  from siliconcompiler import leflib
  from siliconcompiler import utils
  from siliconcompiler import _metadata
  import psutil
  
  class TaskStatus():
      # Could use Python 'enum' class here, but that doesn't work nicely with
      # schema.
      PENDING = 'pending'
      SUCCESS = 'success'
      ERROR = 'error'
  
  class Chip:
      """Object for configuring and executing hardware design flows.
  
      This is the main object used for configuration, data, and
      execution within the SiliconCompiler platform.
  
      Args:
          design (string): Name of the top level chip design module.
  
      Examples:
          >>> siliconcompiler.Chip(design="top")
          Creates a chip object with name "top".
      """
  
      ###########################################################################
      def __init__(self, design, loglevel=None):
          # version numbers
          self.scversion = _metadata.version
          self.schemaversion = SCHEMA_VERSION
  
          # Local variables
          self.scroot = os.path.dirname(os.path.abspath(__file__))
          self.cwd = os.getcwd()
          self.error = 0
          self.cfg = schema_cfg()
          # The 'status' dictionary can be used to store ephemeral config values.
          # Its contents will not be saved, and can be set by parent scripts
          # such as a web server or supervisor process. Currently supported keys:
          # * 'jobhash': A hash or UUID which can identify jobs in a larger system.
          # * 'remote_cfg': Dictionary containing remote server configurations
          #                 (address, credentials, etc.)
          # * 'slurm_account': User account ID in a connected slurm HPC cluster.
          # * 'slurm_partition': Name of the partition in which a task should run
          #                      on a connected slurm HPC cluster.
          # * 'watchdog': Activity-monitoring semaphore for jobs scheduled on an
          #               HPC cluster; expects a 'threading.Event'-like object.
          # * 'max_fs_bytes': A limit on how much disk space a job is allowed
          #                   to consume in a connected HPC cluster's storage.
          self.status = {}
  
          self.builtin = ['minimum','maximum',
                          'nop', 'mux', 'join', 'verify']
  
          # We set 'design' and 'loglevel' directly in the config dictionary
          # because of a chicken-and-egg problem: self.set() relies on the logger,
          # but the logger relies on these values.
          self.cfg['design']['value'] = design
          if loglevel:
              self.cfg['option']['loglevel']['value'] = loglevel
  
          self._init_logger()
  
          self._loaded_modules = {
              'flows': [],
              'pdks': [],
              'libs': [],
              'checklists': []
          }
  
      ###########################################################################
      @property
      def design(self):
          '''Design name of chip object.
  
          This is an immutable property.'''
          return self.get('design')
  
      ###########################################################################
      def _init_logger(self, step=None, index=None, in_run=False):
  
          self.logger = logging.getLogger(uuid.uuid4().hex)
  
          # Don't propagate log messages to "root" handler (we get duplicate
          # messages without this)
          # TODO: this prevents us from being able to capture logs with pytest:
          # we should revisit it
          self.logger.propagate = False
  
          loglevel = self.get('option', 'loglevel')
  
          if loglevel=='DEBUG':
              prefix = '| %(levelname)-7s | %(funcName)-10s | %(lineno)-4s'
          else:
              prefix = '| %(levelname)-7s'
  
          if in_run:
              flow = self.get('option', 'flow')
  
              # Figure out how wide to make step and index fields
              max_step_len = 2
              max_index_len = 2
              for future_step in self.getkeys('flowgraph', flow):
                  max_step_len = max(len(future_step) + 1, max_step_len)
                  for future_index in self.getkeys('flowgraph', flow, future_step):
                      max_index_len = max(len(future_index) + 1, max_index_len)
  
              jobname = self.get('option', 'jobname')
  
              if step is None:
                  step = '-' * max(max_step_len // 4, 1)
              if index is None:
                  index = '-' * max(max_index_len // 4, 1)
  
              run_info = f'%s  | %-{max_step_len}s | %-{max_index_len}s' % (jobname, step, index)
              logformat = ' | '.join([prefix, run_info, '%(message)s'])
          else:
              logformat = ' | '.join([prefix, '%(message)s'])
  
          handler = logging.StreamHandler()
          formatter = logging.Formatter(logformat)
  
          handler.setFormatter(formatter)
  
          # Clear any existing handlers so we don't end up with duplicate messages
          # if repeat calls to _init_logger are made
          if len(self.logger.handlers
  
  [... the rest is omitted ...]
files: siliconcompiler/core.py
files: # Copyright 2020 Silicon Compiler Authors. All Rights Reserved.
  
  from siliconcompiler import utils
  
  import re
  import os
  import sys
  import copy as pycopy
  import json
  
  SCHEMA_VERSION = '0.9.0'
  
  #############################################################################
  # PARAM DEFINITION
  #############################################################################
  
  def scparam(cfg,
              keypath,
              sctype=None,
              require=None,
              defvalue=None,
              scope='job',
              copy='false',
              lock='false',
              hashalgo='sha256',
              signature=None,
              notes=None,
              unit=None,
              shorthelp=None,
              switch=None,
              example=None,
              schelp=None):
  
      # 1. decend keypath until done
      # 2. create key if missing
      # 3. populate leaf cell when keypath empty
      if keypath:
          key = keypath[0]
          keypath.pop(0)
          if key not in cfg.keys():
              cfg[key] = {}
          scparam(cfg[key],
                  keypath,
                  sctype=sctype,
                  scope=scope,
                  require=require,
                  defvalue=defvalue,
                  copy=copy,
                  lock=lock,
                  hashalgo=hashalgo,
                  signature=signature,
                  notes=notes,
                  unit=unit,
                  shorthelp=shorthelp,
                  switch=switch,
                  example=example,
                  schelp=schelp)
      else:
  
          # removing leading spaces as if schelp were a docstring
          schelp = utils.trim(schelp)
  
          # setting valus based on types
          # note (bools are never lists)
          if re.match(r'bool',sctype):
              require = 'all'
              if defvalue is None:
                  defvalue = 'false'
          if re.match(r'\[',sctype) and signature is None:
              signature = []
          if re.match(r'\[',sctype) and defvalue is None:
              defvalue = []
  
          # mandatory for all
          cfg['defvalue'] = defvalue
          cfg['value'] = pycopy.copy(defvalue)
          cfg['type'] = sctype
          cfg['scope'] = scope
          cfg['require'] = require
          cfg['lock'] = lock
          cfg['switch'] = switch
          cfg['shorthelp'] = shorthelp
          cfg['example'] = example
          cfg['help'] = schelp
          cfg['signature'] = signature
          cfg['notes'] = notes
  
          # unit for floats/ints
          if unit is not None:
              cfg['unit'] = unit
  
          # file only values
          if re.search(r'file',sctype):
              cfg['hashalgo'] = hashalgo
              cfg['copy'] = copy
              cfg['filehash'] = []
              cfg['date'] = []
              cfg['author'] = []
  
  
  #############################################################################
  # CHIP CONFIGURATION
  #############################################################################
  
  def schema_cfg():
      '''Method for defining Chip configuration schema
      All the keys defined in this dictionary are reserved words.
      '''
  
      # SC version number (bump on every non trivial change)
      # Version number following semver standard.
      # Software version syncs with SC releases (from _metadata)
  
      SCHEMA_VERSION = '0.8.0'
  
      # Basic schema setup
      cfg = {}
  
      # Place holder dictionaries updated by core methods()
      cfg['history'] = {}
      cfg['library'] = {}
  
      scparam(cfg,['schemaversion'],
              sctype='str',
              scope='global',
              defvalue=SCHEMA_VERSION,
              require='all',
              shorthelp="Schema version number",
              lock='true',
              switch="-schemaversion <str>",
              example=["api: chip.get('schemaversion')"],
              schelp="""SiliconCompiler schema version number.""")
  
      # Design topmodule/entrypoint
      scparam(cfg,['design'],
              sctype='str',
              scope='global',
              require='all',
              shorthelp="Design top module name",
              switch="-design <str>",
              example=["cli: -design hello_world",
                      "api: chip.set('design', 'hello_world')"],
              schelp="""Name of the top level module or library. Required for all
              chip objects.""")
  
      # input/output
      io = {'input': ['Input','true'],
            'output': ['Output','false']
      }
  
      filetype = 'default'
      for item, val in io.items():
          scparam(cfg,[item, filetype],
                  sctype='[file]',
                  copy=f"{val[1]}",
                  shorthelp=f"{val[0]} files",
                  switch=f"-{item} 'filetype <file>'",
                  example=[
                      f"cli: -{item} 'verilog hello_world.v'",
                      f"api: chip.set({item},'verilog','hello_world.v')"],
                  schelp=f"""
                  List of {item} files specifed by type. The filetype name must
                  align with the parameter names within the flow and tool setup
                  scripts. Examples of acceptable file types include python, c,
                  systemc, verilog, vhdl, netlist, def, gds, gerber, saif, sdc,
                  saif, vcd, spef, sdf.""")
  
      # Inputs and constraints
      cfg = schema_constraint(cfg)
  
      # Options
      cfg = schema_option(cfg)
      cfg = schema_arg(cfg)
      cfg = schema_unit(cfg)
  
      # Technology configuration
      cfg = schema_fpga(cfg)
      cfg = schema_asic(cfg)
      cfg = schema_pdk(cfg)
  
      # Flows
      cfg = schema_tool(cfg)
      cfg = schema_flowgraph(cfg)
  
      # Metrics
      cfg = schema_checklist(cfg)
      cfg = schema_metric(cfg)
      cfg = schema_record(cfg)
  
      # Modeling
      cfg = schema_model(cfg)
  
      # Datasheeet
      cfg = schema_datasheet(cfg)
  
      # Packaging
     
  
  [... the rest is omitted ...]
files: siliconcompiler/schema.py
files: # Copyright 2020 Silicon Compiler Authors. All Rights Reserved.
  
  from siliconcompiler import utils
  
  import re
  import os
  import sys
  import copy as pycopy
  import json
  
  SCHEMA_VERSION = '0.9.0'
  
  #############################################################################
  # PARAM DEFINITION
  #############################################################################
  
  def scparam(cfg,
              keypath,
              sctype=None,
              require=None,
              defvalue=None,
              scope='job',
              copy='false',
              lock='false',
              hashalgo='sha256',
              signature=None,
              notes=None,
              unit=None,
              shorthelp=None,
              switch=None,
              example=None,
              schelp=None):
  
      # 1. decend keypath until done
      # 2. create key if missing
      # 3. populate leaf cell when keypath empty
      if keypath:
          key = keypath[0]
          keypath.pop(0)
          if key not in cfg.keys():
              cfg[key] = {}
          scparam(cfg[key],
                  keypath,
                  sctype=sctype,
                  scope=scope,
                  require=require,
                  defvalue=defvalue,
                  copy=copy,
                  lock=lock,
                  hashalgo=hashalgo,
                  signature=signature,
                  notes=notes,
                  unit=unit,
                  shorthelp=shorthelp,
                  switch=switch,
                  example=example,
                  schelp=schelp)
      else:
  
          # removing leading spaces as if schelp were a docstring
          schelp = utils.trim(schelp)
  
          # setting valus based on types
          # note (bools are never lists)
          if re.match(r'bool',sctype):
              require = 'all'
              if defvalue is None:
                  defvalue = 'false'
          if re.match(r'\[',sctype) and signature is None:
              signature = []
          if re.match(r'\[',sctype) and defvalue is None:
              defvalue = []
  
          # mandatory for all
          cfg['defvalue'] = defvalue
          cfg['value'] = pycopy.copy(defvalue)
          cfg['type'] = sctype
          cfg['scope'] = scope
          cfg['require'] = require
          cfg['lock'] = lock
          cfg['switch'] = switch
          cfg['shorthelp'] = shorthelp
          cfg['example'] = example
          cfg['help'] = schelp
          cfg['signature'] = signature
          cfg['notes'] = notes
  
          # unit for floats/ints
          if unit is not None:
              cfg['unit'] = unit
  
          # file only values
          if re.search(r'file',sctype):
              cfg['hashalgo'] = hashalgo
              cfg['copy'] = copy
              cfg['filehash'] = []
              cfg['date'] = []
              cfg['author'] = []
  
  
  #############################################################################
  # CHIP CONFIGURATION
  #############################################################################
  
  def schema_cfg():
      '''Method for defining Chip configuration schema
      All the keys defined in this dictionary are reserved words.
      '''
  
      # SC version number (bump on every non trivial change)
      # Version number following semver standard.
      # Software version syncs with SC releases (from _metadata)
  
      SCHEMA_VERSION = '0.8.0'
  
      # Basic schema setup
      cfg = {}
  
      # Place holder dictionaries updated by core methods()
      cfg['history'] = {}
      cfg['library'] = {}
  
      scparam(cfg,['schemaversion'],
              sctype='str',
              scope='global',
              defvalue=SCHEMA_VERSION,
              require='all',
              shorthelp="Schema version number",
              lock='true',
              switch="-schemaversion <str>",
              example=["api: chip.get('schemaversion')"],
              schelp="""SiliconCompiler schema version number.""")
  
      # Design topmodule/entrypoint
      scparam(cfg,['design'],
              sctype='str',
              scope='global',
              require='all',
              shorthelp="Design top module name",
              switch="-design <str>",
              example=["cli: -design hello_world",
                      "api: chip.set('design', 'hello_world')"],
              schelp="""Name of the top level module or library. Required for all
              chip objects.""")
  
      # input/output
      io = {'input': ['Input','true'],
            'output': ['Output','false']
      }
  
      filetype = 'default'
      for item, val in io.items():
          scparam(cfg,[item, filetype],
                  sctype='[file]',
                  copy=f"{val[1]}",
                  shorthelp=f"{val[0]} files",
                  switch=f"-{item} 'filetype <file>'",
                  example=[
                      f"cli: -{item} 'verilog hello_world.v'",
                      f"api: chip.set({item},'verilog','hello_world.v')"],
                  schelp=f"""
                  List of {item} files specifed by type. The filetype name must
                  align with the parameter names within the flow and tool setup
                  scripts. Examples of acceptable file types include python, c,
                  systemc, verilog, vhdl, netlist, def, gds, gerber, saif, sdc,
                  saif, vcd, spef, sdf.""")
  
      # Inputs and constraints
      cfg = schema_constraint(cfg)
  
      # Options
      cfg = schema_option(cfg)
      cfg = schema_arg(cfg)
      cfg = schema_unit(cfg)
  
      # Technology configuration
      cfg = schema_fpga(cfg)
      cfg = schema_asic(cfg)
      cfg = schema_pdk(cfg)
  
      # Flows
      cfg = schema_tool(cfg)
      cfg = schema_flowgraph(cfg)
  
      # Metrics
      cfg = schema_checklist(cfg)
      cfg = schema_metric(cfg)
      cfg = schema_record(cfg)
  
      # Modeling
      cfg = schema_model(cfg)
  
      # Datasheeet
      cfg = schema_datasheet(cfg)
  
      # Packaging
     
  
  [... the rest is omitted ...]
files: siliconcompiler/schema.py
files: {
      "arg": {
          "flow": {
              "default": {
                  "defvalue": [],
                  "example": [
                      "cli: -arg_flow 'n 100'",
                      "api: chip.set('arg','flow','n', 100)"
                  ],
                  "help": "Parameter passed in as key/value pair to the flow target\nreferenced in the load_flow() API call. See the target flow\nfor specific guidelines regarding configuration parameters.",
                  "lock": "false",
                  "notes": null,
                  "require": null,
                  "scope": "scratch",
                  "shorthelp": "ARG: Flow argument",
                  "signature": [],
                  "switch": "-arg_flow 'key <str>'",
                  "type": "[str]",
                  "value": []
              }
          },
          "index": {
              "defvalue": null,
              "example": [
                  "cli: -arg_index 0",
                  "api: chip.set('arg','index','0')"
              ],
              "help": "Dynamic parameter passed in by the sc runtime as an argument to\na runtime task. The parameter enables configuration code\n(usually TCL) to use control flow that depend on the current\n'index'. The parameter is used the run() function and\nis not intended for external use.",
              "lock": "false",
              "notes": null,
              "require": null,
              "scope": "scratch",
              "shorthelp": "ARG: Index argument",
              "signature": null,
              "switch": "-arg_index <str>",
              "type": "str",
              "value": null
          },
          "pdk": {
              "default": {
                  "defvalue": [],
                  "example": [
                      "cli: -arg_pdk 'mimcap true'",
                      "api: chip.set('arg','pdk','mimcap','true')"
                  ],
                  "help": "Parameter passed in as key/value pair to the technology target\nreferenced in the load_pdk() API call. See the target technology\nfor specific guidelines regarding configuration parameters.",
                  "lock": "false",
                  "notes": null,
                  "require": null,
                  "scope": "scratch",
                  "shorthelp": "ARG: PDK argument",
                  "signature": [],
                  "switch": "-arg_pdk 'key <str>",
                  "type": "[str]",
                  "value": []
              }
          },
          "step": {
              "defvalue": null,
              "example": [
                  "cli: -arg_step 'route'",
                  "api: chip.set('arg', 'step', 'route')"
              ],
              "help": "Dynamic parameter passed in by the sc runtime as an argument to\na runtime task. The parameter enables configuration code\n(usually TCL) to use control flow that depend on the current\n'step'. The parameter is used the run() function and\nis not intended for external use.",
              "lock": "false",
              "notes": null,
              "require": null,
              "scope": "scratch",
              "shorthelp": "ARG: Step argument",
              "signature": null,
              "switch": "-arg_step <str>",
              "type": "str",
              "value": null
          }
      },
      "asic": {
          "aspectratio": {
              "defvalue": null,
              "example": [
                  "cli: -asic_aspectratio 2.0",
                  "api: chip.set('asic', 'aspectratio', '2.0')"
              ],
              "help": "Height to width ratio of the block for automated floor-planning.\nValues below 0.1 and above 10 should be avoided as they will likely fail\nto converge during placement and routing. The ideal aspect ratio for\nmost designs is 1. This value is only used when no diearea or floorplan\nis supplied.",
              "lock": "false",
              "notes": null,
              "require": null,
              "scope": "job",
              "shorthelp": "ASIC: block aspect ratio",
              "signature": null,
              "switch": "-asic_aspectratio <float>",
              "type": "float",
              "value": null
          },
          "cells": {
              "antenna": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_antenna '*eco*'",
                      "api: chip.set('asic','cells',antenna,'*eco*')"
                  ],
                  "help": "List of cells grouped by a property that can be accessed\ndirectly by the designer and tools. The example below shows how\nall cells containing the string 'eco' could be marked as dont use\nfor the tool.",
                  "lock": "false",
                  "notes": null,
                  "require": null,
                  "scope": "job",
                  "shorthelp": "ASIC: antenna cell list",
                  "signature": [],
                  "switch": "-asic_cells_antenna '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "buf": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_buf '*eco*'",
                      "api: chip.set('asic','cells',buf,'*eco*')"
                  ],
                  "help": "List of cells grouped by a property that can be accessed\ndirectly by the designer and tools. The example below shows how\nall cells containing the string 'eco' could be marked as dont use\nfor the tool.",
                  "lock": "false",
                  "notes": null,
                  "require": null,
                  "scope": "job",
                  "shorthelp": "ASIC: buf cell list",
                  "signature": [],
                  "switch": "-asic_cells_buf '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "clkbuf": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_clkbuf '*eco*'",
                      "api: chip.set('asic','cells',clkbuf,'*eco*')"
                  ],
                  "
  
  [... the rest is omitted ...]
files: tests/core/data/defaults.json
files: {
      "arg": {
          "flow": {
              "default": {
                  "defvalue": [],
                  "example": [
                      "cli: -arg_flow 'n 100'",
                      "api: chip.set('arg','flow','n', 100)"
                  ],
                  "help": "Parameter passed in as key/value pair to the flow target\nreferenced in the load_flow() API call. See the target flow\nfor specific guidelines regarding configuration parameters.",
                  "lock": "false",
                  "notes": null,
                  "require": null,
                  "scope": "scratch",
                  "shorthelp": "ARG: Flow argument",
                  "signature": [],
                  "switch": "-arg_flow 'key <str>'",
                  "type": "[str]",
                  "value": []
              }
          },
          "index": {
              "defvalue": null,
              "example": [
                  "cli: -arg_index 0",
                  "api: chip.set('arg','index','0')"
              ],
              "help": "Dynamic parameter passed in by the sc runtime as an argument to\na runtime task. The parameter enables configuration code\n(usually TCL) to use control flow that depend on the current\n'index'. The parameter is used the run() function and\nis not intended for external use.",
              "lock": "false",
              "notes": null,
              "require": null,
              "scope": "scratch",
              "shorthelp": "ARG: Index argument",
              "signature": null,
              "switch": "-arg_index <str>",
              "type": "str",
              "value": null
          },
          "pdk": {
              "default": {
                  "defvalue": [],
                  "example": [
                      "cli: -arg_pdk 'mimcap true'",
                      "api: chip.set('arg','pdk','mimcap','true')"
                  ],
                  "help": "Parameter passed in as key/value pair to the technology target\nreferenced in the load_pdk() API call. See the target technology\nfor specific guidelines regarding configuration parameters.",
                  "lock": "false",
                  "notes": null,
                  "require": null,
                  "scope": "scratch",
                  "shorthelp": "ARG: PDK argument",
                  "signature": [],
                  "switch": "-arg_pdk 'key <str>",
                  "type": "[str]",
                  "value": []
              }
          },
          "step": {
              "defvalue": null,
              "example": [
                  "cli: -arg_step 'route'",
                  "api: chip.set('arg', 'step', 'route')"
              ],
              "help": "Dynamic parameter passed in by the sc runtime as an argument to\na runtime task. The parameter enables configuration code\n(usually TCL) to use control flow that depend on the current\n'step'. The parameter is used the run() function and\nis not intended for external use.",
              "lock": "false",
              "notes": null,
              "require": null,
              "scope": "scratch",
              "shorthelp": "ARG: Step argument",
              "signature": null,
              "switch": "-arg_step <str>",
              "type": "str",
              "value": null
          }
      },
      "asic": {
          "aspectratio": {
              "defvalue": null,
              "example": [
                  "cli: -asic_aspectratio 2.0",
                  "api: chip.set('asic', 'aspectratio', '2.0')"
              ],
              "help": "Height to width ratio of the block for automated floor-planning.\nValues below 0.1 and above 10 should be avoided as they will likely fail\nto converge during placement and routing. The ideal aspect ratio for\nmost designs is 1. This value is only used when no diearea or floorplan\nis supplied.",
              "lock": "false",
              "notes": null,
              "require": null,
              "scope": "job",
              "shorthelp": "ASIC: block aspect ratio",
              "signature": null,
              "switch": "-asic_aspectratio <float>",
              "type": "float",
              "value": null
          },
          "cells": {
              "antenna": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_antenna '*eco*'",
                      "api: chip.set('asic','cells',antenna,'*eco*')"
                  ],
                  "help": "List of cells grouped by a property that can be accessed\ndirectly by the designer and tools. The example below shows how\nall cells containing the string 'eco' could be marked as dont use\nfor the tool.",
                  "lock": "false",
                  "notes": null,
                  "require": null,
                  "scope": "job",
                  "shorthelp": "ASIC: antenna cell list",
                  "signature": [],
                  "switch": "-asic_cells_antenna '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "buf": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_buf '*eco*'",
                      "api: chip.set('asic','cells',buf,'*eco*')"
                  ],
                  "help": "List of cells grouped by a property that can be accessed\ndirectly by the designer and tools. The example below shows how\nall cells containing the string 'eco' could be marked as dont use\nfor the tool.",
                  "lock": "false",
                  "notes": null,
                  "require": null,
                  "scope": "job",
                  "shorthelp": "ASIC: buf cell list",
                  "signature": [],
                  "switch": "-asic_cells_buf '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "clkbuf": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_clkbuf '*eco*'",
                      "api: chip.set('asic','cells',clkbuf,'*eco*')"
                  ],
                  "
  
  [... the rest is omitted ...]
files: tests/core/data/defaults.json