files.new_contents: # 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')"],
          '
  
  [... the rest is omitted ...]
files.new_path: siliconcompiler/schema.py
files.old_contents: # 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')"],
          '
  
  [... the rest is omitted ...]
files.old_path: siliconcompiler/schema.py