In CRL, update real conf. files. Smarter management of pin in LEF parser.

* Change: In CRL Core, etc/, update the configuration files of real
    technologies. Mostly for FreePDK 45. This work is also done for
    AMS c35b4 (350nm) but in a private (SoC) git repository.
      Added a new parameter 'lefImport.minTerminalwidth' for the
    minimum size (width) of a metal1 terminal in standard cells.
      Corrected bug of the minimum trace level which must be
    initialized to a great value and *not* zero;
* Change: In CRL Core, BlifParser, detect when there is no tie low
    or tie high defined, issue an error (connexion left open) but
    continue.
* New: In CRL::RoutingLayerGauge, new overlad of getTrackPosition()
    with the parameter set of getTrackIndex(). Used to know if a
    terminal is on-grid or not.
* New: In CRL::LefImport, smarter management of metal1 pins. Adds a
    _pinPostProcess() function to select the external components
    among the various shapes. If the gauge is VH, all the pin rectangles
    are translateds into vertical segments (even if the metal1 gauge
    says the tracks are horizontals).
      The _pinPostProcess() function adds as external components of
    a net, only the segments of a sufficent width as given in
    'lefImport.minTerminalWidth' and that are on-grid.
This commit is contained in:
Jean-Paul Chaput 2018-01-06 16:18:33 +01:00
parent 3e115eb056
commit 3d0431b238
13 changed files with 285 additions and 128 deletions

View File

@ -7,7 +7,8 @@ execfile( helpers.sysConfDir+'/common/kite.conf' )
parametersTable = \
( ("katabatic.globalLengthThreshold",TypeInt ,1450 ) # Katabatic parameters.
( ('lefImport.minTerminalWidth' ,TypeDouble ,0.0 )
, ("katabatic.globalLengthThreshold",TypeInt ,1450 ) # Katabatic parameters.
, ("katabatic.saturateRatio" ,TypePercentage,80 )
, ("katabatic.saturateRp" ,TypeInt ,8 )
, ('katabatic.topRoutingLayer' ,TypeString , 'METAL5')

View File

@ -3,3 +3,11 @@
import helpers
execfile( helpers.sysConfDir+'/common/etesian.conf' )
parametersTable = helpers.overload \
( parametersTable
, ( ('etesian.feedNames', TypeString, 'FILL' )
, ('etesian.cell.zero', TypeString, 'missing_tie_low' )
, ('etesian.cell.one' , TypeString, 'missing_tie_high')
)
)

View File

@ -9,10 +9,12 @@ helpers.micronsMode()
parametersTable = \
( ("katabatic.globalLengthThreshold",TypeInt ,1450 ) # Katabatic parameters.
( ('lefImport.minTerminalWidth' ,TypeDouble ,0.065 )
, ("katabatic.globalLengthThreshold",TypeInt ,1450 ) # Katabatic parameters.
, ("katabatic.saturateRatio" ,TypePercentage,80 )
, ("katabatic.saturateRp" ,TypeInt ,8 )
, ('katabatic.topRoutingLayer' ,TypeString , 'METAL5')
, ('katabatic.topRoutingLayer' ,TypeString , 'metal5')
, ('anabatic.routingGauge' ,TypeString , 'gscl45')
# Kite parameters.
, ("kite.hTracksReservedLocal" ,TypeInt ,4 , { 'min':0, 'max':18 } )
, ("kite.vTracksReservedLocal" ,TypeInt ,3 , { 'min':0, 'max':18 } )
@ -41,16 +43,16 @@ parametersTable = \
routingGaugesTable = {}
routingGaugesTable['gscl45'] = \
( ( 'METAL1' , ( Gauge.Vertical , Gauge.PinOnly, 0, 0.0, 0, 0.190, 0.065, 0.650, 7 ) )
, ( 'METAL2' , ( Gauge.Horizontal, Gauge.Default, 1, 0.0, 0, 0.190, 0.075, 0.700, 8 ) )
, ( 'METAL3' , ( Gauge.Vertical , Gauge.Default, 2, 0.0, 0, 0.190, 0.070, 0.700, 8 ) )
, ( 'METAL4' , ( Gauge.Horizontal, Gauge.Default, 3, 0.0, 0, 0.285, 0.140, 0.140, 8 ) )
, ( 'METAL5' , ( Gauge.Vertical , Gauge.Default, 4, 0.0, 0, 0.285, 0.140, 0.140, 8 ) )
, ( 'METAL6' , ( Gauge.Horizontal, Gauge.Default, 5, 0.0, 0, 0.285, 0.140, 0.140, 8 ) )
#, ( 'METAL7' , ( Gauge.Vertical , Gauge.Default, 5, 0.0, 0, 0.855, 0.400, 0.400, 8 ) )
#, ( 'METAL8' , ( Gauge.Horizontal, Gauge.Default, 5, 0.0, 0, 0.855, 0.400, 0.400, 8 ) )
#, ( 'METAL9' , ( Gauge.Vertical , Gauge.Default, 5, 0.0, 0, 1.710, 0.800, 0.800, 8 ) )
#, ( 'METAL10' , ( Gauge.Horizontal, Gauge.Default, 5, 0.0, 0, 1.710, 0.800, 0.800, 8 ) )
( ( 'metal1' , ( Gauge.Horizontal, Gauge.PinOnly, 0, 0.0, 0, 0.190, 0.065, 0.065, 7 ) )
, ( 'metal2' , ( Gauge.Vertical , Gauge.Default, 1, 0.0, 0, 0.190, 0.070, 0.070, 8 ) )
, ( 'metal3' , ( Gauge.Horizontal, Gauge.Default, 2, 0.0, 0, 0.190, 0.070, 0.070, 8 ) )
, ( 'metal4' , ( Gauge.Vertical , Gauge.Default, 3, 0.0, 0, 0.285, 0.140, 0.140, 8 ) )
, ( 'metal5' , ( Gauge.Horizontal, Gauge.Default, 4, 0.0, 0, 0.285, 0.140, 0.140, 8 ) )
, ( 'metal6' , ( Gauge.Vertical , Gauge.Default, 5, 0.0, 0, 0.285, 0.140, 0.140, 8 ) )
, ( 'metal7' , ( Gauge.Horizontal, Gauge.Default, 6, 0.0, 0, 0.855, 0.400, 0.400, 8 ) )
, ( 'metal8' , ( Gauge.Vertical , Gauge.Default, 7, 0.0, 0, 0.855, 0.400, 0.400, 8 ) )
, ( 'metal9' , ( Gauge.Horizontal, Gauge.Default, 8, 0.0, 0, 1.710, 0.800, 0.800, 8 ) )
, ( 'metal10' , ( Gauge.Vertical , Gauge.Default, 9, 0.0, 0, 1.710, 0.800, 0.800, 8 ) )
)

View File

@ -10,13 +10,14 @@
from Hurricane import DbU
# Contains the layers
execfile( helpers.sysConfDir+'/common/technology.conf' )
helpers.micronsMode()
technoConfig = { 'name' : 'freepdk_45'
, 'gridValue' : 0.005
, 'gridValue' : 0.0025
, 'gridUnit' : DbU.UnitPowerMicro
, 'gridsPerLambda': 18
}
@ -163,6 +164,35 @@ layersExtensionsTable = \
, ('VIA910.metal9.enclosure' , 0.5)
, ('VIA910.metal10.enclosure' , 0.5)
# VIAs (i.e. Metal <--> Metal) (real).
, ('via12.minimum.side' , 0.065)
, ('via12.metal1.enclosure' , 0.0 )
, ('via12.metal2.enclosure' , 0.025)
, ('via23.minimum.side' , 0.070)
, ('via23.metal2.enclosure' , 0.0 )
, ('via23.metal3.enclosure' , 0.035)
, ('via34.minimum.side' , 0.070)
, ('via34.metal3.enclosure' , 0.0 )
, ('via34.metal4.enclosure' , 0.035)
, ('via45.minimum.side' , 0.140)
, ('via45.metal4.enclosure' , 0.0 )
, ('via45.metal5.enclosure' , 0.0 )
, ('via56.minimum.side' , 0.140)
, ('via56.metal5.enclosure' , 0.0 )
, ('via56.metal6.enclosure' , 0.0 )
, ('via67.minimum.side' , 0.140)
, ('via67.metal6.enclosure' , 0.0 )
, ('via67.metal7.enclosure' , 0.130)
, ('via78.minimum.side' , 0.200)
, ('via78.metal7.enclosure' , 0.0 )
, ('via78.metal8.enclosure' , 0.0 )
, ('via89.minimum.side' , 0.200)
, ('via89.metal8.enclosure' , 0.0 )
, ('via89.metal9.enclosure' , 0.200)
, ('via910.minimum.side' , 0.400)
, ('via910.metal9.enclosure' , 0.0 )
, ('via910.metal10.enclosure' , 0.0 )
# Blockages (symbolic).
, ('BLOCKAGE1.minimum.width' , 1.0)
, ('BLOCKAGE1.blockage1.extention.cap' , 0.5)

View File

@ -6,6 +6,10 @@ parametersTable = \
, ('etesian.spaceMargin' , TypePercentage, 5 )
, ('etesian.uniformDensity' , TypeBool , False )
, ('etesian.routingDriven' , TypeBool , False )
, ('etesian.feedNames' , TypeString , 'tie_x0,rowend_x0')
, ('etesian.cell.zero' , TypeString , 'zero_x0' )
, ('etesian.cell.one' , TypeString , 'one_x0' )
, ("etesian.effort" , TypeEnumerate , 2
, { 'values':( ("Fast" , 1)
, ("Standard" , 2)

View File

@ -7,8 +7,8 @@ parametersTable = \
, ('misc.logMode' , TypeBool, False)
, ('misc.verboseLevel1', TypeBool, True )
, ('misc.verboseLevel2', TypeBool, False)
, ('misc.minTraceLevel', TypeInt , 0, {'min':0} )
, ('misc.maxTraceLevel', TypeInt , 0, {'min':0} )
, ('misc.minTraceLevel', TypeInt , 100000, {'min':0} )
, ('misc.maxTraceLevel', TypeInt , 0, {'min':0} )
, ('viewer.printer.DPI' , TypeInt , 150, {'min':100} )
, ("viewer.printer.mode", TypeEnumerate , 1

View File

@ -7,7 +7,8 @@ execfile( helpers.sysConfDir+'/common/kite.conf' )
parametersTable = \
( ("katabatic.globalLengthThreshold",TypeInt ,1450 ) # Katabatic parameters.
( ('lefImport.minTerminalWidth' ,TypeDouble ,0.0 )
, ("katabatic.globalLengthThreshold",TypeInt ,1450 ) # Katabatic parameters.
, ("katabatic.saturateRatio" ,TypePercentage,80 )
, ("katabatic.saturateRp" ,TypeInt ,8 )
, ('katabatic.topRoutingLayer' ,TypeString , 'METAL5')

View File

@ -7,7 +7,8 @@ execfile( helpers.sysConfDir+'/common/kite.conf' )
parametersTable = \
( ("katabatic.globalLengthThreshold",TypeInt ,1450 ) # Katabatic parameters.
( ('lefImport.minTerminalWidth' ,TypeDouble ,0.0 )
, ("katabatic.globalLengthThreshold",TypeInt ,1450 ) # Katabatic parameters.
, ("katabatic.saturateRatio" ,TypePercentage,80 )
, ("katabatic.saturateRp" ,TypeInt ,8 )
, ('katabatic.topRoutingLayer' ,TypeString , 'METAL5')

View File

@ -7,7 +7,8 @@ execfile( helpers.sysConfDir+'/common/kite.conf' )
parametersTable = \
( ("katabatic.globalLengthThreshold",TypeInt ,1450 ) # Katabatic parameters.
( ('lefImport.minTerminalWidth' ,TypeDouble ,0.0 )
, ("katabatic.globalLengthThreshold",TypeInt ,1450 ) # Katabatic parameters.
, ("katabatic.saturateRatio" ,TypePercentage,80 )
, ("katabatic.saturateRp" ,TypeInt ,8 )
, ('katabatic.topRoutingLayer' ,TypeString , 'METAL5')

View File

@ -371,7 +371,7 @@ namespace CRL {
void System::_trapSig ( int sig )
{
cerr << "\n\n[CRL ERROR] System::_trapSig():\n" << endl;
cerr << "Program stack:\n" << Backtrace().textWhere() << endl;
cerr << "Program stack:\n" << Backtrace(true).textWhere() << endl;
switch ( sig ) {
case SIGINT:

View File

@ -247,7 +247,13 @@ namespace {
typedef unordered_map<string,Model*> Lut;
static Lut _blifLut;
static vector<Model*> _blifOrder;
static bool _staticInit;
static Cell* _zero;
static Cell* _one;
static Net* _masterNetZero;
static Net* _masterNetOne;
public:
static void staticInit ();
static Model* find ( string modelName );
static void orderModels ();
static void connectModels ();
@ -307,6 +313,11 @@ namespace {
Model::Lut Model::_blifLut;
vector<Model*> Model::_blifOrder;
bool Model::_staticInit = false;
Cell* Model::_zero = NULL;
Cell* Model::_one = NULL;
Net* Model::_masterNetZero = NULL;
Net* Model::_masterNetOne = NULL;
struct CompareByDepth {
@ -318,6 +329,32 @@ namespace {
};
void Model::staticInit ()
{
_staticInit = true;
auto framework = AllianceFramework::get();
static string zeroName = Cfg::getParamString("etesian.cell.zero","zero_x0")->asString();
static string oneName = Cfg::getParamString("etesian.cell.one" , "one_x0")->asString();
_zero = framework->getCell( zeroName, Catalog::State::Views|Catalog::State::Foreign );
_one = framework->getCell( oneName, Catalog::State::Views|Catalog::State::Foreign );
if (_zero) {
for ( Net* net : _zero->getNets() ) if (not net->isSupply()) { _masterNetZero = net; break; }
} else
cerr << Warning( "BlifParser::Model::connectSubckts(): The zero (tie high) cell \"%s\" has not been found."
, zeroName.c_str() ) << endl;
if (_one) {
for ( Net* net : _one->getNets() ) if (not net->isSupply()) { _masterNetOne = net; break; }
} else
cerr << Warning( "BlifParser::Model::connectSubckts(): The one (tie low) cell \"%s\" has not been found."
, oneName.c_str() ) << endl;
}
Model* Model::find ( string modelName )
{
Lut::iterator ibcell = _blifLut.find( modelName );
@ -367,6 +404,8 @@ namespace {
, _subckts()
, _depth (0)
{
if (not _staticInit) staticInit();
_blifLut.insert( make_pair(getString(_cell->getName()), this) );
if (_cell->isTerminal())
_depth = 1;
@ -473,20 +512,7 @@ namespace {
void Model::connectSubckts ()
{
auto framework = AllianceFramework::get();
static string zeroName = Cfg::getParamString("etesian.cell.zero","zero_x0")->asString();
static string oneName = Cfg::getParamString("etesian.cell.one" , "one_x0")->asString();
unsigned int supplyCount = 0;
Cell* zero = framework->getCell( zeroName, Catalog::State::Views|Catalog::State::Foreign );
Cell* one = framework->getCell( oneName, Catalog::State::Views|Catalog::State::Foreign );
Net* masterNetZero = NULL;
for ( Net* net : zero->getNets() ) if (not net->isSupply()) { masterNetZero = net; break; }
Net* masterNetOne = NULL;
for ( Net* net : one->getNets() ) if (not net->isSupply()) { masterNetOne = net; break; }
for ( Subckt* subckt : _subckts ) {
if(not subckt->getModel())
@ -551,27 +577,34 @@ namespace {
<< " is connected to POWER/GROUND " << plugNet->getName()
<< " through the alias " << netName
<< ".";
cerr << Warning( message.str() ) << endl;
if (plugNet->isPower()) {
ostringstream insName; insName << "one_" << supplyCount++;
if (_masterNetOne) {
if (plugNet->isPower()) {
ostringstream insName; insName << "one_" << supplyCount++;
Instance* insOne = Instance::create( _cell, insName.str(), one );
Net* netOne = Net::create( _cell, insName.str() );
Instance* insOne = Instance::create( _cell, insName.str(), _one );
Net* netOne = Net::create( _cell, insName.str() );
insOne->getPlug( masterNetOne )->setNet( netOne );
plug->setNet( netOne );
}
insOne->getPlug( _masterNetOne )->setNet( netOne );
plug->setNet( netOne );
}
} else
message << "\n (no tie high, connexion has been LEFT OPEN)";
if (plugNet->isGround()) {
ostringstream insName; insName << "zero_" << supplyCount++;
if (_masterNetZero) {
if (plugNet->isGround()) {
ostringstream insName; insName << "zero_" << supplyCount++;
Instance* insZero = Instance::create( _cell, insName.str(), zero );
Net* netZero = Net::create( _cell, insName.str() );
Instance* insZero = Instance::create( _cell, insName.str(), _zero );
Net* netZero = Net::create( _cell, insName.str() );
insZero->getPlug( masterNetZero )->setNet( netZero );
plug->setNet( netZero );
}
insZero->getPlug( _masterNetZero )->setNet( netZero );
plug->setNet( netZero );
}
} else
message << "\n (no tie low, connexion has been LEFT OPEN)";
if (not message.str().empty()) cerr << Warning( message.str() ) << endl;
}
}
}

View File

@ -109,6 +109,7 @@ namespace CRL {
void divide ( DbU::Unit dividend, long& quotient, long& modulo ) const;
unsigned int getTrackNumber ( DbU::Unit start, DbU::Unit stop ) const;
unsigned int getTrackIndex ( DbU::Unit start, DbU::Unit stop, DbU::Unit position, unsigned mode ) const;
inline DbU::Unit getTrackPosition ( DbU::Unit start, DbU::Unit stop, DbU::Unit position, unsigned mode ) const;
DbU::Unit getTrackPosition ( DbU::Unit start, unsigned depth ) const;
// Hurricane Managment.
void toJson ( JsonWriter* ) const;
@ -181,6 +182,8 @@ namespace CRL {
inline DbU::Unit RoutingLayerGauge::getViaWidth () const { return _viaWidth; }
inline DbU::Unit RoutingLayerGauge::getHalfViaWidth () const { return _viaWidth>>1; }
inline DbU::Unit RoutingLayerGauge::getObstacleDw () const { return _obstacleDw; }
inline DbU::Unit RoutingLayerGauge::getTrackPosition ( DbU::Unit start, DbU::Unit stop, DbU::Unit position, unsigned mode ) const
{ return getTrackPosition( start, getTrackIndex(start,stop,position,mode) ); }
// -------------------------------------------------------------------

View File

@ -14,33 +14,34 @@
// +-----------------------------------------------------------------+
#include <cstdio>
#include <cstring>
#include <iostream>
#include <memory>
#include <boost/algorithm/string.hpp>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <memory>
#include <boost/algorithm/string.hpp>
#if defined(HAVE_LEFDEF)
# include "lefrReader.hpp"
#endif
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DataBase.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/Contact.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/Cell.h"
#include "hurricane/Library.h"
#include "hurricane/UpdateSession.h"
#include "crlcore/Utilities.h"
#include "crlcore/ToolBox.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/CellGauge.h"
#include "crlcore/AllianceFramework.h"
#include "crlcore/LefImport.h"
#include "vlsisapd/configuration/Configuration.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DataBase.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/Contact.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/Cell.h"
#include "hurricane/Library.h"
#include "hurricane/UpdateSession.h"
#include "crlcore/Utilities.h"
#include "crlcore/ToolBox.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/CellGauge.h"
#include "crlcore/AllianceFramework.h"
#include "crlcore/LefImport.h"
#if defined(HAVE_LEFDEF)
@ -77,6 +78,7 @@ namespace {
static Library* parse ( string file );
LefParser ( string file, string libraryName );
~LefParser ();
inline bool isVH () const;
Library* createLibrary ();
inline string getLibraryName () const;
inline Library* getLibrary ( bool create=false );
@ -102,6 +104,8 @@ namespace {
inline void incNthCut ();
inline RoutingGauge* getRoutingGauge () const;
inline CellGauge* getCellGauge () const;
inline void addPinSegment ( string name, Segment* );
inline void clearPinSegments ();
private:
static int _unitsCbk ( lefrCallbackType_e, lefiUnits* , lefiUserData );
static int _layerCbk ( lefrCallbackType_e, lefiLayer* , lefiUserData );
@ -109,6 +113,7 @@ namespace {
static int _obstructionCbk ( lefrCallbackType_e, lefiObstruction*, lefiUserData );
static int _macroCbk ( lefrCallbackType_e, lefiMacro* , lefiUserData );
static int _pinCbk ( lefrCallbackType_e, lefiPin* , lefiUserData );
void _pinPostProcess ();
private:
string _file;
string _libraryName;
@ -117,6 +122,7 @@ namespace {
Net* _net;
string _busBits;
double _unitsMicrons;
map< string, vector<Segment*> > _pinSegments;
static map<string,Layer*> _layerLut;
vector<string> _errors;
int _nthMetal;
@ -129,29 +135,32 @@ namespace {
};
inline DbU::Unit LefParser::getMinTerminalWidth () const { return _minTerminalWidth; }
inline string LefParser::getLibraryName () const { return _libraryName; }
inline Library* LefParser::getLibrary ( bool create ) { if (not _library and create) createLibrary(); return _library; }
inline Cell* LefParser::getCell () const { return _cell; }
inline void LefParser::setCell ( Cell* cell ) { _cell=cell; }
inline Net* LefParser::getNet () const { return _net; }
inline void LefParser::setNet ( Net* net ) { _net=net; }
inline DbU::Unit LefParser::fromUnitsMicrons ( double d ) const { return DbU::fromPhysical(d,DbU::Micro); }
inline double LefParser::getUnitsMicrons () const { return _unitsMicrons; }
inline void LefParser::setUnitsMicrons ( double precision ) { _unitsMicrons=precision; }
inline int LefParser::getNthMetal () const { return _nthMetal; }
inline void LefParser::incNthMetal () { ++_nthMetal; }
inline int LefParser::getNthCut () const { return _nthCut; }
inline void LefParser::incNthCut () { ++_nthCut; }
inline RoutingGauge* LefParser::getRoutingGauge () const { return _routingGauge; }
inline CellGauge* LefParser::getCellGauge () const { return _cellGauge; }
inline void LefParser::setCoreSite ( DbU::Unit x, DbU::Unit y ) { _coreSiteX=x; _coreSiteY=y; }
inline DbU::Unit LefParser::getCoreSiteX () { return _coreSiteX; }
inline DbU::Unit LefParser::getCoreSiteY () { return _coreSiteY; }
inline bool LefParser::hasErrors () const { return not _errors.empty(); }
inline const vector<string>& LefParser::getErrors () const { return _errors; }
inline void LefParser::pushError ( const string& error ) { _errors.push_back(error); }
inline void LefParser::clearErrors () { return _errors.clear(); }
inline bool LefParser::isVH () const { return _routingGauge->isVH(); }
inline DbU::Unit LefParser::getMinTerminalWidth () const { return _minTerminalWidth; }
inline string LefParser::getLibraryName () const { return _libraryName; }
inline Library* LefParser::getLibrary ( bool create ) { if (not _library and create) createLibrary(); return _library; }
inline Cell* LefParser::getCell () const { return _cell; }
inline void LefParser::setCell ( Cell* cell ) { _cell=cell; }
inline Net* LefParser::getNet () const { return _net; }
inline void LefParser::setNet ( Net* net ) { _net=net; }
inline DbU::Unit LefParser::fromUnitsMicrons ( double d ) const { return DbU::fromPhysical(d,DbU::Micro); }
inline double LefParser::getUnitsMicrons () const { return _unitsMicrons; }
inline void LefParser::setUnitsMicrons ( double precision ) { _unitsMicrons=precision; }
inline int LefParser::getNthMetal () const { return _nthMetal; }
inline void LefParser::incNthMetal () { ++_nthMetal; }
inline int LefParser::getNthCut () const { return _nthCut; }
inline void LefParser::incNthCut () { ++_nthCut; }
inline RoutingGauge* LefParser::getRoutingGauge () const { return _routingGauge; }
inline CellGauge* LefParser::getCellGauge () const { return _cellGauge; }
inline void LefParser::setCoreSite ( DbU::Unit x, DbU::Unit y ) { _coreSiteX=x; _coreSiteY=y; }
inline DbU::Unit LefParser::getCoreSiteX () { return _coreSiteX; }
inline DbU::Unit LefParser::getCoreSiteY () { return _coreSiteY; }
inline bool LefParser::hasErrors () const { return not _errors.empty(); }
inline const vector<string>& LefParser::getErrors () const { return _errors; }
inline void LefParser::pushError ( const string& error ) { _errors.push_back(error); }
inline void LefParser::clearErrors () { return _errors.clear(); }
inline void LefParser::addPinSegment ( string name, Segment* s ) { _pinSegments[name].push_back(s); }
inline void LefParser::clearPinSegments () { _pinSegments.clear(); }
map<string,Layer*> LefParser::_layerLut;
@ -199,7 +208,7 @@ namespace {
, _nthCut (0)
, _routingGauge (NULL)
, _cellGauge (NULL)
, _minTerminalWidth(DbU::fromPhysical(0.9,DbU::UnitPower::Micro))
, _minTerminalWidth(DbU::fromPhysical(Cfg::getParamDouble("lefImport.minTerminalWidth",0.0)->asDouble(),DbU::UnitPower::Micro))
{
_routingGauge = AllianceFramework::get()->getRoutingGauge();
_cellGauge = AllianceFramework::get()->getCellGauge();
@ -384,21 +393,20 @@ namespace {
lefiGeomRect* r = geoms->getRect(igeom);
double w = r->xh - r->xl;
double h = r->yh - r->yl;
Component* component = NULL;
if (w >= h) {
component = Horizontal::create( blockageNet, layer
, parser->fromUnitsMicrons( (r->yl + r->yh)/2 )
, parser->fromUnitsMicrons( h )
, parser->fromUnitsMicrons( r->xl )
, parser->fromUnitsMicrons( r->xh )
);
Horizontal::create( blockageNet, layer
, parser->fromUnitsMicrons( (r->yl + r->yh)/2 )
, parser->fromUnitsMicrons( h )
, parser->fromUnitsMicrons( r->xl )
, parser->fromUnitsMicrons( r->xh )
);
} else {
component = Vertical::create( blockageNet, layer
, parser->fromUnitsMicrons( (r->xl + r->xh)/2 )
, parser->fromUnitsMicrons( w )
, parser->fromUnitsMicrons( r->yl )
, parser->fromUnitsMicrons( r->yh )
);
Vertical::create( blockageNet, layer
, parser->fromUnitsMicrons( (r->xl + r->xh)/2 )
, parser->fromUnitsMicrons( w )
, parser->fromUnitsMicrons( r->yl )
, parser->fromUnitsMicrons( r->yh )
);
}
}
}
@ -429,6 +437,9 @@ namespace {
cell->setAbutmentBox( Box( 0, 0, width, height ) );
}
parser->_pinPostProcess();
parser->clearPinSegments();
cerr << " - " << cellName << " " << DbU::getValueString(width) << " " << DbU::getValueString(height) << endl;
parser->setCell( NULL );
@ -481,26 +492,25 @@ namespace {
lefiGeomRect* r = geoms->getRect(igeom);
DbU::Unit w = parser->fromUnitsMicrons(r->xh - r->xl);
DbU::Unit h = parser->fromUnitsMicrons(r->yh - r->yl);
Component* component = NULL;
bool isExternal = false;
if (w >= h) {
isExternal = (h >= parser->getMinTerminalWidth());
component = Horizontal::create( net, layer
, parser->fromUnitsMicrons( (r->yl + r->yh)/2 )
, h
, parser->fromUnitsMicrons( r->xl )
, parser->fromUnitsMicrons( r->xh )
);
} else {
isExternal = (w >= parser->getMinTerminalWidth());
component = Vertical::create( net, layer
, parser->fromUnitsMicrons( (r->xl + r->xh)/2 )
, w
, parser->fromUnitsMicrons( r->yl )
, parser->fromUnitsMicrons( r->yh )
Segment* segment = NULL;
float formFactor = (float)w / (float)h;
if ( (formFactor > 0.5) and not parser->isVH() ) {
segment = Horizontal::create( net, layer
, parser->fromUnitsMicrons( (r->yl + r->yh)/2 )
, h
, parser->fromUnitsMicrons( r->xl )
, parser->fromUnitsMicrons( r->xh )
);
} else {
segment = Vertical::create( net, layer
, parser->fromUnitsMicrons( (r->xl + r->xh)/2 )
, w
, parser->fromUnitsMicrons( r->yl )
, parser->fromUnitsMicrons( r->yh )
);
}
if (isExternal) NetExternalComponents::setExternal( component );
if (segment) parser->addPinSegment( pin->name(), segment );
continue;
}
@ -534,6 +544,69 @@ namespace {
}
void LefParser::_pinPostProcess ()
{
const Layer* metal1 = _routingGauge->getLayerGauge( (size_t)0 )->getLayer();
const RoutingLayerGauge* gaugeMetal2 = _routingGauge->getLayerGauge( 1 );
Box ab = _cell->getAbutmentBox();
for ( auto element : _pinSegments ) {
string pinName = element.first;
vector<Segment*>& segments = element.second;
vector<Segment*> ongrids;
for ( Segment* segment : segments ) {
bool isWide = (segment->getWidth() >= getMinTerminalWidth());
if (not segment->getNet()->isSupply()) {
if (isVH() and (segment->getLayer()->getMask() == metal1->getMask())) {
Vertical* v = dynamic_cast<Vertical*>( segment );
if (v) {
DbU::Unit nearestX = gaugeMetal2->getTrackPosition( ab.getXMin()
, ab.getXMax()
, v->getX()
, Constant::Nearest );
if (nearestX == v->getX()) {
} else {
DbU::Unit neighbor = nearestX
+ ((nearestX > v->getX()) ? 1 : -1) * gaugeMetal2->getPitch();
if ( (v->getX() - v->getHalfWidth() > neighbor)
or (v->getX() + v->getHalfWidth() < neighbor) ) {
ongrids.push_back( Vertical::create( v->getNet()
, v->getLayer()
, nearestX
, _routingGauge->getLayerGauge((size_t)0)->getWireWidth()
, v->getDySource()
, v->getDyTarget()
)
);
} else {
// Unpitched and not wide enough to be under a metal2 track, ignore.
}
continue;
}
}
}
}
if (isWide) ongrids.push_back( segment );
}
if (ongrids.empty()) {
cerr << Warning( "LefParser::_pinPostProcess(): Pin \"%s\" has no terminal ongrid."
, pinName.c_str() ) << endl;
} else {
for ( Segment* segment : ongrids ) {
NetExternalComponents::setExternal( segment );
}
}
}
}
int LefParser::flushErrors ()
{
int code = (hasErrors()) ? 1 : 0;