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) > 0:
              self.logger.handlers.clear()
  
          self.logger.addHandler(handler)
          self.logger.setLevel(loglevel)
  
      ###########################################################################
      def _deinit_logger(self):
          self.logger = None
  
      ###########################################################################
      def _get_switches(self, *keypath):
          '''Helper function for parsing switches and metavars for a keypath.'''
          #Switch field fully describes switch format
          switch = self.get(*keypath, field='switch')
  
          if switch is None:
              switches = []
          elif isinstance(switch, list):
              switches = switch
          else:
              switches = [switch]
          switchstrs = []
  
          # parse out switch from metavar
          # TODO: should we validate that metavar matches for each switch?
          for switch in switches:
              switchmatch = re.match(r'(-[\w_]+)\s+(.*)', switch)
              gccmatch = re.match(r'(-[\w_]+)(.*)', switch)
              plusmatch = re.match(r'(\+[\w_\+]+)(.*)', switch)
  
              if switchmatch:
                  switchstr = switchmatch.group(1)
                  metavar = switchmatch.group(2)
              elif gccmatch:
                  switchstr = gccmatch.group(1)
                  metavar = gccmatch.group(2)
              elif plusmatch:
                  switchstr = plusmatch.group(1)
                  metavar = plusmatch.group(2)
              switchstrs.append(switchstr)
  
          return switchstrs, metavar
  
      ###########################################################################
      def create_cmdline(self, progname, description=None, switchlist=None, input_map=None):
          """Creates an SC command line interface.
  
          Exposes parameters in the SC schema as command line switches,
          simplifying creation of SC apps with a restricted set of schema
          parameters exposed at the command line. The order of command
          line switch settings parsed from the command line is as follows:
  
           1. loglevel
           2. fpga_partname
           3. load_target('target')
           4. read_manifest([cfg])
           5. all other switches
  
          The cmdline interface is implemented using the Python argparse package
          and the following use restrictions apply.
  
          * Help is accessed with the '-h' switch.
          * Arguments that include spaces must be enclosed with double quotes.
          * List parameters are entered individually. (ie. -y libdir1 -y libdir2)
          * For parameters with Boolean types, the switch implies "true".
          * Special characters (such as '-') must be enclosed in double quotes.
          * Compiler compatible switches include: -D, -I, -O{0,1,2,3}
          * Verilog legacy switch formats are supported: +libext+, +incdir+
  
          Args:
              progname (str): Name of program to be executed.
              description (str): Short program description.
              switchlist (list of str): List of SC parameter switches to expose
                  at the command line. By default all SC schema switches are
                  available. Parameter switches should be entered based on the
                  parameter 'switch' field in the schema. For parameters with
                  multiple switches, both will be accepted if any one is included
                  in this list.
              input_map (dict of str): Dictionary mapping file extensions to input
                  filetypes. This is used to automatically assign positional
                  source arguments to ['input', ...] keypaths based on their file
                  extension. If None, the CLI will not accept positional source
                  arguments.
  
          Examples:
              >>> chip.create_cmdline(progname='sc-show',switchlist=['-input','-cfg'])
              Creates a command line interface for 'sc-show' app.
  
              >>> chip.create_cmdline(progname='sc', input_map={'v': 'verilog'})
              All sources ending in .v will be stored in ['input', 'verilog']
          """
  
          # Argparse
          parser = argparse.ArgumentParser(prog=progname,
                                           prefix_chars='-+',
                                           formatter_class=argparse.RawDescriptionHelpFormatter,
                                           description=description)
  
          # Get all keys from global dictionary or override at command line
          allkeys = self.getkeys()
  
          # Iterate over all keys to add parser arguments
          for keypath in allkeys:
              #Fetch fields from leaf cell
              helpstr = self.get(*keypath, field='shorthelp')
              typestr = self.get(*keypath, field='type')
  
              # argparse 'dest' must be a string, so join keypath with commas
              dest = '_'.join(keypath)
  
              switchstrs, metavar = self._get_switches(*keypath)
  
              # Three switch types (bool, list, scalar)
              if not switchlist or any(switch in switchlist for switch in switchstrs):
                  if typestr == 'bool':
                      parser.add_argument(*switchstrs,
                                          nargs='?',
                                          metavar=metavar,
                                          dest=dest,
                                          const='true',
                                          help=helpstr,
                                          default=argparse.SUPPRESS)
                  #list type arguments
                  elif re.match(r'\[', typestr):
                      #all the rest
                      parser.add_argument(*switchstrs,
                                          metavar=metavar,
                                          dest=dest,
                                          action='append',
                                          help=helpstr,
                                          default=argparse.SUPPRESS)
                  else:
                      #all the rest
                      parser.add_argument(*switchstrs,
                                          metavar=metavar,
                                          dest=dest,
                                          help=helpstr,
                                          default=argparse.SUPPRESS)
  
          if input_map is not None:
              parser.add_argument('source',
                                  nargs='*',
                                  help='Input files with filetype inferred by extension')
  
          #Preprocess sys.argv to enable linux commandline switch formats
          #(gcc, verilator, etc)
          scargs = []
  
          # Iterate from index 1, otherwise we end up with script name as a
          # 'source' positional argument
          for item in sys.argv[1:]:
              #Split switches with one character and a number after (O0,O1
  
  [... 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) > 0:
              self.logger.handlers.clear()
  
          self.logger.addHandler(handler)
          self.logger.setLevel(loglevel)
  
      ###########################################################################
      def _deinit_logger(self):
          self.logger = None
  
      ###########################################################################
      def _get_switches(self, *keypath):
          '''Helper function for parsing switches and metavars for a keypath.'''
          #Switch field fully describes switch format
          switch = self.get(*keypath, field='switch')
  
          if switch is None:
              switches = []
          elif isinstance(switch, list):
              switches = switch
          else:
              switches = [switch]
          switchstrs = []
  
          # parse out switch from metavar
          # TODO: should we validate that metavar matches for each switch?
          for switch in switches:
              switchmatch = re.match(r'(-[\w_]+)\s+(.*)', switch)
              gccmatch = re.match(r'(-[\w_]+)(.*)', switch)
              plusmatch = re.match(r'(\+[\w_\+]+)(.*)', switch)
  
              if switchmatch:
                  switchstr = switchmatch.group(1)
                  metavar = switchmatch.group(2)
              elif gccmatch:
                  switchstr = gccmatch.group(1)
                  metavar = gccmatch.group(2)
              elif plusmatch:
                  switchstr = plusmatch.group(1)
                  metavar = plusmatch.group(2)
              switchstrs.append(switchstr)
  
          return switchstrs, metavar
  
      ###########################################################################
      def create_cmdline(self, progname, description=None, switchlist=None, input_map=None):
          """Creates an SC command line interface.
  
          Exposes parameters in the SC schema as command line switches,
          simplifying creation of SC apps with a restricted set of schema
          parameters exposed at the command line. The order of command
          line switch settings parsed from the command line is as follows:
  
           1. loglevel
           2. fpga_partname
           3. load_target('target')
           4. read_manifest([cfg])
           5. all other switches
  
          The cmdline interface is implemented using the Python argparse package
          and the following use restrictions apply.
  
          * Help is accessed with the '-h' switch.
          * Arguments that include spaces must be enclosed with double quotes.
          * List parameters are entered individually. (ie. -y libdir1 -y libdir2)
          * For parameters with Boolean types, the switch implies "true".
          * Special characters (such as '-') must be enclosed in double quotes.
          * Compiler compatible switches include: -D, -I, -O{0,1,2,3}
          * Verilog legacy switch formats are supported: +libext+, +incdir+
  
          Args:
              progname (str): Name of program to be executed.
              description (str): Short program description.
              switchlist (list of str): List of SC parameter switches to expose
                  at the command line. By default all SC schema switches are
                  available. Parameter switches should be entered based on the
                  parameter 'switch' field in the schema. For parameters with
                  multiple switches, both will be accepted if any one is included
                  in this list.
              input_map (dict of str): Dictionary mapping file extensions to input
                  filetypes. This is used to automatically assign positional
                  source arguments to ['input', ...] keypaths based on their file
                  extension. If None, the CLI will not accept positional source
                  arguments.
  
          Examples:
              >>> chip.create_cmdline(progname='sc-show',switchlist=['-input','-cfg'])
              Creates a command line interface for 'sc-show' app.
  
              >>> chip.create_cmdline(progname='sc', input_map={'v': 'verilog'})
              All sources ending in .v will be stored in ['input', 'verilog']
          """
  
          # Argparse
          parser = argparse.ArgumentParser(prog=progname,
                                           prefix_chars='-+',
                                           formatter_class=argparse.RawDescriptionHelpFormatter,
                                           description=description)
  
          # Get all keys from global dictionary or override at command line
          allkeys = self.getkeys()
  
          # Iterate over all keys to add parser arguments
          for keypath in allkeys:
              #Fetch fields from leaf cell
              helpstr = self.get(*keypath, field='shorthelp')
              typestr = self.get(*keypath, field='type')
  
              # argparse 'dest' must be a string, so join keypath with commas
              dest = '_'.join(keypath)
  
              switchstrs, metavar = self._get_switches(*keypath)
  
              # Three switch types (bool, list, scalar)
              if not switchlist or any(switch in switchlist for switch in switchstrs):
                  if typestr == 'bool':
                      parser.add_argument(*switchstrs,
                                          nargs='?',
                                          metavar=metavar,
                                          dest=dest,
                                          const='true',
                                          help=helpstr,
                                          default=argparse.SUPPRESS)
                  #list type arguments
                  elif re.match(r'\[', typestr):
                      #all the rest
                      parser.add_argument(*switchstrs,
                                          metavar=metavar,
                                          dest=dest,
                                          action='append',
                                          help=helpstr,
                                          default=argparse.SUPPRESS)
                  else:
                      #all the rest
                      parser.add_argument(*switchstrs,
                                          metavar=metavar,
                                          dest=dest,
                                          help=helpstr,
                                          default=argparse.SUPPRESS)
  
          if input_map is not None:
              parser.add_argument('source',
                                  nargs='*',
                                  help='Input files with filetype inferred by extension')
  
          #Preprocess sys.argv to enable linux commandline switch formats
          #(gcc, verilator, etc)
          scargs = []
  
          # Iterate from index 1, otherwise we end up with script name as a
          # 'source' positional argument
          for item in sys.argv[1:]:
              #Split switches with one character and a number after (O0,O1
  
  [... 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
      cfg = schema_package(cfg)
  
      return cfg
  
  ###############################################################################
  # FPGA
  ###############################################################################
  
  def schema_fpga(cfg):
      ''' FPGA configuration
      '''
  
      scparam(cfg,['fpga', 'arch'],
              sctype='[file]',
              copy='true',
              shorthelp="FPGA: architecture file",
              switch="-fpga_arch <file>",
              example=["cli: -fpga_arch myfpga.xml",
                       "api:  chip.set('fpga', 'arch', 'myfpga.xml')"],
              schelp=""" Architecture definition file for FPGA place and route
              tool. For the VPR tool, the file is a required XML based description,
              allowing targeting a large number of virtual and commercial
              architectures. For most commercial tools, the fpga part name provides
              enough information to enable compilation and the 'arch' parameter is
              optional.""")
  
      scparam(cfg,['fpga', 'vendor'],
              sctype='str',
              shorthelp="FPGA: vendor name",
              switch="-fpga_vendor <str>",
              example=["cli: -fpga_vendor acme",
                      "api:  chip.set('fpga', 'vendor', 'acme')"],
              schelp="""
              Name of the FPGA vendor. The parameter is used to check part
              name and to select the eda tool flow in case 'edaflow' is
              unspecified.""")
  
      scparam(cfg,['fpga', 'partname'],
              sctype='str',
              require='fpga',
              shorthelp="FPGA: part name",
              switch="-fpga_partname <str>",
              example=["cli: -fpga_partname fpga64k",
                       "api:  chip.set('fpga', 'partname', 'fpga64k')"],
              schelp="""
              Complete part name used as a device target by the FPGA compilation
              tool. The part name must be an exact string match to the partname
              hard coded within the FPGA eda tool.""")
  
      scparam(cfg,['fpga', 'board'],
              sctype='str',
              shorthelp="FPGA: board name",
              switch="-fpga_board <str>",
              example=["cli: -fpga_board parallella",
                       "api:  chip.set('fpga', 'board', 'parallella')"],
              schelp="""
              Complete board name used as a device target by the FPGA compilation
              tool. The board name must be an exact string match to the partname
              hard coded within the FPGA eda tool. The parameter is optional and can
              be used in place of a partname and pin constraints for some tools.""")
  
      scparam(cfg,['fpga', 'program'],
              sctype='bool',
              shorthelp="FPGA: program enable",
              switch="-fpga_program <bool>",
              example=["cli: -fpga_program",
                       "api:  chip.set('fpga', 'program', True)"],
              schelp="""Specifies that the bitstream should be loaded into an FPGA.""")
  
      scparam(cfg,['fpga', 'flash'],
              sctype='bool',
              shorthelp="FPGA: flash enable",
              switch="-fpga_flash <bool>",
              example=["cli: -fpga_flash",
                       "api:  chip.set('fpga', 'flash', True)"],
              schelp="""Specifies that the bitstream should be flashed in the board/device.
              The default is to load the bitstream into volatile memory (SRAM).""")
  
      return cfg
  
  ###############################################################################
  # PDK
  ###############################################################################
  
  def schema_pdk(cfg, stackup='default'):
      ''' Process design kit configuration
      '''
  
      tool = 'default'
      filetype = 'default'
      pdkname = 'default'
  
      scparam(cfg, ['pdk', pdkname, 'foundry'],
              sctype='str',
              scope='global',
              require="asic",
              shorthelp="PDK: foundry name",
              switch="-pdk_foundry 'pdkname <str>'",
              example=["cli: -pdk_foundry 'asap7 virtual'",
                      "api:  chip.set('pdk', 'asap7', 'foundry', 'virtual')"],
              schelp="""
              Name of foundry corporation. Examples include intel, gf, tsmc,
              samsung, skywater, virtual. The \'virtual\' keyword is reserved for
              simulated non-manufacturable processes.""")
  
      scparam(cfg, ['pdk', pdkname, 'node'],
              sctype='float',
              scope='global',
              require="asic",
              shorthelp="PDK: process node",
              switch="-pdk_node 'pdkname <float>'",
              example=["cli: -pdk_node 'asap7 130'",
                      "api:  chip.set('pdk', 'asap7', 'node', 130)"],
              schelp="""
              Approximate relative minimum dimension of the process target specified
              in nanometers. The parameter is required for flows and tools that
              leverage the value to drive technology dependent synthesis and APR
              optimization. Node examples include 180, 130, 90, 65, 45, 32, 22 14,
              10, 7, 5, 3.""")
  
      scparam(cfg, ['pdk', pdkname, 'version'],
              sctype='str',
              scope='global',
              shorthelp="PDK: version",
              switch="-pdk_version 'pdkname <str>'",
              example=["cli: -pdk_version 'asap7 1.0'",
                      "api:  chip.set('pdk', 'asap7', 'version', '1.0')"],
              schelp="""
              Alphanumeric string specifying the version of the PDK. Verification of
              correct PDK and IP versions is a hard ASIC tapeout require in all
              commercial foundries. The version number can be used for design manifest
              tracking and tapeout checklists.""")
  
  
  
  [... 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
      cfg = schema_package(cfg)
  
      return cfg
  
  ###############################################################################
  # FPGA
  ###############################################################################
  
  def schema_fpga(cfg):
      ''' FPGA configuration
      '''
  
      scparam(cfg,['fpga', 'arch'],
              sctype='[file]',
              copy='true',
              shorthelp="FPGA: architecture file",
              switch="-fpga_arch <file>",
              example=["cli: -fpga_arch myfpga.xml",
                       "api:  chip.set('fpga', 'arch', 'myfpga.xml')"],
              schelp=""" Architecture definition file for FPGA place and route
              tool. For the VPR tool, the file is a required XML based description,
              allowing targeting a large number of virtual and commercial
              architectures. For most commercial tools, the fpga part name provides
              enough information to enable compilation and the 'arch' parameter is
              optional.""")
  
      scparam(cfg,['fpga', 'vendor'],
              sctype='str',
              shorthelp="FPGA: vendor name",
              switch="-fpga_vendor <str>",
              example=["cli: -fpga_vendor acme",
                      "api:  chip.set('fpga', 'vendor', 'acme')"],
              schelp="""
              Name of the FPGA vendor. The parameter is used to check part
              name and to select the eda tool flow in case 'edaflow' is
              unspecified.""")
  
      scparam(cfg,['fpga', 'partname'],
              sctype='str',
              require='fpga',
              shorthelp="FPGA: part name",
              switch="-fpga_partname <str>",
              example=["cli: -fpga_partname fpga64k",
                       "api:  chip.set('fpga', 'partname', 'fpga64k')"],
              schelp="""
              Complete part name used as a device target by the FPGA compilation
              tool. The part name must be an exact string match to the partname
              hard coded within the FPGA eda tool.""")
  
      scparam(cfg,['fpga', 'board'],
              sctype='str',
              shorthelp="FPGA: board name",
              switch="-fpga_board <str>",
              example=["cli: -fpga_board parallella",
                       "api:  chip.set('fpga', 'board', 'parallella')"],
              schelp="""
              Complete board name used as a device target by the FPGA compilation
              tool. The board name must be an exact string match to the partname
              hard coded within the FPGA eda tool. The parameter is optional and can
              be used in place of a partname and pin constraints for some tools.""")
  
      scparam(cfg,['fpga', 'program'],
              sctype='bool',
              shorthelp="FPGA: program enable",
              switch="-fpga_program <bool>",
              example=["cli: -fpga_program",
                       "api:  chip.set('fpga', 'program', True)"],
              schelp="""Specifies that the bitstream should be loaded into an FPGA.""")
  
      scparam(cfg,['fpga', 'flash'],
              sctype='bool',
              shorthelp="FPGA: flash enable",
              switch="-fpga_flash <bool>",
              example=["cli: -fpga_flash",
                       "api:  chip.set('fpga', 'flash', True)"],
              schelp="""Specifies that the bitstream should be flashed in the board/device.
              The default is to load the bitstream into volatile memory (SRAM).""")
  
      return cfg
  
  ###############################################################################
  # PDK
  ###############################################################################
  
  def schema_pdk(cfg, stackup='default'):
      ''' Process design kit configuration
      '''
  
      tool = 'default'
      filetype = 'default'
      pdkname = 'default'
  
      scparam(cfg, ['pdk', pdkname, 'foundry'],
              sctype='str',
              scope='global',
              require="asic",
              shorthelp="PDK: foundry name",
              switch="-pdk_foundry 'pdkname <str>'",
              example=["cli: -pdk_foundry 'asap7 virtual'",
                      "api:  chip.set('pdk', 'asap7', 'foundry', 'virtual')"],
              schelp="""
              Name of foundry corporation. Examples include intel, gf, tsmc,
              samsung, skywater, virtual. The \'virtual\' keyword is reserved for
              simulated non-manufacturable processes.""")
  
      scparam(cfg, ['pdk', pdkname, 'node'],
              sctype='float',
              scope='global',
              require="asic",
              shorthelp="PDK: process node",
              switch="-pdk_node 'pdkname <float>'",
              example=["cli: -pdk_node 'asap7 130'",
                      "api:  chip.set('pdk', 'asap7', 'node', 130)"],
              schelp="""
              Approximate relative minimum dimension of the process target specified
              in nanometers. The parameter is required for flows and tools that
              leverage the value to drive technology dependent synthesis and APR
              optimization. Node examples include 180, 130, 90, 65, 45, 32, 22 14,
              10, 7, 5, 3.""")
  
      scparam(cfg, ['pdk', pdkname, 'version'],
              sctype='str',
              scope='global',
              shorthelp="PDK: version",
              switch="-pdk_version 'pdkname <str>'",
              example=["cli: -pdk_version 'asap7 1.0'",
                      "api:  chip.set('pdk', 'asap7', 'version', '1.0')"],
              schelp="""
              Alphanumeric string specifying the version of the PDK. Verification of
              correct PDK and IP versions is a hard ASIC tapeout require in all
              commercial foundries. The version number can be used for design manifest
              tracking and tapeout checklists.""")
  
  
  
  [... 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*')"
                  ],
                  "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: clkbuf cell list",
                  "signature": [],
                  "switch": "-asic_cells_clkbuf '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "clkdelay": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_clkdelay '*eco*'",
                      "api: chip.set('asic','cells',clkdelay,'*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: clkdelay cell list",
                  "signature": [],
                  "switch": "-asic_cells_clkdelay '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "clkgate": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_clkgate '*eco*'",
                      "api: chip.set('asic','cells',clkgate,'*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: clkgate cell list",
                  "signature": [],
                  "switch": "-asic_cells_clkgate '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "clkicg": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_clkicg '*eco*'",
                      "api: chip.set('asic','cells',clkicg,'*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: clkicg cell list",
                  "signature": [],
                  "switch": "-asic_cells_clkicg '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "clkinv": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_clkinv '*eco*'",
                      "api: chip.set('asic','cells',clkinv,'*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: clkinv cell list",
                  "signature": [],
                  "switch": "-asic_cells_clkinv '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "clklogic": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_clklogic '*eco*'",
                      "api: chip.set('asic','cells',clklogic,'*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: clklogic cell list",
                  "signature": [],
                  "switch": "-asic_cells_clklogic '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "decap": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_decap '*eco*'",
                      "api: chip.set('asic','cells',decap,'*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: decap cell list",
                  "signature": [],
                  "switch": "-asic_cells_decap '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "delay": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_delay '*eco*'",
                      "api: chip.set('asic','cells',delay,'*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.",
                 
  
  [... 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*')"
                  ],
                  "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: clkbuf cell list",
                  "signature": [],
                  "switch": "-asic_cells_clkbuf '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "clkdelay": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_clkdelay '*eco*'",
                      "api: chip.set('asic','cells',clkdelay,'*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: clkdelay cell list",
                  "signature": [],
                  "switch": "-asic_cells_clkdelay '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "clkgate": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_clkgate '*eco*'",
                      "api: chip.set('asic','cells',clkgate,'*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: clkgate cell list",
                  "signature": [],
                  "switch": "-asic_cells_clkgate '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "clkicg": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_clkicg '*eco*'",
                      "api: chip.set('asic','cells',clkicg,'*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: clkicg cell list",
                  "signature": [],
                  "switch": "-asic_cells_clkicg '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "clkinv": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_clkinv '*eco*'",
                      "api: chip.set('asic','cells',clkinv,'*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: clkinv cell list",
                  "signature": [],
                  "switch": "-asic_cells_clkinv '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "clklogic": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_clklogic '*eco*'",
                      "api: chip.set('asic','cells',clklogic,'*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: clklogic cell list",
                  "signature": [],
                  "switch": "-asic_cells_clklogic '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "decap": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_decap '*eco*'",
                      "api: chip.set('asic','cells',decap,'*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: decap cell list",
                  "signature": [],
                  "switch": "-asic_cells_decap '<str>'",
                  "type": "[str]",
                  "value": []
              },
              "delay": {
                  "defvalue": [],
                  "example": [
                      "cli: -asic_cells_delay '*eco*'",
                      "api: chip.set('asic','cells',delay,'*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.",
                 
  
  [... the rest is omitted ...]
files: tests/core/data/defaults.json