Non-hierarchical, metal only, rectangle only, extractor is now working.
* New: In Tramontana, * Multi-layer support for the swap line. Split VIAs into their various metal plates and link the two relevant tiles, ensuring connexity between layers. * Improved Equipotential information rebuild. Try to rebuild more closely the Net characteristics. Improved tab widgets.
This commit is contained in:
parent
2568a1a496
commit
23c0c24c0f
|
@ -117,9 +117,11 @@ namespace Tramontana {
|
|||
, _name (defaultName)
|
||||
, _type (Net::Type::UNDEFINED)
|
||||
, _direction (Net::Direction::DirUndefined)
|
||||
, _netCount (0)
|
||||
, _isExternal (false)
|
||||
, _isGlobal (false)
|
||||
, _isAutomatic(false)
|
||||
, _hasFused (false)
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -194,29 +196,21 @@ namespace Tramontana {
|
|||
|
||||
void Equipotential::consolidate ()
|
||||
{
|
||||
int containsFused = 0;
|
||||
set<Net*,NetCompareByName> nets;
|
||||
for ( Component* component : getComponents() ) {
|
||||
Net* net = component->getNet();
|
||||
if (net->isFused ()) containsFused = 1;
|
||||
if (net->isExternal ()) _isExternal = true;
|
||||
if (net->isGlobal ()) _isGlobal = true;
|
||||
if (net->isAutomatic()) _isAutomatic = true;
|
||||
_type = net->getType();
|
||||
_direction |= net->getDirection();
|
||||
if (net->isFused()) _hasFused = true;
|
||||
else {
|
||||
if (net->isExternal ()) _isExternal = true;
|
||||
if (net->isGlobal ()) _isGlobal = true;
|
||||
if (net->isAutomatic()) _isAutomatic = true;
|
||||
_type = net->getType();
|
||||
_direction |= net->getDirection();
|
||||
}
|
||||
nets.insert( component->getNet() );
|
||||
}
|
||||
_name = getString( (*nets.begin())->getName() );
|
||||
_name += " [" + getString(nets.size() - containsFused);
|
||||
if (containsFused)
|
||||
_name += "+fused";
|
||||
_name += "] ";
|
||||
_name += ((_isExternal ) ? "e" : "-");
|
||||
_name += ((_isGlobal ) ? "g" : "-");
|
||||
_name += ((_isAutomatic) ? "a" : "-");
|
||||
_name += " ";
|
||||
_name += getString(_type ) + " ";
|
||||
_name += getString(_direction);
|
||||
_netCount = nets.size();
|
||||
}
|
||||
|
||||
|
||||
|
@ -227,6 +221,20 @@ namespace Tramontana {
|
|||
}
|
||||
|
||||
|
||||
string Equipotential::getFlagsAsString () const
|
||||
{
|
||||
string sflags;
|
||||
sflags += ((_isExternal ) ? "e" : "-");
|
||||
sflags += ((_isGlobal ) ? "g" : "-");
|
||||
sflags += ((_isAutomatic) ? "a" : "-");
|
||||
sflags += " [" + getString( _netCount - ((_hasFused) ? 1 : 0) );
|
||||
if (_hasFused)
|
||||
sflags += "+fused";
|
||||
sflags += "] ";
|
||||
return sflags;
|
||||
}
|
||||
|
||||
|
||||
string Equipotential::_getTypeName () const
|
||||
{ return "Tramontana::Equipotential"; }
|
||||
|
||||
|
@ -234,9 +242,12 @@ namespace Tramontana {
|
|||
string Equipotential::_getString () const
|
||||
{
|
||||
ostringstream os;
|
||||
os << "<Equipotential id:" << getId()
|
||||
//<< " " << getName()
|
||||
<< " " << _owner->getName() << ">";
|
||||
os << "<Equipotential id:" << getId() << " "
|
||||
<< getFlagsAsString()
|
||||
<< " " << getName()
|
||||
<< " " << getType()
|
||||
<< " " << getDirection()
|
||||
<< ">";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ namespace Tramontana {
|
|||
static QFont valueFont = Graphics::getFixedFont ( QFont::Normal, true );
|
||||
|
||||
if (role == Qt::FontRole) {
|
||||
if (index.row() == 0) return QVariant();
|
||||
switch (index.column()) {
|
||||
case 0: return nameFont;
|
||||
default: return valueFont;
|
||||
|
@ -54,8 +53,13 @@ namespace Tramontana {
|
|||
if (not index.isValid()) return QVariant ();
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
int row = index.row ();
|
||||
return QString::fromStdString( _equipotentials[row]->getName() );
|
||||
Equipotential* equi = _equipotentials[ index.row() ];
|
||||
switch ( index.column() ) {
|
||||
case 0: return QString::fromStdString( equi->getName() );
|
||||
case 1: return QString::fromStdString( equi->getFlagsAsString() );
|
||||
case 2: return QString::fromStdString( getString( equi->getType() ));
|
||||
case 3: return QString::fromStdString( getString( equi->getDirection() ));
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
@ -71,26 +75,20 @@ namespace Tramontana {
|
|||
|
||||
if (role == Qt::FontRole ) return headerFont;
|
||||
if (role != Qt::DisplayRole) return QVariant();
|
||||
|
||||
if (section == 0) return QVariant("Equipotential");
|
||||
// if (section < _equipotentials->getColumnCount())
|
||||
// return _equipotentials->getColumnName( section );
|
||||
|
||||
if (section == 0) return QVariant( "Name" );
|
||||
if (section == 1) return QVariant( "Flags" );
|
||||
if (section == 2) return QVariant( "Type" );
|
||||
if (section == 3) return QVariant( "Direction" );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
int EquipotentialsModel::rowCount ( const QModelIndex& parent ) const
|
||||
{
|
||||
return _equipotentials.size();
|
||||
}
|
||||
{ return _equipotentials.size(); }
|
||||
|
||||
|
||||
int EquipotentialsModel::columnCount ( const QModelIndex& parent ) const
|
||||
{
|
||||
return 1;
|
||||
//return (_equipotentials) ? _equipotentials->getColumnCount() : 1;
|
||||
}
|
||||
{ return 4; }
|
||||
|
||||
|
||||
const Equipotential* EquipotentialsModel::getEqui ( int row )
|
||||
|
|
|
@ -83,9 +83,9 @@ namespace Tramontana {
|
|||
|
||||
|
||||
SweepLine::SweepLine ( TramontanaEngine* tramontana )
|
||||
: _tramontana (tramontana)
|
||||
, _tiles ()
|
||||
, _intervalTree()
|
||||
: _tramontana (tramontana)
|
||||
, _tiles ()
|
||||
, _intervalTrees()
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -95,37 +95,79 @@ namespace Tramontana {
|
|||
|
||||
void SweepLine::run ()
|
||||
{
|
||||
BasicLayer* layer = DataBase::getDB()->getTechnology()->getBasicLayer( "metal1" );
|
||||
loadTiles( layer );
|
||||
//cerr << "SweepLine::run()" << endl;
|
||||
//DebugSession::open( 0, 2 );
|
||||
loadTiles();
|
||||
for ( Element& element : _tiles ) {
|
||||
Tile* tile = element.getTile();
|
||||
TileIntv tileIntv ( tile, tile->getYMin(), tile->getYMax() );
|
||||
cerr << right << setw(10) << DbU::getValueString(element.getX()) << " > " << tile << endl;
|
||||
//cerr << right << setw(10) << DbU::getValueString(element.getX()) << " > " << tile << endl;
|
||||
auto intvTree = _intervalTrees.find( element.getMask() );
|
||||
if (intvTree == _intervalTrees.end()) {
|
||||
cerr << Error( "SweepLine::run(): Missing interval tree for layer(mask) %s."
|
||||
" (for tile: %s)"
|
||||
, getString(element.getMask()).c_str()
|
||||
, getString(element.getTile()).c_str()
|
||||
) << endl;
|
||||
continue;
|
||||
}
|
||||
if (element.isLeftEdge()) {
|
||||
for ( const TileIntv& overlap : _intervalTree.getOverlaps(
|
||||
for ( const TileIntv& overlap : intvTree->second.getOverlaps(
|
||||
Interval(tile->getYMin(), tile->getYMax() ))) {
|
||||
cerr << " | intersect " << overlap.getData() << endl;
|
||||
//cerr << " | intersect " << overlap.getData() << endl;
|
||||
tile->merge( overlap.getData() );
|
||||
}
|
||||
_intervalTree.insert( tileIntv );
|
||||
//cerr << " | insert tile" << endl;
|
||||
intvTree->second.insert( tileIntv );
|
||||
} else {
|
||||
_intervalTree.remove( tileIntv );
|
||||
//cerr << " | remove tile" << endl;
|
||||
intvTree->second.remove( tileIntv );
|
||||
// if (tile->getId() == 46055) {
|
||||
// intvTree->second.write( "we_at_remove.gv" );
|
||||
// for ( auto tile : intvTree->second.getElements() ) {
|
||||
// cerr << "| in tree:" << tile << endl;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
//DebugSession::close();
|
||||
mergeEquipotentials();
|
||||
}
|
||||
|
||||
|
||||
void SweepLine::loadTiles ( const BasicLayer* layer )
|
||||
void SweepLine::loadTiles ()
|
||||
{
|
||||
cerr << "SweepLine::run()" << endl;
|
||||
//cerr << "SweepLine::loadTiles()" << endl;
|
||||
vector<const BasicLayer*> extracteds;
|
||||
for ( const BasicLayer* bl : DataBase::getDB()->getTechnology()->getBasicLayers() ) {
|
||||
if (bl->getMaterial() == BasicLayer::Material::metal)
|
||||
extracteds.push_back( bl );
|
||||
}
|
||||
|
||||
// extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "metal5" ));
|
||||
// extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "metal4" ));
|
||||
// extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "metal3" ));
|
||||
// extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "metal2" ));
|
||||
// extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "metal1" ));
|
||||
// extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "poly" ));
|
||||
|
||||
for ( const BasicLayer* layer : extracteds ) {
|
||||
_intervalTrees.insert( make_pair( layer->getMask(), TileIntvTree() ));
|
||||
}
|
||||
|
||||
for ( Occurrence occurrence : getCell()->getOccurrencesUnder( getCell()->getBoundingBox() ) ) {
|
||||
vector<Tile*> tiles;
|
||||
Component* component = dynamic_cast<Component*>( occurrence.getEntity() );
|
||||
if (not component) continue;
|
||||
if (not component->getLayer()->contains(layer)) continue;
|
||||
Tile* tile = Tile::create( occurrence, layer );
|
||||
_tiles.push_back( Element( tile, Tile::LeftEdge ) );
|
||||
_tiles.push_back( Element( tile, Tile::RightEdge ) );
|
||||
for ( const BasicLayer* layer : extracteds ) {
|
||||
if (not component->getLayer()->getMask().intersect(layer->getMask())) continue;
|
||||
tiles.push_back( Tile::create( occurrence, layer ));
|
||||
_tiles.push_back( Element( tiles.back(), Tile::LeftEdge ) );
|
||||
_tiles.push_back( Element( tiles.back(), Tile::RightEdge ) );
|
||||
if (tiles.size() > 1)
|
||||
tiles.back()->setParent( tiles[0] );
|
||||
}
|
||||
tiles.clear();
|
||||
}
|
||||
sort( _tiles.begin(), _tiles.end() );
|
||||
}
|
||||
|
@ -133,7 +175,7 @@ namespace Tramontana {
|
|||
|
||||
void SweepLine::mergeEquipotentials ()
|
||||
{
|
||||
cerr << "Tramontana::mergeEquipotentials()" << endl;
|
||||
//cerr << "SweepLine::mergeEquipotentials()" << endl;
|
||||
Tile::timeTick();
|
||||
for ( Tile* tile : Tile::getAllTiles() ) {
|
||||
tile->getRoot( Tile::MergeEqui );
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace Tramontana {
|
|||
if (not component->getLayer()->contains(layer)) {
|
||||
cerr << Error( "Tile::create(): Component layer does not contains \"%s\".\n"
|
||||
" (%s)"
|
||||
, getString(layer->getName()).c_str()
|
||||
, getString(layer).c_str()
|
||||
, getString(occurrence).c_str()
|
||||
) << endl;
|
||||
return nullptr;
|
||||
|
|
|
@ -145,11 +145,14 @@ namespace Tramontana {
|
|||
|
||||
void TramontanaEngine::extract ()
|
||||
{
|
||||
cerr << "TramontanaEngine::extract() called on " << getCell() << endl;
|
||||
cmess1 << " o Extracting " << getCell() << endl;
|
||||
startMeasures();
|
||||
SweepLine sweepLine ( this );
|
||||
sweepLine.run();
|
||||
consolidate();
|
||||
showEquipotentials();
|
||||
//showEquipotentials();
|
||||
stopMeasures();
|
||||
printMeasures();
|
||||
}
|
||||
|
||||
|
||||
|
@ -167,7 +170,7 @@ namespace Tramontana {
|
|||
|
||||
void TramontanaEngine::consolidate ()
|
||||
{
|
||||
cerr << "Tramontana::consolidate()" << endl;
|
||||
//cerr << "Tramontana::consolidate()" << endl;
|
||||
for ( Equipotential* equi : _equipotentials )
|
||||
equi->consolidate();
|
||||
}
|
||||
|
|
|
@ -49,31 +49,34 @@ namespace Tramontana {
|
|||
public:
|
||||
typedef Entity Super;
|
||||
public:
|
||||
static Equipotential* create ( Cell* );
|
||||
inline bool isEmpty () const;
|
||||
virtual Cell* getCell () const;
|
||||
virtual Box getBoundingBox () const;
|
||||
inline std::string getName () const;
|
||||
inline bool hasComponent ( Component* ) const;
|
||||
void add ( Component* );
|
||||
void add ( Occurrence );
|
||||
void merge ( Equipotential* );
|
||||
void consolidate ();
|
||||
void clear ();
|
||||
inline const ComponentSet& getComponents () const;
|
||||
inline const std::vector<Occurrence>& getChilds () const;
|
||||
Record* _getRecord () const;
|
||||
std::string _getString () const;
|
||||
std::string _getTypeName () const;
|
||||
protected:
|
||||
virtual void _postCreate ();
|
||||
virtual void _preDestroy ();
|
||||
private:
|
||||
Equipotential ( Cell* );
|
||||
~Equipotential ();
|
||||
private:
|
||||
Equipotential ( const Equipotential& ) = delete;
|
||||
Equipotential& operator= ( const Equipotential& ) = delete;
|
||||
static Equipotential* create ( Cell* );
|
||||
inline bool isEmpty () const;
|
||||
virtual Cell* getCell () const;
|
||||
virtual Box getBoundingBox () const;
|
||||
inline std::string getName () const;
|
||||
std::string getFlagsAsString () const;
|
||||
inline Net::Type getType () const;
|
||||
inline Net::Direction getDirection () const;
|
||||
inline bool hasComponent ( Component* ) const;
|
||||
void add ( Component* );
|
||||
void add ( Occurrence );
|
||||
void merge ( Equipotential* );
|
||||
void consolidate ();
|
||||
void clear ();
|
||||
inline const ComponentSet& getComponents () const;
|
||||
inline const std::vector<Occurrence>& getChilds () const;
|
||||
Record* _getRecord () const;
|
||||
std::string _getString () const;
|
||||
std::string _getTypeName () const;
|
||||
protected:
|
||||
virtual void _postCreate ();
|
||||
virtual void _preDestroy ();
|
||||
private:
|
||||
Equipotential ( Cell* );
|
||||
~Equipotential ();
|
||||
private:
|
||||
Equipotential ( const Equipotential& ) = delete;
|
||||
Equipotential& operator= ( const Equipotential& ) = delete;
|
||||
private:
|
||||
Cell* _owner;
|
||||
Box _boundingBox;
|
||||
|
@ -82,9 +85,11 @@ namespace Tramontana {
|
|||
std::string _name;
|
||||
Net::Type _type;
|
||||
Net::Direction _direction;
|
||||
uint32_t _netCount;
|
||||
bool _isExternal;
|
||||
bool _isGlobal;
|
||||
bool _isAutomatic;
|
||||
bool _hasFused;
|
||||
};
|
||||
|
||||
|
||||
|
@ -92,6 +97,8 @@ namespace Tramontana {
|
|||
inline bool Equipotential::isEmpty () const { return _components.empty() and _childs.empty(); }
|
||||
inline const ComponentSet& Equipotential::getComponents () const { return _components; }
|
||||
inline std::string Equipotential::getName () const { return _name; }
|
||||
inline Net::Type Equipotential::getType () const { return _type; }
|
||||
inline Net::Direction Equipotential::getDirection () const { return _direction; }
|
||||
inline const std::vector<Occurrence>& Equipotential::getChilds () const { return _childs; }
|
||||
|
||||
inline bool Equipotential::hasComponent ( Component* component ) const
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#pragma once
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "hurricane/BasicLayer.h"
|
||||
namespace Hurricane {
|
||||
class Net;
|
||||
|
@ -33,22 +34,27 @@ namespace Tramontana {
|
|||
using Hurricane::Box;
|
||||
using Hurricane::DbU;
|
||||
using Hurricane::Cell;
|
||||
using Hurricane::Layer;
|
||||
using Hurricane::BasicLayer;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Tramontana::SweepLine".
|
||||
|
||||
class SweepLine {
|
||||
private:
|
||||
typedef std::map<Layer::Mask,TileIntvTree> IntervalTrees;
|
||||
private:
|
||||
class Element {
|
||||
public:
|
||||
inline Element ( Tile*, uint32_t flags );
|
||||
inline bool operator< ( const Element& ) const;
|
||||
inline bool isLeftEdge () const;
|
||||
inline Tile* getTile () const;
|
||||
inline DbU::Unit getX () const;
|
||||
inline DbU::Unit getY () const;
|
||||
inline DbU::Unit getId () const;
|
||||
inline Element ( Tile*, uint32_t flags );
|
||||
inline bool operator< ( const Element& ) const;
|
||||
inline bool isLeftEdge () const;
|
||||
inline Tile* getTile () const;
|
||||
inline DbU::Unit getX () const;
|
||||
inline DbU::Unit getY () const;
|
||||
inline DbU::Unit getId () const;
|
||||
inline Layer::Mask getMask () const;
|
||||
private:
|
||||
Tile* _tile;
|
||||
uint32_t _flags;
|
||||
|
@ -58,7 +64,7 @@ namespace Tramontana {
|
|||
~SweepLine ();
|
||||
inline Cell* getCell ();
|
||||
void run ();
|
||||
void loadTiles ( const BasicLayer* );
|
||||
void loadTiles ();
|
||||
void mergeEquipotentials ();
|
||||
Record* _getRecord () const;
|
||||
std::string _getString () const;
|
||||
|
@ -69,22 +75,24 @@ namespace Tramontana {
|
|||
private:
|
||||
TramontanaEngine* _tramontana;
|
||||
std::vector<Element> _tiles;
|
||||
TileIntvTree _intervalTree;
|
||||
IntervalTrees _intervalTrees;
|
||||
};
|
||||
|
||||
|
||||
// SweepLine::Element.
|
||||
inline SweepLine::Element::Element ( Tile* tile, uint32_t flags ) : _tile(tile), _flags(flags) { }
|
||||
inline bool SweepLine::Element::isLeftEdge () const { return _flags & Tile::LeftEdge; }
|
||||
inline Tile* SweepLine::Element::getTile () const { return _tile; }
|
||||
inline DbU::Unit SweepLine::Element::getX () const { return isLeftEdge() ? _tile->getLeftEdge() : _tile->getRightEdge(); }
|
||||
inline DbU::Unit SweepLine::Element::getY () const { return _tile->getBoundingBox().getYMin(); }
|
||||
inline DbU::Unit SweepLine::Element::getId () const { return _tile->getId(); }
|
||||
inline SweepLine::Element::Element ( Tile* tile, uint32_t flags ) : _tile(tile), _flags(flags) { }
|
||||
inline bool SweepLine::Element::isLeftEdge () const { return _flags & Tile::LeftEdge; }
|
||||
inline Tile* SweepLine::Element::getTile () const { return _tile; }
|
||||
inline DbU::Unit SweepLine::Element::getX () const { return isLeftEdge() ? _tile->getLeftEdge() : _tile->getRightEdge(); }
|
||||
inline DbU::Unit SweepLine::Element::getY () const { return _tile->getBoundingBox().getYMin(); }
|
||||
inline DbU::Unit SweepLine::Element::getId () const { return _tile->getId(); }
|
||||
inline Layer::Mask SweepLine::Element::getMask () const { return _tile->getMask(); }
|
||||
|
||||
inline bool SweepLine::Element::operator< ( const Element& rhs ) const
|
||||
{
|
||||
if (getX() != rhs.getX()) return (getX() < rhs.getX());
|
||||
if (getY() != rhs.getY()) return (getY() < rhs.getY());
|
||||
if (getMask() != rhs.getMask()) return (getMask() < rhs.getMask());
|
||||
return getId() < rhs.getId();
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,8 @@ namespace Tramontana {
|
|||
Tile* getRoot ( uint32_t flags=Compress );
|
||||
inline Component* getComponent () const;
|
||||
inline Occurrence getOccurrence () const;
|
||||
inline const BasicLayer* getLayer () const;
|
||||
inline Layer::Mask getMask () const;
|
||||
inline const BasicLayer* getLayer () const;
|
||||
inline const Box& getBoundingBox () const;
|
||||
inline Equipotential* getEquipotential () const;
|
||||
inline DbU::Unit getLeftEdge () const;
|
||||
|
@ -110,6 +111,7 @@ namespace Tramontana {
|
|||
inline unsigned int Tile::getId () const { return getComponent()->getId(); }
|
||||
inline Component* Tile::getComponent () const { return dynamic_cast<Component*>( _occurrence.getEntity() ); }
|
||||
inline Occurrence Tile::getOccurrence () const { return _occurrence; }
|
||||
inline Layer::Mask Tile::getMask () const { return _layer->getMask(); }
|
||||
inline const BasicLayer* Tile::getLayer () const { return _layer; }
|
||||
inline const Box& Tile::getBoundingBox () const { return _boundingBox; }
|
||||
inline Equipotential* Tile::getEquipotential () const { return _equipotential; }
|
||||
|
|
Loading…
Reference in New Issue