First step in normalizing/rewriting Seabreeze.

This commit is contained in:
Jean-Paul Chaput 2022-07-20 15:14:38 +02:00
parent be1dd12c1a
commit 336b0ad015
21 changed files with 1104 additions and 988 deletions

View File

@ -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 )

View File

@ -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 <iostream>
#include <iomanip>
#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.

371
Seabreeze/src/Elmore.cpp Normal file
View File

@ -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<Contact*>( 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<Contact*>(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<Segment*>( 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<Contact*>( 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<Segment*>(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<Segment*>( component );
if (not segment) continue;
cdebug_log(199,0) << "| " << segment << endl;
Contact* target = dynamic_cast<Contact*>( 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<Segment*>( component );
if (not segment) continue;
Contact* opposite = dynamic_cast<Contact*>( 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<Segment*>( component );
if (not segment) continue;
cdebug_log(199,0) << "| " << segment << endl;
Contact* opposite = dynamic_cast<Contact*>( 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<SeabreezeEngine*>( 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<ElmoreProperty*>( property )->getElmore();
return elmore;
}
} // Seabreeze namespace.

View File

@ -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 <iostream>
#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.

View File

@ -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 {

View File

@ -10,18 +10,18 @@
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./PySeabreezeEngine.cpp" |
// | C++ Module : "./PySeabreezeEngine.cpp" |
// +-----------------------------------------------------------------+
#include <functional>
#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 <functional>
#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." }

View File

@ -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<Contact*>(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<Contact*>(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<Segment*>(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<Contact*>(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<Segment*>(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<Segment*>(comp);
if ( not segmt )
continue;
cdebug_log(199,1) << "Segment : " << segmt->getId() << endl;
cdebug_tabw(199,-1);
Contact* target = dynamic_cast<Contact*>(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<Segment*>(cp);
if ( not sm )
continue;
Contact* tar = dynamic_cast<Contact*>(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<Segment*>(cp);
if ( not sm )
continue;
cdebug_log(199,1) << "Sm : " << sm->getId() << endl;
cdebug_tabw(199,-1);
Contact* tar = dynamic_cast<Contact*>(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 )
{
}
}

View File

@ -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 <coriolis> 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)

View File

@ -1,59 +0,0 @@
#pragma once
#include <string>
#include <vector>
#include <hurricane/DbU.h>
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;
};
}

View File

@ -1,23 +0,0 @@
#pragma once // ensures that this header file is only included once
#include <vector>
#include "hurricane/Contact.h"
using Hurricane::Contact;
class Node {
public :
double R;
double Rt;
double C;
Node* Np;
std::vector<Node*> Ne;
Contact* _contact;
int label;
int ap;
public:
Node ();
Node ( Node* parent, Contact* ct );
~Node ();
};

View File

@ -1,118 +0,0 @@
#include <string>
#include <vector>
#include <set>
#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<Contact*>& get_conts () const;
inline Configuration* getConfig ();
double delayElmore ( RoutingPad* rp );
void toTREE ( ostream& ) const;
private:
Configuration* _config;
set<Contact*> _conts;
set<Contact*> checker;
Tree* _tree;
};
inline const set<Contact*>& 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

View File

@ -1,71 +0,0 @@
#ifndef SEABREEZE_SEABREEZE_ENGINE_H
#define SEABREEZE_SEABREEZE_ENGINE_H
#include <string>
#include <iostream>
#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<ToolEngine*>(this); }
inline void SeabreezeEngine::setViewer ( CellViewer* viewer ) { _viewer = viewer; }
} // Seabreeze namespace.
INSPECTOR_P_SUPPORT(Seabreeze::SeabreezeEngine);
#endif // SEABREEZE_SEABREEZE_ENGINE_H

View File

@ -1,34 +0,0 @@
#pragma once
#include <set>
#include <vector>
#include <iostream>
#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<Node*> get_node_list ();
void new_node ();
void add_node ( Node* node );
void After_i ( Node* ni );
set<Node*> Branch_i ( Contact* ct );
double Delay_Elmore ( RoutingPad* rp );
void print ( ostream& out );
void clear ();
private:
vector<Node*> nodes;
};

View File

@ -1,6 +1,19 @@
#include <Python.h>
#include <sstream>
#include <fstream>
// -*- 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 <iomanip>
#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<SeabreezeEngine*>(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<Plug*>(rp->getPlugOccurrence().getEntity());
if ( p->getMasterNet()->getDirection() & Net::Direction::DirOut ) {
Plug* p = static_cast<Plug*>( 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<Plug*>(rp->getPlugOccurrence().getEntity());
if ( p->getMasterNet()->getDirection() & Net::Direction::DirOut ) {
Plug* plug = static_cast<Plug*>( 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.

View File

@ -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 <string>
#include <iostream>
#include <iterator>
#include <algorithm>
#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<Node*> 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<Node*> Tree::Branch_i ( Contact* ct )
{
set<Node*> 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<Contact*>(c);
if ( cont ) {
ct = cont;
break;
set<Node*> Tree::Branch_i ( Contact* contact )
{
set<Node*> 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<Contact*>( 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<Node*> br = Branch_i( sink );
Node* ni = get_node( sink );
After_i( ni );
ni->setAp( 0 );
set<Node*> 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.

View File

@ -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 <string>
#include <vector>
#include <hurricane/DbU.h>
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.

View File

@ -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 <string>
#include <vector>
#include <set>
#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<Contact*>& getContacts () const;
double delayElmore ( RoutingPad* );
void toTree ( ostream& ) const;
inline void setSeabreeze ( SeabreezeEngine* );
private:
SeabreezeEngine* _seabreeze;
set<Contact*> _contacts;
set<Contact*> _checker;
Tree* _tree;
};
inline SeabreezeEngine* Elmore::getSeabreeze () const { return _seabreeze; }
inline const set<Contact*>& 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

View File

@ -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 <vector>
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<Node*>& 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<Node*> _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*>& 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;

View File

@ -3,7 +3,7 @@
#include "hurricane/isobar/PyHurricane.h"
#include "crlcore/PyToolEngine.h"
#include "SeabreezeEngine.h"
#include "seabreeze/SeabreezeEngine.h"
namespace Seabreeze {

View File

@ -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 <string>
#include <iostream>
#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<ToolEngine*>(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);

View File

@ -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 <set>
#include <vector>
#include <iostream>
#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<Node*>& get_node_list () const;
void new_node ();
void add_node ( Node* );
void After_i ( Node* );
std::set<Node*> Branch_i ( Contact* );
double Delay_Elmore ( RoutingPad* );
void printNode ( std::ostream& , Node* , size_t depth );
void print ( std::ostream& );
void clear ();
private:
std::vector<Node*> _nodes;
};
inline size_t Tree::get_N () { return _nodes.size(); }
inline const std::vector<Node*>& Tree::get_node_list () const { return _nodes; }
} // Seabreeze namespace.