From 770b1fbbbc7d97eb72d071b67a6bbe1491267385 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sat, 25 Apr 2015 16:52:18 +0200 Subject: [PATCH] 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. --- crlcore/src/ccore/AllianceFramework.cpp | 2 +- crlcore/src/ccore/alliance/ap/Ap.h | 50 +- crlcore/src/ccore/alliance/ap/ApParser.cpp | 9 + crlcore/src/ccore/blif/BlifParser.cpp | 894 ++++++++++++------- crlcore/src/ccore/toolbox/NamingScheme.cpp | 40 +- etesian/src/EtesianEngine.cpp | 2 + hurricane/doc/hurricane/Cell.dox | 22 + hurricane/doc/hurricane/Instance.dox | 12 + hurricane/doc/hurricane/Net.dox | 7 + hurricane/src/hurricane/Cell.cpp | 201 +++++ hurricane/src/hurricane/CellCollections.cpp | 6 + hurricane/src/hurricane/Instance.cpp | 47 +- hurricane/src/hurricane/Net.cpp | 15 + hurricane/src/hurricane/NetAlias.cpp | 54 +- hurricane/src/hurricane/Relation.cpp | 2 +- hurricane/src/hurricane/hurricane/Cell.h | 76 +- hurricane/src/hurricane/hurricane/Instance.h | 8 +- hurricane/src/hurricane/hurricane/Net.h | 3 + hurricane/src/hurricane/hurricane/NetAlias.h | 59 +- hurricane/src/hurricane/hurricane/Relation.h | 6 +- hurricane/src/isobar/PyCell.cpp | 39 +- hurricane/src/isobar/PyInstance.cpp | 144 ++- hurricane/src/isobar/PyNet.cpp | 38 +- katabatic/src/GCell.cpp | 2 + kite/src/KiteEngine.cpp | 19 +- unicorn/src/cgt.py | 1 - 26 files changed, 1252 insertions(+), 506 deletions(-) diff --git a/crlcore/src/ccore/AllianceFramework.cpp b/crlcore/src/ccore/AllianceFramework.cpp index c3bf3bb0..f615e51e 100644 --- a/crlcore/src/ccore/AllianceFramework.cpp +++ b/crlcore/src/ccore/AllianceFramework.cpp @@ -304,7 +304,7 @@ namespace CRL { (parser->getParsCell())( _environment.getLIBRARIES().getSelected() , state->getCell() ); } catch ( ... ) { if ( createCell ) - state->getCell()->destroy(); + //state->getCell()->destroy(); throw; } } diff --git a/crlcore/src/ccore/alliance/ap/Ap.h b/crlcore/src/ccore/alliance/ap/Ap.h index 357010ba..bd07a41f 100644 --- a/crlcore/src/ccore/alliance/ap/Ap.h +++ b/crlcore/src/ccore/alliance/ap/Ap.h @@ -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 -// Sophie Belloeil -// Hugo Clément -// Jean-Paul Chaput -// Damien Dupuis -// Christian Masson -// Marek Sroka -// -// 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 @@ -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 diff --git a/crlcore/src/ccore/alliance/ap/ApParser.cpp b/crlcore/src/ccore/alliance/ap/ApParser.cpp index 073625d8..72cb6a3a 100644 --- a/crlcore/src/ccore/alliance/ap/ApParser.cpp +++ b/crlcore/src/ccore/alliance/ap/ApParser.cpp @@ -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 (); } diff --git a/crlcore/src/ccore/blif/BlifParser.cpp b/crlcore/src/ccore/blif/BlifParser.cpp index aa653cf7..e735f54b 100644 --- a/crlcore/src/ccore/blif/BlifParser.cpp +++ b/crlcore/src/ccore/blif/BlifParser.cpp @@ -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 #include #include +#include #include #include #include @@ -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 > CoverTable; + public: + Tokenize ( string blifFile ); + inline size_t lineno () const; + inline unsigned int state () const; + const vector& blifLine () const; + const CoverTable& coverTable () const; + bool readEntry (); + private: + bool _readline (); + private: + size_t _lineno; + unsigned int _state; + ifstream _stream; + vector _tokens; + vector _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& 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 > pins; - }; + bool Tokenize::_readline () + { + _tokens.clear(); - struct model{ - string name; - unordered_map pins; - vector subcircuits; - vector > aliases; - bool operator<(model const & o) const{ return name < o.name; } - }; + bool nextLine = true; - std::vector tokenize(std::string const & s){ - std::vector 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 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 > 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& ); + void connectSubckts (); + private: + string _modelName; + string _instanceName; + Connections _connections; + Model* _model; + }; + + typedef vector Subckts; + + +// ------------------------------------------------------------------- +// Class : "::Model" (declaration). + + + class Model { + public: + typedef unordered_map Lut; + static Lut _blifLut; + static vector _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& connection ) { _connections.push_back(connection); } + + +// ------------------------------------------------------------------- +// Class : "::Model" (implementation). + + + Model::Lut Model::_blifLut; + vector 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 models; - ParserState state = EXT; - bool hasName = true; - - string line; - vector current_names; - while(getline(ccell, line)){ - istringstream linestream(line); - vector 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[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& 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(D | it->second); - } - else{ - models.back().pins.insert(pair(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(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 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 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 ; imergeNet( 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 ; imergeNet( 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; igetCell(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 ; iaddConnection( 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; } diff --git a/crlcore/src/ccore/toolbox/NamingScheme.cpp b/crlcore/src/ccore/toolbox/NamingScheme.cpp index cd4b130f..b08d53c0 100644 --- a/crlcore/src/ccore/toolbox/NamingScheme.cpp +++ b/crlcore/src/ccore/toolbox/NamingScheme.cpp @@ -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 1) ? '_' : '('; char rightPar = (parCount > 1) ? '_' : ')'; + if (parCount == 1) { + for ( size_t i=posLeftPar+1 ; isetName( converter( inst->getName() ) ); if (flags & Recursive) - for ( auto model : models ) toVhdl( model, flags ); + for ( auto model : models ) { + if (not model->isTerminal()) toVhdl( model, flags ); + } } diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index 002a6d52..8834ae6e 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -579,6 +579,8 @@ namespace Etesian { using namespace coloquinte::gp; using namespace coloquinte::dp; + getCell()->uniquify(); + getConfiguration()->print( getCell() ); if (getCell()->getAbutmentBox().isEmpty()) setDefaultAb(); diff --git a/hurricane/doc/hurricane/Cell.dox b/hurricane/doc/hurricane/Cell.dox index 9e50d9d3..f3e7c84b 100644 --- a/hurricane/doc/hurricane/Cell.dox +++ b/hurricane/doc/hurricane/Cell.dox @@ -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. + //! No physical components will be duplicated. + //! + //! \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. No physical components will be duplicated. /*! \typedef typedef GenericCollection Cells; * Generic collection representing a set of cell objects. diff --git a/hurricane/doc/hurricane/Instance.dox b/hurricane/doc/hurricane/Instance.dox index d417f820..5d8e7899 100644 --- a/hurricane/doc/hurricane/Instance.dox +++ b/hurricane/doc/hurricane/Instance.dox @@ -163,6 +163,18 @@ * occurences are therefore deleted. */ + //! \function void Instance::uniquify (); + //! Replace the \c of this instance by a cloned copy. + //! + //! \see Cell::getClone(). + + //! \function Instance* Instance::getClone ( Cell* cloneCell ); + //! Build a duplicate of instance (\c ) inside a cloned Cell \c . + //! The connections (Plug) on the copied instance are copied. That is, + //! connected to Net with identical names in \c . + //! + //! \important In \c , a copy (by name) of all the nets this instance + //! is connected to must exits. //! \name Instance Collection // \{ diff --git a/hurricane/doc/hurricane/Net.dox b/hurricane/doc/hurricane/Net.dox index a15f55c7..0595fc66 100644 --- a/hurricane/doc/hurricane/Net.dox +++ b/hurricane/doc/hurricane/Net.dox @@ -291,6 +291,13 @@ * their occurences). */ + //! \function Net* Net::getClone ( Cell* cloneCell ); + //! Build a duplicate of net (\c ) inside a cloned Cell \c . + //! The connectivity (Plug) or components of the original net are \b not + //! copied. + //! + //! \remark It is likely that \c is a copy of this net's onwer Cell, + //! but it is not mandatory. //! \name Net Collection // \{ diff --git a/hurricane/src/hurricane/Cell.cpp b/hurricane/src/hurricane/Cell.cpp index a793ad41..f498197f 100644 --- a/hurricane/src/hurricane/Cell.cpp +++ b/hurricane/src/hurricane/Cell.cpp @@ -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(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( 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(this); + + uniquify = UniquifyRelation::get( this ); + return dynamic_cast( 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(*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 toUniquify; + set 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() + , _dboLocator (NULL) + { + UniquifyRelation* uniquify = UniquifyRelation::get( cell ); + if (uniquify) { + _dboLocator = uniquify->getSlaveOwners().getLocator(); + } + } + + + Locator* Cell::ClonedSet::Locator::getClone () const + { return new Locator(*this); } + + + Cell* Cell::ClonedSet::Locator::getElement () const + { return (_dboLocator and _dboLocator->isValid()) + ? dynamic_cast(_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::ClonedSet::getClone () const + { return new ClonedSet(*this); } + + + Locator* 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 // **************************************************************************************************** diff --git a/hurricane/src/hurricane/CellCollections.cpp b/hurricane/src/hurricane/CellCollections.cpp index e3e5e1d2..576141d7 100644 --- a/hurricane/src/hurricane/CellCollections.cpp +++ b/hurricane/src/hurricane/CellCollections.cpp @@ -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 // ********************************************************** { diff --git a/hurricane/src/hurricane/Instance.cpp b/hurricane/src/hurricane/Instance.cpp index b572d8fe..27aab002 100644 --- a/hurricane/src/hurricane/Instance.cpp +++ b/hurricane/src/hurricane/Instance.cpp @@ -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 . // **************************************************************************************************** +#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() // ************************* { diff --git a/hurricane/src/hurricane/Net.cpp b/hurricane/src/hurricane/Net.cpp index 04a4f87a..afa82bfe 100644 --- a/hurricane/src/hurricane/Net.cpp +++ b/hurricane/src/hurricane/Net.cpp @@ -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 ); diff --git a/hurricane/src/hurricane/NetAlias.cpp b/hurricane/src/hurricane/NetAlias.cpp index 4accc53b..6e3c7453 100644 --- a/hurricane/src/hurricane/NetAlias.cpp +++ b/hurricane/src/hurricane/NetAlias.cpp @@ -163,10 +163,10 @@ namespace Hurricane { Net* NetMainName::getNet () const { return (Net*)((ptrdiff_t)this - _offset); } string NetMainName::_getString () const { return ""; } + // ------------------------------------------------------------------- // 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() + , _hook (net->getMainName()->getNext()) + { } + + + Locator* 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* AliasList::getClone () const + { return new AliasList(*this); } + + + Locator* AliasList::getLocator () const + { return new Locator(_net); } + + + string AliasList::_getString () const + { + string s = "<" + _TName("NetAliasHook") + " " + + getString(_net->getName()) + + ">"; + return s; + } + + } // Hurricane namespace. diff --git a/hurricane/src/hurricane/Relation.cpp b/hurricane/src/hurricane/Relation.cpp index 1d03181b..3196de87 100644 --- a/hurricane/src/hurricane/Relation.cpp +++ b/hurricane/src/hurricane/Relation.cpp @@ -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. // diff --git a/hurricane/src/hurricane/hurricane/Cell.h b/hurricane/src/hurricane/hurricane/Cell.h index 9c1c2cc2..bd88435d 100644 --- a/hurricane/src/hurricane/hurricane/Cell.h +++ b/hurricane/src/hurricane/hurricane/Cell.h @@ -17,10 +17,12 @@ // not, see . // **************************************************************************************************** -#ifndef HURRICANE_CELL -#define HURRICANE_CELL +#ifndef HURRICANE_CELL_H +#define HURRICANE_CELL_H +#include #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 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 { + public: + // Sub-Class: Locator. + class Locator : public Hurricane::Locator { + public: + Locator ( const Cell* ); + inline Locator ( const Locator& ); + virtual Cell* getElement () const; + virtual Hurricane::Locator* getClone () const; + virtual bool isValid () const; + virtual void progress (); + virtual string _getString () const; + protected: + Hurricane::Locator* _dboLocator; + }; + + public: + inline ClonedSet ( const Cell* cell ); + inline ClonedSet ( const ClonedSet& ); + virtual Hurricane::Collection* getClone () const; + virtual Hurricane::Locator* getLocator () const; + virtual string _getString () const; + protected: + const Cell* _cell; + }; + class InstanceMap : public IntrusiveMap { // **************************************************** @@ -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::max()) const; + public: Occurrences getOccurrencesUnder(const Box& area, unsigned searchDepth = std::numeric_limits::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::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() + , _dboLocator(other._dboLocator) +{ } + +inline Cell::ClonedSet::ClonedSet ( const Cell* cell ) + : Hurricane::Collection() + , _cell(cell) +{ } + +inline Cell::ClonedSet::ClonedSet ( const ClonedSet& other ) + : Hurricane::Collection() + , _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 // **************************************************************************************************** diff --git a/hurricane/src/hurricane/hurricane/Instance.h b/hurricane/src/hurricane/hurricane/Instance.h index 50357e9a..adf2146f 100644 --- a/hurricane/src/hurricane/hurricane/Instance.h +++ b/hurricane/src/hurricane/hurricane/Instance.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 . // **************************************************************************************************** -#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 // ****** diff --git a/hurricane/src/hurricane/hurricane/Net.h b/hurricane/src/hurricane/hurricane/Net.h index c6fd2ce3..2b4e9781 100644 --- a/hurricane/src/hurricane/hurricane/Net.h +++ b/hurricane/src/hurricane/hurricane/Net.h @@ -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 // ****** diff --git a/hurricane/src/hurricane/hurricane/NetAlias.h b/hurricane/src/hurricane/hurricane/NetAlias.h index 0924ccf7..655239d8 100644 --- a/hurricane/src/hurricane/hurricane/NetAlias.h +++ b/hurricane/src/hurricane/hurricane/NetAlias.h @@ -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 AliasNameSet; + typedef std::set AliasNameSet; + + +// ------------------------------------------------------------------- +// Class : "Hurricane::AliasList" (Collection). + + typedef GenericCollection Aliases; + typedef GenericLocator AliasesLocator; + typedef GenericFilter AliasesFilter; + + + class AliasList : public Collection { + public: + // Sub-Class: Locator. + class Locator : public Hurricane::Locator { + public: + Locator ( const Net* ); + inline Locator ( const Locator& ); + virtual NetAliasHook* getElement () const; + virtual Hurricane::Locator* 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* getClone () const; + virtual Hurricane::Locator* getLocator () const; + virtual string _getString () const; + protected: + const Net* _net; + }; + + + inline AliasList::Locator::Locator ( const Locator& other ) + : Hurricane::Locator() + , _hook(other._hook) + { } + + inline AliasList::AliasList ( const Net* net ) + : Hurricane::Collection() + , _net(net) + { } + + inline AliasList::AliasList ( const AliasList& other ) + : Hurricane::Collection() + , _net(other._net) + { } } // Namespace Hurricane. diff --git a/hurricane/src/hurricane/hurricane/Relation.h b/hurricane/src/hurricane/hurricane/Relation.h index 7cefd0ae..0eb9d246 100644 --- a/hurricane/src/hurricane/hurricane/Relation.h +++ b/hurricane/src/hurricane/hurricane/Relation.h @@ -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 . // **************************************************************************************************** -#ifndef HURRICANE_RELATION -#define HURRICANE_RELATION +#ifndef HURRICANE_RELATION_H +#define HURRICANE_RELATION_H #include "hurricane/Property.h" diff --git a/hurricane/src/isobar/PyCell.cpp b/hurricane/src/isobar/PyCell.cpp index 993c7c51..89710f17 100644 --- a/hurricane/src/isobar/PyCell.cpp +++ b/hurricane/src/isobar/PyCell.cpp @@ -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 ." } + , { "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 */ diff --git a/hurricane/src/isobar/PyInstance.cpp b/hurricane/src/isobar/PyInstance.cpp index 6bb3113b..79957557 100644 --- a/hurricane/src/isobar/PyInstance.cpp +++ b/hurricane/src/isobar/PyInstance.cpp @@ -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. diff --git a/hurricane/src/isobar/PyNet.cpp b/hurricane/src/isobar/PyNet.cpp index 75323207..ad84e4fe 100644 --- a/hurricane/src/isobar/PyNet.cpp +++ b/hurricane/src/isobar/PyNet.cpp @@ -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 to the net 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 */ }; diff --git a/katabatic/src/GCell.cpp b/katabatic/src/GCell.cpp index 8b5cd1cc..2be34245 100644 --- a/katabatic/src/GCell.cpp +++ b/katabatic/src/GCell.cpp @@ -382,6 +382,8 @@ namespace Katabatic { delete [] _blockages; delete [] _densities; delete [] _feedthroughs; + delete [] _fragmentations; + delete [] _globalsCount; //delete [] _saturateDensities; _allocateds--; diff --git a/kite/src/KiteEngine.cpp b/kite/src/KiteEngine.cpp index 95360368..b31325ff 100644 --- a/kite/src/KiteEngine.cpp +++ b/kite/src/KiteEngine.cpp @@ -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 ( getCell(), "Segs" , routeds+unrouteds.size() ); addMeasure( getCell(), "DWL(l)" , totalWireLength , 12 ); addMeasure( getCell(), "fWL(l)" , totalWireLength-routedWireLength , 12 ); diff --git a/unicorn/src/cgt.py b/unicorn/src/cgt.py index 9862475a..3eff1b54 100755 --- a/unicorn/src/cgt.py +++ b/unicorn/src/cgt.py @@ -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'