In BlifParser, correct management of alias to $true/$false for terminals.

* Bug: In CRL/BlifParser::Model::mergeAlias(), when a signal is aliased
    toward $true or $false in a Blif file (through a ".name" statement),
    it was directly merged to "vdd" (resp. "vss"), and if it is an
    external signal, this leads to its removal, potentially making "hole"
    in its interface.
      Now, create a gate zero or one for each tied up/low signal. This
    way the interface is fully kept. At the cost of some supplemental
    gates.
This commit is contained in:
Jean-Paul Chaput 2020-02-24 18:58:48 +01:00
parent 5d968b0997
commit eab4a4aa7f
1 changed files with 112 additions and 41 deletions

View File

@ -252,8 +252,8 @@ namespace {
static bool _staticInit; static bool _staticInit;
static string _groundName; static string _groundName;
static string _powerName; static string _powerName;
static Cell* _zero; static Cell* _zeroCell;
static Cell* _one; static Cell* _oneCell;
static Net* _masterNetZero; static Net* _masterNetZero;
static Net* _masterNetOne; static Net* _masterNetOne;
public: public:
@ -270,6 +270,8 @@ namespace {
Model ( Cell* ); Model ( Cell* );
inline ~Model (); inline ~Model ();
inline Cell* getCell () const; inline Cell* getCell () const;
Net* newOne ();
Net* newZero ();
inline size_t getDepth () const; inline size_t getDepth () const;
inline const Subckts& getSubckts () const; inline const Subckts& getSubckts () const;
Subckt* addSubckt ( string modelName ); Subckt* addSubckt ( string modelName );
@ -281,6 +283,7 @@ namespace {
Cell* _cell; Cell* _cell;
Subckts _subckts; Subckts _subckts;
size_t _depth; size_t _depth;
size_t _supplyCount;
}; };
@ -341,8 +344,8 @@ namespace {
bool Model::_staticInit = false; bool Model::_staticInit = false;
string Model::_groundName = "vss"; string Model::_groundName = "vss";
string Model::_powerName = "vdd"; string Model::_powerName = "vdd";
Cell* Model::_zero = NULL; Cell* Model::_zeroCell = NULL;
Cell* Model::_one = NULL; Cell* Model::_oneCell = NULL;
Net* Model::_masterNetZero = NULL; Net* Model::_masterNetZero = NULL;
Net* Model::_masterNetOne = NULL; Net* Model::_masterNetOne = NULL;
@ -365,13 +368,13 @@ namespace {
static string zeroName = Cfg::getParamString("etesian.cell.zero","zero_x0")->asString(); static string zeroName = Cfg::getParamString("etesian.cell.zero","zero_x0")->asString();
static string oneName = Cfg::getParamString("etesian.cell.one" , "one_x0")->asString(); static string oneName = Cfg::getParamString("etesian.cell.one" , "one_x0")->asString();
_zero = framework->getCell( zeroName, Catalog::State::Views|Catalog::State::Foreign ); _zeroCell = framework->getCell( zeroName, Catalog::State::Views|Catalog::State::Foreign );
_one = framework->getCell( oneName, Catalog::State::Views|Catalog::State::Foreign ); _oneCell = framework->getCell( oneName, Catalog::State::Views|Catalog::State::Foreign );
_groundName = Cfg::getParamString("crlcore.groundName","vss")->asString(); _groundName = Cfg::getParamString("crlcore.groundName","vss")->asString();
_powerName = Cfg::getParamString("crlcore.powerName" ,"vdd")->asString(); _powerName = Cfg::getParamString("crlcore.powerName" ,"vdd")->asString();
if (_zero) { if (_zeroCell) {
for ( Net* net : _zero->getNets() ) for ( Net* net : _zeroCell->getNets() )
if ( not net->isSupply () if ( not net->isSupply ()
and not net->isAutomatic() and not net->isAutomatic()
and not net->isBlockage () ) { _masterNetZero = net; break; } and not net->isBlockage () ) { _masterNetZero = net; break; }
@ -379,8 +382,8 @@ namespace {
cerr << Warning( "BlifParser::Model::connectSubckts(): The zero (tie high) cell \"%s\" has not been found." cerr << Warning( "BlifParser::Model::connectSubckts(): The zero (tie high) cell \"%s\" has not been found."
, zeroName.c_str() ) << endl; , zeroName.c_str() ) << endl;
if (_one) { if (_oneCell) {
for ( Net* net : _one->getNets() ) for ( Net* net : _oneCell->getNets() )
if ( not net->isSupply () if ( not net->isSupply ()
and not net->isAutomatic() and not net->isAutomatic()
and not net->isBlockage () ) { _masterNetOne = net; break; } and not net->isBlockage () ) { _masterNetOne = net; break; }
@ -440,8 +443,9 @@ namespace {
Model::Model ( Cell* cell ) Model::Model ( Cell* cell )
: _cell (cell) : _cell (cell)
, _subckts() , _subckts ()
, _depth (0) , _depth (0)
, _supplyCount (0)
{ {
if (not _staticInit) staticInit(); if (not _staticInit) staticInit();
@ -478,6 +482,34 @@ namespace {
inline const Subckts& Model::getSubckts () const { return _subckts; } inline const Subckts& Model::getSubckts () const { return _subckts; }
Net* Model::newOne ()
{
if (not _masterNetOne) return NULL;
ostringstream name; name << "one_" << _supplyCount++;
Instance* oneInstance = Instance::create( _cell, name.str(), _oneCell );
Net* one = Net::create( _cell, name.str() );
oneInstance->getPlug( _masterNetOne )->setNet( one );
return one;
}
Net* Model::newZero ()
{
if (not _masterNetZero) return NULL;
ostringstream name; name << "zero_" << _supplyCount++;
Instance* zeroInstance = Instance::create( _cell, name.str(), _zeroCell );
Net* zero = Net::create( _cell, name.str() );
zeroInstance->getPlug( _masterNetZero )->setNet( zero );
return zero;
}
Net* Model::mergeNet ( string name, bool isExternal, unsigned int direction ) Net* Model::mergeNet ( string name, bool isExternal, unsigned int direction )
{ {
bool isClock = AllianceFramework::get()->isCLOCK( name ); bool isClock = AllianceFramework::get()->isCLOCK( name );
@ -488,6 +520,8 @@ namespace {
net->setExternal ( isExternal ); net->setExternal ( isExternal );
net->setDirection( (Net::Direction::Code)direction ); net->setDirection( (Net::Direction::Code)direction );
if (isClock) net->setType( Net::Type::CLOCK ); if (isClock) net->setType( Net::Type::CLOCK );
if (_cell->getName() == "sm0") cerr << "sm0 netPlug:" << name << endl;
} else { } else {
net->addAlias( name ); net->addAlias( name );
if (isExternal) net->setExternal( true ); if (isExternal) net->setExternal( true );
@ -495,6 +529,8 @@ namespace {
direction |= net->getDirection(); direction |= net->getDirection();
net->setDirection( (Net::Direction::Code)direction ); net->setDirection( (Net::Direction::Code)direction );
if (isClock) net->setType( Net::Type::CLOCK ); if (isClock) net->setType( Net::Type::CLOCK );
if (_cell->getName() == "sm0") cerr << "sm0 netPlug:" << name << endl;
} }
return net; return net;
} }
@ -505,8 +541,45 @@ namespace {
Net* net1 = _cell->getNet( name1 ); Net* net1 = _cell->getNet( name1 );
Net* net2 = _cell->getNet( name2 ); Net* net2 = _cell->getNet( name2 );
if (_cell->getName() == "sm0") {
cerr << "Merge: " << name1 << " + " << name2 << endl;
cerr << " net1:" << net1 << " net2:" << net2 << endl;
}
if (net1 and (net1 == net2)) return net1; if (net1 and (net1 == net2)) return net1;
if (net1 and net2) { if (net1 and net2) {
if (net1->isSupply() and (net2->isExternal() and not net2->isSupply())) {
ostringstream message;
if (net1->isPower()) {
message << "In model " << _cell->getName() << "\n "
<< "Terminal " << net2->getName()
<< " is connected to POWER " << net1->getName()
<< " through the alias " << name1 << ".";
Net* one = newOne();
if (one) net2->merge( one );
else
message << "\n (no tie high, connexion has been LEFT OPEN)";
}
if (net1->isGround()) {
message << "In model " << _cell->getName() << "\n "
<< "Terminal " << net2->getName()
<< " is connected to GROUND " << net1->getName()
<< " through the alias " << name1 << ".";
Net* zero = newZero();
if (zero) net2->merge( zero );
else
message << "\n (no tie low, connexion has been LEFT OPEN)";
}
if (not message.str().empty()) cerr << Warning( message.str() ) << endl;
return net2;
}
if ( (not net1->isExternal() and net2->isExternal()) if ( (not net1->isExternal() and net2->isExternal())
or ( net1->isExternal() and net2->isExternal() and (net1->getId() > net2->getId()) ) ) { or ( net1->isExternal() and net2->isExternal() and (net1->getId() > net2->getId()) ) ) {
std::swap( net1 , net2 ); std::swap( net1 , net2 );
@ -514,6 +587,7 @@ namespace {
} }
net1->merge( net2 ); return net1; net1->merge( net2 ); return net1;
} }
if (net2) { if (net2) {
std::swap( net1 , net2 ); std::swap( net1 , net2 );
std::swap( name1, name2 ); std::swap( name1, name2 );
@ -562,8 +636,6 @@ namespace {
void Model::connectSubckts () void Model::connectSubckts ()
{ {
unsigned int supplyCount = 0;
for ( Subckt* subckt : _subckts ) { for ( Subckt* subckt : _subckts ) {
if(not subckt->getModel()) if(not subckt->getModel())
throw Error( "No .model or cell named <%s> has been found.\n" throw Error( "No .model or cell named <%s> has been found.\n"
@ -620,6 +692,10 @@ namespace {
else plugNet->merge( net ); else plugNet->merge( net );
} }
if (subckt->getModel()->getCell()->getName() == "sm0") {
cerr << "sm0 plug:" << plug->getMasterNet()->getName() << " => net:" << net->getName() << endl;
}
if (plugNet->isSupply() and not plug->getMasterNet()->isSupply()) { if (plugNet->isSupply() and not plug->getMasterNet()->isSupply()) {
ostringstream message; ostringstream message;
message << "In " << instance << "\n " message << "In " << instance << "\n "
@ -629,28 +705,12 @@ namespace {
<< "."; << ".";
if (_masterNetOne) { if (_masterNetOne) {
if (plugNet->isPower()) { if (plugNet->isPower()) plug->setNet( newOne() );
ostringstream insName; insName << "one_" << supplyCount++;
Instance* insOne = Instance::create( _cell, insName.str(), _one );
Net* netOne = Net::create( _cell, insName.str() );
insOne->getPlug( _masterNetOne )->setNet( netOne );
plug->setNet( netOne );
}
} else } else
message << "\n (no tie high, connexion has been LEFT OPEN)"; message << "\n (no tie high, connexion has been LEFT OPEN)";
if (_masterNetZero) { if (_masterNetZero) {
if (plugNet->isGround()) { if (plugNet->isGround()) plug->setNet( newZero() );
ostringstream insName; insName << "zero_" << supplyCount++;
Instance* insZero = Instance::create( _cell, insName.str(), _zero );
Net* netZero = Net::create( _cell, insName.str() );
insZero->getPlug( _masterNetZero )->setNet( netZero );
plug->setNet( netZero );
}
} else } else
message << "\n (no tie low, connexion has been LEFT OPEN)"; message << "\n (no tie low, connexion has been LEFT OPEN)";
@ -759,13 +819,19 @@ namespace CRL {
} }
if (tokenize.state() == Tokenize::Inputs) { if (tokenize.state() == Tokenize::Inputs) {
for ( size_t i=1 ; i<blifLine.size() ; ++i ) for ( size_t i=1 ; i<blifLine.size() ; ++i ) {
blifModel->mergeNet( blifLine[i], true, Net::Direction::IN ); blifModel->mergeNet( blifLine[i], true, Net::Direction::IN );
if (blifModel->getCell()->getName() == "sm0")
cerr << "Blif model sm0: plug:" << blifLine[i] << endl;
}
} }
if (tokenize.state() == Tokenize::Outputs) { if (tokenize.state() == Tokenize::Outputs) {
for ( size_t i=1 ; i<blifLine.size() ; ++i ) for ( size_t i=1 ; i<blifLine.size() ; ++i ) {
blifModel->mergeNet( blifLine[i], true, Net::Direction::OUT ); blifModel->mergeNet( blifLine[i], true, Net::Direction::OUT );
if (blifModel->getCell()->getName() == "sm0")
cerr << "Blif model sm0: plug:" << blifLine[i] << endl;
}
} }
if (tokenize.state() & Tokenize::Names) { if (tokenize.state() & Tokenize::Names) {
@ -814,6 +880,11 @@ namespace CRL {
} }
subckt->addConnection( make_pair(blifLine[i].substr(0,equal) subckt->addConnection( make_pair(blifLine[i].substr(0,equal)
,blifLine[i].substr( equal+1)) ); ,blifLine[i].substr( equal+1)) );
if (subckt->getModelName() == "sm0") {
cerr << "Blif sm0 plug:" << blifLine[i].substr(0,equal)
<< " net:" << blifLine[i].substr( equal+1) << endl;
}
} }
} }
} }