From 336b0ad015c011a09100401806de949081f530a2 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Wed, 20 Jul 2022 15:14:38 +0200 Subject: [PATCH] First step in normalizing/rewriting Seabreeze. --- Seabreeze/src/CMakeLists.txt | 27 +- Seabreeze/src/Configuration.cpp | 51 ++- Seabreeze/src/Elmore.cpp | 371 ++++++++++++++++++ Seabreeze/src/Node.cpp | 68 +++- Seabreeze/src/PySeabreeze.cpp | 3 +- Seabreeze/src/PySeabreezeEngine.cpp | 19 +- Seabreeze/src/Seabreeze.cpp | 334 ---------------- Seabreeze/src/Seabreeze.py | 113 ------ Seabreeze/src/Seabreeze/Configuration.h | 59 --- Seabreeze/src/Seabreeze/Node.h | 23 -- Seabreeze/src/Seabreeze/Seabreeze.h | 118 ------ Seabreeze/src/Seabreeze/SeabreezeEngine.h | 71 ---- Seabreeze/src/Seabreeze/Tree.h | 34 -- Seabreeze/src/SeabreezeEngine.cpp | 90 +++-- Seabreeze/src/Tree.cpp | 284 +++++++------- Seabreeze/src/seabreeze/Configuration.h | 62 +++ Seabreeze/src/seabreeze/Elmore.h | 131 +++++++ Seabreeze/src/seabreeze/Node.h | 77 ++++ .../PySeabreezeEngine.h | 2 +- Seabreeze/src/seabreeze/SeabreezeEngine.h | 94 +++++ Seabreeze/src/seabreeze/Tree.h | 61 +++ 21 files changed, 1104 insertions(+), 988 deletions(-) create mode 100644 Seabreeze/src/Elmore.cpp delete mode 100644 Seabreeze/src/Seabreeze.cpp delete mode 100755 Seabreeze/src/Seabreeze.py delete mode 100644 Seabreeze/src/Seabreeze/Configuration.h delete mode 100644 Seabreeze/src/Seabreeze/Node.h delete mode 100644 Seabreeze/src/Seabreeze/Seabreeze.h delete mode 100644 Seabreeze/src/Seabreeze/SeabreezeEngine.h delete mode 100644 Seabreeze/src/Seabreeze/Tree.h create mode 100644 Seabreeze/src/seabreeze/Configuration.h create mode 100644 Seabreeze/src/seabreeze/Elmore.h create mode 100644 Seabreeze/src/seabreeze/Node.h rename Seabreeze/src/{Seabreeze => seabreeze}/PySeabreezeEngine.h (96%) create mode 100644 Seabreeze/src/seabreeze/SeabreezeEngine.h create mode 100644 Seabreeze/src/seabreeze/Tree.h diff --git a/Seabreeze/src/CMakeLists.txt b/Seabreeze/src/CMakeLists.txt index 68088db0..e75357dc 100644 --- a/Seabreeze/src/CMakeLists.txt +++ b/Seabreeze/src/CMakeLists.txt @@ -9,25 +9,25 @@ ${Boost_INCLUDE_DIRS} ${Python_INCLUDE_DIRS} ) - set( includes Seabreeze/SeabreezeEngine.h - #Seabreeze/GraphicSeabreezeEngine.h + set( includes seabreeze/SeabreezeEngine.h + #seabreeze/GraphicSeabreezeEngine.h ) - set( pyIncludes Seabreeze/PySeabreezeEngine.h - # Seabreeze/PyGraphicSeabreezeEngine.h + set( pyIncludes seabreeze/PySeabreezeEngine.h + #seabreeze/PyGraphicSeabreezeEngine.h ) - #set( mocIncludes Seabreeze/GraphicSeabreezeEngine.h ) - set( cpps SeabreezeEngine.cpp - Seabreeze.cpp + #set( mocIncludes seabreeze/GraphicSeabreezeEngine.h ) + set( cpps Configuration.cpp Node.cpp Tree.cpp - Configuration.cpp - #GraphicSeabreezeEngine.cpp + Elmore.cpp + SeabreezeEngine.cpp + #GraphicSeabreezeEngine.cpp ) set( pyCpps PySeabreeze.cpp PySeabreezeEngine.cpp - # PyGraphicSeabreezeEngine.cpp + #PyGraphicSeabreezeEngine.cpp ) - #qtX_wrap_cpp( mocCpps ${mocIncludes} ) + #qtX_wrap_cpp( mocCpps ${mocIncludes} ) set( depLibs ${CORIOLIS_PYTHON_LIBRARIES} ${CORIOLIS_LIBRARIES} @@ -57,12 +57,11 @@ "Do_not_generate_C_library" Seabreeze "Seabreeze;${depLibs}" - include/coriolis2/Seabreeze + include/coriolis2/seabreeze ) install( TARGETS Seabreeze DESTINATION lib${LIB_SUFFIX} ) - #install( PROGRAMS Seabreeze.py DESTINATION bin RENAME Seabreeze ) install( FILES ${includes} - ${mocIncludes} DESTINATION include/coriolis2/Seabreeze ) + ${mocIncludes} DESTINATION include/coriolis2/seabreeze ) diff --git a/Seabreeze/src/Configuration.cpp b/Seabreeze/src/Configuration.cpp index 39f6ac57..51165753 100644 --- a/Seabreeze/src/Configuration.cpp +++ b/Seabreeze/src/Configuration.cpp @@ -1,3 +1,19 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) SU 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | S e a b r e e z e - Timing Analysis | +// | | +// | Author : Vu Hoang Anh PHAM | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./Configuration.cpp" | +// +-----------------------------------------------------------------+ + + #include #include #include "hurricane/configuration/Configuration.h" @@ -11,7 +27,8 @@ #include "hurricane/Segment.h" #include "hurricane/Cell.h" #include "crlcore/Utilities.h" -#include "Seabreeze/Configuration.h" +#include "seabreeze/Configuration.h" + namespace Seabreeze { @@ -30,6 +47,7 @@ namespace Seabreeze { using Hurricane::Layer; using Hurricane::DbU; + //------------------------------------------------------------------------ // Class : "Seabreeze::Configuration" @@ -39,45 +57,38 @@ namespace Seabreeze { , _Csm (1) {} + Configuration::~Configuration () {} + Configuration::Configuration ( const Configuration& other ) : _Rct (other._Rct) , _Rsm (other._Rsm) , _Csm (other._Csm) {} + Configuration* Configuration::clone () const - { return new Configuration(*this); } + { return new Configuration( *this ); } - double Configuration::getRct () - { - return _Rct; - } - - double Configuration::getRsm () - { - return _Rsm; - } - - double Configuration::getCsm () - { - return _Csm; - } + /* Record* Configuration::_getRecord () const { } + string Configuration::_getString () const { } */ + + string Configuration::_getTypeName () const - { - return "Configuration"; - } -} + { return "Configuration"; } + + +} // Seabreeze namespace. diff --git a/Seabreeze/src/Elmore.cpp b/Seabreeze/src/Elmore.cpp new file mode 100644 index 00000000..7dd85659 --- /dev/null +++ b/Seabreeze/src/Elmore.cpp @@ -0,0 +1,371 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) SU 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | S e a b r e e z e - Timing Analysis | +// | | +// | Author : Vu Hoang Anh PHAM | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./Elmore.cpp" | +// +-----------------------------------------------------------------+ + +#include "hurricane/Net.h" +#include "hurricane/Segment.h" +#include "hurricane/DebugSession.h" +#include "hurricane/Error.h" +#include "seabreeze/Elmore.h" +#include "seabreeze/SeabreezeEngine.h" + +namespace Seabreeze { + + using namespace std; + using Hurricane::Error; + using Hurricane::DBo; + using Hurricane::DbU; + using Hurricane::Net; + using Hurricane::Cell; + using Hurricane::Instance; + using Hurricane::Property; + using Hurricane::PrivateProperty; + using Hurricane::Component; + using Hurricane::Segment; + using Hurricane::DebugSession; + + +//--------------------------------------------------------- +// Class : "Elmore" + + Elmore::Elmore ( Net* net ) + : _seabreeze(nullptr) + , _contacts () + , _checker () + , _tree (new Tree()) + {} + + + Elmore::~Elmore () + { + delete _tree; + } + + + const Configuration* Elmore::getConfiguration () const + { return _seabreeze->getConfiguration(); } + + + void Elmore::contFromNet ( Net* net ) + { + for ( RoutingPad* rp : net->getRoutingPads() ) { + for ( Component* component : rp->getSlaveComponents() ) { + Contact* contact = dynamic_cast( component ); + if (not contact) continue; + _contacts.insert( contact ); + } + } + } + + + void Elmore::buildTree ( RoutingPad* rp ) + { + if (not rp) { + cerr << Error( "Elmore::buildTree(): NULL RoutingPad, aborting." ) << endl; + return; + } + + Contact* rootContact = nullptr; + for ( Component* component : rp->getSlaveComponents() ) { + Contact* contact = dynamic_cast(component); + if (contact) { + rootContact = contact; + break; + } + } + if (not rootContact) { + cerr << Error( "Elmore::buildTree(): No Contact anchored on %s." + , getString(rp).c_str() ) << endl; + return; + } + + cdebug_log(199,1) << "Elmore::buildTree()" << endl; + cdebug_log(199,0) << "Root contact " << rootContact << endl; + + _checker.insert( rootContact ); + Node* rootNode = new Node( nullptr, rootContact ); + double R = 0; + double C = 0; + setRC( &R, &C, rootContact, nullptr ); + rootNode->setR( R ); + rootNode->setC( (C == 0.0) ? 0.0 : 1/C ); + + Segment* segment = nullptr; + size_t count = 0; + for ( Component* component : rootContact->getSlaveComponents() ) { + segment = dynamic_cast( component ); + if (not segment) continue; + ++count; + } + if (count != 1) { + cerr << Error( "Elmore::buildTree(): Terminal contact has more than one segment (%d), aborting.\n" + " (on %s)" + , count + , getString(rootContact).c_str() + ) << endl; + cdebug_tabw(199,-1); + return; + } + + buildFromNode( rootNode, segment ); + cdebug_log(199,0) << "Elmore::buildTree() - Finished" << endl; + cdebug_tabw(199,-1); + + _tree->print( cerr ); + } + + + void Elmore::buildFromNode ( Node* rootNode, Segment* toSegment ) + { + if (not rootNode->contact()) { + cerr << Error( "Elmore::buildFromNode(): rootNode has no contact, aborting." ) << endl; + return; + } + _tree->add_node( rootNode ); + + cdebug_log(199,1) << "Elmore::buildFromNode()" << endl; + cdebug_log(199,0) << "rootNode->_contact=" << rootNode->contact() << endl; + cdebug_log(199,0) << "toSegment=" << toSegment << endl; + + Contact* opposite = dynamic_cast( toSegment->getOppositeAnchor( rootNode->contact()) ); + if (not opposite or (rootNode->parent() and (opposite == rootNode->parent()->contact())) ) { + cdebug_tabw(199,-1); + return; + } + cdebug_log(199,0) << "opposite=" << opposite << endl; + + double Rb = 0; + double Cb = 0; + opposite = buildBranch( &Rb, &Cb, opposite ); + if (not opposite) { + cerr << Error( "Elmore::buildFromNode(): Branch end up on NULL Contact, pruned." ) << endl; + cdebug_tabw(199,-1); + return; + } + cdebug_log(199,0) << "Reached fork " << opposite << endl; + + Node* node = new Node( rootNode, opposite); + node->setR( Rb ); + node->setC( (Cb == 0.0) ? 0.0 : 1/Cb ); + cdebug_log(199,0) << "R=" << Rb << " C=" << Cb << endl; + + int count = 0; + for ( Component* component : opposite->getSlaveComponents() ) { + count += (dynamic_cast(component)) ? 1 : 0; + } + cdebug_log(199,0) << "Node's contact has : " << count << " segments" << endl; + + if (count == 1) { + _tree->add_node( node ); + } else if (count > 2) { + for ( Component* component : opposite->getSlaveComponents() ) { + Segment* segment = dynamic_cast( component ); + if (not segment) continue; + cdebug_log(199,0) << "| " << segment << endl; + + Contact* target = dynamic_cast( segment->getOppositeAnchor(opposite) ); + if (not target) { + cerr << Error( "Elmore::buildFromNode(): Segment missing opposite anchor. pruned." ) << endl; + continue; + } + cdebug_log(199,0) << "target=" << target << endl; + + if (not _checker.count(target)) { + buildFromNode( node, segment); + } + } + } + cdebug_tabw(199,-1); + } + + + Contact* Elmore::buildBranch ( double* R, double* C, Contact* current ) + { + cdebug_log(199,1) << "Elmore::buildBranch()" << endl; + cdebug_log(199,0) << "current=" << current << endl; + + while ( true ) { + _checker.insert( current ); + int count = 0; + Segment* segment = nullptr; + for ( Component* component : current->getSlaveComponents() ) { + segment = dynamic_cast( component ); + if (not segment) continue; + + Contact* opposite = dynamic_cast( segment->getOppositeAnchor(current) ); + if (opposite and (_checker.count(opposite)) != 0) { + setRC( R, C, current, segment ); + cdebug_log(199,0) << "current=" << current << endl; + cdebug_log(199,0) << "segment=" << segment << endl; + cdebug_log(199,0) << "R=" << *R << endl; + cdebug_log(199,0) << "C=" << *C << endl; + } + ++count; + } + if (not count) { + cerr << Error( "Elmore::buildBranch(): Contact seems to be a dead end, pruning.\n" + " (on %s)" + , getString(current).c_str() ) << endl; + cdebug_tabw(199,-1); + return nullptr; + } + else if (count != 2) { + break; + } + + Contact* next = nullptr; + for ( Component* component : current->getSlaveComponents() ) { + segment = dynamic_cast( component ); + if (not segment) continue; + + cdebug_log(199,0) << "| " << segment << endl; + + Contact* opposite = dynamic_cast( segment->getOppositeAnchor(current) ); + cdebug_log(199,0) << "opposite=" << opposite << endl; + if (opposite and (_checker.count(opposite) == 0)) + next = opposite; + } + + if (not next) { + cerr << Error( "Elmore::buildBranch(): Wire loop detected.\n" + " (on %s)" + , getString(current).c_str() ) << endl; + cdebug_tabw(199,-1); + return nullptr; + } + + current = next; + } + + cdebug_tabw(199,-1); + return current; + } + + + void Elmore::setRC ( double* R, double* C, Contact* contact, Segment* segment ) + { + double Rcont = getConfiguration()->getRct(); + //double Hcont = DbU::toPhysical( contact->getHeight(), DbU::UnitPower::Nano ); + //double Wcont = DbU::toPhysical( contact->getWidth (), DbU::UnitPower::Nano ); + double Wcont = DbU::toLambda( contact->getWidth () ); + double Acont = Wcont * Wcont; + *R += Rcont * Acont; + + if (not segment) { + *C = 0; + } else { + double Rseg = getConfiguration()->getRsm(); + double Cseg = getConfiguration()->getCsm(); + //double Lseg = DbU::toPhysical( segment->getLength(), DbU::UnitPower::Nano ); + //double Wseg = DbU::toPhysical( segment->getWidth (), DbU::UnitPower::Nano ); + double Lseg = DbU::toLambda( segment->getLength() ); + double Wseg = DbU::toLambda( segment->getWidth () ); + double Aseg = Lseg * Wseg; + cdebug_log(199,0) << "Elmore::setRC() on " << segment << endl; + cdebug_log(199,0) << " Lseg=" << Lseg << " Wseg=" << Wseg << " Aseg=" << Aseg << endl; + *R += Rseg * Aseg; + *C += (Aseg) ? 1/(Cseg*Aseg) : 0.0; + } + } + + + void Elmore::clearTree () + { + _tree->clear(); + _checker.clear(); + } + + + double Elmore::delayElmore ( RoutingPad* rp ) + { return _tree->Delay_Elmore( rp ); } + + + void Elmore::toTree ( ostream& os ) const + { _tree->print( os ); } + + +//--------------------------------------------------------- +// Class : "ElmoreProperty" + + Name ElmoreProperty::_name = "Seabreeze::Elmore"; + + + ElmoreProperty::ElmoreProperty ( Net* net ) + : PrivateProperty() + , _elmore (net) + { + if (net) { + SeabreezeEngine* seabreeze + = dynamic_cast( ToolEngine::get( net->getCell(), "Seabreeze" )); + if (not seabreeze) { + cerr << Error( "ElmoreProperty::ElmoreProperty(): Cannot find SeabreezeEngine on %s." + , getString(net->getCell()).c_str()) << endl; + } + _elmore.setSeabreeze( seabreeze ); + } + } + + + ElmoreProperty* ElmoreProperty::create ( Net* net ) + { + ElmoreProperty* property = new ElmoreProperty( net ); + property->_postCreate(); + return property; + } + + + Name ElmoreProperty::staticGetName () + { return _name; } + + + Name ElmoreProperty::getName () const + { return _name; } + + + string ElmoreProperty::_getTypeName () const + { return "ElmoreProperty"; } + + +//--------------------------------------------------------- +// Class : "ElmoreExtension" + + Elmore* ElmoreExtension::create ( Net* net ) + { + Elmore* elmore = get( net ); + if (not elmore) { + ElmoreProperty* property = new ElmoreProperty( net ); + net->put( property ); + elmore = property->getElmore(); + } + return elmore; + } + + + void ElmoreExtension::destroy ( Net* net ) + { + Property* property = net->getProperty( ElmoreProperty::staticGetName() ); + if (property) net->remove( property ); + } + + + Elmore* ElmoreExtension::get ( Net* net ) + { + Elmore* elmore = nullptr; + Property* property = net->getProperty( ElmoreProperty::staticGetName() ); + if (property) elmore = static_cast( property )->getElmore(); + return elmore; + } + + +} // Seabreeze namespace. diff --git a/Seabreeze/src/Node.cpp b/Seabreeze/src/Node.cpp index a80b4f97..3e99caae 100644 --- a/Seabreeze/src/Node.cpp +++ b/Seabreeze/src/Node.cpp @@ -1,25 +1,53 @@ -#include "Seabreeze/Node.h" +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) SU 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | S e a b r e e z e - Timing Analysis | +// | | +// | Author : Vu Hoang Anh PHAM | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./Node.cpp" | +// +-----------------------------------------------------------------+ + #include +#include "seabreeze/Node.h" -Node::Node () - : R(0) - , C(0) - , label(-1) - , ap(0) -{ _contact = nullptr; } +namespace Seabreeze { -Node::Node ( Node* p, Contact* ct ) - : R(0) - , C(0) - , Np(p) - , _contact(ct) - , label(-1) - , ap(0) -{ - if( p != nullptr) - (p->Ne).push_back(this); -} -Node::~Node () -{} + Node::Node () + : _R (0.0) + , _Rt (0.0) + , _C (0.0) + , _parent (nullptr) + , _childs () + , _contact(nullptr) + , _label (-1) + , _ap (0) + { } + + + Node::Node ( Node* parent, Contact* contact ) + : _R (0.0) + , _Rt (0.0) + , _C (0.0) + , _parent (parent) + , _childs () + , _contact(contact) + , _label (-1) + , _ap (0) + { + if (parent) parent->addChild( this ); + } + + + Node::~Node () + { } + + +} // Seabreeze namespace. diff --git a/Seabreeze/src/PySeabreeze.cpp b/Seabreeze/src/PySeabreeze.cpp index 51b15fd4..424fbaf5 100644 --- a/Seabreeze/src/PySeabreeze.cpp +++ b/Seabreeze/src/PySeabreeze.cpp @@ -17,8 +17,7 @@ #include "hurricane/isobar/PyHurricane.h" #include "hurricane/isobar/PyCell.h" -#include "Seabreeze/PySeabreezeEngine.h" -//#include "Seabreeze/PyGraphicSeabreezeEngine.h" +#include "seabreeze/PySeabreezeEngine.h" namespace Seabreeze { diff --git a/Seabreeze/src/PySeabreezeEngine.cpp b/Seabreeze/src/PySeabreezeEngine.cpp index d08ad89e..e18f48ac 100644 --- a/Seabreeze/src/PySeabreezeEngine.cpp +++ b/Seabreeze/src/PySeabreezeEngine.cpp @@ -10,18 +10,18 @@ // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | -// | C++ Module : "./PySeabreezeEngine.cpp" | +// | C++ Module : "./PySeabreezeEngine.cpp" | // +-----------------------------------------------------------------+ +#include #include "hurricane/isobar/PyCell.h" #include "hurricane/viewer/PyCellViewer.h" #include "hurricane/isobar/PyNet.h" #include "hurricane/viewer/ExceptionWidget.h" #include "hurricane/Cell.h" #include "crlcore/Utilities.h" -#include "Seabreeze/PySeabreezeEngine.h" -#include +#include "seabreeze/PySeabreezeEngine.h" # undef ACCESS_OBJECT # undef ACCESS_CLASS @@ -153,15 +153,14 @@ extern "C" { } */ - static PyObject* PySeabreezeEngine_runTool ( PySeabreezeEngine* self, PyObject* args ) + static PyObject* PySeabreezeEngine_buildElmore ( PySeabreezeEngine* self, PyObject* args ) { - cdebug_log(40,0) << "PySeabreezeEngine_runTool()" << endl; - + cdebug_log(40,0) << "PySeabreezeEngine_buildElmore()" << endl; HTRY PyObject* arg0 = NULL; - METHOD_HEAD("SeabreezeEngine.runTool()") - if (not ParseOneArg("Seabreeze.runTool()", args, NET_ARG, &arg0)) return NULL; - seabreeze->runTool(PYNET_O(arg0)); + METHOD_HEAD("SeabreezeEngine.buildElmore()") + if (not ParseOneArg("Seabreeze.buildElmore()", args, NET_ARG, &arg0)) return NULL; + seabreeze->buildElmore(PYNET_O(arg0)); HCATCH Py_RETURN_NONE; @@ -183,7 +182,7 @@ extern "C" { , "Associate a Viewer to this SeabreezeEngine." } //, { "runDemoPart1" , (PyCFunction)PySeabreezeEngine_runDemoPart1 , METH_NOARGS // , "Run the first part of the demo." } - , { "runTool" , (PyCFunction)PySeabreezeEngine_runTool , METH_VARARGS + , { "buildElmore" , (PyCFunction)PySeabreezeEngine_buildElmore , METH_VARARGS , "Run the Seabreeze tool." } , { "destroy" , (PyCFunction)PySeabreezeEngine_destroy , METH_NOARGS , "Destroy the associated hurricane object. The python object remains." } diff --git a/Seabreeze/src/Seabreeze.cpp b/Seabreeze/src/Seabreeze.cpp deleted file mode 100644 index 3c67f3ce..00000000 --- a/Seabreeze/src/Seabreeze.cpp +++ /dev/null @@ -1,334 +0,0 @@ -#include "Seabreeze/Seabreeze.h" -#include "hurricane/Net.h" -#include "hurricane/Segment.h" -#include "hurricane/DebugSession.h" - -namespace Seabreeze { - - using namespace std; - using Hurricane::DBo; - using Hurricane::DbU; - using Hurricane::Net; - using Hurricane::Cell; - using Hurricane::Instance; - using Hurricane::PrivateProperty; - using Hurricane::Component; - using Hurricane::Segment; - using Hurricane::DebugSession; - -//--------------------------------------------------------- -// Class : "Elmore" - - Elmore::Elmore ( Net* net ) - : _config (new Configuration()) - , _conts () - , checker () - , _tree (new Tree()) - {} - - Elmore::~Elmore () - { - delete _tree; - } - - void Elmore::contFromNet ( Net* net ) { - for ( RoutingPad* rp : net->getRoutingPads() ) { - for ( Component* comp : rp->getSlaveComponents() ) { - Contact* ct = dynamic_cast(comp); - if ( not ct ) continue; - _conts.insert(ct); - } - } - } - - void Elmore::buildTree ( RoutingPad* rp ) - { - if ( rp == nullptr ) { - cerr << "Input RoutingPad is NULL. Please select a RoutingPad !" << endl; - cerr << "Cannot build tree" << endl; - return; - } - - Contact* ct = nullptr; - for ( Component* c : rp->getSlaveComponents() ) { - Contact* cont = dynamic_cast(c); - - if ( cont ) { - ct = cont; - break; - } - } - if ( ct == nullptr ) { - cerr << "No contact found" << endl; - cerr << "Cannot build tree" << endl; - return; - } - - cerr << "Root contact : " << ct->getId() << endl; - cerr << "Start building tree..." << endl; - - checker.insert(ct); - Node* s = new Node(nullptr, ct); -//--------------------------------------------------------- - double R = 0; - double C = 0; - Set_RC(&R, &C, ct, nullptr); - s->R = R; - if ( C == 0 ) - s->C = 0; - else - s->C = 1/C; -//--------------------------------------------------------- - Segment* seg = nullptr; - int c = 0; - for ( Component* comp : ct->getSlaveComponents() ) { - seg = dynamic_cast(comp); - if ( not seg ) continue; - c++; - } - if ( c != 1 ) { - cerr << "Not begin with a RoutingPad ? Something doesn't seem right : " << c << " linked segments" << endl; - cerr << "Tree build failed" << endl; - return; - } - build_from_Node(s, seg); - cerr << endl << "Finished building tree !" << endl << endl; - _tree->print(cerr); - } - - void Elmore::build_from_Node ( Node* s, Segment* seg ) - { - if ( s->_contact == nullptr ) { - cerr << "No contact found" << s->_contact << endl; - return; - } - _tree->add_node(s); - - cdebug_log(199,0) << endl - << endl - << "Build from contact : " << s->_contact->getId() << endl - << "With segment : " << seg->getId() << endl; - - Contact* ccont = dynamic_cast(seg->getOppositeAnchor(s->_contact)); - if ( not ccont || (s->Np && ccont == (s->Np)->_contact) ) - return; - - cdebug_log(199,0) << "Target contact : " << ccont->getId() << endl; -//----------------------------------------------------------------------- - double Rb = 0; - double Cb = 0; -//----------------------------------------------------------------------- - ccont = build_branch(&Rb, &Cb, ccont); - - cdebug_log(199, 0) << "Found a node : " << ccont->getId() << endl; - - if ( not ccont ) { - cerr << "This branch leads to a NULL contact ?" << endl; - return; - } - - Node* node = new Node(s, ccont); -//----------------------------------------------------------------------- - node->R = Rb; - if ( Cb == 0 ) - node->C = 0; - else - node->C = 1/Cb; - - cdebug_log(199,0) << "R = " << Rb << "; C = " << Cb << endl; -//----------------------------------------------------------------------- - int count = 0; - for ( Component* comp : ccont->getSlaveComponents() ) { - count += (dynamic_cast(comp)) ? 1 : 0; - } - - cdebug_log(199,0) << "This node's contact has : " << count << " segments" << endl; - - if ( count == 1 ){ - _tree->add_node(node); - } - else if ( count > 2 ) { - for ( Component* comp : ccont->getSlaveComponents() ) { - Segment* segmt = dynamic_cast(comp); - if ( not segmt ) - continue; - - cdebug_log(199,1) << "Segment : " << segmt->getId() << endl; - cdebug_tabw(199,-1); - - Contact* target = dynamic_cast(segmt->getOppositeAnchor(ccont)); - if ( not target ) { - cerr << "Wait... How can this happen ?" << endl; - continue; - } - - cdebug_log(199,0) << "Target is : " << target->getId() << endl; - cdebug_tabw(199,-1); - - if ( checker.count(target) == 0 ){ - build_from_Node(node, segmt); - cdebug_log(199,0) << endl; - } - } - } - } - - Contact* Elmore::build_branch ( double* R, double* C, Contact* ct ) - { - Contact* tmp = ct; - - cdebug_log(199,1) << endl << "Start building branch with contact : " << ct->getId() << endl; - - int count; - do { - checker.insert(tmp); - count = 0; - Segment* sm = nullptr; - for ( Component* cp : tmp->getSlaveComponents() ) { - sm = dynamic_cast(cp); - if ( not sm ) - continue; - - Contact* tar = dynamic_cast(sm->getOppositeAnchor(tmp)); - if ( tar && checker.count(tar) != 0 ) { - Set_RC(R, C, tmp, sm); - cdebug_log(199,0) << "RC from build_branch :" << endl; - cdebug_log(199,0) << "tmp = " << tmp->getId() << "; sm = " << sm->getId() << "; R = " << *R << "; C = " << *C << endl; - } - count += 1; - } - if ( count == 0 ) { - cerr << "Something is not right here : Contact " << tmp << " is isolated ?" << endl; - break; - } - else if ( count != 2 ) { - break; - } - else { - Contact* cct = nullptr; - for ( Component* cp : tmp->getSlaveComponents() ) { - sm = dynamic_cast(cp); - if ( not sm ) - continue; - - cdebug_log(199,1) << "Sm : " << sm->getId() << endl; - cdebug_tabw(199,-1); - - Contact* tar = dynamic_cast(sm->getOppositeAnchor(tmp)); - - cdebug_log(199,0) << "tar : " << tar->getId() << endl << endl; - - if ( tar && checker.count(tar) == 0 ) - cct = tar; - } - - cdebug_tabw(199,-1); - cdebug_log(199,0) << "cct : " << cct->getId() << endl; - - if ( not cct || checker.count(cct) != 0 ) { - cerr << "This branch leads to no where ?" << endl; - tmp = nullptr; - break; - } - else - tmp = cct; - } - } while ( count == 2 ); - - cdebug_tabw(199,-1); - cdebug_log(199,0) << "Branch done !" << endl; - - return tmp; - } - - void Elmore::Set_RC ( double* R, double* C, Contact* ct, Segment* sm ) { - double Rct = getConfig()->getRct(); - //double h_ct = DbU::toPhysical(ct->getHeight(), DbU::UnitPower::Nano); - double w_ct = DbU::toPhysical(ct->getWidth(), DbU::UnitPower::Nano); - - double S_ct = w_ct*w_ct; - (*R) += Rct*S_ct; - - if ( sm == nullptr ) { - *C = 0; - } - else { - double Rsm = getConfig()->getRsm(); - double Csm = getConfig()->getCsm(); - double l_sm = DbU::toPhysical(sm->getLength(), DbU::UnitPower::Nano); - double w_sm = DbU::toPhysical(sm->getWidth(), DbU::UnitPower::Nano); - double S_sm = l_sm*w_sm; -//--------------------------------------------------------------------------------------- - cdebug_log(199,0) << "sm = " << sm->getId() << "; l_sm = " << l_sm << "; w_sm = " << w_sm << "; S_sm = " << S_sm << endl; -//--------------------------------------------------------------------------------------- - (*R) += Rsm*S_sm; - if ( S_sm == 0 ) - (*C) += 0; - else - (*C) += 1/(Csm*S_sm); - } - } - - void Elmore::clearTree () - { - _tree->clear(); - checker.clear(); - } - - Tree* Elmore::getTree () - { - return _tree; - } - - double Elmore::delayElmore ( RoutingPad* rp ) - { - return _tree->Delay_Elmore(rp); - } - - void Elmore::toTREE ( ostream& out ) const - { - _tree->print( out ); - } - -//--------------------------------------------------------- -// Class : "ElmoreProperty" - - Name ElmoreProperty::_name = "Seabreeze::Elmore"; - - ElmoreProperty* ElmoreProperty::create ( Net* net ) - { - ElmoreProperty* property = new ElmoreProperty(net); - //ElmoreProperty* property(net); - - property->_postCreate(); - return property; - } - - Name ElmoreProperty::getName () const - { - return _name; - } - - string ElmoreProperty::_getTypeName () const - { - return "ElmoreProperty"; - } - -//--------------------------------------------------------- -// Class : "ElmoreExtension" - - Elmore* ElmoreExtension::create ( Net* net ) - { - return ElmoreProperty::create(net)->getElmore(); - } - - void ElmoreExtension::destroyAll () - { - - } - - void ElmoreExtension::destroy ( Net* net ) - { - - } -} diff --git a/Seabreeze/src/Seabreeze.py b/Seabreeze/src/Seabreeze.py deleted file mode 100755 index e00ae35e..00000000 --- a/Seabreeze/src/Seabreeze.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python3 - - -try: - import sys - import os.path - import optparse - import Cfg - import Hurricane - import Viewer - import helpers.io - import CRL - import Unicorn - import Seabreeze -except ImportError, e: - serror = str(e) - if serror.startswith('No module named'): - module = serror.split()[-1] - print( '[ERROR] The "{}" python module or symbol cannot be loaded.'.format(module) ) - print( ' Please check the integrity of the package.' ) - if serror.find('cannot open shared object file'): - library = serror.split(':')[0] - print( '[ERROR] The "{}" shared library cannot be loaded.'.format(library) ) - print( ' Under RHEL 6, you must be under devtoolset-2.' ) - print( ' (scl enable devtoolset-2 bash)' ) - sys.exit(1) -except Exception, e: - print( '[ERROR] A strange exception occurred while loading the basic Coriolis/Python' ) - print( ' modules. Something may be wrong at Python/C API level.\n' ) - print( ' {}'.format(e) ) - sys.exit(2) - - -def setCgtBanner ( banner ): - banner.setName('tutu') - banner.setPurpose('Seabreeze for Users') - return banner - - -def credits (): - s = '' - s += ' Tool Credits\n' - s += ' Hurricane .................... Remy Escassut & Christian Masson\n' - return s - - -if __name__ == '__main__': - try: - usage = str(setCgtBanner(CRL.Banner())) - usage += '\ncgt [options]' - parser = optparse.OptionParser(usage) - parser.add_option( '--no-init' , action='store_true', dest='noInit' , help='Do not load any initialization.') - parser.add_option( '-c', '--cell' , type='string' , dest='cell' , help='The name of the cell to load, without extension.') - parser.add_option( '--acm-sigda-89' , type='string' , dest='acmSigdaName' , help='An ACM/SIGDA 89 bench name to load, without extension.') - parser.add_option( '--blif' , type='string' , dest='blifName' , help='A Blif (Yosys) design name to load, without extension.') - parser.add_option( '--ispd-05' , type='string' , dest='ispd05name' , help='An ISPD 05 bench (placement) name to load, without extension.') - parser.add_option( '-v', '--verbose' , action='store_true', dest='verbose' , help='First level of verbosity.') - parser.add_option( '-V', '--very-verbose' , action='store_true', dest='veryVerbose' , help='Second level of verbosity.') - parser.add_option( '-i', '--info' , action='store_true', dest='info' , help='Display lots of informational messages.') - parser.add_option( '--paranoid' , action='store_true', dest='paranoid' , help='Display everything that *may be* suspicious...') - parser.add_option( '-b', '--bug' , action='store_true', dest='bug' , help='Display bug related messages.') - parser.add_option( '--show-conf' , action='store_true', dest='showConf' , help='Display Kite configuration.') - parser.add_option( '-D', '--core-dump' , action='store_true', dest='coreDump' , help='Enable core-dump when a crash occurs.') - parser.add_option( '-L', '--log-mode' , action='store_true', dest='logMode' , help='Disable ANSI escape sequences in console output.') - (options, args) = parser.parse_args() - args.insert(0, 'tutu') - - flags = 0 - if options.noInit: - flags |= CRL.AllianceFramework.NoPythonInit - - af = CRL.AllianceFramework.create( flags ) - print( af.getEnvironment().getPrint() ) - - Cfg.Configuration.pushDefaultPriority(Cfg.Parameter.Priority.CommandLine) - if options.coreDump: Cfg.getParamBool('misc.catchCore' ).setBool(False) - if options.verbose: Cfg.getParamBool('misc.verboseLevel1').setBool(True) - if options.veryVerbose: Cfg.getParamBool('misc.verboseLevel2').setBool(True) - if options.info: Cfg.getParamBool('misc.info' ).setBool(True) - if options.paranoid: Cfg.getParamBool('misc.paranoid' ).setBool(True) - if options.bug: Cfg.getParamBool('misc.bug' ).setBool(True) - if options.logMode: Cfg.getParamBool('misc.logMode' ).setBool(True) - if options.showConf: Cfg.getParamBool('misc.showConf' ).setBool(True) - Cfg.Configuration.popDefaultPriority() - cell = None - if options.acmSigdaName: - cell = CRL.AcmSigda.load(options.acmSigdaName) - elif options.ispd05name: - cell = CRL.Ispd05.load(options.ispd05name) - elif options.blifName: - cell = CRL.Blif.load(options.blifName) - elif options.cell: - cell = af.getCell(options.cell, CRL.Catalog.State.Views) - - # Run in graphic mode. - ha = Viewer.HApplication.create(args) - Viewer.Graphics.enable() - unicorn = Unicorn.UnicornGui.create() - unicorn.setApplicationName ('tutu') - #unicorn.registerTool (Seabreeze.GraphicSeabreezeEngine.grab()) - unicorn.setLayerVisible ("grid" , False); - unicorn.setLayerVisible ("text.instance" , False); - unicorn.setLayerVisible ("text.component", False); - - setCgtBanner(unicorn.getBanner()) - print( unicorn.getBanner() ) - print( credits() ) - if cell: unicorn.setCell(cell) - unicorn.show() - ha.qtExec() - except Exception, e: - helpers.io.catch( e ) - sys.exit(0) diff --git a/Seabreeze/src/Seabreeze/Configuration.h b/Seabreeze/src/Seabreeze/Configuration.h deleted file mode 100644 index aef8f553..00000000 --- a/Seabreeze/src/Seabreeze/Configuration.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once -#include -#include -#include - -namespace Hurricane { - class Layer; - class Cell; - class Net; - class RoutingPad; - class Contact; - class Segment; -} - -namespace CRL { - class CellGauge; - class RoutingGauge; - class RoutingLayerGauge; -} - -namespace Seabreeze { - - using std::string; - using Hurricane::Record; - using Hurricane::Name; - using Hurricane::Layer; - using Hurricane::DbU; - using Hurricane::RoutingPad; - using Hurricane::Cell; - using Hurricane::Net; - using Hurricane::Contact; - using Hurricane::Segment; - -//------------------------------------------------------------------------ -// Class : "Seabreeze::Configuration" - - class Configuration { - public : - // Constructor & Destructor - virtual Configuration* clone () const; - Configuration (); - Configuration ( const Configuration& ); - ~Configuration (); - // Methods - double getRct (); - double getRsm (); - double getCsm (); - //virtual Record* _getRecord () const; - //virtual string _getString () const; - virtual string _getTypeName () const; - protected : - // Attributes - double _Rct; - double _Rsm; - double _Csm; - private : - Configuration& operator = ( const Configuration& ) = delete; - }; -} diff --git a/Seabreeze/src/Seabreeze/Node.h b/Seabreeze/src/Seabreeze/Node.h deleted file mode 100644 index c4bb0de5..00000000 --- a/Seabreeze/src/Seabreeze/Node.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once // ensures that this header file is only included once - -#include - -#include "hurricane/Contact.h" - -using Hurricane::Contact; - -class Node { - public : - double R; - double Rt; - double C; - Node* Np; - std::vector Ne; - Contact* _contact; - int label; - int ap; - public: - Node (); - Node ( Node* parent, Contact* ct ); - ~Node (); -}; diff --git a/Seabreeze/src/Seabreeze/Seabreeze.h b/Seabreeze/src/Seabreeze/Seabreeze.h deleted file mode 100644 index d6df5a8d..00000000 --- a/Seabreeze/src/Seabreeze/Seabreeze.h +++ /dev/null @@ -1,118 +0,0 @@ -#include -#include -#include - -#include "hurricane/Property.h" -#include "hurricane/RoutingPad.h" -#include "hurricane/Contact.h" -#include "hurricane/Segment.h" -#include "Configuration.h" -#include "Tree.h" - -namespace Hurricane { - class Net; - class Instance; -} - -namespace Seabreeze { - - using namespace std; - using Hurricane::Name; - using Hurricane::DBo; - using Hurricane::Net; - using Hurricane::Cell; - using Hurricane::RoutingPad; - using Hurricane::Contact; - using Hurricane::Instance; - using Hurricane::Segment; - using Hurricane::PrivateProperty; - -//---------------------------------------------------------- -// Class : Seabreeze::Elmore - - class Elmore { - public: - Elmore ( Net* net = NULL ); - ~Elmore (); - void contFromNet ( Net* net ); - void buildTree ( RoutingPad* rp ); - void build_from_Node ( Node* source, Segment* seg ); - Contact* build_branch ( double* R, double* C, Contact* contact ); - void Set_RC ( double* R, double* C, Contact* ct, Segment* sm ); - void clearTree (); - Tree* getTree (); - inline const set& get_conts () const; - inline Configuration* getConfig (); - double delayElmore ( RoutingPad* rp ); - void toTREE ( ostream& ) const; - private: - Configuration* _config; - set _conts; - set checker; - Tree* _tree; - }; - - inline const set& Elmore::get_conts () const - { - return _conts; - } - - inline Configuration* Elmore::getConfig () - { - return _config; - } - -//--------------------------------------------------------- -// Class : Seabreeze::ElmoreProperty - - class ElmoreProperty : public Hurricane::PrivateProperty { - friend class ElmoreExtension; - public: - static Name _name; - public: - static ElmoreProperty* create ( Net* net ); - Name getName () const; - virtual string _getTypeName () const; - inline Elmore* getElmore (); - protected: - // Attribute - Elmore _elmore; - protected: - // Constructor - inline ElmoreProperty ( Net* ); - }; - - inline ElmoreProperty::ElmoreProperty ( Net* n ) - : PrivateProperty() - , _elmore(NULL) - {} - - inline Elmore* ElmoreProperty::getElmore() - { - return &_elmore; - } - -//--------------------------------------------------------- -// Class : Seabreeze::ElmoreExtension - - class ElmoreExtension { - public: - static void destroyAll (); - static Elmore* create ( Net* ); - static inline Tree* getTree ( Elmore* ); - static inline void toTREE ( const Elmore*, std::ostream& ); - static void destroy ( Net* net ); - private: - static Net* Nets; - }; - - inline Tree* ElmoreExtension::getTree ( Elmore* elmore ) - { - return elmore->getTree(); - } - - inline void ElmoreExtension::toTREE ( const Elmore* elmore, std::ostream& out ) - { - elmore->toTREE(out); - } -} // Seabreeze Namespace diff --git a/Seabreeze/src/Seabreeze/SeabreezeEngine.h b/Seabreeze/src/Seabreeze/SeabreezeEngine.h deleted file mode 100644 index 357a4117..00000000 --- a/Seabreeze/src/Seabreeze/SeabreezeEngine.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef SEABREEZE_SEABREEZE_ENGINE_H -#define SEABREEZE_SEABREEZE_ENGINE_H - -#include -#include - -#include "hurricane/Name.h" -#include "hurricane/viewer/CellViewer.h" -#include "hurricane/RoutingPad.h" - -namespace Hurricane { - class Net; - class Cell; -} - -#include "crlcore/ToolEngine.h" -#include "Seabreeze.h" - -namespace Seabreeze { - - using Hurricane::Record; - using Hurricane::Name; - using Hurricane::Net; - using Hurricane::Cell; - using Hurricane::CellViewer; - using Hurricane::RoutingPad; - using CRL::ToolEngine; - -//---------------------------------------------------------- -// Class : "Seabreeze::SeabreezeEngine" - - class SeabreezeEngine : public ToolEngine { - public : - typedef ToolEngine Super; - public : - static const Name& staticGetName (); - static SeabreezeEngine* create ( Cell* ); - static SeabreezeEngine* get ( const Cell* ); - public : - inline CellViewer* getViewer () const; - inline ToolEngine* base (); - virtual const Name& getName () const; - inline void setViewer ( CellViewer* ); - virtual Record* _getRecord () const; - virtual std::string _getString () const; - virtual std::string _getTypeName () const; - virtual void runTool ( Net* net ); - protected : - SeabreezeEngine ( Cell* ); - virtual ~SeabreezeEngine (); - virtual void _postCreate (); - virtual void _preDestroy (); - private : - SeabreezeEngine ( const SeabreezeEngine& ); - SeabreezeEngine& operator= ( const SeabreezeEngine& ); - private : - // Attributes. - static Name _toolName; - protected : - CellViewer* _viewer; - }; - -// Inline Functions. - inline CellViewer* SeabreezeEngine::getViewer () const { return _viewer; } - inline ToolEngine* SeabreezeEngine::base () { return static_cast(this); } - inline void SeabreezeEngine::setViewer ( CellViewer* viewer ) { _viewer = viewer; } -} // Seabreeze namespace. - -INSPECTOR_P_SUPPORT(Seabreeze::SeabreezeEngine); - -#endif // SEABREEZE_SEABREEZE_ENGINE_H diff --git a/Seabreeze/src/Seabreeze/Tree.h b/Seabreeze/src/Seabreeze/Tree.h deleted file mode 100644 index 88161663..00000000 --- a/Seabreeze/src/Seabreeze/Tree.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "Node.h" - -#include "hurricane/Contact.h" -#include "hurricane/RoutingPad.h" -#include "hurricane/Component.h" - -using namespace std; -using Hurricane::Contact; -using Hurricane::RoutingPad; -using Hurricane::Component; - -class Tree { - public: - Tree (); - ~Tree (); - int get_N (); - Node* get_node ( Contact* cont ); - vector get_node_list (); - void new_node (); - void add_node ( Node* node ); - void After_i ( Node* ni ); - set Branch_i ( Contact* ct ); - double Delay_Elmore ( RoutingPad* rp ); - void print ( ostream& out ); - void clear (); - private: - vector nodes; -}; diff --git a/Seabreeze/src/SeabreezeEngine.cpp b/Seabreeze/src/SeabreezeEngine.cpp index dc75e330..b45abe34 100644 --- a/Seabreeze/src/SeabreezeEngine.cpp +++ b/Seabreeze/src/SeabreezeEngine.cpp @@ -1,6 +1,19 @@ -#include -#include -#include +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) SU 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | S e a b r e e z e - Timing Analysis | +// | | +// | Author : Vu Hoang Anh PHAM | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./SeabreezeEngine.cpp" | +// +-----------------------------------------------------------------+ + + #include #include "hurricane/utilities/Path.h" #include "hurricane/DebugSession.h" @@ -20,7 +33,8 @@ #include "hurricane/Vertical.h" #include "hurricane/Horizontal.h" #include "crlcore/AllianceFramework.h" -#include "Seabreeze/SeabreezeEngine.h" +#include "seabreeze/SeabreezeEngine.h" +#include "seabreeze/Elmore.h" namespace Seabreeze { @@ -50,14 +64,17 @@ namespace Seabreeze { using Hurricane::Transformation; using Hurricane::Occurrence; + //--------------------------------------------------------- // Class : "Seabreeze::SeabreezeEngine". Name SeabreezeEngine::_toolName = "Seabreeze"; + const Name& SeabreezeEngine::staticGetName () { return _toolName; } + SeabreezeEngine* SeabreezeEngine::create ( Cell* cell ) { SeabreezeEngine* seabreeze = new SeabreezeEngine ( cell ); @@ -65,12 +82,15 @@ namespace Seabreeze { return seabreeze; } + SeabreezeEngine* SeabreezeEngine::get ( const Cell* cell ) { return static_cast(ToolEngine::get(cell, staticGetName())); } + const Name& SeabreezeEngine::getName () const { return _toolName; }; + Record* SeabreezeEngine::_getRecord () const { Record* record= Super::_getRecord (); @@ -81,69 +101,77 @@ namespace Seabreeze { return record; } - string SeabreezeEngine::_getString () const + + string SeabreezeEngine::_getString () const { ostringstream os; os << "<" << "SeabreezeEngine " << _cell->getName() << ">"; return os.str(); } - string SeabreezeEngine::_getTypeName () const + + string SeabreezeEngine::_getTypeName () const { return "Seabreeze::SeabreezeEngine"; } - void SeabreezeEngine::runTool ( Net* net ) + + void SeabreezeEngine::buildElmore ( Net* net ) { - cerr << "SeabreezeEngine::runTool() has been called." << endl; - -// DebugSession::addToTrace(net); - DebugSession::open(net, 190, 200); - - RoutingPad* driver= nullptr; + DebugSession::open( net, 190, 200 ); + cdebug_log(199,1) << "SeabreezeEngine::buildElmore()" << endl; + cdebug_log(199,0) << "Run on " << net << endl; + RoutingPad* driver = nullptr; for ( RoutingPad* rp : net->getRoutingPads() ) { - Plug* p = static_cast(rp->getPlugOccurrence().getEntity()); - if ( p->getMasterNet()->getDirection() & Net::Direction::DirOut ) { + Plug* p = static_cast( rp->getPlugOccurrence().getEntity() ); + if (p->getMasterNet()->getDirection() & Net::Direction::DirOut) { driver = rp; break; } } - Elmore* elm = ElmoreProperty::create(net)->getElmore(); - elm->contFromNet(net); + Elmore* elmore = ElmoreProperty::create( net )->getElmore(); + elmore->contFromNet( net ); - cdebug_log(199, 0) << endl << "There are : " << (elm->get_conts()).size() << " routing pads presented by :" << endl; - for ( Contact* ct : elm->get_conts() ) { - cdebug_log(199, 1) << ct << endl; - cdebug_tabw(199, -1); + cdebug_log(199,0) << "Found " << elmore->getContacts().size() << " RoutingPads:" << endl; + for ( Contact* contact : elmore->getContacts() ) { + cdebug_log(199,0) << "| " << contact << endl; } - cdebug_log(199,0) << endl; - elm->buildTree(driver); + elmore->buildTree( driver ); for ( RoutingPad* rp : net->getRoutingPads() ) { - Plug* p = static_cast(rp->getPlugOccurrence().getEntity()); - if ( p->getMasterNet()->getDirection() & Net::Direction::DirOut ) { + Plug* plug = static_cast( rp->getPlugOccurrence().getEntity() ); + if (plug->getMasterNet()->getDirection() & Net::Direction::DirOut) { continue; } + cdebug_log(199,0) << "| Elmore's delay: " << elmore->delayElmore(rp) << " " << rp << endl; + } - cerr << "Elmore's delay : " << elm->delayElmore(rp) << endl; - } + cdebug_tabw(199,-1); DebugSession::close(); } + SeabreezeEngine::SeabreezeEngine ( Cell* cell ) - : Super (cell) - , _viewer (NULL) + : Super (cell) + , _configuration(new Configuration()) + , _viewer (NULL) {} + SeabreezeEngine::~SeabreezeEngine () - {} + { + delete _configuration; + } + void SeabreezeEngine::_postCreate() { Super::_postCreate (); } + void SeabreezeEngine::_preDestroy () {} -} + +} // Seabreeze namespace. diff --git a/Seabreeze/src/Tree.cpp b/Seabreeze/src/Tree.cpp index 0259894e..36679b00 100644 --- a/Seabreeze/src/Tree.cpp +++ b/Seabreeze/src/Tree.cpp @@ -1,164 +1,172 @@ -#include "Seabreeze/Tree.h" +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) SU 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | S e a b r e e z e - Timing Analysis | +// | | +// | Author : Vu Hoang Anh PHAM | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./Tree.cpp" | +// +-----------------------------------------------------------------+ + +#include #include -#include +#include +#include "hurricane/Error.h" +#include "seabreeze/Tree.h" -using namespace std; -Tree::Tree () - :nodes() -{} +namespace Seabreeze { -Tree::~Tree () -{ - for(Node* n : nodes){ - delete n; + using std::string; + using std::find; + using std::set; + using std::cerr; + using std::endl; + using std::ostream; + using Hurricane::Error; + + + Tree::Tree () + : _nodes() + {} + + + Tree::~Tree () + { + for( Node* n : _nodes) delete n; } -} -int Tree::get_N () -{ - return nodes.size(); -} -Node* Tree::get_node ( Contact* cont ) -{ - Node* node = nullptr; - for ( Node* n : nodes ) { - if ( n->_contact == cont ) { - node = n; + Node* Tree::get_node ( Contact* contact ) + { + for ( Node* n : _nodes ) { + if (n->contact() == contact) return n; + } + return nullptr; + } + + + void Tree::new_node () + { _nodes.push_back( new Node() ); } + + + void Tree::add_node ( Node* node ) + { + node->setLabel( _nodes.size() ); + if (find(_nodes.begin(), _nodes.end(), node) == _nodes.end()) + _nodes.push_back( node ); + } + + + void Tree::After_i ( Node *ni ) + { + if (not ni) return; + ni->setAp( 1 ); + for ( Node* child : ni->childs() ) { + After_i( child ); } } - return node; -} -vector Tree::get_node_list () -{ - return nodes; -} - -void Tree::new_node () -{ - nodes.push_back(new Node()); -} - -void Tree::add_node ( Node* node ) -{ - node->label = nodes.size(); - if ( find(nodes.begin(), nodes.end(), node) == nodes.end() ) - nodes.push_back(node); -} - -void Tree::After_i ( Node *ni ) -{ - if(ni == nullptr) - return; - - ni->ap = 1; - for ( Node* ne : ni->Ne ) { - After_i(ne); - } -} - -set Tree::Branch_i ( Contact* ct ) -{ - set ln; - Node *ni = get_node(ct); - while ( ni->Np != nullptr ) { - ln.insert(ni->Np); - ni = ni->Np; - } - - return ln; -} - -double Tree::Delay_Elmore ( RoutingPad* rp ) -{ - if ( rp == nullptr ) { - cerr << "Input RoutingPad is NULL. Please select a RoutingPad !" << endl; - return -1; - } - - Contact* ct = nullptr; - for ( Component* c : rp->getSlaveComponents() ) { - Contact* cont = dynamic_cast(c); - - if ( cont ) { - ct = cont; - break; + set Tree::Branch_i ( Contact* contact ) + { + set parents; + Node *ni = get_node( contact ); + while ( ni->parent() ) { + parents.insert( ni->parent() ); + ni = ni->parent(); } + return parents; } - if ( ct == nullptr ) { - cerr << "No contact found" << endl; - return -1; - } + + + double Tree::Delay_Elmore ( RoutingPad* rp ) + { + if (not rp) { + cerr << Error( "Tree::computeDelay(): Sink RoutingPad argument is NULL." ) << endl; + return -1.0; + } - double t = 0; -//--------------------------------------------------------------------------------------- - cerr << "Contact to be calculated : " << ct->getId() << endl; -//--------------------------------------------------------------------------------------- + Contact* sink = nullptr; + for ( Component* component : rp->getSlaveComponents() ) { + Contact* contact = dynamic_cast( component ); + if (contact) { + sink = contact; + break; + } + } + if (not sink) { + cerr << Error( "Tree::computeDelay(): No Contact anchored on RoutingPad, aborting.\n" + " (on %s)" + , getString(rp).c_str() + ) << endl; + return -1.0; + } + + cdebug_log(199,1) << "Tree::computeDelay()" << endl; + cdebug_log(199,0) << " rp=" << rp << endl; + cdebug_log(199,0) << " sink=" << sink << endl; + + set br = Branch_i( sink ); + Node* ni = get_node( sink ); + After_i( ni ); + ni->setAp( 0 ); - set br = Branch_i(ct); - Node *ni = get_node(ct); - After_i(ni); - ni->ap = 0; // Compute Rt of all nodes - for ( size_t k = 0; k < nodes.size(); k++ ) { - if ( k == 0 ) - nodes[k]->Rt = nodes[k]->R; - else{ - if ( nodes[k]->ap == 0 ) { - if ( br.count(nodes[k]) > 0 ) { - nodes[k]->Rt = (nodes[k]->Np)->Rt + nodes[k]->R; - } - else{ - nodes[k]->Rt = (nodes[k]->Np)->Rt; - } - } - else{ - nodes[k]->Rt = ni->Rt; + for ( size_t k = 0; k < _nodes.size(); k++ ) { + if (k == 0) + _nodes[k]->setRt( _nodes[k]->R() ); + else { + if (_nodes[k]->ap() == 0) { + if (br.count(_nodes[k]) > 0) { + _nodes[k]->setRt( _nodes[k]->parent()->Rt() + _nodes[k]->R() ); + } else { + _nodes[k]->setRt( _nodes[k]->parent()->Rt() ); + } + } else { + _nodes[k]->setRt( ni->Rt() ); + } } } + + // Compute Elmore delay time + double delay = 0.0; + for ( size_t k = 0; k < _nodes.size(); k++ ) { + delay += (_nodes[k]->Rt()) * (_nodes[k]->C()); + } + + return delay; + } + + + void Tree::printNode ( ostream& os, Node* node, size_t depth ) + { + string indent ( depth*2, ' '); + os << indent << node->contact() << " R=" << node->R() << " C=" << node->C() << endl; + for ( Node* child : node->childs() ) { + printNode( os, child, depth+1 ); + } } - //Compute Elmore delay time - for ( size_t k = 0; k < nodes.size(); k++ ) { - t += (nodes[k]->Rt)*(nodes[k]->C); - } - return t; -} -void Tree::print ( ostream& out ) -{ - out << "Start printing tree..." << endl; - out << "Tree has " << nodes.size() << " nodes :" << endl; - out << nodes[0]->_contact->getId() - << " : R = " << nodes[0]->R - << ", C = " << nodes[0]->C - << " -> "; - for(Node* n : nodes[0]->Ne){ - out << n->_contact->getId() << ", "; + void Tree::print ( ostream& os ) + { + os << "Elmore Tree of " << _nodes[0]->contact()->getNet() << endl; + os << " Tree has " << _nodes.size() << " nodes :" << endl; + printNode( os, _nodes[0], 0 ); } - out << std::endl; - for ( size_t i = 1; i < nodes.size(); i++ ) { - out << nodes[i]->Np->_contact->getId() - << " -> " << nodes[i]->_contact->getId() - << " : R = " << nodes[i]->R - << ", C = " << nodes[i]->C; - if ( !(nodes[i]->Ne).empty() ) { - out << " -> "; - for ( Node* n : nodes[i]->Ne ) { - out << n->_contact->getId() << ", "; - } - } - else - out << " |"; - out << endl; + + void Tree::clear () + { + _nodes.clear(); } -} -void Tree::clear () { - nodes.clear(); -} + +} // Seabreeze namespace. diff --git a/Seabreeze/src/seabreeze/Configuration.h b/Seabreeze/src/seabreeze/Configuration.h new file mode 100644 index 00000000..1fdc894e --- /dev/null +++ b/Seabreeze/src/seabreeze/Configuration.h @@ -0,0 +1,62 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) SU 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | S e a b r e e z e - Timing Analysis | +// | | +// | Author : Vu Hoang Anh PHAM | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./seabreeze/Configuration.h" | +// +-----------------------------------------------------------------+ + +#pragma once +#include +#include +#include + +namespace Seabreeze { + + using std::string; + using Hurricane::Record; + using Hurricane::Name; + using Hurricane::Layer; + using Hurricane::DbU; + using Hurricane::Contact; + using Hurricane::Segment; + + +//------------------------------------------------------------------------ +// Class : "Seabreeze::Configuration" + + class Configuration { + public : + Configuration (); + Configuration ( const Configuration& ); + ~Configuration (); + virtual Configuration* clone () const; + inline double getRct () const; + inline double getRsm () const; + inline double getCsm () const; + //virtual Record* _getRecord () const; + //virtual string _getString () const; + virtual string _getTypeName () const; + protected : + // Attributes + double _Rct; + double _Rsm; + double _Csm; + private : + Configuration& operator= ( const Configuration& ) = delete; + }; + + + inline double Configuration::getRct () const { return _Rct; } + inline double Configuration::getRsm () const { return _Rsm; } + inline double Configuration::getCsm () const { return _Csm; } + + +} // Seabreeze namespace. diff --git a/Seabreeze/src/seabreeze/Elmore.h b/Seabreeze/src/seabreeze/Elmore.h new file mode 100644 index 00000000..cd7b0121 --- /dev/null +++ b/Seabreeze/src/seabreeze/Elmore.h @@ -0,0 +1,131 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) SU 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | S e a b r e e z e - Timing Analysis | +// | | +// | Author : Vu Hoang Anh PHAM | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./seabreeze/Elmore.cpp" | +// +-----------------------------------------------------------------+ + +#include +#include +#include +#include "hurricane/Property.h" +#include "hurricane/RoutingPad.h" +#include "hurricane/Contact.h" +#include "hurricane/Segment.h" +#include "Configuration.h" +#include "Tree.h" + +namespace Hurricane { + class Net; + class Instance; +} + +namespace Seabreeze { + + using namespace std; + using Hurricane::Name; + using Hurricane::DBo; + using Hurricane::Net; + using Hurricane::Cell; + using Hurricane::RoutingPad; + using Hurricane::Contact; + using Hurricane::Instance; + using Hurricane::Segment; + using Hurricane::PrivateProperty; + class SeabreezeEngine; + + +//---------------------------------------------------------- +// Class : Seabreeze::Elmore + + class Elmore { + public: + Elmore ( Net* ); + ~Elmore (); + inline SeabreezeEngine* getSeabreeze () const; + const Configuration* getConfiguration () const; + void contFromNet ( Net* ); + void buildTree ( RoutingPad* ); + void buildFromNode ( Node* source, Segment* ); + Contact* buildBranch ( double* R, double* C, Contact* contact ); + void setRC ( double* R, double* C, Contact* , Segment* ); + void clearTree (); + inline Tree* getTree (); + inline const set& getContacts () const; + double delayElmore ( RoutingPad* ); + void toTree ( ostream& ) const; + inline void setSeabreeze ( SeabreezeEngine* ); + private: + SeabreezeEngine* _seabreeze; + set _contacts; + set _checker; + Tree* _tree; + }; + + + inline SeabreezeEngine* Elmore::getSeabreeze () const { return _seabreeze; } + inline const set& Elmore::getContacts () const { return _contacts; } + inline Tree* Elmore::getTree () { return _tree; } + inline void Elmore::setSeabreeze ( SeabreezeEngine* seabreeze ) { _seabreeze = seabreeze; } + + +//--------------------------------------------------------- +// Class : Seabreeze::ElmoreProperty + + class ElmoreProperty : public Hurricane::PrivateProperty { + friend class ElmoreExtension; + public: + static Name _name; + public: + static ElmoreProperty* create ( Net* net ); + static Name staticGetName (); + Name getName () const; + inline Elmore* getElmore (); + virtual string _getTypeName () const; + protected: + Elmore _elmore; + protected: + ElmoreProperty ( Net* ); + }; + + + inline Elmore* ElmoreProperty::getElmore () + { return &_elmore; } + + +//--------------------------------------------------------- +// Class : Seabreeze::ElmoreExtension + + class ElmoreExtension { + public: + static Elmore* create ( Net* ); + static Elmore* get ( Net* ); + static inline Tree* getTree ( Net* ); + static inline void toTree ( Net*, std::ostream& ); + static void destroy ( Net* ); + }; + + + inline Tree* ElmoreExtension::getTree ( Net* net ) + { + Elmore* elmore = get( net ); + return (elmore) ? elmore->getTree() : nullptr; + } + + + inline void ElmoreExtension::toTree ( Net* net, std::ostream& os ) + { + Elmore* elmore = get( net ); + if (elmore) elmore->toTree( os ); + } + + +} // Seabreeze Namespace diff --git a/Seabreeze/src/seabreeze/Node.h b/Seabreeze/src/seabreeze/Node.h new file mode 100644 index 00000000..86935669 --- /dev/null +++ b/Seabreeze/src/seabreeze/Node.h @@ -0,0 +1,77 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) SU 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | S e a b r e e z e - Timing Analysis | +// | | +// | Author : Vu Hoang Anh PHAM | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./seabreeze/Node.h" | +// +-----------------------------------------------------------------+ + +#pragma once +#include +namespace Hurricane { + class Contact; +} + +namespace Seabreeze { + + using Hurricane::Contact; + + +//---------------------------------------------------------- +// Class : Seabreeze::Tree. + + class Node { + public: + Node (); + Node ( Node* parent, Contact* ); + ~Node (); + inline double R () const; + inline double Rt () const; + inline double C () const; + inline int label () const; + inline int ap () const; + inline Contact* contact () const; + inline Node* parent () const; + inline const std::vector& childs () const; + inline void addChild ( Node* ); + inline void setLabel ( int ); + inline void setAp ( int ); + inline void setRt ( double ); + inline void setR ( double ); + inline void setC ( double ); + private : + double _R; + double _Rt; + double _C; + Node* _parent; + std::vector _childs; + Contact* _contact; + int _label; + int _ap; + }; + + + inline double Node::R () const { return _R; } + inline double Node::Rt () const { return _Rt; } + inline double Node::C () const { return _C; } + inline int Node::label () const { return _label; } + inline int Node::ap () const { return _ap; } + inline Contact* Node::contact () const { return _contact; } + inline Node* Node::parent () const { return _parent; } + inline const std::vector& Node::childs () const { return _childs; } + inline void Node::addChild ( Node* child ) { _childs.push_back( child ); } + inline void Node::setLabel ( int label ) { _label = label; } + inline void Node::setAp ( int ap ) { _ap = ap; } + inline void Node::setRt ( double rt ) { _Rt = rt; } + inline void Node::setR ( double r ) { _R = r; } + inline void Node::setC ( double c ) { _C = c; } + + +} // Seabreeze namespace; diff --git a/Seabreeze/src/Seabreeze/PySeabreezeEngine.h b/Seabreeze/src/seabreeze/PySeabreezeEngine.h similarity index 96% rename from Seabreeze/src/Seabreeze/PySeabreezeEngine.h rename to Seabreeze/src/seabreeze/PySeabreezeEngine.h index 235ad10d..aaa5b1a5 100644 --- a/Seabreeze/src/Seabreeze/PySeabreezeEngine.h +++ b/Seabreeze/src/seabreeze/PySeabreezeEngine.h @@ -3,7 +3,7 @@ #include "hurricane/isobar/PyHurricane.h" #include "crlcore/PyToolEngine.h" -#include "SeabreezeEngine.h" +#include "seabreeze/SeabreezeEngine.h" namespace Seabreeze { diff --git a/Seabreeze/src/seabreeze/SeabreezeEngine.h b/Seabreeze/src/seabreeze/SeabreezeEngine.h new file mode 100644 index 00000000..c270744a --- /dev/null +++ b/Seabreeze/src/seabreeze/SeabreezeEngine.h @@ -0,0 +1,94 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) SU 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | S e a b r e e z e - Timing Analysis | +// | | +// | Author : Vu Hoang Anh PHAM | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./seabreeze/SeabreezeEngine.h" | +// +-----------------------------------------------------------------+ + +#pragma once +#include +#include + +#include "hurricane/Name.h" +#include "hurricane/viewer/CellViewer.h" +#include "hurricane/RoutingPad.h" + +namespace Hurricane { + class Net; + class Cell; +} + +#include "crlcore/ToolEngine.h" +#include "seabreeze/Configuration.h" + +namespace Seabreeze { + + using Hurricane::Record; + using Hurricane::Name; + using Hurricane::Net; + using Hurricane::Cell; + using Hurricane::CellViewer; + using Hurricane::RoutingPad; + using CRL::ToolEngine; + + +//---------------------------------------------------------- +// Class : "Seabreeze::SeabreezeEngine" + + class SeabreezeEngine : public ToolEngine { + public : + typedef ToolEngine Super; + public : + static const Name& staticGetName (); + static SeabreezeEngine* create ( Cell* ); + static SeabreezeEngine* get ( const Cell* ); + public : + inline CellViewer* getViewer () const; + inline ToolEngine* base (); + virtual const Name& getName () const; + inline const Configuration* getConfiguration () const; + inline double getRct () const; + inline double getRsm () const; + inline double getCsm () const; + inline void setViewer ( CellViewer* ); + virtual Record* _getRecord () const; + virtual std::string _getString () const; + virtual std::string _getTypeName () const; + virtual void buildElmore ( Net* net ); + protected : + SeabreezeEngine ( Cell* ); + virtual ~SeabreezeEngine (); + virtual void _postCreate (); + virtual void _preDestroy (); + private : + SeabreezeEngine ( const SeabreezeEngine& ) = delete; + SeabreezeEngine& operator= ( const SeabreezeEngine& ) = delete; + private : + // Attributes. + static Name _toolName; + protected : + Configuration* _configuration; + CellViewer* _viewer; + }; + + +// Inline Functions. + inline ToolEngine* SeabreezeEngine::base () { return static_cast(this); } + inline const Configuration* SeabreezeEngine::getConfiguration () const { return _configuration; } + inline double SeabreezeEngine::getRct () const { return getConfiguration()->getRct(); } + inline double SeabreezeEngine::getRsm () const { return getConfiguration()->getRsm(); } + inline double SeabreezeEngine::getCsm () const { return getConfiguration()->getCsm(); } + inline CellViewer* SeabreezeEngine::getViewer () const { return _viewer; } + inline void SeabreezeEngine::setViewer ( CellViewer* viewer ) { _viewer = viewer; } + +} // Seabreeze namespace. + +INSPECTOR_P_SUPPORT(Seabreeze::SeabreezeEngine); diff --git a/Seabreeze/src/seabreeze/Tree.h b/Seabreeze/src/seabreeze/Tree.h new file mode 100644 index 00000000..64306828 --- /dev/null +++ b/Seabreeze/src/seabreeze/Tree.h @@ -0,0 +1,61 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) SU 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | S e a b r e e z e - Timing Analysis | +// | | +// | Author : Vu Hoang Anh PHAM | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./seabreeze/Tree.h" | +// +-----------------------------------------------------------------+ + + +#pragma once +#include +#include +#include +#include "hurricane/Contact.h" +#include "hurricane/RoutingPad.h" +#include "hurricane/Component.h" +#include "Node.h" + + +namespace Seabreeze { + + using Hurricane::Contact; + using Hurricane::RoutingPad; + using Hurricane::Component; + + +//---------------------------------------------------------- +// Class : Seabreeze::Tree. + + class Tree { + public: + Tree (); + ~Tree (); + inline size_t get_N (); + Node* get_node ( Contact* ); + inline const std::vector& get_node_list () const; + void new_node (); + void add_node ( Node* ); + void After_i ( Node* ); + std::set Branch_i ( Contact* ); + double Delay_Elmore ( RoutingPad* ); + void printNode ( std::ostream& , Node* , size_t depth ); + void print ( std::ostream& ); + void clear (); + private: + std::vector _nodes; + }; + + + inline size_t Tree::get_N () { return _nodes.size(); } + inline const std::vector& Tree::get_node_list () const { return _nodes; } + + +} // Seabreeze namespace.