files: import os
  import sys
  import re
  import siliconcompiler
  
  def make_docs():
      '''
      The asap7 PDK was developed at ASU in collaboration with ARM Research.
      With funding from the DARPA IDEA program, the PDK was released
      a permissive open source PDK in 2021. The PDK contains SPICE-compatible
      FinFET device models (BSIM-CMG), Technology files for Cadence Virtuoso,
      Design Rule Checker (DRC), Layout vs Schematic Checker (LVS) and
      Extraction Deck for the 7nm technology node. For more details regarding
      the technical specifications of the PDK, please refer the PDK
      documentation and associated publication. Note that this process
      design kit is provided as an academic and research aid only and the
      resulting designs are not manufacturable.
  
      PDK content:
  
      * open source DRM
      * device primitive library (virtuoso)
      * spice (hspice)
      * extraction runsets (calibre)
      * drc runsets (calibre)
      * APR technology files
      * 7.5 track multi-vt standard cell libraries
  
      More information:
  
      * http://asap.asu.edu/asap
      * L.T. Clark, V. Vashishtha, L. Shifren, A. Gujja, S. Sinha, B. Cline,
        C. Ramamurthya, and G. Yeric, “ASAP7: A 7-nm FinFET Predictive Process
        Design Kit,” Microelectronics Journal, vol. 53, pp. 105-115, July 2016.
  
  
      Sources: https://github.com/The-OpenROAD-Project/asap
  
      .. warning::
         Work in progress (not ready for use)
  
      '''
  
      chip = siliconcompiler.Chip()
      setup(chip)
  
      return chip
  
  def setup(chip):
      '''
      TODO: Add process information
      '''
  
      foundry = 'virtual'
      process = 'asap7'
      node = 7
      rev = 'r1p7'
      stackup = '10M'
      libtype = '7p5t'
      pdkdir = os.path.join('..', 'third_party', 'pdks', foundry, process, 'pdk', rev)
  
      # If you got here,  you are in asic mode
      chip.set('mode', 'asic', clobber=True)
  
      # process name
      chip.set('pdk','foundry', foundry)
      chip.set('pdk','process', process)
      chip.set('pdk','node', node)
      chip.set('pdk','version', rev)
      chip.set('pdk','stackup', stackup)
      chip.set('pdk','tapmax', 25)
      chip.set('pdk','tapoffset', 0)
  
      # APR tech file
      for tool in ('openroad', 'klayout', 'magic'):
          chip.set('pdk','aprtech', tool, stackup, libtype, 'lef',
                   pdkdir+'/apr/asap7_tech.lef')
  
      # Openroad APR setup files
      chip.set('pdk', 'aprtech', 'openroad', stackup, libtype, 'tracks',
               pdkdir + '/apr/openroad_tracks.tcl')
      chip.set('pdk', 'aprtech', 'openroad', stackup, libtype, 'tapcells',
               pdkdir + '/apr/openroad_tapcells.tcl')
  
      # Klayout setup file
      chip.set('pdk','layermap','klayout',stackup, 'def', 'gds',
               pdkdir+'/setup/klayout/asap7.lyt')
  
      # Routing Grid Definitions
      for layer, sc_name in [('M1', 'm1')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.036)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.036)
          chip.set('pdk','grid', stackup, layer, 'adj',     1.0)
  
      for layer, sc_name in [('M2', 'm2')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.036)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.027)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.8)
  
      for layer, sc_name in [('M3', 'm3')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.036)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.036)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.7)
  
      for layer, sc_name in [('M4', 'm4')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.036)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.048)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
  
      for layer, sc_name in [('M5', 'm5')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.048)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.048)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
  
      for layer, sc_name in [('M6', 'm6')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.048)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.064)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
  
      for layer, sc_name in [('M7', 'm7')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.064)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.064)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
  
      for layer, sc_name in [('M8', 'm8'), ('M9', 'm9')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.08)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.08)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
  
      # Defaults for OpenROAD tool variables
      chip.set('pdk', 'variable', stackup, 'openroad', 'place_density', ['0.77'])
      chip.set('pdk', 'variable', stackup, 'openroad', 'pad_global_place', ['2'])
      chip.set('pdk', 'variable', stackup, 'openroad', 'pad_detail_place', ['1'])
      chip.set('pdk', 'variable', stackup, 'openroad', 'macro_place_halo', ['22.4', '15.12'])
      chip.set('pdk', 'variable', stackup, 'openroad', 'macro_place_channel', ['18.8', '19.95'])
  
  #########################
  if __name__ == "__main__":
  
      chip = make_docs()
      chip.writecfg('asap7.json')
  
  
  [... the rest is omitted ...]
files: siliconcompiler/pdks/asap7.py
files: import os
  import sys
  import re
  import siliconcompiler
  
  def make_docs():
      '''
      The asap7 PDK was developed at ASU in collaboration with ARM Research.
      With funding from the DARPA IDEA program, the PDK was released
      a permissive open source PDK in 2021. The PDK contains SPICE-compatible
      FinFET device models (BSIM-CMG), Technology files for Cadence Virtuoso,
      Design Rule Checker (DRC), Layout vs Schematic Checker (LVS) and
      Extraction Deck for the 7nm technology node. For more details regarding
      the technical specifications of the PDK, please refer the PDK
      documentation and associated publication. Note that this process
      design kit is provided as an academic and research aid only and the
      resulting designs are not manufacturable.
  
      PDK content:
  
      * open source DRM
      * device primitive library (virtuoso)
      * spice (hspice)
      * extraction runsets (calibre)
      * drc runsets (calibre)
      * APR technology files
      * 7.5 track multi-vt standard cell libraries
  
      More information:
  
      * http://asap.asu.edu/asap
      * L.T. Clark, V. Vashishtha, L. Shifren, A. Gujja, S. Sinha, B. Cline,
        C. Ramamurthya, and G. Yeric, “ASAP7: A 7-nm FinFET Predictive Process
        Design Kit,” Microelectronics Journal, vol. 53, pp. 105-115, July 2016.
  
  
      Sources: https://github.com/The-OpenROAD-Project/asap
  
      .. warning::
         Work in progress (not ready for use)
  
      '''
  
      chip = siliconcompiler.Chip()
      setup(chip)
  
      return chip
  
  def setup(chip):
      '''
      TODO: Add process information
      '''
  
      foundry = 'virtual'
      process = 'asap7'
      node = 7
      rev = 'r1p7'
      stackup = '10M'
      libtype = '7p5t'
      pdkdir = os.path.join('..', 'third_party', 'pdks', foundry, process, 'pdk', rev)
  
      # If you got here,  you are in asic mode
      chip.set('mode', 'asic', clobber=True)
  
      # process name
      chip.set('pdk','foundry', foundry)
      chip.set('pdk','process', process)
      chip.set('pdk','node', node)
      chip.set('pdk','version', rev)
      chip.set('pdk','stackup', stackup)
      chip.set('pdk','tapmax', 25)
      chip.set('pdk','tapoffset', 0)
  
      # APR tech file
      for tool in ('openroad', 'klayout', 'magic'):
          chip.set('pdk','aprtech', tool, stackup, libtype, 'lef',
                   pdkdir+'/apr/asap7_tech.lef')
  
      # Openroad APR setup files
      chip.set('pdk', 'aprtech', 'openroad', stackup, libtype, 'tracks',
               pdkdir + '/apr/openroad_tracks.tcl')
      chip.set('pdk', 'aprtech', 'openroad', stackup, libtype, 'tapcells',
               pdkdir + '/apr/openroad_tapcells.tcl')
  
      # Klayout setup file
      chip.set('pdk','layermap','klayout',stackup, 'def', 'gds',
               pdkdir+'/setup/klayout/asap7.lyt')
  
      # Routing Grid Definitions
      for layer, sc_name in [('M1', 'm1')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.036)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.036)
          chip.set('pdk','grid', stackup, layer, 'adj',     1.0)
  
      for layer, sc_name in [('M2', 'm2')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.036)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.027)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.8)
  
      for layer, sc_name in [('M3', 'm3')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.036)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.036)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.7)
  
      for layer, sc_name in [('M4', 'm4')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.036)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.048)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
  
      for layer, sc_name in [('M5', 'm5')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.048)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.048)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
  
      for layer, sc_name in [('M6', 'm6')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.048)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.064)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
  
      for layer, sc_name in [('M7', 'm7')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.064)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.064)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
  
      for layer, sc_name in [('M8', 'm8'), ('M9', 'm9')]:
          chip.set('pdk','grid', stackup, layer, 'name', sc_name)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.08)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.08)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
  
  #########################
  if __name__ == "__main__":
  
      chip = make_docs()
      chip.writecfg('asap7.json')
  
  
  [... the rest is omitted ...]
files: siliconcompiler/pdks/asap7.py
files: 
  import os
  import sys
  import re
  import siliconcompiler
  
  
  ############################################################################
  # DOCS
  ############################################################################
  
  def make_docs():
      '''
      The freepdk45 PDK is a virtual PDK derived from the work done at
      NCSU (NCSU_TechLib_FreePDK45.)  It supplies techfiles, display
      resources, design rules and scripts to permit layout design and rule
      checking for a generic 45 nanometer process.  The technology information
      contained in this kit has been compiled from published papers,
      predictive technology models and rule scaling.  This information may be
      freely used, modified, and distributed under the open-source Apache
      License (see the file APACHE-LICENSE-2.0.txt in the root install
      directory for the complete text). This technology is intended to work
      with the 45nm BSIM4 Predictive Technology Model from Arizona State
      University (http://www.eas.asu.edu/~ptm).  See the HSPICE Models
      section of this file for details about these models.
  
      More information:
      * https://www.eda.ncsu.edu/wiki/FreePDK45:Manual
  
      '''
  
      chip = siliconcompiler.Chip()
      setup(chip)
  
      return chip
  
  
  ####################################################
  # PDK Setup
  ####################################################
  
  def setup(chip):
      '''
      Setup function for the freepdk45 PDK.
      '''
  
      ###############################################
      # Process
      ###############################################
  
      foundry = 'virtual'
      process = 'freepdk45'
      rev = 'r1p0'
      stackup = '10M'
      libtype = '10t'
      node = 45
      wafersize = 300
      hscribe = 0.1
      vscribe = 0.1
      edgemargin = 2
      d0 = 1.25
  
      pdkdir = os.path.join('..', 'third_party', 'pdks', foundry, process, 'pdk', rev)
  
      # If you got here,  you are in asic mode
      chip.set('mode', 'asic', clobber=True)
  
      # process name
      chip.set('pdk','foundry', foundry)
      chip.set('pdk','process', process)
      chip.set('pdk','node', node)
      chip.set('pdk','version', rev)
      chip.set('pdk','stackup', stackup)
      chip.set('pdk','wafersize', wafersize)
      chip.set('pdk','edgemargin', edgemargin)
      chip.set('pdk','hscribe', hscribe)
      chip.set('pdk','vscribe', vscribe)
      chip.set('pdk','d0', d0)
  
      chip.set('pdk','tapmax', 120)
      chip.set('pdk','tapoffset', 2)
  
      # APR tech file
      for tool in ('openroad', 'klayout', 'magic'):
          chip.set('pdk','aprtech', tool, stackup, libtype, 'lef',
                   pdkdir+'/apr/freepdk45.tech.lef')
  
      # Klayout setup file
      chip.set('pdk','layermap','klayout',stackup, 'def', 'gds',
               pdkdir+'/setup/klayout/freepdk45.lyt')
  
      # Routing Grid Definitions
      for layer, sc_name in [('metal1', 'm1')]:
          chip.set('pdk','grid', stackup, layer, 'name',    sc_name)
          chip.set('pdk','grid', stackup, layer, 'xoffset', 0.095)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.19)
          chip.set('pdk','grid', stackup, layer, 'yoffset', 0.07)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.14)
          chip.set('pdk','grid', stackup, layer, 'adj',     1.0)
          chip.set('pdk','grid', stackup, layer, 'dir',    'horizontal')
  
      for layer, sc_name in [('metal2', 'm2')]:
          chip.set('pdk','grid', stackup, layer, 'name',    sc_name)
          chip.set('pdk','grid', stackup, layer, 'xoffset', 0.095)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.19)
          chip.set('pdk','grid', stackup, layer, 'yoffset', 0.07)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.14)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.8)
          chip.set('pdk','grid', stackup, layer, 'dir',    'vertical')
  
      for layer, sc_name in [('metal3', 'm3')]:
          chip.set('pdk','grid', stackup, layer, 'name',    sc_name)
          chip.set('pdk','grid', stackup, layer, 'xoffset', 0.095)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.19)
          chip.set('pdk','grid', stackup, layer, 'yoffset', 0.07)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.14)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.7)
          chip.set('pdk','grid', stackup, layer, 'dir',    'horizontal')
  
      for layer, sc_name in [('metal4', 'm4'), ('metal5', 'm5'), ('metal6', 'm6')]:
          chip.set('pdk','grid', stackup, layer, 'name',    sc_name)
          chip.set('pdk','grid', stackup, layer, 'xoffset', 0.095)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.28)
          chip.set('pdk','grid', stackup, layer, 'yoffset', 0.07)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.28)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
          if layer in ('metal4', 'metal6'):
              chip.set('pdk','grid', stackup, layer, 'dir', 'vertical')
          else:
              chip.set('pdk','grid', stackup, layer, 'dir', 'horizontal')
  
      for layer, sc_name in [('metal7', 'm7'), ('metal8', 'm8')]:
          chip.set('pdk','grid', stackup, layer, 'name',    sc_name)
          chip.set('pdk','grid', stackup, layer, 'xoffset', 0.095)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.8)
          chip.set('pdk','grid', stackup, layer, 'yoffset', 0.07)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.8)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
          if layer in ('metal8'):
              chip.set('pdk','grid', stackup, layer, 'dir', 'vertical')
          else:
              chip.set('pdk','grid', stackup, layer, 'dir', 'horizontal')
  
  
      for layer, sc_name in [('metal9', 'm9'), ('metal10', 'm10')]:
          chip.set('pdk','grid', stackup, layer, 'name',    sc_name)
          chip.set('pdk','grid', stackup, layer, 'xoffset', 0.095)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  1.6)
          chip.set('pdk','grid', stackup, layer, 'yoffset', 0.07)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  1.6)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
          if layer in ('metal10'):
              chip.set('pdk','grid', stackup, layer, 'dir', 'vertical')
          else:
              chip.set('pdk','grid', stackup, layer, 'dir', 'horizontal')
  
      # Defaults for OpenROAD tool variables
      chip.set('pdk', 'variable', 'openroad', stackup, 'place_density', ['0.3'])
      chip.set('pdk', 'variable', 'openroad', stackup, 'pad_global_place', ['2'])
      chip.set('pdk', 'variable', 'openroad', stackup, 'pad_detail_
  
  [... the rest is omitted ...]
files: siliconcompiler/pdks/freepdk45.py
files: 
  import os
  import sys
  import re
  import siliconcompiler
  
  
  ############################################################################
  # DOCS
  ############################################################################
  
  def make_docs():
      '''
      The freepdk45 PDK is a virtual PDK derived from the work done at
      NCSU (NCSU_TechLib_FreePDK45.)  It supplies techfiles, display
      resources, design rules and scripts to permit layout design and rule
      checking for a generic 45 nanometer process.  The technology information
      contained in this kit has been compiled from published papers,
      predictive technology models and rule scaling.  This information may be
      freely used, modified, and distributed under the open-source Apache
      License (see the file APACHE-LICENSE-2.0.txt in the root install
      directory for the complete text). This technology is intended to work
      with the 45nm BSIM4 Predictive Technology Model from Arizona State
      University (http://www.eas.asu.edu/~ptm).  See the HSPICE Models
      section of this file for details about these models.
  
      More information:
      * https://www.eda.ncsu.edu/wiki/FreePDK45:Manual
  
      '''
  
      chip = siliconcompiler.Chip()
      setup(chip)
  
      return chip
  
  
  ####################################################
  # PDK Setup
  ####################################################
  
  def setup(chip):
      '''
      Setup function for the freepdk45 PDK.
      '''
  
      ###############################################
      # Process
      ###############################################
  
      foundry = 'virtual'
      process = 'freepdk45'
      rev = 'r1p0'
      stackup = '10M'
      libtype = '10t'
      node = 45
      wafersize = 300
      hscribe = 0.1
      vscribe = 0.1
      edgemargin = 2
      d0 = 1.25
  
      pdkdir = os.path.join('..', 'third_party', 'pdks', foundry, process, 'pdk', rev)
  
      # If you got here,  you are in asic mode
      chip.set('mode', 'asic', clobber=True)
  
      # process name
      chip.set('pdk','foundry', foundry)
      chip.set('pdk','process', process)
      chip.set('pdk','node', node)
      chip.set('pdk','version', rev)
      chip.set('pdk','stackup', stackup)
      chip.set('pdk','wafersize', wafersize)
      chip.set('pdk','edgemargin', edgemargin)
      chip.set('pdk','hscribe', hscribe)
      chip.set('pdk','vscribe', vscribe)
      chip.set('pdk','d0', d0)
  
      chip.set('pdk','tapmax', 120)
      chip.set('pdk','tapoffset', 2)
  
      # APR tech file
      for tool in ('openroad', 'klayout', 'magic'):
          chip.set('pdk','aprtech', tool, stackup, libtype, 'lef',
                   pdkdir+'/apr/freepdk45.tech.lef')
  
      # Klayout setup file
      chip.set('pdk','layermap','klayout',stackup, 'def', 'gds',
               pdkdir+'/setup/klayout/freepdk45.lyt')
  
      # Routing Grid Definitions
      for layer, sc_name in [('metal1', 'm1')]:
          chip.set('pdk','grid', stackup, layer, 'name',    sc_name)
          chip.set('pdk','grid', stackup, layer, 'xoffset', 0.095)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.19)
          chip.set('pdk','grid', stackup, layer, 'yoffset', 0.07)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.14)
          chip.set('pdk','grid', stackup, layer, 'adj',     1.0)
          chip.set('pdk','grid', stackup, layer, 'dir',    'horizontal')
  
      for layer, sc_name in [('metal2', 'm2')]:
          chip.set('pdk','grid', stackup, layer, 'name',    sc_name)
          chip.set('pdk','grid', stackup, layer, 'xoffset', 0.095)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.19)
          chip.set('pdk','grid', stackup, layer, 'yoffset', 0.07)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.14)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.8)
          chip.set('pdk','grid', stackup, layer, 'dir',    'vertical')
  
      for layer, sc_name in [('metal3', 'm3')]:
          chip.set('pdk','grid', stackup, layer, 'name',    sc_name)
          chip.set('pdk','grid', stackup, layer, 'xoffset', 0.095)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.19)
          chip.set('pdk','grid', stackup, layer, 'yoffset', 0.07)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.14)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.7)
          chip.set('pdk','grid', stackup, layer, 'dir',    'horizontal')
  
      for layer, sc_name in [('metal4', 'm4'), ('metal5', 'm5'), ('metal6', 'm6')]:
          chip.set('pdk','grid', stackup, layer, 'name',    sc_name)
          chip.set('pdk','grid', stackup, layer, 'xoffset', 0.095)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.28)
          chip.set('pdk','grid', stackup, layer, 'yoffset', 0.07)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.28)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
          if layer in ('metal4', 'metal6'):
              chip.set('pdk','grid', stackup, layer, 'dir', 'vertical')
          else:
              chip.set('pdk','grid', stackup, layer, 'dir', 'horizontal')
  
      for layer, sc_name in [('metal7', 'm7'), ('metal8', 'm8')]:
          chip.set('pdk','grid', stackup, layer, 'name',    sc_name)
          chip.set('pdk','grid', stackup, layer, 'xoffset', 0.095)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  0.8)
          chip.set('pdk','grid', stackup, layer, 'yoffset', 0.07)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  0.8)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
          if layer in ('metal8'):
              chip.set('pdk','grid', stackup, layer, 'dir', 'vertical')
          else:
              chip.set('pdk','grid', stackup, layer, 'dir', 'horizontal')
  
  
      for layer, sc_name in [('metal9', 'm9'), ('metal10', 'm10')]:
          chip.set('pdk','grid', stackup, layer, 'name',    sc_name)
          chip.set('pdk','grid', stackup, layer, 'xoffset', 0.095)
          chip.set('pdk','grid', stackup, layer, 'xpitch',  1.6)
          chip.set('pdk','grid', stackup, layer, 'yoffset', 0.07)
          chip.set('pdk','grid', stackup, layer, 'ypitch',  1.6)
          chip.set('pdk','grid', stackup, layer, 'adj',     0.4)
          if layer in ('metal10'):
              chip.set('pdk','grid', stackup, layer, 'dir', 'vertical')
          else:
              chip.set('pdk','grid', stackup, layer, 'dir', 'horizontal')
  
  #########################
  if __name__ == "__main__":
  
      chip = make_docs()
      chip.writecfg('freepdk45.json')
  
  
  [... the rest is omitted ...]
files: siliconcompiler/pdks/freepdk45.py
files: 
  import os
  import sys
  import re
  import siliconcompiler
  
  ############################################################################
  # DOCS
  ############################################################################
  
  def make_docs():
      '''
      The 'skywater130' Open Source PDK is a collaboration between Google and
      SkyWater Technology Foundry to provide a fully open source Process
      Design Kit and related resources, which can be used to create
      manufacturable designs at SkyWaterâ€™s facility.
  
      Skywater130 Process Highlights:
      * 130nm process
      * support for internal 1.8V with 5.0V I/Os (operable at 2.5V)
      * 1 level of local interconnect
      * 5 levels of metal
  
      PDK content:
      * An open source design rule manual
      * multiple standard digital cell libraries
      * primitive cell libraries and models for creating analog designs
      * EDA support files for multiple open source and proprietary flows
  
      More information:
      * https://skywater-pdk.readthedocs.io/en/latest/
  
      Sources:
      * https://github.com/google/skywater-pdk
  
      '''
  
      chip = siliconcompiler.Chip()
      setup(chip)
  
      return chip
  
  ####################################################
  # PDK Setup
  ####################################################
  
  def setup(chip):
      '''
      Setup function for the skywater130 PDK.
      '''
  
      foundry = 'skywater'
      process = 'skywater130'
      rev = 'v0_0_2'
      stackup = '5M1LI'
  
      # TODO: eventualy support hs libtype as well
      libtype = 'hd'
      node = 130
      # TODO: dummy numbers, only matter for cost estimation
      wafersize = 300
      hscribe = 0.1
      vscribe = 0.1
      edgemargin = 2
  
      pdkdir = os.path.join('..', 'third_party', 'pdks', foundry, process, 'pdk', rev)
  
      #if you are calling this file, you are in asic mode
      chip.set('mode','asic', clobber = True)
  
      # process name
      chip.set('pdk','foundry', foundry)
      chip.set('pdk','process', process)
      chip.set('pdk','node', node)
      chip.set('pdk','version', rev)
      chip.set('pdk','stackup', stackup)
      chip.set('pdk','wafersize', wafersize)
      chip.set('pdk','edgemargin', edgemargin)
      chip.set('pdk','hscribe', hscribe)
      chip.set('pdk','vscribe', vscribe)
  
      # Values chosen based on
      # https://github.com/The-OpenROAD-Project/OpenROAD-flow-scripts/blob/59ad47a1325239b578bf1c2b3cf6617e44d05d47/flow/platforms/sky130hd/tapcell.tcl
      chip.set('pdk','tapmax', 14)
      chip.set('pdk','tapoffset', 2)
  
      # Tech file
      for tool in ('openroad', 'klayout', 'magic'):
          chip.set('pdk','aprtech',tool,stackup, libtype,'lef',
                   pdkdir+'/apr/sky130_fd_sc_hd.tlef')
  
      # DRC Runsets
      chip.set('pdk','drc','magic', stackup, 'runset', pdkdir+'/setup/magic/sky130A.tech')
  
      # LVS Runsets
      chip.set('pdk','lvs','netgen', stackup, 'runset', pdkdir+'/setup/netgen/lvs_setup.tcl')
  
      # Layer map
      chip.set('pdk','layermap','klayout',stackup, 'def', 'gds', pdkdir+'/setup/klayout/skywater130.lyt')
  
      # Routing Grid Definitions
  
      # TODO: what should the SC-internal name of the LI layer be?
      chip.set('pdk','grid', stackup, 'li1', 'name', 'li1')
      chip.set('pdk','grid', stackup, 'li1', 'xoffset', 0.23)
      chip.set('pdk','grid', stackup, 'li1', 'xpitch',  0.46)
      chip.set('pdk','grid', stackup, 'li1', 'yoffset', 0.17)
      chip.set('pdk','grid', stackup, 'li1', 'ypitch',  0.34)
      chip.set('pdk','grid', stackup, 'li1', 'adj', 1.0)
  
      chip.set('pdk','grid', stackup, 'met1', 'name', 'm1')
      chip.set('pdk','grid', stackup, 'met1', 'xoffset', 0.17)
      chip.set('pdk','grid', stackup, 'met1', 'xpitch',  0.34)
      chip.set('pdk','grid', stackup, 'met1', 'yoffset', 0.17)
      chip.set('pdk','grid', stackup, 'met1', 'ypitch',  0.34)
      chip.set('pdk','grid', stackup, 'met1', 'adj', 0.5)
  
      chip.set('pdk','grid', stackup, 'met2', 'name', 'm2')
      chip.set('pdk','grid', stackup, 'met2', 'xoffset', 0.23)
      chip.set('pdk','grid', stackup, 'met2', 'xpitch',  0.46)
      chip.set('pdk','grid', stackup, 'met2', 'yoffset', 0.23)
      chip.set('pdk','grid', stackup, 'met2', 'ypitch',  0.46)
      chip.set('pdk','grid', stackup, 'met2', 'adj', 0.5)
  
      chip.set('pdk','grid', stackup, 'met3', 'name', 'm3')
      chip.set('pdk','grid', stackup, 'met3', 'xoffset', 0.34)
      chip.set('pdk','grid', stackup, 'met3', 'xpitch',  0.68)
      chip.set('pdk','grid', stackup, 'met3', 'yoffset', 0.34)
      chip.set('pdk','grid', stackup, 'met3', 'ypitch',  0.68)
      chip.set('pdk','grid', stackup, 'met3', 'adj', 0.5)
  
      chip.set('pdk','grid', stackup, 'met4', 'name', 'm4')
      chip.set('pdk','grid', stackup, 'met4', 'xoffset', 0.46)
      chip.set('pdk','grid', stackup, 'met4', 'xpitch',  0.92)
      chip.set('pdk','grid', stackup, 'met4', 'yoffset', 0.46)
      chip.set('pdk','grid', stackup, 'met4', 'ypitch',  0.92)
      chip.set('pdk','grid', stackup, 'met4', 'adj', 0.5)
  
      chip.set('pdk','grid', stackup, 'met5', 'name', 'm5')
      chip.set('pdk','grid', stackup, 'met5', 'xoffset', 1.7)
      chip.set('pdk','grid', stackup, 'met5', 'xpitch',  3.4)
      chip.set('pdk','grid', stackup, 'met5', 'yoffset', 1.7)
      chip.set('pdk','grid', stackup, 'met5', 'ypitch',  3.4)
      chip.set('pdk','grid', stackup, 'met5', 'adj', 0.5)
  
      # Defaults for OpenROAD tool variables
      chip.set('pdk', 'variable', stackup, 'openroad', 'place_density', ['0.6'])
      chip.set('pdk', 'variable', stackup, 'openroad', 'pad_global_place', ['4'])
      chip.set('pdk', 'variable', stackup, 'openroad', 'pad_detail_place', ['2'])
      chip.set('pdk', 'variable', stackup, 'openroad', 'macro_place_halo', ['1', '1'])
      chip.set('pdk', 'variable', stackup, 'openroad', 'macro_place_channel', ['80', '80'])
  
  #########################
  if __name__ == "__main__":
  
      chip = make_docs()
      chip.writecfg('skywater130.json')
  
  
  [... the rest is omitted ...]
files: siliconcompiler/pdks/skywater130.py
files: 
  import os
  import sys
  import re
  import siliconcompiler
  
  ############################################################################
  # DOCS
  ############################################################################
  
  def make_docs():
      '''
      The 'skywater130' Open Source PDK is a collaboration between Google and
      SkyWater Technology Foundry to provide a fully open source Process
      Design Kit and related resources, which can be used to create
      manufacturable designs at SkyWaterâ€™s facility.
  
      Skywater130 Process Highlights:
      * 130nm process
      * support for internal 1.8V with 5.0V I/Os (operable at 2.5V)
      * 1 level of local interconnect
      * 5 levels of metal
  
      PDK content:
      * An open source design rule manual
      * multiple standard digital cell libraries
      * primitive cell libraries and models for creating analog designs
      * EDA support files for multiple open source and proprietary flows
  
      More information:
      * https://skywater-pdk.readthedocs.io/en/latest/
  
      Sources:
      * https://github.com/google/skywater-pdk
  
      '''
  
      chip = siliconcompiler.Chip()
      setup(chip)
  
      return chip
  
  ####################################################
  # PDK Setup
  ####################################################
  
  def setup(chip):
      '''
      Setup function for the skywater130 PDK.
      '''
  
      foundry = 'skywater'
      process = 'skywater130'
      rev = 'v0_0_2'
      stackup = '5M1LI'
  
      # TODO: eventualy support hs libtype as well
      libtype = 'hd'
      node = 130
      # TODO: dummy numbers, only matter for cost estimation
      wafersize = 300
      hscribe = 0.1
      vscribe = 0.1
      edgemargin = 2
  
      pdkdir = os.path.join('..', 'third_party', 'pdks', foundry, process, 'pdk', rev)
  
      #if you are calling this file, you are in asic mode
      chip.set('mode','asic', clobber = True)
  
      # process name
      chip.set('pdk','foundry', foundry)
      chip.set('pdk','process', process)
      chip.set('pdk','node', node)
      chip.set('pdk','version', rev)
      chip.set('pdk','stackup', stackup)
      chip.set('pdk','wafersize', wafersize)
      chip.set('pdk','edgemargin', edgemargin)
      chip.set('pdk','hscribe', hscribe)
      chip.set('pdk','vscribe', vscribe)
  
      # Values chosen based on
      # https://github.com/The-OpenROAD-Project/OpenROAD-flow-scripts/blob/59ad47a1325239b578bf1c2b3cf6617e44d05d47/flow/platforms/sky130hd/tapcell.tcl
      chip.set('pdk','tapmax', 14)
      chip.set('pdk','tapoffset', 2)
  
      # Tech file
      for tool in ('openroad', 'klayout', 'magic'):
          chip.set('pdk','aprtech',tool,stackup, libtype,'lef',
                   pdkdir+'/apr/sky130_fd_sc_hd.tlef')
  
      # DRC Runsets
      chip.set('pdk','drc','magic', stackup, 'runset', pdkdir+'/setup/magic/sky130A.tech')
  
      # LVS Runsets
      chip.set('pdk','lvs','netgen', stackup, 'runset', pdkdir+'/setup/netgen/lvs_setup.tcl')
  
      # Layer map
      chip.set('pdk','layermap','klayout',stackup, 'def', 'gds', pdkdir+'/setup/klayout/skywater130.lyt')
  
      # Routing Grid Definitions
  
      # TODO: what should the SC-internal name of the LI layer be?
      chip.set('pdk','grid', stackup, 'li1', 'name', 'li1')
      chip.set('pdk','grid', stackup, 'li1', 'xoffset', 0.23)
      chip.set('pdk','grid', stackup, 'li1', 'xpitch',  0.46)
      chip.set('pdk','grid', stackup, 'li1', 'yoffset', 0.17)
      chip.set('pdk','grid', stackup, 'li1', 'ypitch',  0.34)
      chip.set('pdk','grid', stackup, 'li1', 'adj', 1.0)
  
      chip.set('pdk','grid', stackup, 'met1', 'name', 'm1')
      chip.set('pdk','grid', stackup, 'met1', 'xoffset', 0.17)
      chip.set('pdk','grid', stackup, 'met1', 'xpitch',  0.34)
      chip.set('pdk','grid', stackup, 'met1', 'yoffset', 0.17)
      chip.set('pdk','grid', stackup, 'met1', 'ypitch',  0.34)
      chip.set('pdk','grid', stackup, 'met1', 'adj', 0.5)
  
      chip.set('pdk','grid', stackup, 'met2', 'name', 'm2')
      chip.set('pdk','grid', stackup, 'met2', 'xoffset', 0.23)
      chip.set('pdk','grid', stackup, 'met2', 'xpitch',  0.46)
      chip.set('pdk','grid', stackup, 'met2', 'yoffset', 0.23)
      chip.set('pdk','grid', stackup, 'met2', 'ypitch',  0.46)
      chip.set('pdk','grid', stackup, 'met2', 'adj', 0.5)
  
      chip.set('pdk','grid', stackup, 'met3', 'name', 'm3')
      chip.set('pdk','grid', stackup, 'met3', 'xoffset', 0.34)
      chip.set('pdk','grid', stackup, 'met3', 'xpitch',  0.68)
      chip.set('pdk','grid', stackup, 'met3', 'yoffset', 0.34)
      chip.set('pdk','grid', stackup, 'met3', 'ypitch',  0.68)
      chip.set('pdk','grid', stackup, 'met3', 'adj', 0.5)
  
      chip.set('pdk','grid', stackup, 'met4', 'name', 'm4')
      chip.set('pdk','grid', stackup, 'met4', 'xoffset', 0.46)
      chip.set('pdk','grid', stackup, 'met4', 'xpitch',  0.92)
      chip.set('pdk','grid', stackup, 'met4', 'yoffset', 0.46)
      chip.set('pdk','grid', stackup, 'met4', 'ypitch',  0.92)
      chip.set('pdk','grid', stackup, 'met4', 'adj', 0.5)
  
      chip.set('pdk','grid', stackup, 'met5', 'name', 'm5')
      chip.set('pdk','grid', stackup, 'met5', 'xoffset', 1.7)
      chip.set('pdk','grid', stackup, 'met5', 'xpitch',  3.4)
      chip.set('pdk','grid', stackup, 'met5', 'yoffset', 1.7)
      chip.set('pdk','grid', stackup, 'met5', 'ypitch',  3.4)
      chip.set('pdk','grid', stackup, 'met5', 'adj', 0.5)
  
  #########################
  if __name__ == "__main__":
  
      chip = make_docs()
      chip.writecfg('skywater130.json')
  
  
  [... the rest is omitted ...]
files: siliconcompiler/pdks/skywater130.py
files: import os
  import re
  import shutil
  import siliconcompiler
  from siliconcompiler.floorplan import _infer_diearea
  
  ####################################################################
  # Make Docs
  ####################################################################
  
  def make_docs():
      '''
      OpenROAD is an automated physical design platform for
      integrated circuit design with a complete set of features
      needed to translate a synthesized netlist to a tapeout ready
      GDSII.
  
      Documentation:https://github.com/The-OpenROAD-Project/OpenROAD
  
      Sources: https://github.com/The-OpenROAD-Project/OpenROAD
  
      Installation: https://github.com/The-OpenROAD-Project/OpenROAD-flow-scripts
  
      '''
  
      chip = siliconcompiler.Chip()
      chip.set('arg', 'step', '<step>')
      chip.set('arg', 'index', '<index>')
      chip.set('design', '<design>')
      setup(chip)
  
      return chip
  
  ################################
  # Setup Tool (pre executable)
  ################################
  
  def setup(chip, mode='batch'):
  
      # default tool settings, note, not additive!
  
      tool = 'openroad'
      refdir = 'tools/'+tool
      step = chip.get('arg', 'step')
      index = chip.get('arg', 'index')
  
      if mode == 'show':
          clobber = True
          script = '/sc_display.tcl'
          option = "-no_init -gui"
      else:
          clobber = False
          script = '/sc_apr.tcl'
          option = "-no_init"
  
      # exit automatically in batch mode and not bkpt
      if (mode=='batch') and (step not in chip.get('bkpt')):
          option += " -exit"
  
      chip.set('eda', tool, 'exe', tool, clobber=clobber)
      chip.set('eda', tool, 'vswitch', '-version', clobber=clobber)
      chip.set('eda', tool, 'version', 'v2.0', clobber=clobber)
      chip.set('eda', tool, 'format', 'tcl', clobber=clobber)
      chip.set('eda', tool, 'copy', 'true', clobber=clobber)
      chip.set('eda', tool, 'option',  step, index, option, clobber=clobber)
      chip.set('eda', tool, 'refdir',  step, index, refdir, clobber=clobber)
      chip.set('eda', tool, 'script',  step, index, refdir + script, clobber=clobber)
      chip.set('eda', tool, 'threads', step, index, os.cpu_count(), clobber=clobber)
  
      # Input/Output requirements
      if step == 'floorplan':
          if (not chip.valid('read', 'netlist', step, index) or
              not chip.get('read', 'netlist', step, index)):
              chip.add('eda', tool, 'input', step, index, chip.get('design') +'.vg')
      else:
          if (not chip.valid('read', 'def', step, index) or
              not chip.get('read', 'def', step, index)):
              chip.add('eda', tool, 'input', step, index, chip.get('design') +'.def')
  
      chip.add('eda', tool, 'output', step, index, chip.get('design') + '.sdc')
      chip.add('eda', tool, 'output', step, index, chip.get('design') + '.vg')
      chip.add('eda', tool, 'output', step, index, chip.get('design') + '.def')
  
      # openroad makes use of these parameters
      targetlibs = chip.get('asic', 'logiclib')
      stackup = chip.get('asic', 'stackup')
      if stackup and targetlibs:
          mainlib = targetlibs[0]
          macrolibs = chip.get('asic', 'macrolib')
          libtype = str(chip.get('library', mainlib, 'arch'))
  
          chip.add('eda', tool, 'require', step, index, ",".join(['asic', 'logiclib']))
          chip.add('eda', tool, 'require', step, index, ",".join(['asic', 'stackup']))
          chip.add('eda', tool, 'require', step, index, ",".join(['library', mainlib, 'arch']))
          chip.add('eda', tool, 'require', step, index, ",".join(['pdk', 'aprtech', 'openroad', stackup, libtype, 'lef']))
  
          for lib in (targetlibs + macrolibs):
              for corner in chip.getkeys('library', lib, 'nldm'):
                  chip.add('eda', tool, 'require', step, index, ",".join(['library', lib, 'nldm', corner, 'lib']))
              chip.add('eda', tool, 'require', step, index, ",".join(['library', lib, 'lef']))
      else:
          chip.error = 1
          chip.logger.error(f'Stackup and logiclib parameters required for OpenROAD.')
  
      variables = (
          'place_density',
          'pad_global_place',
          'pad_detail_place',
          'macro_place_halo',
          'macro_place_channel'
      )
      for variable in variables:
          # For each OpenROAD tool variable, read default from PDK and write it
          # into schema. If PDK doesn't contain a default, the value must be set
          # by the user, so we add the variable keypath as a requirement.
          if chip.valid('pdk', 'variable', tool, stackup, variable):
              value = chip.get('pdk', 'variable', tool, stackup, variable)
              # Clobber needs to be False here, since a user might want to
              # overwrite these.
              chip.set('eda', tool, 'variable', step, index, variable, value,
                       clobber=False)
  
          keypath = ','.join(['eda', tool, 'variable', step, index, variable])
          chip.add('eda', tool, 'require', step, index, keypath)
  
      for clock in chip.getkeys('clock'):
          chip.add('eda', tool, 'require', step, index, ','.join(['clock', clock, 'period']))
          chip.add('eda', tool, 'require', step, index, ','.join(['clock', clock, 'pin']))
  
  ################################
  # Version Check
  ################################
  
  def parse_version(stdout):
      # stdout will be in one of the following forms:
      # - 1 08de3b46c71e329a10aa4e753dcfeba2ddf54ddd
      # - 1 v2.0-880-gd1c7001ad
      # - v2.0-1862-g0d785bd84
  
      # strip off the "1" prefix if it's there
      version = stdout.split()[-1]
  
      # strip off extra details in new version styles
      return version.split('-')[0]
  
  def pre_process(chip):
      step = chip.get('arg', 'step')
  
      # Only do diearea inference if we're on floorplanning step and these
      # parameters are all unset.
      if (step != 'floorplan' or
          chip.get('asic', 'diearea') or
          chip.get('asic', 'corearea') or
          ('floorplan' in chip.getkeys('read', 'def'))):
          return
  
      r = _infer_diearea(chip)
      if r is None:
          return
      diearea, corearea = r
  
      chip.set('asic', 'diearea', diearea)
      chip.set('asic', 'corearea', corearea)
  
  ################################
  # Post_process (post executable)
  ################################
  
  def post_process(chip):
      ''' Tool specific function to run after step execution
      '''
  
      #Check log file for errors and statistics
      tool = 'openroad'
      step = chip.get('arg', 'step')
      index = chip.get('arg', 'index')
      design = chip.get('design')
      logfile = f"{step}.log"
  
      # basic warning and error grep check on logfile
      chip.set('eda', tool, 'regex', step, index, 'warnings', "WARNING", clobber=False)
      chip.set('eda', tool, 'regex', step, index, 'errors', "ERROR", clobber=False)
  
      # reports
      for metric in chip.getkeys('metric', step, index):
          if metric not in ('runtime', 'memory',
                            'luts', 'dsps', 'brams'):
              chip.set('eda', tool, 'report', step, index, metric, logfile)
  
      # parsing log file
      errors = 0
      warnings = 0
      metric = None
  
      with open(logfile) as f:
          for line in f:
              metricmatch = re.search(r'^SC_METRIC:\s+(\w+)', line)
             
  
  [... the rest is omitted ...]
files: siliconcompiler/tools/openroad/openroad.py
files: import os
  import re
  import shutil
  import siliconcompiler
  from siliconcompiler.floorplan import _infer_diearea
  
  ####################################################################
  # Make Docs
  ####################################################################
  
  def make_docs():
      '''
      OpenROAD is an automated physical design platform for
      integrated circuit design with a complete set of features
      needed to translate a synthesized netlist to a tapeout ready
      GDSII.
  
      Documentation:https://github.com/The-OpenROAD-Project/OpenROAD
  
      Sources: https://github.com/The-OpenROAD-Project/OpenROAD
  
      Installation: https://github.com/The-OpenROAD-Project/OpenROAD-flow-scripts
  
      '''
  
      chip = siliconcompiler.Chip()
      chip.set('arg', 'step', '<step>')
      chip.set('arg', 'index', '<index>')
      chip.set('design', '<design>')
      setup(chip)
  
      return chip
  
  ################################
  # Setup Tool (pre executable)
  ################################
  
  def setup(chip, mode='batch'):
  
      # default tool settings, note, not additive!
  
      tool = 'openroad'
      refdir = 'tools/'+tool
      step = chip.get('arg', 'step')
      index = chip.get('arg', 'index')
  
      if mode == 'show':
          clobber = True
          script = '/sc_display.tcl'
          option = "-no_init -gui"
      else:
          clobber = False
          script = '/sc_apr.tcl'
          option = "-no_init"
  
      # exit automatically in batch mode and not bkpt
      if (mode=='batch') and (step not in chip.get('bkpt')):
          option += " -exit"
  
      chip.set('eda', tool, 'exe', tool, clobber=clobber)
      chip.set('eda', tool, 'vswitch', '-version', clobber=clobber)
      chip.set('eda', tool, 'version', 'v2.0', clobber=clobber)
      chip.set('eda', tool, 'format', 'tcl', clobber=clobber)
      chip.set('eda', tool, 'copy', 'true', clobber=clobber)
      chip.set('eda', tool, 'option',  step, index, option, clobber=clobber)
      chip.set('eda', tool, 'refdir',  step, index, refdir, clobber=clobber)
      chip.set('eda', tool, 'script',  step, index, refdir + script, clobber=clobber)
      chip.set('eda', tool, 'threads', step, index, os.cpu_count(), clobber=clobber)
  
      # Input/Output requirements
      if step == 'floorplan':
          if (not chip.valid('read', 'netlist', step, index) or
              not chip.get('read', 'netlist', step, index)):
              chip.add('eda', tool, 'input', step, index, chip.get('design') +'.vg')
      else:
          if (not chip.valid('read', 'def', step, index) or
              not chip.get('read', 'def', step, index)):
              chip.add('eda', tool, 'input', step, index, chip.get('design') +'.def')
  
      chip.add('eda', tool, 'output', step, index, chip.get('design') + '.sdc')
      chip.add('eda', tool, 'output', step, index, chip.get('design') + '.vg')
      chip.add('eda', tool, 'output', step, index, chip.get('design') + '.def')
  
      # openroad makes use of these parameters
      targetlibs = chip.get('asic', 'logiclib')
      stackup = chip.get('asic', 'stackup')
      if stackup and targetlibs:
          mainlib = targetlibs[0]
          macrolibs = chip.get('asic', 'macrolib')
          libtype = str(chip.get('library', mainlib, 'arch'))
  
          chip.add('eda', tool, 'require', step, index, ",".join(['asic', 'logiclib']))
          chip.add('eda', tool, 'require', step, index, ",".join(['asic', 'stackup']))
          chip.add('eda', tool, 'require', step, index, ",".join(['library', mainlib, 'arch']))
          chip.add('eda', tool, 'require', step, index, ",".join(['pdk', 'aprtech', 'openroad', stackup, libtype, 'lef']))
  
          for lib in (targetlibs + macrolibs):
              for corner in chip.getkeys('library', lib, 'nldm'):
                  chip.add('eda', tool, 'require', step, index, ",".join(['library', lib, 'nldm', corner, 'lib']))
              chip.add('eda', tool, 'require', step, index, ",".join(['library', lib, 'lef']))
      else:
          chip.error = 1
          chip.logger.error(f'Stackup and logiclib parameters required for OpenROAD.')
  
  
      # defining default dictionary
      default_options = {
          'place_density': [],
          'pad_global_place': [],
          'pad_detail_place': [],
          'macro_place_halo': [],
          'macro_place_channel': []
      }
  
      # Setting up technologies with default values
      # NOTE: no reasonable defaults, for halo and channel.
      # TODO: Could possibly scale with node number for default, but safer to error out?
      # perhaps we should use node as comp instead?
      if chip.get('pdk', 'process'):
          process = chip.get('pdk', 'process')
          if process == 'freepdk45':
              default_options = {
                  'place_density': ['0.3'],
                  'pad_global_place': ['2'],
                  'pad_detail_place': ['1'],
                  'macro_place_halo': ['22.4', '15.12'],
                  'macro_place_channel': ['18.8', '19.95']
              }
          elif process == 'asap7':
              default_options = {
                  'place_density': ['0.77'],
                  'pad_global_place': ['2'],
                  'pad_detail_place': ['1'],
                  'macro_place_halo': ['22.4', '15.12'],
                  'macro_place_channel': ['18.8', '19.95']
              }
          elif process == 'skywater130':
              default_options = {
                  'place_density': ['0.6'],
                  'pad_global_place': ['4'],
                  'pad_detail_place': ['2'],
                  'macro_place_halo': ['1', '1'],
                  'macro_place_channel': ['80', '80']
              }
          else:
              chip.error = 1
              chip.logger.error(f'Process {process} not supported with OpenROAD.')
      else:
          default_options = {
              'place_density': ['1'],
              'pad_global_place': ['<space>'],
              'pad_detail_place': ['<space>'],
              'macro_place_halo': ['<xspace>', '<yspace>'],
              'macro_place_channel': ['<xspace>', '<yspace>']
          }
  
      for option in default_options:
          if chip.valid('eda', tool, 'variable', step, index, option, quiet=True, default_valid=False):
              chip.logger.info('User provided variable %s OpenROAD flow detected.', option)
          elif not default_options[option]:
              chip.error = 1
              chip.logger.error('Missing variable %s for OpenROAD.', option)
          else:
              chip.set('eda', tool, 'variable', step, index, option, default_options[option], clobber=clobber)
  
      for clock in chip.getkeys('clock'):
          chip.add('eda', tool, 'require', step, index, ','.join(['clock', clock, 'period']))
          chip.add('eda', tool, 'require', step, index, ','.join(['clock', clock, 'pin']))
  
  ################################
  # Version Check
  ################################
  
  def parse_version(stdout):
      # stdout will be in one of the following forms:
      # - 1 08de3b46c71e329a10aa4e753dcfeba2ddf54ddd
      # - 1 v2.0-880-gd1c7001ad
      # - v2.0-1862-g0d785bd84
  
      # strip off the "1" prefix if it's there
      version = stdout.split()[-1]
  
      # strip off extra details in new version styles
      return version.split('-')[0]
  
  def pre_process(chip):
      step = chip.get('arg', 'step')
  
      # Only do diearea inference if we're on floorplanning step and these
      # parameters are all unset.
      if (step != 'floorplan' or
         
  
  [... the rest is omitted ...]
files: siliconcompiler/tools/openroad/openroad.py