Add complete support for Equipotential selection in the Controller.
This commit is contained in:
parent
e5d9c8808b
commit
a0911be50a
|
@ -18,12 +18,19 @@
|
|||
set( pyIncludes tramontana/PyTramontanaEngine.h
|
||||
tramontana/PyGraphicTramontanaEngine.h
|
||||
)
|
||||
set( mocIncludes tramontana/GraphicTramontanaEngine.h )
|
||||
set( mocIncludes tramontana/GraphicTramontanaEngine.h
|
||||
tramontana/EquipotentialsModel.h
|
||||
tramontana/EquipotentialsWidget.h
|
||||
tramontana/TabEquipotentials.h
|
||||
)
|
||||
set( cpps Tile.cpp
|
||||
SweepLine.cpp
|
||||
Equipotential.cpp
|
||||
TramontanaEngine.cpp
|
||||
GraphicTramontanaEngine.cpp
|
||||
EquipotentialsModel.cpp
|
||||
EquipotentialsWidget.cpp
|
||||
TabEquipotentials.cpp
|
||||
)
|
||||
set( pyCpps PyTramontana.cpp
|
||||
PyTramontanaEngine.cpp
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
|
||||
#include <iomanip>
|
||||
#include <set>
|
||||
#include "hurricane/utilities/Path.h"
|
||||
#include "hurricane/DebugSession.h"
|
||||
#include "hurricane/UpdateSession.h"
|
||||
|
@ -39,6 +40,32 @@
|
|||
#include "tramontana/TramontanaEngine.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using Hurricane::Net;
|
||||
|
||||
|
||||
class NetCompareByName {
|
||||
public:
|
||||
bool operator() ( const Net* lhs, const Net* rhs ) const;
|
||||
};
|
||||
|
||||
|
||||
bool NetCompareByName::operator() ( const Net* lhs, const Net* rhs ) const
|
||||
{
|
||||
if (lhs->isFused () != rhs->isFused ()) return rhs->isFused();
|
||||
if (lhs->isAutomatic() != rhs->isAutomatic()) return rhs->isAutomatic();
|
||||
if (lhs->isGlobal () != rhs->isGlobal ()) return rhs->isGlobal();
|
||||
|
||||
if (lhs->getName().size() != rhs->getName().size())
|
||||
return lhs->getName().size() < rhs->getName().size();
|
||||
return lhs->getName() < rhs->getName();
|
||||
}
|
||||
|
||||
|
||||
} // Anonymous namespace.
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using std::cout;
|
||||
|
@ -54,6 +81,7 @@ namespace Tramontana {
|
|||
using std::ostringstream;
|
||||
using std::setprecision;
|
||||
using std::vector;
|
||||
using std::set;
|
||||
using std::make_pair;
|
||||
using Hurricane::dbo_ptr;
|
||||
using Hurricane::UpdateSession;
|
||||
|
@ -66,6 +94,7 @@ namespace Tramontana {
|
|||
using Hurricane::Box;
|
||||
using Hurricane::Layer;
|
||||
using Hurricane::Entity;
|
||||
using Hurricane::Net;
|
||||
using Hurricane::Horizontal;
|
||||
using Hurricane::Vertical;
|
||||
using Hurricane::RoutingPad;
|
||||
|
@ -77,11 +106,20 @@ namespace Tramontana {
|
|||
// Class : "Tramontana::Equipotential".
|
||||
|
||||
|
||||
const char* defaultName = "Unamed (please call consolidate())";
|
||||
|
||||
|
||||
Equipotential::Equipotential ( Cell* owner )
|
||||
: _owner (owner)
|
||||
, _boundingBox()
|
||||
, _components ()
|
||||
, _childs ()
|
||||
, _name (defaultName)
|
||||
, _type (Net::Type::UNDEFINED)
|
||||
, _direction (Net::Direction::DirUndefined)
|
||||
, _isExternal (false)
|
||||
, _isGlobal (false)
|
||||
, _isAutomatic(false)
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -154,6 +192,34 @@ 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();
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void Equipotential::clear ()
|
||||
{
|
||||
_components.clear();
|
||||
|
@ -168,7 +234,9 @@ namespace Tramontana {
|
|||
string Equipotential::_getString () const
|
||||
{
|
||||
ostringstream os;
|
||||
os << "<Equipotential id:" << getId() << " " << _owner->getName() << ">";
|
||||
os << "<Equipotential id:" << getId()
|
||||
//<< " " << getName()
|
||||
<< " " << _owner->getName() << ">";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
@ -181,6 +249,7 @@ namespace Tramontana {
|
|||
record->add( getSlot( "_boundingBox", &_boundingBox ) );
|
||||
record->add( getSlot( "_components" , &_components ) );
|
||||
record->add( getSlot( "_childs" , &_childs ) );
|
||||
//record->add( getSlot( "_name" , &_name ) );
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | T r a m o n t a n a - Extractor & LVX |
|
||||
// | |
|
||||
// | Algorithm : Christian MASSON |
|
||||
// | First impl. : Yifei WU |
|
||||
// | Second impl. : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./EquipotentialsModel.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include <QFont>
|
||||
#include <QApplication>
|
||||
#include "hurricane/Name.h"
|
||||
#include "hurricane/Net.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "hurricane/viewer/Graphics.h"
|
||||
#include "tramontana/EquipotentialsModel.h"
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using Hurricane::Graphics;
|
||||
|
||||
|
||||
EquipotentialsModel::EquipotentialsModel ( QObject* parent )
|
||||
: QAbstractTableModel(parent)
|
||||
, _cell (nullptr)
|
||||
, _equipotentials ()
|
||||
{ }
|
||||
|
||||
|
||||
QVariant EquipotentialsModel::data ( const QModelIndex& index, int role ) const
|
||||
{
|
||||
static QFont nameFont = Graphics::getFixedFont ( QFont::Bold );
|
||||
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;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (not index.isValid()) return QVariant ();
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
int row = index.row ();
|
||||
return QString::fromStdString( _equipotentials[row]->getName() );
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
QVariant EquipotentialsModel::headerData ( int section
|
||||
, Qt::Orientation orientation
|
||||
, int role ) const
|
||||
{
|
||||
if (orientation == Qt::Vertical) return QVariant();
|
||||
|
||||
static QFont headerFont = Graphics::getFixedFont( QFont::Bold, false, false, +0 );
|
||||
|
||||
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 );
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
int EquipotentialsModel::rowCount ( const QModelIndex& parent ) const
|
||||
{
|
||||
return _equipotentials.size();
|
||||
}
|
||||
|
||||
|
||||
int EquipotentialsModel::columnCount ( const QModelIndex& parent ) const
|
||||
{
|
||||
return 1;
|
||||
//return (_equipotentials) ? _equipotentials->getColumnCount() : 1;
|
||||
}
|
||||
|
||||
|
||||
const Equipotential* EquipotentialsModel::getEqui ( int row )
|
||||
{
|
||||
if (row >= (int)_equipotentials.size()) return nullptr;
|
||||
return _equipotentials[ row ];
|
||||
}
|
||||
|
||||
|
||||
void EquipotentialsModel::setCell ( Cell* cell )
|
||||
{
|
||||
if (_cell != cell) {
|
||||
emit layoutAboutToBeChanged ();
|
||||
|
||||
if (_cell) _equipotentials.clear();
|
||||
_cell = cell;
|
||||
|
||||
if (_cell) {
|
||||
TramontanaEngine* tramontana = TramontanaEngine::get( _cell );
|
||||
if (tramontana) {
|
||||
for ( Equipotential* equi : tramontana->getEquipotentials() )
|
||||
_equipotentials.push_back( equi );
|
||||
}
|
||||
}
|
||||
|
||||
emit layoutChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // Tramontana namespace.
|
|
@ -0,0 +1,230 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | T r a m o n t a n a - Extractor & LVX |
|
||||
// | |
|
||||
// | Algorithm : Christian MASSON |
|
||||
// | First impl. : Yifei WU |
|
||||
// | Second impl. : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./EquipotentialsWidget.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include <QFontMetrics>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QHeaderView>
|
||||
#include <QKeyEvent>
|
||||
#include <QGroupBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QAction>
|
||||
#include <QModelIndex>
|
||||
#include "hurricane/Commons.h"
|
||||
#include "hurricane/viewer/Graphics.h"
|
||||
#include "tramontana/EquipotentialsModel.h"
|
||||
#include "tramontana/EquipotentialsWidget.h"
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using Hurricane::Bug;
|
||||
using Hurricane::Graphics;
|
||||
|
||||
|
||||
EquipotentialsWidget::EquipotentialsWidget ( QWidget* parent )
|
||||
: QWidget (parent)
|
||||
, _cellWidget (NULL)
|
||||
, _cell (NULL)
|
||||
, _baseModel (new EquipotentialsModel(this))
|
||||
, _sortModel (new QSortFilterProxyModel(this))
|
||||
, _view (new QTableView(this))
|
||||
, _rowHeight (20)
|
||||
, _selecteds ()
|
||||
, _forceReselect(false)
|
||||
{
|
||||
setAttribute( Qt::WA_DeleteOnClose );
|
||||
setAttribute( Qt::WA_QuitOnClose, false );
|
||||
setContextMenuPolicy( Qt::ActionsContextMenu );
|
||||
|
||||
_rowHeight = QFontMetrics( Graphics::getFixedFont() ).height() + 4;
|
||||
|
||||
_sortModel->setSourceModel ( _baseModel );
|
||||
_sortModel->setDynamicSortFilter( true );
|
||||
_sortModel->setFilterKeyColumn ( 0 );
|
||||
|
||||
_view->setShowGrid ( false );
|
||||
_view->setAlternatingRowColors( true );
|
||||
_view->setSelectionBehavior ( QAbstractItemView::SelectRows );
|
||||
_view->setSortingEnabled ( true );
|
||||
_view->setModel ( _sortModel );
|
||||
|
||||
QHeaderView* horizontalHeader = _view->horizontalHeader();
|
||||
horizontalHeader->setDefaultAlignment ( Qt::AlignHCenter );
|
||||
horizontalHeader->setMinimumSectionSize( (Graphics::isHighDpi()) ? 300 : 150 );
|
||||
horizontalHeader->setStretchLastSection( true );
|
||||
|
||||
QHeaderView* verticalHeader = _view->verticalHeader();
|
||||
verticalHeader->setVisible( false );
|
||||
verticalHeader->setDefaultSectionSize( _rowHeight );
|
||||
|
||||
// verticalHeader->setStyleSheet( "QHeaderView::section {"
|
||||
// "padding-bottom: 0px;"
|
||||
// "padding-top: 0px;"
|
||||
// "padding-left: 0px;"
|
||||
// "padding-right: 1px;"
|
||||
// "margin: 0px;"
|
||||
// "}"
|
||||
// );
|
||||
|
||||
_filterPatternLineEdit = new QLineEdit( this );
|
||||
QLabel* filterPatternLabel = new QLabel( tr("&Filter pattern:"), this );
|
||||
filterPatternLabel->setBuddy( _filterPatternLineEdit );
|
||||
|
||||
QGridLayout* gLayout = new QGridLayout();
|
||||
gLayout->addWidget( _view , 1, 0, 1, 2 );
|
||||
gLayout->addWidget( filterPatternLabel , 2, 0 );
|
||||
gLayout->addWidget( _filterPatternLineEdit, 2, 1 );
|
||||
|
||||
setLayout( gLayout );
|
||||
|
||||
QAction* fitAction = new QAction( tr("&Fit to Equi"), this );
|
||||
fitAction->setShortcut ( QKeySequence(tr("CTRL+F")) );
|
||||
fitAction->setStatusTip( tr("Fit the view to the Equipotentials's bounding box") );
|
||||
addAction( fitAction );
|
||||
|
||||
connect( _filterPatternLineEdit , SIGNAL(textChanged(const QString &))
|
||||
, this , SLOT (textFilterChanged()) );
|
||||
connect( _view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&))
|
||||
, this , SLOT (updateSelecteds (const QItemSelection&,const QItemSelection&)) );
|
||||
//connect( fitAction, SIGNAL(triggered()), this, SLOT(fitToEqui()) );
|
||||
|
||||
resize( 300, 300 );
|
||||
}
|
||||
|
||||
|
||||
void EquipotentialsWidget::goTo ( int delta )
|
||||
{
|
||||
if ( delta == 0 ) return;
|
||||
|
||||
QModelIndex newIndex = _sortModel->index( _view->currentIndex().row()+delta, 0, QModelIndex() );
|
||||
if (newIndex.isValid())
|
||||
_view->selectRow( newIndex.row() );
|
||||
}
|
||||
|
||||
|
||||
void EquipotentialsWidget::updateSelecteds ()
|
||||
{
|
||||
_forceReselect = true;
|
||||
|
||||
QItemSelection dummy;
|
||||
updateSelecteds( dummy, dummy );
|
||||
}
|
||||
|
||||
|
||||
void EquipotentialsWidget::updateSelecteds ( const QItemSelection& , const QItemSelection& )
|
||||
{
|
||||
if (_cellWidget) _cellWidget->openRefreshSession ();
|
||||
|
||||
_selecteds.resetAccesses ();
|
||||
|
||||
const Equipotential* equi = nullptr;
|
||||
QModelIndexList iList = _view->selectionModel()->selectedRows();
|
||||
for ( int i=0 ; i<iList.size() ; i++ ) {
|
||||
equi = _baseModel->getEqui( _sortModel->mapToSource(iList[i]).row() );
|
||||
if ( equi )
|
||||
_selecteds.insert( equi );
|
||||
}
|
||||
|
||||
if (_forceReselect) {
|
||||
_selecteds.forceInserteds();
|
||||
_forceReselect = false;
|
||||
}
|
||||
|
||||
SelectedEquiSet::iterator remove;
|
||||
SelectedEquiSet::iterator isel = _selecteds.begin ();
|
||||
while ( isel != _selecteds.end() ) {
|
||||
switch ( isel->getAccesses() ) {
|
||||
case 1: break;
|
||||
case 64:
|
||||
emit equipotentialSelect ( isel->getEqui()->getComponents() );
|
||||
break;
|
||||
case 0:
|
||||
emit equipotentialUnselect ( isel->getEqui()->getComponents() );
|
||||
remove = isel;
|
||||
++isel;
|
||||
_selecteds.erase( remove );
|
||||
continue;
|
||||
default:
|
||||
cerr << Bug( "EquipotentialsWidget::updateSelecteds(): invalid code %d"
|
||||
, isel->getAccesses()) << endl;
|
||||
}
|
||||
++isel;
|
||||
}
|
||||
|
||||
if (_cellWidget) _cellWidget->closeRefreshSession ();
|
||||
}
|
||||
|
||||
|
||||
void EquipotentialsWidget::textFilterChanged ()
|
||||
{
|
||||
_sortModel->setFilterRegExp( _filterPatternLineEdit->text() );
|
||||
//updateSelecteds ();
|
||||
}
|
||||
|
||||
|
||||
// void EquipotentialsWidget::fitToNet ()
|
||||
// {
|
||||
// const Equipotential* equi = _baseModel->getEqui( _sortModel->mapToSource(_view->currentIndex()).row() );
|
||||
// if (equi) emit netFitted ( equi );
|
||||
// }
|
||||
|
||||
|
||||
void EquipotentialsWidget::setCellWidget ( CellWidget* cw )
|
||||
{
|
||||
if (_cellWidget) {
|
||||
disconnect( this, 0, _cellWidget, 0 );
|
||||
}
|
||||
|
||||
_cellWidget = cw;
|
||||
if (_cellWidget) {
|
||||
setCell( _cellWidget->getCell() );
|
||||
//connect( this, SIGNAL(netFitted(const Equi*)), _cellWidget, SLOT(fitToEqui (const Equi*)) );
|
||||
} else
|
||||
setCell( nullptr );
|
||||
}
|
||||
|
||||
|
||||
void EquipotentialsWidget::setCell ( Cell* cell )
|
||||
{
|
||||
_cell = cell;
|
||||
_view->setVisible( false );
|
||||
_view->selectionModel()->clear();
|
||||
_baseModel->setCell( cell );
|
||||
|
||||
string windowTitle = "Equis" + getString(cell);
|
||||
setWindowTitle( tr(windowTitle.c_str()) );
|
||||
|
||||
QHeaderView* header = _view->horizontalHeader();
|
||||
|
||||
_view->selectRow( 0 );
|
||||
for ( int i=0 ; i<_baseModel->columnCount() ; ++i ) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
header->setSectionResizeMode( i, QHeaderView::Interactive );
|
||||
#else
|
||||
header->setResizeMode( i, QHeaderView::Interactive );
|
||||
#endif
|
||||
_view->resizeColumnToContents( i );
|
||||
}
|
||||
_view->setVisible( true );
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -36,6 +36,7 @@
|
|||
#include <crlcore/Utilities.h>
|
||||
#include <crlcore/AllianceFramework.h>
|
||||
#include <anabatic/GCell.h>
|
||||
#include <tramontana/TabEquipotentials.h>
|
||||
#include <tramontana/GraphicTramontanaEngine.h>
|
||||
|
||||
|
||||
|
@ -100,7 +101,6 @@ namespace Tramontana {
|
|||
fontScale = -5;
|
||||
halfHeight = 9;
|
||||
halfWidth = 39;
|
||||
|
||||
}
|
||||
|
||||
painter.setPen ( pen );
|
||||
|
@ -188,6 +188,14 @@ namespace Tramontana {
|
|||
, "Run the extractor"
|
||||
, std::bind(&GraphicTramontanaEngine::_extract,this)
|
||||
);
|
||||
|
||||
ControllerWidget* controller = viewer->getControllerWidget();
|
||||
if (controller) {
|
||||
TabEquipotentials* tabEqui = new TabEquipotentials ();
|
||||
tabEqui->setObjectName( "controller.tabEquipotentials" );
|
||||
tabEqui->setCellWidget( viewer->getCellWidget() );
|
||||
controller->insertTabAfter( "controller.tabNetlist", tabEqui, "Equipotentials" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -133,6 +133,7 @@ namespace Tramontana {
|
|||
|
||||
void SweepLine::mergeEquipotentials ()
|
||||
{
|
||||
cerr << "Tramontana::mergeEquipotentials()" << endl;
|
||||
Tile::timeTick();
|
||||
for ( Tile* tile : Tile::getAllTiles() ) {
|
||||
tile->getRoot( Tile::MergeEqui );
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | T r a m o n t a n a - Extractor & LVX |
|
||||
// | |
|
||||
// | Algorithm : Christian MASSON |
|
||||
// | First impl. : Yifei WU |
|
||||
// | Second impl. : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./TabEquipotentials.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include <QAction>
|
||||
#include <QFrame>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include "tramontana/TabEquipotentials.h"
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using Hurricane::Graphics;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Tramontana::TabEquipotentials".
|
||||
|
||||
|
||||
TabEquipotentials::TabEquipotentials ( QWidget* parent )
|
||||
: ControllerTab (parent)
|
||||
, _browser (new EquipotentialsWidget())
|
||||
, _syncEquipotentials (new QCheckBox())
|
||||
, _syncSelection (new QCheckBox())
|
||||
, _cwCumulativeSelection(false)
|
||||
{
|
||||
_browser->setObjectName ( "controller.tabEquipotentials.browser" );
|
||||
|
||||
QVBoxLayout* wLayout = new QVBoxLayout ();
|
||||
wLayout->setContentsMargins( 10, 0, 10, 0 );
|
||||
wLayout->setSpacing( 0 );
|
||||
|
||||
_syncEquipotentials->setText ( tr("Sync Equipotentials") );
|
||||
_syncEquipotentials->setChecked( false );
|
||||
_syncEquipotentials->setFont ( Graphics::getFixedFont(QFont::Bold,false,false) );
|
||||
connect( _syncEquipotentials, SIGNAL(toggled(bool)), this, SLOT(setSyncEquipotentials(bool)) );
|
||||
|
||||
_syncSelection->setText ( tr("Sync Selection") );
|
||||
_syncSelection->setChecked( false );
|
||||
_syncSelection->setFont ( Graphics::getFixedFont(QFont::Bold,false,false) );
|
||||
connect( _syncSelection, SIGNAL(toggled(bool)), this, SLOT(setSyncSelection(bool)) );
|
||||
|
||||
QHBoxLayout* commands = new QHBoxLayout ();
|
||||
commands->setContentsMargins( 0, 0, 0, 0 );
|
||||
commands->addStretch();
|
||||
commands->addWidget ( _syncEquipotentials );
|
||||
commands->addStretch();
|
||||
commands->addWidget ( _syncSelection );
|
||||
commands->addStretch();
|
||||
wLayout->addLayout ( commands );
|
||||
|
||||
QFrame* separator = new QFrame ();
|
||||
separator->setFrameShape ( QFrame::HLine );
|
||||
separator->setFrameShadow( QFrame::Sunken );
|
||||
wLayout->addWidget( separator );
|
||||
wLayout->addWidget( _browser );
|
||||
|
||||
setLayout( wLayout );
|
||||
}
|
||||
|
||||
|
||||
void TabEquipotentials::setSyncEquipotentials ( bool state )
|
||||
{
|
||||
if (state and getCellWidget()) {
|
||||
_browser->setCell( getCellWidget()->getCell() );
|
||||
} else {
|
||||
_browser->setCell( nullptr );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TabEquipotentials::setSyncSelection ( bool state )
|
||||
{
|
||||
if (state and getCellWidget() and _syncEquipotentials->isChecked()) {
|
||||
_cwCumulativeSelection = getCellWidget()->cumulativeSelection();
|
||||
if (not _cwCumulativeSelection) {
|
||||
getCellWidget()->openRefreshSession ();
|
||||
getCellWidget()->unselectAll ();
|
||||
getCellWidget()->closeRefreshSession ();
|
||||
}
|
||||
getCellWidget()->setShowSelection( true );
|
||||
connect( _browser, SIGNAL(equipotentialSelect (const ComponentSet&)), getCellWidget(), SLOT(selectSet (const ComponentSet&)) );
|
||||
connect( _browser, SIGNAL(equipotentialUnselect(const ComponentSet&)), getCellWidget(), SLOT(unselectSet(const ComponentSet&)) );
|
||||
_browser->updateSelecteds();
|
||||
} else {
|
||||
getCellWidget()->setShowSelection( false );
|
||||
getCellWidget()->setCumulativeSelection( _cwCumulativeSelection );
|
||||
_browser->disconnect( getCellWidget(), SLOT(selectSet (const ComponentSet&)) );
|
||||
_browser->disconnect( getCellWidget(), SLOT(unselectSet(const ComponentSet&)) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TabEquipotentials::setCell ( Cell* cell )
|
||||
{
|
||||
setSyncEquipotentials( _syncEquipotentials->isChecked() );
|
||||
}
|
||||
|
||||
|
||||
void TabEquipotentials::setCellWidget ( CellWidget* cellWidget )
|
||||
{
|
||||
if (getCellWidget() != cellWidget) {
|
||||
ControllerTab::setCellWidget( cellWidget );
|
||||
_browser->setCellWidget( cellWidget );
|
||||
if (getCellWidget()) {
|
||||
connect( getCellWidget(), SIGNAL(cellChanged(Cell*)), this, SLOT(setCell(Cell*)) );
|
||||
}
|
||||
setSyncEquipotentials( _syncEquipotentials->isChecked() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TabEquipotentials::cellPreModificate ()
|
||||
{
|
||||
_browser->setCell( nullptr );
|
||||
}
|
||||
|
||||
|
||||
void TabEquipotentials::cellPostModificate ()
|
||||
{
|
||||
setSyncEquipotentials( _syncEquipotentials->isChecked() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -157,15 +157,17 @@ namespace Tramontana {
|
|||
|
||||
if (flags & MergeEqui) {
|
||||
Equipotential* rootEqui = root->getEquipotential();
|
||||
if (not rootEqui)
|
||||
if (not rootEqui) {
|
||||
rootEqui = root->newEquipotential();
|
||||
}
|
||||
|
||||
Tile* current = this;
|
||||
while ( current ) {
|
||||
if (current->isUpToDate()) break;
|
||||
if (current->getEquipotential()) {
|
||||
if (current->getEquipotential() != rootEqui)
|
||||
if (current->getEquipotential() != rootEqui) {
|
||||
rootEqui->merge( current->getEquipotential() );
|
||||
}
|
||||
} else {
|
||||
rootEqui->add( current->getOccurrence() );
|
||||
}
|
||||
|
|
|
@ -148,6 +148,7 @@ namespace Tramontana {
|
|||
cerr << "TramontanaEngine::extract() called on " << getCell() << endl;
|
||||
SweepLine sweepLine ( this );
|
||||
sweepLine.run();
|
||||
consolidate();
|
||||
showEquipotentials();
|
||||
}
|
||||
|
||||
|
@ -163,6 +164,15 @@ namespace Tramontana {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void TramontanaEngine::consolidate ()
|
||||
{
|
||||
cerr << "Tramontana::consolidate()" << endl;
|
||||
for ( Equipotential* equi : _equipotentials )
|
||||
equi->consolidate();
|
||||
}
|
||||
|
||||
|
||||
void TramontanaEngine::add ( Equipotential* equi )
|
||||
{
|
||||
_equipotentials.insert( equi );
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace Tramontana {
|
|||
using Hurricane::Net;
|
||||
using Hurricane::Cell;
|
||||
using Hurricane::Component;
|
||||
using Hurricane::ComponentSet;
|
||||
using Hurricane::Occurrence;
|
||||
|
||||
|
||||
|
@ -47,16 +48,17 @@ namespace Tramontana {
|
|||
class Equipotential : public Entity {
|
||||
public:
|
||||
typedef Entity Super;
|
||||
typedef std::set<Component*,DBo::CompareById> ComponentSet;
|
||||
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;
|
||||
|
@ -77,13 +79,20 @@ namespace Tramontana {
|
|||
Box _boundingBox;
|
||||
ComponentSet _components;
|
||||
std::vector<Occurrence> _childs;
|
||||
std::string _name;
|
||||
Net::Type _type;
|
||||
Net::Direction _direction;
|
||||
bool _isExternal;
|
||||
bool _isGlobal;
|
||||
bool _isAutomatic;
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline bool Equipotential::isEmpty () const { return _components.empty() and _childs.empty(); }
|
||||
inline const Equipotential::ComponentSet& Equipotential::getComponents () const { return _components; }
|
||||
inline const std::vector<Occurrence>& Equipotential::getChilds () const { return _childs; }
|
||||
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 const std::vector<Occurrence>& Equipotential::getChilds () const { return _childs; }
|
||||
|
||||
inline bool Equipotential::hasComponent ( Component* component ) const
|
||||
{ return _components.find( component ) != _components.end(); }
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | T r a m o n t a n a - Extractor & LVX |
|
||||
// | |
|
||||
// | Algorithm : Christian MASSON |
|
||||
// | First impl. : Yifei WU |
|
||||
// | Second impl. : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./tramontana/EquipotentialsModel.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <QFont>
|
||||
#include <QApplication>
|
||||
#include <QAbstractTableModel>
|
||||
#include "hurricane/Commons.h"
|
||||
#include "hurricane/Name.h"
|
||||
#include "hurricane/Net.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "hurricane/viewer/Graphics.h"
|
||||
#include "tramontana/Equipotential.h"
|
||||
#include "tramontana/TramontanaEngine.h"
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using Hurricane::Cell;
|
||||
|
||||
|
||||
class EquipotentialsModel : public QAbstractTableModel {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
EquipotentialsModel ( QObject* parent=NULL );
|
||||
void setCell ( Cell* cell );
|
||||
int rowCount ( const QModelIndex& parent=QModelIndex() ) const;
|
||||
int columnCount ( const QModelIndex& parent=QModelIndex() ) const;
|
||||
QVariant data ( const QModelIndex& index, int role=Qt::DisplayRole ) const;
|
||||
QVariant headerData ( int section, Qt::Orientation orientation, int role=Qt::DisplayRole ) const;
|
||||
inline Cell* getCell ();
|
||||
const Equipotential* getEqui ( int row );
|
||||
|
||||
private:
|
||||
Cell* _cell;
|
||||
std::vector<Equipotential*> _equipotentials;
|
||||
};
|
||||
|
||||
|
||||
// Inline Functions.
|
||||
|
||||
inline Cell* EquipotentialsModel::getCell () { return _cell; }
|
||||
|
||||
|
||||
} // Hurricane namespace.
|
|
@ -0,0 +1,163 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | T r a m o n t a n a - Extractor & LVX |
|
||||
// | |
|
||||
// | Algorithm : Christian MASSON |
|
||||
// | First impl. : Yifei WU |
|
||||
// | Second impl. : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./tramontana/EquipotentialsWidget.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <set>
|
||||
#include <QWidget>
|
||||
#include <QTableView>
|
||||
#include <QHeaderView>
|
||||
#include <QItemDelegate>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include "hurricane/Commons.h"
|
||||
#include "hurricane/Bug.h"
|
||||
#include "hurricane/viewer/CellWidget.h"
|
||||
#include "hurricane/viewer/CellWidget.h"
|
||||
#include "tramontana/EquipotentialsModel.h"
|
||||
|
||||
|
||||
class QSortFilterProxyModel;
|
||||
class QModelIndex;
|
||||
class QTableView;
|
||||
class QLineEdit;
|
||||
class QComboBox;
|
||||
class QHeaderView;
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using std::string;
|
||||
using std::set;
|
||||
using Hurricane::Cell;
|
||||
using Hurricane::CellWidget;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "SelectedEqui".
|
||||
|
||||
|
||||
class SelectedEqui {
|
||||
public:
|
||||
inline SelectedEqui ();
|
||||
inline SelectedEqui ( const Equipotential*, size_t access=0 );
|
||||
inline const Equipotential* getEqui () const;
|
||||
inline size_t getAccesses () const;
|
||||
inline void incAccesses () const;
|
||||
inline void setInserted () const;
|
||||
inline void resetAccesses () const;
|
||||
private:
|
||||
const Equipotential* _equi;
|
||||
mutable size_t _accesses;
|
||||
};
|
||||
|
||||
|
||||
inline SelectedEqui::SelectedEqui () : _equi(nullptr), _accesses(0) { }
|
||||
inline SelectedEqui::SelectedEqui ( const Equipotential* equi, size_t accesses ) : _equi(equi), _accesses(accesses) { }
|
||||
inline const Equipotential* SelectedEqui::getEqui () const { return _equi; }
|
||||
inline void SelectedEqui::setInserted () const { _accesses = 64; }
|
||||
inline size_t SelectedEqui::getAccesses () const { return _accesses; }
|
||||
inline void SelectedEqui::incAccesses () const { ++_accesses; }
|
||||
inline void SelectedEqui::resetAccesses () const { _accesses = 0; }
|
||||
|
||||
|
||||
struct SelectedEquiCompare {
|
||||
inline bool operator() ( const SelectedEqui& lhs, const SelectedEqui& rhs ) const;
|
||||
};
|
||||
|
||||
|
||||
inline bool SelectedEquiCompare::operator() ( const SelectedEqui& lhs, const SelectedEqui& rhs ) const
|
||||
{
|
||||
return lhs.getEqui()->getId() < rhs.getEqui()->getId();
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "SelectedEquiSet".
|
||||
|
||||
|
||||
class SelectedEquiSet : public set<SelectedEqui,SelectedEquiCompare>{
|
||||
public:
|
||||
void insert ( const Equipotential* );
|
||||
void forceInserteds ();
|
||||
void resetAccesses ();
|
||||
};
|
||||
|
||||
|
||||
inline void SelectedEquiSet::insert ( const Equipotential* equi )
|
||||
{
|
||||
iterator iselected = find(SelectedEqui(equi));
|
||||
if (iselected != end())
|
||||
iselected->incAccesses();
|
||||
else
|
||||
set<SelectedEqui,SelectedEquiCompare>::insert( SelectedEqui(equi,64) );
|
||||
}
|
||||
|
||||
|
||||
inline void SelectedEquiSet::forceInserteds ()
|
||||
{
|
||||
for ( iterator iselected=begin() ; iselected != end() ; ++iselected )
|
||||
iselected->setInserted();
|
||||
}
|
||||
|
||||
|
||||
inline void SelectedEquiSet::resetAccesses ()
|
||||
{
|
||||
for ( iterator iselected=begin() ; iselected != end() ; ++iselected )
|
||||
iselected->resetAccesses();
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "EquipotentialsWidget".
|
||||
|
||||
|
||||
class EquipotentialsWidget : public QWidget {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
EquipotentialsWidget ( QWidget* parent=nullptr );
|
||||
inline Cell* getCell ();
|
||||
void setCellWidget ( CellWidget* );
|
||||
void setCell ( Cell* );
|
||||
void goTo ( int );
|
||||
void updateSelecteds ();
|
||||
signals:
|
||||
void equipotentialSelect ( const ComponentSet& );
|
||||
void equipotentialUnselect ( const ComponentSet& );
|
||||
void netFitted ( const Equipotential* );
|
||||
private slots:
|
||||
void textFilterChanged ();
|
||||
void updateSelecteds ( const QItemSelection& , const QItemSelection& );
|
||||
// void fitToEqui ();
|
||||
|
||||
private:
|
||||
CellWidget* _cellWidget;
|
||||
Cell* _cell;
|
||||
EquipotentialsModel* _baseModel;
|
||||
QSortFilterProxyModel* _sortModel;
|
||||
QTableView* _view;
|
||||
QLineEdit* _filterPatternLineEdit;
|
||||
int _rowHeight;
|
||||
SelectedEquiSet _selecteds;
|
||||
bool _forceReselect;
|
||||
};
|
||||
|
||||
|
||||
inline Cell* EquipotentialsWidget::getCell () { return _cell; }
|
||||
|
||||
|
||||
} // Hurricane namespace.
|
|
@ -0,0 +1,62 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | T r a m o n t a n a - Extractor & LVX |
|
||||
// | |
|
||||
// | Algorithm : Christian MASSON |
|
||||
// | First impl. : Yifei WU |
|
||||
// | Second impl. : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./tramontana/TabEquipotentials.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#pragma once
|
||||
#include "hurricane/viewer/ControllerWidget.h"
|
||||
#include "tramontana/EquipotentialsWidget.h"
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using Hurricane::ControllerTab;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Tramontana::TabEquipotentials".
|
||||
|
||||
|
||||
class TabEquipotentials : public ControllerTab {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
TabEquipotentials ( QWidget* parent=NULL );
|
||||
inline QCheckBox* getSyncEquipotentials ();
|
||||
inline QCheckBox* getSyncSelection ();
|
||||
inline EquipotentialsWidget* getBrowser ();
|
||||
virtual void cellPreModificate ();
|
||||
virtual void cellPostModificate ();
|
||||
public slots:
|
||||
virtual void setCell ( Cell* );
|
||||
virtual void setCellWidget ( CellWidget* );
|
||||
virtual void setSyncEquipotentials ( bool );
|
||||
virtual void setSyncSelection ( bool );
|
||||
|
||||
protected:
|
||||
EquipotentialsWidget* _browser;
|
||||
QCheckBox* _syncEquipotentials;
|
||||
QCheckBox* _syncSelection;
|
||||
bool _cwCumulativeSelection;
|
||||
};
|
||||
|
||||
|
||||
inline EquipotentialsWidget* TabEquipotentials::getBrowser () { return _browser; }
|
||||
inline QCheckBox* TabEquipotentials::getSyncEquipotentials () { return _syncEquipotentials; }
|
||||
inline QCheckBox* TabEquipotentials::getSyncSelection () { return _syncSelection; }
|
||||
|
||||
|
||||
}
|
|
@ -53,9 +53,12 @@ namespace Tramontana {
|
|||
static TramontanaEngine* get ( const Cell* );
|
||||
public:
|
||||
const Name& getName () const;
|
||||
inline const std::set<Equipotential*,DBo::CompareById>
|
||||
getEquipotentials () const;
|
||||
inline void setViewer ( CellViewer* );
|
||||
inline CellViewer* getViewer ();
|
||||
void extract ();
|
||||
void consolidate ();
|
||||
void showEquipotentials () const;
|
||||
void add ( Equipotential* );
|
||||
virtual Record* _getRecord () const;
|
||||
|
@ -81,6 +84,8 @@ namespace Tramontana {
|
|||
|
||||
inline void TramontanaEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; }
|
||||
inline CellViewer* TramontanaEngine::getViewer () { return _viewer; }
|
||||
inline const std::set<Equipotential*,DBo::CompareById>
|
||||
TramontanaEngine::getEquipotentials () const { return _equipotentials; }
|
||||
|
||||
|
||||
} // Tramontana namespace.
|
||||
|
|
Loading…
Reference in New Issue