files: # Copyright 2020 Silicon Compiler Authors. All Rights Reserved.
  
  import re
  import os
  import textwrap
  import sys
  
  ###############################################################################
  # CHIP CONFIGURATION
  ###############################################################################
  
  def schema_cfg():
      '''Method for defining Chip configuration schema
      All the keys defined in this dictionary are reserved words.
      '''
  
      cfg = {}
  
      # Flow Setup (from schema_options)
      cfg = schema_flow(cfg, 'default')
  
      # Metric Tracking
      cfg = schema_metrics(cfg, 'goal')
      cfg = schema_metrics(cfg, 'real')    
      
      # Recording design provenance 
      cfg = schema_record(cfg) 
      
      # FPGA Parameters
      cfg = schema_fpga(cfg)
  
      # ASIC Parameters
      cfg = schema_pdk(cfg)
      cfg = schema_asic(cfg) 
      cfg = schema_libs(cfg, 'stdcell')
      cfg = schema_libs(cfg, 'macro')
  
      # Designer's Choice
      cfg = schema_design(cfg)
      cfg = schema_mcmm(cfg)
      
      # Designer Runtime options
      cfg = schema_options(cfg)
  
      # Remote options
      cfg = schema_remote(cfg)
      
      # Run status
      cfg = schema_status(cfg)
      
      return cfg
  
  
  ###############################################################################
  # CHIP LIBRARY 
  ###############################################################################
  def schema_lib():
      pass    
  
  ###############################################################################
  # CHIP LAYOUT
  ###############################################################################
  def schema_layout():
      
      layout = {}
  
      layout = schema_lef(layout)
  
      layout = schema_def(layout)
  
      return layout
  
  ###############################################################################
  # UTILITY FUNCTIONS TIED TO SC SPECIFICATIONS
  ###############################################################################
  
  def schema_path(filename):
      ''' Resolves file paths using SCPATH and resolve environment variables
      starting with $
      '''
  
      #Resolve absolute path usign SCPATH
      #list is read left to right    
      scpaths = str(os.environ['SCPATH']).split(':')
      for searchdir in scpaths:        
          abspath = searchdir + "/" + filename
          if os.path.exists(abspath):
              filename = abspath
              break
      #Replace $ Variables
      varmatch = re.match('^\$(\w+)(.*)', filename)
      if varmatch:
          var = varmatch.group(1)
          varpath = os.getenv(var)
          if varpath is None:
              print("ERROR: Missing environment variable:", var)
              sys.exit()
          relpath = varmatch.group(2)
          filename = varpath + relpath
          
      return filename
              
  def schema_istrue(value):
      ''' Checks schema boolean string and returns Python True/False
      '''
      boolean = value[-1].lower()
      if boolean == "true":
          return True
      else:
          return False
  
  def schema_check(cfg, leafkey, value):
      ''' Checks that leaf cell value agrees with type 
      '''
  
      ok = True
      keyval = "(Key,value) = (" + leafkey +  ",'" + ' '.join(value) + "')"
      if cfg['type'] == 'bool':
          if value[0] not in ('true', 'false'):
              print("ERROR: Value should be boolan.", keyval)
              ok = False
      else:
          for item in value:            
              if cfg['type'] == 'str':
                  ok =  isinstance(item, str)
                  if not ok:
                      print("ERROR: Value should be a string.", keyval)
              elif cfg['type'] == 'num':
                  try:
                      isinstance(float(item), float)
                  except:
                      ok = False
                      print("ERROR: Value should be a number.", keyval)
              elif cfg['type'] == 'file':
                  ok =  os.path.isfile(schema_path(item))
                  if not ok:
                      print("ERROR: File is missing.", keyval)
              elif cfg['type'] == 'dir':
                  ok =  os.path.isdir(schema_path(item))
                  if not ok:
                      print("ERROR: Directory is missing.", keyval)
  
      return ok
  
  
  def schema_reorder_keys(param_help, item):
      ''' Returns a keylist used to access the dictionary based on the 
      cmdline switch argument and the param_help field.
      '''
  
      #Split param help into keys and data based in <>
      m = re.search('(.*?)(<.*)',param_help)
      paramlist = m.group(1).split()
      datalist = m.group(2).split()
      #Split cmdline inputn based on spaces
      itemlist = item.split()
      
      depth = len(paramlist)+1
      args = [None] * depth
  
      #Combine keys from param_help and cmdline field
      j=0
      for i in range(depth-1):
          if paramlist[i].endswith('var'):
              args[i]=itemlist[j]
              j=j+1
          else:
              args[i]=paramlist[i]
  
      #Insert data field as last entry (some are string tuples)
      args[-1] = itemlist[-len(datalist):]
      
      return args
  
      
  ###############################################################################
  # FPGA
  ###############################################################################
  
  def schema_fpga(cfg):
      ''' FPGA Setup
      '''
      cfg['fpga'] = {}
  
      cfg['fpga']['xml'] = {
          'switch' : '-fpga_xml',
          'requirement' : 'fpga',
          'type' : 'file',        
          'lock' : 'false',
          'copy' : 'true',        
          'defvalue' : [],
          'hash'   : [],
          'date'   : [],
          'author' : [],
          'signature' : [],
          'short_help' : 'FPGA Architecture File',
          'param_help' : "fpga xml <file>",
          'example': ["cli: -fpga_xml myfpga.xml",                    
                      "api:  chip.set('fpga', 'xml', 'myfpga.xml')"],
          'help' : """
          Provides an XML-based architecture description for the target FPGA
          architecture to be used in VTR, allowing targeting a large number of 
          virtual and commercial architectures.
          [More information...](https://verilogtorouting.org)
          """
      }
  
      cfg['fpga']['vendor'] = {
          'switch' : '-fpga_vendor',
          'requirement' : '!fpga_xml',
          'type' : 'str',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'FPGA Vendor Name',
          'param_help' : "fpga vendor <str>",
          'example': ["cli: -fpga_vendor acme",                    
                      "api:  chip.set('fpga', 'vendor', 'acme')"],
          'help' : """
          Name of the FPGA vendor for non-VTR based compilation
          """
      }
  
      cfg['fpga']['device'] = {
          'switch' : '-fpga_device',
          'requirement' : '!fpga_xml',
          'type' : 'str',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'FPGA Device Name',
          'param_help' : "fpga device <str>",
          'example': ["cli: -fpga_device fpga64k",                    
                      "api:  chip.set('fpga', 'device', 'fpga64k')"],
          'help' : """
          Name of the FPGA device for non-VTR based compilation
          """
      }
  
      return cfg
  
  ###############################################################################
  # PDK
  ###############################################################################
  
  def schema_pdk(cfg):
      ''' Process Design Kit Setup
      '''
      cfg['pdk'] = {}
      cfg['pdk']['foundry'] = {
          'switch' : '-pdk_foundry',
          'requirement' : 'asic',
          'type' : 'str',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Foundry Name',
          'param_help' : "pdk foundry <str>",
          'example': ["cli: -pdk_foundry virtual",                    
                      "api:  chip.set('pdk', 'foundry', 'virtual')"],
          'help' : """
          The name of the foundry. For example: intel, gf, tsmc, "samsung, 
          skywater, virtual. The \'virtual\' keyword is reserved for simulated 
          non-manufacturable processes such as freepdk45 and asap7.              
          """        
      }
  
      cfg['pdk']['process'] = {
          'switch' : '-pdk_process',
          'requirement' : 'asic',
          'type' : 'str',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Name',
          'param_help' : "pdk process <str>",
          'example': ["cli: -pdk_process asap7",                    
                      "api:  chip.set('pdk', 'process', 'asap7')"],
          'help' : """
          The official public name of the foundry process. The name is case 
          insensitive, but should otherwise match the complete public process 
          name from the foundry. Example process names include 22ffl from Intel,
          12lpplus from Globalfoundries, and 16ffc from TSMC.        
          """
      }
  
      cfg['pdk']['node'] = {
          'switch' : '-pdk_node',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Node',
          'param_help' : "pdk node <num>",
          'example': ["cli: -pdk_node 130",                    
                      "api:  chip.set('pdk', 'node', '130')"],
          'help' : """
          An approximate relative minimum dimension of the process node. A 
          required parameter in some reference flows that leverage the value to 
          drive technology dependent synthesis and APR optimization. Node 
          examples include 180nm, 130nm, 90nm, 65nm, 45nm, 32nm, 22nm, 14nm, 
          10nm, 7nm, 5nm, 3nm. The value entered implies nanometers.
          """
      }
  
      cfg['pdk']['wafersize'] = {
          'switch' : '-pdk_wafersize',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Wafer Size',
          'param_help' : "pdk wafersize <num>",
          'example': ["cli: -pdk_wafersize 300",                    
                      "api:  chip.set('pdk', 'wafersize', '300')"],
          'help' : """
          Specifies the wafer diameter for the process in mm.
          """
      }
  
      cfg['pdk']['wafercost'] = {
          'switch' : '-pdk_wafercost',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Wafer Cost',
          'param_help' : "pdk wafercost <num>",
          'example': ["cli: -pdk_wafercost 10000",                    
                      "api:  chip.set('pdk', 'wafercost', '10000')"],
          'help' : """
          Specifies the raw cost per wafer purchased in USD, not 
          accounting for yield loss.
          """
      }
  
      cfg['pdk']['d0'] = {
          'switch' : '-pdk_d0',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Defect Density',
          'param_help' : "pdk d0 <num>",
          'example': ["cli: -pdk_d0 0.1",                    
                      "api:  chip.set('pdk', 'd0', '0.1')"],
          'help' : """
          Process defect density (D0) expressed as random defects per cm^2.
          """
      }
      
      cfg['pdk']['hscribe'] = {
          'switch' : '-pdk_hscribe',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Horizontal Scribeline',
          'param_help' : "pdk hscribe <num>",
          'example': ["cli: -pdk_hscribe 0.1",                    
                      "api:  chip.set('pdk', 'hscribe', '0.1')"],
          'help' : """
          Specifies the width of the horizontal scribe line in mm.
          """
      }
  
      cfg['pdk']['vscribe'] = {
          'switch' : '-pdk_vscribe',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Horizontal Scribeline',
          'param_help' : "pdk vscribe <num>",
          'example': ["cli: -pdk_vscribe 0.1",                    
                      "api:  chip.set('pdk', 'vscribe', '0.1')"],
          'help' : """
          Specifies the width of the vertical scribe line in mm.
          """
      }
      
      cfg['pdk']['edgemargin'] = {
          'switch' : '-pdk_edgemargin',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Wafer Edge Margin',
          'param_help' : "pdk edgemargin <num>",
          'example': ["cli: -pdk_edgemargin 1",                    
                      "api:  chip.set('pdk', 'edgemargin', '1')"],
          'help' : """
          Specifies keepout distance/margin (in mm) from the wafer edge 
          where no dies can be placed.
          """
      }
      
      cfg['pdk']['density'] = {
          'switch' : '-pdk_density',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Transistor Density',
          'param_help' : "pdk density <num>",
          'example': ["cli: -pdk_density 100e6",                    
                      "api:  chip.set('pdk', 'density', '10e6')"],
          'help' : """
          An approximate logic density expressed as # transistors / mm^2
          calculated as:
          0.6 * (Nand2 Transistor Count) / (Nand2 Cell Area) +
          0.4 * (Register Transistor Count) / (Register Cell Area)
          """
      }
  
      cfg['pdk']['sramsize'] = {
          'switch' : '-pdk_sramsize',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process SRAM Bitcell Size',
          'param_help' : "pdk sramsize <num>",
          'example': ["cli: -pdk_sramsize 0.032",                    
                      "api:  chip.set('pdk', 'sramcell', '0.026')"],
          'help' : """
          The area an SRAM bitcell expressed in um^2. 
          """
      }
  
      cfg['pdk']['rev'] = {
          'switch' : '-pdk_rev',
          'requirement' : 'asic',
          'type' : 'str',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Revision',
          'param_help' : "pdk rev <str>",
          'example': ["cli: -pdk_rev 1.0",                    
                      "api:  chip.set('pdk', 'rev', '1.0')"],
          'help' : """
          An alphanumeric string specifying the revision  of the current PDK. 
          Verification of correct PDK and IP revisions revisions is an ASIC 
          tapeout requirement in all commercial foundries.
          """
      }
      
      cfg['pdk']['drm'] = {
          'switch' : '-pdk_drm',
          'requirement' : 'asic',
          'type' : 'file',
          'lock' : 'false',
          'copy' : 'false',
          'defvalue' : [],
          'hash'   : [],
          'date'   : [],
          'author' : [],
          'signature' : [],        
          'short_help' : 'PDK Design Rule Manual',
          'param_help' : "pdk drm <file>",
          'example': ["cli: -pdk_drm asap7_drm.pdf",                    
                      "api:  chip.set('pdk', 'drm', 'asap7_drm.pdf')"],
          'help' : """
          A PDK document that includes complete information about physical and 
          electrical design rules to comply with in the design and layout of the 
          chip. In cases where the user guides and design rules are combined into
          a single document, the pdk_doc parameter can be left blank.
          """
      }
  
      cfg['pdk']['doc'] = {
          'switch' : '-pdk_doc',
          'requirement' : 'asic',
          'type' : 'file',
          'lock' : 'false',
          'copy' : 'false
  
  [... the rest is omitted ...]
files: siliconcompiler/schema.py
files: # Copyright 2020 Silicon Compiler Authors. All Rights Reserved.
  
  import re
  import os
  import textwrap
  import sys
  
  ###############################################################################
  # CHIP CONFIGURATION
  ###############################################################################
  
  def schema_cfg():
      '''Method for defining Chip configuration schema
      All the keys defined in this dictionary are reserved words.
      '''
  
      cfg = {}
  
      # Flow Setup (from schema_options)
      cfg = schema_flow(cfg, 'default')
  
      # Metric Tracking
      cfg = schema_metrics(cfg, 'goal')
      cfg = schema_metrics(cfg, 'real')    
      
      # Recording design provenance 
      cfg = schema_record(cfg) 
      
      # FPGA Parameters
      cfg = schema_fpga(cfg)
  
      # ASIC Parameters
      cfg = schema_pdk(cfg)
      cfg = schema_asic(cfg) 
      cfg = schema_libs(cfg, 'stdcell')
      cfg = schema_libs(cfg, 'macro')
  
      # Designer's Choice
      cfg = schema_design(cfg)
      cfg = schema_mcmm(cfg)
      
      # Designer Runtime options
      cfg = schema_options(cfg)
  
      # Remote options
      cfg = schema_remote(cfg)
      
      # Run status
      cfg = schema_status(cfg)
      
      return cfg
  
  
  ###############################################################################
  # CHIP LIBRARY 
  ###############################################################################
  def schema_lib():
      pass    
  
  ###############################################################################
  # CHIP LAYOUT
  ###############################################################################
  def schema_layout():
      
      layout = {}
  
      layout = schema_lef(layout)
  
      layout = schema_def(layout)
  
      return layout
  
  ###############################################################################
  # UTILITY FUNCTIONS TIED TO SC SPECIFICATIONS
  ###############################################################################
  
  def schema_path(filename):
      ''' Resolves file paths using SCPATH and resolve environment variables
      starting with $
      '''
  
      #Resolve absolute path usign SCPATH
      #list is read left to right    
      scpaths = str(os.environ['SCPATH']).split(':')
      for searchdir in scpaths:        
          abspath = searchdir + "/" + filename
          if os.path.exists(abspath):
              filename = abspath
              break
      #Replace $ Variables
      varmatch = re.match('^\$(\w+)(.*)', filename)
      if varmatch:
          var = varmatch.group(1)
          varpath = os.getenv(var)
          if varpath is None:
              print("ERROR: Missing environment variable:", var)
              sys.exit()
          relpath = varmatch.group(2)
          filename = varpath + relpath
          
      return filename
              
  def schema_istrue(value):
      ''' Checks schema boolean string and returns Python True/False
      '''
      boolean = value[-1].lower()
      if boolean == "true":
          return True
      else:
          return False
  
  def schema_check(cfg, leafkey, value):
      ''' Checks that leaf cell value agrees with type 
      '''
  
      ok = True
      keyval = "(Key,value) = (" + leafkey +  ",'" + ' '.join(value) + "')"
      if cfg['type'] == 'bool':
          if value[0] not in ('true', 'false'):
              print("ERROR: Value should be boolan.", keyval)
              ok = False
      else:
          for item in value:            
              if cfg['type'] == 'str':
                  ok =  isinstance(item, str)
                  if not ok:
                      print("ERROR: Value should be a string.", keyval)
              elif cfg['type'] == 'num':
                  try:
                      isinstance(float(item), float)
                  except:
                      ok = False
                      print("ERROR: Value should be a number.", keyval)
              elif cfg['type'] == 'file':
                  ok =  os.path.isfile(schema_path(item))
                  if not ok:
                      print("ERROR: File is missing.", keyval)
              elif cfg['type'] == 'dir':
                  ok =  os.path.isdir(schema_path(item))
                  if not ok:
                      print("ERROR: Directory is missing.", keyval)
  
      return ok
  
  
  def schema_reorder_keys(param_help, item):
      ''' Returns a keylist used to access the dictionary based on the 
      cmdline switch argument and the param_help field.
      '''
  
      #Split param help into keys and data based in <>
      m = re.search('(.*?)(<.*)',param_help)
      paramlist = m.group(1).split()
      datalist = m.group(2).split()
      #Split cmdline inputn based on spaces
      itemlist = item.split()
      
      depth = len(paramlist)+1
      args = [None] * depth
  
      #Combine keys from param_help and cmdline field
      j=0
      for i in range(depth-1):
          if paramlist[i].endswith('var'):
              args[i]=itemlist[j]
              j=j+1
          else:
              args[i]=paramlist[i]
  
      #Insert data field as last entry (some are string tuples)
      args[-1] = itemlist[-len(datalist):]
      
      return args
  
      
  ###############################################################################
  # FPGA
  ###############################################################################
  
  def schema_fpga(cfg):
      ''' FPGA Setup
      '''
      cfg['fpga'] = {}
  
      cfg['fpga']['xml'] = {
          'switch' : '-fpga_xml',
          'requirement' : 'fpga',
          'type' : 'file',        
          'lock' : 'false',
          'copy' : 'true',        
          'defvalue' : [],
          'hash'   : [],
          'date'   : [],
          'author' : [],
          'signature' : [],
          'short_help' : 'FPGA Architecture File',
          'param_help' : "fpga xml <file>",
          'example': ["cli: -fpga_xml myfpga.xml",                    
                      "api:  chip.set('fpga', 'xml', 'myfpga.xml')"],
          'help' : """
          Provides an XML-based architecture description for the target FPGA
          architecture to be used in VTR, allowing targeting a large number of 
          virtual and commercial architectures.
          [More information...](https://verilogtorouting.org)
          """
      }
  
      cfg['fpga']['vendor'] = {
          'switch' : '-fpga_vendor',
          'requirement' : '!fpga_xml',
          'type' : 'str',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'FPGA Vendor Name',
          'param_help' : "fpga vendor <str>",
          'example': ["cli: -fpga_vendor acme",                    
                      "api:  chip.set('fpga', 'vendor', 'acme')"],
          'help' : """
          Name of the FPGA vendor for non-VTR based compilation
          """
      }
  
      cfg['fpga']['device'] = {
          'switch' : '-fpga_device',
          'requirement' : '!fpga_xml',
          'type' : 'str',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'FPGA Device Name',
          'param_help' : "fpga device <str>",
          'example': ["cli: -fpga_device fpga64k",                    
                      "api:  chip.set('fpga', 'device', 'fpga64k')"],
          'help' : """
          Name of the FPGA device for non-VTR based compilation
          """
      }
  
      return cfg
  
  ###############################################################################
  # PDK
  ###############################################################################
  
  def schema_pdk(cfg):
      ''' Process Design Kit Setup
      '''
      cfg['pdk'] = {}
      cfg['pdk']['foundry'] = {
          'switch' : '-pdk_foundry',
          'requirement' : 'asic',
          'type' : 'str',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Foundry Name',
          'param_help' : "pdk foundry <str>",
          'example': ["cli: -pdk_foundry virtual",                    
                      "api:  chip.set('pdk', 'foundry', 'virtual')"],
          'help' : """
          The name of the foundry. For example: intel, gf, tsmc, "samsung, 
          skywater, virtual. The \'virtual\' keyword is reserved for simulated 
          non-manufacturable processes such as freepdk45 and asap7.              
          """        
      }
  
      cfg['pdk']['process'] = {
          'switch' : '-pdk_process',
          'requirement' : 'asic',
          'type' : 'str',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Name',
          'param_help' : "pdk process <str>",
          'example': ["cli: -pdk_process asap7",                    
                      "api:  chip.set('pdk', 'process', 'asap7')"],
          'help' : """
          The official public name of the foundry process. The name is case 
          insensitive, but should otherwise match the complete public process 
          name from the foundry. Example process names include 22ffl from Intel,
          12lpplus from Globalfoundries, and 16ffc from TSMC.        
          """
      }
  
      cfg['pdk']['node'] = {
          'switch' : '-pdk_node',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Node',
          'param_help' : "pdk node <num>",
          'example': ["cli: -pdk_node 130",                    
                      "api:  chip.set('pdk', 'node', '130')"],
          'help' : """
          An approximate relative minimum dimension of the process node. A 
          required parameter in some reference flows that leverage the value to 
          drive technology dependent synthesis and APR optimization. Node 
          examples include 180nm, 130nm, 90nm, 65nm, 45nm, 32nm, 22nm, 14nm, 
          10nm, 7nm, 5nm, 3nm. The value entered implies nanometers.
          """
      }
  
      cfg['pdk']['wafersize'] = {
          'switch' : '-pdk_wafersize',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Wafer Size',
          'param_help' : "pdk wafersize <num>",
          'example': ["cli: -pdk_wafersize 300",                    
                      "api:  chip.set('pdk', 'wafersize', '300')"],
          'help' : """
          Specifies the wafer diameter for the process in mm.
          """
      }
  
      cfg['pdk']['wafercost'] = {
          'switch' : '-pdk_wafercost',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Wafer Cost',
          'param_help' : "pdk wafercost <num>",
          'example': ["cli: -pdk_wafercost 10000",                    
                      "api:  chip.set('pdk', 'wafercost', '10000')"],
          'help' : """
          Specifies the raw cost per wafer purchased in USD, not 
          accounting for yield loss.
          """
      }
  
      cfg['pdk']['d0'] = {
          'switch' : '-pdk_d0',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Defect Density',
          'param_help' : "pdk d0 <num>",
          'example': ["cli: -pdk_d0 0.1",                    
                      "api:  chip.set('pdk', 'd0', '0.1')"],
          'help' : """
          Process defect density (D0) expressed as random defects per cm^2.
          """
      }
      
      cfg['pdk']['hscribe'] = {
          'switch' : '-pdk_hscribe',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Horizontal Scribeline',
          'param_help' : "pdk hscribe <num>",
          'example': ["cli: -pdk_hscribe 0.1",                    
                      "api:  chip.set('pdk', 'hscribe', '0.1')"],
          'help' : """
          Specifies the width of the horizontal scribe line in mm.
          """
      }
  
      cfg['pdk']['vscribe'] = {
          'switch' : '-pdk_vscribe',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Horizontal Scribeline',
          'param_help' : "pdk vscribe <num>",
          'example': ["cli: -pdk_vscribe 0.1",                    
                      "api:  chip.set('pdk', 'vscribe', '0.1')"],
          'help' : """
          Specifies the width of the vertical scribe line in mm.
          """
      }
      
      cfg['pdk']['edgemargin'] = {
          'switch' : '-pdk_edgemargin',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Wafer Edge Margin',
          'param_help' : "pdk edgemargin <num>",
          'example': ["cli: -pdk_edgemargin 1",                    
                      "api:  chip.set('pdk', 'edgemargin', '1')"],
          'help' : """
          Specifies keepout distance/margin (in mm) from the wafer edge 
          where no dies can be placed.
          """
      }
      
      cfg['pdk']['density'] = {
          'switch' : '-pdk_density',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Transistor Density',
          'param_help' : "pdk density <num>",
          'example': ["cli: -pdk_density 100e6",                    
                      "api:  chip.set('pdk', 'density', '10e6')"],
          'help' : """
          An approximate logic density expressed as # transistors / mm^2
          calculated as:
          0.6 * (Nand2 Transistor Count) / (Nand2 Cell Area) +
          0.4 * (Register Transistor Count) / (Register Cell Area)
          """
      }
  
      cfg['pdk']['sramsize'] = {
          'switch' : '-pdk_sramsize',
          'requirement' : 'asic',
          'type' : 'num',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process SRAM Bitcell Size',
          'param_help' : "pdk sramsize <num>",
          'example': ["cli: -pdk_sramsize 0.032",                    
                      "api:  chip.set('pdk', 'sramcell', '0.026')"],
          'help' : """
          The area an SRAM bitcell expressed in um^2. 
          """
      }
  
      cfg['pdk']['rev'] = {
          'switch' : '-pdk_rev',
          'requirement' : 'asic',
          'type' : 'str',
          'lock' : 'false',
          'defvalue' : [],
          'short_help' : 'Process Revision',
          'param_help' : "pdk rev <str>",
          'example': ["cli: -pdk_rev 1.0",                    
                      "api:  chip.set('pdk', 'rev', '1.0')"],
          'help' : """
          An alphanumeric string specifying the revision  of the current PDK. 
          Verification of correct PDK and IP revisions revisions is an ASIC 
          tapeout requirement in all commercial foundries.
          """
      }
      
      cfg['pdk']['drm'] = {
          'switch' : '-pdk_drm',
          'requirement' : 'asic',
          'type' : 'file',
          'lock' : 'false',
          'copy' : 'false',
          'defvalue' : [],
          'hash'   : [],
          'date'   : [],
          'author' : [],
          'signature' : [],        
          'short_help' : 'PDK Design Rule Manual',
          'param_help' : "pdk drm <file>",
          'example': ["cli: -pdk_drm asap7_drm.pdf",                    
                      "api:  chip.set('pdk', 'drm', 'asap7_drm.pdf')"],
          'help' : """
          A PDK document that includes complete information about physical and 
          electrical design rules to comply with in the design and layout of the 
          chip. In cases where the user guides and design rules are combined into
          a single document, the pdk_doc parameter can be left blank.
          """
      }
  
      cfg['pdk']['doc'] = {
          'switch' : '-pdk_doc',
          'requirement' : 'asic',
          'type' : 'file',
          'lock' : 'false',
          'copy' : 'false
  
  [... the rest is omitted ...]
files: siliconcompiler/schema.py