First step in normalizing/rewriting Seabreeze.
This commit is contained in:
parent
be1dd12c1a
commit
336b0ad015
|
@ -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 )
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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." }
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -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)
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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 ();
|
||||
};
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
};
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
|
@ -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
|
|
@ -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;
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "hurricane/isobar/PyHurricane.h"
|
||||
#include "crlcore/PyToolEngine.h"
|
||||
#include "SeabreezeEngine.h"
|
||||
#include "seabreeze/SeabreezeEngine.h"
|
||||
|
||||
|
||||
namespace Seabreeze {
|
|
@ -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);
|
|
@ -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.
|
Loading…
Reference in New Issue