Coriolis Configuration & Initialisation

General Software Architecture

Coriolis has been build with respect of the classical paradigm that the computational instensive parts have been written in C++, and almost everything else in Python. To build the Python interface we used two methods:

  • For self-contained modules boost::python (mainly in vlsisapd).
  • For all modules based on Hurricane, we created our own wrappers due to very specific requirements such as shared functions between modules or C++/Python secure bi-directional object deletion.

Note

Python Documentation: Most of the documentation is related to the C++ API and implemetation of the tools. However, the Python bindings have been created so they mimic as closely as possible the C++ interface, so the documentation applies to both languages with only minor syntactic changes.

Coriolis Software Schematic

All configuration & initialization files are Python scripts, despite their .conf extention. From a syntactic point of view, there is no difference between the system-wide configuration files and the user’s configuration, they use the same Python helpers.

Configuration is done in two stages:

  1. Selecting the technology.
  2. Loading the complete configuration for the given technology and the user’s settings.

First Stage: Technology Selection

The initialization process is done by executing, in order, the following file(s):

Order Meaning File
1 The system setting /etc/coriolis2/techno.conf
2 The user’s global setting ${HOME}/.coriolis2/techno.py
3 The user’s local setting <CWD>/.coriolis2/techno.py

Thoses files must provides only one variable, the name of the technology. Each technology will provide configuration for both the symbolic part and the real part. Coriolis can work with purely symbolic technology (symbolic/cmos) in that case, the real technology part is a dummy one.

For example, to use mosis 180nm:

# -*- Mode:Python -*-

technology = '180/scn6m_deep_09'

Second Stage: Technology Configuration Loading

The technology variable is set by the first stage and it’s the name of the technology. A directory of that name, with all the configuration files, must exists in the configuration directory (/etc/coriolis2). In addition to the technology-specific directories, a common/ directory is there to provides a trunk for all the identical datas across the various technologies. The initialization process is done by executing, in order, the following file(s):

Order Meaning File
1 The system initialization /etc/coriolis2/<technology>/<TOOL>.conf
2 The user’s global initialization ${HOME}/.coriolis2/settings.py
3 The user’s local initialization <CWD>/.coriolis2/settings.py

Note

The loading policy is not hard-coded. It is implemented at Python level in /etc/coriolis2/coriolisInit.py, and thus may be easily amended to whatever site policy.

The truly mandatory requirement is the existence of coriolisInit.py which must contain a coriolisConfigure() function with no argument.

The coriolisInit.py script execution is triggered by the import of the CRL module:

import sys
import os.path
import Cfg
import Hurricane
import CRL        # Triggers execution of "coriolisInit.py".
import Viewer

Configuration Helpers

To ease the writing of configuration files, a set of small helpers is available. They allow to setup the configuration parameters through simple assembly of tuples. The helpers are installed under the directory:

<install>/etc/coriolis2/

Where <install>/ is the root of the installation.

Alliance Helper

The configuration file must provide an allianceConfig tuple as shown below. Like all the Coriolis configuration file, it is to be executed through Python, so we can use it to perform a not so dumb search of the Alliance installation directory. Our default policy is to try to read the ALLIANCE_TOP environment variable, and if not found, default to /soc/alliance.

import os
from helpers.Alliance import AddMode
from helpers.Alliance import Gauge

allianceTop = None
if os.environ.has_key('ALLIANCE_TOP'):
  allianceTop = os.environ['ALLIANCE_TOP']
  if not os.path.isdir(allianceTop):
    allianceTop = None

if not allianceTop: allianceTop = '/soc/alliance'

cellsTop = allianceTop+'/cells/'


allianceConfig = \
    ( ( 'CATALOG'            , 'CATAL')
    , ( 'WORKING_LIBRARY'    , '.')
    , ( 'SYSTEM_LIBRARY'     , ( (cellsTop+'sxlib'   , AddMode.Append)
                               , (cellsTop+'dp_sxlib', AddMode.Append)
                               , (cellsTop+'ramlib'  , AddMode.Append)
                               , (cellsTop+'romlib'  , AddMode.Append)
                               , (cellsTop+'rflib'   , AddMode.Append)
                               , (cellsTop+'rf2lib'  , AddMode.Append)
                               , (cellsTop+'pxlib'   , AddMode.Append)
                               , (cellsTop+'padlib'  , AddMode.Append) ) )
    , ( 'IN_LO'              , 'vst')
    , ( 'IN_PH'              , 'ap')
    , ( 'OUT_LO'             , 'vst')
    , ( 'OUT_PH'             , 'ap')
    , ( 'POWER'              , 'vdd')
    , ( 'GROUND'             , 'vss')
    , ( 'CLOCK'              , '.*ck.*|.*nck.*')
    , ( 'BLOCKAGE'           , '^blockage[Nn]et*')
    , ( 'PAD'                , '.*_px$')
    )

The example above shows the system configuration file, with all the available settings. Some important remarks about thoses settings:

  • In it’s configuration file, the user do not need to redefine all the settings, just the one he wants to change. In most of the cases, the SYSTEM_LIBRARY, the WORKING_LIBRARY and the special net names (at this point there is not much alternatives for the others settings).

  • SYSTEM_LIBRARY setting: Setting up the library search path. Each library entry in the tuple will be added to the search path according to the second parameter:

    • AddMode::Append: append to the search path.
    • AddMode::Prepend: insert in head of the search path.
    • AddMode::Replace: look for a library of the same name and replace it, whithout changing the search path order. If no library of that name already exists, it is appended.

    A library is identified by it’s name, this name is the last component of the path name. For instance: /soc/alliance/sxlib will be named sxlib. Implementing the Alliance specification, when looking for a Cell name, the system will browse sequentially trought the library list and returns the first Cell whose name match.

  • For POWER, GROUND, CLOCK and BLOCKAGE net names, a regular expression (gnu regexp) is expected.

A typical user’s configuration file would be:

import os

homeDir = os.getenv('HOME')

allianceConfig = \
    ( ('WORKING_LIBRARY'    , homeDir+'/worklib')
    , ('SYSTEM_LIBRARY'     , ( (homeDir+'/mylib', Environment.Append) ) )
    , ('POWER'              , 'vdd.*')
    , ('GROUND'             , 'vss.*')
    )

Tools Configuration Helpers

All the tools uses the same helper to load their configuration (a.k.a. Configuration Helper). Currently the following configuration system-wide configuration files are defined:

  • misc.conf: commons settings or not belonging specifically to a tool.
  • etesian.conf: for the Etesian tool.
  • kite.conf: for the Kite tool.
  • stratus1.conf: for the Stratus1 tool.

Here is the contents of etesian.conf:

# Etesian parameters.
parametersTable = \
    ( ('etesian.aspectRatio'    , TypePercentage, 100    , { 'min':10, 'max':1000 } )
    , ('etesian.spaceMargin'    , TypePercentage, 5      )
    , ('etesian.uniformDensity' , TypeBool      , False  )
    , ('etesian.routingDriven'  , TypeBool      , False  )
    , ("etesian.effort"         , TypeEnumerate , 2
      , { 'values':( ("Fast"    , 1)
                   , ("Standard", 2)
                   , ("High"    , 3)
                   , ("Extreme" , 4) ) }
      )
    , ("etesian.graphics"       , TypeEnumerate , 2
      , { 'values':( ("Show every step"  , 1)
                   , ("Show lower bound" , 2)
                   , ("Show result only" , 3) ) }
      )
    )

layoutTable = \
    ( (TypeTab   , 'Etesian', 'etesian')

    , (TypeTitle , 'Placement area')
    , (TypeOption, "etesian.aspectRatio"   , "Aspect Ratio, X/Y (%)", 0 )
    , (TypeOption, "etesian.spaceMargin"   , "Space Margin"         , 1 )
    , (TypeRule  ,)
    , (TypeTitle , 'Etesian - Placer')
    , (TypeOption, "etesian.uniformDensity", "Uniform density"      , 0 )
    , (TypeOption, "etesian.routingDriven" , "Routing driven"       , 0 )
    , (TypeOption, "etesian.effort"        , "Placement effort"     , 1 )
    , (TypeOption, "etesian.graphics"      , "Placement view"       , 1 )
    , (TypeRule  ,)
    )

Taxonomy of the file:

  • It must contains, at least, the two tables:
    • parametersTable, defines & initialise the configuration variables.
    • layoutTables, defines how the various parameters will be displayed in the configuration window (The Settings Tab).
  • The parametersTable, is a tuple (list) of tuples. Each entry in the list describe a configuration parameter. In it’s simplest form, it’s a quadruplet (TypeOption, ‘paramId’, ParameterType, DefaultValue) with:
    1. TypeOption, tells that this tuple describe a parameter.
    2. paramId, the identifier of the parameter. Identifiers are defined by the tools. The list of parameters is detailed in each tool section.
    3. ParameterType, the kind of parameter. Could be:
      • TypeBool, boolean.
      • TypeInt, signed integer.
      • TypeEnumerate, enumerated type, needs extra entry.
      • TypePercentage, percentage, expressed between 0 and 100.
      • TypeDouble, float.
      • TypeString, character string.
    4. DefaultValue, the default value for that parameter.

Hacking the Configuration Files

Asides from the symbols that gets used by the configuration helpers like allianceConfig or parametersTable, you can put pretty much anything in <CWD>/.coriolis2/settings.py (that is, written in Python).

For example:

# -*- Mode:Python -*-

defaultStyle = 'Alliance.Classic [black]'

# Regular Coriolis configuration.
parametersTable = \
    ( ('misc.catchCore'           , TypeBool      , False  )
    , ('misc.info'                , TypeBool      , False  )
    , ('misc.paranoid'            , TypeBool      , False  )
    , ('misc.bug'                 , TypeBool      , False  )
    , ('misc.logMode'             , TypeBool      , True   )
    , ('misc.verboseLevel1'       , TypeBool      , False  )
    , ('misc.verboseLevel2'       , TypeBool      , True   )
    , ('misc.minTraceLevel'       , TypeInt       , 0      )
    , ('misc.maxTraceLevel'       , TypeInt       , 0      )
    )

# Some ordinary Python script...
import os

print '       o  Cleaning up ClockTree previous run.'
for fileName in os.listdir('.'):
  if fileName.endswith('.ap') or (fileName.find('_clocked.') >= 0):
    print '          - <%s>' % fileName
    os.unlink(fileName)

See Python Interface for Hurricane / Coriolis for more details those capabilities.