Support for Uniquification. Rewrite of the Blif parser.
* New: In Hurricane, In NetAlias & Net, add an AliasList collection to iterate over all the aliases names (this *not* include the main net name). * New: In Hurricane, In Cell, Instance & Net add support for cloning and uniquification (update documentation). All Cells that are uniquified from a given model are kept in an Uniquify relation. This relation allows to get all the clones and generate unique clone names by adding a "_uXX" suffix. * Bug: In Hurricane, the Cell::_isFlattenLeaf attribute was not initialized in the constructor. * Change: In CRL Core, in AllianceFramework::getCell(), no longer destroy a partially loaded Cell in case of parser failure, let the incomplete Cell be. * New: In CRL Core, in ApParser, if all the instances are placed, sets the Cell::Placed flag. * Change: In CRL Core, in BlifParser, complete rewrite of the parser. Not so good an idea afterwards... * New: In Etesian, uniquify the design before placing. * Change: In Kite, display the list of unrouted wired after all other statistics.
This commit is contained in:
parent
4023481da3
commit
770b1fbbbc
|
@ -304,7 +304,7 @@ namespace CRL {
|
|||
(parser->getParsCell())( _environment.getLIBRARIES().getSelected() , state->getCell() );
|
||||
} catch ( ... ) {
|
||||
if ( createCell )
|
||||
state->getCell()->destroy();
|
||||
//state->getCell()->destroy();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +1,17 @@
|
|||
|
||||
|
||||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Project.
|
||||
// Copyright (C) Laboratoire LIP6 - Departement ASIM
|
||||
// Universite Pierre et Marie Curie
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) UPMC 2008-2015, All Rights Reserved
|
||||
//
|
||||
// Main contributors :
|
||||
// Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
||||
// Sophie Belloeil <Sophie.Belloeil@lip6.fr>
|
||||
// Hugo Clément <Hugo.Clement@lip6.fr>
|
||||
// Jean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
|
||||
// Damien Dupuis <Damien.Dupuis@lip6.fr>
|
||||
// Christian Masson <Christian.Masson@lip6.fr>
|
||||
// Marek Sroka <Marek.Sroka@lip6.fr>
|
||||
//
|
||||
// The Coriolis Project is free software; you can redistribute it
|
||||
// and/or modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// The Coriolis Project is distributed in the hope that it will be
|
||||
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Coriolis Project; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA
|
||||
//
|
||||
// License-Tag
|
||||
// Authors-Tag
|
||||
// ===================================================================
|
||||
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | Alliance / Hurricane Interface |
|
||||
// | |
|
||||
// | Author : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./alliance/ap/Ap.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include <string>
|
||||
|
@ -44,8 +22,8 @@ namespace Hurricane {
|
|||
}
|
||||
|
||||
|
||||
#ifndef __AP_H__
|
||||
#define __AP_H__
|
||||
#ifndef CRL_AP_H
|
||||
#define CRL_AP_H
|
||||
|
||||
|
||||
namespace CRL {
|
||||
|
@ -60,4 +38,4 @@ namespace CRL {
|
|||
|
||||
}
|
||||
|
||||
# endif
|
||||
#endif // CRL_AP_H
|
||||
|
|
|
@ -838,6 +838,15 @@ namespace {
|
|||
|
||||
if (materializationState) Go::disableAutoMaterialization ();
|
||||
|
||||
bool isPlaced = true;
|
||||
forEach ( Instance*, iinstance, _cell->getInstances() ) {
|
||||
if (iinstance->getPlacementStatus() == Instance::PlacementStatus::UNPLACED) {
|
||||
isPlaced = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isPlaced) _cell->setFlags( Cell::Placed );
|
||||
|
||||
fileStream.close ();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) UPMC 2008-2014, All Rights Reserved
|
||||
// Copyright (c) UPMC 2015-2015, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | Alliance / Hurricane Interface |
|
||||
// | Yacc Grammar for Alliance Structural VHDL |
|
||||
// | Yosys & Blif / Hurricane Interface |
|
||||
// | |
|
||||
// | Author : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
||||
// | |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./blif/BlifParser.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
|
@ -16,6 +18,7 @@
|
|||
#include <string.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
@ -39,111 +42,464 @@ using namespace CRL;
|
|||
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace std;
|
||||
|
||||
void addSupplyNets ( Cell* cell )
|
||||
{
|
||||
Net* vss = Net::create ( cell, "vss" );
|
||||
vss->setExternal ( true );
|
||||
vss->setGlobal ( true );
|
||||
vss->setType ( Net::Type::GROUND );
|
||||
|
||||
Net* vdd = Net::create ( cell, "vdd" );
|
||||
vdd->setExternal ( true );
|
||||
vdd->setGlobal ( true );
|
||||
vdd->setType ( Net::Type::POWER );
|
||||
inline bool isAbcAutomaticName ( string name )
|
||||
{ return (name.substr(0,5) == "$abc$"); }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "::Tokenize".
|
||||
|
||||
|
||||
class Tokenize {
|
||||
public:
|
||||
enum State { Init = 0x00000001
|
||||
, Unknown = 0x00000002
|
||||
, Model = 0x00000004
|
||||
, End = 0x00000008
|
||||
, Subckt = 0x00000010
|
||||
, Latch = 0x00000020
|
||||
, Inputs = 0x00000040
|
||||
, Outputs = 0x00000080
|
||||
, Clock = 0x00000100
|
||||
, Names = 0x00000200
|
||||
, CoverZero = 0x00001000
|
||||
, CoverOne = 0x00002000
|
||||
, CoverLogic = 0x00004000
|
||||
, CoverAlias = 0x00008000
|
||||
};
|
||||
typedef vector< pair<string,string> > CoverTable;
|
||||
public:
|
||||
Tokenize ( string blifFile );
|
||||
inline size_t lineno () const;
|
||||
inline unsigned int state () const;
|
||||
const vector<string>& blifLine () const;
|
||||
const CoverTable& coverTable () const;
|
||||
bool readEntry ();
|
||||
private:
|
||||
bool _readline ();
|
||||
private:
|
||||
size_t _lineno;
|
||||
unsigned int _state;
|
||||
ifstream _stream;
|
||||
vector<string> _tokens;
|
||||
vector<string> _blifLine;
|
||||
CoverTable _coverTable;
|
||||
};
|
||||
|
||||
|
||||
Tokenize::Tokenize ( string blifFile )
|
||||
: _lineno (0)
|
||||
, _state (Init)
|
||||
, _stream ()
|
||||
, _tokens ()
|
||||
, _blifLine ()
|
||||
, _coverTable()
|
||||
{
|
||||
_stream.open( blifFile+".blif" );
|
||||
if (_stream.fail())
|
||||
throw Error( "Unable to open BLIF file %s.blif\n", blifFile.c_str() );
|
||||
|
||||
_readline();
|
||||
}
|
||||
|
||||
void connectSupplyNets ( Instance * instance, Cell* design )
|
||||
{
|
||||
Cell* instcell = instance->getCell();
|
||||
if(instcell == NULL){
|
||||
throw Error("Instance's cell is null\n");
|
||||
}
|
||||
Net* vssint = instcell->getNet( "vss" );
|
||||
Net* vddint = instcell->getNet( "vdd" );
|
||||
Net* vssext = design->getNet( "vss" );
|
||||
Net* vddext = design->getNet( "vdd" );
|
||||
auto vssplug = instance->getPlug( vssint );
|
||||
auto vddplug = instance->getPlug( vddint );
|
||||
vssplug->setNet( vssext );
|
||||
vddplug->setNet( vddext );
|
||||
}
|
||||
|
||||
void SetNetType ( Net* net, AllianceFramework * framework )
|
||||
inline size_t Tokenize::lineno () const { return (_lineno) ? _lineno-1 : 0; }
|
||||
inline unsigned int Tokenize::state () const { return _state; }
|
||||
inline const vector<string>& Tokenize::blifLine () const { return _blifLine; }
|
||||
inline const Tokenize::CoverTable& Tokenize::coverTable() const { return _coverTable; }
|
||||
|
||||
|
||||
bool Tokenize::readEntry ()
|
||||
{
|
||||
if ( framework->isPOWER(net->getName()) ) {
|
||||
net->setType ( Net::Type::POWER );
|
||||
net->setGlobal ( true );
|
||||
} else if ( framework->isGROUND(net->getName()) ) {
|
||||
net->setType ( Net::Type::GROUND );
|
||||
net->setGlobal ( true );
|
||||
} else if ( framework->isCLOCK(net->getName()) ) {
|
||||
net->setType ( Net::Type::CLOCK );
|
||||
_blifLine .clear();
|
||||
_coverTable.clear();
|
||||
_blifLine = _tokens;
|
||||
_state = 0;
|
||||
|
||||
if (_stream.eof()) return false;
|
||||
|
||||
if (_tokens.front() == ".model" ) { _state = Model; }
|
||||
if (_tokens.front() == ".end" ) { _state = End; }
|
||||
if (_tokens.front() == ".inputs" ) { _state = Inputs; }
|
||||
if (_tokens.front() == ".outputs") { _state = Outputs; }
|
||||
if (_tokens.front() == ".clock" ) { _state = Clock; }
|
||||
if (_tokens.front() == ".subckt" ) { _state = Subckt; }
|
||||
if (_tokens.front() == ".latch" ) { _state = Latch; }
|
||||
if (_tokens.front() == ".names" ) {
|
||||
_state = Names;
|
||||
|
||||
while ( _readline() and (_tokens.front()[0] != '.')) {
|
||||
switch ( _tokens.size() ) {
|
||||
case 0: break;
|
||||
case 1: _coverTable.push_back( make_pair(_tokens[0],string()) ); break;
|
||||
default:
|
||||
case 2: _coverTable.push_back( make_pair(_tokens[0],_tokens[1]) ); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_coverTable.empty()) _state |= CoverZero;
|
||||
else if (_coverTable.size () == 1) {
|
||||
if ( (_coverTable[0].first == "1") and (_coverTable[0].second.empty()) ) _state |= CoverOne;
|
||||
else if ( (_coverTable[0].first == "1") and (_coverTable[0].second == "1") ) _state |= CoverAlias;
|
||||
} else {
|
||||
_state |= CoverLogic;
|
||||
}
|
||||
} else
|
||||
net->setType ( Net::Type::LOGICAL );
|
||||
_readline();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum ParserState{
|
||||
EXT = 0x00,
|
||||
MODEL = 0x01,
|
||||
SUBCKT = 0x02,
|
||||
NAMES = 0x04,
|
||||
INPUTS = 0x08,
|
||||
OUTPUTS = 0x16
|
||||
};
|
||||
|
||||
struct subckt{
|
||||
string cell;
|
||||
vector<pair<string, string> > pins;
|
||||
};
|
||||
bool Tokenize::_readline ()
|
||||
{
|
||||
_tokens.clear();
|
||||
|
||||
struct model{
|
||||
string name;
|
||||
unordered_map<string, Net::Direction> pins;
|
||||
vector<subckt> subcircuits;
|
||||
vector<pair<string, string> > aliases;
|
||||
bool operator<(model const & o) const{ return name < o.name; }
|
||||
};
|
||||
bool nextLine = true;
|
||||
|
||||
std::vector<std::string> tokenize(std::string const & s){
|
||||
std::vector<std::string> ret;
|
||||
auto b_it = s.begin();
|
||||
while(b_it != s.end()){
|
||||
// Remove whitespace
|
||||
while(b_it != s.end() && (*b_it == ' ' or *b_it == '\t'))
|
||||
++b_it;
|
||||
// Find the end of the token
|
||||
auto e_it = b_it;
|
||||
while(e_it != s.end() && *e_it != ' ' && *e_it != '\t' and *e_it != '#')
|
||||
++e_it;
|
||||
// Create the token
|
||||
if(e_it != b_it)
|
||||
ret.push_back(std::string(b_it, e_it));
|
||||
// Handle comments
|
||||
if(e_it != s.end() && *e_it == '#')
|
||||
e_it = s.end();
|
||||
b_it = e_it;
|
||||
while ( nextLine ) {
|
||||
if (_stream.eof()) return false;
|
||||
|
||||
nextLine = false;
|
||||
++_lineno;
|
||||
|
||||
string line;
|
||||
getline( _stream, line );
|
||||
|
||||
bool comment = false;
|
||||
size_t tokstart = 0;
|
||||
for ( size_t i=0 ; i<line.size() ; ++i ) {
|
||||
size_t nextTokstart = i+1;
|
||||
|
||||
switch ( line[i] ) {
|
||||
case '\\':
|
||||
if (i == line.size()-1) nextLine = true;
|
||||
default: continue;
|
||||
case ' ':
|
||||
case '\t': break;
|
||||
case '#': comment = true; break;
|
||||
}
|
||||
|
||||
if (i > tokstart)
|
||||
_tokens.push_back( line.substr(tokstart,i-tokstart) );
|
||||
|
||||
tokstart = nextTokstart;
|
||||
|
||||
if (comment) break;
|
||||
}
|
||||
|
||||
if ( (not comment) and (tokstart < line.size()) )
|
||||
_tokens.push_back( line.substr(tokstart) );
|
||||
|
||||
if (_tokens.empty())
|
||||
nextLine = true;
|
||||
}
|
||||
std::reverse(ret.begin(), ret.end());
|
||||
return ret;
|
||||
|
||||
return not _tokens.empty();
|
||||
}
|
||||
|
||||
} // End of anonymous namespace.
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "::Subckt" (declaration).
|
||||
|
||||
|
||||
class Model;
|
||||
|
||||
|
||||
class Subckt {
|
||||
public:
|
||||
typedef vector< pair<string,string> > Connections;
|
||||
public:
|
||||
Subckt ( string modelName, string instanceName );
|
||||
inline string getModelName () const;
|
||||
inline string getInstanceName () const;
|
||||
inline const Connections& getConnections () const;
|
||||
inline size_t getDepth () const;
|
||||
inline Model* getModel () const;
|
||||
inline void setModel ( Model* );
|
||||
inline void addConnection ( const pair<string,string>& );
|
||||
void connectSubckts ();
|
||||
private:
|
||||
string _modelName;
|
||||
string _instanceName;
|
||||
Connections _connections;
|
||||
Model* _model;
|
||||
};
|
||||
|
||||
typedef vector<Subckt*> Subckts;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "::Model" (declaration).
|
||||
|
||||
|
||||
class Model {
|
||||
public:
|
||||
typedef unordered_map<string,Model*> Lut;
|
||||
static Lut _blifLut;
|
||||
static vector<Model*> _blifOrder;
|
||||
public:
|
||||
static Model* find ( string modelName );
|
||||
static void orderModels ();
|
||||
static void connectModels ();
|
||||
static void toVhdlModels ();
|
||||
static void clearStatic ();
|
||||
static const Lut& getLut ();
|
||||
public:
|
||||
Model ( Cell* );
|
||||
inline ~Model ();
|
||||
inline Cell* getCell () const;
|
||||
inline size_t getDepth () const;
|
||||
inline const Subckts& getSubckts () const;
|
||||
Subckt* addSubckt ( string modelName );
|
||||
size_t computeDepth ();
|
||||
void connectSubckts ();
|
||||
Net* mergeNet ( string name, bool isExternal, unsigned int );
|
||||
Net* mergeAlias ( string name1, string name2 );
|
||||
private:
|
||||
Cell* _cell;
|
||||
Subckts _subckts;
|
||||
size_t _depth;
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "::Subckt" (implementation).
|
||||
|
||||
|
||||
Subckt::Subckt ( string modelName, string instanceName )
|
||||
: _modelName (modelName)
|
||||
, _instanceName(instanceName)
|
||||
, _connections ()
|
||||
, _model (NULL)
|
||||
{
|
||||
Cell* cell = AllianceFramework::get()->getCell( modelName, Catalog::State::Views, 0 );
|
||||
if (cell) {
|
||||
_model = Model::find( getString(cell->getName()) );
|
||||
if (not _model) {
|
||||
_model = new Model ( cell );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline Model* Subckt::getModel () const { return _model; }
|
||||
inline string Subckt::getModelName () const { return _modelName; }
|
||||
inline string Subckt::getInstanceName () const { return _instanceName; }
|
||||
inline const Subckt::Connections&
|
||||
Subckt::getConnections () const { return _connections; }
|
||||
inline size_t Subckt::getDepth () const { return (_model) ? _model->getDepth() : 0; }
|
||||
inline void Subckt::setModel ( Model* model ) { _model = model; }
|
||||
inline void Subckt::addConnection ( const pair<string,string>& connection ) { _connections.push_back(connection); }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "::Model" (implementation).
|
||||
|
||||
|
||||
Model::Lut Model::_blifLut;
|
||||
vector<Model*> Model::_blifOrder;
|
||||
|
||||
|
||||
struct CompareByDepth {
|
||||
inline bool operator() ( const Model* lhs, const Model* rhs )
|
||||
{
|
||||
if (lhs->getDepth() != rhs->getDepth()) return lhs->getDepth() < rhs->getDepth();
|
||||
return lhs->getCell()->getId() < rhs->getCell()->getId();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Model* Model::find ( string modelName )
|
||||
{
|
||||
Lut::iterator ibcell = _blifLut.find( modelName );
|
||||
if (ibcell == _blifLut.end()) return NULL;
|
||||
|
||||
return ibcell->second;
|
||||
}
|
||||
|
||||
|
||||
void Model::orderModels ()
|
||||
{
|
||||
for ( auto element : _blifLut ) {
|
||||
element.second->computeDepth();
|
||||
_blifOrder.push_back( element.second );
|
||||
}
|
||||
sort( _blifOrder.begin(), _blifOrder.end(), CompareByDepth() );
|
||||
}
|
||||
|
||||
|
||||
void Model::connectModels ()
|
||||
{
|
||||
for ( Model* blifModel : _blifOrder )
|
||||
blifModel->connectSubckts();
|
||||
}
|
||||
|
||||
|
||||
void Model::toVhdlModels ()
|
||||
{
|
||||
for ( Model* model : _blifOrder )
|
||||
CRL::NamingScheme::toVhdl( model->getCell()
|
||||
, CRL::NamingScheme::Recursive|CRL::NamingScheme::FromVerilog );
|
||||
}
|
||||
|
||||
|
||||
void Model::clearStatic ()
|
||||
{
|
||||
for ( auto ibcell : _blifLut ) delete ibcell.second;
|
||||
_blifLut.clear();
|
||||
_blifOrder.clear();
|
||||
}
|
||||
|
||||
|
||||
Model::Model ( Cell* cell )
|
||||
: _cell (cell)
|
||||
, _subckts()
|
||||
, _depth (0)
|
||||
{
|
||||
|
||||
_blifLut.insert( make_pair(getString(_cell->getName()), this) );
|
||||
if (_cell->isTerminal())
|
||||
_depth = 1;
|
||||
else {
|
||||
cmess2 << " " << tab++ << "+ " << cell->getName() << " [.model]" << endl;
|
||||
|
||||
Net* vss = Net::create ( _cell, "vss" );
|
||||
vss->setExternal( true );
|
||||
vss->setGlobal ( true );
|
||||
vss->setType ( Net::Type::GROUND );
|
||||
|
||||
Net* vdd = Net::create ( _cell, "vdd" );
|
||||
vdd->setExternal( true );
|
||||
vdd->setGlobal ( true );
|
||||
vdd->setType ( Net::Type::POWER );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline Model::~Model ()
|
||||
{ for ( auto subckt : _subckts ) delete subckt; }
|
||||
|
||||
|
||||
inline const Model::Lut& Model::getLut () { return _blifLut; }
|
||||
inline Cell* Model::getCell () const { return _cell; }
|
||||
inline size_t Model::getDepth () const { return _depth; }
|
||||
inline const Subckts& Model::getSubckts () const { return _subckts; }
|
||||
|
||||
|
||||
Net* Model::mergeNet ( string name, bool isExternal, unsigned int direction )
|
||||
{
|
||||
Net* net = _cell->getNet( name );
|
||||
if (not net) {
|
||||
net = Net::create( _cell, name );
|
||||
net->setExternal ( isExternal );
|
||||
net->setDirection( (Net::Direction::Code)direction );
|
||||
} else {
|
||||
net->addAlias( name );
|
||||
if (isExternal) net->setExternal( true );
|
||||
direction |= net->getDirection();
|
||||
net->setDirection( (Net::Direction::Code)direction );
|
||||
}
|
||||
return net;
|
||||
}
|
||||
|
||||
|
||||
Net* Model::mergeAlias ( string name1, string name2 )
|
||||
{
|
||||
Net* net1 = _cell->getNet( name1 );
|
||||
Net* net2 = _cell->getNet( name2 );
|
||||
|
||||
if (net1 and (net1 == net2)) return net1;
|
||||
if (net1 and net2) { net1->merge( net2 ); return net1; }
|
||||
if (net2) {
|
||||
swap( net1 , net2 );
|
||||
swap( name1, name2 );
|
||||
}
|
||||
|
||||
if (not net1) {
|
||||
net1 = Net::create( _cell, name1 );
|
||||
net1->setExternal ( false );
|
||||
}
|
||||
|
||||
net1->addAlias( name2 );
|
||||
return net1;
|
||||
}
|
||||
|
||||
|
||||
Subckt* Model::addSubckt ( string modelName )
|
||||
{
|
||||
string instanceName = "subckt_" + getString(_subckts.size()) + "_" + modelName;
|
||||
_subckts.push_back( new Subckt( modelName, instanceName ) );
|
||||
|
||||
return _subckts.back();
|
||||
}
|
||||
|
||||
|
||||
size_t Model::computeDepth ()
|
||||
{
|
||||
if (_depth) return _depth;
|
||||
|
||||
for ( auto subckt : _subckts ) {
|
||||
Model* subcktModel = subckt->getModel();
|
||||
if (not subcktModel) {
|
||||
subcktModel = Model::find( subckt->getModelName() );
|
||||
subckt->setModel( subcktModel );
|
||||
}
|
||||
|
||||
size_t subcktDepth = subckt->getDepth();
|
||||
if (not subcktDepth and subckt->getModel())
|
||||
subcktDepth = subckt->getModel()->computeDepth();
|
||||
|
||||
_depth = std::max( _depth, subcktDepth );
|
||||
}
|
||||
|
||||
return _depth;
|
||||
}
|
||||
|
||||
|
||||
void Model::connectSubckts ()
|
||||
{
|
||||
for ( Subckt* subckt : _subckts ) {
|
||||
Instance* instance = Instance::create( _cell
|
||||
, subckt->getInstanceName()
|
||||
, subckt->getModel()->getCell()
|
||||
);
|
||||
|
||||
for ( auto connection : subckt->getConnections() ) {
|
||||
string masterNetName = connection.first;
|
||||
string netName = connection.second;
|
||||
Net* net = _cell->getNet( netName );
|
||||
Plug* plug = instance->getPlug( instance->getMasterCell()->getNet(masterNetName) );
|
||||
Net* plugNet = plug->getNet();
|
||||
|
||||
if (not plugNet) {
|
||||
if (not net) net = Net::create( _cell, netName );
|
||||
plug->setNet( net );
|
||||
continue;
|
||||
}
|
||||
|
||||
if (not net) { plugNet->addAlias( netName ); continue; }
|
||||
if (plugNet == net) continue;
|
||||
|
||||
plugNet->merge( net );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // Anonymous namespace.
|
||||
|
||||
|
||||
namespace CRL {
|
||||
|
||||
//
|
||||
// Can only parse simple, netlist BLIF files generated by Yosys
|
||||
// Ignores all ".names" and uses only the .subckt, .model, .input and .output
|
||||
//
|
||||
|
||||
Cell* Blif::load ( string cellPath )
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
Cell* mainModel = NULL;
|
||||
string mainName;
|
||||
string blifFile = cellPath;
|
||||
size_t dot = cellPath.find_first_of('.');
|
||||
|
@ -152,280 +508,136 @@ namespace CRL {
|
|||
mainName = cellPath.substr( dot+1 );
|
||||
}
|
||||
|
||||
auto framework = AllianceFramework::get ();
|
||||
auto framework = AllianceFramework::get();
|
||||
|
||||
std::ifstream ccell ( blifFile+".blif" );
|
||||
if(ccell.fail()){
|
||||
throw Error( "Unable to open BLIF file %s.blif\n", blifFile.c_str() );
|
||||
}
|
||||
cmess2 << " " << tab++ << "+ " << blifFile << " [blif]" << endl;
|
||||
|
||||
std::vector<model> models;
|
||||
ParserState state = EXT;
|
||||
bool hasName = true;
|
||||
|
||||
string line;
|
||||
vector<string> current_names;
|
||||
while(getline(ccell, line)){
|
||||
istringstream linestream(line);
|
||||
vector<string> tokens = tokenize(line);
|
||||
if(not tokens.empty()){
|
||||
string const token = tokens.back();
|
||||
tokens.pop_back();
|
||||
assert(not token.empty());
|
||||
if(token[0] == '.'){
|
||||
// Process finished .names statement
|
||||
if(not current_names.empty()){
|
||||
if( current_names.size() != 4
|
||||
or current_names[2] != "1" or current_names[3] != "1"
|
||||
){
|
||||
ostringstream mess;
|
||||
mess << "\'.names\' statement is not an alias and will be ignored.\n"
|
||||
<< " Map to standard cells for functions and tie cells for constants.\n"
|
||||
<< " ";
|
||||
for ( size_t iname=0 ; iname<current_names.size() ; ++iname ) {
|
||||
if (iname) mess << ", ";
|
||||
mess << "\'" << current_names[iname] << "\'";
|
||||
}
|
||||
cerr << Warning(mess.str()) << endl;
|
||||
}
|
||||
else{
|
||||
// Name statement is an alias: the second signal will map to the first
|
||||
models.back().aliases.push_back(pair<string, string>(current_names[0], current_names[1]));
|
||||
}
|
||||
current_names.clear();
|
||||
}
|
||||
if(token == ".model"){
|
||||
if(state != EXT)
|
||||
throw Error("Nested model are not supported\n");
|
||||
state = MODEL;
|
||||
hasName = false;
|
||||
models.push_back(model());
|
||||
}
|
||||
else if(token == ".subckt"){
|
||||
if(state == EXT)
|
||||
throw Error("Subcircuit without an enclosing model are not supported\n");
|
||||
if(state == MODEL and not hasName)
|
||||
throw Error("Model has no name\n");
|
||||
state = SUBCKT;
|
||||
hasName = false;
|
||||
models.back().subcircuits.push_back(subckt());
|
||||
}
|
||||
else if(token == ".names"){
|
||||
if(state == EXT)
|
||||
throw Error("Names without an enclosing model are not supported\n");
|
||||
if(state == MODEL and not hasName)
|
||||
throw Error("Model has no name\n");
|
||||
state = NAMES;
|
||||
}
|
||||
else if(token == ".latch"){
|
||||
throw Error("Latch constructs are not understood by the parser\n");
|
||||
}
|
||||
else if(token == ".inputs"){
|
||||
if(state == EXT)
|
||||
throw Error("Inputs have been found without an enclosing model\n");
|
||||
state = INPUTS;
|
||||
}
|
||||
else if(token == ".outputs"){
|
||||
if(state == EXT)
|
||||
throw Error("Outputs have been found without an enclosing model\n");
|
||||
state = OUTPUTS;
|
||||
}
|
||||
else if(token == ".end"){
|
||||
if(state == EXT)
|
||||
throw Error("A .end has been found out of a model\n");
|
||||
state = EXT;
|
||||
}
|
||||
else{
|
||||
ostringstream mess;
|
||||
mess << "Unknown control token <" << token << ">\n";
|
||||
throw Error(mess.str());
|
||||
}
|
||||
|
||||
}
|
||||
else if(state == NAMES){
|
||||
// Part of a cover for a logic function
|
||||
current_names.push_back(token);
|
||||
}
|
||||
else{
|
||||
ostringstream mess;
|
||||
mess << "Encountered a non-control token at the beginning of a line: <" << token << ">\n";
|
||||
throw Error(mess.str());
|
||||
|
||||
Cell* mainModel = NULL;
|
||||
Model* blifModel = NULL;
|
||||
Tokenize tokenize ( blifFile );
|
||||
const vector<string>& blifLine = tokenize.blifLine();
|
||||
|
||||
while ( tokenize.readEntry() ) {
|
||||
if (tokenize.state() == Tokenize::Model) {
|
||||
if (blifModel) {
|
||||
cerr << Error( "Blif::load() Previous \".model\" %s not closed (missing \".end\"?).\n"
|
||||
" File %s.blif at line %u."
|
||||
, getString(blifModel->getCell()->getName()).c_str()
|
||||
, blifFile.c_str()
|
||||
, tokenize.lineno()
|
||||
) << endl;
|
||||
blifModel = NULL;
|
||||
--tab;
|
||||
}
|
||||
|
||||
Cell* cell = framework->createCell( blifLine[1] );
|
||||
cell->setTerminal( false );
|
||||
blifModel = new Model ( cell );
|
||||
|
||||
if (not mainModel or (blifLine[1] == mainName))
|
||||
mainModel = blifModel->getCell();
|
||||
}
|
||||
|
||||
if (tokenize.state() == Tokenize::End) {
|
||||
if (blifModel) { blifModel = NULL; --tab; continue; }
|
||||
}
|
||||
// Process all tokens after the control
|
||||
while(not tokens.empty()){
|
||||
string const token = tokens.back();
|
||||
tokens.pop_back();
|
||||
assert(not token.empty());
|
||||
// Either a pin or an input/output definition
|
||||
if(state == INPUTS or state == OUTPUTS){
|
||||
auto it = models.back().pins.find(token);
|
||||
Net::Direction D = (state == INPUTS)? Net::Direction::DirIn : Net::Direction::DirOut;
|
||||
if(it != models.back().pins.end()){
|
||||
it->second = static_cast<Net::Direction::Code>(D | it->second);
|
||||
}
|
||||
else{
|
||||
models.back().pins.insert(pair<string, Net::Direction>(token, D));
|
||||
}
|
||||
}
|
||||
else if(state == SUBCKT){
|
||||
if(hasName){
|
||||
// Encountered a pin: need to be processed
|
||||
auto equal_pos = token.find_first_of('=');
|
||||
if(equal_pos+1 < token.size()){
|
||||
string before_space = token.substr(0, equal_pos);
|
||||
string after_space = token.substr(equal_pos+1, string::npos);
|
||||
models.back().subcircuits.back().pins.push_back(pair<string, string>(before_space, after_space));
|
||||
}
|
||||
else{
|
||||
ostringstream mess;
|
||||
mess << "Unable to parse the subckt pin specification <"
|
||||
<< token << ">\n";
|
||||
Error(mess.str());
|
||||
}
|
||||
}
|
||||
else{
|
||||
models.back().subcircuits.back().cell = token;
|
||||
hasName = true;
|
||||
}
|
||||
}
|
||||
else if(state == NAMES){
|
||||
current_names.push_back(token);
|
||||
}
|
||||
else if(state == MODEL){
|
||||
if(hasName)
|
||||
throw Error("Unexpected token after model name\n");
|
||||
else{
|
||||
models.back().name = token;
|
||||
cmess2 << " " << tab << "+ " << token << " [interface+signals]" << endl;
|
||||
hasName = true;
|
||||
}
|
||||
}
|
||||
else{
|
||||
throw Error("Unexpected token\n");
|
||||
}
|
||||
|
||||
if (tokenize.state() == Tokenize::Clock) {
|
||||
cerr << Error( "Blif::load() \".clock\" command is not supported.\n"
|
||||
" File %s.blif at line %u."
|
||||
, blifFile.c_str()
|
||||
, tokenize.lineno()
|
||||
) << endl;
|
||||
continue;
|
||||
}
|
||||
line.clear();
|
||||
}
|
||||
if(state != EXT){
|
||||
cerr << Warning("End of model has not been found\n");
|
||||
}
|
||||
|
||||
/*
|
||||
for(auto & M : models){
|
||||
cout << "Model: " << M.name << endl;
|
||||
for(auto & S : M.subcircuits){
|
||||
cout << "\tInstance of " << S.cell;
|
||||
for(auto & P : S.pins){
|
||||
cout << " " << P.first << ":" << P.second;
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
if (tokenize.state() == Tokenize::Latch) {
|
||||
cerr << Error( "Blif::load() \".latch\" command is not supported.\n"
|
||||
" File %s.blif at line %u."
|
||||
, blifFile.c_str()
|
||||
, tokenize.lineno()
|
||||
) << endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Two passes: first create the cells and their nets, then create the internals
|
||||
std::vector<Cell*> model_cells;
|
||||
for(auto M : models){
|
||||
Cell * design = framework->createCell(M.name);
|
||||
if(design == NULL){
|
||||
throw Error("Model " + M.name + " is NULL\n");
|
||||
|
||||
if (not blifModel) {
|
||||
cerr << Error( "Blif::load() Unexpected command \"%s\" outside of .model definition.\n"
|
||||
" File %s.blif at line %u."
|
||||
, blifLine[0].c_str()
|
||||
, blifFile.c_str()
|
||||
, tokenize.lineno()
|
||||
) << endl;
|
||||
continue;
|
||||
}
|
||||
if (M.name == mainName) mainModel = design;
|
||||
|
||||
model_cells.push_back(design);
|
||||
addSupplyNets(design);
|
||||
|
||||
unordered_set<string> net_names;
|
||||
for(auto const & S : M.subcircuits){
|
||||
for(auto const & P : S.pins){
|
||||
net_names.insert(P.second);
|
||||
}
|
||||
for(auto const & A : M.aliases){
|
||||
net_names.insert(A.first);
|
||||
net_names.insert(A.second);
|
||||
}
|
||||
|
||||
if (tokenize.state() == Tokenize::Inputs) {
|
||||
for ( size_t i=1 ; i<blifLine.size() ; ++i )
|
||||
blifModel->mergeNet( blifLine[i], true, Net::Direction::IN );
|
||||
}
|
||||
|
||||
for(auto const & P : M.pins){
|
||||
net_names.insert(P.first);
|
||||
|
||||
if (tokenize.state() == Tokenize::Outputs) {
|
||||
for ( size_t i=1 ; i<blifLine.size() ; ++i )
|
||||
blifModel->mergeNet( blifLine[i], true, Net::Direction::OUT );
|
||||
}
|
||||
|
||||
for(string const & N : net_names){
|
||||
Net* new_net = Net::create( design, N );
|
||||
auto it = M.pins.find(N);
|
||||
if(it != M.pins.end()){
|
||||
new_net->setExternal( true );
|
||||
new_net->setDirection( it->second );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: every cell and its nets have already been created
|
||||
for(size_t i=0; i<models.size(); ++i){
|
||||
cmess2 << " " << tab++ << "+ " << models[i].name << " [instances]" << endl;
|
||||
auto const & M = models[i];
|
||||
Cell * design = model_cells[i];
|
||||
for(size_t j=0; j<M.subcircuits.size(); ++j){
|
||||
auto & S = M.subcircuits[j];
|
||||
ostringstream subckt_name;
|
||||
subckt_name << "subckt_" << j;
|
||||
Cell * cell = framework->getCell(S.cell, Catalog::State::Views, 0);
|
||||
if(cell == NULL){
|
||||
throw Error("Cell <" + S.cell + "> to instanciate hasn't been found\n");
|
||||
}
|
||||
//cmess2 << "Creating instance <" << subckt_name.str() << "> of <" << S.cell << "> in <" << models[i].name << ">" << endl;
|
||||
Instance* instance = Instance::create( design, subckt_name.str(), cell);
|
||||
|
||||
for(auto & P : S.pins){
|
||||
Net* internalNet = cell->getNet( P.first );
|
||||
Net* externalNet = design->getNet( P.second );
|
||||
assert(internalNet != NULL and externalNet != NULL and instance != NULL);
|
||||
instance->getPlug( internalNet )->setNet( externalNet );
|
||||
}
|
||||
//connectSupplyNets(instance, design);
|
||||
}
|
||||
// Merge the aliased nets
|
||||
for(auto alias : M.aliases){
|
||||
//cmess2 << "Merging nets <" << alias.first << "> and <" << alias.second << ">" << endl;
|
||||
Net * first_net = design->getNet( alias.first );
|
||||
Net * second_net = design->getNet( alias.second );
|
||||
if(first_net == NULL or second_net == NULL){
|
||||
ostringstream mess;
|
||||
mess << "Trying to create an alias for non-instantiated nets:";
|
||||
if(first_net == NULL)
|
||||
mess << " <" << alias.first << ">";
|
||||
if(second_net == NULL)
|
||||
mess << " <" << alias.second << ">";
|
||||
mess << ", will be ignored\n";
|
||||
cerr << Warning(mess.str());
|
||||
|
||||
if (tokenize.state() & Tokenize::Names) {
|
||||
if (tokenize.state() & Tokenize::CoverAlias) {
|
||||
blifModel->mergeAlias( blifLine[1], blifLine[2] );
|
||||
} else if (tokenize.state() & Tokenize::CoverZero) {
|
||||
} else if (tokenize.state() & Tokenize::CoverOne ) {
|
||||
} else {
|
||||
cerr << Error( "Blif::load() Unsupported \".names\" cover construct.\n"
|
||||
" File %s.blif at line %u."
|
||||
, blifFile.c_str()
|
||||
, tokenize.lineno()
|
||||
) << endl;
|
||||
continue;
|
||||
}
|
||||
if(!first_net->isExternal())
|
||||
swap(first_net, second_net); // If only one net is external, it needs to be the first
|
||||
first_net->merge(second_net);
|
||||
}
|
||||
--tab;
|
||||
|
||||
if (tokenize.state() == Tokenize::Subckt) {
|
||||
Subckt* subckt = blifModel->addSubckt( blifLine[1] );
|
||||
for ( size_t i=2 ; i<blifLine.size() ; ++i ) {
|
||||
size_t equal = blifLine[i].find('=');
|
||||
if (equal == string::npos) {
|
||||
cerr << Error( "Blif::load() Bad affectation in \".subckt\": %s.\n"
|
||||
" File %s.blif at line %u."
|
||||
, blifLine[i].c_str()
|
||||
, blifFile.c_str()
|
||||
, tokenize.lineno()
|
||||
) << endl;
|
||||
continue;
|
||||
}
|
||||
subckt->addConnection( make_pair(blifLine[i].substr(0,equal)
|
||||
,blifLine[i].substr( equal+1)) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (blifModel) {
|
||||
cerr << Error( "Blif::load() Last \".model\" %s was not closed (missing \".end\"?).\n"
|
||||
" File %s.blif at line %u."
|
||||
, getString(blifModel->getCell()->getName()).c_str()
|
||||
, blifFile.c_str()
|
||||
, tokenize.lineno()
|
||||
) << endl;
|
||||
tab--;
|
||||
}
|
||||
tab--;
|
||||
|
||||
Model::orderModels();
|
||||
Model::connectModels();
|
||||
Model::toVhdlModels();
|
||||
Model::clearStatic();
|
||||
|
||||
--tab;
|
||||
|
||||
for ( auto model : model_cells )
|
||||
CRL::NamingScheme::toVhdl( model, CRL::NamingScheme::Recursive|CRL::NamingScheme::FromVerilog );
|
||||
|
||||
if(model_cells.empty()){
|
||||
throw Error("No model found in the file\n");
|
||||
}
|
||||
else if(mainModel) {
|
||||
return mainModel;
|
||||
}
|
||||
else if (model_cells.size() > 1){
|
||||
cerr << Warning( "Blif::load(): Several models found, returned the first one %s.\n"
|
||||
, getString(model_cells[0]->getName()).c_str()
|
||||
if (not mainModel)
|
||||
cerr << Warning( "Blif::load(): File %s.blif doesn't contains any \".model\".\n"
|
||||
, blifFile.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
return model_cells[0];
|
||||
return mainModel;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,19 +32,38 @@ namespace CRL {
|
|||
{
|
||||
string vhdlName;
|
||||
|
||||
size_t parCount = 0;
|
||||
|
||||
// VHDL reserved keywords (scalar).
|
||||
if (vlogName == Name("in" )) return "in_v";
|
||||
if (vlogName == Name("out" )) return "out_v";
|
||||
if (vlogName == Name("inout")) return "inout_v";
|
||||
|
||||
size_t parCount = 0;
|
||||
size_t posLeftPar = 0;
|
||||
size_t posRightPar = 0;
|
||||
for ( size_t i=0 ; i<vlogName.size() ; ++i ) {
|
||||
if (vlogName[i] == '(') ++parCount;
|
||||
if (vlogName[i] == '[') ++parCount;
|
||||
if (vlogName[i] == '(') { ++parCount; posLeftPar=i; }
|
||||
if (vlogName[i] == '[') { ++parCount; posLeftPar=i; }
|
||||
if (vlogName[i] == ')') { posRightPar=i; }
|
||||
if (vlogName[i] == ']') { posRightPar=i; }
|
||||
}
|
||||
char leftPar = (parCount > 1) ? '_' : '(';
|
||||
char rightPar = (parCount > 1) ? '_' : ')';
|
||||
|
||||
if (parCount == 1) {
|
||||
for ( size_t i=posLeftPar+1 ; i<posRightPar ; ++i ) {
|
||||
if (not isdigit(vlogName[i])) {
|
||||
leftPar = rightPar = '_';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( size_t i=0 ; i<vlogName.size() ; ++i ) {
|
||||
char translated = tolower( vlogName[i] );
|
||||
|
||||
if ( (i == 0) and (isdigit(translated)) )
|
||||
vhdlName += 'N';
|
||||
if ( vhdlName.empty() and (isdigit(translated)) )
|
||||
vhdlName += 'n';
|
||||
|
||||
if (translated == '\\') translated = '_';
|
||||
if (translated == '$' ) translated = '_';
|
||||
|
@ -54,7 +73,7 @@ namespace CRL {
|
|||
if (translated == ']' ) translated = rightPar;
|
||||
|
||||
if (translated == '_') {
|
||||
if (i == 0 ) continue;
|
||||
if (vhdlName.empty() ) continue;
|
||||
if (i == vlogName.size()-1) break;
|
||||
if (vhdlName.back() == '_') continue;
|
||||
}
|
||||
|
@ -62,6 +81,11 @@ namespace CRL {
|
|||
vhdlName += translated;
|
||||
}
|
||||
|
||||
// VHDL reserved keywords (vector).
|
||||
if (vhdlName.substr(0,3) == "in(" ) vhdlName.insert(2,"_v");
|
||||
if (vhdlName.substr(0,4) == "out(" ) vhdlName.insert(3,"_v");
|
||||
if (vhdlName.substr(0,6) == "inout(") vhdlName.insert(5,"_v");
|
||||
|
||||
return Name(vhdlName);
|
||||
}
|
||||
|
||||
|
@ -91,7 +115,9 @@ namespace CRL {
|
|||
for ( auto inst : instances ) inst->setName( converter( inst->getName() ) );
|
||||
|
||||
if (flags & Recursive)
|
||||
for ( auto model : models ) toVhdl( model, flags );
|
||||
for ( auto model : models ) {
|
||||
if (not model->isTerminal()) toVhdl( model, flags );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -579,6 +579,8 @@ namespace Etesian {
|
|||
using namespace coloquinte::gp;
|
||||
using namespace coloquinte::dp;
|
||||
|
||||
getCell()->uniquify();
|
||||
|
||||
getConfiguration()->print( getCell() );
|
||||
if (getCell()->getAbutmentBox().isEmpty()) setDefaultAb();
|
||||
|
||||
|
|
|
@ -198,6 +198,28 @@
|
|||
* De-materializes all components of all the nets of the Cell.
|
||||
*/
|
||||
|
||||
//! \function void Cell::uniquify ( unsigned int depth=(unsigned int)-1 );
|
||||
//! \param depth Recursively perform the uniquification until that
|
||||
//! hierarchical depth.
|
||||
//!
|
||||
//! Multiple instances of a same model are modificated so that
|
||||
//! each instance has it's own \e unique copy of the model.
|
||||
//!
|
||||
//! This is equivalent to a flatten operation, but without
|
||||
//! destroying the intermediate level of hierarchy. Only the
|
||||
//! \b netlist and instance's placements gets duplicated.
|
||||
//! <em>No physical components will be duplicated.</em>
|
||||
//!
|
||||
//! \see Cell::getClone(), Instance::uniquify().
|
||||
|
||||
//! \function Cell* Cell::getClone ();
|
||||
//! Build a duplicate of the Cell. The database keep track of all
|
||||
//! the duplicate of one original Cell. The name of a duplicate
|
||||
//! is generated by appending \c '_uXX' where \c 'XX' is the number
|
||||
//! of the duplicate.
|
||||
//!
|
||||
//! Only logical information (netlist) and instance's placements
|
||||
//! gets duplicated. <em>No physical components will be duplicated.</em>
|
||||
|
||||
/*! \typedef typedef GenericCollection<Cell*> Cells;
|
||||
* Generic collection representing a set of cell objects.
|
||||
|
|
|
@ -163,6 +163,18 @@
|
|||
* occurences are therefore deleted.
|
||||
*/
|
||||
|
||||
//! \function void Instance::uniquify ();
|
||||
//! Replace the \c <masterCell> of this instance by a cloned copy.
|
||||
//!
|
||||
//! \see Cell::getClone().
|
||||
|
||||
//! \function Instance* Instance::getClone ( Cell* cloneCell );
|
||||
//! Build a duplicate of instance (\c <this>) inside a cloned Cell \c <cloneCell>.
|
||||
//! The connections (Plug) on the copied instance are copied. That is,
|
||||
//! connected to Net with identical names in \c <cloneCell>.
|
||||
//!
|
||||
//! \important In \c <cloneCell>, a copy (by name) of all the nets this instance
|
||||
//! is connected to must exits.
|
||||
|
||||
//! \name Instance Collection
|
||||
// \{
|
||||
|
|
|
@ -291,6 +291,13 @@
|
|||
* their occurences).
|
||||
*/
|
||||
|
||||
//! \function Net* Net::getClone ( Cell* cloneCell );
|
||||
//! Build a duplicate of net (\c <this>) inside a cloned Cell \c <cloneCell>.
|
||||
//! The connectivity (Plug) or components of the original net are \b not
|
||||
//! copied.
|
||||
//!
|
||||
//! \remark It is likely that \c <cloneCell> is a copy of this net's onwer Cell,
|
||||
//! but it is not mandatory.
|
||||
|
||||
//! \name Net Collection
|
||||
// \{
|
||||
|
|
|
@ -38,6 +38,72 @@
|
|||
namespace Hurricane {
|
||||
|
||||
|
||||
const Name Cell::UniquifyRelation::_name = "Cell::UniquifyRelation";
|
||||
|
||||
|
||||
Cell::UniquifyRelation::UniquifyRelation ( Cell* masterOwner )
|
||||
: Relation (masterOwner)
|
||||
, _duplicates(1)
|
||||
{ }
|
||||
|
||||
|
||||
Cell::UniquifyRelation* Cell::UniquifyRelation::create ( Cell* masterOwner )
|
||||
{
|
||||
UniquifyRelation* relation = new UniquifyRelation(masterOwner);
|
||||
|
||||
relation->_postCreate();
|
||||
|
||||
return relation;
|
||||
}
|
||||
|
||||
|
||||
void Cell::UniquifyRelation::_preDestroy ()
|
||||
{
|
||||
Relation::_preDestroy();
|
||||
}
|
||||
|
||||
|
||||
Cell::UniquifyRelation* Cell::UniquifyRelation::get ( const Cell* cell )
|
||||
{
|
||||
if (not cell)
|
||||
throw Error( "Can't get Cell::UniquifyRelation : empty cell" );
|
||||
Property* property = cell->getProperty( staticGetName() );
|
||||
if (property) {
|
||||
UniquifyRelation* relation = dynamic_cast<UniquifyRelation*>(property);
|
||||
if (not relation )
|
||||
throw Error ( "Bad Property type: Must be a UniquifyRelation" );
|
||||
return relation;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Name Cell::UniquifyRelation::staticGetName () { return _name; }
|
||||
Name Cell::UniquifyRelation::getName () const { return _name; }
|
||||
string Cell::UniquifyRelation::_getTypeName () const { return "Cell::UniquifyRelation"; }
|
||||
|
||||
|
||||
Name Cell::UniquifyRelation::getUniqueName ()
|
||||
{
|
||||
Cell* owner = dynamic_cast<Cell*>( getMasterOwner() );
|
||||
ostringstream name;
|
||||
|
||||
name << getString(owner->getName()) << "_u" << setw(2) << setfill('0') << _duplicates++;
|
||||
|
||||
return Name(name.str());
|
||||
}
|
||||
|
||||
|
||||
Record* Cell::UniquifyRelation::_getRecord () const
|
||||
{
|
||||
Record* record = Relation::_getRecord();
|
||||
if (record) {
|
||||
record->add( getSlot( "_duplicates", &_duplicates ) );
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
void Cell::_insertSlice ( ExtensionSlice* slice )
|
||||
{
|
||||
ExtensionSliceMap::iterator islice = _extensionSlices.find ( slice->getName() );
|
||||
|
@ -100,6 +166,7 @@ Cell::Cell(Library* library, const Name& name)
|
|||
_abutmentBox(),
|
||||
_boundingBox(),
|
||||
_isTerminal(true),
|
||||
_isFlattenLeaf(false),
|
||||
_isPad(false),
|
||||
_nextOfLibraryCellMap(NULL),
|
||||
_nextOfSymbolCellSet(NULL),
|
||||
|
@ -343,6 +410,80 @@ void Cell::flattenNets(unsigned int flags)
|
|||
UpdateSession::close();
|
||||
}
|
||||
|
||||
|
||||
Cell* Cell::getCloneMaster() const
|
||||
// *******************************
|
||||
{
|
||||
UniquifyRelation* uniquify = UniquifyRelation::get( this );
|
||||
if (not uniquify) return const_cast<Cell*>(this);
|
||||
|
||||
uniquify = UniquifyRelation::get( this );
|
||||
return dynamic_cast<Cell*>( uniquify->getMasterOwner() );
|
||||
}
|
||||
|
||||
|
||||
Cell* Cell::getClone()
|
||||
// *******************
|
||||
{
|
||||
UpdateSession::open();
|
||||
|
||||
UniquifyRelation* uniquify = UniquifyRelation::get( this );
|
||||
if (not uniquify) {
|
||||
uniquify = UniquifyRelation::create( this );
|
||||
}
|
||||
|
||||
Cell* clone = Cell::create( getLibrary(), uniquify->getUniqueName() );
|
||||
clone->put ( uniquify );
|
||||
clone->setTerminal ( isTerminal () );
|
||||
clone->setFlattenLeaf( isFlattenLeaf () );
|
||||
clone->setPad ( isPad () );
|
||||
clone->setAbutmentBox( getAbutmentBox() );
|
||||
|
||||
forEach( Net*, inet, getNets() ) {
|
||||
if (dynamic_cast<DeepNet*>(*inet)) continue;
|
||||
inet->getClone( clone );
|
||||
}
|
||||
|
||||
bool isPlaced = true;
|
||||
forEach( Instance*, iinstance, getInstances() ) {
|
||||
if (iinstance->getClone(clone)->getPlacementStatus() == Instance::PlacementStatus::UNPLACED)
|
||||
isPlaced = false;
|
||||
}
|
||||
if (isPlaced) clone->setFlags( Placed );
|
||||
|
||||
UpdateSession::close();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
void Cell::uniquify(unsigned int depth)
|
||||
// ************************************
|
||||
{
|
||||
vector<Instance*> toUniquify;
|
||||
set<Cell*> masterCells;
|
||||
|
||||
forEach ( Instance*, iinstance, getInstances() ) {
|
||||
Cell* masterCell = iinstance->getMasterCell();
|
||||
if (masterCell->isTerminal()) continue;
|
||||
|
||||
masterCells.insert( masterCell );
|
||||
if (masterCell->getSlaveInstances().getSize() > 1) {
|
||||
toUniquify.push_back( *iinstance );
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto iinst : toUniquify ) {
|
||||
iinst->uniquify();
|
||||
masterCells.insert( iinst->getMasterCell() );
|
||||
}
|
||||
|
||||
if (depth > 0) {
|
||||
for ( auto icell : masterCells )
|
||||
icell->uniquify( depth-1 );
|
||||
}
|
||||
}
|
||||
|
||||
void Cell::materialize()
|
||||
// *********************
|
||||
{
|
||||
|
@ -509,6 +650,66 @@ void Cell::notify(unsigned flags)
|
|||
_observers.notify(flags);
|
||||
}
|
||||
|
||||
// ****************************************************************************************************
|
||||
// Cell::ClonedSet implementation
|
||||
// ****************************************************************************************************
|
||||
|
||||
Cell::ClonedSet::Locator::Locator ( const Cell* cell )
|
||||
: Hurricane::Locator<Cell*>()
|
||||
, _dboLocator (NULL)
|
||||
{
|
||||
UniquifyRelation* uniquify = UniquifyRelation::get( cell );
|
||||
if (uniquify) {
|
||||
_dboLocator = uniquify->getSlaveOwners().getLocator();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Locator<Cell*>* Cell::ClonedSet::Locator::getClone () const
|
||||
{ return new Locator(*this); }
|
||||
|
||||
|
||||
Cell* Cell::ClonedSet::Locator::getElement () const
|
||||
{ return (_dboLocator and _dboLocator->isValid())
|
||||
? dynamic_cast<Cell*>(_dboLocator->getElement()) : NULL; }
|
||||
|
||||
|
||||
bool Cell::ClonedSet::Locator::isValid () const
|
||||
{ return (_dboLocator and _dboLocator->isValid()); }
|
||||
|
||||
|
||||
void Cell::ClonedSet::Locator::progress ()
|
||||
{
|
||||
_dboLocator->progress();
|
||||
}
|
||||
|
||||
|
||||
string Cell::ClonedSet::Locator::_getString () const
|
||||
{
|
||||
string s = "<" + _TName("Cell::ClonedSet::Locator")
|
||||
+ getString(getElement())
|
||||
+ ">";
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
Collection<Cell*>* Cell::ClonedSet::getClone () const
|
||||
{ return new ClonedSet(*this); }
|
||||
|
||||
|
||||
Locator<Cell*>* Cell::ClonedSet::getLocator () const
|
||||
{ return new Locator(_cell); }
|
||||
|
||||
|
||||
string Cell::ClonedSet::_getString () const
|
||||
{
|
||||
string s = "<" + _TName("Cell_ClonedSet") + " "
|
||||
+ getString(_cell->getName())
|
||||
+ ">";
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
// ****************************************************************************************************
|
||||
// Cell::InstanceMap implementation
|
||||
// ****************************************************************************************************
|
||||
|
|
|
@ -1980,6 +1980,12 @@ Cells Cell::getSubCells() const
|
|||
return Cell_SubCells(this);
|
||||
}
|
||||
|
||||
Cells Cell::getClonedCells() const
|
||||
// *******************************
|
||||
{
|
||||
return ClonedSet(this);
|
||||
}
|
||||
|
||||
Components Cell::getComponents(const Layer::Mask& mask) const
|
||||
// **********************************************************
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ****************************************************************************************************
|
||||
// File: ./Instance.cpp
|
||||
// Authors: R. Escassut
|
||||
// Copyright (c) BULL S.A. 2000-2009, All Rights Reserved
|
||||
// Copyright (c) BULL S.A. 2000-2015, All Rights Reserved
|
||||
//
|
||||
// This file is part of Hurricane.
|
||||
//
|
||||
|
@ -17,6 +17,8 @@
|
|||
// not, see <http://www.gnu.org/licenses/>.
|
||||
// ****************************************************************************************************
|
||||
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/UpdateSession.h"
|
||||
#include "hurricane/SharedPath.h"
|
||||
#include "hurricane/Instance.h"
|
||||
#include "hurricane/Cell.h"
|
||||
|
@ -392,6 +394,7 @@ void Instance::setMasterCell(Cell* masterCell, bool secureFlag)
|
|||
// ************************************************************
|
||||
{
|
||||
if (masterCell != _masterCell) {
|
||||
UpdateSession::open();
|
||||
|
||||
if (!masterCell)
|
||||
throw Error("Can't set master : null master cell");
|
||||
|
@ -442,9 +445,51 @@ void Instance::setMasterCell(Cell* masterCell, bool secureFlag)
|
|||
if (!getPlug(externalNet)) Plug::_create(this, externalNet);
|
||||
end_for;
|
||||
}
|
||||
|
||||
UpdateSession::close();
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::uniquify()
|
||||
// **********************
|
||||
{
|
||||
if (_masterCell->getSlaveInstances().getSize() == 1) {
|
||||
cerr << Warning( "Instance::uniquify(): Master Cell %s of %s is already unique."
|
||||
, getString(_masterCell->getName()).c_str()
|
||||
, getString(getName()).c_str()
|
||||
) << endl;
|
||||
}
|
||||
setMasterCell( _masterCell->getClone() );
|
||||
}
|
||||
|
||||
Instance* Instance::getClone(Cell* cloneCell) const
|
||||
// ************************************************
|
||||
{
|
||||
Instance* clone = Instance::create( cloneCell
|
||||
, getName()
|
||||
, getMasterCell()
|
||||
, getPlacementStatus()
|
||||
);
|
||||
|
||||
forEach( Plug*, iplug, getPlugs() ) {
|
||||
if (iplug->isConnected()) {
|
||||
Plug* clonePlug = clone->getPlug( iplug->getMasterNet() );
|
||||
Net* cloneNet = cloneCell->getNet( iplug->getNet()->getName() );
|
||||
if (cloneNet) {
|
||||
clonePlug->setNet( cloneNet );
|
||||
} else {
|
||||
cerr << Warning( "Instance::getClone(): While cloning instance %s, missing net %s in cloned cell %s."
|
||||
, getString(getName()).c_str()
|
||||
, getString(iplug->getNet()->getName()).c_str()
|
||||
, getString(cloneCell->getName()).c_str()
|
||||
) << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
void Instance::_postCreate()
|
||||
// *************************
|
||||
{
|
||||
|
|
|
@ -536,6 +536,19 @@ bool Net::removeAlias(const Name& name )
|
|||
return false;
|
||||
}
|
||||
|
||||
Net* Net::getClone(Cell* clonedCell)
|
||||
// *********************************
|
||||
{
|
||||
Net* clonedNet = Net::create( clonedCell, getName() );
|
||||
clonedNet->setArity ( getArity() );
|
||||
clonedNet->setGlobal ( isGlobal() );
|
||||
clonedNet->setExternal ( isExternal() );
|
||||
clonedNet->setType ( getType() );
|
||||
clonedNet->setDirection( getDirection() );
|
||||
|
||||
return clonedNet;
|
||||
}
|
||||
|
||||
void Net::materialize()
|
||||
// ********************
|
||||
{
|
||||
|
@ -639,6 +652,8 @@ void Net::merge(Net* net)
|
|||
net->_mainName.detach();
|
||||
}
|
||||
|
||||
if (net->isExternal() and not isExternal())
|
||||
setExternal( true );
|
||||
net->destroy();
|
||||
|
||||
if (slaves) _mainName.attach( slaves );
|
||||
|
|
|
@ -163,10 +163,10 @@ namespace Hurricane {
|
|||
Net* NetMainName::getNet () const { return (Net*)((ptrdiff_t)this - _offset); }
|
||||
string NetMainName::_getString () const { return "<NetMainName " + getString(getName()) + ">"; }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Hurricane::NetAliasName".
|
||||
|
||||
|
||||
NetAliasName::NetAliasName ( Name name )
|
||||
: NetAliasHook()
|
||||
, _name (name)
|
||||
|
@ -210,4 +210,56 @@ namespace Hurricane {
|
|||
return record;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Hurricane::AliasList" (Collection).
|
||||
|
||||
AliasList::Locator::Locator ( const Net* net )
|
||||
: Hurricane::Locator<NetAliasHook*>()
|
||||
, _hook (net->getMainName()->getNext())
|
||||
{ }
|
||||
|
||||
|
||||
Locator<NetAliasHook*>* AliasList::Locator::getClone () const
|
||||
{ return new Locator(*this); }
|
||||
|
||||
|
||||
NetAliasHook* AliasList::Locator::getElement () const
|
||||
{ return isValid() ? _hook : NULL; }
|
||||
|
||||
|
||||
bool AliasList::Locator::isValid () const
|
||||
{ return (_hook and not _hook->isMaster()); }
|
||||
|
||||
|
||||
void AliasList::Locator::progress ()
|
||||
{ if (not _hook->isMaster()) _hook = _hook->getNext(); }
|
||||
|
||||
|
||||
string AliasList::Locator::_getString () const
|
||||
{
|
||||
string s = "<" + _TName("AliasList::Locator")
|
||||
+ getString(getElement())
|
||||
+ ">";
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
Collection<NetAliasHook*>* AliasList::getClone () const
|
||||
{ return new AliasList(*this); }
|
||||
|
||||
|
||||
Locator<NetAliasHook*>* AliasList::getLocator () const
|
||||
{ return new Locator(_net); }
|
||||
|
||||
|
||||
string AliasList::_getString () const
|
||||
{
|
||||
string s = "<" + _TName("NetAliasHook") + " "
|
||||
+ getString(_net->getName())
|
||||
+ ">";
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
} // Hurricane namespace.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ****************************************************************************************************
|
||||
// File: ./Relation.cpp
|
||||
// Authors: R. Escassut
|
||||
// Copyright (c) BULL S.A. 2000-2009, All Rights Reserved
|
||||
// Copyright (c) BULL S.A. 2000-2015, All Rights Reserved
|
||||
//
|
||||
// This file is part of Hurricane.
|
||||
//
|
||||
|
|
|
@ -17,10 +17,12 @@
|
|||
// not, see <http://www.gnu.org/licenses/>.
|
||||
// ****************************************************************************************************
|
||||
|
||||
#ifndef HURRICANE_CELL
|
||||
#define HURRICANE_CELL
|
||||
#ifndef HURRICANE_CELL_H
|
||||
#define HURRICANE_CELL_H
|
||||
|
||||
#include <limits>
|
||||
#include "hurricane/Observer.h"
|
||||
#include "hurricane/Relation.h"
|
||||
#include "hurricane/Pathes.h"
|
||||
#include "hurricane/Entity.h"
|
||||
#include "hurricane/Cells.h"
|
||||
|
@ -82,6 +84,50 @@ class Cell : public Entity {
|
|||
public: typedef Entity Inherit;
|
||||
public: typedef map<Name,ExtensionSlice*> ExtensionSliceMap;
|
||||
|
||||
class UniquifyRelation : public Relation {
|
||||
public:
|
||||
static UniquifyRelation* create ( Cell* );
|
||||
static UniquifyRelation* get ( const Cell* );
|
||||
virtual Name getName () const;
|
||||
static Name staticGetName ();
|
||||
Name getUniqueName ();
|
||||
virtual string _getTypeName () const;
|
||||
virtual Record* _getRecord () const;
|
||||
private:
|
||||
static const Name _name;
|
||||
unsigned int _duplicates;
|
||||
private:
|
||||
UniquifyRelation ( Cell* );
|
||||
protected:
|
||||
virtual void _preDestroy ();
|
||||
};
|
||||
|
||||
class ClonedSet : public Collection<Cell*> {
|
||||
public:
|
||||
// Sub-Class: Locator.
|
||||
class Locator : public Hurricane::Locator<Cell*> {
|
||||
public:
|
||||
Locator ( const Cell* );
|
||||
inline Locator ( const Locator& );
|
||||
virtual Cell* getElement () const;
|
||||
virtual Hurricane::Locator<Cell*>* getClone () const;
|
||||
virtual bool isValid () const;
|
||||
virtual void progress ();
|
||||
virtual string _getString () const;
|
||||
protected:
|
||||
Hurricane::Locator<DBo*>* _dboLocator;
|
||||
};
|
||||
|
||||
public:
|
||||
inline ClonedSet ( const Cell* cell );
|
||||
inline ClonedSet ( const ClonedSet& );
|
||||
virtual Hurricane::Collection<Cell*>* getClone () const;
|
||||
virtual Hurricane::Locator<Cell*>* getLocator () const;
|
||||
virtual string _getString () const;
|
||||
protected:
|
||||
const Cell* _cell;
|
||||
};
|
||||
|
||||
class InstanceMap : public IntrusiveMap<Name, Instance> {
|
||||
// ****************************************************
|
||||
|
||||
|
@ -289,8 +335,8 @@ class Cell : public Entity {
|
|||
public: References getReferences() const;
|
||||
public: Components getComponents(const Layer::Mask& mask = ~0) const;
|
||||
public: Components getComponentsUnder(const Box& area, const Layer::Mask& mask = ~0) const;
|
||||
public: Occurrences getOccurrences(unsigned searchDepth = (unsigned)-1) const;
|
||||
public: Occurrences getOccurrencesUnder(const Box& area, unsigned searchDepth = (unsigned)-1) const;
|
||||
public: Occurrences getOccurrences(unsigned searchDepth = std::numeric_limits<unsigned int>::max()) const;
|
||||
public: Occurrences getOccurrencesUnder(const Box& area, unsigned searchDepth = std::numeric_limits<unsigned int>::max()) const;
|
||||
public: Occurrences getTerminalInstanceOccurrences() const;
|
||||
public: Occurrences getTerminalInstanceOccurrencesUnder(const Box& area) const;
|
||||
public: Occurrences getLeafInstanceOccurrences() const;
|
||||
|
@ -305,6 +351,8 @@ class Cell : public Entity {
|
|||
public: Gos getExtensionGosUnder ( const Box& area, const Name& name ) const;
|
||||
public: Gos getExtensionGosUnder ( const Box& area, ExtensionSlice::Mask mask = ~0 ) const;
|
||||
public: Cells getSubCells() const;
|
||||
public: Cells getClonedCells() const;
|
||||
public: Cell* getCloneMaster() const;
|
||||
public: Pathes getRecursiveSlavePathes() const;
|
||||
public: const Box& getAbutmentBox() const {return _abutmentBox;};
|
||||
|
||||
|
@ -334,6 +382,8 @@ class Cell : public Entity {
|
|||
public: void resetFlags(unsigned int flags) { _flags &= ~flags; }
|
||||
public: void materialize();
|
||||
public: void unmaterialize();
|
||||
public: Cell* getClone();
|
||||
public: void uniquify(unsigned int depth=std::numeric_limits<unsigned int>::max());
|
||||
public: void addObserver(BaseObserver*);
|
||||
public: void removeObserver(BaseObserver*);
|
||||
public: void notify(unsigned flags);
|
||||
|
@ -341,6 +391,22 @@ class Cell : public Entity {
|
|||
};
|
||||
|
||||
|
||||
inline Cell::ClonedSet::Locator::Locator ( const Locator& other )
|
||||
: Hurricane::Locator<Cell*>()
|
||||
, _dboLocator(other._dboLocator)
|
||||
{ }
|
||||
|
||||
inline Cell::ClonedSet::ClonedSet ( const Cell* cell )
|
||||
: Hurricane::Collection<Cell*>()
|
||||
, _cell(cell)
|
||||
{ }
|
||||
|
||||
inline Cell::ClonedSet::ClonedSet ( const ClonedSet& other )
|
||||
: Hurricane::Collection<Cell*>()
|
||||
, _cell(other._cell)
|
||||
{ }
|
||||
|
||||
|
||||
} // End of Hurricane namespace.
|
||||
|
||||
|
||||
|
@ -353,7 +419,7 @@ INSPECTOR_P_SUPPORT(Hurricane::Cell::SliceMap);
|
|||
INSPECTOR_P_SUPPORT(Hurricane::Cell::MarkerSet);
|
||||
|
||||
|
||||
#endif // HURRICANE_CELL
|
||||
#endif // HURRICANE_CELL_H
|
||||
|
||||
|
||||
// ****************************************************************************************************
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ****************************************************************************************************
|
||||
// File: ./hurricane/Instance.h
|
||||
// Authors: R. Escassut
|
||||
// Copyright (c) BULL S.A. 2000-2009, All Rights Reserved
|
||||
// Copyright (c) BULL S.A. 2000-2015, All Rights Reserved
|
||||
//
|
||||
// This file is part of Hurricane.
|
||||
//
|
||||
|
@ -17,8 +17,8 @@
|
|||
// not, see <http://www.gnu.org/licenses/>.
|
||||
// ****************************************************************************************************
|
||||
|
||||
#ifndef HURRICANE_INSTANCE
|
||||
#define HURRICANE_INSTANCE
|
||||
#ifndef HURRICANE_INSTANCE_H
|
||||
#define HURRICANE_INSTANCE_H
|
||||
|
||||
#include "hurricane/Go.h"
|
||||
#include "hurricane/Plug.h"
|
||||
|
@ -161,6 +161,8 @@ class Instance : public Go {
|
|||
public: void setTransformation(const Transformation& transformation);
|
||||
public: void setPlacementStatus(const PlacementStatus& placementstatus);
|
||||
public: void setMasterCell(Cell* masterCell, bool secureFlag = true);
|
||||
public: void uniquify();
|
||||
public: Instance* getClone(Cell* cloneCell) const;
|
||||
|
||||
// Others
|
||||
// ******
|
||||
|
|
|
@ -169,6 +169,7 @@ class Net : public Entity {
|
|||
public: virtual Cell* getCell() const {return _cell;};
|
||||
public: virtual Box getBoundingBox() const;
|
||||
public: const Name& getName() const {return _name;};
|
||||
public: const NetMainName* getMainName() const { return &_mainName; }
|
||||
public: const Arity& getArity() const {return _arity;};
|
||||
public: const Type& getType() const {return _type;};
|
||||
public: const Direction& getDirection() const {return _direction;};
|
||||
|
@ -188,6 +189,7 @@ class Net : public Entity {
|
|||
public: Plugs getSlavePlugs() const;
|
||||
public: Plugs getConnectedSlavePlugs() const;
|
||||
public: Plugs getUnconnectedSlavePlugs() const;
|
||||
public: Aliases getAliases() const { return new AliasList(this); };
|
||||
|
||||
// Filters
|
||||
// *******
|
||||
|
@ -231,6 +233,7 @@ class Net : public Entity {
|
|||
public: bool addAlias(const Name& name);
|
||||
public: bool removeAlias(const Name& name);
|
||||
public: void merge(Net* net);
|
||||
public: Net* getClone(Cell* cloneCell);
|
||||
|
||||
// Others
|
||||
// ******
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace Hurricane {
|
|||
|
||||
class NetAliasName : public NetAliasHook {
|
||||
public:
|
||||
class Less {
|
||||
class CompareByName {
|
||||
public:
|
||||
inline bool operator() ( const NetAliasName* lhs, const NetAliasName* rhs ) const;
|
||||
};
|
||||
|
@ -122,12 +122,63 @@ namespace Hurricane {
|
|||
};
|
||||
|
||||
|
||||
inline bool NetAliasName::Less::operator() ( const NetAliasName* lhs
|
||||
, const NetAliasName* rhs ) const
|
||||
inline bool NetAliasName::CompareByName::operator() ( const NetAliasName* lhs
|
||||
, const NetAliasName* rhs ) const
|
||||
{ return lhs->getName() < rhs->getName(); }
|
||||
|
||||
|
||||
typedef std::set<NetAliasName*,NetAliasName::Less> AliasNameSet;
|
||||
typedef std::set<NetAliasName*,NetAliasName::CompareByName> AliasNameSet;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Hurricane::AliasList" (Collection).
|
||||
|
||||
typedef GenericCollection<NetAliasHook*> Aliases;
|
||||
typedef GenericLocator <NetAliasHook*> AliasesLocator;
|
||||
typedef GenericFilter <NetAliasHook*> AliasesFilter;
|
||||
|
||||
|
||||
class AliasList : public Collection<NetAliasHook*> {
|
||||
public:
|
||||
// Sub-Class: Locator.
|
||||
class Locator : public Hurricane::Locator<NetAliasHook*> {
|
||||
public:
|
||||
Locator ( const Net* );
|
||||
inline Locator ( const Locator& );
|
||||
virtual NetAliasHook* getElement () const;
|
||||
virtual Hurricane::Locator<NetAliasHook*>* getClone () const;
|
||||
virtual bool isValid () const;
|
||||
virtual void progress ();
|
||||
virtual string _getString () const;
|
||||
protected:
|
||||
NetAliasHook* _hook;
|
||||
};
|
||||
|
||||
public:
|
||||
inline AliasList ( const Net* net );
|
||||
inline AliasList ( const AliasList& );
|
||||
virtual Hurricane::Collection<NetAliasHook*>* getClone () const;
|
||||
virtual Hurricane::Locator<NetAliasHook*>* getLocator () const;
|
||||
virtual string _getString () const;
|
||||
protected:
|
||||
const Net* _net;
|
||||
};
|
||||
|
||||
|
||||
inline AliasList::Locator::Locator ( const Locator& other )
|
||||
: Hurricane::Locator<NetAliasHook*>()
|
||||
, _hook(other._hook)
|
||||
{ }
|
||||
|
||||
inline AliasList::AliasList ( const Net* net )
|
||||
: Hurricane::Collection<NetAliasHook*>()
|
||||
, _net(net)
|
||||
{ }
|
||||
|
||||
inline AliasList::AliasList ( const AliasList& other )
|
||||
: Hurricane::Collection<NetAliasHook*>()
|
||||
, _net(other._net)
|
||||
{ }
|
||||
|
||||
|
||||
} // Namespace Hurricane.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ****************************************************************************************************
|
||||
// File: ./hurricane/Relation.h
|
||||
// Authors: R. Escassut
|
||||
// Copyright (c) BULL S.A. 2000-2009, All Rights Reserved
|
||||
// Copyright (c) BULL S.A. 2000-2015, All Rights Reserved
|
||||
//
|
||||
// This file is part of Hurricane.
|
||||
//
|
||||
|
@ -17,8 +17,8 @@
|
|||
// not, see <http://www.gnu.org/licenses/>.
|
||||
// ****************************************************************************************************
|
||||
|
||||
#ifndef HURRICANE_RELATION
|
||||
#define HURRICANE_RELATION
|
||||
#ifndef HURRICANE_RELATION_H
|
||||
#define HURRICANE_RELATION_H
|
||||
|
||||
#include "hurricane/Property.h"
|
||||
|
||||
|
|
|
@ -652,6 +652,41 @@ extern "C" {
|
|||
HCATCH
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyCell_uniquify ()"
|
||||
|
||||
static PyObject* PyCell_uniquify ( PyCell *self, PyObject* args ) {
|
||||
trace << "PyCell_uniquify ()" << endl;
|
||||
|
||||
HTRY
|
||||
METHOD_HEAD ( "Cell.uniquify()" )
|
||||
unsigned int depth;
|
||||
if (not PyArg_ParseTuple(args,"I:Cell.uniquify", &depth)) {
|
||||
PyErr_SetString(ConstructorError, "Cell.uniquify(): Invalid number/bad type of parameter.");
|
||||
return NULL;
|
||||
}
|
||||
cell->uniquify( depth );
|
||||
HCATCH
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyCell_getClone ()"
|
||||
|
||||
static PyObject* PyCell_getClone ( PyCell *self ) {
|
||||
trace << "PyCell_getClone ()" << endl;
|
||||
|
||||
Cell* cloneCell = NULL;
|
||||
HTRY
|
||||
METHOD_HEAD( "Cell.getClone()" )
|
||||
cloneCell = cell->getClone();
|
||||
HCATCH
|
||||
|
||||
return PyCell_Link( cloneCell );
|
||||
}
|
||||
|
||||
|
||||
// Standart Predicates (Attributes).
|
||||
|
@ -692,10 +727,12 @@ extern "C" {
|
|||
, { "getAbutmentBox" , (PyCFunction)PyCell_getAbutmentBox , METH_NOARGS , "Returns the abutment box of the cell(which is defined by the designer unlike the bounding box which is managed dynamically)" }
|
||||
, { "isTerminal" , (PyCFunction)PyCell_isTerminal , METH_NOARGS , "Returns true if the cell is marked as terminal, else false." }
|
||||
, { "isLeaf" , (PyCFunction)PyCell_isLeaf , METH_NOARGS , "Returns true if the cell is a leaf of the hierarchy, else false." }
|
||||
, { "isBound" , (PyCFunction)PyCell_isPyBound , METH_NOARGS, "Returns true if the cell is bounded to the hurricane cell" }
|
||||
, { "isBound" , (PyCFunction)PyCell_isPyBound , METH_NOARGS , "Returns true if the cell is bounded to the hurricane cell" }
|
||||
, { "setName" , (PyCFunction)PyCell_setName , METH_VARARGS, "Allows to change the cell name." }
|
||||
, { "setAbutmentBox" , (PyCFunction)PyCell_setAbutmentBox , METH_VARARGS, "Sets the cell abutment box." }
|
||||
, { "setTerminal" , (PyCFunction)PyCell_setTerminal , METH_VARARGS, "Sets the cell terminal status." }
|
||||
, { "uniquify" , (PyCFunction)PyCell_uniquify , METH_VARARGS, "Uniquify the Cell and it's instances up to <depth>." }
|
||||
, { "getClone" , (PyCFunction)PyCell_getClone , METH_NOARGS , "Return a copy of the Cell (placement only)." }
|
||||
, { "destroy" , (PyCFunction)PyCell_destroy , METH_NOARGS
|
||||
, "Destroy associated hurricane object The python object remains." }
|
||||
, {NULL, NULL, 0, NULL} /* sentinel */
|
||||
|
|
|
@ -38,25 +38,18 @@ extern "C" {
|
|||
#define ACCESS_CLASS(_pyObject) &(_pyObject->_baseObject)
|
||||
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(Instance,instance,function)
|
||||
|
||||
#define LOAD_CONSTANT(CONSTANT_VALUE,CONSTANT_NAME) \
|
||||
#define LOAD_CONSTANT(CONSTANT_VALUE,CONSTANT_NAME) \
|
||||
constant = PyInt_FromLong ( (long)CONSTANT_VALUE ); \
|
||||
PyDict_SetItemString ( dictionnary, CONSTANT_NAME, constant ); \
|
||||
Py_DECREF ( constant );
|
||||
|
||||
|
||||
// x=================================================================x
|
||||
// +=================================================================+
|
||||
// | "PyInstance" Python Module Code Part |
|
||||
// x=================================================================x
|
||||
// +=================================================================+
|
||||
|
||||
#if defined(__PYTHON_MODULE__)
|
||||
|
||||
|
||||
// x-------------------------------------------------------------x
|
||||
// | "PyInstance" Local Functions |
|
||||
// x-------------------------------------------------------------x
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Local Function : "PyInt_AsType ()"
|
||||
|
||||
static Instance::PlacementStatus PyInt_AsPlacementStatus ( PyObject* object )
|
||||
{
|
||||
|
@ -68,13 +61,6 @@ extern "C" {
|
|||
|
||||
return ( Instance::PlacementStatus(Instance::PlacementStatus::UNPLACED) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// x-------------------------------------------------------------x
|
||||
// | "PyInstance" Attribute Methods |
|
||||
// x-------------------------------------------------------------x
|
||||
|
||||
|
||||
// Standart Accessors (Attributes).
|
||||
|
@ -82,15 +68,11 @@ extern "C" {
|
|||
// Standart destroy (Attribute).
|
||||
DBoDestroyAttribute(PyInstance_destroy,PyInstance)
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_getName ()"
|
||||
|
||||
GetNameMethod(Instance, instance)
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_create ()"
|
||||
|
||||
PyObject* PyInstance_create ( PyObject*, PyObject *args ) {
|
||||
static PyObject* PyInstance_create ( PyObject*, PyObject *args )
|
||||
{
|
||||
trace << "PyInstance_create ()" << endl;
|
||||
|
||||
Instance* instance = NULL;
|
||||
|
@ -132,10 +114,9 @@ extern "C" {
|
|||
return PyInstance_Link ( instance );
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_getMasterCell ()"
|
||||
|
||||
static PyObject* PyInstance_getMasterCell ( PyInstance *self ) {
|
||||
static PyObject* PyInstance_getMasterCell ( PyInstance *self )
|
||||
{
|
||||
trace << "PyInstance_getMasterCell ()" << endl;
|
||||
|
||||
Cell* cell = NULL;
|
||||
|
@ -148,10 +129,9 @@ extern "C" {
|
|||
return PyCell_Link ( cell );
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_getPlacementStatus ()"
|
||||
|
||||
static PyObject* PyInstance_getPlacementStatus ( PyInstance *self ) {
|
||||
static PyObject* PyInstance_getPlacementStatus ( PyInstance *self )
|
||||
{
|
||||
trace << "PyInstance_getPlacementStatus ()" << endl;
|
||||
|
||||
METHOD_HEAD ( "Instance.getPlacementStatus()" );
|
||||
|
@ -164,10 +144,9 @@ extern "C" {
|
|||
return pyObject;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_SetPlacementStatus ()"
|
||||
|
||||
static PyObject* PyInstance_setPlacementStatus ( PyInstance *self, PyObject* args ) {
|
||||
static PyObject* PyInstance_setPlacementStatus ( PyInstance *self, PyObject* args )
|
||||
{
|
||||
trace << "PyInstance_setPlacementStatus()" << endl;
|
||||
METHOD_HEAD ( "Instance.setPlacementStatus()" )
|
||||
|
||||
|
@ -181,10 +160,9 @@ extern "C" {
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_getTransformation ()"
|
||||
|
||||
static PyObject* PyInstance_getTransformation ( PyInstance *self ) {
|
||||
static PyObject* PyInstance_getTransformation ( PyInstance *self )
|
||||
{
|
||||
trace << "PyInstance_getTransformation ()" << endl;
|
||||
METHOD_HEAD ( "Instance.getTransformation()" );
|
||||
|
||||
|
@ -198,10 +176,9 @@ extern "C" {
|
|||
return ( (PyObject*)resultPyTransf );
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_getPlug ()"
|
||||
|
||||
static PyObject* PyInstance_getPlug ( PyInstance *self, PyObject* args ) {
|
||||
static PyObject* PyInstance_getPlug ( PyInstance *self, PyObject* args )
|
||||
{
|
||||
trace << "PyInstance_getPlug ()" << endl;
|
||||
|
||||
Plug* plug = NULL;
|
||||
|
@ -218,10 +195,9 @@ extern "C" {
|
|||
return PyPlug_Link ( plug );
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_getPlugs()"
|
||||
|
||||
static PyObject* PyInstance_getPlugs(PyInstance *self ) {
|
||||
static PyObject* PyInstance_getPlugs(PyInstance *self )
|
||||
{
|
||||
trace << "PyInstance_getPlugs()" << endl;
|
||||
|
||||
METHOD_HEAD ( "Instance.getPlugs()" )
|
||||
|
@ -243,12 +219,8 @@ extern "C" {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_getConnectedPlugs()"
|
||||
|
||||
static PyObject* PyInstance_getConnectedPlugs(PyInstance *self) {
|
||||
static PyObject* PyInstance_getConnectedPlugs(PyInstance *self)
|
||||
{
|
||||
trace << "PyInstance_getConnectedPlugs ()" << endl;
|
||||
|
||||
METHOD_HEAD ( "Instance.getConnectedPlugs()")
|
||||
|
@ -269,10 +241,9 @@ extern "C" {
|
|||
return (PyObject*)pyPlugCollection;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_getUnconnectedPlugsLocator ()"
|
||||
|
||||
static PyObject* PyInstance_getUnconnectedPlugs(PyInstance *self) {
|
||||
static PyObject* PyInstance_getUnconnectedPlugs(PyInstance *self)
|
||||
{
|
||||
trace << "PyInstance_getUnconnectedPlugs ()" << endl;
|
||||
|
||||
METHOD_HEAD ( "Instance.getUnconnectedPlugs()")
|
||||
|
@ -293,10 +264,9 @@ extern "C" {
|
|||
return (PyObject*)pyPlugCollection;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_getAbutmentBox ()"
|
||||
|
||||
static PyObject* PyInstance_getAbutmentBox ( PyInstance *self ) {
|
||||
static PyObject* PyInstance_getAbutmentBox ( PyInstance *self )
|
||||
{
|
||||
trace << "PyInstance_getAbutmentBox ()" << endl;
|
||||
METHOD_HEAD ( "Instance.getAbutmentBox()" )
|
||||
|
||||
|
@ -309,20 +279,46 @@ extern "C" {
|
|||
|
||||
return ( (PyObject*)pyBox );
|
||||
}
|
||||
|
||||
|
||||
static PyObject* PyInstance_uniquify ( PyInstance *self )
|
||||
{
|
||||
trace << "PyInstance_uniquify ()" << endl;
|
||||
|
||||
HTRY
|
||||
METHOD_HEAD ( "Instance.uniquify()" )
|
||||
instance->uniquify();
|
||||
HCATCH
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PyObject* PyInstance_getClone ( PyInstance *self, PyObject* args )
|
||||
{
|
||||
trace << "PyInstance_getClone ()" << endl;
|
||||
|
||||
Instance* cloneInstance = NULL;
|
||||
HTRY
|
||||
METHOD_HEAD( "Instance.getClone()" )
|
||||
PyCell* pyCloneCell;
|
||||
if (PyArg_ParseTuple(args, "O!:Instance.getClone", &PyTypeCell, &pyCloneCell)) {
|
||||
cloneInstance = instance->getClone( PYCELL_O(pyCloneCell) );
|
||||
} else {
|
||||
PyErr_SetString (ConstructorError, "Instance.getClone(): invalid number/bad type of parameter(s).");
|
||||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
|
||||
return PyInstance_Link( cloneInstance );
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_setName ()"
|
||||
|
||||
SetNameMethod(Instance, instance)
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_SetTransformation ()"
|
||||
|
||||
static PyObject* PyInstance_setTransformation ( PyInstance *self, PyObject* args ) {
|
||||
static PyObject* PyInstance_setTransformation ( PyInstance *self, PyObject* args )
|
||||
{
|
||||
trace << "PyInstance_setTransformation()" << endl;
|
||||
METHOD_HEAD ( "Instance.setTransformation()" )
|
||||
|
||||
|
@ -337,12 +333,8 @@ extern "C" {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyInstance_SetMasterCell ()"
|
||||
|
||||
static PyObject* PyInstance_setMasterCell ( PyInstance *self, PyObject* args ) {
|
||||
static PyObject* PyInstance_setMasterCell ( PyInstance *self, PyObject* args )
|
||||
{
|
||||
trace << "Instance.setMasterCell()" << endl;
|
||||
METHOD_HEAD ( "Instance.setMasterCell()" )
|
||||
|
||||
|
@ -356,12 +348,12 @@ extern "C" {
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
// Standart Predicates (Attributes).
|
||||
DirectGetBoolAttribute(PyInstance_isTerminal ,isTerminal ,PyInstance,Instance)
|
||||
DirectGetBoolAttribute(PyInstance_isLeaf ,isLeaf ,PyInstance,Instance)
|
||||
|
||||
GetBoundStateAttribute(PyInstance_isPyBound ,PyInstance,Instance)
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
@ -386,17 +378,13 @@ extern "C" {
|
|||
, { "setTransformation" , (PyCFunction)PyInstance_setTransformation , METH_VARARGS, "Allows to modify the instance transformation." }
|
||||
, { "setPlacementStatus" , (PyCFunction)PyInstance_setPlacementStatus , METH_VARARGS, "Allows to modify the instance placement status." }
|
||||
, { "setMasterCell" , (PyCFunction)PyInstance_setMasterCell , METH_VARARGS, "Allows to change the cell referenced by this instance." }
|
||||
, { "uniquify" , (PyCFunction)PyInstance_uniquify , METH_NOARGS , "Uniquify the Instance (clone it's master Cell)." }
|
||||
, { "getClone" , (PyCFunction)PyInstance_getClone , METH_VARARGS, "Create a clone of this Instance into the cloned Cell (placement only)." }
|
||||
, { "destroy" , (PyCFunction)PyInstance_destroy , METH_NOARGS , "Destroy associated hurricane object The python object remains." }
|
||||
, {NULL, NULL, 0, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// x-------------------------------------------------------------x
|
||||
// | "PyInstance" Object Methods |
|
||||
// x-------------------------------------------------------------x
|
||||
|
||||
DBoDeleteMethod(Instance)
|
||||
PyTypeObjectLinkPyType(Instance)
|
||||
|
||||
|
@ -404,19 +392,15 @@ extern "C" {
|
|||
#else // End of Python Module Code Part.
|
||||
|
||||
|
||||
// x=================================================================x
|
||||
// +=================================================================+
|
||||
// | "PyInstance" Shared Library Code Part |
|
||||
// x=================================================================x
|
||||
|
||||
// +=================================================================+
|
||||
|
||||
|
||||
// Link/Creation Method.
|
||||
DBoLinkCreateMethod(Instance)
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// PyInstance Object Definitions.
|
||||
|
||||
PyTypeInheritedObjectDefinitions(Instance, Entity)
|
||||
|
||||
|
||||
|
@ -430,10 +414,6 @@ extern "C" {
|
|||
|
||||
#endif // End of Shared Library Code Part.
|
||||
|
||||
|
||||
} // End of extern "C".
|
||||
|
||||
|
||||
|
||||
|
||||
} // End of Isobar namespace.
|
||||
|
|
|
@ -468,22 +468,39 @@ extern "C" {
|
|||
trace << "PyNet_merge()" << endl;
|
||||
|
||||
HTRY
|
||||
PyNet* pyNetToMerge;
|
||||
METHOD_HEAD ( "Net.merge()" )
|
||||
if (PyArg_ParseTuple(args, "O!:Net.merge", &PyTypeNet, &pyNetToMerge)) {
|
||||
net->merge(PYNET_O(pyNetToMerge));
|
||||
} else {
|
||||
PyErr_SetString (ConstructorError, "invalid number of parameters for Net.merge.");
|
||||
return NULL;
|
||||
}
|
||||
PyNet* pyNetToMerge;
|
||||
METHOD_HEAD ( "Net.merge()" )
|
||||
if (PyArg_ParseTuple(args, "O!:Net.merge", &PyTypeNet, &pyNetToMerge)) {
|
||||
net->merge(PYNET_O(pyNetToMerge));
|
||||
} else {
|
||||
PyErr_SetString (ConstructorError, "invalid number of parameters for Net.merge.");
|
||||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyNet_merge ()"
|
||||
|
||||
static PyObject* PyNet_getClone ( PyNet *self, PyObject* args ) {
|
||||
trace << "PyNet_getClone()" << endl;
|
||||
|
||||
Net* cloneNet = NULL;
|
||||
HTRY
|
||||
PyCell* pyCloneCell;
|
||||
METHOD_HEAD ( "Net.getClone()" )
|
||||
if (PyArg_ParseTuple(args, "O!:Net.getClone", &PyTypeCell, &pyCloneCell)) {
|
||||
cloneNet = net->getClone( PYCELL_O(pyCloneCell) );
|
||||
} else {
|
||||
PyErr_SetString (ConstructorError, "Net.getClone(): invalid number/bad type of parameter(s).");
|
||||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
|
||||
return PyNet_Link(cloneNet);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
@ -519,8 +536,9 @@ extern "C" {
|
|||
, { "addAlias" , (PyCFunction)PyNet_addAlias , METH_VARARGS, "Add an alias name to the net." }
|
||||
, { "removeAlias" , (PyCFunction)PyNet_removeAlias , METH_VARARGS, "Remove an alias name from the net." }
|
||||
, { "merge" , (PyCFunction)PyNet_merge , METH_VARARGS, "Merges the net <net> to the net <this> which keeps its characteristics (arity, global, external and direction)." }
|
||||
, { "getClone" , (PyCFunction)PyNet_getClone , METH_VARARGS, "Create a clone of this net into the cloned cell (components not cloneds)." }
|
||||
, { "destroy" , (PyCFunction)PyNet_destroy , METH_NOARGS , "Destroy associated hurricane object, the python object remains." }
|
||||
, {NULL, NULL, 0, NULL} /* sentinel */
|
||||
, {NULL, NULL, 0, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -382,6 +382,8 @@ namespace Katabatic {
|
|||
delete [] _blockages;
|
||||
delete [] _densities;
|
||||
delete [] _feedthroughs;
|
||||
delete [] _fragmentations;
|
||||
delete [] _globalsCount;
|
||||
//delete [] _saturateDensities;
|
||||
|
||||
_allocateds--;
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace Kite {
|
|||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::dec;
|
||||
using std::setw;
|
||||
using std::left;
|
||||
using std::ostream;
|
||||
|
@ -604,6 +605,15 @@ namespace Kite {
|
|||
float segmentRatio = (float)(routeds) / (float)(routeds+unrouteds.size()) * 100.0;
|
||||
float wireLengthRatio = (float)(routedWireLength) / (float)(totalWireLength) * 100.0;
|
||||
|
||||
_toolSuccess = (unrouteds.empty());
|
||||
|
||||
if (not unrouteds.empty()) {
|
||||
cerr << " o Routing did not complete, unrouted segments:" << endl;
|
||||
for ( size_t i=0; i<unrouteds.size() ; ++i ) {
|
||||
cerr << " " << dec << setw(4) << (i+1) << "| " << unrouteds[i] << endl;
|
||||
}
|
||||
}
|
||||
|
||||
result << setprecision(4) << segmentRatio
|
||||
<< "% [" << routeds << "+" << unrouteds.size() << "]";
|
||||
cmess1 << Dots::asString( " - Track Segment Completion Ratio", result.str() ) << endl;
|
||||
|
@ -623,15 +633,6 @@ namespace Kite {
|
|||
cmess1 << Dots::asString( " - Wire Length Expand Ratio", result.str() ) << endl;
|
||||
}
|
||||
|
||||
_toolSuccess = (unrouteds.empty());
|
||||
|
||||
if (not unrouteds.empty()) {
|
||||
cerr << " o Routing did not complete, unrouted segments:" << endl;
|
||||
for ( size_t i=0; i<unrouteds.size() ; ++i ) {
|
||||
cerr << " " << setw(4) << (i+1) << "| " << unrouteds[i] << endl;
|
||||
}
|
||||
}
|
||||
|
||||
addMeasure<size_t> ( getCell(), "Segs" , routeds+unrouteds.size() );
|
||||
addMeasure<unsigned long long>( getCell(), "DWL(l)" , totalWireLength , 12 );
|
||||
addMeasure<unsigned long long>( getCell(), "fWL(l)" , totalWireLength-routedWireLength , 12 );
|
||||
|
|
|
@ -48,7 +48,6 @@ def credits ():
|
|||
|
||||
s += ' Coloquinte software credits (used by Etesian)\n'
|
||||
s += ' Author ........................................ Gabriel Gouvine\n'
|
||||
s += ' URL .............. https://github.com/Coloquinte/Coloquinte.git\n\n'
|
||||
|
||||
s += ' FLUTE software credits (used by Knik)\n'
|
||||
s += ' Author ........................................ Chris C. N. CHU\n'
|
||||
|
|
Loading…
Reference in New Issue