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:
parent
3e115eb056
commit
3d0431b238
|
@ -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')
|
||||
|
|
|
@ -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')
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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 ) )
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) ); }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue