From ff69a2ef745574887014e44f0c55337d1d734340 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Thu, 23 Jul 2015 00:44:56 +0200 Subject: [PATCH 01/60] Added Hierarchy browser to the Controller. * New: In Hurricane, added hierarchy browser in the controller. The hierarchy is presented as a tree. New MVC, HierarchyInformations, HierarchyModel and HierarchyBrowser. When using a data model which is not directly connect inside the model, we must use the internalPointer field of the QModelIndex. But this field is also used by the QSortFilterproxymodel, this prevent using it with a Tree model. The filter is directly implemented and is specific to each Instance entry. * Change: In CellWidget & CellWidget::State, now store the Cell and a Path, this way we can keep track of the hierarchy when browsing. The Path is in the State and so propagated back to the Controller. * Change: In HierarchyCommand, use the Path with setCell(). --- crlcore/src/ccore/Catalog.cpp | 14 +- crlcore/src/ccore/crlcore/Catalog.h | 3 +- hurricane/src/hurricane/Path.cpp | 13 + hurricane/src/hurricane/hurricane/Cell.h | 13 +- hurricane/src/hurricane/hurricane/Path.h | 1 + hurricane/src/viewer/CMakeLists.txt | 5 + hurricane/src/viewer/CellViewer.cpp | 14 +- hurricane/src/viewer/CellWidget.cpp | 75 +++-- hurricane/src/viewer/Command.cpp | 19 +- hurricane/src/viewer/ControllerWidget.cpp | 114 +++++-- hurricane/src/viewer/HierarchyCommand.cpp | 61 ++-- .../src/viewer/HierarchyInformations.cpp | 288 ++++++++++++++++++ hurricane/src/viewer/HierarchyModel.cpp | 146 +++++++++ hurricane/src/viewer/HierarchyWidget.cpp | 265 ++++++++++++++++ .../src/viewer/hurricane/viewer/CellWidget.h | 58 +++- .../src/viewer/hurricane/viewer/Command.h | 16 +- .../hurricane/viewer/ControllerWidget.h | 82 +++-- .../hurricane/viewer/HierarchyCommand.h | 80 ++--- .../hurricane/viewer/HierarchyInformations.h | 178 +++++++++++ .../viewer/hurricane/viewer/HierarchyModel.h | 85 ++++++ .../viewer/hurricane/viewer/HierarchyWidget.h | 111 +++++++ 21 files changed, 1420 insertions(+), 221 deletions(-) create mode 100644 hurricane/src/viewer/HierarchyInformations.cpp create mode 100644 hurricane/src/viewer/HierarchyModel.cpp create mode 100644 hurricane/src/viewer/HierarchyWidget.cpp create mode 100644 hurricane/src/viewer/hurricane/viewer/HierarchyInformations.h create mode 100644 hurricane/src/viewer/hurricane/viewer/HierarchyModel.h create mode 100644 hurricane/src/viewer/hurricane/viewer/HierarchyWidget.h diff --git a/crlcore/src/ccore/Catalog.cpp b/crlcore/src/ccore/Catalog.cpp index 26bb3723..8f691bd8 100644 --- a/crlcore/src/ccore/Catalog.cpp +++ b/crlcore/src/ccore/Catalog.cpp @@ -27,7 +27,7 @@ using namespace std; namespace CRL { - const char* MissingStateProperty = "%s:\n\n Missing Catalog State Property in cell \"%s\".\n"; + const char* MissingStateProperty = "%s:\n\n Missing Catalog State Property in cell \"%s\".\n"; // ------------------------------------------------------------------- @@ -41,6 +41,17 @@ namespace CRL { } + Cell* Catalog::State::setCell ( Cell* cell ) + { + _cell = cell; + if (_cell) { + if (isPad ()) _cell->setPad ( true ); + if (isFeed()) _cell->setFeed( true ); + } + return _cell; + } + + void Catalog::State::merge ( const State& other ) { if ( (_cell ==NULL) && other._cell ) _cell = other._cell; @@ -78,7 +89,6 @@ namespace CRL { return record; } - // ------------------------------------------------------------------- // Class : "Catalog". diff --git a/crlcore/src/ccore/crlcore/Catalog.h b/crlcore/src/ccore/crlcore/Catalog.h index 73a9f4ed..0b272450 100644 --- a/crlcore/src/ccore/crlcore/Catalog.h +++ b/crlcore/src/ccore/crlcore/Catalog.h @@ -112,7 +112,7 @@ namespace CRL { inline unsigned int getDepth () const; // Modifiers. inline void merge ( const State& other ); - inline Cell* setCell ( Cell* cell ); + Cell* setCell ( Cell* cell ); inline Library* setLibrary ( Library* library ); inline void setDepth ( unsigned int depth ); // Hurricane Management. @@ -193,7 +193,6 @@ namespace CRL { inline bool Catalog::State::setDelete ( bool value ) { return setFlags(Delete ,value); } inline bool Catalog::State::setPhysical ( bool value ) { return setFlags(Physical ,value); } inline bool Catalog::State::setLogical ( bool value ) { return setFlags(Logical ,value); } - inline Cell* Catalog::State::setCell ( Cell* cell ) { return _cell = cell; } inline Library* Catalog::State::setLibrary ( Library* library ) { return _library = library; } inline void Catalog::State::setDepth ( unsigned int depth ) { _depth = depth; } inline Cell* Catalog::State::getCell () const { return _cell; } diff --git a/hurricane/src/hurricane/Path.cpp b/hurricane/src/hurricane/Path.cpp index 72c0253d..36a17c38 100644 --- a/hurricane/src/hurricane/Path.cpp +++ b/hurricane/src/hurricane/Path.cpp @@ -245,6 +245,19 @@ void Path::setNameSeparator(char nameSeparator) SharedPath::setNameSeparator(nameSeparator); } +string Path::getCompactString() const +// ********************************** +{ + if (isEmpty()) return ""; + + string s = "<"; + s += getString(getOwnerCell()->getName()); + s += ":"; + s += getString(_sharedPath->getName()) + ":"; + s += getString(getMasterCell()->getName()) + ">"; + return s; +} + string Path::_getString() const // **************************** { diff --git a/hurricane/src/hurricane/hurricane/Cell.h b/hurricane/src/hurricane/hurricane/Cell.h index 9ef539dd..0ea136a4 100644 --- a/hurricane/src/hurricane/hurricane/Cell.h +++ b/hurricane/src/hurricane/hurricane/Cell.h @@ -88,11 +88,12 @@ class Cell : public Entity { , Terminal = 0x00001000 , FlattenLeaf = 0x00002000 , Pad = 0x00004000 - , FlattenedNets = 0x00008000 - , Placed = 0x00010000 - , Routed = 0x00020000 - , MergedQuadTree = 0x00040000 - , Materialized = 0x00080000 + , Feed = 0x00008000 + , FlattenedNets = 0x00010000 + , Placed = 0x00020000 + , Routed = 0x00040000 + , MergedQuadTree = 0x00080000 + , Materialized = 0x00100000 }; public: @@ -391,6 +392,7 @@ class Cell : public Entity { public: bool isUniquified() const; public: bool isUniquifyMaster() const; public: bool isPad() const {return _flags.isset(Flags::Pad);}; + public: bool isFeed() const {return _flags.isset(Flags::Feed);}; public: bool isFlattenedNets() const {return _flags.isset(Flags::FlattenedNets);}; public: bool isPlaced() const {return _flags.isset(Flags::Placed);}; public: bool isRouted() const {return _flags.isset(Flags::Routed);}; @@ -406,6 +408,7 @@ class Cell : public Entity { public: void setTerminal(bool isTerminal) {_flags.set(Flags::Terminal,isTerminal);}; public: void setFlattenLeaf(bool isFlattenLeaf) {_flags.set(Flags::FlattenLeaf,isFlattenLeaf);}; public: void setPad(bool isPad) {_flags.set(Flags::Pad,isPad);}; + public: void setFeed(bool isFeed) {_flags.set(Flags::Feed,isFeed);}; public: void flattenNets(unsigned int flags=Flags::BuildRings); public: void createRoutingPadRings(unsigned int flags=Flags::BuildRings); public: void setFlags(unsigned int flags) { _flags |= flags; } diff --git a/hurricane/src/hurricane/hurricane/Path.h b/hurricane/src/hurricane/hurricane/Path.h index 80dca474..bd5d4fc6 100644 --- a/hurricane/src/hurricane/hurricane/Path.h +++ b/hurricane/src/hurricane/hurricane/Path.h @@ -97,6 +97,7 @@ class Path { // Others // ****** + public: string getCompactString() const; public: string _getTypeName() const { return _TName("Occurrence"); }; public: string _getString() const; public: Record* _getRecord() const; diff --git a/hurricane/src/viewer/CMakeLists.txt b/hurricane/src/viewer/CMakeLists.txt index 25aed97f..344b80eb 100644 --- a/hurricane/src/viewer/CMakeLists.txt +++ b/hurricane/src/viewer/CMakeLists.txt @@ -36,6 +36,8 @@ hurricane/viewer/SelectionWidget.h hurricane/viewer/NetlistModel.h hurricane/viewer/NetlistWidget.h + hurricane/viewer/HierarchyModel.h + hurricane/viewer/HierarchyWidget.h hurricane/viewer/DisplayFilterWidget.h hurricane/viewer/ControllerWidget.h hurricane/viewer/ScriptWidget.h @@ -104,6 +106,9 @@ NetInformations.cpp NetlistModel.cpp NetlistWidget.cpp + HierarchyInformations.cpp + HierarchyModel.cpp + HierarchyWidget.cpp DisplayFilterWidget.cpp ControllerWidget.cpp ScriptWidget.cpp diff --git a/hurricane/src/viewer/CellViewer.cpp b/hurricane/src/viewer/CellViewer.cpp index 226af418..f7dff57d 100644 --- a/hurricane/src/viewer/CellViewer.cpp +++ b/hurricane/src/viewer/CellViewer.cpp @@ -550,7 +550,10 @@ namespace Hurricane { list< shared_ptr >::iterator istate = _cellHistory.begin(); for ( size_t i=0 ; igetName()).c_str() ); + QString entry = tr("&%1: %2 %3") + .arg(i+1) + .arg( getString((*istate)->getName()).c_str() ) + .arg( (*istate)->getTopPath().getCompactString().c_str() ); _cellHistoryAction[i]->setText ( entry ); _cellHistoryAction[i]->setVisible ( true ); istate++; @@ -689,12 +692,11 @@ namespace Hurricane { void CellViewer::openHistoryCell () { - QAction* historyAction = qobject_cast ( sender() ); - if ( historyAction ) { + QAction* historyAction = qobject_cast( sender() ); + if (historyAction) { list< shared_ptr >::iterator istate = _cellHistory.begin(); - //size_t index = historyAction->data().toUInt(); - //for ( ; index>0 ; index--, istate++ ) - // cerr << "History: " << (*istate)->getName() << endl; + size_t index = historyAction->data().toUInt(); + for ( ; index>0 ; index--, ++istate ); emit stateChanged ( *istate ); } } diff --git a/hurricane/src/viewer/CellWidget.cpp b/hurricane/src/viewer/CellWidget.cpp index 8981c15e..4a4a99d9 100644 --- a/hurricane/src/viewer/CellWidget.cpp +++ b/hurricane/src/viewer/CellWidget.cpp @@ -977,6 +977,7 @@ namespace Hurricane { State* clone = new State(); clone->setCell ( getCell() ); + clone->setTopPath ( getTopPath() ); clone->setCursorStep ( getCursorStep() ); clone->setUnitPower ( getUnitPower() ); clone->setDbuMode ( getDbuMode() ); @@ -1173,6 +1174,12 @@ namespace Hurricane { } + void CellWidget::resetCommands () + { + for ( size_t i=0 ; i<_commands.size() ; ++i ) _commands[i]->reset(); + } + + void CellWidget::pushCursor ( Qt::CursorShape cursor ) { setCursor ( cursor ); @@ -2410,39 +2417,46 @@ namespace Hurricane { } - void CellWidget::setCell ( Cell* cell ) + void CellWidget::setCell ( Cell* cell, Path topPath, unsigned int flags ) { //cerr << "CellWidget::setCell() - " << cell << endl; - if ( cell == getCell() ) return; + if (cell == getCell()) return; - openRefreshSession (); + if (not topPath.isEmpty() and (topPath.getTailInstance()->getMasterCell() != cell)) { + cerr << Warning( "CellWidget::setCell(): Incompatible Path %s with %s." + , topPath.getCompactString().c_str() + , getString(cell->getName()).c_str() ) << endl; + topPath = Path(); + } - shared_ptr state ( new State(cell) ); - setState ( state ); - if ( cell and cell->isTerminal() ) setQueryFilter ( ~0 ); + openRefreshSession(); + + shared_ptr state ( new State(cell,topPath) ); + setState( state, flags ); + if ( cell and cell->isTerminal() ) setQueryFilter( ~0 ); //setRealMode (); - fitToContents ( false ); + fitToContents( false ); - _state->setHistoryEnable ( true ); + _state->setHistoryEnable( true ); - closeRefreshSession (); + closeRefreshSession(); } - void CellWidget::setState ( shared_ptr& state ) + void CellWidget::setState ( shared_ptr& state, unsigned int flags ) { //cerr << "CellWidget::setState() - " << state->getName() << endl; - if ( state == _state ) return; + if (state == _state) return; - openRefreshSession (); - - cellPreModificate (); - _state->getSelection ().clear (); - _state->setCellWidget ( NULL ); - _state->setTopLeft ( getTopLeft() ); + openRefreshSession(); + cellPreModificate(); + if (not (flags & NoResetCommands)) resetCommands(); + _state->getSelection ().clear (); + _state->setCellWidget( NULL ); + _state->setTopLeft ( getTopLeft() ); _cellChanged = true; _state = state; @@ -2453,23 +2467,22 @@ namespace Hurricane { // << DbU::getValueString(_state->getTopLeft().getX()) << "," // << DbU::getValueString(_state->getTopLeft().getY()) << ")" << endl; - _state->setHistoryEnable ( false ); - _state->setCellWidget ( this ); - _drawingQuery .setCell ( getCell() ); - _drawingQuery .setStartLevel ( _state->getStartLevel() ); - _drawingQuery .setStopLevel ( _state->getStopLevel() ); - _textDrawingQuery.setCell ( getCell() ); + _state->setHistoryEnable( false ); + _state->setCellWidget ( this ); + _drawingQuery .setCell ( getCell() ); + _drawingQuery .setStartLevel( _state->getStartLevel() ); + _drawingQuery .setStopLevel ( _state->getStopLevel() ); + _textDrawingQuery.setCell ( getCell() ); - reframe (); - _state->setHistoryEnable ( true ); + reframe(); + _state->setHistoryEnable( true ); - emit cellChanged ( getCell() ); - emit stateChanged ( _state ); - emit queryFilterChanged (); + emit cellChanged ( getCell() ); + emit stateChanged ( _state ); + emit queryFilterChanged(); - cellPostModificate (); - - closeRefreshSession (); + cellPostModificate(); + closeRefreshSession(); } diff --git a/hurricane/src/viewer/Command.cpp b/hurricane/src/viewer/Command.cpp index f7949edb..271f311f 100644 --- a/hurricane/src/viewer/Command.cpp +++ b/hurricane/src/viewer/Command.cpp @@ -1,32 +1,22 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2015, All Rights Reserved +// Copyright (c) UPMC 2008-2015, All Rights Reserved // -// =================================================================== -// -// $Id$ -// -// x-----------------------------------------------------------------x -// | | +// +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./Command.cpp" | -// | *************************************************************** | -// | U p d a t e s | -// | | -// x-----------------------------------------------------------------x +// +-----------------------------------------------------------------+ #include #include #include - #include #include @@ -68,6 +58,7 @@ namespace Hurricane { void Command::mousePressEvent ( QMouseEvent* ) { } void Command::mouseReleaseEvent ( QMouseEvent* ) { } void Command::draw () { } + void Command::reset () { } } // End of Hurricane namespace. diff --git a/hurricane/src/viewer/ControllerWidget.cpp b/hurricane/src/viewer/ControllerWidget.cpp index ad15f900..d657919e 100644 --- a/hurricane/src/viewer/ControllerWidget.cpp +++ b/hurricane/src/viewer/ControllerWidget.cpp @@ -8,7 +8,7 @@ // | V L S I B a c k e n d D a t a - B a s e | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./ControllerWidget.cpp" | // +-----------------------------------------------------------------+ @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -267,6 +268,62 @@ namespace Hurricane { } +// ------------------------------------------------------------------- +// Class : "Hurricane::TabNetlist". + + + TabHierarchy::TabHierarchy ( QWidget* parent ) + : ControllerTab (parent) + , _hierarchyBrowser (new HierarchyWidget()) + { + _hierarchyBrowser->setObjectName ( "controller.tabHierarchy.hierarchyBrowser" ); + + QVBoxLayout* wLayout = new QVBoxLayout (); + wLayout->setContentsMargins ( 10, 0, 10, 0 ); + wLayout->setSpacing ( 0 ); + + QFrame* separator = new QFrame (); + separator->setFrameShape ( QFrame::HLine ); + separator->setFrameShadow ( QFrame::Sunken ); + wLayout->addWidget ( separator ); + wLayout->addWidget ( _hierarchyBrowser ); + + setLayout ( wLayout ); + } + + + void TabHierarchy::setCell ( Cell* cell ) + { } + + + void TabHierarchy::setCellWidget ( CellWidget* cellWidget ) + { + if (getCellWidget() != cellWidget) { + ControllerTab::setCellWidget( cellWidget ); + _hierarchyBrowser->setCellWidget( cellWidget ); + if (getCellWidget()) { + connect( getCellWidget(), SIGNAL(cellChanged(Cell*)), this, SLOT(setCell(Cell*)) ); + } + } + } + + + void TabHierarchy::cellPreModificate () + { } + + + void TabHierarchy::cellPostModificate () + { + CellWidget* cw = getCellWidget(); + Cell* topCell = cw->getTopCell(); + if (not topCell) topCell = cw->getCell(); + _hierarchyBrowser->setCell( topCell ); + + if (not cw->getTopPath().isEmpty()) + _hierarchyBrowser->rexpand( cw->getTopPath() ); + } + + // ------------------------------------------------------------------- // Class : "Hurricane::TabSelection". @@ -475,48 +532,51 @@ namespace Hurricane { , _tabPalette (new TabPalette()) , _tabDisplayFilter(new TabDisplayFilter()) , _tabNetlist (new TabNetlist()) + , _tabHierarchy (new TabHierarchy()) , _tabSelection (new TabSelection()) , _tabInspector (new TabInspector()) , _tabSettings (new TabSettings()) { - setObjectName ( "controller" ); - setAttribute ( Qt::WA_QuitOnClose, false ); - setWindowTitle ( tr("Controller") ); + setObjectName ( "controller" ); + setAttribute ( Qt::WA_QuitOnClose, false ); + setWindowTitle( tr("Controller") ); //connect ( _netlistBrowser, SIGNAL(destroyed()), this, SLOT(netlistBrowserDestroyed()) ); - _tabGraphics ->setObjectName ( "controller.graphics" ); - _tabPalette ->setObjectName ( "controller.palette" ); - _tabDisplayFilter->setObjectName ( "controller.displayFilter" ); - _tabNetlist ->setObjectName ( "controller.tabNetlist" ); - _tabSelection ->setObjectName ( "controller.tabSelection" ); - _tabInspector ->setObjectName ( "controller.tabInspector" ); - _tabSettings ->setObjectName ( "controller.tabSettings" ); + _tabGraphics ->setObjectName( "controller.graphics" ); + _tabPalette ->setObjectName( "controller.palette" ); + _tabDisplayFilter->setObjectName( "controller.displayFilter" ); + _tabNetlist ->setObjectName( "controller.tabNetlist" ); + _tabHierarchy ->setObjectName( "controller.tabHierarchy" ); + _tabSelection ->setObjectName( "controller.tabSelection" ); + _tabInspector ->setObjectName( "controller.tabInspector" ); + _tabSettings ->setObjectName( "controller.tabSettings" ); - addTab ( _tabGraphics , "Look" ); - addTab ( _tabDisplayFilter , "Filter" ); - addTab ( _tabPalette , "Layers&&Gos" ); - addTab ( _tabNetlist , "Netlist" ); - addTab ( _tabSelection , "Selection" ); - addTab ( _tabInspector , "Inspector" ); - addTab ( _tabSettings , "Settings" ); + addTab( _tabGraphics , "Look" ); + addTab( _tabDisplayFilter , "Filter" ); + addTab( _tabPalette , "Layers&&Gos" ); + addTab( _tabHierarchy , "Hierarchy" ); + addTab( _tabNetlist , "Netlist" ); + addTab( _tabSelection , "Selection" ); + addTab( _tabInspector , "Inspector" ); + addTab( _tabSettings , "Settings" ); QAction* toggleShow = new QAction ( tr("Controller"), this ); - toggleShow->setObjectName ( "controller.action.hideShow" ); - toggleShow->setShortcut ( QKeySequence(tr("CTRL+I")) ); - addAction ( toggleShow ); + toggleShow->setObjectName( "controller.action.hideShow" ); + toggleShow->setShortcut ( QKeySequence(tr("CTRL+I")) ); + addAction( toggleShow ); - connect ( toggleShow, SIGNAL(triggered()) , this, SLOT(toggleShow()) ); - connect ( this , SIGNAL(currentChanged(int)), this, SLOT(updateTab(int)) ); - connect ( _tabSelection->getSelection(), SIGNAL(inspect(Occurrence&)) - , _tabInspector , SLOT (setSelectionOccurrence(Occurrence&)) ); + connect( toggleShow, SIGNAL(triggered()) , this, SLOT(toggleShow()) ); + connect( this , SIGNAL(currentChanged(int)), this, SLOT(updateTab(int)) ); + connect( _tabSelection->getSelection(), SIGNAL(inspect(Occurrence&)) + , _tabInspector , SLOT (setSelectionOccurrence(Occurrence&)) ); - resize ( Graphics::toHighDpi(600), Graphics::toHighDpi(500) ); + resize( Graphics::toHighDpi(600), Graphics::toHighDpi(500) ); } void ControllerWidget::toggleShow () - { setVisible ( !isVisible() ); } + { setVisible( !isVisible() ); } void ControllerWidget::setCellWidget ( CellWidget* cellWidget ) diff --git a/hurricane/src/viewer/HierarchyCommand.cpp b/hurricane/src/viewer/HierarchyCommand.cpp index bc66dfa2..179e5d08 100644 --- a/hurricane/src/viewer/HierarchyCommand.cpp +++ b/hurricane/src/viewer/HierarchyCommand.cpp @@ -1,26 +1,17 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2015, All Rights Reserved +// Copyright (c) UPMC 2008-2015, All Rights Reserved // -// =================================================================== -// -// $Id$ -// -// x-----------------------------------------------------------------x -// | | +// +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./HierarchyCommand.cpp" | -// | *************************************************************** | -// | U p d a t e s | -// | | -// x-----------------------------------------------------------------x +// +-----------------------------------------------------------------+ # include @@ -58,41 +49,53 @@ namespace Hurricane { { return _name; } + void HierarchyCommand::reset () + { + _history.clear(); + _historyIndex = 0; + } + + void HierarchyCommand::keyReleaseEvent ( QKeyEvent* event ) { bool control = (event->modifiers() & Qt::ControlModifier); bool shift = (event->modifiers() & Qt::ShiftModifier ); - if ( !shift && !control ) return; - if ( !_cellWidget->getCell() ) return; + if (not shift and not control) return; + if (not _cellWidget->getCell()) return; QPoint position ( _cellWidget->mapFromGlobal(QCursor::pos()) ); Box pointBox ( _cellWidget->screenToDbuBox(QRect(position,QSize(1,1))) ); switch ( event->key() ) { case Qt::Key_Up: - if ( ( _historyIndex > 0 ) && (shift || control) ) { - _cellWidget->setState ( _history[--_historyIndex]._state ); + if ( (_historyIndex > 0) and (shift or control) ) { + _cellWidget->setState ( _history[--_historyIndex], CellWidget::NoResetCommands ); } break; case Qt::Key_Down: { - if ( control ) { - if ( _history.empty() ) - _history.push_back ( HistoryEntry ( NULL, _cellWidget->getState() ) ); + if (control) { + Path topPath; + if (_history.empty()) { + _history.push_back( _cellWidget->getState() ); + topPath = _cellWidget->getState()->getTopPath(); + } else if (_historyIndex > 0) { + topPath = _history[_historyIndex-1]->getTopPath(); + } - Instances instances = _cellWidget->getCell()->getInstancesUnder ( pointBox ); - if ( !instances.isEmpty() ) { - _history.erase ( _history.begin()+_historyIndex+1, _history.end() ); + Instances instances = _cellWidget->getCell()->getInstancesUnder( pointBox ); + if (not instances.isEmpty()) { + _history.erase( _history.begin()+_historyIndex+1, _history.end() ); - Instance* instance = instances.getFirst (); - _cellWidget->setCell ( instance->getMasterCell() ); - _history.push_back ( HistoryEntry ( instance, _cellWidget->getState() ) ); + topPath = Path( topPath, instances.getFirst() ); + _cellWidget->setCell( topPath.getMasterCell(), topPath, CellWidget::NoResetCommands ); + _history.push_back( _cellWidget->getState() ); _historyIndex++; } - } else if ( shift ) { - if ( _historyIndex+1 < _history.size() ) { - _cellWidget->setState ( _history[++_historyIndex]._state ); + } else if (shift) { + if (_historyIndex+1 < _history.size()) { + _cellWidget->setState( _history[++_historyIndex], CellWidget::NoResetCommands ); } } } diff --git a/hurricane/src/viewer/HierarchyInformations.cpp b/hurricane/src/viewer/HierarchyInformations.cpp new file mode 100644 index 00000000..4a8a31fb --- /dev/null +++ b/hurricane/src/viewer/HierarchyInformations.cpp @@ -0,0 +1,288 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./HierarchyInformations.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include "hurricane/Name.h" +#include "hurricane/Cell.h" +#include "hurricane/Instance.h" +#include "hurricane/viewer/HierarchyInformations.h" + + +namespace Hurricane { + + +// ------------------------------------------------------------------- +// Class : "HierarchyInfos" + + HierarchyInfos::HierarchyInfos ( HierarchyInfos* parent, size_t rowInParent ) + : _parent (parent) + , _rowInParent(rowInParent) + { } + + + HierarchyInfos::~HierarchyInfos () + { } + + + int HierarchyInfos::getColumnCount () + { return 2; } + + + QVariant HierarchyInfos::getColumnName ( int column ) + { + switch ( column ) { + case 0: return QVariant(QObject::tr("Instance")); + case 1: return QVariant(QObject::tr("Model/Cell")); + } + return QVariant(QObject::tr("Column Out of Bound")); + } + + + QVariant HierarchyInfos::getColumn ( int column ) const + { + if (isRoot()) return QVariant(QObject::tr("RootItem")); + + const Instance* instance = getInstance(); + if (instance) { + switch ( column ) { + case 0: return getString(instance->getName()).c_str(); + case 1: return getString(instance->getMasterCell()->getName()).c_str(); + } + } else { + switch ( column ) { + case 0: return ""; + case 1: return getString(getMasterCell()->getName()).c_str(); + } + } + + return QVariant(QObject::tr("Column Out of Bound")); + } + + + Path HierarchyInfos::getPath () const + { + if (isRoot() or not getInstance()) return Path(); + + return Path( getParent()->getPath(), const_cast(getInstance()) ); + } + + +// ------------------------------------------------------------------- +// Class : "LeafHierarchyInfos" + + + const vector LeafHierarchyInfos::_instances; + + + LeafHierarchyInfos::LeafHierarchyInfos ( const Instance* instance + , HierarchyInfos* parent + , size_t rowInParent ) + : HierarchyInfos(parent,rowInParent) + , _instance(instance) + { } + + + LeafHierarchyInfos::~LeafHierarchyInfos () + { } + + + bool LeafHierarchyInfos::isRoot () const { return false; } + bool LeafHierarchyInfos::isLeaf () const { return true; } + bool LeafHierarchyInfos::isCollapsed () const { return true; } + const HierarchyInfos* LeafHierarchyInfos::getRow ( int row ) const { return NULL; } + int LeafHierarchyInfos::size () const { return 0; } + Cell* LeafHierarchyInfos::getMasterCell () const { return _instance->getMasterCell(); } + const Instance* LeafHierarchyInfos::getInstance () const { return _instance; } + const std::vector& LeafHierarchyInfos::getInstances () const { return _instances; } + QString LeafHierarchyInfos::getFilterPattern () const { return ""; } + void LeafHierarchyInfos::setFilterPattern ( const QString& ) { } + void LeafHierarchyInfos::expand () { } + void LeafHierarchyInfos::collapse () { } + + +// ------------------------------------------------------------------- +// Class : "InstHierarchyInfos" + + InstHierarchyInfos::InstHierarchyInfos ( const Instance* instance + , HierarchyInfos* parent + , size_t rowInParent ) + : HierarchyInfos(parent,rowInParent) + , _flags (HierarchyInfos::Collapsed) + , _instance (instance) + , _instances() + { } + + + InstHierarchyInfos::~InstHierarchyInfos () + { + collapse(); + } + + + bool InstHierarchyInfos::isRoot () const { return false; } + bool InstHierarchyInfos::isLeaf () const { return false; } + bool InstHierarchyInfos::isCollapsed () const { return _flags & HierarchyInfos::Collapsed; } + Cell* InstHierarchyInfos::getMasterCell () const { return _instance->getMasterCell(); } + const Instance* InstHierarchyInfos::getInstance () const { return _instance; } + const std::vector& InstHierarchyInfos::getInstances () const { return _instances; } + QString InstHierarchyInfos::getFilterPattern () const { return _filter.pattern(); } + + + int InstHierarchyInfos::size () const + { + if (_flags & HierarchyInfos::Collapsed) { + const_cast(this)->expand(); + } + return _instances.size(); + } + + + void InstHierarchyInfos::setFilterPattern ( const QString& pattern ) + { + _filter.setPattern( pattern ); + + if (_flags & HierarchyInfos::Collapsed) return; + + size_t i = 0; + for ( Instance* instance : getMasterCell()->getInstances() ) { + if (instance->getMasterCell()->isFeed()) continue; + + if ( (i < _instances.size()) and (instance == _instances[i]->getInstance()) ) { + // The instance *is already* in the list. + if ( not _filter.isEmpty() and (_filter.indexIn(getString(instance->getName()).c_str()) < 0) ) { + delete _instances[i]; + _instances.erase( _instances.begin()+i ); + } else { + ++i; + } + } else { + // The instance *is not* in the list. + if (_filter.isEmpty() or (_filter.indexIn(getString(instance->getName()).c_str()) >= 0) ) { + HierarchyInfos* infos = NULL; + if (instance->isLeaf()) infos = new LeafHierarchyInfos( instance, this, 0 ); + else infos = new InstHierarchyInfos( instance, this, 0 ); + + _instances.insert( _instances.begin()+i, infos ); + ++i; + } + } + } + + for ( size_t i=0 ; i<_instances.size() ; ++i ) _instances[i]->setRowInParent( i ); + } + + + void InstHierarchyInfos::expand () + { + if (not (_flags & HierarchyInfos::Collapsed)) return; + _flags &= ~HierarchyInfos::Collapsed; + + if (not getMasterCell()) return; + + for ( Instance* instance : getMasterCell()->getInstances() ) { + if (instance->getMasterCell()->isFeed()) continue; + if (not _filter.isEmpty()) { + if (_filter.indexIn(getString(instance->getName()).c_str()) < 0) continue; + } + + HierarchyInfos* infos = NULL; + if (instance->isLeaf()) infos = new LeafHierarchyInfos( instance, this, _instances.size() ); + else infos = new InstHierarchyInfos( instance, this, _instances.size() ); + + _instances.push_back( infos ); + } + } + + + void InstHierarchyInfos::collapse () + { + if (_flags & HierarchyInfos::Collapsed) return; + _flags |= HierarchyInfos::Collapsed; + + for ( HierarchyInfos* info : _instances ) delete info; + + vector().swap( _instances ); + } + + + const HierarchyInfos* InstHierarchyInfos::getRow ( int row ) const + { + if (_flags & HierarchyInfos::Collapsed) { + const_cast(this)->expand(); + } + + if (row >= (int)_instances.size()) return NULL; + return _instances[row]; + } + + +// ------------------------------------------------------------------- +// Class : "TopCellHierarchyInfos" + + TopCellHierarchyInfos::TopCellHierarchyInfos ( Cell* cell, HierarchyInfos* parent ) + : InstHierarchyInfos(NULL,parent,0) + , _rootCell(cell) + { expand(); } + + + TopCellHierarchyInfos::~TopCellHierarchyInfos () + { collapse(); } + + + bool TopCellHierarchyInfos::isRoot () const { return false; } + Cell* TopCellHierarchyInfos::getMasterCell () const { return _rootCell; } + const Instance* TopCellHierarchyInfos::getInstance () const { return NULL; } + + + void TopCellHierarchyInfos::setCell ( Cell* rootCell ) + { + collapse(); + _rootCell = rootCell; + expand(); + } + + +// ------------------------------------------------------------------- +// Class : "RootHierarchyInfos" + + + RootHierarchyInfos::RootHierarchyInfos ( Cell* cell ) + : HierarchyInfos(NULL,0) + , _instances() + { + _instances.push_back( new TopCellHierarchyInfos(cell,this) ); + } + + + RootHierarchyInfos::~RootHierarchyInfos () + { delete _instances[0]; } + + + bool RootHierarchyInfos::isRoot () const { return true; } + bool RootHierarchyInfos::isLeaf () const { return false; } + bool RootHierarchyInfos::isCollapsed () const { return false; } + int RootHierarchyInfos::size () const { return _instances.size(); } + const HierarchyInfos* RootHierarchyInfos::getRow ( int row ) const { return (row==0) ? _instances[0] : NULL; } + Cell* RootHierarchyInfos::getMasterCell () const { return _instances[0]->getMasterCell(); } + const Instance* RootHierarchyInfos::getInstance () const { return NULL; } + const std::vector& RootHierarchyInfos::getInstances () const { return _instances; } + QString RootHierarchyInfos::getFilterPattern () const { return ""; } + void RootHierarchyInfos::setFilterPattern ( const QString& ) { } + void RootHierarchyInfos::expand () { } + void RootHierarchyInfos::collapse () { } + void RootHierarchyInfos::setCell ( Cell* topCell ) { dynamic_cast(_instances[0])->setCell(topCell); } + +} // End of Hurricane namespace. diff --git a/hurricane/src/viewer/HierarchyModel.cpp b/hurricane/src/viewer/HierarchyModel.cpp new file mode 100644 index 00000000..2dd8bf60 --- /dev/null +++ b/hurricane/src/viewer/HierarchyModel.cpp @@ -0,0 +1,146 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./HierarchyModel.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include "hurricane/Name.h" +#include "hurricane/Net.h" +#include "hurricane/Cell.h" +#include "hurricane/viewer/Graphics.h" +#include "hurricane/viewer/HierarchyInformations.h" +#include "hurricane/viewer/HierarchyModel.h" + + +namespace Hurricane { + + + HierarchyModel::HierarchyModel ( QObject* parent ) + : QAbstractItemModel(parent) + , _root (NULL) + { } + + + HierarchyModel::~HierarchyModel () + { } + + + bool HierarchyModel::hasChildren ( const QModelIndex& parent ) const + { + if (not parent.isValid()) return true; + + const HierarchyInfos* infos = infosFromIndex(parent); + if (not infos) return true; + + return not infos->isLeaf(); + } + + + QVariant HierarchyModel::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) { + switch (index.column()) { + case 0: return nameFont; + default: return valueFont; + } + return QVariant(); + } + + if (not index.isValid()) return QVariant(); + + if (role == Qt::DisplayRole) { + const HierarchyInfos* infos = infosFromIndex( index ); + if (infos) + return infos->getColumn( index.column() ); + } + return QVariant(); + } + + + QVariant HierarchyModel::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 (role == Qt::SizeHintRole) return (Graphics::isHighDpi()) ? 600 : 300; + + return HierarchyInfos::getColumnName( section ); + } + + + int HierarchyModel::rowCount ( const QModelIndex& parent ) const + { + const HierarchyInfos* infos = infosFromIndex( parent ); + if (not infos) return 0; + + if (infos->isCollapsed()) { + cerr << "HierarchyModel::rowCount(): collapsed " << infos->size() << " " << infos->getInstance() << endl; + } + + return infos->size(); + } + + + int HierarchyModel::columnCount ( const QModelIndex& parent ) const + { return _root.getColumnCount(); } + + + QModelIndex HierarchyModel::index ( int row, int column, const QModelIndex& parent ) const + { + if (not _root.getMasterCell() or (row < 0) or (column < 0)) return QModelIndex(); + + const HierarchyInfos* parentInfos = infosFromIndex( parent ); + const HierarchyInfos* childInfos = parentInfos->getRow( row ); + + if (not childInfos) return QModelIndex(); + + QModelIndex index = createIndex( row, column, (void*)childInfos ); + // cerr << "HierarchyModel::index(): " << index.row() << "+" << index.column() + // << ":" << index.internalPointer() + // << " " << childInfos->getMasterCell() << endl; + + return index; + } + + + QModelIndex HierarchyModel::parent ( const QModelIndex& child ) const + { + const HierarchyInfos* childInfos = infosFromIndex( child ); + if (not childInfos) return QModelIndex(); + + const HierarchyInfos* parentInfos = childInfos->getParent(); + if (not parentInfos) return QModelIndex(); + + const HierarchyInfos* grandParentInfos = parentInfos->getParent(); + if (not grandParentInfos) return QModelIndex(); + + QModelIndex index = createIndex( parentInfos->getRowInParent(), 0, (void*)parentInfos ); + // cerr << "HierarchyModel::index(): " << index.row() << "+" << index.column() + // << ":" << index.internalPointer() + // << " " << childInfos->getMasterCell() << endl; + + return index; + } + + +} // Hurricane namespace. diff --git a/hurricane/src/viewer/HierarchyWidget.cpp b/hurricane/src/viewer/HierarchyWidget.cpp new file mode 100644 index 00000000..b92cc485 --- /dev/null +++ b/hurricane/src/viewer/HierarchyWidget.cpp @@ -0,0 +1,265 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./HierarchyWidget.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hurricane/Commons.h" +#include "hurricane/Warning.h" +#include "hurricane/Net.h" +#include "hurricane/viewer/Graphics.h" +#include "hurricane/viewer/HierarchyModel.h" +#include "hurricane/viewer/HierarchyWidget.h" + + +namespace Hurricane { + + +// ------------------------------------------------------------------- +// Class : "HierarchyWidget". + + + HierarchyWidget::HierarchyWidget ( QWidget* parent ) + : QWidget (parent) + , _cellWidget (NULL) + , _cell (NULL) + , _baseModel (new HierarchyModel(this)) + , _view (new QTreeView(this)) + , _filterPatternLineEdit(new QLineEdit(this)) + , _rowHeight (20) + { + setAttribute( Qt::WA_DeleteOnClose ); + setAttribute( Qt::WA_QuitOnClose, false ); + setContextMenuPolicy( Qt::ActionsContextMenu ); + + _rowHeight = QFontMetrics( Graphics::getFixedFont() ).height() + 4; + + //_view->setShowGrid ( false ); + _view->setAlternatingRowColors( true ); + _view->setSelectionBehavior ( QAbstractItemView::SelectRows ); + _view->setSelectionMode ( QAbstractItemView::SingleSelection ); + _view->setSortingEnabled ( true ); + _view->setModel ( _baseModel ); + //_view->resizeColumnToContents ( 1 ); + + QHeaderView* horizontalHeader = _view->header(); + horizontalHeader->setDefaultAlignment ( Qt::AlignHCenter ); + horizontalHeader->setMinimumSectionSize( (Graphics::isHighDpi()) ? 600 : 300 ); + horizontalHeader->setResizeMode ( 0, QHeaderView::Interactive ); + horizontalHeader->setResizeMode ( 1, QHeaderView::Interactive ); + horizontalHeader->setStretchLastSection( true ); + + 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 ); + + connect ( _view, SIGNAL(collapsed (const QModelIndex&)) + , this , SLOT (collapseHook(const QModelIndex& )) ); + connect ( _filterPatternLineEdit , SIGNAL(returnPressed ()) + , this , SLOT (textFilterChanged()) ); + connect ( _view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)) + , this , SLOT (followSelected (const QItemSelection&,const QItemSelection&)) ); + + TreeKeyFilter* filter = new TreeKeyFilter( this ); + _view->installEventFilter( filter ); + + resize(300, 300); + } + + + void HierarchyWidget::setCell ( Cell* cell ) + { + if (_cell == cell) return; + + _cell = cell; + _view->setVisible( false ); + _view->selectionModel()->clear(); + _baseModel->setCell( cell ); + + string windowTitle = "Hierarchy" + getString(cell); + setWindowTitle( tr(windowTitle.c_str()) ); + + _view->selectionModel()->select( _baseModel->index(0,0,_view->rootIndex()) + , QItemSelectionModel::Select|QItemSelectionModel::Rows ); + _view->resizeColumnToContents( 0 ); + _view->setVisible( true ); + } + + + bool HierarchyWidget::isRSelected ( const QModelIndex& index ) const + { + HierarchyInfos* infos = const_cast(_baseModel->infosFromIndex(index)); + for ( size_t row=0 ; row < infos->getInstances().size() ; ++row ) { + QModelIndex childIndex = _baseModel->index( row, 0, index ); + if (_view->selectionModel()->isSelected(childIndex)) + return true; + + if (not infos->isCollapsed() and isRSelected(childIndex)) return true; + } + + return false; + } + + + void HierarchyWidget::rexpand ( Path path ) + { + if (path.isEmpty()) return; + + QModelIndex index = _baseModel->index( 0, 0, QModelIndex() ); + do { + Instance* head = path.getHeadInstance(); + path = path.getTailPath(); + + _view->expand( index ); + HierarchyInfos* parentInfos = const_cast( _baseModel->infosFromIndex(index) ); + HierarchyInfos* childInfos = NULL; + + for ( HierarchyInfos* child : parentInfos->getInstances() ) { + if (child->getInstance() == head) { + childInfos = child; + break; + } + } + if (not childInfos) { + cerr << Warning("HierarchyWidget::rexpand(): discrepency between Path and Hierarchy.") << endl; + return; + } + + index = _baseModel->index( childInfos->getRowInParent(), 0, index ); + } while (not path.isEmpty()); + + _view->selectionModel()->clear(); + _view->selectionModel()->select( index, QItemSelectionModel::Select|QItemSelectionModel::Rows ); + _view->setCurrentIndex( index ); + } + + + void HierarchyWidget::rexpand ( const QModelIndex& index ) + { + HierarchyInfos* infos = const_cast(_baseModel->infosFromIndex(index)); + if (infos) { + if (not infos->isCollapsed()) { + _view->expand( index ); + for ( HierarchyInfos* child : infos->getInstances() ) { + rexpand( _baseModel->index( child->getRowInParent(), 0, index ) ); + } + } + } + } + + + void HierarchyWidget::collapseHook ( const QModelIndex& index ) + { + if (isRSelected(index)) { + _view->selectionModel()->clear(); + _view->selectionModel()->select( index, QItemSelectionModel::Select|QItemSelectionModel::Rows ); + } + + HierarchyInfos* infos = const_cast(_baseModel->infosFromIndex(index)); + infos->collapse(); + } + + + void HierarchyWidget::textFilterChanged () + { + QModelIndexList selecteds = _view->selectionModel()->selectedIndexes(); + + if (not selecteds.isEmpty()) { + QModelIndex index = selecteds[0]; + HierarchyInfos* infos = const_cast(_baseModel->infosFromIndex(index)); + infos->setFilterPattern( _filterPatternLineEdit->text() ); + _view->reset(); + rexpand( _view->rootIndex() ); + _view->selectionModel()->select( index, QItemSelectionModel::Select|QItemSelectionModel::Rows ); + _view->setCurrentIndex( index ); + } + } + + + void HierarchyWidget::followSelected ( const QItemSelection& selecteds, const QItemSelection& deselecteds ) + { + if (selecteds.indexes().isEmpty()) { + //cerr << Warning("HierarchyWidget::followSelected(): Selection should never be empty.") << endl; + return; + } + + QModelIndex index = selecteds.indexes()[0]; + HierarchyInfos* infos = const_cast(_baseModel->infosFromIndex(index)); + _filterPatternLineEdit->setText( infos->getFilterPattern() ); + } + + + void HierarchyWidget::goTo ( int delta ) + { + if (delta == 0) return; + + QModelIndex newIndex = _baseModel->index( _view->currentIndex().row()+delta, 0, QModelIndex() ); + + //if (newIndex.isValid()) + // _view->selectRow( newIndex.row() ); + } + + +// ------------------------------------------------------------------- +// Class : "TreeKeyFilter". + + + TreeKeyFilter::TreeKeyFilter ( QObject* parent ) + : QObject(parent) + { } + + + bool TreeKeyFilter::eventFilter ( QObject* object, QEvent* event ) + { + if (event->type() == QEvent::KeyPress) { + HierarchyWidget* owner = qobject_cast( parent() ); + if (not owner) return false; + + QKeyEvent* keyEvent = static_cast(event); + + if (keyEvent->key() == Qt::Key_Return) { + QModelIndexList selecteds = owner->_view->selectionModel()->selectedIndexes(); + + if (not selecteds.isEmpty()) { + QModelIndex index = selecteds[0]; + HierarchyInfos* infos = const_cast(owner->_baseModel->infosFromIndex(index)); + if (infos) { + if (owner->getCellWidget()) { + owner->getCellWidget()->setCell( infos->getMasterCell(), infos->getPath() ); + } + } + } + } + } + + return QObject::eventFilter( object, event ); + } + + +} // Hurricane namespace. diff --git a/hurricane/src/viewer/hurricane/viewer/CellWidget.h b/hurricane/src/viewer/hurricane/viewer/CellWidget.h index 2be1da63..69d9fc6f 100644 --- a/hurricane/src/viewer/hurricane/viewer/CellWidget.h +++ b/hurricane/src/viewer/hurricane/viewer/CellWidget.h @@ -97,15 +97,18 @@ namespace Hurricane { typedef void ( InitExtensionGo_t )( CellWidget* ); typedef boost::function< void(QPainter&) > PainterCb_t; enum RubberShape { Centric=1, Barycentric, Steiner }; - enum TextFlag { Bold =0x001 - , BigFont =0x002 - , Reverse =0x004 - , Frame =0x008 - , Rounded =0x010 - , Center =0x020 - , Left =0x040 - , Right =0x080 - , Top =0x100 + enum TextFlag { Bold =0x0001 + , BigFont =0x0002 + , Reverse =0x0004 + , Frame =0x0008 + , Rounded =0x0010 + , Center =0x0020 + , Left =0x0040 + , Right =0x0080 + , Top =0x0100 + }; + enum Flag { NoFlags =0x0000 + , NoResetCommands=0x0001 }; public: enum ResolutionMode { Res_CellMode=1, Res_DesignMode=2 }; @@ -115,8 +118,10 @@ namespace Hurricane { virtual ~CellWidget (); // Accessors. // MapView* getMapView () { return _mapView; }; - void setCell ( Cell* ); + void setCell ( Cell*, Path topPath=Path(), unsigned int flags=NoFlags ); inline Cell* getCell () const; + inline Cell* getTopCell () const; + inline Path getTopPath () const; inline shared_ptr& getState (); inline shared_ptr getStateClone (); inline PaletteWidget* getPalette (); @@ -132,6 +137,7 @@ namespace Hurricane { void detachFromPalette (); void bindCommand ( Command* ); void unbindCommand ( Command* ); + void resetCommands (); inline void setActiveCommand ( Command* ); inline Command* getActiveCommand () const; Command* getCommand ( const std::string& ) const; @@ -245,7 +251,8 @@ namespace Hurricane { virtual void paintEvent ( QPaintEvent* ); public slots: // Qt QWidget Slots Overload & CellWidget Specifics. - void setState ( shared_ptr& ); + void setState ( shared_ptr& + , unsigned int flags=NoFlags ); inline void openRefreshSession (); inline void closeRefreshSession (); inline DrawingPlanes& getDrawingPlanes (); @@ -534,9 +541,10 @@ namespace Hurricane { public: class State { public: - inline State ( Cell* cell=NULL ); + inline State ( Cell* cell=NULL, Path topPath=Path() ); State* clone () const; inline void setCell ( Cell* ); + inline void setTopPath ( Path ); inline void setCellWidget ( CellWidget* ); inline void setCursorStep ( DbU::Unit ); inline DbU::Unit getCursorStep () const; @@ -557,6 +565,8 @@ namespace Hurricane { bool scaleHistoryUp (); bool scaleHistoryDown (); inline Cell* getCell () const; + inline Cell* getTopCell () const; + inline Path getTopPath () const; const Name& getName () const; inline SelectorCriterions& getSelection (); inline RulerSet& getRulers (); @@ -590,6 +600,7 @@ namespace Hurricane { private: Cell* _cell; + Path _topPath; CellWidget* _cellWidget; SelectorCriterions _selection; RulerSet _rulers; @@ -879,8 +890,9 @@ namespace Hurricane { { } - inline CellWidget::State::State ( Cell* cell ) + inline CellWidget::State::State ( Cell* cell, Path topPath ) : _cell (cell) + , _topPath (topPath) , _cellWidget (NULL) , _selection () , _rulers () @@ -922,6 +934,10 @@ namespace Hurricane { { _cell = cell; } + inline void CellWidget::State::setTopPath ( Path topPath ) + { _topPath = topPath; } + + inline void CellWidget::State::setCellWidget ( CellWidget* cw ) { _cellWidget = cw; @@ -1002,6 +1018,14 @@ namespace Hurricane { { return _cell; } + inline Path CellWidget::State::getTopPath () const + { return _topPath; } + + + inline Cell* CellWidget::State::getTopCell () const + { return (_topPath.isEmpty()) ? _cell : _topPath.getOwnerCell(); } + + inline DbU::Unit CellWidget::State::cursorStep () const { return _cursorStep; } @@ -1255,6 +1279,14 @@ namespace Hurricane { { return _state->getCell(); } + inline Cell* CellWidget::getTopCell () const + { return _state->getTopCell(); } + + + inline Path CellWidget::getTopPath () const + { return _state->getTopPath(); } + + inline PaletteWidget* CellWidget::getPalette () { return _palette; } diff --git a/hurricane/src/viewer/hurricane/viewer/Command.h b/hurricane/src/viewer/hurricane/viewer/Command.h index eef67714..b6296e3d 100644 --- a/hurricane/src/viewer/hurricane/viewer/Command.h +++ b/hurricane/src/viewer/hurricane/viewer/Command.h @@ -1,27 +1,24 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2012, All Rights Reserved +// Copyright (c) UPMC 2008-2015, All Rights Reserved // // +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Header : "./hurricane/viewer/Command.h" | // +-----------------------------------------------------------------+ -#ifndef __HURRICANE_COMMAND_H__ -#define __HURRICANE_COMMAND_H__ - - -#include -#include +#ifndef HURRICANE_COMMAND_H +#define HURRICANE_COMMAND_H +#include +#include class QKeyEvent; class QMouseEvent; @@ -54,6 +51,7 @@ namespace Hurricane { virtual void mousePressEvent ( QMouseEvent* ); virtual void mouseReleaseEvent ( QMouseEvent* ); virtual void draw (); + virtual void reset (); private: Command ( const Command& ); Command& operator= ( const Command& ); diff --git a/hurricane/src/viewer/hurricane/viewer/ControllerWidget.h b/hurricane/src/viewer/hurricane/viewer/ControllerWidget.h index be9f7873..ae95f958 100644 --- a/hurricane/src/viewer/hurricane/viewer/ControllerWidget.h +++ b/hurricane/src/viewer/hurricane/viewer/ControllerWidget.h @@ -9,7 +9,7 @@ // | V L S I B a c k e n d D a t a - B a s e | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Header : "./hurricane/viewer/ControllerWidget.h" | // +-----------------------------------------------------------------+ @@ -42,6 +42,7 @@ namespace Hurricane { class GraphicsWidget; class DisplayFilterWidget; class NetlistWidget; + class HierarchyWidget; class SelectionWidget; class InspectorWidget; @@ -167,6 +168,30 @@ namespace Hurricane { inline QCheckBox* TabNetlist::getSyncSelection () { return _syncSelection; } +// ------------------------------------------------------------------- +// Class : "Hurricane::TabHierarchy". + + + class TabHierarchy : public ControllerTab { + Q_OBJECT; + + public: + TabHierarchy ( QWidget* parent=NULL ); + inline HierarchyWidget* getHierarchyBrowser (); + virtual void cellPreModificate (); + virtual void cellPostModificate (); + public slots: + virtual void setCell ( Cell* ); + virtual void setCellWidget ( CellWidget* ); + + protected: + HierarchyWidget* _hierarchyBrowser; + }; + + + inline HierarchyWidget* TabHierarchy::getHierarchyBrowser () { return _hierarchyBrowser; } + + // ------------------------------------------------------------------- // Class : "Hurricane::TabSelection". @@ -268,23 +293,24 @@ namespace Hurricane { Q_OBJECT; public: - ControllerWidget ( QWidget* parent=NULL ); - inline CellWidget* getCellWidget (); - inline GraphicsWidget* getGraphics (); - inline PaletteWidget* getPalette (); - inline DisplayFilterWidget* getDisplayFilter (); - inline NetlistWidget* getNetlistBrowser (); - inline SelectionWidget* getSelection (); - inline InspectorWidget* getInspectorWidget (); - inline TabSettings* getSettings (); - void setCellWidget ( CellWidget* ); - //inline int addSetting ( QWidget* page, const QString& label ); - public slots: - void cellPreModificate (); - void cellPostModificate (); - void cellChanged ( Cell* ); - void updateTab ( int index ); - void toggleShow (); + ControllerWidget ( QWidget* parent=NULL ); + inline CellWidget* getCellWidget (); + inline GraphicsWidget* getGraphics (); + inline PaletteWidget* getPalette (); + inline DisplayFilterWidget* getDisplayFilter (); + inline NetlistWidget* getNetlistBrowser (); + inline HierarchyWidget* getHierarchyBrowser (); + inline SelectionWidget* getSelection (); + inline InspectorWidget* getInspectorWidget (); + inline TabSettings* getSettings (); + void setCellWidget ( CellWidget* ); + //inline int addSetting ( QWidget* page, const QString& label ); + public slots: + void cellPreModificate (); + void cellPostModificate (); + void cellChanged ( Cell* ); + void updateTab ( int index ); + void toggleShow (); protected: CellWidget* _cellWidget; @@ -292,21 +318,23 @@ namespace Hurricane { TabPalette* _tabPalette; TabDisplayFilter* _tabDisplayFilter; TabNetlist* _tabNetlist; + TabHierarchy* _tabHierarchy; TabSelection* _tabSelection; TabInspector* _tabInspector; TabSettings* _tabSettings; }; - inline CellWidget* ControllerWidget::getCellWidget () { return _cellWidget; } - inline GraphicsWidget* ControllerWidget::getGraphics () { return _tabGraphics->getGraphics(); } - inline PaletteWidget* ControllerWidget::getPalette () { return _tabPalette->getPalette(); } - inline DisplayFilterWidget* ControllerWidget::getDisplayFilter () { return _tabDisplayFilter->getDisplayFilter(); } - inline NetlistWidget* ControllerWidget::getNetlistBrowser () { return _tabNetlist->getNetlistBrowser(); } - inline SelectionWidget* ControllerWidget::getSelection () { return _tabSelection->getSelection(); } - inline InspectorWidget* ControllerWidget::getInspectorWidget () { return _tabInspector->getInspectorWidget(); } - inline TabSettings* ControllerWidget::getSettings () { return _tabSettings; } -//inline int ControllerWidget::addSetting ( QWidget* page, const QString& label ) { return _tabSettings->addSetting(page,label); } + inline CellWidget* ControllerWidget::getCellWidget () { return _cellWidget; } + inline GraphicsWidget* ControllerWidget::getGraphics () { return _tabGraphics->getGraphics(); } + inline PaletteWidget* ControllerWidget::getPalette () { return _tabPalette->getPalette(); } + inline DisplayFilterWidget* ControllerWidget::getDisplayFilter () { return _tabDisplayFilter->getDisplayFilter(); } + inline NetlistWidget* ControllerWidget::getNetlistBrowser () { return _tabNetlist->getNetlistBrowser(); } + inline HierarchyWidget* ControllerWidget::getHierarchyBrowser () { return _tabHierarchy->getHierarchyBrowser(); } + inline SelectionWidget* ControllerWidget::getSelection () { return _tabSelection->getSelection(); } + inline InspectorWidget* ControllerWidget::getInspectorWidget () { return _tabInspector->getInspectorWidget(); } + inline TabSettings* ControllerWidget::getSettings () { return _tabSettings; } +//inline int ControllerWidget::addSetting ( QWidget* page, const QString& label ) { return _tabSettings->addSetting(page,label); } } // End of Hurricane namespace. diff --git a/hurricane/src/viewer/hurricane/viewer/HierarchyCommand.h b/hurricane/src/viewer/hurricane/viewer/HierarchyCommand.h index db74882b..201063de 100644 --- a/hurricane/src/viewer/hurricane/viewer/HierarchyCommand.h +++ b/hurricane/src/viewer/hurricane/viewer/HierarchyCommand.h @@ -1,87 +1,55 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2015, All Rights Reserved +// Copyright (c) UPMC 2008-2015, All Rights Reserved // -// =================================================================== -// -// $Id$ -// -// x-----------------------------------------------------------------x -// | | +// +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Header : "./HierarchyCommand.h" | -// | *************************************************************** | -// | U p d a t e s | -// | | -// x-----------------------------------------------------------------x +// +-----------------------------------------------------------------+ -#ifndef __HURRICANE_HIERARCHY_COMMAND__ -#define __HURRICANE_HIERARCHY_COMMAND__ - -#include - -#include -#include +#ifndef HURRICANE_HIERARCHY_COMMAND_H +#define HURRICANE_HIERARCHY_COMMAND_H +#include +#include +#include class QAction; -#include "hurricane/Occurrence.h" -#include "hurricane/viewer/Command.h" -#include "hurricane/viewer/CellWidget.h" - - -using namespace std; +#include "hurricane/Occurrence.h" +#include "hurricane/viewer/Command.h" +#include "hurricane/viewer/CellWidget.h" namespace Hurricane { - class Cell; class HierarchyCommand : public Command { public: - HierarchyCommand (); - virtual ~HierarchyCommand (); - virtual const string& getName () const; - virtual void keyReleaseEvent ( QKeyEvent* ); + HierarchyCommand (); + virtual ~HierarchyCommand (); + virtual const std::string& getName () const; + virtual void reset (); + virtual void keyReleaseEvent ( QKeyEvent* ); private: - HierarchyCommand ( const HierarchyCommand& ); - HierarchyCommand& operator= ( const HierarchyCommand& ); + HierarchyCommand ( const HierarchyCommand& ); + HierarchyCommand& operator= ( const HierarchyCommand& ); private: - class HistoryEntry { - public: - inline HistoryEntry ( Instance*, shared_ptr ); - public: - Instance* _instance; - shared_ptr _state; - }; - private: - static string _name; - vector _history; - size_t _historyIndex; + static std::string _name; + std::vector< std::shared_ptr > _history; + size_t _historyIndex; }; -// Inline Functions. - inline HierarchyCommand::HistoryEntry::HistoryEntry ( Instance* instance - , shared_ptr state - ) - : _instance(instance) - , _state (state) - { } +} // Hurricane namespace. - -} // End of Hurricane namespace. - - -#endif +#endif // HURRICANE_HIERARCHY_COMMAND_H diff --git a/hurricane/src/viewer/hurricane/viewer/HierarchyInformations.h b/hurricane/src/viewer/hurricane/viewer/HierarchyInformations.h new file mode 100644 index 00000000..9a44cf11 --- /dev/null +++ b/hurricane/src/viewer/hurricane/viewer/HierarchyInformations.h @@ -0,0 +1,178 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/viewer/HierarchyInformations.h" | +// +-----------------------------------------------------------------+ + + +#ifndef HURRICANE_HIERARCHY_INFORMATIONS_H +#define HURRICANE_HIERARCHY_INFORMATIONS_H + +#include +#include +#include +#include "hurricane/Commons.h" +#include "hurricane/Path.h" + + +namespace Hurricane { + + class Instance; + class Cell; + + +// ------------------------------------------------------------------- +// Class : "HierarchyInfos" + + + class HierarchyInfos { + public: + enum Flags { NoFlags=0x0000, Collapsed=0x0001 }; + public: + HierarchyInfos ( HierarchyInfos* parent, size_t rowInParent ); + virtual ~HierarchyInfos (); + virtual bool isRoot () const = 0; + virtual bool isLeaf () const = 0; + virtual bool isCollapsed () const = 0; + static int getColumnCount (); + static QVariant getColumnName ( int column ); + QVariant getColumn ( int column ) const; + virtual const HierarchyInfos* getRow ( int row ) const = 0; + inline const HierarchyInfos* getParent () const; + inline size_t getRowInParent () const; + virtual int size () const = 0; + virtual Cell* getMasterCell () const = 0; + virtual const Instance* getInstance () const = 0; + virtual const std::vector& getInstances () const = 0; + inline const Name getName () const; + virtual Path getPath () const; + virtual QString getFilterPattern () const = 0; + virtual void setFilterPattern ( const QString& ) = 0; + inline void setRowInParent ( size_t ); + virtual void expand () = 0; + virtual void collapse () = 0; + protected: + HierarchyInfos* _parent; + size_t _rowInParent; + }; + + + inline size_t HierarchyInfos::getRowInParent () const { return _rowInParent; } + inline const HierarchyInfos* HierarchyInfos::getParent () const { return _parent; } + inline const Name HierarchyInfos::getName () const { return isRoot() ? Name("Root") : getInstance()->getName(); } + inline void HierarchyInfos::setRowInParent ( size_t rowInParent ) { _rowInParent=rowInParent; } + + +// ------------------------------------------------------------------- +// Class : "LeafHierarchyInfos" + + + class LeafHierarchyInfos : public HierarchyInfos { + public: + LeafHierarchyInfos ( const Instance* + , HierarchyInfos* parent + , size_t rowInParent ); + virtual ~LeafHierarchyInfos (); + virtual bool isRoot () const; + virtual bool isLeaf () const; + virtual bool isCollapsed () const; + virtual const HierarchyInfos* getRow ( int row ) const; + virtual int size () const; + virtual Cell* getMasterCell () const; + virtual const Instance* getInstance () const; + virtual const std::vector& getInstances () const; + virtual void setFilterPattern ( const QString& ); + virtual QString getFilterPattern () const; + virtual void expand (); + virtual void collapse (); + protected: + const Instance* _instance; + static const std::vector _instances; + }; + + +// ------------------------------------------------------------------- +// Class : "InstHierarchyInfos" + + + class InstHierarchyInfos : public HierarchyInfos { + public: + InstHierarchyInfos ( const Instance* + , HierarchyInfos* parent + , size_t rowInParent ); + virtual ~InstHierarchyInfos (); + virtual bool isRoot () const; + virtual bool isLeaf () const; + virtual bool isCollapsed () const; + virtual const HierarchyInfos* getRow ( int row ) const; + virtual int size () const; + virtual Cell* getMasterCell () const; + virtual const Instance* getInstance () const; + virtual const std::vector& getInstances () const; + virtual void setFilterPattern ( const QString& ); + virtual QString getFilterPattern () const; + virtual void expand (); + virtual void collapse (); + protected: + unsigned int _flags; + const Instance* _instance; + std::vector _instances; + QRegExp _filter; + }; + + +// ------------------------------------------------------------------- +// Class : "TopCellHierarchyInfos" + + + class TopCellHierarchyInfos : public InstHierarchyInfos { + public: + TopCellHierarchyInfos ( Cell*, HierarchyInfos* parent ); + virtual ~TopCellHierarchyInfos (); + virtual bool isRoot () const; + virtual Cell* getMasterCell () const; + virtual const Instance* getInstance () const; + void setCell ( Cell* ); + protected: + Cell* _rootCell; + }; + + +// ------------------------------------------------------------------- +// Class : "RootHierarchyInfos" + + + class RootHierarchyInfos : public HierarchyInfos { + public: + RootHierarchyInfos ( Cell* ); + virtual ~RootHierarchyInfos (); + virtual bool isRoot () const; + virtual bool isLeaf () const; + virtual bool isCollapsed () const; + virtual const HierarchyInfos* getRow ( int row ) const; + virtual int size () const; + virtual Cell* getMasterCell () const; + virtual const Instance* getInstance () const; + virtual const std::vector& getInstances () const; + virtual void setFilterPattern ( const QString& ); + virtual QString getFilterPattern () const; + virtual void expand (); + virtual void collapse (); + void setCell ( Cell* ); + protected: + std::vector _instances; + }; + + +} // Hurricane namespace. + +#endif // HURRICANE_HIERARCHY_INFORMATIONS_H diff --git a/hurricane/src/viewer/hurricane/viewer/HierarchyModel.h b/hurricane/src/viewer/hurricane/viewer/HierarchyModel.h new file mode 100644 index 00000000..2229f5f9 --- /dev/null +++ b/hurricane/src/viewer/hurricane/viewer/HierarchyModel.h @@ -0,0 +1,85 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/viewer/HierarchyModel.h" | +// +-----------------------------------------------------------------+ + + +#ifndef HURRICANE_HIERARCHY_MODEL_H +#define HURRICANE_HIERARCHY_MODEL_H + +#include +#include +#include +#include +#include "hurricane/Commons.h" +#include "hurricane/Name.h" +#include "hurricane/Net.h" +#include "hurricane/Cell.h" +#include "hurricane/viewer/Graphics.h" +#include "hurricane/viewer/HierarchyInformations.h" + + +namespace Hurricane { + + class Net; + class Cell; + + + class HierarchyModel : public QAbstractItemModel { + Q_OBJECT; + + public: + HierarchyModel ( QObject* parent=NULL ); + ~HierarchyModel (); + inline void setRootCell ( Cell* cell ); + virtual bool hasChildren ( const QModelIndex& parent=QModelIndex() ) const; + QModelIndex index ( int row, int column, const QModelIndex& parent ) const; + QModelIndex parent ( const QModelIndex& child ) const; + 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 (); + inline HierarchyInfos* getRoot (); + inline void setCell ( Cell* ); + inline const HierarchyInfos* infosFromIndex ( const QModelIndex& ) const; + private: + RootHierarchyInfos _root; + }; + + +// Inline Functions. + + inline Cell* HierarchyModel::getCell () { return _root.getMasterCell(); } + inline HierarchyInfos* HierarchyModel::getRoot () { return &_root; } + + + inline void HierarchyModel::setCell ( Cell* cell ) + { + _root.setCell( cell ); + reset(); + } + + + inline const HierarchyInfos* HierarchyModel::infosFromIndex ( const QModelIndex& index ) const + { + if (index.isValid()) + return static_cast(index.internalPointer()); + return &_root; + } + + +} // End of Hurricane namespace. + + +#endif // HURRICANE_HIERARCHY_MODEL_H diff --git a/hurricane/src/viewer/hurricane/viewer/HierarchyWidget.h b/hurricane/src/viewer/hurricane/viewer/HierarchyWidget.h new file mode 100644 index 00000000..f643eefd --- /dev/null +++ b/hurricane/src/viewer/hurricane/viewer/HierarchyWidget.h @@ -0,0 +1,111 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/viewer/HierarchyWidget.h" | +// +-----------------------------------------------------------------+ + + +#ifndef HURRICANE_HIERARCHY_WIDGET_H +#define HURRICANE_HIERARCHY_WIDGET_H + +#include +#include +#include +#include +#include "hurricane/Commons.h" +#include "hurricane/Bug.h" +#include "hurricane/viewer/HierarchyModel.h" +#include "hurricane/viewer/CellWidget.h" + + +class QModelIndex; +class QItemSelection; +class QLineEdit; +class QComboBox; +class QHeaderView; + + +namespace Hurricane { + + using std::set; + class Net; + class Cell; + + +// ------------------------------------------------------------------- +// Class : "TreeKeyFilter". + + + class TreeKeyFilter : public QObject { + Q_OBJECT; + + public: + TreeKeyFilter ( QObject* parent ); + bool eventFilter ( QObject*, QEvent* ); + }; + + +// ------------------------------------------------------------------- +// Class : "HierarchyWidget". + + + class HierarchyWidget : public QWidget { + Q_OBJECT; + + friend class TreeKeyFilter; + public: + HierarchyWidget ( QWidget* parent=NULL ); + bool isRSelected ( const QModelIndex& index ) const; + inline CellWidget* getCellWidget (); + void rexpand ( Path path ); + void rexpand ( const QModelIndex& index ); + inline Cell* getCell (); + inline void setCellWidget ( CellWidget* ); + void setCell ( Cell* ); + void goTo ( int ); + private slots: + void collapseHook ( const QModelIndex& ); + void textFilterChanged (); + void followSelected ( const QItemSelection&, const QItemSelection& ); + private: + CellWidget* _cellWidget; + Cell* _cell; + HierarchyModel* _baseModel; + QTreeView* _view; + QLineEdit* _filterPatternLineEdit; + int _rowHeight; + }; + + + inline Cell* HierarchyWidget::getCell () { return _cell; } + inline CellWidget* HierarchyWidget::getCellWidget () { return _cellWidget; } + + + inline void HierarchyWidget::setCellWidget ( CellWidget* cw ) + { + if (_cellWidget) { + disconnect( this, 0, _cellWidget, 0 ); + } + + _cellWidget = cw; + if (_cellWidget) { + if (_cellWidget->getTopCell()) setCell( _cellWidget->getTopCell() ); + else setCell( _cellWidget->getCell() ); + } else + setCell( NULL ); + } + + +} // Hurricane namespace. + +#endif // HURRICANE_HIERARCHY_WIDGET_H From ed2cd18c48c9cb3e5261d203070853e1e3c656e4 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sat, 25 Jul 2015 11:38:00 +0200 Subject: [PATCH 02/60] Too narrow search area for straight net in Knik. * Bug: In Knik, in Graph::Dijsktra(), when all the RoutingPads of a net are aligned, the seaching area is only one vertex wide (in width or height). That is, it contains only one edge in it's main direction. So when that sub-graph contains a fully blocked edge, Dijkstra cannot find a path... Now enlarge the one edge graph to at least three by inflating the search area. Curiously a code for similar purpose seems to be present, but commented. --- knik/src/Graph.cpp | 11 +++++++++++ knik/src/knik/MatrixVertex.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/knik/src/Graph.cpp b/knik/src/Graph.cpp index 433e008e..342d2461 100644 --- a/knik/src/Graph.cpp +++ b/knik/src/Graph.cpp @@ -1023,6 +1023,7 @@ int Graph::initRouting ( Net* net ) } } } + //cerr << " traitement pour les contacts : OK" << endl; //OoOoooOoooOoO A QUOI SERT CE BOOLEEN OoOoooOoooOoO ==>> pour le //5 le connexID ne doit pas avoir été augmenté ! ou alors connexID-1 !! //bool useConnexID = false; @@ -1063,6 +1064,13 @@ int Graph::initRouting ( Net* net ) } } } + + if (_searchingArea.getHeight() <= _matrixVertex->getTileHeight()) + _searchingArea.inflate( 0, _matrixVertex->getTileHeight() ); + + if (_searchingArea.getWidth() <= _matrixVertex->getTileWidth()) + _searchingArea.inflate( _matrixVertex->getTileWidth(), 0 ); + // for ripup & reroute purpose if ( __ripupMode__ ) _searchingArea = _cell->getAbutmentBox(); // recherche sur toute la surface : trop long pour gros circuits @@ -1135,6 +1143,9 @@ void Graph::Dijkstra() ltrace(600) << "Dijkstra for net: " << _working_net << endl; ltracein(600); ltrace(600) << "Stamp:" << _netStamp << endl; + ltrace(600) << "Search area : " << _searchingArea + << " h:" << DbU::getValueString(_searchingArea.getHeight()) << endl; + ltrace(600) << "Matrix tile height : " << DbU::getValueString(_matrixVertex->getTileHeight()) << endl; ltrace(600) << "Central vertex : " << centralVertex << endl; ltrace(600) << "_vertexes_to_route.size(): " << _vertexes_to_route.size() << endl; ltracein(600); diff --git a/knik/src/knik/MatrixVertex.h b/knik/src/knik/MatrixVertex.h index 789fa468..c141fbf8 100644 --- a/knik/src/knik/MatrixVertex.h +++ b/knik/src/knik/MatrixVertex.h @@ -70,6 +70,8 @@ namespace Knik { // Accessors // ********* public: + DbU::Unit getTileWidth () const { return _tileWidth; } + DbU::Unit getTileHeight () const { return _tileHeight; } size_t getXSize () const { return _matrix[0].size(); }; size_t getYSize () const { return _matrix.size(); }; unsigned int getLineIndex ( DbU::Unit y ); From 8ead28d86c52f408475ab4facc2d03dc7beed55d Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sat, 25 Jul 2015 11:55:42 +0200 Subject: [PATCH 03/60] In the Netlist tab of the Controller, add a count of RoutingPads. * New: In Hurricane, in NetlistWidget & NetlistModel, adds a column for the RoutingPads count. Special display to mark global nets. * Change: In Hurricane, in all MVC's models, some improvements on the way the columns are sized and the titles displayeds. --- hurricane/src/viewer/NetInformations.cpp | 73 ++++++------------- hurricane/src/viewer/NetlistWidget.cpp | 65 +++++++++-------- hurricane/src/viewer/RecordModel.cpp | 1 - hurricane/src/viewer/SelectionModel.cpp | 1 - hurricane/src/viewer/SelectionPopupModel.cpp | 1 - .../viewer/hurricane/viewer/NetInformations.h | 9 ++- .../viewer/hurricane/viewer/NetlistWidget.h | 13 ++-- 7 files changed, 70 insertions(+), 93 deletions(-) diff --git a/hurricane/src/viewer/NetInformations.cpp b/hurricane/src/viewer/NetInformations.cpp index 750a8557..02f485e7 100644 --- a/hurricane/src/viewer/NetInformations.cpp +++ b/hurricane/src/viewer/NetInformations.cpp @@ -1,60 +1,23 @@ - // -*- C++ -*- // -// This file is part of the Coriolis Project. -// Copyright (C) Laboratoire LIP6 - Departement ASIM -// Universite Pierre et Marie Curie +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2008-2015, All Rights Reserved // -// Main contributors : -// Christophe Alexandre -// Sophie Belloeil -// Hugo Clment -// Jean-Paul Chaput -// Damien Dupuis -// Christian Masson -// Marek Sroka -// -// The Coriolis Project is free software; you can redistribute it -// and/or modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 of -// the License, or (at your option) any later version. -// -// The Coriolis Project is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with the Coriolis Project; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -// USA -// -// License-Tag -// Authors-Tag -// =================================================================== -// -// $Id$ -// -// x-----------------------------------------------------------------x -// | | +// +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./NetInformations.cpp" | -// | *************************************************************** | -// | U p d a t e s | -// | | -// x-----------------------------------------------------------------x +// +-----------------------------------------------------------------+ -#include - -#include "hurricane/Name.h" -#include "hurricane/Net.h" -#include "hurricane/viewer/NetInformations.h" +#include +#include "hurricane/Name.h" +#include "hurricane/Net.h" +#include "hurricane/viewer/NetInformations.h" namespace Hurricane { @@ -100,7 +63,7 @@ namespace Hurricane { int SimpleNetInformations::getColumnCount () - { return 2; } + { return 3; } QVariant SimpleNetInformations::getColumnName ( int column ) @@ -108,6 +71,7 @@ namespace Hurricane { switch ( column ) { case 0: return QVariant(QObject::tr("Net")); case 1: return QVariant(QObject::tr("Plugs")); + case 2: return QVariant(QObject::tr("RoutingPads")); } return QVariant(QObject::tr("Column Out of Bound")); } @@ -116,8 +80,15 @@ namespace Hurricane { QVariant SimpleNetInformations::getColumn ( int column ) { switch ( column ) { - case 0: return _columnNet; - case 1: return _columnPlug; + case 0: return _netName; + case 1: return (unsigned int)_plugsCount; + case 2: + if (_net->isGlobal()) { + if (not _rpsCount) return "N/A (global)"; + string s = getString(_rpsCount) + " (global)"; + return s.c_str(); + } + return (unsigned int)_rpsCount; } return QVariant(QObject::tr("Column Out of Bound")); } @@ -125,9 +96,9 @@ namespace Hurricane { SimpleNetInformations::SimpleNetInformations ( const Net* net ) : NetInformations(net) + , _netName (getString(getName()).c_str()) , _plugsCount (_net->getPlugs().getSize()) - , _columnNet (getString(getName()).c_str()) - , _columnPlug ((unsigned int)_plugsCount) + , _rpsCount (_net->getRoutingPads().getSize()) { } diff --git a/hurricane/src/viewer/NetlistWidget.cpp b/hurricane/src/viewer/NetlistWidget.cpp index 4696df5a..e0cecf4c 100644 --- a/hurricane/src/viewer/NetlistWidget.cpp +++ b/hurricane/src/viewer/NetlistWidget.cpp @@ -58,22 +58,27 @@ namespace Hurricane { _rowHeight = QFontMetrics(Graphics::getFixedFont()).height() + 4; - _sortModel->setSourceModel ( _baseModel ); - _sortModel->setDynamicSortFilter ( true ); - _sortModel->setFilterKeyColumn ( 0 ); + _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 ); + _view->setShowGrid ( false ); + _view->setAlternatingRowColors( true ); + _view->setSelectionBehavior ( QAbstractItemView::SelectRows ); + _view->setSortingEnabled ( true ); + _view->setModel ( _sortModel ); - QHeaderView* horizontalHeader = _view->horizontalHeader (); - horizontalHeader->setStretchLastSection ( true ); + QHeaderView* horizontalHeader = _view->horizontalHeader(); + horizontalHeader->setDefaultAlignment ( Qt::AlignHCenter ); + horizontalHeader->setMinimumSectionSize( (Graphics::isHighDpi()) ? 300 : 150 ); + horizontalHeader->setResizeMode ( 0, QHeaderView::Interactive ); + horizontalHeader->setResizeMode ( 1, QHeaderView::Interactive ); + horizontalHeader->setResizeMode ( 2, QHeaderView::Interactive ); + horizontalHeader->setStretchLastSection( true ); - QHeaderView* verticalHeader = _view->verticalHeader (); - verticalHeader->setVisible ( false ); - verticalHeader->setDefaultSectionSize ( _rowHeight ); + QHeaderView* verticalHeader = _view->verticalHeader(); + verticalHeader->setVisible( false ); + verticalHeader->setDefaultSectionSize( _rowHeight ); // verticalHeader->setStyleSheet( "QHeaderView::section {" // "padding-bottom: 0px;" @@ -84,29 +89,29 @@ namespace Hurricane { // "}" // ); - _filterPatternLineEdit = new QLineEdit(this); - QLabel* filterPatternLabel = new QLabel(tr("&Filter pattern:"), this); - filterPatternLabel->setBuddy(_filterPatternLineEdit); + _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); + gLayout->addWidget( _view , 1, 0, 1, 2 ); + gLayout->addWidget( filterPatternLabel , 2, 0 ); + gLayout->addWidget( _filterPatternLineEdit, 2, 1 ); - setLayout ( gLayout ); + setLayout( gLayout ); - QAction* fitAction = new QAction ( tr("&Fit to Net"), this ); - fitAction->setShortcut ( QKeySequence(tr("CTRL+F")) ); - fitAction->setStatusTip ( tr("Fit the view to the Net's bounding box") ); - addAction ( fitAction ); + QAction* fitAction = new QAction( tr("&Fit to Net"), this ); + fitAction->setShortcut ( QKeySequence(tr("CTRL+F")) ); + fitAction->setStatusTip( tr("Fit the view to the Net'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(fitToNet ()) ); + 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(fitToNet ()) ); - resize(300, 300); + resize( 300, 300 ); } diff --git a/hurricane/src/viewer/RecordModel.cpp b/hurricane/src/viewer/RecordModel.cpp index 75505b52..6b09c2b2 100644 --- a/hurricane/src/viewer/RecordModel.cpp +++ b/hurricane/src/viewer/RecordModel.cpp @@ -112,7 +112,6 @@ namespace Hurricane { } if ( role == Qt::FontRole ) { - //if ( index.row() == 0 ) return QVariant(); switch (index.column()) { case 0: return nameFont; case 1: return valueFont; diff --git a/hurricane/src/viewer/SelectionModel.cpp b/hurricane/src/viewer/SelectionModel.cpp index ff2302b4..557d8d11 100644 --- a/hurricane/src/viewer/SelectionModel.cpp +++ b/hurricane/src/viewer/SelectionModel.cpp @@ -176,7 +176,6 @@ namespace Hurricane { if ( !index.isValid() ) return QVariant (); if ( role == Qt::SizeHintRole ) { - if ( index.row() == 0 ) return QVariant(); switch (index.column()) { case 0: return 200; default: diff --git a/hurricane/src/viewer/SelectionPopupModel.cpp b/hurricane/src/viewer/SelectionPopupModel.cpp index d9effafa..c5925627 100644 --- a/hurricane/src/viewer/SelectionPopupModel.cpp +++ b/hurricane/src/viewer/SelectionPopupModel.cpp @@ -117,7 +117,6 @@ namespace Hurricane { } if ( role == Qt::FontRole ) { - if ( index.row() == 0 ) return QVariant(); switch (index.column()) { default: return entityFont; } diff --git a/hurricane/src/viewer/hurricane/viewer/NetInformations.h b/hurricane/src/viewer/hurricane/viewer/NetInformations.h index 599caa31..8ca7254e 100644 --- a/hurricane/src/viewer/hurricane/viewer/NetInformations.h +++ b/hurricane/src/viewer/hurricane/viewer/NetInformations.h @@ -67,16 +67,17 @@ namespace Hurricane { static QVariant getColumnName ( int column ); virtual QVariant getColumn ( int column ); inline size_t getPlugsCount () const; + inline size_t getRpsCount () const; protected: + QVariant _netName; size_t _plugsCount; - QVariant _columnNet; - QVariant _columnPlug; + size_t _rpsCount; }; - inline size_t SimpleNetInformations::getPlugsCount () const - { return _plugsCount; } + inline size_t SimpleNetInformations::getPlugsCount () const { return _plugsCount; } + inline size_t SimpleNetInformations::getRpsCount () const { return _rpsCount; } // ------------------------------------------------------------------- diff --git a/hurricane/src/viewer/hurricane/viewer/NetlistWidget.h b/hurricane/src/viewer/hurricane/viewer/NetlistWidget.h index 1558bb8c..bc8a8033 100644 --- a/hurricane/src/viewer/hurricane/viewer/NetlistWidget.h +++ b/hurricane/src/viewer/hurricane/viewer/NetlistWidget.h @@ -180,14 +180,17 @@ namespace Hurricane { void NetlistWidget::setCell ( Cell* cell ) { _cell = cell; - _view->selectionModel()->clear (); - _baseModel->setCell ( cell ); + _view->setVisible( false ); + _view->selectionModel()->clear(); + _baseModel->setCell( cell ); string windowTitle = "Netlist" + getString(cell); - setWindowTitle ( tr(windowTitle.c_str()) ); + setWindowTitle( tr(windowTitle.c_str()) ); - _view->selectRow ( 0 ); - _view->resizeColumnToContents ( 0 ); + _view->selectRow( 0 ); + for ( int i=0 ; i<_baseModel->columnCount() ; ++i ) + _view->resizeColumnToContents( i ); + _view->setVisible( true ); } From ed557d9027c31acf6ff3e7615fc1c4226aaa2811 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sun, 16 Aug 2015 23:29:28 +0200 Subject: [PATCH 04/60] Added support for "same layer" dogleg. Big fix for pad routing. * Change: In Knik, in Vertex, add a "blocked" flag to signal disabled vertexes in the grid (must not be used by the global router). Modificate the Graph::getVertex() method so that when a vertex is geometrically queried, if is a blocked one, return a non-blocked neighbor. This mechanism is introduced to, at last, prevent the global router to go *under* the pad in case of a commplete chip. * New: In Katabatic, in AutoSegment, a new state has been added: "reduced". A reduced segment is in the same layer as it's perpandiculars. To be reduced, a segments has to be connected on source & target to AutoContactTurn, both of the perpandiculars must be of the same layer (below or above) and it's length must not exceed one pitch in the perpandicular direction. To reduce an AutoSegment, call ::reduce() and to revert the state, call ::raise(). Two associated predicates are associated: ::canReduce() and ::mustRaise(). Note: No two adjacent segments can be reduced at the same time. * Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad() to connect to the pads. Create wiring, fixed and non managed by Katabatic, to connect the pad connector layer to the lowest routing layers (depth 1 & 2). The former implementation was sometimes leading to gaps (sheared contact) that *must not* occurs during the building stage. Remark: This bug did put under the light the fact that the initial wiring must be created without gaps. Gaps are closed by making doglegs on contacts. But this mechanism could only work when the database if fully initialised (the cache is up to date). Otherwise various problems arise, in the canonization process for example. * New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(), when anchored on a RoutingPad, now take account the potential rotation of the Path's transformation. Here again, for the chip's pads. * New: In Kite, support for reduced AutoSegment. TrackSegment associateds to reduced AutoSegment are *not* inserted into track to become effectively invisibles. When a segment becomes reduced, a TrackEvent is generated to remove it. Conversely when it is raised a RoutingEvent is created/rescheduled to insert it. All this is mostly managed inside the Session::revalidate() method. * New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip, mark all global routing vertexes (Knik) that are under a pad, as blockeds. * Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and Y coordinate of the chip size. Did not show until a non-square chip was routed (i.e. our MIPS R3000). * Change: In Stratus1, in st_placement.py add the ClockBuffer class for backward compatibility with the MIPS32 bench. Have to review this functionnality coming from the deprecated placeAndroute.py. In st_instance.py, no longer creates the Plug ring of a Net. In my opinion it just clutter the display until the P&R is called. Can re-enable later as an option (in Unicorn). * Change: In Unicorn, in cgt.py, more reliable way of loading then running user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py . --- crlcore/etc/common/display.conf | 16 +- crlcore/src/ccore/RoutingGauge.cpp | 13 +- crlcore/src/ccore/crlcore/RoutingGauge.h | 2 + crlcore/src/ccore/crlcore/Utilities.h | 2 + crlcore/src/ccore/toolbox/ToolBox.cpp | 27 +- cumulus/src/plugins/ChipPlugin.py | 4 +- cumulus/src/plugins/chip/PadsCorona.py | 16 +- katabatic/doc/AutoContact.dox | 11 +- katabatic/doc/AutoSegment.dox | 85 +++++- katabatic/doc/images/reduce-1.fig | 108 ++++++++ katabatic/doc/images/reduce-1.pdf | Bin 0 -> 8496 bytes katabatic/doc/images/reduce-1.png | Bin 0 -> 8696 bytes katabatic/src/AutoContact.cpp | 4 + katabatic/src/AutoContactHTee.cpp | 25 +- katabatic/src/AutoContactTerminal.cpp | 67 ++++- katabatic/src/AutoContactTurn.cpp | 8 + katabatic/src/AutoContactVTee.cpp | 4 + katabatic/src/AutoHorizontal.cpp | 3 +- katabatic/src/AutoSegment.cpp | 164 +++++++++-- katabatic/src/KatabaticEngine.cpp | 7 +- katabatic/src/LoadGrByNet.cpp | 258 ++++++++++++++++-- katabatic/src/katabatic/AutoContact.h | 19 +- katabatic/src/katabatic/AutoContactHTee.h | 1 + katabatic/src/katabatic/AutoContactTerminal.h | 1 + katabatic/src/katabatic/AutoContactTurn.h | 1 + katabatic/src/katabatic/AutoContactVTee.h | 1 + katabatic/src/katabatic/AutoSegment.h | 84 +++--- katabatic/src/katabatic/Session.h | 22 +- kite/doc/Session.dox | 10 +- kite/doc/TrackSegment.dox | 8 +- kite/doc/notes.dox | 8 + kite/src/BuildPowerRails.cpp | 4 +- kite/src/KiteEngine.cpp | 27 +- kite/src/NegociateWindow.cpp | 1 + kite/src/ProtectRoutingPads.cpp | 7 +- kite/src/RoutingEvent.cpp | 3 +- kite/src/SegmentFsm.cpp | 63 +++-- kite/src/Session.cpp | 65 +++-- kite/src/TrackCost.cpp | 29 +- kite/src/TrackElement.cpp | 2 +- kite/src/TrackFixedSegment.cpp | 14 +- kite/src/TrackSegment.cpp | 2 +- kite/src/kite/RoutingEvent.h | 8 +- kite/src/kite/Session.h | 1 + kite/src/kite/TrackCost.h | 13 +- kite/src/kite/TrackElement.h | 2 +- kite/src/kite/TrackSegment.h | 2 +- knik/src/Graph.cpp | 6 +- knik/src/MatrixVertex.cpp | 18 +- knik/src/knik/Vertex.h | 110 ++++---- stratus1/src/stratus/st_instance.py | 2 +- stratus1/src/stratus/st_placement.py | 66 ++++- stratus1/src/stratus/stratus.py | 2 +- unicorn/src/cgt.py | 35 ++- .../utilities/src/vlsisapd/utilities/Dots.h | 2 +- 55 files changed, 1131 insertions(+), 332 deletions(-) create mode 100644 katabatic/doc/images/reduce-1.fig create mode 100644 katabatic/doc/images/reduce-1.pdf create mode 100644 katabatic/doc/images/reduce-1.png diff --git a/crlcore/etc/common/display.conf b/crlcore/etc/common/display.conf index d77430a1..7d04738d 100644 --- a/crlcore/etc/common/display.conf +++ b/crlcore/etc/common/display.conf @@ -172,14 +172,14 @@ stylesTable = \ # Blockages. , (Group , 'Blockages') - , (Drawing, 'blockage1', { 'color':'Blue' , 'pattern':'light_antislash0.8', 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage2', { 'color':'Aqua' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage3', { 'color':'LightPink', 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage4', { 'color':'Green' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage5', { 'color':'Yellow' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage6', { 'color':'Violet' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage7', { 'color':'Red' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) - , (Drawing, 'blockage8', { 'color':'Blue' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':2 }) + , (Drawing, 'blockage1', { 'color':'Blue' , 'pattern':'light_antislash0.8', 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage2', { 'color':'Aqua' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage3', { 'color':'LightPink', 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage4', { 'color':'Green' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage5', { 'color':'Yellow' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage6', { 'color':'Violet' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage7', { 'color':'Red' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) + , (Drawing, 'blockage8', { 'color':'Blue' , 'pattern':'poids4.8' , 'threshold':0.80*scale, 'border':4 }) # Knick & Kite. , (Group , 'Knick & Kite') diff --git a/crlcore/src/ccore/RoutingGauge.cpp b/crlcore/src/ccore/RoutingGauge.cpp index 2fcfb504..3e503b48 100644 --- a/crlcore/src/ccore/RoutingGauge.cpp +++ b/crlcore/src/ccore/RoutingGauge.cpp @@ -1,20 +1,20 @@ // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2015, All Rights Reserved +// Copyright (c) UPMC 2008-2015, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | Alliance / Hurricane Interface | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./RoutingGauge.cpp" | // +-----------------------------------------------------------------+ -#include +#include #include #include #include "hurricane/Commons.h" @@ -49,6 +49,9 @@ namespace CRL { // Class : "RoutingGauge". + const size_t RoutingGauge::nlayerdepth = std::numeric_limits::max(); + + RoutingGauge::RoutingGauge ( const char* name ) : _name (name) , _layerGauges() @@ -150,7 +153,7 @@ namespace CRL { if ( _layerGauges[i]->getLayer()->getMask() == bottomLayer->getMask() ) return i; } - return UINT_MAX; + return nlayerdepth; } @@ -160,7 +163,7 @@ namespace CRL { if ( _layerGauges[i]->getLayer()->getMask() == layer->getMask() ) return i; } - return UINT_MAX; + return nlayerdepth; } diff --git a/crlcore/src/ccore/crlcore/RoutingGauge.h b/crlcore/src/ccore/crlcore/RoutingGauge.h index 83ff3138..8c512496 100644 --- a/crlcore/src/ccore/crlcore/RoutingGauge.h +++ b/crlcore/src/ccore/crlcore/RoutingGauge.h @@ -48,6 +48,8 @@ namespace CRL { class RoutingGauge { public: + // Constants. + static const size_t nlayerdepth; // Constructors & Destructors. static RoutingGauge* create ( const char* name ); virtual void destroy (); diff --git a/crlcore/src/ccore/crlcore/Utilities.h b/crlcore/src/ccore/crlcore/Utilities.h index 9dbaf189..1d5fe796 100644 --- a/crlcore/src/ccore/crlcore/Utilities.h +++ b/crlcore/src/ccore/crlcore/Utilities.h @@ -273,6 +273,7 @@ inline std::string tty::bgcolor ( unsigned int mask ) template inline mstream& operator<< ( T* t ); template inline mstream& operator<< ( const T& t ); template inline mstream& operator<< ( const T* t ); + inline mstream& put ( char c ); inline mstream& flush (); // Overload for manipulators. inline mstream &operator<< ( std::ostream &(*pf)(std::ostream &) ); @@ -290,6 +291,7 @@ inline std::string tty::bgcolor ( unsigned int mask ) inline unsigned int mstream::getActiveMask () { return _activeMask; } inline void mstream::setStreamMask ( unsigned int mask ) { _streamMask |= mask; } inline void mstream::unsetStreamMask( unsigned int mask ) { _streamMask &= ~mask; } + inline mstream& mstream::put ( char c ) { if (enabled()) static_cast(this)->put(c); return *this; } inline mstream& mstream::flush () { if (enabled()) static_cast(this)->flush(); return *this; } inline mstream& mstream::operator<< ( std::ostream& (*pf)(std::ostream&) ) { if (enabled()) (*pf)(*this); return *this; } diff --git a/crlcore/src/ccore/toolbox/ToolBox.cpp b/crlcore/src/ccore/toolbox/ToolBox.cpp index d3f94173..47def764 100644 --- a/crlcore/src/ccore/toolbox/ToolBox.cpp +++ b/crlcore/src/ccore/toolbox/ToolBox.cpp @@ -1,30 +1,29 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2012, All Rights Reserved +// Copyright (c) UPMC 2008-2015, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | Alliance / Hurricane Interface | // | | // | Author : The Borg Collective | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./ToolBox.cpp" | // +-----------------------------------------------------------------+ -#include "hurricane/Plug.h" -#include "hurricane/Pin.h" -#include "hurricane/Library.h" -#include "hurricane/Net.h" -#include "hurricane/Cell.h" -#include "hurricane/Instance.h" -#include "hurricane/Segment.h" -#include "hurricane/NetExternalComponents.h" -#include "hurricane/UpdateSession.h" -#include "hurricane/Warning.h" +#include "hurricane/Plug.h" +#include "hurricane/Pin.h" +#include "hurricane/Library.h" +#include "hurricane/Net.h" +#include "hurricane/Cell.h" +#include "hurricane/Instance.h" +#include "hurricane/Segment.h" +#include "hurricane/NetExternalComponents.h" +#include "hurricane/UpdateSession.h" +#include "hurricane/Warning.h" using namespace Hurricane; #include "crlcore/ToolBox.h" @@ -279,6 +278,7 @@ static void AttachPlugOrPin(Net& net) } + void createPartRing(Cell* cell, Name nom) { if (!cell) @@ -295,6 +295,7 @@ void createPartRing(Cell* cell, Name nom) UpdateSession::close(); } + void createPartRing2(Net& net) { UpdateSession::open(); diff --git a/cumulus/src/plugins/ChipPlugin.py b/cumulus/src/plugins/ChipPlugin.py index 7482547e..c61c6f16 100644 --- a/cumulus/src/plugins/ChipPlugin.py +++ b/cumulus/src/plugins/ChipPlugin.py @@ -95,8 +95,8 @@ class PlaceCore ( chip.Configuration.ChipConfWrapper ): coreAb = self.cores[0].getMasterCell().getAbutmentBox() if (not coreAb.isEmpty()): - if coreAb.getWidth () < self.coreSize.getWidth() \ - and coreAb.getHeight() < self.coreSize.getHeight(): + if coreAb.getWidth () <= self.coreSize.getWidth() \ + and coreAb.getHeight() <= self.coreSize.getHeight(): self.coreSize = coreAb else: print ErrorMessage( 1, [ 'Core %s already have an abutment box, bigger than the requested one:' diff --git a/cumulus/src/plugins/chip/PadsCorona.py b/cumulus/src/plugins/chip/PadsCorona.py index 2f61b752..b157dc96 100644 --- a/cumulus/src/plugins/chip/PadsCorona.py +++ b/cumulus/src/plugins/chip/PadsCorona.py @@ -57,10 +57,10 @@ class Side ( object ): def getAxis ( self, i ): - if self._type == chip.North: return self._corona.chipSize.getXMax() - self._corona.padHeight + self._corona._powerRails[i][2] - elif self._type == chip.South: return self._corona.chipSize.getXMin() + self._corona.padHeight - self._corona._powerRails[i][2] - elif self._type == chip.East: return self._corona.chipSize.getYMax() - self._corona.padHeight + self._corona._powerRails[i][2] - elif self._type == chip.West: return self._corona.chipSize.getYMin() + self._corona.padHeight - self._corona._powerRails[i][2] + if self._type == chip.North: return self._corona.chipSize.getYMax() - self._corona.padHeight + self._corona._powerRails[i][2] + elif self._type == chip.South: return self._corona.chipSize.getYMin() + self._corona.padHeight - self._corona._powerRails[i][2] + elif self._type == chip.East: return self._corona.chipSize.getXMax() - self._corona.padHeight + self._corona._powerRails[i][2] + elif self._type == chip.West: return self._corona.chipSize.getXMin() + self._corona.padHeight - self._corona._powerRails[i][2] else: raise ErrorMessage( 1, 'PadsCorona.Side.__init__(): Invalid value for sideType (%d)' % sideType ) return 0 @@ -224,14 +224,14 @@ class Side ( object ): def _routePads ( self ): for i in range(len(self._corona._powerRails)): if self._type == chip.South: - Horizontal.create( self._corona._corners[chip.SouthWest ][i] + Horizontal.create( self._corona._corners[chip.SouthWest][i] , self._corona._corners[chip.SouthEast][i] , self._corona._powerRails[i][1] , self.getAxis( i ) , self._corona._powerRails[i][3] ) elif self._type == chip.North: - Horizontal.create( self._corona._corners[chip.NorthWest ][i] + Horizontal.create( self._corona._corners[chip.NorthWest][i] , self._corona._corners[chip.NorthEast][i] , self._corona._powerRails[i][1] , self.getAxis( i ) @@ -239,14 +239,14 @@ class Side ( object ): ) elif self._type == chip.East: Vertical.create( self._corona._corners[chip.SouthEast][i] - , self._corona._corners[chip.NorthEast ][i] + , self._corona._corners[chip.NorthEast][i] , self._corona._powerRails[i][1] , self.getAxis( i ) , self._corona._powerRails[i][3] ) elif self._type == chip.West: Vertical.create( self._corona._corners[chip.SouthWest][i] - , self._corona._corners[chip.NorthWest ][i] + , self._corona._corners[chip.NorthWest][i] , self._corona._powerRails[i][1] , self.getAxis( i ) , self._corona._powerRails[i][3] diff --git a/katabatic/doc/AutoContact.dox b/katabatic/doc/AutoContact.dox index 142ab2af..4d4b623d 100644 --- a/katabatic/doc/AutoContact.dox +++ b/katabatic/doc/AutoContact.dox @@ -236,11 +236,16 @@ //! \function GCell* AutoContact::getGCell () const; //! \sreturn The GCell into which the AutoContact is located. - //! \function AutoSegment* AutoContact::getOpposite ( const AutoSegment* segment ) const; - //! \sreturn The AutoSegment other the same direction as \c segment, this is - //! only meaningful on AutoContactHTee or AutoContactVTee. It there is + //! \function AutoSegment* AutoContact::getOpposite ( const AutoSegment* reference ) const; + //! \sreturn The other AutoSegment the \e same direction as \c reference, this is + //! only meaningful on AutoContactHTee or AutoContactVTee. If there is //! no opposite, \c NULL is returned. + //! \function AutoSegment* AutoContact::getPerpandicular ( const AutoSegment* reference ) const; + //! \sreturn The AutoSegment in the \e perpandicular direction to \c reference, this is + //! only meaningful on AutoContacTurn. It there is no unique perpandicular, + //! \c NULL is returned. + //! \function AutoSegment* AutoContact::getSegment ( unsigned int index ) const; //! \sreturn The nth anchored AutoSegment. The index is significant: //! - \b 0 : first horizontal (\b h1). diff --git a/katabatic/doc/AutoSegment.dox b/katabatic/doc/AutoSegment.dox index 3e6daeaa..26d61c44 100644 --- a/katabatic/doc/AutoSegment.dox +++ b/katabatic/doc/AutoSegment.dox @@ -68,6 +68,9 @@ * This operation is used to slacken the constraints on a segment * or restore connexity on source/target contact after a layer * change. The new segment is always created on the source. + *
  • Reduction/Raising. When a segment is a short dogleg, + * no greater than one picth, it can use the layer of the + * perpandiculars. * * * @@ -97,6 +100,8 @@ *
  • The interval giving the complete length of the AutoSegment, * that is, with all extentions cap taken into account. * This interval is refered as the \e span. + *
  • A small counter, of the number of reduced neighbors (never + * exceed two). * * * @@ -197,6 +202,10 @@ //! \var AutoSegmentFlag::SegTargetBottom //! The target contact of this segment is connected to the bottom layer. + //! \var AutoSegmentFlag::SegIsReduced + //! This segment is the perpandicular part of a dogleg which will use the + //! same layer as the parallels. + //! \var AutoSegmentFlag::SegLayerChange //! This AutoSegment has been created to to reconnect parts of an AutoSegment //! after a layer change. @@ -273,10 +282,11 @@ //! \c source or \c target are not the one decorating the anchors, an //! exception is thrown. - //! \function AutoSegment* AutoSegment::create ( AutoContact* source, AutoContact* target, unsigned int flags ); + //! \function AutoSegment* AutoSegment::create ( AutoContact* source, AutoContact* target, unsigned int dir, size_t depth ); //! \param source The source AutoContact. //! \param target The target AutoContact. - //! \param flags Specify the constructor behavior. + //! \param dir Specify the segment direction. + //! \param depth The layer, given by it's depth in the RoutingGauge. //! \return The AutoHorizontal/AutoVertical. //! //! Factory method to create AutoHorizontal or AutoVertical. @@ -391,6 +401,22 @@ //! \sreturn \true if segment is a strap used only to connect between two different //! metal layers on the way up or down. + //! \function bool AutoSegment::isSpinTop() const; + //! \sreturn \true if segment is connected to turns and both perpandiculars segments + //! are in the \e top layer (candidate for reduction). + + //! \function bool AutoSegment::isSpinBottom() const; + //! \sreturn \true if segment is connected to turns and both perpandiculars segments + //! are in the \e bottom layer (candidate for reduction). + + //! \function bool AutoSegment::isSpinTopOrBottom() const; + //! \sreturn \true if segment is either spin top or spin bottom + //! (candidate for reduction). + + //! \function bool AutoSegment::isReduced() const; + //! \sreturn \true if segment is actually in a reduced state: it's effective layer + //! will be the one of it's perpandiculars. + //! \function bool AutoSegment::isStrap() const; //! \sreturn \true if segment has been created from a slackening operation to //! restore the slack of another segment. @@ -427,6 +453,20 @@ // \function bool AutoSegment::canDesalignate( AutoContact* contact ) const; // \sreturn \true if \c contact restrict the slack of the segment. + //! \function bool AutoSegment::canReduce() const; + //! \sreturn \true if the segment can be reduced. That is: + //! - Source & target are AutoContactTurn. + //! - It is either spin top or spin bottom, that is + //! connecting perpandiculars both in the same layer. + //! - Has a length less or equal one pitch in the perpandicular direction. + //! - Neither of the perpandicular are also reduceds. + + //! \function bool AutoSegment::mustRaise() const; + //! \sreturn \true if the segment must \e be reduced. That is: + //! - It is in reduced state... + //! - It is no longer spin top or spin bottom. + //! - It's length exceed one pitch in the perpandicular direction. + //! \function bool AutoSegment::canSlacken( unsigned int flags=0 ) const; //! \sreturn \true if the segment can be slackened. That is, source or target constraints //! are less than three pitches. @@ -806,6 +846,40 @@ //! Perform operations that must be done before the actual destructor is //! called. Merely whidrawn the AutoSegment from the lookup/Session mechanism. + //! \function bool AutoSegment::reduce (); + //! Sets the segment into reduced state. + //! + //! \sreturn \true if the operation did succeed. The layer will not be actually changed + //! until the Katabatic database is saved/destroyed. + //! + //! A segment can be reduced if: + //! - Source & target are AutoContactTurn. + //! - It is either spin top or spin bottom, that is + //! connecting perpandiculars both in the same layer. + //! - Has a length less or equal one pitch in the perpandicular direction. + //! - Neither of the perpandicular are also reduceds. + //! + //! \image html reduce-1.png "Reduce Example" + //! + //! If segment \c id:12 is reduced, it prevents \c id:10 & \c id:14 to + //! be also reduced, by increasing the \c _reduced counter. In this + //! example \c id:14 is spin top and \c id:12 is spin bottom. + //! + //! If we reduce two adjacent segments, one will go up while the other + //! will go down (they will actually exchange their layers), it will + //! thus defeat the purpose of creating a same layer dogleg. + //! Besides, the turn contact between them will be changed into a pure + //! metal one, generating a disconnexion... + //! + //! \see AutoSegment::raise() + + //! \function bool AutoSegment::raise (); + //! Get a segment out of \e reduced state. + //! + //! \sreturn \true if a state change did really take place. + //! + //! \see AutoSegment::reduce() + //! \function AutoSegment* AutoSegment::makeDogleg ( AutoContact* from ); //! \param from The AutoContact \e from which we want to make a dogleg. //! @@ -969,4 +1043,11 @@ //! //! \image html _slacken-2.png "slacken() for an Horizontal (special cases)" + //! \function bool AutoSegment::reduceDoglegLayer (); + //! + //! Perform the actual layer change on a reduced segment. This method is to + //! be called juste before destroying the Katabatic database. + //! + //! \sreturn \true if a change occurs. + } diff --git a/katabatic/doc/images/reduce-1.fig b/katabatic/doc/images/reduce-1.fig new file mode 100644 index 00000000..c378c196 --- /dev/null +++ b/katabatic/doc/images/reduce-1.fig @@ -0,0 +1,108 @@ +#FIG 3.2 Produced by xfig version 3.2.5c +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +0 32 #ffffde +6 450 900 750 2250 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1125 675 975 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1200 675 1050 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1275 675 1125 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1350 675 1200 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1425 675 1275 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1500 675 1350 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1575 675 1425 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1650 675 1500 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1725 675 1575 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1800 675 1650 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1875 675 1725 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1950 675 1800 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 2025 675 1875 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 2100 675 1950 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 2175 675 2025 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 525 1050 600 975 +2 1 0 1 1 32 50 -1 -1 4.000 0 0 -1 0 0 2 + 600 2175 675 2100 +2 2 0 2 1 32 50 -1 -1 6.000 0 0 -1 0 0 5 + 525 975 675 975 675 2175 525 2175 525 975 +-6 +1 2 3 1 4 7 40 -1 -1 4.000 1 0.0000 1800 1800 375 900 1425 1800 2175 1800 +2 2 0 4 0 32 40 -1 -1 10.000 0 0 -1 0 0 5 + 525 1125 675 1125 675 1275 525 1275 525 1125 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 1050 1200 1050 900 1350 900 1350 1200 +2 1 0 2 1 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 675 1200 1800 1200 +2 1 0 4 0 32 40 -1 -1 0.000 0 0 -1 0 0 3 + 1650 1200 1800 1200 1800 1350 +2 1 0 2 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 1800 1200 1800 2400 +2 1 0 4 0 32 40 -1 -1 0.000 0 0 -1 0 0 3 + 1950 2400 1800 2400 1800 2250 +2 1 0 2 1 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 1875 2400 3000 2400 +2 1 0 4 0 32 40 -1 -1 0.000 0 0 -1 0 0 3 + 2850 2400 3000 2400 3000 2550 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 1800 1650 2100 1650 2100 1950 1800 1950 +2 1 0 2 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3000 2400 3000 3600 +2 1 0 2 1 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3000 3600 4125 3600 +2 1 0 4 0 32 40 -1 -1 0.000 0 0 -1 0 0 3 + 3150 3600 3000 3600 3000 3450 +2 1 0 4 0 32 40 -1 -1 0.000 0 0 -1 0 0 3 + 4050 3600 4200 3600 4200 3750 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 3000 2850 3300 2850 3300 3150 3000 3150 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 2250 2400 2250 2100 2550 2100 2550 2400 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 3450 3600 3450 3300 3750 3300 3750 3600 +2 1 0 1 4 7 40 -1 -1 4.000 0 0 -1 0 0 2 + 2025 1050 2400 900 +2 1 1 1 0 7 40 -1 -1 4.000 0 0 -1 0 0 2 + 1875 1200 4200 1200 +2 1 1 1 0 7 40 -1 -1 4.000 0 0 -1 0 0 2 + 3075 2400 4200 2400 +2 1 0 1 0 7 40 -1 -1 4.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 4125 1200 4125 2400 +2 2 0 0 0 32 70 -1 21 2.000 0 0 -1 0 0 5 + 0 600 5700 600 5700 5100 0 5100 0 600 +4 1 0 50 -1 14 12 0.0000 4 120 240 1950 1875 12\001 +4 1 0 50 -1 14 12 0.0000 4 120 240 2400 2325 14\001 +4 1 0 50 -1 14 12 0.0000 4 120 240 3150 3075 16\001 +4 1 0 50 -1 14 12 0.0000 4 120 240 3600 3525 18\001 +4 1 0 50 -1 14 12 0.0000 4 120 240 1200 1125 10\001 +4 1 0 50 -1 14 12 0.0000 4 120 360 1200 1425 r:1\001 +4 1 0 50 -1 14 12 1.5708 4 120 360 1725 1800 r:0\001 +4 1 0 50 -1 14 12 1.5708 4 120 360 2925 3000 r:0\001 +4 1 0 50 -1 14 12 0.0000 4 120 360 3600 3825 r:0\001 +4 1 0 50 -1 14 12 0.0000 4 120 360 2400 2625 r:1\001 +4 1 0 50 -1 14 12 0.0000 4 120 120 2250 1875 R\001 +4 0 4 40 -1 16 12 0.0000 4 195 2280 2475 900 Segment id:12 is reduced.\001 +4 0 0 40 -1 16 12 0.0000 4 195 4950 300 4500 As segment id:12 is reduced, reduced count is increased\001 +4 0 0 40 -1 16 12 0.0000 4 195 5175 300 4800 on segments id:10 and id:14 which then cannot be reduced.\001 +4 1 0 40 -1 16 12 1.5708 4 195 915 4050 1800 1 M2 pitch\001 diff --git a/katabatic/doc/images/reduce-1.pdf b/katabatic/doc/images/reduce-1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..60749cee6b38ab25c556e4bff53554b002c612eb GIT binary patch literal 8496 zcmb_?2|QHm8*nMfXjMd%lUqhI&MaoeOpNT2Ercv(%p6Q+Yi2OCFA_>pB#AZ(Nm3!= zk|If@B1_py60(+b`OXYVxBLJ8|L^G7|_b~>a#K?DEg>^CxLW@y4O zw9M5-Wc}i8nz&xUyL5Jb=oXvg<0`2MmP#4$ZCyrbDzfHLSF+RjZ6l)5IrvuGr67WH z(qOoXXLS~%t;spCp=-;_Q;c_i*$&ZN+ODjwEcX0>dM4DVNoz-Xo=nZS_NS6o^R2YR zOW%%vz}AMgc$85-@SRf^k3O#@KQ&CNN)haQ^Fg!vvU$`;V_!?4M*U)QTDxjh`?@WQ zSc0|EZSe&HGxIf)4TdQN1A3d?P3`Koa{a@bu?zg^x%Ro`$G#|bEnVU(U@OX>PE)+9 z+F7)%xnHo?WkE1d=nLjN-ql!WQ2i&x1EJ8NUo(&6q|-F>_JNn#@e6pe&=s%Ke_Z$K zb33;zt+!a{-0XeFw0LpL9Ovec&_27xN1c5-_ERj^CYN;@N+m})#p&GRUnFULbCd#6 zkF1?kGNPi18xrXy4$`l#8Mu6=Mclz%3p($4(qOI9s*v4A?Rn8T@`**ylNNQ>E)(4A zS^glE+$nvcXk#yiCIswx@7j)#rMXRt~dSb>P5>OO>_3s=O>%o)IRw+F8=z!M@_dq zxUwxK=+3#c*#kiToAPc;8!Oo(249R`g?ZNBYt!z4Zd)cTeY` z8@FoxF${btTpsbbV()M^@~Xw)Q*CtfkM>JQoPmq1P{c^0X3=@Z14CaJ#fW45~Sb-@Q49>kqIw7sF} zc5rF;`x!OeE!^?B+lk%tpVdc|JUXKtVnJ?{%uj5&d_X0yl;Qd|2(@=s@3PU45Su<3 zbnr+NsG{%`ed`eMh{-AKpE2wZ$b~>#sy75$L39SykRt?K(J&aNjRUYmj5`7b@*uVV zz=@(90op-)jvtQ(@!|Nl<#A~CkiZp$GXwxSKtchGZXy(z*$dzt0AR2aB&Hmg95X== zrv%Uleug>n0Z}TkL%>s$Vu?^DQVYxtmJ1LI#s|Pn3_2fhMTo? z#}k05KeTxClj0W+uu2F7k)!<6rGpds=9J?9GoA=zYBfA;fT{7%5f&>7IMF5IISCg_ z35T<22Bs3pC4!&iNWW?4mWMad2#`5Z4$g597k|MQwQxp8i&bY zgW|t~y&IE9fxLMgm1}D0d8aW4 zACJYy59D{W2PS+8To_?)tPs&wl$mUpWx(0Cf`EW)GrYv(-B?1T6slOZ zzP;!UR+;V@X>N_07k29Mk^$QxH+tZLC2hjK>SSkocIfLr>GD-i-fpsV$>hCDRa}kL z&!4HXWyk<^}wxI*GO1C-z5$c)9&@YrjvYr8*zkbb8mB^ z2?wJvKQ}j7H7M{CBIvx!id+|GLO!dEVjFAIi+&gTVRq2-BF)(kZhBXQf}F;s=@D)r z)V!NR3cy$4_#?J04d0Q%Fk`Yc>rYGAgpLj~M!_+8ev&Ux1yoBht zCX5#5wN}?b>Fns%2XkeXs@%AdSLOU&|QT*@o+GJCL6!%gvAWQv(9!5Xhw;RrU@g^eph5 zV|F~tQvH?otk*BATi9tkGZ2d$R}-cytV=lNgL5BmNfW=HAb^^xq0_Y-@%ck@{eK`&fW z+q(lff0B=~cBSK9D(!oUo=0r4%PXy|sU^%fv>H+WmAms+fevX)XLFK6?V7?4-N@|; zHVwH}8CG?V2Ai@|lVh`wT~u(SRHSaDFO9K%sGcpo$IN{w_t^uvD0lveGyU!LACh)8 zj%MtL4(sc#KV-gs+Z8jw<##EX7pWgO4k{Vozl0 zr4kGttnT@1;j_8TGppl|JPg_DpjPtym=Litwuhmmq?^(m8aX%R;T+Rb^sqVjTnogG zfZO^hA-T@Fa}RMd@0Yd}ekzb!xN&Su<;CSO*KE$0QgCyBj=@;#4?1ME z)fmdEt6wXc>cejF%C<(fX?zeUr=@e8-t^85x)pSGu(KC;YCO6VBh#)wu;(zw)pYjU z9F}Hfu#B=x%<_@3b^B`1zTHRe4pv$%n-($>8L(s_#wDpJ_Kd_<`ZhCa?c?F(S3&Rk zdg{q$H7S+bt}ZN7+UtI+$WGygWA}PnxAMaBw6ce89K@ zA#RP1%cAn!v^<%Wby@nvayspn$GlOgQN;rxqT>APhErT||Cb{1kEMI6LSQjE0Fi(N zh}xK`5`hzC_lXh!&rUB7;>RE50Ve$q^#R@&!6jjO5r7LK0-P!Wc--_NU;tWy_8=AX z1Zk7yfW~35s30ALCQ5=g=mRo97RUxU;_|=+xe$-Rp^NGS$mddN5GW8=3qLU6_lhCj z{Z6YG(|%b0?-c_Jzw5M$vE{Uk!xC@#Qtx?Z&pIBCdc7DGcg06;=}fs=DMT3H(Kc(* z(%q&<_pd%+IOF1u^x@#dx{n_%nl#o@HZ;m+YDl5@l5Kp{`p! z>V%he;v1DCjZj%ry61~cN^(^_lKX}aTVUjoAC zJvbKUT~Yb?Dem2}9ko}rENYUx>1qmwFR~;g4k2x*3fsM;vrdQ7WMd&q)l((cJyc^y zELSfnGseioDyYS5Ejx@3R}7^ps(2~1Jr-gRrgYPqa*Q(W+*+^YuNN~_8%oB=^x;V6 zYul~&u3NwAmGAPmSh?!0Rz|Z#?)kwPKIsyjtjqtny?(9{#E6zK)r10aB zD8DG?$PBY#(mY;k<;h##b4G09C2zg^j7&2o@S7I|w6Dy0?6#lS=pb+|4x$E}$gX>P z;Axc4&bVC{6UJ>el{Ve|=5Rdfd;Ou8`7G)aouoQ_sWnQDW^?@$3Rt(AXUMqH4ym1+ z7ty*r^jKo+CROt*P0PMhcfYldmC0N+i+*W`Q|#c)HOJ;56L#_sO0=PXgRPr<3(Mt7 z!jR5#Pj4*MdYx~w35T(`&po#OTwP>s#O%+xQksVi+qD%89W*laWgmJcp=9qB3)Nq3 zTv(7`l3!N!Fzeu!OVAECqVQlxG&`?+R*xO)Nq3l%_RVZz$B|8S^UvJ8tou>7(bmcD z)8}eECx7XHuc)Nnp86xR`>a)667TRLJ|DFh{hWJyfKbOi)e>B1R6o-DVI5sT_Gl^d z>EW|OjL%^PP?G@KWHR&laZB^p3Yn%(!&?vVx{AImDA>Nv@*PF>L4BKtwjBCW_E4x_ z_gReDmWv^m$34H#dl`|>O}_V6(D9vHQ=ZRCwIcQ%_J4@{taaAN_4DlE=MGnk>J;fr z`e1-H{)_|72L*zE<=DM0;*4^;DzhUa$12BM=Qt4-R{^^6NEkHj=eUOF@fL z^j@)DHN*NSBJ|}ecYDvhM`}(iWLSMY>tA(nc?7X>k*aWE=^Xl_;1}34M~nc%6XZ@> z{7l-;{onoA`M3>MQU=Pib)NQzG%isd49As0iuPtNtdyCXUo>1e_I}rbL}ujOGrRY{ zF+13oeyG%e8{K=NVB;08)n1n)Sg>P-(PQ4lGYzBNof_+8$z55ewv6bOtJf*#9m>zo z{cz}ddN_Y5&Gt6HM)o-@mL=YkZ;; zS6dj}nq}+MB*?wnzwK=K-sUQ^XsGzYnV7Sgj}X*%Vecz*^{O_`-%|Anz46(+eCNi% z^Glv--tfh~8Jr2Jl&z8|PS#sfKC+G%lbmuPEM#Yi=8%5Ci%VOJ3h&g&m^s+5rxz{h zJhZ7{%*8qS&4rY(3kgEh(VUZWu~%*87c{?oDZQ^QBd(Hlw!m5`^za4f{AYxa=-L|) z@2--${as5=a79EJ?`}=RmwHHtrsIPtJMR&oaJ1yqG4BN9-p{9(#NAmjODe@Wa(r7O zMoD|PBJUkazHNoW`8xC=bXjNs*A-%aE$HOp24gZgIlE+~?`ZPg%jpH+q>_o7GuohACqoT|im( z_V5J9gBJcVITXWVE1KVFK&H8u%IECsou4fXch`xHqr@*$*>~A}vs{~zskNGf^f|}H zerj8XM(SgT;AO&~$-5E4st~i24YhI#14CV5j=+lYMh^LQXLE$jn+*A}vhIN_O-UQN zN$rWT^lgjsK58j5XFYT3Gh80abXh%w4_?A)jaH!Gg|C5wF4w=fk*W)Uo?UZ6@AX0I zbD$N6j&zQwNSsi4TafD(ctyBRs~*rbyXejz84C2Zl9)oR*C;$=cl7a_n3DDNbU&Uqmb9Wcj*2^+kB~ z{Z7D$Fz7xq5_jZTnrk)w#hI%20rC0O=!5;AH#$O3(z0EY_RhYDU+Zxu%B7cB@@%L3 zo7Ogi597_AZLBesGZ}aH@hz5JUj1yFWyY&35AP)lwa3w!)%q5$H?>VtIMpjdldEhV9f=o`weKEH3!r)q5kU4DV>PAP6m zyXKwsQEfs!stobe=7$HpZq6aNaj1P26va2JQ}N)=(HrsC@3?<+8aSF52R2^qiq}fq z<6f~qR#&!*w9sCXaOS}!o|UBco{>u1uF{^KfZ^PQwAgV8`QgM{|FCJCYE!~}MR8|g zs#W*%x3aU9<&PiA+IZ}bZI7_d)_VJYN8# zML@zVd2}zb9o#IPU&lu^A9pMUrQ{L7Q8hD8O|U^3k^;!G}V`3aM*xoVX7y`PoRhN^JCD-RBaNG zNT7M5h%{{?3WM=NqtNgNMb*(EdJ$<xI0%krOzF?wl36QkVL?k%*`u~oYV(HJ}m zt%Jf4956&O7Ei|OtV3hTXtXZ)H%!?0FsTuIb_Jhh{STzmFsG4ncn+{jP`nu4SUThn zI6^$W$QC#)EMQ9&(0rJXKg0y^^oixgJSItWL6O0xsp{WW9+hil^?z3%izV`J5gyr? zL-S+7jW=`S{}=E1w+&9G{ScVz$76~^g-!z@CM1%L58E6AOH8Mcy*NA;6?SwgmkW0Y zsRCH%Anc$>iY^QkFa%79A`V0YreI>gWQYQb%%rlt^^igo9rB|3F$G8p4-z>veD(=j zaKa)?24!L(rUifUgGV%xw{Un9EbXD4Q@klVxU>ySi0exQ)GZ(?8)XY~2jEsC*H5ta zZ*0Y6BDO!6{evTjr{F9C`vmwSM^O;Kzx4U{82wDlaF0L_86Zl#zjX^lJ?qJ4!BhrO z|EC197XH02(lBgIQADa6lSSc-*1-@kL@Zt$$w)LB38TRg|6ed1L{6YS-MmxWIXw0M z8m=&|fuFz!M*V47x8F?bws!50Gb14n@`Bs<7$QQHWG6lV0guPw0WV;34ujEwo9m(v zz@C~T5{YnE;MX|}1_!tJf1N{RRvJorBn z0MMQh1Rp#S0nm=aflmlw-?9ThbG8=;m^_R$HwIjFO>|654ACYe1B{6&L7Sv)XkcVw otfP(AHijJvZ)`;Q?-=f)vqQds$`goz4=ltW8vpcwKE(Qep;T002O$uBN01 z0APh+8ZRL>W<=*fi7Tcf@>VnT0{}?0|87`sUnj9)27wS|6NtW-BjmM>uLD3;SBpi} z*~<^&XXoqU4PlXdE+7spldizXDXA;T8@wqzD(b0amwZ1;EsTdZ{08AhVjwR&XmXMA z&8SN7Fnq|&qduGH!L-CR;73Z{1=ebowKc6!ecR{xTBlFCw5~P`i}^8;sA*B{ss^D` z3gYO>KV$c)Zac|I28FsxH{1JaAXhlj2_FDx`}1`f(;YvEBLkE^BL@P&hAbdJcr6$L z02oH>0|2$yb65ZaymA~sHL(%_K$kiWZowL$b!gIJYdgB&DF-f^gw$_V&4DU|h~e}^jbTJvT5@enh%J$AX@#XdoXU{%ToQ;WM( zbd9(ko3a;-Z_l`wIiIoM>x+n>is!TM+B@6@%A#EVRNeB~B{iA?Zv8yuOr3wKi0S4P zQ9IBzeTSDW`>sq5N0<0j#)>1F)z^iR?X*P7MY_G&;Azw75f-<&mQlOQ(N zqaW!yWdV!3Nv zO3Pod7G#2KPKxuFn{xOws~etyA;%;cbi!E`a+5Opu}g2c_w7a~xPDQ*W%=AHGKLTI z5cQZnddk`Ar*%Ck(ui;(GRQ)xA?VOaQ%7=lUo9+pZ8>H8pN(M`7~6u=O3*z`|AQbMLKe==8_vef4z(mt#j*c*I^ql%})iJ54vBsx_?S~^*c)|)w!ih zGJ)R`@xjFJlSv)VP;6tlJ6lnks*}=M4X#&Su^&voE=0df*;+7srM z39zz?*+@fft{ekOAH-=J1+~elG2|PndU?_z+PHV3eu-}XfCg+vUKvmVp&Q(1+V|Hd zCozKOceiq$j^3r!t4Ww(TjazpxKZCIrOXG*GX!vX`*zqi*$M;rJ0 z{HM4GhkYnN{hL`$bDv%6yV zt0w2B=#3&!eQ)nNUmh4^0L;Ep<~~0;aXa8OKFC3!`0TW5ywLDpMhDde+K;3ccX|AE zT?ak4rEZ;#@KgafAI%Tq;9F?qydG;dlbm z!p`c(hm)Bw87gBiTVj^GgMIZs8#O9$JDAmD&rZn(K_7(I=ovx^w{fzspjD)bWlfTB zuPzm_3wU(UxH-`rR$_VWzO-yu+bBV;8{z;G#4{v5nCc6<4fd5R>bt!=J>R~5E8BS< zPj6qXJZiwDpR~HxNEB{&F?ycfo-@(VqvTr2Bg$#1(dm`Ecsa;?ceFivZ<`eQ=NBwC zmRW;Qp9~sCwebWBBe5w`SEvwdh9Y`}T`w&0_Q2B8A=xLeiStvoTwM#opKnS|^JqTR zbH?k%B2b8Bqp9rG2zw+`oFrbx?eo^3J>nv64-1RbPcG3pO)qkJ+Hl5GQ{TELt5x-) z0|hiHfGw<5v3ju&nZv}}sr{h7Xbn6ScAX;MA0zMN-}u^c`R|1IfkG!bHCAOJ9HOrU z7SWp@MkJqm%Tsh+{MkT5dLKO8u%#V9Ps_ggY9rqW<-}2C2JapTNHQSKS(k|l` z-3FXdS=VkQyw5efFh(`2`AKJ2c+WJJK6OcGVH_bn(Q)mdu|>9*x|m<)!uc~h8mX4@ zB~Nu_)kWA5Oe+hwFAYz*6JLvDy%?JJWzR$^bl`=498JytB4_n@SFEC=`4ZZ`T^>lPLZ;tpHx+id!z=#9?IML3f{%-bW3J% z4=nk5PkHH2^5r%2#DFeE0CptFRRg>MO+8Zb(Yr5u`Cc;&3JMs&X!K-lT74uj zB6}gg^MoU>iVO}N7?Q9{pHjv-(K)}MgMz`lv)?w@LJQ_03OstnrFZNS9gNnQ;Ose+ z85@v!-oBKI;{7QVByjDid$26RLwwHdKU*SC^PWb{Qi3YI56U)VG{KpGQtQk);g%s~ z{8-Hi+5-EI$dBjcE%3lsI`N6E&pEw&_d;--IB7BPFsU^-s(3x!HUBI0)dM$YJRw#m zI~TSLTC(HoXKI)1Lq<9k>Q=uVe*&{~CaOz*J&2<*!ZWkuhlCK=mleaP2-$OT@zY~# zWVRN%6~v8fob5}wMKa;P#l*?g$b{PHhzoC?Er%Lv0Lj(hc-Z4D*!*h)BGa`lMpsdH zc4{8!4{SdcuC8s$6EMRt{%Phxyt%L3*<2j*V?bc*MV^*YIq0|pOT5>Wa%ET zD7|{UGx#%;O-bRswcKD3F5R}rcN_g&niW>GyN1Xl&qd<{L1Ro zgA_MnXYM1C{NO9ELJH+To*_86mWhy^fcxWBmBD#Qp7)i0Y!F zd$W^Dg%Tqv#^op0L-tA^lR6}qM-wQF3x18T1?_1$PetGhW3y$T!86i5PsW{ocRp)P zt*2<(a$@*Bwe-mL(|Z+$cNfCBScL4?Pb~I-9#+;fl~Tv9TItCKYV?h7L!GQy@Uix= zvB$%9WW(CCP?aR8srdvdgnXjU700Z0wJDS?y^x}^J(pMm7|cy(mt+eTF|c~U*K!~& z=#;rh_VvqhwL43iIU^j<#txK6FGnAmeZ|QU#W*ib%kU!s^>6G56NEd-PzG8-FQqJeMV>|S;nii|-46@t ze)``i3Vc0PXG8EI}nqPCt3XECu&c>LWLHr7brviO9*6#xa8=kd% zO$TN$R+3IVz#f+`{}vlGXWs3v$+}x?i{7K*E)igT!bZrBtQ;A$ekV4GaMgLa;LdCJ zo&Y19pE4DZ58nz@^kv_COf=0S;DtHNQF*D~P=_Sr=_Ci%d&=$d)v~l0RALw7?4b$K zfLVS^y3L@+EVLL)s*^IaPOdYRaS4Tb<{Ki(U!>tAfqmC?qO4b5e>w@@V!i83=_sje0qO7GGN_e;22xT zHx3~chlw~QuWBol*tzc?;1jm!U7z@7`wNBMoFb3UYTfON#b@~?FEYR#}-QwnQ z03QKvhEud#8ayo}dokhBYqCZDIvf@D*MhNmVdFjoPXfq+y7ZOpae(wkfRl*f^R8S2 zB%TU>Ef45Usd4iLH&Z2XE7*8P@VZ|?8K@4yoV(wc&5owVOiY}{Yb zJdiGuz?W{)01l%vB|;gxjFgt_N|&ImWlDu6^DOxJNXd3;P5feQCY)mhDA@s;c7#qp zwn>3cxA4ut(wO;#Xqc(7HMS0C%3RSA7XCg*mvFvcN9$s^N`)v^oVExX*%YG~Z(1=a z&{}10IwDsAhg%0wPBp!=>7oH_Dc88Cq?tDN!FSH*D z?Q{r+ikm^SqJ@T?tJa|F2%4VI72<-Ny(D``bQw3{R;X;qAH?9`L;u6^XuUq7pWzho z{Y275#j^|rp~cYL6hnC5?hWkRC@4|;tdkl$Q&XOpyr}r}b(y3UCuqZ0Zuh1#VjP;y zhlR%OF}~gU!C(f~XC{9NNW>}6e78&^hik@VT?U3^{8i9gk;$3CLLH8c`AWNPE>^pI zIi@I_fR#q9#7TW=Al9ruGEIbhiC>Dn-=hI_UW3_-OYW&e`9#2k0Zo(4D=5jFB5B$u z0asBgp5;e-cbI$vuz*zz2M{M$pty+(y{hX)C}>qCWT;Mw4)B@4keIU3LwgqwWquf} zOdZ@B9wCEEp-r00;%vFgqNy8TqDk69`o%napCqREJmO2yf{T%(o_+A0JkQYJO<)#Q zHGaOaWN8*HjuYRhF;no72UIM;(q1?nERiY%pa#1>&<%H)NhR2h+%q(~3MkLnhY(n= zmIh{1-+KOZcYP^<*9-V0#{$ADRkC^nYI2A+XY{u|scE+XXaPhTiTjtdj`@Yf_$mED zZu{xB83V#b*nPcAFtIi9^Tb#*Sm+my4vglaLIQyMe}CNnM;5@E0e7F&VMh>iWpWb_ zqx4VAjhtwdKGF%W(w|ni7#)f+x9AbT#l^dX-IbcjrP$3Z1b#ul564DbdaAQl37Z^9 zgs{rNT7T09Z$PC4ddCHOvl=5>({)W+*ey84Wcvhd^;}EMDI9FLINu{+I6-W?k13ea zNTh+fM4P_it&JuEKq3)BYXHBwc2RP5@41{iJ)>ePti#&#r~r^3y1|znE7+d+AG-` zSxHqP6ESjNTBKyP&P0#i7!#qbJPW-&AX7|U`oCdnMo{5-g6wz?k&LIusboq7Q>i;4 zQ3{7Fpo*wH>i?YRX&KEE{c8S)PK!8>ESE>&utAe@vr-G%_LV#P84YhS3pr50PGWP} zRG&Nh;POW60S#LsdLev2e2UBe5lrX%X-#XQO#_U~5m$-8UZp1L>P9*APUwB2yoM4V zf6VSYj6jKimlT?^Ffj1l9D(cC*gsEhJ9)X+rH4mln>d`viHBJ!^@;O-3%Qg`RH4G; z>KCHM8N36WIV`_nODluK6!KSB6DvJ)-gQ$USPV zIInXA6Cx%6zLUSLo{X(Tki{w>@e2}ExA59!xLDgO`cKuJm)!_R0b&bA6Hg^!9!)Bj zd}Dahz_h&F=dS+SY@}V8_%*$yuvpxSvFg9GVgKqdA4Agk z1NB(aNNC8QC$>qV(^!7ZRRC$=M|-Yayj@MleV2TE40xQ*c!aLc=Lm!aOTQ%vsm`*D z4lDh=0Fs`5#mG1=e{aV@x=8*({9jm@9V<-SimI2|1#tL&oWT}p?B|VVI$b}BnH|W- z{(CCO*vQI*4dUPAtt{{Ibm@~cqqLO-XtO}XO`;uYm-b!K3sM_h(CB3p9r>!2KHwh& zUcT{vP3`?h@Bc42!2c1!aW;?!FdD;IOzEvc$Zegx3=Zfd^sjkpnVeqsDw1%z??4jx zY@Evcek$)c@IlVd89lOo@$iVd<}5Md7cB|v!roO1hh|npO;omZa}*vOEXuZ9oY3sgc}H%oqGY*v-F-!`q#6fA zGQyV*&&w!nmqd83TD}P*J2Zf2Di&EAYRQj!irRCnF2kHXD+gB?{UfT6x#PTL<%w`v1y7KKIP2@ZI-@3*jJ-rGOqzjo3v2t19Q93!2}sLy?hQ zzmN{nAAY8<&i3kfZqb&nBRd7};uAm2*!$vVOsi_wROrS2BX!sdLHJ^YY!WwRpTxJf zXu9oIi?8kqj9^%sBm2CPBB(`bn6pRa3=-Xfo~HU3fhH{yMY>&g=pEPWXb*gK$PYcs z4Kg-((9@EovjBh?8E@LYkcy>sW|Z7n$AM{eyl~nn_eZ|-Vx)O(8X8UD$`ZoaDmEWD zEa$_ED!=$X-M{%G(!vnHh>!P* zT~ipZi2=ilo^X3B#@0?~U61yBU~HV&4SPCtyt}J; zelX$5F8a3lktR%fs8}t?Vo?D8k~_d7?Nz8pR?joFXwK&u^5u$#*2TG=SowmQ*UCFL zMiV_N4OO92PobWbLx1tsBQL)dW|7I{i|N9$f5t9NZr&acVpM>YC6h&x1!u3AgZy%KvT^n<&8+wUz4(~niJ*GzuDbwt?AOcIr{9dn8`LRZ5Bnmbf8Z=Jk zdlP;Z)4D#J36}8@9DPyoVV^|xV#BAmYKBVuk9J&+FThO80a{x3)jf)wI6d{B3iFi7yD>a@y&DNJ+sIQ~LW+=zTco|S^>{M)ryWcNeeCcQ=5{5}3OW!-av9j`GepAE?-E=pc${4#BLSi~Xf?_|hMt4Tr$+?o)o z>pSY!_a_sW0HO+~=+&0;-?MZ!+7tuVjfN`+j&?!{9CeLr^anz+GbgPlB_DG#{b2S?|W9g)MN zdfwMvi>>n~PupH7nh<%8e!mh6P9|%o{E&-6eM1mRmYyT}av{#jkU>62xo&*rnMda&mGfg}L>-XD(L+gzY! z{Yj{L(WQs41DcC(((X79UW6ka9vT^7Xs=%O;%#8Y8|bc{|9R3MMI&y>jO`ZJd>DDj zf|z8y`=3}iZindvlkYi#rmKa;UXuU!>f?W(c}(2ngy*`){^hpv z1ygths4HtLH7Hm|#{d5=-QtY=Tj_Q|5DUOU(l5~8hukV>VkZvrpP9n0E?mOux6&d| z%Ogt@05getBoundingBox (); } @@ -154,32 +163,60 @@ namespace Katabatic { RoutingPad* routingPad; if ( (horizontal = dynamic_cast(component)) ) { + ltrace(110) << "Anchor: " << horizontal << "@" << horizontal->getSourcePosition() << endl; xMin = horizontal->getSourcePosition().getX(); xMax = horizontal->getTargetPosition().getX(); yMin = yMax = horizontal->getTargetPosition().getY(); } else if ( (vertical = dynamic_cast(component)) ) { + ltrace(110) << "Anchor: " << vertical << "@" << vertical->getSourcePosition() << endl; yMin = vertical->getSourcePosition().getY(); yMax = vertical->getTargetPosition().getY(); xMin = xMax = vertical->getTargetPosition().getX(); } else if ( (routingPad = dynamic_cast(component)) ) { - Entity* entity = routingPad->getOccurrence().getEntity(); + Entity* entity = routingPad->getOccurrence().getEntity(); + Transformation transf = routingPad->getOccurrence().getPath().getTransformation(); + ltrace(110) << "Anchor: " << routingPad << endl; - // Assumes there is no rotation in the Transformation. - if ( dynamic_cast(entity) ) { - xMin = routingPad->getSourcePosition().getX(); - xMax = routingPad->getTargetPosition().getX(); - yMin = yMax - = routingPad->getTargetPosition().getY(); + int rpOrient = 1; + switch ( transf.getOrientation() ) { + case Transformation::Orientation::R1: + case Transformation::Orientation::R3: + case Transformation::Orientation::XR: + case Transformation::Orientation::YR: + rpOrient = 2; + break; + default: + break; + } + + if (dynamic_cast(entity)) { + // rpOrient *is* the rotation. } else if ( dynamic_cast(entity) ) { - yMin = routingPad->getSourcePosition().getY(); - yMax = routingPad->getTargetPosition().getY(); - xMin = xMax - = routingPad->getTargetPosition().getX(); + // rpOrient is the inverse rotation. + rpOrient = (rpOrient == 1) ? 2 : 1; } else { - xMin = xMax = routingPad->getPosition().getX(); - yMin = yMax = routingPad->getPosition().getY(); + rpOrient = 0; + } + + switch ( rpOrient ) { + case 1: + xMin = routingPad->getSourcePosition().getX(); + xMax = routingPad->getTargetPosition().getX(); + yMin = yMax + = routingPad->getTargetPosition().getY(); + break; + case 2: + yMin = routingPad->getSourcePosition().getY(); + yMax = routingPad->getTargetPosition().getY(); + xMin = xMax + = routingPad->getTargetPosition().getX(); + break; + default: + xMin = xMax = routingPad->getPosition().getX(); + yMin = yMax = routingPad->getPosition().getY(); + break; } } else { xMin = xMax = component->getPosition().getX(); @@ -189,6 +226,10 @@ namespace Katabatic { order( xMin, xMax ); order( yMin, yMax ); + ltrace(110) << "| Using (y): " << DbU::getValueString(yMin) << " " + << DbU::getValueString(yMax) << endl; + + ltraceout(110); return Box( xMin, yMin, xMax, yMax ); } diff --git a/katabatic/src/AutoContactTurn.cpp b/katabatic/src/AutoContactTurn.cpp index f38fbe5f..294a00dd 100644 --- a/katabatic/src/AutoContactTurn.cpp +++ b/katabatic/src/AutoContactTurn.cpp @@ -88,6 +88,14 @@ namespace Katabatic { { return NULL; } + AutoSegment* AutoContactTurn::getPerpandicular ( const AutoSegment* reference ) const + { + if (reference == _horizontal1) return _vertical1; + if (reference == _vertical1 ) return _horizontal1; + return NULL; + } + + AutoSegment* AutoContactTurn::getSegment ( unsigned int index ) const { switch ( index ) { diff --git a/katabatic/src/AutoContactVTee.cpp b/katabatic/src/AutoContactVTee.cpp index c355b2e5..59ae782d 100644 --- a/katabatic/src/AutoContactVTee.cpp +++ b/katabatic/src/AutoContactVTee.cpp @@ -91,6 +91,10 @@ namespace Katabatic { } + AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* ) const + { return NULL; } + + AutoSegment* AutoContactVTee::getSegment ( unsigned int index ) const { switch ( index ) { diff --git a/katabatic/src/AutoHorizontal.cpp b/katabatic/src/AutoHorizontal.cpp index 8dede65c..fc1e2e5b 100644 --- a/katabatic/src/AutoHorizontal.cpp +++ b/katabatic/src/AutoHorizontal.cpp @@ -689,9 +689,8 @@ namespace Katabatic { unsigned int AutoHorizontal::_makeDogleg ( GCell* doglegGCell, unsigned int flags ) { - ltrace(200) << "AutoHorizontal::_makeDogleg(GCell*)" << endl; - DebugSession::open( getNet(), 80 ); + ltrace(200) << "AutoHorizontal::_makeDogleg(GCell*)" << endl; ltracein(159); //Session::doglegReset(); diff --git a/katabatic/src/AutoSegment.cpp b/katabatic/src/AutoSegment.cpp index 43d03c2c..1f2b95a5 100644 --- a/katabatic/src/AutoSegment.cpp +++ b/katabatic/src/AutoSegment.cpp @@ -313,6 +313,8 @@ namespace Katabatic { , _flags (SegCreated) , _depth (Session::getLayerDepth(segment->getLayer())) , _optimalMin (0) + , _optimalMax (0) + , _reduceds (0) , _sourcePosition (0) , _targetPosition (0) , _userConstraints(false) @@ -465,25 +467,29 @@ namespace Katabatic { unsigned int oldSpinFlags = _flags & SegDepthSpin; if (_flags & (SegInvalidatedSource|SegCreated)) { - const Layer* contactLayer = getAutoSource()->getLayer(); + AutoContact* source = getAutoSource(); + const Layer* contactLayer = source->getLayer(); const Layer* segmentLayer = getLayer(); - ltrace(200) << "Changed source: " << getAutoSource() << endl; + ltrace(200) << "Changed source: " << source << endl; unsetFlags( SegSourceTop|SegSourceBottom ); - if (contactLayer != segmentLayer) { + if (contactLayer != segmentLayer) setFlags( (segmentLayer == contactLayer->getTop()) ? SegSourceBottom : SegSourceTop ); - } + if (source->isTurn() and source->getPerpandicular(this)->isReduced()) + incReduceds(); } if (_flags & (SegInvalidatedTarget|SegCreated)) { - const Layer* contactLayer = getAutoTarget()->getLayer(); + AutoContact* target = getAutoTarget(); + const Layer* contactLayer = target->getLayer(); const Layer* segmentLayer = getLayer(); - ltrace(200) << "Changed target: " << getAutoTarget() << endl; + ltrace(200) << "Changed target: " << target << endl; unsetFlags( SegTargetTop|SegTargetBottom ); - if (contactLayer != segmentLayer) { + if (contactLayer != segmentLayer) setFlags( (segmentLayer == contactLayer->getTop()) ? SegTargetBottom : SegTargetTop ); - } + if (target->isTurn() and target->getPerpandicular(this)->isReduced()) + incReduceds(); } unsigned int observerFlags = Revalidate; @@ -517,21 +523,6 @@ namespace Katabatic { } - bool AutoSegment::isSameLayerDogleg () const - { - if (not isSpinTopOrBottom()) return false; - - unsigned int perpandicularDepth = getDepth() + (isSpinTop() ? 1 : -1); - if (perpandicularDepth >= Session::getDepth()) { - cerr << this << " isSpinTop too high." << endl; - } - perpandicularDepth = Session::getDepth() - 1; - - return (getLength() > (Session::getPitch(perpandicularDepth))) - and (getLength() < (Session::getPitch(perpandicularDepth) * 3)); - } - - DbU::Unit AutoSegment::getPPitch () const { unsigned int depth = getDepth(); @@ -706,6 +697,11 @@ namespace Katabatic { { AutoContact* source = getAutoSource(); if (source) { + if (source->isTurn()) { + AutoSegment* perpandicular = source->getPerpandicular(this); + if (perpandicular and perpandicular->isReduced()) + decReduceds(); + } base()->getSourceHook()->detach(); source->cacheDetach( this ); unsetFlags( SegNotSourceAligned ); @@ -718,6 +714,11 @@ namespace Katabatic { { AutoContact* target = getAutoTarget(); if (target) { + if (target->isTurn()) { + AutoSegment* perpandicular = target->getPerpandicular(this); + if (perpandicular and perpandicular->isReduced()) + decReduceds(); + } base()->getTargetHook()->detach(); target->cacheDetach( this ); unsetFlags( SegNotTargetAligned ); @@ -1149,6 +1150,72 @@ namespace Katabatic { } + bool AutoSegment::canReduce () const + { + AutoContact* source = getAutoSource(); + AutoContact* target = getAutoTarget(); + + if (not source->isTurn() or not target->isTurn()) return false; + if (not isSpinTopOrBottom()) return false; + if (_reduceds) return false; + + unsigned int perpandicularDepth = getDepth(); + if (isSpinBottom()) --perpandicularDepth; + else if (isSpinTop()) { + ++perpandicularDepth; + if (perpandicularDepth >= Session::getDepth()) return false; + } else + return false; + + if (getLength() >= (Session::getPitch(perpandicularDepth) * 2)) return false; + + return true; + } + + + bool AutoSegment::reduce () + { + if (not canReduce()) return false; + + AutoContact* source = getAutoSource(); + AutoContact* target = getAutoTarget(); + + _flags |= SegIsReduced; + source->getPerpandicular( this )->incReduceds(); + target->getPerpandicular( this )->incReduceds(); + + return true; + } + + + bool AutoSegment::mustRaise () const + { + if (not (_flags & SegIsReduced)) return false; + + unsigned int perpandicularDepth = getDepth(); + if (isSpinBottom()) --perpandicularDepth; + else if (isSpinTop ()) ++perpandicularDepth; + else return true; + + return (getLength() >= (Session::getPitch(perpandicularDepth) * 2)); + } + + + bool AutoSegment::raise () + { + if (not (_flags & SegIsReduced)) return false; + + AutoContact* source = getAutoSource(); + AutoContact* target = getAutoTarget(); + + _flags &= ~SegIsReduced; + source->getPerpandicular( this )->decReduceds(); + target->getPerpandicular( this )->decReduceds(); + + return true; + } + + void AutoSegment::changeDepth ( unsigned int depth, unsigned int flags ) { ltrace(200) << "changeDepth() " << depth << " - " << this << endl; @@ -1481,6 +1548,32 @@ namespace Katabatic { } + bool AutoSegment::reduceDoglegLayer () + { + if (not isReduced()) return true; + + AutoContact* source = getAutoSource(); + AutoContact* target = getAutoTarget(); + + unsigned int perpandicularDepth = getDepth(); + if (isSpinBottom()) --perpandicularDepth; + if (isSpinTop ()) ++perpandicularDepth; + + if (perpandicularDepth == getDepth()) { + cerr << Bug( "AutoSegment::reduceDoglegLayer(): Reduced segment spin is neither top (TT) nor bottom (BB).\n" + " %s" + , getString(this).c_str() ) << endl; + return false; + } + + source->setLayer( Session::getRoutingLayer(perpandicularDepth) ); + target->setLayer( Session::getRoutingLayer(perpandicularDepth) ); + setLayer( Session::getRoutingLayer(perpandicularDepth) ); + + return true; + } + + #if THIS_IS_DISABLED @@ -1811,6 +1904,7 @@ namespace Katabatic { state += isWeakTerminal2 () ? "w": "-"; state += isNotAligned () ? "A": "-"; state += isSlackened () ? "S": "-"; + state += isReduced () ? "r": "-"; state += isInvalidated () ? "i": "-"; if (_flags & SegSourceTop) state += 'T'; @@ -1968,12 +2062,28 @@ namespace Katabatic { AutoSegment* AutoSegment::create ( AutoContact* source , AutoContact* target , unsigned int dir + , size_t depth ) { - static const Layer* horizontalLayer = Session::getRoutingLayer( 1 ); - static DbU::Unit horizontalWidth = Session::getWireWidth ( 1 ); - static const Layer* verticalLayer = Session::getRoutingLayer( 2 ); - static DbU::Unit verticalWidth = Session::getWireWidth ( 2 ); + // Hardcoded: make the assumption that, + // depth=0 is terminal reserved | METAL1 + // depth=1 is horizontal | METAL2 + // depth=2 is vertical | METAL3 + // Should be based on gauge informations. + static const Layer* hLayer = Session::getRoutingLayer( 1 ); + static DbU::Unit hWidth = Session::getWireWidth ( 1 ); + static const Layer* vLayer = Session::getRoutingLayer( 2 ); + static DbU::Unit vWidth = Session::getWireWidth ( 2 ); + + const Layer* horizontalLayer = hLayer; + DbU::Unit horizontalWidth = hWidth; + const Layer* verticalLayer = vLayer; + DbU::Unit verticalWidth = vWidth; + + if (depth != RoutingGauge::nlayerdepth) { + horizontalLayer = verticalLayer = Session::getRoutingLayer( depth ); + horizontalWidth = verticalWidth = Session::getWireWidth ( depth ); + } AutoSegment* segment; AutoContact* reference = source; diff --git a/katabatic/src/KatabaticEngine.cpp b/katabatic/src/KatabaticEngine.cpp index 208e5fe6..e67a3de2 100644 --- a/katabatic/src/KatabaticEngine.cpp +++ b/katabatic/src/KatabaticEngine.cpp @@ -255,10 +255,12 @@ namespace Katabatic { ltracein(90); ltrace(90) << "Saving AutoContacts/AutoSegments." << endl; - size_t fixedSegments = 0; + size_t fixedSegments = 0; + size_t sameLayerDoglegs = 0; AutoSegmentLut::const_iterator isegment = _autoSegmentLut.begin(); for ( ; isegment != _autoSegmentLut.end() ; ++isegment ) { - if ((*isegment).second->isFixed()) fixedSegments++; + if ((*isegment).second->isFixed()) ++fixedSegments; + if ((*isegment).second->reduceDoglegLayer()) ++sameLayerDoglegs; } cmess1 << " o Driving Hurricane data-base." << endl; @@ -266,6 +268,7 @@ namespace Katabatic { cmess1 << Dots::asSizet(" - Active AutoContacts",AutoContact::getAllocateds()-fixedSegments*2) << endl; cmess1 << Dots::asSizet(" - AutoSegments" ,AutoSegment::getAllocateds()) << endl; cmess1 << Dots::asSizet(" - AutoContacts" ,AutoContact::getAllocateds()) << endl; + cmess1 << Dots::asSizet(" - Same Layer doglegs" ,sameLayerDoglegs) << endl; forEach ( Net*, inet, _cell->getNets() ) _saveNet( *inet ); diff --git a/katabatic/src/LoadGrByNet.cpp b/katabatic/src/LoadGrByNet.cpp index c08f1909..b665d87a 100644 --- a/katabatic/src/LoadGrByNet.cpp +++ b/katabatic/src/LoadGrByNet.cpp @@ -21,6 +21,8 @@ #include "hurricane/Warning.h" #include "hurricane/DebugSession.h" #include "hurricane/Layer.h" +#include "hurricane/BasicLayer.h" +#include "hurricane/RegularLayer.h" #include "hurricane/Technology.h" #include "hurricane/DataBase.h" #include "hurricane/Net.h" @@ -47,6 +49,9 @@ namespace { + using Katabatic::AutoContactTerminal; + + /*! \defgroup LoadGlobalRouting Global Routing Loading * \brief Translation rules to build detailed routing from global * @@ -111,6 +116,12 @@ namespace { * * \brief Build the wiring for a Net inside a GCell (\b internal). * + * As this class is called to initially construct the Katabatic wiring, + * it must build a \b connex wiring. That is without gaps in layer depth, + * because the topology restauration mechanism (AutoContact::updateTopology()) + * of the AutoContact cannot work until all AutoSegments are revalidated at + * least once. The topology restauration work by creating doglegs which in turn, + * call the canonization, which needs all the caches to be up to date. */ //! \function void GCellTopology::doRp_AutoContacts ( GCell* gcell, Component* rp, AutoContact*& source, AutoContact*& target, unsigned int flags ); @@ -171,6 +182,33 @@ namespace { //! //! \image html doRp_Access.png "doRp_Access()" +//! \function AutoContact* GCellTopology::doRp_AccessPad ( Component* rp, unsigned int flags ); +//! \param rp The Component onto which anchor the access contact. +//! \param flags Relevant flags are: +//! - HAccess, the terminal is to be accessed through an horizontal +//! segment. +//! - VSmall, force the terminal to be considered as small in the +//! vertical direction. +//! \return A Katabatic::AutoContactTerminal . +//! +//! The Component \c rp is a RoutingPad which belongs to a pad cell. This case +//! occurs when we are routing a complete chip. This method build, from the +//! \c rp a stack of articulated punctual segments and contacts to reach the +//! default H/V routing layers (usually \c METAL2 & \c METAL3). This may be +//! needed when the pad terminal is in \c METAL5, for instance. +//! +//! The returned AutoContactTerminal is anchored on the last punctual segment +//! build. +//! +//! The GCell into which the AutoContactTerminal is created may be under the +//! pads area. However, it will be right on the border of the GCell. +//! The global router vertexes of GCell under the pad area are marked as +//! blocked so will never be used for routing. +//! +//! \remark The segments and contacts added to ensure the layer connexity are not +//! put into the Katabatic database. They are plain Hurricane objects, invisibles +//! from it. + //! \function void GCellTopology::doRp_StairCaseH ( GCell* gcell, Component* rp1, Component* rp2 ); //! //! Build the wiring to connect to horizontal Component. Two cases: @@ -187,7 +225,17 @@ namespace { //! //! \image html doRp_StairCaseV.png "doRp_StairCaseV()" -//! \function GCellTopology::_do_xG (); +//! \function void GCellTopology::_do_xG_1Pad (); +//! +//! Construct the topology, when there is only global wires and one local +//! terminal, but coming from a Pad. As thoses connectors will always be +//! on one border of the GCell they can be considered as a kind of global. +//! +//! So this method mostly calls GCellTopology::doRp_AccessPad() to create +//! the AutoContactTerminal, then calls GCellTopology::_do_xG(), except +//! for straight lines which are managed directly. + +//! \function void GCellTopology::_do_xG (); //! //! Construct the topology, when there is only global wires (no local terminals). //! @@ -594,6 +642,7 @@ namespace { inline GCell* getGCell () const; static void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, unsigned int flags ); static AutoContact* doRp_Access ( GCell*, Component*, unsigned int flags ); + static AutoContact* doRp_AccessPad ( Component*, unsigned int flags ); static void doRp_StairCaseH ( GCell*, Component* rp1, Component* rp2 ); static void doRp_StairCaseV ( GCell*, Component* rp1, Component* rp2 ); private: @@ -1132,6 +1181,135 @@ namespace { } + AutoContact* GCellTopology::doRp_AccessPad ( Component* rp, unsigned int flags ) + { + ltrace(99) << "doRp_AccessPad()" << endl; + ltracein(99); + ltrace(99) << rp << endl; + + // Hardcoded: H access is METAL2 (depth=1), V access is METAL3 (depth=2). + size_t accessDepth = (flags & HAccess) ? 1 : 2 ; + size_t padDepth = Session::getLayerDepth(rp->getLayer()); + if (padDepth > Session::getAllowedDepth()) { + cerr << Error( "GCellTopology::doRp_AccessPad(): Pad RoutingPad %s\n" + " has a layer unreachable by the router (top layer is: %s)" + , getString(rp).c_str() + , getString(Session::getRoutingLayer(Session::getAllowedDepth())).c_str() + ) << endl; + padDepth = Session::getAllowedDepth(); + } + + rp->getBodyHook()->detach(); + + Point position = rp->getCenter(); + GCell* gcell = Session::getKatabatic()->getGCellGrid()->getGCell(position); + Component* anchor = rp; + + if (padDepth != accessDepth) { + if (padDepth > accessDepth) { + // Go *down* from the pad's RoutingPad. + --padDepth; + + Contact* target = NULL; + Contact* source = Contact::create ( rp + , Session::getContactLayer(padDepth) + , 0 + , 0 + , Session::getViaWidth(padDepth) + , Session::getViaWidth(padDepth) + ); + + for ( size_t depth = padDepth ; depth >= accessDepth ; --depth ) { + const Layer* segmentLayer = Session::getRoutingLayer(depth); + const Layer* targetLayer = (depth == accessDepth) ? segmentLayer + : Session::getContactLayer(depth-1); + DbU::Unit targetSide = (depth == accessDepth) ? Session::getWireWidth(depth) + : Session::getViaWidth (depth-1); + + target = Contact::create( rp->getNet() + , targetLayer + , position.getX() + , position.getY() + , targetSide + , targetSide + ); + if (Session::getDirection(depth) == KbHorizontal) { + anchor = Horizontal::create( source + , target + , segmentLayer + , position.getY() + , Session::getWireWidth(depth) + ); + } else { + anchor = Vertical::create( source + , target + , segmentLayer + , position.getX() + , Session::getWireWidth(depth) + ); + } + ltrace(99) << "Pad strap: " << anchor << endl; + source = target; + } + } else { + // Go *up* from the pad's RoutingPad. + Contact* target = NULL; + Contact* source = Contact::create ( rp + , Session::getContactLayer(padDepth) + , 0 + , 0 + , Session::getViaWidth(padDepth) + , Session::getViaWidth(padDepth) + ); + + for ( size_t depth = padDepth ; depth <= accessDepth ; ++depth ) { + const Layer* segmentLayer = Session::getRoutingLayer(depth); + const Layer* targetLayer = (depth == accessDepth) ? segmentLayer + : Session::getContactLayer(depth); + DbU::Unit targetSide = (depth == accessDepth) ? Session::getWireWidth(depth) + : Session::getViaWidth (depth); + + target = Contact::create( rp->getNet() + , targetLayer + , position.getX() + , position.getY() + , targetSide + , targetSide + ); + if (Session::getDirection(depth) == KbHorizontal) { + anchor = Horizontal::create( source + , target + , segmentLayer + , position.getY() + , Session::getWireWidth(depth) + ); + } else { + anchor = Vertical::create( source + , target + , segmentLayer + , position.getX() + , Session::getWireWidth(depth) + ); + } + ltrace(99) << "Pad strap: " << anchor << endl; + source = target; + } + } + } + + AutoContact* autoSource + = AutoContactTerminal::create ( gcell + , anchor + , Session::getRoutingLayer(accessDepth) + , position + , Session::getWireWidth(accessDepth) + , Session::getWireWidth(accessDepth) + ); + ltraceout(99); + return autoSource; + } + + void GCellTopology::doRp_StairCaseH ( GCell* gcell, Component* rp1, Component* rp2 ) { ltrace(99) << "doRp_StairCaseH()" << endl; @@ -1203,6 +1381,7 @@ namespace { void GCellTopology::_do_xG () { ltrace(99) << "_do_xG()" << endl; + ltracein(99); if (_connexity.fields.globals == 2) { _southWestContact @@ -1229,6 +1408,7 @@ namespace { AutoSegment::create( _southWestContact, turn, KbHorizontal ); AutoSegment::create( turn, _northEastContact, KbVertical ); } + ltraceout(99); } @@ -1236,56 +1416,68 @@ namespace { { ltrace(99) << "_do_xG_1Pad() [Managed Configuration - Optimized] " << _topology << endl; ltracein(99); + ltrace(99) << "_connexity.globals:" << _connexity.fields.globals << endl; - bool eastPad = false; - bool westPad = false; - bool northPad = false; - bool southPad = false; - Instance* padInstance = dynamic_cast(_routingPads[0])->getOccurrence().getPath().getHeadInstance(); + unsigned int flags = NoFlags; + bool eastPad = false; + bool westPad = false; + bool northPad = false; + bool southPad = false; + Instance* padInstance = dynamic_cast(_routingPads[0])->getOccurrence().getPath().getHeadInstance(); switch ( padInstance->getTransformation().getOrientation() ) { case Transformation::Orientation::ID: northPad = true; break; - case Transformation::Orientation::YR: eastPad = true; break; - case Transformation::Orientation::R3: eastPad = true; break; case Transformation::Orientation::MY: southPad = true; break; - case Transformation::Orientation::R1: westPad = true; break; + case Transformation::Orientation::YR: + case Transformation::Orientation::R3: eastPad = true; flags |= HAccess; break; + case Transformation::Orientation::R1: westPad = true; flags |= HAccess; break; default: cerr << Warning( "Unmanaged orientation %s for pad <%s>." , getString(padInstance->getTransformation().getOrientation()).c_str() , getString(padInstance).c_str() ) << endl; break; } + ltrace(99) << "eastPad:" << eastPad << ", " + << "westPad:" << westPad << ", " + << "northPad:" << northPad << ", " + << "southPad:" << southPad + << endl; - Point position = _routingPads[0]->getCenter(); - AutoContact* source = NULL; - GCell* gcell = Session::getKatabatic()->getGCellGrid()->getGCell(position); + AutoContact* source = doRp_AccessPad( _routingPads[0], flags ); + // Point position = _routingPads[0]->getCenter(); + // AutoContact* source = NULL; + // GCell* gcell = Session::getKatabatic()->getGCellGrid()->getGCell(position); - source = AutoContactTerminal::create ( gcell - , _routingPads[0] - , Session::getContactLayer(3) - , position - , Session::getViaWidth(3), Session::getViaWidth(3) - ); - source->setFlags( CntFixed ); + // source = AutoContactTerminal::create ( gcell + // , _routingPads[0] + // , Session::getContactLayer(3) + // , position + // , Session::getViaWidth(3), Session::getViaWidth(3) + // ); + // source->setFlags( CntFixed ); - if (northPad or eastPad) { - _southWestContact = _northEastContact = source; - ltraceout(99); - return; - } + // if (northPad or eastPad) { + // _southWestContact = _northEastContact = source; + // ltraceout(99); + // return; + // } // Check for straight lines, which are not managed by _do_xG(). if (_connexity.fields.globals == 1) { - if (westPad and (_east != NULL)) { + if ( (westPad and (_east != NULL)) + or (eastPad and (_west != NULL)) ) { AutoContact* turn = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) ); - _northEastContact = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) ); + _northEastContact = _southWestContact + = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) ); AutoSegment::create( source, turn, KbHorizontal ); AutoSegment::create( turn, _northEastContact, KbVertical ); ltraceout(99); return; - } else if (southPad and (_north != NULL)) { + } else if ( (southPad and (_north != NULL)) + or (northPad and (_south != NULL)) ) { AutoContact* turn = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) ); - _northEastContact = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) ); + _northEastContact = _southWestContact + = AutoContactTurn::create( _gcell, _net, Session::getContactLayer(1) ); AutoSegment::create( source, turn, KbVertical ); AutoSegment::create( turn, _northEastContact, KbHorizontal ); ltraceout(99); @@ -1297,7 +1489,9 @@ namespace { --_connexity.fields.Pad; if (westPad ) _west = source->getBodyHook(); + if (eastPad ) _east = source->getBodyHook(); if (southPad) _south = source->getBodyHook(); + if (northPad) _north = source->getBodyHook(); _do_xG(); @@ -1305,10 +1499,18 @@ namespace { AutoSegment::create( source, _southWestContact, KbHorizontal ); _west = NULL; } + if (eastPad) { + AutoSegment::create( source, _northEastContact, KbHorizontal ); + _east = NULL; + } if (southPad) { AutoSegment::create( source, _southWestContact, KbVertical ); _south = NULL; } + if (northPad) { + AutoSegment::create( source, _northEastContact, KbVertical ); + _north = NULL; + } --_connexity.fields.globals; ltraceout(99); diff --git a/katabatic/src/katabatic/AutoContact.h b/katabatic/src/katabatic/AutoContact.h index 8c482d33..52327661 100644 --- a/katabatic/src/katabatic/AutoContact.h +++ b/katabatic/src/katabatic/AutoContact.h @@ -17,13 +17,13 @@ #ifndef KATABATIC_AUTOCONTACT_H #define KATABATIC_AUTOCONTACT_H -#include -#include -#include "hurricane/Contact.h" -#include "hurricane/ExtensionGo.h" -#include "katabatic/Constants.h" -#include "katabatic/AutoSegment.h" -#include "katabatic/GCell.h" +#include +#include +#include "hurricane/Contact.h" +#include "hurricane/ExtensionGo.h" +#include "katabatic/Constants.h" +#include "katabatic/AutoSegment.h" +#include "katabatic/GCell.h" namespace Katabatic { @@ -124,6 +124,7 @@ namespace Katabatic { virtual Box getBoundingBox () const; inline GCell* getGCell () const; virtual AutoSegment* getOpposite ( const AutoSegment* ) const = 0; + virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const = 0; virtual AutoSegment* getSegment ( unsigned int ) const = 0; unsigned int getMinDepth () const; unsigned int getMaxDepth () const; @@ -313,11 +314,11 @@ namespace Katabatic { inline void LocatorHelper::progress () { ltracein(80); - ltrace(80) << "LocatorHelper::progress() [" << _index << "] " << _contact->getSegment(_index) << endl; ++_index; + ltrace(80) << "LocatorHelper::progress() [" << _index << "] " << _contact->getSegment(_index) << endl; while ((_index < _max()) and (_contact->getSegment(_index) == NULL)) { - ltrace(80) << "LocatorHelper::progress() [" << _index << "] " << _contact->getSegment(_index) << endl; ++_index; + ltrace(80) << "LocatorHelper::progress() [" << _index << "] " << _contact->getSegment(_index) << endl; } ltraceout(80); } diff --git a/katabatic/src/katabatic/AutoContactHTee.h b/katabatic/src/katabatic/AutoContactHTee.h index c79cdbf9..8febc972 100644 --- a/katabatic/src/katabatic/AutoContactHTee.h +++ b/katabatic/src/katabatic/AutoContactHTee.h @@ -44,6 +44,7 @@ namespace Katabatic { inline AutoHorizontal* getHorizontal2 () const; inline AutoVertical* getVertical1 () const; virtual AutoSegment* getOpposite ( const AutoSegment* ) const; + virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const; virtual AutoSegment* getSegment ( unsigned int ) const; virtual void updateGeometry (); virtual void updateTopology (); diff --git a/katabatic/src/katabatic/AutoContactTerminal.h b/katabatic/src/katabatic/AutoContactTerminal.h index 7832476e..5068e648 100644 --- a/katabatic/src/katabatic/AutoContactTerminal.h +++ b/katabatic/src/katabatic/AutoContactTerminal.h @@ -55,6 +55,7 @@ namespace Katabatic { inline AutoSegment* getSegment () const; virtual AutoSegment* getSegment ( unsigned int ) const; virtual AutoSegment* getOpposite ( const AutoSegment* ) const; + virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const; virtual void updateGeometry (); virtual void updateTopology (); virtual void cacheDetach ( AutoSegment* ); diff --git a/katabatic/src/katabatic/AutoContactTurn.h b/katabatic/src/katabatic/AutoContactTurn.h index 52657e82..3605636a 100644 --- a/katabatic/src/katabatic/AutoContactTurn.h +++ b/katabatic/src/katabatic/AutoContactTurn.h @@ -43,6 +43,7 @@ namespace Katabatic { inline AutoHorizontal* getHorizontal1 () const; inline AutoVertical* getVertical1 () const; virtual AutoSegment* getOpposite ( const AutoSegment* ) const; + virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const; virtual AutoSegment* getSegment ( unsigned int ) const; virtual void updateGeometry (); virtual void updateTopology (); diff --git a/katabatic/src/katabatic/AutoContactVTee.h b/katabatic/src/katabatic/AutoContactVTee.h index ba4d0f64..225daf3c 100644 --- a/katabatic/src/katabatic/AutoContactVTee.h +++ b/katabatic/src/katabatic/AutoContactVTee.h @@ -41,6 +41,7 @@ namespace Katabatic { inline AutoVertical* getVertical1 () const; inline AutoVertical* getVertical2 () const; virtual AutoSegment* getOpposite ( const AutoSegment* ) const; + virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const; virtual AutoSegment* getSegment ( unsigned int ) const; virtual void updateGeometry (); virtual void updateTopology (); diff --git a/katabatic/src/katabatic/AutoSegment.h b/katabatic/src/katabatic/AutoSegment.h index f42668a8..f48043eb 100644 --- a/katabatic/src/katabatic/AutoSegment.h +++ b/katabatic/src/katabatic/AutoSegment.h @@ -30,7 +30,7 @@ namespace Hurricane { class Vertical; class Cell; } - +#include "crlcore/RoutingGauge.h" #include "katabatic/Constants.h" #include "katabatic/Observer.h" #include "katabatic/GCell.h" @@ -53,6 +53,7 @@ namespace Katabatic { using Hurricane::Horizontal; using Hurricane::Vertical; using Hurricane::Cell; + using CRL::RoutingGauge; class AutoHorizontal; class AutoVertical; @@ -60,43 +61,44 @@ namespace Katabatic { // ------------------------------------------------------------------- // Class : "AutoSegment". - enum AutoSegmentFlag { SegNoFlags = 0x00000000 - , SegHorizontal = 0x00000001 - , SegFixed = 0x00000002 - , SegGlobal = 0x00000004 - , SegWeakGlobal = 0x00000008 - , SegCanonical = 0x00000010 - , SegBipoint = 0x00000020 - , SegDogleg = 0x00000040 - , SegStrap = 0x00000080 - , SegSourceTop = 0x00000100 - , SegSourceBottom = 0x00000200 - , SegTargetTop = 0x00000400 - , SegTargetBottom = 0x00000800 - , SegLayerChange = 0x00001000 - , SegSourceTerminal = 0x00002000 // Replace Terminal. - , SegTargetTerminal = 0x00004000 // Replace Terminal. + enum AutoSegmentFlag { SegNoFlags = 0x0 + , SegHorizontal = (1<< 0) + , SegFixed = (1<< 1) + , SegGlobal = (1<< 2) + , SegWeakGlobal = (1<< 3) + , SegCanonical = (1<< 4) + , SegBipoint = (1<< 5) + , SegDogleg = (1<< 6) + , SegStrap = (1<< 7) + , SegSourceTop = (1<< 8) + , SegSourceBottom = (1<< 9) + , SegTargetTop = (1<<10) + , SegTargetBottom = (1<<11) + , SegIsReduced = (1<<12) + , SegLayerChange = (1<<13) + , SegSourceTerminal = (1<<14) // Replace Terminal. + , SegTargetTerminal = (1<<15) // Replace Terminal. , SegStrongTerminal = SegSourceTerminal|SegTargetTerminal - , SegWeakTerminal1 = 0x00008000 // Replace TopologicalEnd. - , SegWeakTerminal2 = 0x00010000 // Replace TopologicalEnd. - , SegNotSourceAligned = 0x00020000 - , SegNotTargetAligned = 0x00040000 - , SegUnbound = 0x00100000 - , SegHalfSlackened = 0x00200000 - , SegSlackened = 0x00400000 - , SegAxisSet = 0x00800000 - , SegInvalidated = 0x01000000 - , SegInvalidatedSource = 0x02000000 - , SegInvalidatedTarget = 0x04000000 - , SegInvalidatedLayer = 0x08000000 - , SegCreated = 0x10000000 - , SegUserDefined = 0x20000000 + , SegWeakTerminal1 = (1<<16) // Replace TopologicalEnd. + , SegWeakTerminal2 = (1<<17) // Replace TopologicalEnd. + , SegNotSourceAligned = (1<<18) + , SegNotTargetAligned = (1<<19) + , SegUnbound = (1<<20) + , SegHalfSlackened = (1<<21) + , SegSlackened = (1<<22) + , SegAxisSet = (1<<23) + , SegInvalidated = (1<<24) + , SegInvalidatedSource = (1<<25) + , SegInvalidatedTarget = (1<<26) + , SegInvalidatedLayer = (1<<27) + , SegCreated = (1<<28) + , SegUserDefined = (1<<29) // Masks. , SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2 , SegNotAligned = SegNotSourceAligned|SegNotTargetAligned - , SegSpinTop = SegSourceTop |SegTargetTop - , SegSpinBottom = SegSourceBottom|SegTargetBottom - , SegDepthSpin = SegSpinTop |SegSpinBottom + , SegSpinTop = SegSourceTop |SegTargetTop + , SegSpinBottom = SegSourceBottom |SegTargetBottom + , SegDepthSpin = SegSpinTop |SegSpinBottom }; @@ -122,6 +124,7 @@ namespace Katabatic { static AutoSegment* create ( AutoContact* source , AutoContact* target , unsigned int dir + , size_t depth=RoutingGauge::nlayerdepth ); void destroy (); // Wrapped Segment Functions. @@ -169,11 +172,11 @@ namespace Katabatic { bool isStrongTerminal ( unsigned int flags=0 ) const; inline bool isSourceTerminal () const; inline bool isTargetTerminal () const; - bool isSameLayerDogleg () const; inline bool isLayerChange () const; inline bool isSpinTop () const; inline bool isSpinBottom () const; inline bool isSpinTopOrBottom () const; + inline bool isReduced () const; inline bool isStrap () const; inline bool isDogleg () const; inline bool isUnbound () const; @@ -185,6 +188,8 @@ namespace Katabatic { inline bool isSlackened () const; inline bool isUserDefined () const; virtual bool _canSlacken () const = 0; + bool canReduce () const; + bool mustRaise () const; unsigned int canDogleg ( Interval ); virtual bool canMoveULeft ( float reserve=0.0 ) const = 0; virtual bool canMoveURight ( float reserve=0.0 ) const = 0; @@ -239,6 +244,8 @@ namespace Katabatic { inline void unsetFlags ( unsigned int ); inline void setFlags ( unsigned int ); void setFlagsOnAligneds ( unsigned int ); + inline void incReduceds (); + inline void decReduceds (); virtual void setDuSource ( DbU::Unit du ) = 0; virtual void setDuTarget ( DbU::Unit du ) = 0; void computeTerminal (); @@ -270,6 +277,9 @@ namespace Katabatic { void changeDepth ( unsigned int depth, unsigned int flags ); bool moveUp ( unsigned int flags=KbNoFlags ); bool moveDown ( unsigned int flags=KbNoFlags ); + bool reduceDoglegLayer (); + bool reduce (); + bool raise (); // Canonical Modifiers. AutoSegment* canonize ( unsigned int flags=KbNoFlags ); virtual void invalidate ( unsigned int flags=KbPropagate ); @@ -314,6 +324,7 @@ namespace Katabatic { unsigned int _depth : 8; unsigned int _optimalMin : 8; unsigned int _optimalMax : 8; + unsigned int _reduceds : 2; DbU::Unit _sourcePosition; DbU::Unit _targetPosition; Interval _userConstraints; @@ -445,6 +456,7 @@ namespace Katabatic { inline bool AutoSegment::isSpinTop () const { return ((_flags & SegSpinTop ) == SegSpinTop); } inline bool AutoSegment::isSpinBottom () const { return ((_flags & SegSpinBottom) == SegSpinBottom); } inline bool AutoSegment::isSpinTopOrBottom () const { return isSpinTop() or isSpinBottom(); } + inline bool AutoSegment::isReduced () const { return _flags & SegIsReduced; } inline bool AutoSegment::isSlackened () const { return _flags & SegSlackened; } inline bool AutoSegment::isCanonical () const { return _flags & SegCanonical; } inline bool AutoSegment::isUnsetAxis () const { return not (_flags & SegAxisSet); } @@ -457,6 +469,8 @@ namespace Katabatic { inline unsigned int AutoSegment::getFlags () const { return _flags; } inline unsigned int AutoSegment::_getFlags () const { return _flags; } + inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; } + inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; } inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); } inline void AutoSegment::setOptimalMin ( DbU::Unit min ) { _optimalMin = (unsigned int)DbU::getLambda(min-getOrigin()); } inline void AutoSegment::setOptimalMax ( DbU::Unit max ) { _optimalMax = (unsigned int)DbU::getLambda(max-getOrigin()); } diff --git a/katabatic/src/katabatic/Session.h b/katabatic/src/katabatic/Session.h index 8dab84a7..fbdbbe63 100644 --- a/katabatic/src/katabatic/Session.h +++ b/katabatic/src/katabatic/Session.h @@ -17,17 +17,17 @@ #ifndef KATABATIC_SESSION_H #define KATABATIC_SESSION_H -#include -#include -#include -#include -#include -#include "hurricane/Commons.h" -#include "hurricane/DbU.h" -#include "crlcore/CellGauge.h" -#include "crlcore/RoutingGauge.h" -#include "katabatic/Constants.h" -#include "katabatic/Configuration.h" +#include +#include +#include +#include +#include +#include "hurricane/Commons.h" +#include "hurricane/DbU.h" +#include "crlcore/CellGauge.h" +#include "crlcore/RoutingGauge.h" +#include "katabatic/Constants.h" +#include "katabatic/Configuration.h" namespace Hurricane { class Layer; diff --git a/kite/doc/Session.dox b/kite/doc/Session.dox index dc6dd463..bbbd7568 100644 --- a/kite/doc/Session.dox +++ b/kite/doc/Session.dox @@ -56,17 +56,23 @@ * - Process all insert events. This is the time TrackSegment * are moved into their new Track (physical displacement). * It is at this point that the invalidation of both AutoSegment - * and TrackSEgment is done. + * and TrackSegment is done. * - Call the Katabatic::Session::revalidate() method which * will recompute the correct contact extensions and topologies. * \e After this step the Katabatic data-base is up to date, - * but \e not the Kite one. AutoSEgment are revalidated. + * but \e not the Kite one. AutoSegment are revalidated. * - Recompute the canonical position of source and target * of all invalidateds TrackSegment (take account of * extention modifications). The set of invalidated TrackSegment * is computed from the revalidated AutoSegment, that is * AutoSegment that are canonical. * - Perform a sort() on all Track that have been modifieds. + * - Now that the size of the segments have been accurately computed, + * look for revalidateds TrackSegment that: + * -# Can be reduced, generate a track remove event. + * -# Must be raised, generate a routing event (put into the + * queue). + * - Process the additional track remove events. * * Note: We cannot use the Observer mechanism to automatically * update TrackSegment from an AutoSegment, because we must wait for all diff --git a/kite/doc/TrackSegment.dox b/kite/doc/TrackSegment.dox index eb8e54ca..b617ce4b 100644 --- a/kite/doc/TrackSegment.dox +++ b/kite/doc/TrackSegment.dox @@ -27,7 +27,7 @@ * The associated DataNegociate and RoutingEvent are \b not updated. * - The RoutingEvent will be updated when it's key is updated, * typically during a requeueing operation \b and in the - * SegmentFsm constructor. This should be optimzed in the future. + * SegmentFsm constructor. This should be optimized in the future. * - The DataNegociate is updated \e only in the SegmentFsm * constructor. This is the most costly of the two updates as * it perform a perpandicular & parallel connexity exploration. @@ -51,9 +51,9 @@ * * Figure 2 below, shows an example of dogleg creation: * - At the Katabatic level, AutoSegment \c id:12 is broken. Thus - * the creation of AutoSegments \c id:20 and \c id:21. As per - * specification, the orignal segment \c id:10 remains on the - * left side (source) of the break. + * the creation of AutoSegments \c id:20 and \c id:21. The orignal + * TrackSegment (canonical AutoSegment \c id:10) remains on the + * right side (target) of the break. * - But, because the canonical of the former aligned AutoSegment * set \c (10,11,12,13,14) was on the \e right side of the break, * the new parallel TrackSegment will be created on the \c left diff --git a/kite/doc/notes.dox b/kite/doc/notes.dox index 8664e043..ae0f16e4 100644 --- a/kite/doc/notes.dox +++ b/kite/doc/notes.dox @@ -42,6 +42,14 @@ * - Now that the Hurricane database is deterministic, the router * seems to be likewise. * + * - Reduce/raise mechanism. To manage same layer dogleg + * this mechanism has been implemented. When a candidate dogleg + * perpandicular segment length shrink below one pitch it is + * removed from any track to become invisible. + * Conversely, when a reduced segment length expand over one pitch + * generate a new RoutingEvent to insert it. All this is managed + * in the Session::revalidate() method. + * * * \section secPendingModifications Pending Modifications * diff --git a/kite/src/BuildPowerRails.cpp b/kite/src/BuildPowerRails.cpp index 6a6a377b..5cee9ac1 100644 --- a/kite/src/BuildPowerRails.cpp +++ b/kite/src/BuildPowerRails.cpp @@ -723,10 +723,10 @@ namespace { axisMin = _axis - _width/2; axisMax = _axis + _width/2; - if (coronaBb.contains(segment->getBoundingBox())) { + //if (coronaBb.contains(segment->getBoundingBox())) { axisMin -= delta; axisMax += delta; - } + //} Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior ); for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNextTrack() ) { diff --git a/kite/src/KiteEngine.cpp b/kite/src/KiteEngine.cpp index 3cd1b1a8..c885d358 100644 --- a/kite/src/KiteEngine.cpp +++ b/kite/src/KiteEngine.cpp @@ -354,6 +354,11 @@ namespace Kite { size_t coronaReserved = 4; for( Knik::Vertex* vertex : _knik->getRoutingGraph()->getVertexes() ) { + if ( chipTools.isChip() + and ( chipTools.hPadsEnclosed(Box(vertex->getPosition())) + or chipTools.vPadsEnclosed(Box(vertex->getPosition()))) ) + vertex->setBlocked(); + for ( int i=0 ; i<2 ; ++i ) { Knik::Edge* edge = NULL; @@ -661,6 +666,7 @@ namespace Kite { unsigned long long totalWireLength = 0; unsigned long long routedWireLength = 0; vector unrouteds; + vector reduceds; ostringstream result; AutoSegmentLut::const_iterator ilut = _getAutoSegmentLut().begin(); @@ -676,20 +682,16 @@ namespace Kite { } if (segment->isFixed() or segment->isBlockage()) continue; - - // if (segment->isSameLayerDogleg()) { - // cerr << " Same layer:" << segment << endl; - // cerr << " S: " << segment->base()->getAutoSource() << endl; - // cerr << " T: " << segment->base()->getAutoTarget() << endl; - // } + if (segment->isReduced()) reduceds.push_back( segment ); totalWireLength += wl; - if (segment->getTrack() != NULL) { + if ( (segment->getTrack() != NULL) or (segment->isReduced()) ) { routeds++; routedWireLength += wl; - } else { - unrouteds.push_back( segment ); + continue; } + + unrouteds.push_back( segment ); } float segmentRatio = (float)(routeds) / (float)(routeds+unrouteds.size()) * 100.0; @@ -704,6 +706,13 @@ namespace Kite { } } + // if (not reduceds.empty()) { + // cerr << " o Reduced segments:" << endl; + // for ( size_t i=0; isetFixedPreRouted(); } + Session::revalidate(); Session::get()->isEmpty(); # if defined(CHECK_DATABASE) diff --git a/kite/src/ProtectRoutingPads.cpp b/kite/src/ProtectRoutingPads.cpp index 309db737..7206a581 100644 --- a/kite/src/ProtectRoutingPads.cpp +++ b/kite/src/ProtectRoutingPads.cpp @@ -71,12 +71,17 @@ namespace { void protectRoutingPad ( RoutingPad* rp ) { + Name padNetName = "pad"; Component* usedComponent = rp->_getEntityAsComponent(); Path path = rp->getOccurrence().getPath(); Net* masterNet = usedComponent->getNet(); Transformation transformation = path.getTransformation(); - if ( CatalogExtension::isPad(masterNet->getCell()) ) return; + if ( CatalogExtension::isPad(masterNet->getCell()) ) { + if ( rp->getNet()->isPower() + or (rp->getNet()->getName() == padNetName) ) + return; + } vector segments; diff --git a/kite/src/RoutingEvent.cpp b/kite/src/RoutingEvent.cpp index 74f54c79..9cf6540d 100644 --- a/kite/src/RoutingEvent.cpp +++ b/kite/src/RoutingEvent.cpp @@ -476,7 +476,8 @@ namespace Kite { _axisHistory = _segment->getAxis(); _eventLevel = 0; ltrace(500) << "Deter| addInsertEvent() @" << fsm.getCost(itrack).getTrack() << endl; - Session::addInsertEvent( _segment, fsm.getCost(itrack).getTrack() ); + if (not _segment->isReduced()) + Session::addInsertEvent( _segment, fsm.getCost(itrack).getTrack() ); fsm.setState( SegmentFsm::SelfInserted ); } else { // Do ripup. diff --git a/kite/src/SegmentFsm.cpp b/kite/src/SegmentFsm.cpp index d8340254..54fed1ba 100644 --- a/kite/src/SegmentFsm.cpp +++ b/kite/src/SegmentFsm.cpp @@ -443,23 +443,23 @@ namespace Kite { SegmentFsm::SegmentFsm ( RoutingEvent* event, RoutingEventQueue& queue, RoutingEventHistory& history ) - : _event (event) - , _queue (queue) - , _history (history) - , _state (0) - , _data (NULL) - , _constraint () - , _optimal () - , _costs () - , _actions () - , _fullBlocked (true) + : _event (event) + , _queue (queue) + , _history (history) + , _state (0) + , _data (NULL) + , _constraint () + , _optimal () + , _costs () + , _actions () + , _fullBlocked(true) { TrackElement* segment = _event->getSegment(); unsigned int depth = Session::getRoutingGauge()->getLayerDepth(segment->getLayer()); - _event->setTracksFree ( 0 ); + _event->setTracksFree( 0 ); _data = segment->getDataNegociate(); - if ( !_data ) { + if (not _data) { _state = MissingData; return; } @@ -470,7 +470,7 @@ namespace Kite { _constraint = _event->getConstraints(); _optimal = _event->getOptimal(); - const Interval& perpandicular = _event->getPerpandicularFree (); + const Interval& perpandicular = _event->getPerpandicularFree(); ltrace(148) << "Katabatic intervals:" << endl; ltrace(148) << "* Optimal: " << _optimal << endl; @@ -478,18 +478,18 @@ namespace Kite { ltrace(148) << "* Perpandicular: " << perpandicular << endl; ltrace(148) << "* AxisHint: " << DbU::getValueString(_event->getAxisHint()) << endl; - if ( _event->getTracksNb() ) { - if ( _constraint.getIntersection(perpandicular).isEmpty() ) { + if (_event->getTracksNb()) { + if (_constraint.getIntersection(perpandicular).isEmpty()) { ltrace(200) << "Perpandicular free is too tight." << endl; _state = EmptyTrackList; } else - _constraint.intersection ( perpandicular ); + _constraint.intersection( perpandicular ); } else { ltrace(200) << "No Track in perpandicular free." << endl; _state = EmptyTrackList; } - if ( _state == EmptyTrackList ) return; + if (_state == EmptyTrackList) return; ltrace(148) << "Negociate intervals:" << endl; ltrace(148) << "* Optimal: " << _optimal << endl; @@ -504,27 +504,30 @@ namespace Kite { and (segment->base()->getAutoSource()->getGCell()->getGlobalsCount(depth) >= 9.0); RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(segment->getLayer()); - for( Track* track : Tracks_Range::get(plane,_constraint)) { + for ( Track* track : Tracks_Range::get(plane,_constraint) ) { unsigned int costflags = 0; costflags |= (segment->isLocal() and (depth >= 3)) ? TrackCost::LocalAndTopDepth : 0; - _costs.push_back ( track->getOverlapCost(segment,costflags) ); - _costs.back().setAxisWeight ( _event->getAxisWeight(track->getAxis()) ); - _costs.back().incDeltaPerpand ( _data->getWiringDelta(track->getAxis()) ); + if (not segment->isReduced()) + _costs.push_back( track->getOverlapCost(segment,costflags) ); + else + _costs.push_back( TrackCost(track,segment->getNet()) ); + _costs.back().setAxisWeight ( _event->getAxisWeight(track->getAxis()) ); + _costs.back().incDeltaPerpand( _data->getWiringDelta(track->getAxis()) ); if (segment->isGlobal()) { ltrace(500) << "Deter| setForGlobal() on " << track << endl; _costs.back().setForGlobal(); } if ( inLocalDepth and (_costs.back().getDataState() == DataNegociate::MaximumSlack) ) - _costs.back().setInfinite (); + _costs.back().setInfinite(); if ( isOneLocalTrack and _costs.back().isOverlapGlobal() and (_costs.back().getDataState() >= DataNegociate::ConflictSolveByHistory) ) - _costs.back().setInfinite (); + _costs.back().setInfinite(); - _costs.back().consolidate (); + _costs.back().consolidate(); if ( _fullBlocked and (not _costs.back().isBlockage() and not _costs.back().isFixed()) ) _fullBlocked = false; @@ -532,7 +535,7 @@ namespace Kite { } ltraceout(148); - if ( _costs.empty() ) { + if (_costs.empty()) { Track* nearest = plane->getTrackByPosition(_constraint.getCenter()); if ( (nearest->getAxis() < _constraint.getVMin()) @@ -541,9 +544,9 @@ namespace Kite { //cerr << "[UNIMPLEMENTED] " << segment << " no Track in constraint interval " // << _constraint << " " << "." << endl; } else { - cerr << Bug(" %s Track_Range() failed to find Tracks in %s (they exists)." - ,getString(segment).c_str() - ,getString(_constraint).c_str() + cerr << Bug( " %s Track_Range() failed to find Tracks in %s (they exists)." + , getString(segment).c_str() + , getString(_constraint).c_str() ) << endl; } _state = EmptyTrackList; @@ -557,11 +560,11 @@ namespace Kite { ? TrackCost::DiscardGlobals : 0; flags |= (RoutingEvent::getStage() == RoutingEvent::Repair) ? TrackCost::IgnoreSharedLength : 0; - if ( flags & TrackCost::DiscardGlobals ) { + if (flags & TrackCost::DiscardGlobals) { ltrace(200) << "TrackCost::Compare() - DiscardGlobals" << endl; } - sort ( _costs.begin(), _costs.end(), TrackCost::Compare(flags) ); + sort( _costs.begin(), _costs.end(), TrackCost::Compare(flags) ); size_t i=0; for ( ; (i<_costs.size()) and _costs[i].isFree() ; i++ ); diff --git a/kite/src/Session.cpp b/kite/src/Session.cpp index 4ed63a37..90dd21c7 100644 --- a/kite/src/Session.cpp +++ b/kite/src/Session.cpp @@ -14,14 +14,14 @@ // +-----------------------------------------------------------------+ -#include "hurricane/Bug.h" -#include "hurricane/Point.h" -#include "hurricane/Error.h" -#include "katabatic/GCellGrid.h" -#include "kite/Session.h" -#include "kite/Track.h" -#include "kite/TrackElement.h" -#include "kite/KiteEngine.h" +#include "hurricane/Bug.h" +#include "hurricane/Point.h" +#include "hurricane/Error.h" +#include "katabatic/GCellGrid.h" +#include "kite/Session.h" +#include "kite/Track.h" +#include "kite/TrackElement.h" +#include "kite/KiteEngine.h" namespace { @@ -135,11 +135,8 @@ namespace Kite { { return _getKiteEngine()->getGCellGrid()->getGCell(Point(x,y)); }; - size_t Session::_revalidate () + void Session::_doRemovalEvents () { - ltrace(90) << "Kite::Session::_revalidate()" << endl; - ltracein(90); - set packTracks; for ( size_t i=0 ; i<_removeEvents.size() ; ++i ) { @@ -152,6 +149,15 @@ namespace Kite { for ( set::iterator it=packTracks.begin() ; it != packTracks.end() ; ++it ) (*it)->doRemoval(); + } + + + size_t Session::_revalidate () + { + ltrace(150) << "Kite::Session::_revalidate()" << endl; + ltracein(150); + + _doRemovalEvents(); for ( size_t i=0 ; i<_insertEvents.size() ; ++i ) { if (_insertEvents[i]._segment) { @@ -194,10 +200,10 @@ namespace Kite { # if defined(CHECK_DATABASE) unsigned int overlaps = 0; # endif - for ( set::iterator it=_sortEvents.begin() ; it!=_sortEvents.end() ; ++it ) { - (*it)->doReorder(); + for ( Track* track : _sortEvents ) { + track->doReorder(); # if defined(CHECK_DATABASE) - (*it)->check( overlaps, "Session::_revalidate() - track sorting." ); + track->check( overlaps, "Session::_revalidate() - track sorting." ); # endif } @@ -227,7 +233,24 @@ namespace Kite { } #endif - ltraceout(90); + // Looking for reduced/raised segments. + for ( size_t i=0 ; icanReduce()) { + revalidateds[i]->reduce(); + TrackElement* trackSegment = lookup( revalidateds[i] ); + if (trackSegment->getTrack()) _addRemoveEvent( trackSegment ); + ltrace(150) << "Session: reduce:" << revalidateds[i] << endl; + } + if (revalidateds[i]->mustRaise()) { + revalidateds[i]->raise(); + lookup( revalidateds[i] )->reschedule( 0 ); + ltrace(150) << "Session: raise:" << revalidateds[i] << endl; + } + } + + _doRemovalEvents(); + + ltraceout(150); return count; } @@ -235,11 +258,17 @@ namespace Kite { bool Session::_isEmpty () const { if ( not _insertEvents.empty() or not _removeEvents.empty() or not _sortEvents.empty() ) { - cerr << Bug( " Session::checkEmpty() failed :\n" - " %u inserts, %u removes and %u sort events remains." + cerr << Bug( "Session::_isEmpty() failed :\n" + " %u inserts, %u removes and %u sort events remains." , _insertEvents.size() , _removeEvents.size() , _sortEvents .size() ) << endl; + if (not _sortEvents.empty()) { + cerr << " Remaining sort events on Tracks:" << endl; + for ( Track* track : _sortEvents ) { + cerr << " | " << track << endl; + } + } return false; } diff --git a/kite/src/TrackCost.cpp b/kite/src/TrackCost.cpp index dc78f751..5a7de899 100644 --- a/kite/src/TrackCost.cpp +++ b/kite/src/TrackCost.cpp @@ -31,6 +31,34 @@ namespace Kite { // ------------------------------------------------------------------- // Class : "TrackCost". + TrackCost::TrackCost ( Track* track, Net* net ) + : _flags (ZeroCost) + , _track (track) + , _begin (Track::npos) + , _end (Track::npos) + , _interval () + , _forGlobal (false) + , _blockage (false) + , _fixed (false) + , _infinite (false) + , _hardOverlap (false) + , _overlap (false) + , _leftOverlap (false) + , _rightOverlap (false) + , _overlapGlobal (false) + , _globalEnclosed (false) + , _terminals (0) + , _delta (0) + , _deltaShared (0) + , _deltaPerpand (0) + , _axisWeight (0) + , _distanceToFixed(2*Session::getSliceHeight()) + , _longuestOverlap(0) + , _dataState (0) + , _ripupCount (0) + { } + + TrackCost::TrackCost ( Track* track , const Interval& interval , size_t begin @@ -94,7 +122,6 @@ namespace Kite { } } - TrackCost::~TrackCost () { } diff --git a/kite/src/TrackElement.cpp b/kite/src/TrackElement.cpp index fb3cee5b..05ac0ef4 100644 --- a/kite/src/TrackElement.cpp +++ b/kite/src/TrackElement.cpp @@ -149,7 +149,7 @@ namespace Kite { bool TrackElement::isStrap () const { return false; } bool TrackElement::isSlackened () const { return false; } bool TrackElement::isDogleg () const { return false; } - bool TrackElement::isSameLayerDogleg () const { return false; } + bool TrackElement::isReduced () const { return false; } bool TrackElement::isUserDefined () const { return false; } // Predicates. bool TrackElement::canSlacken () const { return false; } diff --git a/kite/src/TrackFixedSegment.cpp b/kite/src/TrackFixedSegment.cpp index 661cfa1a..7192783b 100644 --- a/kite/src/TrackFixedSegment.cpp +++ b/kite/src/TrackFixedSegment.cpp @@ -1,8 +1,7 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC 2008-2013, All Rights Reserved +// Copyright (c) UPMC 2008-2015, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -120,12 +119,13 @@ namespace Kite { _sourceU = max( boundingBox.getYMin(), uside.getVMin()); _targetU = min( boundingBox.getYMax(), uside.getVMax()); - Katabatic::GCell* gcell = track->getKiteEngine()->getGCellGrid()->getGCell( Point(track->getAxis(),_sourceU) ); - Katabatic::GCell* end = track->getKiteEngine()->getGCellGrid()->getGCell( Point(track->getAxis(),_targetU) ); - Katabatic::GCell* up = NULL; - Interval guside = gcell->getSide( KbVertical ); - Interval segside ( boundingBox.getYMin(), boundingBox.getYMax() ); + Katabatic::GCell* gcell = track->getKiteEngine()->getGCellGrid()->getGCell( Point(track->getAxis(),_sourceU) ); if (gcell) { + Katabatic::GCell* end = track->getKiteEngine()->getGCellGrid()->getGCell( Point(track->getAxis(),_targetU) ); + Katabatic::GCell* up = NULL; + Interval guside = gcell->getSide( KbVertical ); + Interval segside ( boundingBox.getYMin(), boundingBox.getYMax() ); + while ( gcell and (gcell != end) ) { up = gcell->getUp(); if (up == NULL) break; diff --git a/kite/src/TrackSegment.cpp b/kite/src/TrackSegment.cpp index cbbcea47..41d9b451 100644 --- a/kite/src/TrackSegment.cpp +++ b/kite/src/TrackSegment.cpp @@ -141,7 +141,7 @@ namespace Kite { bool TrackSegment::isStrap () const { return _base->isStrap(); } bool TrackSegment::isSlackened () const { return _base->isSlackened(); } bool TrackSegment::isDogleg () const { return _base->isDogleg(); } - bool TrackSegment::isSameLayerDogleg () const { return _base->isSameLayerDogleg(); } + bool TrackSegment::isReduced () const { return _base->isReduced(); } bool TrackSegment::isUserDefined () const { return _base->isUserDefined(); } // Predicates. // Accessors. diff --git a/kite/src/kite/RoutingEvent.h b/kite/src/kite/RoutingEvent.h index 43ce7166..5850f048 100644 --- a/kite/src/kite/RoutingEvent.h +++ b/kite/src/kite/RoutingEvent.h @@ -17,10 +17,10 @@ #ifndef KITE_ROUTING_EVENT_H #define KITE_ROUTING_EVENT_H -#include -#include -#include -#include +#include +#include +#include +#include #include "hurricane/Interval.h" namespace Hurricane { diff --git a/kite/src/kite/Session.h b/kite/src/kite/Session.h index b2a27a16..cf0d35cf 100644 --- a/kite/src/kite/Session.h +++ b/kite/src/kite/Session.h @@ -83,6 +83,7 @@ namespace Kite { Net* _getBlockageNet (); unsigned int _getRipupCost (); Katabatic::GCell* _getGCellUnder ( DbU::Unit, DbU::Unit ); + void _doRemovalEvents (); virtual size_t _revalidate (); bool _isEmpty () const; NegociateWindow* _getNegociateWindow (); diff --git a/kite/src/kite/TrackCost.h b/kite/src/kite/TrackCost.h index d7d72cc1..e29d5e56 100644 --- a/kite/src/kite/TrackCost.h +++ b/kite/src/kite/TrackCost.h @@ -1,4 +1,3 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. @@ -40,10 +39,11 @@ namespace Kite { class TrackCost { public: - enum Flags { IgnoreAxisWeight = 0x1 - , DiscardGlobals = 0x2 - , IgnoreSharedLength = 0x4 - , LocalAndTopDepth = 0x1 + enum Flags { IgnoreAxisWeight = 0x0001 + , DiscardGlobals = 0x0002 + , IgnoreSharedLength = 0x0004 + , LocalAndTopDepth = 0x0008 + , ZeroCost = 0x0010 }; public: @@ -61,6 +61,9 @@ namespace Kite { }; public: + TrackCost ( Track* track + , Net* net + ); TrackCost ( Track* track , const Interval& interval , size_t begin diff --git a/kite/src/kite/TrackElement.h b/kite/src/kite/TrackElement.h index 863b96fa..dd7695e4 100644 --- a/kite/src/kite/TrackElement.h +++ b/kite/src/kite/TrackElement.h @@ -116,7 +116,7 @@ namespace Kite { virtual bool isStrap () const; virtual bool isSlackened () const; virtual bool isDogleg () const; - virtual bool isSameLayerDogleg () const; + virtual bool isReduced () const; virtual bool isUserDefined () const; // Predicates. inline bool isCreated () const; diff --git a/kite/src/kite/TrackSegment.h b/kite/src/kite/TrackSegment.h index 608d9fa3..a79524c7 100644 --- a/kite/src/kite/TrackSegment.h +++ b/kite/src/kite/TrackSegment.h @@ -67,7 +67,7 @@ namespace Kite { virtual bool isStrap () const; virtual bool isSlackened () const; virtual bool isDogleg () const; - virtual bool isSameLayerDogleg () const; + virtual bool isReduced () const; virtual bool isUserDefined () const; // Predicates. virtual bool canDogleg (); diff --git a/knik/src/Graph.cpp b/knik/src/Graph.cpp index 342d2461..e4453b98 100644 --- a/knik/src/Graph.cpp +++ b/knik/src/Graph.cpp @@ -369,7 +369,7 @@ Vertex* Graph::getVertex ( Point p ) { Vertex* vertex; #ifdef __USE_MATRIXVERTEX__ - vertex = _matrixVertex->getVertex(p); + vertex = _matrixVertex->getVertex(p); assert(vertex); #endif #ifdef __USE_SLICINGTREE__ @@ -1139,7 +1139,7 @@ void Graph::Dijkstra() UpdateEstimateCongestion(); //#endif - DebugSession::open( _working_net, 600 ); +//DebugSession::open( _working_net, 600 ); ltrace(600) << "Dijkstra for net: " << _working_net << endl; ltracein(600); ltrace(600) << "Stamp:" << _netStamp << endl; @@ -1304,7 +1304,7 @@ void Graph::Dijkstra() ltraceout(600); ltraceout(600); - DebugSession::close(); +//DebugSession::close(); } void Graph::Monotonic() diff --git a/knik/src/MatrixVertex.cpp b/knik/src/MatrixVertex.cpp index d61a0cd6..8adc2f0e 100644 --- a/knik/src/MatrixVertex.cpp +++ b/knik/src/MatrixVertex.cpp @@ -381,7 +381,23 @@ Vertex* MatrixVertex::getVertex ( Point point ) // ******************************************** { pair indexes = getIJ ( point ); - return getVertex ( indexes ); + Vertex* vertex = getVertex ( indexes ); + if (vertex and vertex->isBlocked()) { + Vertex* neighbor = NULL; + for ( size_t i=0; i<4 ; ++i ) { + neighbor = vertex->getFirstEdges(i)->getOpposite( vertex ); + if (neighbor and not neighbor->isBlocked()) + return neighbor; + } + } + + if (not vertex) { + cerr << Error( "MatrixVertex::getVertex(Point): On %s,\n" + " blocked and it's neighbors are also blocked (vertex unreachable)." + , getString(vertex).c_str() ) << endl; + } + + return vertex; } Vertex* MatrixVertex::getVertex ( DbU::Unit x, DbU::Unit y ) diff --git a/knik/src/knik/Vertex.h b/knik/src/knik/Vertex.h index d942c9c5..a5dc0851 100644 --- a/knik/src/knik/Vertex.h +++ b/knik/src/knik/Vertex.h @@ -19,24 +19,26 @@ namespace Knik { // ***** public: typedef ExtensionGo Inherit; + enum Flags { Blocked=0x0001 }; //enum EdgeDirection { EAST=0, NORTH=1, WEST=2, SOUTH=3, UNDEFINED=4 }; // Attributes // ********** private: - static const Name _extensionName; - Graph* _routingGraph; - Edge* _firstEdges[4]; // dans l'ordre : _hEdgeOut, _vEdgeOut, _hEdgeIn et _vEdgeIn - Edge* _predecessor; - Contact* _contact; - Point _position; - VTuple* _vtuple; - float _distance; - int _connexID; // XXX limiter le nombre de bits du connexID pour associer aux 3 booléens ? - unsigned _netStamp; - DbU::Unit _halfWidth; // this corresponds to the half width of dual bin of the vertex - DbU::Unit _halfHeight; // this corresponds to the half height of dual bin of the vertex - Box _boundingBox; + static const Name _extensionName; + Graph* _routingGraph; + Edge* _firstEdges[4]; // dans l'ordre : _hEdgeOut, _vEdgeOut, _hEdgeIn et _vEdgeIn + Edge* _predecessor; + Contact* _contact; + Point _position; + VTuple* _vtuple; + float _distance; + int _connexID; // XXX limiter le nombre de bits du connexID pour associer aux 3 booléens ? + unsigned _netStamp; + DbU::Unit _halfWidth; // this corresponds to the half width of dual bin of the vertex + DbU::Unit _halfHeight; // this corresponds to the half height of dual bin of the vertex + Box _boundingBox; + unsigned int _flags; // Constructors & Destructors // ************************** @@ -65,60 +67,62 @@ namespace Knik { void setVTuple ( VTuple* vtuple ) { _vtuple = vtuple; }; void attachToLocalRing ( Component* component ); void sortEdges (); + void setBlocked () { _flags |= Blocked; } + void resetBlocked () { _flags &= ~Blocked; } // Accessors // ********* public: - static const Name& staticGetName () { return _extensionName; }; - virtual const Name& getName () const { return _extensionName; }; - Edge* getHEdgeOut () const { return _firstEdges[0]; }; - Edge* getVEdgeOut () const { return _firstEdges[1]; }; - Edge* getHEdgeIn () const { return _firstEdges[2]; }; - Edge* getVEdgeIn () const { return _firstEdges[3]; }; - Edges getAdjacentEdges () const; - Edge* getPredecessor () const { return _predecessor; }; - Contact* getContact () const { return _contact; }; - int getConnexID () const { return _connexID; }; - float getDistance () const { return _distance; }; - unsigned getNetStamp () const { return _netStamp; }; - Point getPosition () const { return _position; }; - VTuple* getVTuple () const { return _vtuple; }; - Graph* getRoutingGraph () const { return _routingGraph; }; - DbU::Unit getX () const { return _position.getX(); }; - DbU::Unit getY () const { return _position.getY(); }; - DbU::Unit getXMin () const { return _position.getX() - _halfWidth; }; - DbU::Unit getYMin () const { return _position.getY() - _halfHeight; }; - DbU::Unit getXMax () const { return _position.getX() + _halfWidth; }; - DbU::Unit getYMax () const { return _position.getY() + _halfHeight; }; - DbU::Unit getHalfWidth () const { return _halfWidth; }; - DbU::Unit getHalfHeight () const { return _halfHeight; }; - Box getBox () const { return Box(getXMin(),getYMin(),getXMax(),getYMax()); }; - Edge* getFirstEdges ( int i ) const { return _firstEdges[i]; }; - Contact* getContact ( Edge* arrivalEdge ); - Edge* getHEdgeLeadingTo ( Vertex* to ); - Edge* getVEdgeLeadingTo ( Vertex* to ); - Edge* getHEdgeComingFrom ( Vertex* from ); - Edge* getVEdgeComingFrom ( Vertex* from ); - Edge* getBestHEdgeOut ( DbU::Unit yDest ); - Edge* getBestVEdgeOut ( DbU::Unit xDest ); - Edge* getBestHEdgeIn ( DbU::Unit yDest ); - Edge* getBestVEdgeIn ( DbU::Unit xDest ); + static const Name& staticGetName () { return _extensionName; }; + virtual const Name& getName () const { return _extensionName; }; + Edge* getHEdgeOut () const { return _firstEdges[0]; }; + Edge* getVEdgeOut () const { return _firstEdges[1]; }; + Edge* getHEdgeIn () const { return _firstEdges[2]; }; + Edge* getVEdgeIn () const { return _firstEdges[3]; }; + Edges getAdjacentEdges () const; + Edge* getPredecessor () const { return _predecessor; }; + Contact* getContact () const { return _contact; }; + int getConnexID () const { return _connexID; }; + float getDistance () const { return _distance; }; + unsigned getNetStamp () const { return _netStamp; }; + Point getPosition () const { return _position; }; + VTuple* getVTuple () const { return _vtuple; }; + Graph* getRoutingGraph () const { return _routingGraph; }; + DbU::Unit getX () const { return _position.getX(); }; + DbU::Unit getY () const { return _position.getY(); }; + DbU::Unit getXMin () const { return _position.getX() - _halfWidth; }; + DbU::Unit getYMin () const { return _position.getY() - _halfHeight; }; + DbU::Unit getXMax () const { return _position.getX() + _halfWidth; }; + DbU::Unit getYMax () const { return _position.getY() + _halfHeight; }; + DbU::Unit getHalfWidth () const { return _halfWidth; }; + DbU::Unit getHalfHeight () const { return _halfHeight; }; + Box getBox () const { return Box(getXMin(),getYMin(),getXMax(),getYMax()); }; + Edge* getFirstEdges ( int i ) const { return _firstEdges[i]; }; + Contact* getContact ( Edge* arrivalEdge ); + Edge* getHEdgeLeadingTo ( Vertex* to ); + Edge* getVEdgeLeadingTo ( Vertex* to ); + Edge* getHEdgeComingFrom ( Vertex* from ); + Edge* getVEdgeComingFrom ( Vertex* from ); + Edge* getBestHEdgeOut ( DbU::Unit yDest ); + Edge* getBestVEdgeOut ( DbU::Unit xDest ); + Edge* getBestHEdgeIn ( DbU::Unit yDest ); + Edge* getBestVEdgeIn ( DbU::Unit xDest ); // Predicates // ********** public: + bool isBlocked () const { return _flags & Blocked; }; bool isVerticallyAligned ( Vertex* vertex ) { return ( getX() == vertex->getX() ); }; bool isHorizontallyAligned ( Vertex* vertex ) { return ( getY() == vertex->getY() ); }; - bool hasInfo() const; + bool hasInfo () const; // ExtensionGo methods // ************** public: - void translate ( const DbU::Unit& dx, const DbU::Unit& dy ); - Cell* getCell () const; - Box getBoundingBox() const { Box area ( getPosition() ); return area.inflate(DbU::lambda(1)); }; - - void invalidate ( bool propagateFlag ); + void translate ( const DbU::Unit& dx, const DbU::Unit& dy ); + Cell* getCell () const; + Box getBoundingBox () const { Box area ( getPosition() ); return area.inflate(DbU::lambda(1)); }; + void invalidate ( bool propagateFlag ); // Others // ****** diff --git a/stratus1/src/stratus/st_instance.py b/stratus1/src/stratus/st_instance.py index e0dbbd8b..983f862b 100644 --- a/stratus1/src/stratus/st_instance.py +++ b/stratus1/src/stratus/st_instance.py @@ -322,7 +322,7 @@ class Inst : plug.setNet ( hurNet ) # In order to see the ring - if str ( realNet.__class__ ) not in ALIM_NET : CRL.createPartRing ( self._st_cell._hur_cell, hurNet.getName() ) + #if str ( realNet.__class__ ) not in ALIM_NET : CRL.createPartRing ( self._st_cell._hur_cell, hurNet.getName() ) ##### Loop on each pin for pin in self._map : diff --git a/stratus1/src/stratus/st_placement.py b/stratus1/src/stratus/st_placement.py index 3a861da1..09f630c7 100644 --- a/stratus1/src/stratus/st_placement.py +++ b/stratus1/src/stratus/st_placement.py @@ -49,9 +49,13 @@ from Hurricane import * - +from st_net import * from util_Place import * +global nbCkBuf +nbCkBuf = 0 + + ########### def Place ( ins, sym, ref, plac = FIXED, cell = None ) : global MYPITCH, MYSLICE @@ -535,3 +539,63 @@ def gauche ( sym ) : def droite ( sym ) : return sym == Transformation.Orientation.R2 or sym == Transformation.Orientation.MX or sym == Transformation.Orientation.R1 or sym == Transformation.Orientation.XR + + +################# +## ClockBuffer ## +################# +class ClockBuffer : + def __init__ ( self, netname ) : + global CELLS + from st_model import CELLS + global nbCkBuf + self.cell = CELLS[-1] + + self.net = self.cell._hur_cell.getNet ( netname ) + self.ck_b = Signal ( "ck_b%d"%nbCkBuf, 1 ) + + modelMasterCell = CRL.AllianceFramework.get().getCell ( "buf_x2", CRL.Catalog.State.Views ) + if not modelMasterCell : + err = "Stratus Error : ClockBuffer : Cannot find model cell : buf_x2 in database !\n" + raise Exception ( err ) + + inst = Instance.create ( self.cell._hur_cell, "ck_buffer%d"%nbCkBuf, modelMasterCell ) + nbCkBuf += 1 + + ##### Connection ##### + plugI = inst.getPlug ( modelMasterCell.getNet ( "i" ) ) + plugI.setNet ( self.net ) + + plugQ = inst.getPlug ( modelMasterCell.getNet ( "q" ) ) + plugQ.setNet ( self.ck_b._hur_net[0] ) + + plugGround = inst.getPlug ( iter(modelMasterCell.getGroundNets()).next() ) + plugGround.setNet ( iter(self.cell._hur_cell.getGroundNets()).next() ) + + plugPower = inst.getPlug ( iter(modelMasterCell.getPowerNets()).next() ) + plugPower.setNet ( iter(self.cell._hur_cell.getPowerNets()).next() ) + + def AddFF ( self, netname ) : + net = self.cell._hur_cell.getNet ( netname ) + if not net : + err = "AddFF Error net : " + netname + " not found" + raise Exception ( err ) + + instDrive = None + for plug in net.getPlugs(): + if plug.getMasterNet().getDirection() == Net.Direction.OUT : + instDrive = plug.getInstance() + break + + if instDrive == None : + err = "AddFF Error no drive instance found for net " + netname + ".\n" + raise Exception ( err ) + + masterCell = instDrive.getMasterCell() + ## ici il vaudrait mieux faire une recherche sur l'ensemble des plugs de l'instDrive et trouver celle accrochee au self.net ## + netCk = masterCell.getNet ( "ck" ) + if instDrive.getPlug ( netCk ).getNet() != self.net : + err = "Stratus Error : AddFF : driver Instance of net " + netname + " is not connected to signal " + str ( self.net.getName() ) + ".\n" + raise Exception ( err ) + + instDrive.getPlug ( netCk ).setNet ( self.ck_b._hur_net[0] ) diff --git a/stratus1/src/stratus/stratus.py b/stratus1/src/stratus/stratus.py index 1bb7316d..2f8ed701 100644 --- a/stratus1/src/stratus/stratus.py +++ b/stratus1/src/stratus/stratus.py @@ -73,7 +73,7 @@ DoStop = 0x0004 def buildModel ( name, flags ): try: - print name + #print name module = __import__( name, globals(), locals(), name ) if not module.__dict__.has_key(name): print '[ERROR] Stratus module <%s> do not contains a design of the same name.' % name diff --git a/unicorn/src/cgt.py b/unicorn/src/cgt.py index 3eff1b54..191976f0 100755 --- a/unicorn/src/cgt.py +++ b/unicorn/src/cgt.py @@ -57,25 +57,34 @@ def credits (): def runScript ( scriptPath, editor ): - try: - script = __import__(scriptPath) - except Exception, e: + try: + kw = { 'editor':editor } + sys.path.append(os.path.dirname(scriptPath)) + + module = __import__( os.path.basename(scriptPath), globals(), locals() ) + if not module.__dict__.has_key('ScriptMain'): + print '[ERROR] Script module is missing function ScriptMain().' + print ' <%s>' % scriptPath + return + if not callable( module.__dict__['ScriptMain'] ): + print '[ERROR] Script module symbol ScriptMain is not callable (not a function?).' + print ' <%s>' % scriptPath + return + + module.__dict__['ScriptMain']( **kw ) + + except ImportError, e: + module = str(e).split()[-1] + print '[ERROR] The <%s> script cannot be loaded.' % module + print ' Please check your design hierarchy.' + except Exception, e: print '[ERROR] An exception occured while loading the Stratus script module:' print ' <%s>\n' % (scriptPath) print ' You should check for simple python errors in this module.' print ' Error was:' print ' %s\n' % e print ' Trying to continue anyway...' - return - - if not hasattr(script,'ScriptMain'): - print '[ERROR] Script module is missing function ScriptMain().' - print ' <%s>' % scriptPath - return - - script.ScriptMain(editor) - - return + return if __name__ == '__main__': diff --git a/vlsisapd/src/utilities/src/vlsisapd/utilities/Dots.h b/vlsisapd/src/utilities/src/vlsisapd/utilities/Dots.h index 6e6884ce..a9cbf95a 100644 --- a/vlsisapd/src/utilities/src/vlsisapd/utilities/Dots.h +++ b/vlsisapd/src/utilities/src/vlsisapd/utilities/Dots.h @@ -64,7 +64,7 @@ namespace Utilities { inline void Dots::_flush ( char c ) { - _ostream.put( c ); + _ostream << c; _ostream.flush(); } From 9db97608cbdef5936261f4203ba7bbb436d6e3bc Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Tue, 18 Aug 2015 15:42:28 +0200 Subject: [PATCH 05/60] More clever way of taking into account constraints on caged terminals. * Change: In vlsispad, in Dots, add an enable/disable flag because when printing into a cmess, it is only the base class ostream which is took into account as none of it's methods are virtuals (silly me). * Bug: In Etesian, print into cmess instead of cout and make use of the Dots enabling feature. * New: In Katabatic, added AutoContact::migrateConstraintBox() to transfert constraint from one contact to another. New flag for AutoContact, CntWeakTerminal for AutoContact which are at the other of a segment directly connected to a terminal. They may hold special constraints in case of caged terminals (computed in Kite). In AutoHorizontal & AutoVertical, in ::_makeDogleg(), transfert flags and constraints when breaking a segment directly connected to a terminal. * New: In Kite, in protectCagedTerminals(), uses cross constraint on the AutoContact opposite to the ContactTerminal (CntWeakTerminal) instead of moving up one terminal over two consecutives. This is simpler without degrading the routing quality. --- etesian/src/Configuration.cpp | 16 ++++++------ etesian/src/EtesianEngine.cpp | 3 +++ katabatic/doc/AutoContact.dox | 6 +++++ katabatic/src/AutoContact.cpp | 17 +++++++++++++ katabatic/src/AutoContactHTee.cpp | 2 ++ katabatic/src/AutoContactTurn.cpp | 1 + katabatic/src/AutoContactVTee.cpp | 2 ++ katabatic/src/AutoHorizontal.cpp | 8 ++++++ katabatic/src/AutoSegment.cpp | 4 +++ katabatic/src/AutoVertical.cpp | 8 ++++++ katabatic/src/katabatic/AutoContact.h | 2 ++ kite/src/PreProcess.cpp | 25 ++++++++++++++----- knik/src/Graph.cpp | 4 +-- vlsisapd/src/utilities/src/Dots.cpp | 3 ++- .../utilities/src/vlsisapd/utilities/Dots.h | 12 +++++++-- 15 files changed, 94 insertions(+), 19 deletions(-) diff --git a/etesian/src/Configuration.cpp b/etesian/src/Configuration.cpp index bf992b46..a554790f 100644 --- a/etesian/src/Configuration.cpp +++ b/etesian/src/Configuration.cpp @@ -91,14 +91,14 @@ namespace Etesian { void Configuration::print ( Cell* cell ) const { - cout << " o Configuration of ToolEngine for Cell <" << cell->getName() << ">" << endl; - cout << Dots::asIdentifier(" - Cell Gauge" ,getString(_cg->getName())) << endl; - cout << Dots::asInt (" - Place Effort" ,_placeEffort ) << endl; - cout << Dots::asInt (" - Update Conf" ,_updateConf ) << endl; - cout << Dots::asInt (" - Spreading Conf",_spreadingConf) << endl; - cout << Dots::asBool (" - Routing driven",_routingDriven) << endl; - cout << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl; - cout << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl; + cmess1 << " o Configuration of ToolEngine for Cell <" << cell->getName() << ">" << endl; + cmess1 << Dots::asIdentifier(" - Cell Gauge" ,getString(_cg->getName())) << endl; + cmess1 << Dots::asInt (" - Place Effort" ,_placeEffort ) << endl; + cmess1 << Dots::asInt (" - Update Conf" ,_updateConf ) << endl; + cmess1 << Dots::asInt (" - Spreading Conf",_spreadingConf) << endl; + cmess1 << Dots::asBool (" - Routing driven",_routingDriven) << endl; + cmess1 << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl; + cmess1 << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl; } diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index 39610890..a76f207d 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -404,6 +404,7 @@ namespace Etesian { _flatDesign = true; Dots dots ( cmess2, " ", 80, 1000 ); + if (not cmess2.enabled()) dots.disable(); cmess1 << " o Erasing previous placement of <" << getCell()->getName() << ">" << endl; @@ -450,6 +451,8 @@ namespace Etesian { AllianceFramework* af = AllianceFramework::get(); DbU::Unit pitch = getPitch(); + if (not cmess2.enabled()) dots.disable(); + cmess1 << " - Building RoutingPads (transhierarchical) ..." << endl; //getCell()->flattenNets( Cell::Flags::BuildRings|Cell::Flags::NoClockFlatten ); getCell()->flattenNets( Cell::Flags::NoClockFlatten ); diff --git a/katabatic/doc/AutoContact.dox b/katabatic/doc/AutoContact.dox index 4d4b623d..b4f2831d 100644 --- a/katabatic/doc/AutoContact.dox +++ b/katabatic/doc/AutoContact.dox @@ -380,6 +380,12 @@ //! will not lead to an empty interval, in that case, do nothing and //! return \false. + //! \function void AutoContact::migrateConstraintBox ( AutoContact* other ); + //! Transfer the user constraint box from \c other to the current + //! object \c this. The constraints of \c other are restored to their + //! native values. The two contacts must belong to the same GCell for + //! this method to take effect. + /*! \class LocatorHelper * diff --git a/katabatic/src/AutoContact.cpp b/katabatic/src/AutoContact.cpp index 665d5adc..85e5cb74 100644 --- a/katabatic/src/AutoContact.cpp +++ b/katabatic/src/AutoContact.cpp @@ -500,6 +500,23 @@ namespace Katabatic { { return box = box.getIntersection ( getConstraintBox() ); } + void AutoContact::migrateConstraintBox ( AutoContact* other ) + { + if (_gcell != other->_gcell) { + cerr << Error( "AutoContact::migrateConstraintBox(): AutoContacts do not belongs to the same GCell:\n" + " from: %s\n" + " to: %s" + , getString(other).c_str() + , getString(this ).c_str() + ) << endl; + return; + } + + setConstraintBox( other->getConstraintBox() ); + other->restoreNativeConstraintBox(); + } + + Box AutoContact::getBoundingBox () const { return _gcell->getBoundingBox (); } diff --git a/katabatic/src/AutoContactHTee.cpp b/katabatic/src/AutoContactHTee.cpp index 27625c37..ddd2687b 100644 --- a/katabatic/src/AutoContactHTee.cpp +++ b/katabatic/src/AutoContactHTee.cpp @@ -294,6 +294,8 @@ namespace Katabatic { ltrace(110) << "delta:" << delta << endl; + unsetFlags( CntWeakTerminal ); + if (maxDepth - minDepth > 3) { showTopologyError( "Sheared HTee, layer delta exceed 3." ); setFlags( CntBadTopology ); diff --git a/katabatic/src/AutoContactTurn.cpp b/katabatic/src/AutoContactTurn.cpp index 294a00dd..00d37828 100644 --- a/katabatic/src/AutoContactTurn.cpp +++ b/katabatic/src/AutoContactTurn.cpp @@ -239,6 +239,7 @@ namespace Katabatic { size_t depthContact = (depthH1 < depthV1) ? depthH1 : depthH1-1; size_t delta = abssub ( depthH1, depthV1 ); + unsetFlags( CntWeakTerminal ); if (delta > 3) { showTopologyError( "Sheared Turn, layer delta exceed 3." ); setFlags( CntBadTopology ); diff --git a/katabatic/src/AutoContactVTee.cpp b/katabatic/src/AutoContactVTee.cpp index 59ae782d..a3fecb80 100644 --- a/katabatic/src/AutoContactVTee.cpp +++ b/katabatic/src/AutoContactVTee.cpp @@ -262,6 +262,8 @@ namespace Katabatic { ltrace(110) << "maxDepth:" << maxDepth << endl; ltrace(110) << "delta:" << delta << endl; + unsetFlags( CntWeakTerminal ); + if ( maxDepth - minDepth > 3 ) { showTopologyError( "Sheared VTee, layer delta exceed 3." ); setFlags( CntBadTopology ); diff --git a/katabatic/src/AutoHorizontal.cpp b/katabatic/src/AutoHorizontal.cpp index fc1e2e5b..53eef1ba 100644 --- a/katabatic/src/AutoHorizontal.cpp +++ b/katabatic/src/AutoHorizontal.cpp @@ -747,11 +747,19 @@ namespace Katabatic { if (isSourceTerminal()) { segment1->setFlags( SegWeakTerminal1 ); segment2->setFlags( SegWeakTerminal1 ); + autoTarget->unsetFlags( CntWeakTerminal ); + dlContact1->setFlags ( CntWeakTerminal ); + if (autoTarget->getGCell() == doglegGCell) + dlContact1->migrateConstraintBox( autoTarget ); } else if (isTargetTerminal()) { unsetFlags( SegTargetTerminal ); setFlags( SegWeakTerminal1 ); segment1->setFlags( SegWeakTerminal1 ); segment2->setFlags( SegTargetTerminal ); + autoSource->unsetFlags( CntWeakTerminal ); + dlContact2->setFlags ( CntWeakTerminal ); + if (autoSource->getGCell() == doglegGCell) + dlContact2->migrateConstraintBox( autoSource ); } else if (isWeakTerminal()) { segment1->setFlags( SegWeakTerminal1 ); segment2->setFlags( SegWeakTerminal1 ); diff --git a/katabatic/src/AutoSegment.cpp b/katabatic/src/AutoSegment.cpp index 1f2b95a5..cb8787b2 100644 --- a/katabatic/src/AutoSegment.cpp +++ b/katabatic/src/AutoSegment.cpp @@ -873,9 +873,13 @@ namespace Katabatic { if (source->isTerminal()) { unsetFlags( SegWeakTerminal ); setFlags ( SegSourceTerminal ); + if (not target->isTerminal()) + target->setFlags( CntWeakTerminal ); } else if (target->isTerminal()) { unsetFlags( SegWeakTerminal ); setFlags ( SegTargetTerminal ); + if (not source->isTerminal()) + source->setFlags( CntWeakTerminal ); } else { unsigned int terminalFlag = 0; switch ( _getFlags() & SegWeakTerminal ) { diff --git a/katabatic/src/AutoVertical.cpp b/katabatic/src/AutoVertical.cpp index ac3da7dc..72cc9b30 100644 --- a/katabatic/src/AutoVertical.cpp +++ b/katabatic/src/AutoVertical.cpp @@ -668,11 +668,19 @@ namespace Katabatic { if (isSourceTerminal()) { segment1->setFlags( SegWeakTerminal1 ); segment2->setFlags( SegWeakTerminal1 ); + autoTarget->unsetFlags( CntWeakTerminal ); + dlContact1->setFlags ( CntWeakTerminal ); + if (autoTarget->getGCell() == doglegGCell) + dlContact1->migrateConstraintBox( autoTarget ); } else if (isTargetTerminal()) { unsetFlags( SegTargetTerminal ); setFlags( SegWeakTerminal1 ); segment1->setFlags( SegWeakTerminal1 ); segment2->setFlags( SegTargetTerminal ); + autoSource->unsetFlags( CntWeakTerminal ); + dlContact2->setFlags ( CntWeakTerminal ); + if (autoSource->getGCell() == doglegGCell) + dlContact2->migrateConstraintBox( autoSource ); } else if (isWeakTerminal()) { segment1->setFlags( SegWeakTerminal1 ); segment2->setFlags( SegWeakTerminal1 ); diff --git a/katabatic/src/katabatic/AutoContact.h b/katabatic/src/katabatic/AutoContact.h index 52327661..528f4d62 100644 --- a/katabatic/src/katabatic/AutoContact.h +++ b/katabatic/src/katabatic/AutoContact.h @@ -66,6 +66,7 @@ namespace Katabatic { , CntInCreationStage = 0x00000080 , CntBadTopology = 0x00000100 , CntIgnoreAnchor = 0x00000200 + , CntWeakTerminal = 0x00000400 }; class AutoContact { @@ -161,6 +162,7 @@ namespace Katabatic { , DbU::Unit constraintMax , unsigned int flags=KbWarnOnError ); void restoreNativeConstraintBox (); + void migrateConstraintBox ( AutoContact* other ); void destroy (); // Inspector Management. Record* _getRecord () const; diff --git a/kite/src/PreProcess.cpp b/kite/src/PreProcess.cpp index e367bc2e..4b7aaa36 100644 --- a/kite/src/PreProcess.cpp +++ b/kite/src/PreProcess.cpp @@ -226,8 +226,8 @@ namespace { ltrace(150) << "protectCagedTerminals() " << track << endl; ltracein(150); - DbU::Unit lastMovedUp = track->getMin(); - unsigned int moveUpCount = 0; + DbU::Unit lastMovedUp = track->getMin(); + unsigned int moveUpCount = 0; Configuration* configuration = Session::getConfiguration(); const Layer* metal2 = configuration->getRoutingLayer( 1 ); @@ -258,9 +258,22 @@ namespace { continue; } - Katabatic::AutoContact* support = segment->base()->getAutoSource(); - RoutingPad* rp = dynamic_cast(support->getAnchor()); - Track* metal3track = metal3plane->getTrackByPosition( rp->getSourcePosition().getX() ); + Katabatic::AutoContact* support = NULL; + Katabatic::AutoContact* turn = NULL; + if (segment->base()->isSourceTerminal()) { + support = segment->base()->getAutoSource(); + turn = segment->base()->getAutoTarget(); + } else { + support = segment->base()->getAutoTarget(); + turn = segment->base()->getAutoSource(); + } + + RoutingPad* rp = dynamic_cast(support->getAnchor()); + Track* metal3track = metal3plane->getTrackByPosition( rp->getSourcePosition().getX() ); + + turn->restrictConstraintBox( freeInterval.getVMin() + , freeInterval.getVMax() + , KbVertical ); if (metal3track->getFreeInterval(segment->getAxis(),segment->getNet()).isEmpty()) { cparanoid << "[INFO] Cannot protect caged terminal because top layer (metal3) is obstructed." << endl; @@ -270,7 +283,7 @@ namespace { if (segment->getSourceU() - lastMovedUp < ppitch*4) { ++moveUpCount; if (moveUpCount % 2 == 0) { - moveUpCaged( segment ); + //moveUpCaged( segment ); } } else { moveUpCount = 0; diff --git a/knik/src/Graph.cpp b/knik/src/Graph.cpp index e4453b98..c4dffba2 100644 --- a/knik/src/Graph.cpp +++ b/knik/src/Graph.cpp @@ -170,12 +170,12 @@ void Graph::_postCreate() } if (_lowerLeftVertex->getHEdgeOut()) - cout << Dots::asUInt (" - Global router H edges capacity" ,_lowerLeftVertex->getHEdgeOut()->getCapacity()) << endl; + cmess1 << Dots::asUInt (" - Global router H edges capacity" ,_lowerLeftVertex->getHEdgeOut()->getCapacity()) << endl; else cerr << Warning( "Knik::Graph: Design has only one column, H edge capacity is zero." ) << endl; if (_lowerLeftVertex->getVEdgeOut()) - cout << Dots::asUInt (" - Global router V edges capacity" ,_lowerLeftVertex->getVEdgeOut()->getCapacity()) << endl; + cmess1 << Dots::asUInt (" - Global router V edges capacity" ,_lowerLeftVertex->getVEdgeOut()->getCapacity()) << endl; else cerr << Warning( "Knik::Graph: Design has only one row, V edge capacity is zero." ) << endl; diff --git a/vlsisapd/src/utilities/src/Dots.cpp b/vlsisapd/src/utilities/src/Dots.cpp index d18551cf..6ff55197 100644 --- a/vlsisapd/src/utilities/src/Dots.cpp +++ b/vlsisapd/src/utilities/src/Dots.cpp @@ -30,7 +30,8 @@ namespace Utilities { CR(); else _flags &= ~FirstDot; - _ostream << _indent; + if (enabled()) + _ostream << _indent; } _flush( '.' ); diff --git a/vlsisapd/src/utilities/src/vlsisapd/utilities/Dots.h b/vlsisapd/src/utilities/src/vlsisapd/utilities/Dots.h index a9cbf95a..30c9a838 100644 --- a/vlsisapd/src/utilities/src/vlsisapd/utilities/Dots.h +++ b/vlsisapd/src/utilities/src/vlsisapd/utilities/Dots.h @@ -26,7 +26,7 @@ namespace Utilities { class Dots { public: - enum Flag { NoFlags=0x00, FirstDot=0x01, Reset=0x02 }; + enum Flag { NoFlags=0x00, FirstDot=0x01, Reset=0x02, Disabled=0x04 }; public: inline Dots ( std::ostream& , const std::string& indent @@ -38,6 +38,9 @@ namespace Utilities { inline void CR (); void dot (); void finish ( unsigned int flags ); + inline bool enabled (); + inline void enable (); + inline void disable (); private: inline void _flush ( char ); private: @@ -61,9 +64,14 @@ namespace Utilities { inline void Dots::setWidth ( unsigned int w ) { _width=w; } inline void Dots::setDivider ( unsigned int d ) { _divider=d; } + inline bool Dots::enabled () { return not (_flags & Disabled); } + inline void Dots::enable () { _flags &= ~Disabled; } + inline void Dots::disable () { _flags |= Disabled; } inline void Dots::_flush ( char c ) { + if (not enabled()) return; + _ostream << c; _ostream.flush(); } @@ -75,7 +83,7 @@ namespace Utilities { inline void Dots::reset ( unsigned int flags ) { - _flags = flags; + _flags = flags | ((not enabled()) ? Disabled : NoFlags); _count = 0; } From 7669c66597eb788d751ceb2024435ace48027d2b Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sun, 6 Sep 2015 17:14:24 +0200 Subject: [PATCH 06/60] In Cumulus/PadsCorona.py, now manage global nets explicitly connecteds. --- cumulus/src/plugins/chip/PadsCorona.py | 28 ++++++++++++++------------ 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/cumulus/src/plugins/chip/PadsCorona.py b/cumulus/src/plugins/chip/PadsCorona.py index b157dc96..8221b052 100644 --- a/cumulus/src/plugins/chip/PadsCorona.py +++ b/cumulus/src/plugins/chip/PadsCorona.py @@ -120,22 +120,24 @@ class Side ( object ): trace( 550, ',+', '\t_createPowerContacts() for %s\n' % net.getName() ) + components = None masterCell = pad.getMasterCell() - if net.isGlobal(): - trace( 550, '\tLooking for global net %s\n' % net.getName() ) + trace( 550, '\tLooking for global net %s\n' % net.getName() ) + for plug in net.getPlugs(): + if plug.getInstance() == pad: + trace( 550, '\tFound Plug on %s\n' % pad ) + components = plug.getMasterNet().getExternalComponents() + if not components: masterNet = masterCell.getNet( net.getName() ) - if not masterNet: - raise ErrorMessage( 1, [ 'PadsCorona.Side._createPowerContact():' - , 'Pad model <%s> of instance <%s> do not have global net <%s>' % (pad.getName(),masterCell.getName(),net.getName()) - , 'The power/clock nets *names* in the chip must match those of the pads models.' - ] ) + if masterNet: + components = masterCell.getNet(net.getName()).getExternalComponents() + if not components: + raise ErrorMessage( 1, [ 'PadsCorona.Side._createPowerContact():' + , 'Pad model <%s> of instance <%s> neither have global net <%s>' % (pad.getName(),masterCell.getName(),net.getName()) + , 'for implicit connection nor is it explicitly connected.' + , 'The power/clock nets *names* in the chip must match those of the pads models.' + ] ) - components = masterCell.getNet(net.getName()).getExternalComponents() - else: - for plug in net.getPlugs(): - if plug.getInstance() == pad: - trace( 550, '\tFound Plug on %s\n' % pad ) - components = plug.getMasterNet().getExternalComponents() connecteds = False trace( 550, '\t %s\n' % str(masterCell.getAbutmentBox()) ) From 1adefabb2fb3c7e9f611777454955e1e159e6fd2 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sun, 6 Sep 2015 17:24:04 +0200 Subject: [PATCH 07/60] Correctly remove VHDL Entity and Bit properties. * Bug: In CRL Core, in Vst driver, remove VhdlEntity (from Cell) and BitProperty/Bit (from Net) with the property remove and not the destroy() method. The BitProperty removal was completly forgotten leading to the use of removed Signals when doing multiple saves (hence core-dump). * Change: In CRL Core, in Vst driver, never save as Signals the DeepNets as they are created by a virtual flatten and do not connect any instances at top level. Note that they will exists in the physical file if routing layout has been created. --- crlcore/src/ccore/alliance/vst/VhdlEntity.cpp | 33 ++++++++++--------- crlcore/src/ccore/alliance/vst/VhdlSignal.cpp | 4 +-- crlcore/src/ccore/crlcore/VhdlBit.h | 2 ++ crlcore/src/pyCRL/PyCRL.cpp | 2 +- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/crlcore/src/ccore/alliance/vst/VhdlEntity.cpp b/crlcore/src/ccore/alliance/vst/VhdlEntity.cpp index 149c742b..e972b37c 100644 --- a/crlcore/src/ccore/alliance/vst/VhdlEntity.cpp +++ b/crlcore/src/ccore/alliance/vst/VhdlEntity.cpp @@ -111,16 +111,17 @@ namespace Vhdl { if (_flags == NoFlags) _flags = EntityMode; - forEach ( Net*, inet, cell->getNets() ) { - if (not inet->isExternal() and (flags & ComponentMode)) continue; + for ( Net* net : cell->getNets() ) { + if (net->isDeepNet()) continue; + if (not net->isExternal() and (flags & ComponentMode)) continue; string stem; size_t index = 0; - if (parseNetName(*inet,stem,index)) { - if (inet->isGlobal()) { + if (parseNetName(net,stem,index)) { + if (net->isGlobal()) { cerr << Warning( "Vhdl::Entity::Entity(): Net is both vectorized and global, this is not allowed.\n" " On Net <%s> of Cell <%s>." - , getString(inet->getName()).c_str() + , getString(net->getName()).c_str() , getString(cell->getName()).c_str() ) << endl; } @@ -128,12 +129,12 @@ namespace Vhdl { VectorSignal* signal = const_cast( dynamic_cast( getSignal(stem) ) ); if (not signal) signal = new VectorSignal ( stem ); - signal->addNet( index, *inet ); + signal->addNet( index, net ); _signals.insert( signal ); } else { - _signals.insert( new ScalarSignal(*inet) ); - if (inet->isGlobal()) - _globals.insert( new ScalarSignal(*inet) ); + _signals.insert( new ScalarSignal(net) ); + if (net->isGlobal()) + _globals.insert( new ScalarSignal(net) ); } } @@ -144,6 +145,7 @@ namespace Vhdl { Entity::~Entity () { for ( auto signal : _signals ) delete signal; + for ( auto global : _globals ) delete global; for ( auto ientity=_entities.begin() ; ientity!=_entities.end() ; ++ientity ) { if (*ientity == this) { _entities.erase( ientity ); @@ -210,19 +212,20 @@ namespace Vhdl { { if (isEntityMode()) return; - forEach ( Net*, inet, getCell()->getNets() ) { - if (inet->isExternal()) continue; + for ( Net* net : getCell()->getNets() ) { + if (net->isDeepNet()) continue; + if (net->isExternal()) continue; string stem; size_t index = 0; - if (parseNetName(*inet,stem,index)) { + if (parseNetName(net,stem,index)) { VectorSignal* signal = const_cast( dynamic_cast( getSignal(stem) ) ); if (not signal) signal = new VectorSignal ( stem ); - signal->addNet( index, *inet ); + signal->addNet( index, net ); _signals.insert( signal ); } else { - _signals.insert( new ScalarSignal(*inet) ); + _signals.insert( new ScalarSignal(net) ); } } } @@ -518,7 +521,7 @@ namespace Vhdl { void EntityExtension::destroy ( Cell* cell ) { Property* property = cell->getProperty( EntityProperty::getPropertyName() ); - if (property) static_cast(property)->destroy(); + if (property) cell->remove( property ); _owner = NULL; _cache = NULL; diff --git a/crlcore/src/ccore/alliance/vst/VhdlSignal.cpp b/crlcore/src/ccore/alliance/vst/VhdlSignal.cpp index 77f4ca01..17b50fed 100644 --- a/crlcore/src/ccore/alliance/vst/VhdlSignal.cpp +++ b/crlcore/src/ccore/alliance/vst/VhdlSignal.cpp @@ -102,7 +102,7 @@ namespace Vhdl { { } ScalarSignal::~ScalarSignal () - { } + { _bit->destroy(); } bool ScalarSignal::isScalar () const { return true; } bool ScalarSignal::isVector () const { return false; } @@ -150,7 +150,7 @@ namespace Vhdl { { } VectorSignal::~VectorSignal () - { for ( auto bit : _bits ) bit->getProperty()->destroy(); } + { for ( auto bit : _bits ) bit->destroy(); } bool VectorSignal::isScalar () const { return false; } diff --git a/crlcore/src/ccore/crlcore/VhdlBit.h b/crlcore/src/ccore/crlcore/VhdlBit.h index ef069911..1ca72fd8 100644 --- a/crlcore/src/ccore/crlcore/VhdlBit.h +++ b/crlcore/src/ccore/crlcore/VhdlBit.h @@ -59,6 +59,7 @@ namespace Vhdl { const Signal* getSignal () const; std::string getName () const; size_t getIndex () const; + inline void destroy (); std::string _getString () const; Record* _getRecord () const; private: @@ -151,6 +152,7 @@ namespace Vhdl { inline BitProperty* Bit::getProperty () const { return (BitProperty*)((ptrdiff_t)(this) - _offset); } inline const Net* Bit::getNet () const { return (const Net*)getProperty()->getOwner(); } + inline void Bit::destroy () { ((Net*)getProperty()->getOwner())->remove( getProperty() ); } } // Vhdl Namespace. diff --git a/crlcore/src/pyCRL/PyCRL.cpp b/crlcore/src/pyCRL/PyCRL.cpp index c59c56f3..f0ed2ffd 100644 --- a/crlcore/src/pyCRL/PyCRL.cpp +++ b/crlcore/src/pyCRL/PyCRL.cpp @@ -8,7 +8,7 @@ // | Alliance / Hurricane Interface | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./PyCRL.cpp" | // +-----------------------------------------------------------------+ From 2c6bee30ad83f473b468b84531da8fb9e3f0353d Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sun, 6 Sep 2015 17:25:49 +0200 Subject: [PATCH 08/60] Minor style change (beautifying). --- hurricane/src/hurricane/Property.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/hurricane/src/hurricane/Property.cpp b/hurricane/src/hurricane/Property.cpp index cb03d59b..13b13d16 100644 --- a/hurricane/src/hurricane/Property.cpp +++ b/hurricane/src/hurricane/Property.cpp @@ -19,12 +19,7 @@ // License along with Hurricane. If not, see // . // -// =================================================================== -// -// $Id$ -// -// x-----------------------------------------------------------------x -// | | +// +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | // | | @@ -32,10 +27,7 @@ // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./Property.cpp" | -// | *************************************************************** | -// | U p d a t e s | -// | | -// x-----------------------------------------------------------------x +// +-----------------------------------------------------------------+ #include "hurricane/Property.h" From 0930660a1f4f74cbfc2238d0107d98a62dcc662c Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Fri, 2 Oct 2015 15:59:01 +0200 Subject: [PATCH 09/60] Added detection of Windows 10 / Cygwin64 (N. Shimizu). --- bootstrap/builder/Configuration.py | 6 ++++++ bootstrap/ccb.py | 7 +++++++ bootstrap/cmake_modules/FindBootstrap.cmake | 12 +++++++----- bootstrap/coriolisEnv.py | 7 +++++++ vlsisapd/src/liberty/src/LibertyParserScanner.ll | 1 + 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/bootstrap/builder/Configuration.py b/bootstrap/builder/Configuration.py index ca574de7..795d0285 100644 --- a/bootstrap/builder/Configuration.py +++ b/bootstrap/builder/Configuration.py @@ -146,6 +146,8 @@ class Configuration ( object ): self._osCygwinW7 = re.compile (".*CYGWIN_NT-6\.1.*i686.*") self._osCygwinW8_64 = re.compile (".*CYGWIN_NT-6\.[2-3].*x86_64.*") self._osCygwinW8 = re.compile (".*CYGWIN_NT-6\.[2-3].*i686.*") + self._osCygwinW10_64 = re.compile (".*CYGWIN_NT-10\.[0-3].*x86_64.*") + self._osCygwinW10 = re.compile (".*CYGWIN_NT-10\.[0-3].*i686.*") uname = subprocess.Popen ( ["uname", "-srm"], stdout=subprocess.PIPE ) lines = uname.stdout.readlines() @@ -186,6 +188,10 @@ class Configuration ( object ): self._osType = "Cygwin.W8_64" self._libSuffix = "64" elif self._osCygwinW8.match(lines[0]): self._osType = "Cygwin.W8" + elif self._osCygwinW10_64.match(lines[0]): + self._osType = "Cygwin.W10_64" + self._libSuffix = "64" + elif self._osCygwinW10.match(lines[0]): self._osType = "Cygwin.W10" else: uname = subprocess.Popen ( ["uname", "-sr"], stdout=subprocess.PIPE ) self._osType = uname.stdout.readlines()[0][:-1] diff --git a/bootstrap/ccb.py b/bootstrap/ccb.py index e209cb77..b442b625 100755 --- a/bootstrap/ccb.py +++ b/bootstrap/ccb.py @@ -80,6 +80,8 @@ def guessOs (): osCygwinW7 = re.compile (".*CYGWIN_NT-6\.1.*i686.*") osCygwinW8_64 = re.compile (".*CYGWIN_NT-6\.[2-3].*x86_64.*") osCygwinW8 = re.compile (".*CYGWIN_NT-6\.[2-3].*i686.*") + osCygwinW10_64 = re.compile (".*CYGWIN_NT-10\.[0-3].*x86_64.*") + osCygwinW10 = re.compile (".*CYGWIN_NT-10\.[0-3].*i686.*") uname = subprocess.Popen ( ["uname", "-srm"], stdout=subprocess.PIPE ) lines = uname.stdout.readlines() @@ -127,6 +129,11 @@ def guessOs (): libDir = "lib64" elif osCygwinW8.match(lines[0]): osType = "Cygwin.W8" + elif osCygwinW10_64.match(lines[0]): + osType = "Cygwin.W10_64" + libDir = "lib64" + elif osCygwinW10.match(lines[0]): + osType = "Cygwin.W10" else: uname = subprocess.Popen ( ["uname", "-sr"], stdout=subprocess.PIPE ) osType = uname.stdout.readlines()[0][:-1] diff --git a/bootstrap/cmake_modules/FindBootstrap.cmake b/bootstrap/cmake_modules/FindBootstrap.cmake index 322c6e77..b76b67fc 100644 --- a/bootstrap/cmake_modules/FindBootstrap.cmake +++ b/bootstrap/cmake_modules/FindBootstrap.cmake @@ -78,14 +78,16 @@ #set(DEBUG_FLAGS "-g -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC") set(DEBUG_FLAGS "-g") if(CYGWIN) - set(CXX_STANDARD "gnu++0x") + set(ADDTIONAL_FLAGS "-D_GLIBCXX_USE_C99") + set(CXX_STANDARD "gnu++11") else() + set(ADDTIONAL_FLAGS "") set(CXX_STANDARD "c++11") endif() - set(CMAKE_C_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug options." FORCE) - set(CMAKE_C_FLAGS_RELEASE "-std=${CXX_STANDARD} -Wall -O2 -DNDEBUG" CACHE STRING "C Compiler Release options." FORCE) - set(CMAKE_CXX_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall ${DEBUG_FLAGS}" CACHE STRING "C++ Compiler Debug options." FORCE) - set(CMAKE_CXX_FLAGS_RELEASE "-std=${CXX_STANDARD} -Wall -O2 -DNDEBUG" CACHE STRING "C++ Compiler Release options." FORCE) + set(CMAKE_C_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C Compiler Debug options." FORCE) + set(CMAKE_C_FLAGS_RELEASE "-std=${CXX_STANDARD} -Wall -O2 ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C Compiler Release options." FORCE) + set(CMAKE_CXX_FLAGS_DEBUG "-std=${CXX_STANDARD} -Wall ${ADDTIONAL_FLAGS} ${DEBUG_FLAGS}" CACHE STRING "C++ Compiler Debug options." FORCE) + set(CMAKE_CXX_FLAGS_RELEASE "-std=${CXX_STANDARD} -Wall -O2 ${ADDTIONAL_FLAGS} -DNDEBUG" CACHE STRING "C++ Compiler Release options." FORCE) # diff --git a/bootstrap/coriolisEnv.py b/bootstrap/coriolisEnv.py index db1b5041..b336757d 100755 --- a/bootstrap/coriolisEnv.py +++ b/bootstrap/coriolisEnv.py @@ -52,6 +52,8 @@ def guessOs (): osCygwinW7 = re.compile (".*CYGWIN_NT-6\.1.*i686.*") osCygwinW8_64 = re.compile (".*CYGWIN_NT-6\.[2-3].*x86_64.*") osCygwinW8 = re.compile (".*CYGWIN_NT-6\.[2-3].*i686.*") + osCygwinW10_64 = re.compile (".*CYGWIN_NT-10\.[0-3].*x86_64.*") + osCygwinW10 = re.compile (".*CYGWIN_NT-10\.[0-3].*i686.*") uname = subprocess.Popen ( ["uname", "-srm"], stdout=subprocess.PIPE ) lines = uname.stdout.readlines() @@ -108,6 +110,11 @@ def guessOs (): libDir = "lib64" elif osCygwinW8.match(lines[0]): osType = "Cygwin.W8" + elif osCygwinW10_64.match(lines[0]): + osType = "Cygwin.W10_64" + libDir = "lib64" + elif osCygwinW10.match(lines[0]): + osType = "Cygwin.W10" else: uname = subprocess.Popen ( ["uname", "-sr"], stdout=subprocess.PIPE ) osType = uname.stdout.readlines()[0][:-1] diff --git a/vlsisapd/src/liberty/src/LibertyParserScanner.ll b/vlsisapd/src/liberty/src/LibertyParserScanner.ll index 11e5fe01..e03820d3 100644 --- a/vlsisapd/src/liberty/src/LibertyParserScanner.ll +++ b/vlsisapd/src/liberty/src/LibertyParserScanner.ll @@ -3,6 +3,7 @@ %{ +#include #include #include #include From f537a10d45b74f45e608665fea432306ff884fbc Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Thu, 7 Jan 2016 13:13:16 +0100 Subject: [PATCH 10/60] Implementation of DataBase native save/restore in JSON (step 1). * New: In Hurricane, added first support for DataBase native import/export using JSON. We choose RapidJSON, in SAX mode, to manage the JSON format low level Read/Write. Thus, it's Git repository http://github.com/miloyip/rapidjson must be added under ~/coriolis-2.x/src and manually build and installed in the Coriolis installation tree (to be integrated in ccb later). Two mode are being supported: 1. Cell mode: one Cell only is saved. In that mode, Entities referred by Occurrences are "outside" the file. They are coded through their "signature" (mostly, all the values of their attributes). The ids saved in the file cannot be restored identically as we cannot predict when and in which context the Cell will be reloaded. 2. Design Blob mode: the whole design hierarchy, down and including the standard cells is saved. This way the design is completly self contained and Entities ared referred through their ids. A design blob can only be loaded immediatly after starting cgt as the DataBase *must* be empty. This way we restore the whole design hierarchy with *exactly* the same ids. Now, Hurricane object should provide a "toJson()" method for driving JSON, and be associated with a JsonObject derived class for parsing. * New: In Hurricane, ability to force the next id that will be used for a DBo (used by Design Blob Mode). * New: In Hurricane, in DataBase, added getCell() and getLibrary() functions to allow the hierarchical access of a Cell/Library in native mode (i.e. whithout the requirement of AllianceFramework). * New: In Hurricane, In CellViewer, added menu entry for Save/Load of JSON Design Blobs. Added at this level because we consider it as the "native" format of Hurricane. * New: In Unicorn, added support of import/export of JSON Cell. * Bug: In Hurricane, in Instance, when cloning an Instance or uniquifying it's master Cell, we forgot about the Occurrences (through shared pathes). When an instance is cloned the Shared pathes still points toward the original Instance. And when it's the master Cell that is uniquifyed it's the Entities pointed to that remains in the original Cell. This is a software design problem. It is difficult to define what policy to adopt when uniquifying: basically that means that one Occurence is either moved onto the clone or duplicated. Furthermore, it is not trivial to known what Occurrence is pointing on the uniquifyed/cloned item. Have to think about it a little more. * Bug: In Etesian, in EtesianEngine, build the flattened nets and their RoutingPads *after* uniquifying (through slaving bounding boxes). This way we avoid the Occurrences problem described above. * Bug: In Etesian, in EtesianEngine, invalidate the RoutingPad after processing the placement so they are put into the right quadtree. This problem is due to the fact that the RoutingPads do not belong to the Instance that they refer. And when this instance is moved around, she doesn't inform the RoutingPad that is has moved. More software architecture design to review... --- crlcore/src/ccore/AllianceFramework.cpp | 50 +- crlcore/src/ccore/crlcore/AllianceFramework.h | 1 + etesian/src/EtesianEngine.cpp | 18 +- hurricane/src/hurricane/Box.cpp | 54 +- hurricane/src/hurricane/CMakeLists.txt | 9 + hurricane/src/hurricane/Cell.cpp | 145 +++ hurricane/src/hurricane/Component.cpp | 54 +- hurricane/src/hurricane/Contact.cpp | 81 +- hurricane/src/hurricane/DBo.cpp | 51 +- hurricane/src/hurricane/DataBase.cpp | 51 +- hurricane/src/hurricane/DeepNet.cpp | 58 +- hurricane/src/hurricane/DesignBlob.cpp | 74 ++ hurricane/src/hurricane/Entity.cpp | 112 +- hurricane/src/hurricane/Hook.cpp | 26 + hurricane/src/hurricane/Horizontal.cpp | 57 + hurricane/src/hurricane/Instance.cpp | 98 +- hurricane/src/hurricane/JsonReader.cpp | 821 ++++++++++++ hurricane/src/hurricane/JsonWriter.cpp | 101 ++ hurricane/src/hurricane/Layer.cpp | 7 +- hurricane/src/hurricane/Library.cpp | 77 ++ hurricane/src/hurricane/Net.cpp | 133 +- hurricane/src/hurricane/Occurrence.cpp | 88 ++ hurricane/src/hurricane/Pad.cpp | 50 + hurricane/src/hurricane/Path.cpp | 20 +- hurricane/src/hurricane/Plug.cpp | 122 +- hurricane/src/hurricane/Point.cpp | 33 + hurricane/src/hurricane/RoutingPad.cpp | 70 +- hurricane/src/hurricane/Segment.cpp | 66 +- hurricane/src/hurricane/SharedPath.cpp | 17 + hurricane/src/hurricane/Signature.cpp | 167 +++ hurricane/src/hurricane/Tabulation.cpp | 3 +- hurricane/src/hurricane/Transformation.cpp | 56 + hurricane/src/hurricane/Vertical.cpp | 57 + hurricane/src/hurricane/grenier/json/DBo.cpp | 198 +++ hurricane/src/hurricane/grenier/json/DBo.h | 114 ++ .../src/hurricane/grenier/json/JsonReader.cpp | 650 ++++++++++ .../src/hurricane/grenier/json/JsonReader.h | 790 ++++++++++++ hurricane/src/hurricane/grenier/json/Net.cpp | 1106 +++++++++++++++++ hurricane/src/hurricane/grenier/json/Net.h | 363 ++++++ hurricane/src/hurricane/hurricane/Box.h | 13 +- hurricane/src/hurricane/hurricane/Cell.h | 16 +- .../src/hurricane/hurricane/Collection.h | 191 ++- hurricane/src/hurricane/hurricane/Commons.h | 2 + hurricane/src/hurricane/hurricane/Component.h | 13 +- hurricane/src/hurricane/hurricane/Contact.h | 14 +- hurricane/src/hurricane/hurricane/DBo.h | 93 +- hurricane/src/hurricane/hurricane/DataBase.h | 10 +- hurricane/src/hurricane/hurricane/DbU.h | 4 + hurricane/src/hurricane/hurricane/DeepNet.h | 64 +- .../src/hurricane/hurricane/DesignBlob.h | 60 + hurricane/src/hurricane/hurricane/Entity.h | 56 +- hurricane/src/hurricane/hurricane/Hook.h | 8 +- .../src/hurricane/hurricane/Horizontal.h | 11 + hurricane/src/hurricane/hurricane/Instance.h | 17 + hurricane/src/hurricane/hurricane/Interval.h | 9 + .../src/hurricane/hurricane/IntrusiveMap.h | 16 + .../src/hurricane/hurricane/IntrusiveSet.h | 5 + .../src/hurricane/hurricane/JsonReader.h | 439 +++++++ .../src/hurricane/hurricane/JsonWriter.h | 207 +++ hurricane/src/hurricane/hurricane/Layer.h | 1 + hurricane/src/hurricane/hurricane/Library.h | 12 + hurricane/src/hurricane/hurricane/Name.h | 6 + hurricane/src/hurricane/hurricane/Net.h | 23 +- hurricane/src/hurricane/hurricane/NetAlias.h | 3 + .../src/hurricane/hurricane/Occurrence.h | 17 +- hurricane/src/hurricane/hurricane/Pad.h | 11 + hurricane/src/hurricane/hurricane/Path.h | 1 + hurricane/src/hurricane/hurricane/Plug.h | 20 + hurricane/src/hurricane/hurricane/Point.h | 12 +- .../src/hurricane/hurricane/RoutingPad.h | 22 +- hurricane/src/hurricane/hurricane/Segment.h | 19 +- .../src/hurricane/hurricane/SharedPath.h | 1 + hurricane/src/hurricane/hurricane/Signature.h | 149 +++ .../src/hurricane/hurricane/Tabulation.h | 2 +- .../src/hurricane/hurricane/Transformation.h | 12 +- hurricane/src/hurricane/hurricane/Vertical.h | 11 + hurricane/src/isobar/CMakeLists.txt | 1 + hurricane/src/viewer/CMakeLists.txt | 2 + hurricane/src/viewer/CellPrinter.cpp | 4 +- hurricane/src/viewer/CellViewer.cpp | 50 + hurricane/src/viewer/CellWidget.cpp | 2 +- hurricane/src/viewer/OpenBlobDialog.cpp | 97 ++ .../src/viewer/hurricane/viewer/CellViewer.h | 2 + .../viewer/hurricane/viewer/OpenBlobDialog.h | 42 + unicorn/src/ExportCellDialog.cpp | 1 + unicorn/src/UnicornGui.cpp | 16 +- unicorn/src/unicorn/ExportCellDialog.h | 2 +- 87 files changed, 7620 insertions(+), 217 deletions(-) create mode 100644 hurricane/src/hurricane/DesignBlob.cpp create mode 100644 hurricane/src/hurricane/JsonReader.cpp create mode 100644 hurricane/src/hurricane/JsonWriter.cpp create mode 100644 hurricane/src/hurricane/Signature.cpp create mode 100644 hurricane/src/hurricane/grenier/json/DBo.cpp create mode 100644 hurricane/src/hurricane/grenier/json/DBo.h create mode 100644 hurricane/src/hurricane/grenier/json/JsonReader.cpp create mode 100644 hurricane/src/hurricane/grenier/json/JsonReader.h create mode 100644 hurricane/src/hurricane/grenier/json/Net.cpp create mode 100644 hurricane/src/hurricane/grenier/json/Net.h create mode 100644 hurricane/src/hurricane/hurricane/DesignBlob.h create mode 100644 hurricane/src/hurricane/hurricane/JsonReader.h create mode 100644 hurricane/src/hurricane/hurricane/JsonWriter.h create mode 100644 hurricane/src/hurricane/hurricane/Signature.h create mode 100644 hurricane/src/viewer/OpenBlobDialog.cpp create mode 100644 hurricane/src/viewer/hurricane/viewer/OpenBlobDialog.h diff --git a/crlcore/src/ccore/AllianceFramework.cpp b/crlcore/src/ccore/AllianceFramework.cpp index 847517f6..01b83216 100644 --- a/crlcore/src/ccore/AllianceFramework.cpp +++ b/crlcore/src/ccore/AllianceFramework.cpp @@ -13,32 +13,28 @@ // | C++ Module : "./AllianceFramework.cpp" | // +-----------------------------------------------------------------+ - -#include -#include "vlsisapd/utilities/Path.h" -#include "hurricane/Warning.h" -#include "hurricane/Technology.h" -#include "hurricane/DataBase.h" -#include "hurricane/Library.h" -#include "hurricane/Cell.h" -#include "hurricane/Instance.h" -#include "hurricane/viewer/Graphics.h" -#include "crlcore/Utilities.h" -#include "crlcore/GraphicsParser.h" -#include "crlcore/SymbolicTechnologyParser.h" -#include "crlcore/RealTechnologyParser.h" -#include "crlcore/CellGauge.h" -#include "crlcore/RoutingGauge.h" -#include "crlcore/RoutingLayerGauge.h" -#include "crlcore/AllianceFramework.h" - - - +#include +#include "vlsisapd/utilities/Path.h" +#include "hurricane/Warning.h" +#include "hurricane/Technology.h" +#include "hurricane/DataBase.h" +#include "hurricane/Library.h" +#include "hurricane/Cell.h" +#include "hurricane/Instance.h" +#include "hurricane/viewer/Graphics.h" +#include "crlcore/Utilities.h" +#include "crlcore/GraphicsParser.h" +#include "crlcore/SymbolicTechnologyParser.h" +#include "crlcore/RealTechnologyParser.h" +#include "crlcore/CellGauge.h" +#include "crlcore/RoutingGauge.h" +#include "crlcore/RoutingLayerGauge.h" +#include "crlcore/AllianceFramework.h" namespace CRL { - + using namespace std::placeholders; using Hurricane::Warning; using Hurricane::tab; using Hurricane::Graphics; @@ -133,6 +129,7 @@ namespace CRL { db = DataBase::create (); db->put ( AllianceFrameworkProperty::create(this) ); + db->_setCellLoader( bind(&AllianceFramework::cellLoader,this,_1) ); //cmess1 << " o Reading Alliance Environment." << endl; @@ -262,6 +259,15 @@ namespace CRL { } + Cell* AllianceFramework::cellLoader ( const string& rpath ) + { + size_t dot = rpath.rfind('.'); + string cellName = rpath.substr(dot+1); + + return getCell( cellName, Catalog::State::Views ); + } + + Cell* AllianceFramework::getCell ( const string& name, unsigned int mode, unsigned int depth ) { bool createCell = false; diff --git a/crlcore/src/ccore/crlcore/AllianceFramework.h b/crlcore/src/ccore/crlcore/AllianceFramework.h index 53acb7fa..e41b43f1 100644 --- a/crlcore/src/ccore/crlcore/AllianceFramework.h +++ b/crlcore/src/ccore/crlcore/AllianceFramework.h @@ -85,6 +85,7 @@ namespace CRL { void addRoutingGauge ( RoutingGauge* ); void addCellGauge ( CellGauge* ); // Cell Management. + Cell* cellLoader ( const string& rpath ); Cell* getCell ( const string& name , unsigned int mode , unsigned int depth=(unsigned int)-1 ); diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index a76f207d..d59eacbb 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -453,10 +453,6 @@ namespace Etesian { if (not cmess2.enabled()) dots.disable(); - cmess1 << " - Building RoutingPads (transhierarchical) ..." << endl; - //getCell()->flattenNets( Cell::Flags::BuildRings|Cell::Flags::NoClockFlatten ); - getCell()->flattenNets( Cell::Flags::NoClockFlatten ); - // Coloquinte circuit description data-structures. size_t instancesNb = getCell()->getLeafInstanceOccurrences().getSize(); vector idsToTransf ( instancesNb ); @@ -487,6 +483,10 @@ namespace Etesian { } UpdateSession::close(); + cmess1 << " - Building RoutingPads (transhierarchical) ..." << endl; + //getCell()->flattenNets( Cell::Flags::BuildRings|Cell::Flags::NoClockFlatten ); + getCell()->flattenNets( Cell::Flags::NoClockFlatten ); + index_t instanceId = 0; for ( Occurrence occurrence : getCell()->getLeafInstanceOccurrences() ) { @@ -925,6 +925,14 @@ namespace Etesian { _placed = true; + UpdateSession::open(); + for ( Net* net : getCell()->getNets() ) { + for ( RoutingPad* rp : net->getComponents().getSubSet() ) { + rp->invalidate(); + } + } + UpdateSession::close(); + getCell()->setFlags( Cell::Flags::Placed ); } @@ -999,7 +1007,7 @@ namespace Etesian { ); //cerr << "Setting <" << instanceName << " @" << instancePosition << endl; - // This is temporary as it's not trans-hierarchic: we ignore the posutions + // This is temporary as it's not trans-hierarchic: we ignore the positions // of all the intermediary instances. instance->setTransformation( trans ); instance->setPlacementStatus( Instance::PlacementStatus::PLACED ); diff --git a/hurricane/src/hurricane/Box.cpp b/hurricane/src/hurricane/Box.cpp index 5cb0e291..bad9ce79 100644 --- a/hurricane/src/hurricane/Box.cpp +++ b/hurricane/src/hurricane/Box.cpp @@ -318,7 +318,7 @@ Box& Box::merge(const Box& box) } Box& Box::translate(const DbU::Unit& dx, const DbU::Unit& dy) -// ************************************************ +// ********************************************************** { if (!isEmpty()) { _xMin += dx; @@ -353,6 +353,58 @@ Record* Box::_getRecord() const return record; } +void Box::toJson(JsonWriter* w) const +// *********************************** +{ + w->startObject(); + jsonWrite( w, "@typename", "Box" ); + jsonWrite( w, "_xMin", getXMin() ); + jsonWrite( w, "_yMin", getYMin() ); + jsonWrite( w, "_xMax", getXMax() ); + jsonWrite( w, "_yMax", getYMax() ); + w->endObject(); +} + +JsonBox::JsonBox(unsigned long flags) +// ********************************** + : JsonObject(flags) +{ + add( "_xMin", typeid(int64_t) ); + add( "_yMin", typeid(int64_t) ); + add( "_xMax", typeid(int64_t) ); + add( "_yMax", typeid(int64_t) ); +} + +string JsonBox::getTypeName() const +// ********************************* +{ return "Box"; } + +JsonBox* JsonBox::clone(unsigned long flags) const +// *********************************************** +{ return new JsonBox ( flags ); } + +void JsonBox::toData(JsonStack& stack) +// *********************************** +{ + check( stack, "JsonBox::toData" ); + + DbU::Unit xMin = DbU::fromDb(get(stack,"_xMin")); + DbU::Unit yMin = DbU::fromDb(get(stack,"_yMin")); + DbU::Unit xMax = DbU::fromDb(get(stack,"_xMax")); + DbU::Unit yMax = DbU::fromDb(get(stack,"_yMax")); + + Box box; + + if ( (xMin <= xMax) and (yMin <= yMax) ) + box.merge( xMin, yMin, xMax, yMax ); + + ltrace(51) << "Box(" << xMin << ", " + << yMin << ", " + << xMax << ", " + << yMax << ")" << endl; + + update( stack, box ); +} } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/CMakeLists.txt b/hurricane/src/hurricane/CMakeLists.txt index abb9a7c2..55b6b7bc 100644 --- a/hurricane/src/hurricane/CMakeLists.txt +++ b/hurricane/src/hurricane/CMakeLists.txt @@ -1,11 +1,15 @@ include_directories ( ${HURRICANE_SOURCE_DIR}/src/hurricane + ${CONFIGURATION_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ) set ( includes hurricane/Mask.h hurricane/Flags.h hurricane/DebugSession.h hurricane/Backtrace.h + hurricane/JsonWriter.h + hurricane/JsonReader.h + hurricane/Signature.h hurricane/Observer.h hurricane/BasicLayer.h hurricane/BasicLayers.h hurricane/RegularLayer.h hurricane/RegularLayers.h @@ -90,12 +94,16 @@ hurricane/Views.h hurricane/Warning.h hurricane/TextTranslator.h + hurricane/DesignBlob.h ) set ( cpps Record.cpp Slot.cpp Commons.cpp Flags.cpp Backtrace.cpp + JsonWriter.cpp + JsonReader.cpp + Signature.cpp Exception.cpp Bug.cpp Error.cpp @@ -164,6 +172,7 @@ Marker.cpp Timer.cpp TextTranslator.cpp + DesignBlob.cpp ) add_library ( hurricane ${cpps} ) diff --git a/hurricane/src/hurricane/Cell.cpp b/hurricane/src/hurricane/Cell.cpp index 81bb29b4..dbabfe17 100644 --- a/hurricane/src/hurricane/Cell.cpp +++ b/hurricane/src/hurricane/Cell.cpp @@ -28,6 +28,10 @@ #include "hurricane/Net.h" #include "hurricane/Pin.h" #include "hurricane/RoutingPad.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "hurricane/Contact.h" +#include "hurricane/Pad.h" #include "hurricane/Layer.h" #include "hurricane/Slice.h" #include "hurricane/Rubber.h" @@ -254,6 +258,91 @@ bool Cell::isUniquifyMaster() const return (not relation) or (relation->getMasterOwner() == this); } +string Cell::getHierarchicalName () const +// ************************************** +{ + return getLibrary()->getHierarchicalName() + "." + getString(getName()); +} + +Entity* Cell::getEntity(const Signature& signature) const +// ****************************************************** +{ + if ( (signature.getType() == Signature::TypeContact ) + or (signature.getType() == Signature::TypeHorizontal) + or (signature.getType() == Signature::TypeVertical ) + or (signature.getType() == Signature::TypePad ) ) { + Net* net = getNet( signature.getName() ); + if (not net) { + cerr << Error( "Cell::getEntity(): Cell %s do have Net %s, signature incoherency." + , getString(getName()).c_str() + , signature.getName().c_str() ) << endl; + return NULL; + } + + ltrace(51) << "Cell::getEntity(): <" << getName() << ">, Net:<" << net->getName() << ">" << endl; + + if (signature.getType() == Signature::TypeContact) { + ltrace(51) << "Looking in Contacts..." << endl; + for ( Contact* component : getComponents().getSubSet() ) { + ltrace(51) << "| " << component << endl; + if ( (component->getLayer () == signature.getLayer()) + and (component->getDx () == signature.getDim(Signature::ContactDx)) + and (component->getDy () == signature.getDim(Signature::ContactDy)) + and (component->getWidth () == signature.getDim(Signature::ContactWidth)) + and (component->getHeight() == signature.getDim(Signature::ContactHeight)) ) + return component; + } + } + + if (signature.getType() == Signature::TypeVertical) { + ltrace(51) << "Looking in Verticals..." << endl; + for ( Vertical* component : getComponents().getSubSet() ) { + ltrace(51) << "| " << component << endl; + if ( (component->getLayer () == signature.getLayer()) + and (component->getWidth () == signature.getDim(Signature::VerticalWidth)) + and (component->getX () == signature.getDim(Signature::VerticalX)) + and (component->getDySource() == signature.getDim(Signature::VerticalDySource)) + and (component->getDyTarget() == signature.getDim(Signature::VerticalDyTarget)) ) + return component; + } + } + + if (signature.getType() == Signature::TypeHorizontal) { + ltrace(51) << "Looking in Horizontals..." << endl; + for ( Horizontal* component : getComponents().getSubSet() ) { + ltrace(51) << "| " << component << endl; + if ( (component->getLayer () == signature.getLayer()) + and (component->getWidth () == signature.getDim(Signature::HorizontalWidth)) + and (component->getY () == signature.getDim(Signature::HorizontalY)) + and (component->getDxSource() == signature.getDim(Signature::HorizontalDxSource)) + and (component->getDxTarget() == signature.getDim(Signature::HorizontalDxTarget)) ) + return component; + } + } + + if (signature.getType() == Signature::TypePad) { + ltrace(51) << "Looking in Pads..." << endl; + for ( Pad* component : getComponents().getSubSet() ) { + ltrace(51) << "| " << component << endl; + if ( (component->getLayer() == signature.getLayer()) + and (component->getBoundingBox().getXMin() == signature.getDim(Signature::PadXMin)) + and (component->getBoundingBox().getYMin() == signature.getDim(Signature::PadYMin)) + and (component->getBoundingBox().getXMax() == signature.getDim(Signature::PadXMax)) + and (component->getBoundingBox().getYMax() == signature.getDim(Signature::PadYMax)) ) + return component; + } + } + + cerr << Error( "Cell::getEntity(): Cannot find a Component of type %d matching Signature." + , signature.getType() ) << endl; + } else { + cerr << Error( "Cell::getEntity(): Signature type %d is unsupported yet." + , signature.getType() ) << endl; + } + + return NULL; +} + Net* Cell::getNet ( const Name& name ) const //****************************************** { @@ -793,6 +882,23 @@ void Cell::notify(unsigned flags) _observers.notify(flags); } +void Cell::_toJson(JsonWriter* writer) const +// ***************************************** +{ + Inherit::_toJson( writer ); + + jsonWrite( writer, "_library" , getLibrary()->getHierarchicalName() ); + jsonWrite( writer, "_name" , getName() ); + jsonWrite( writer, "_abutmentBox", &_abutmentBox ); +} + +void Cell::_toJsonCollections(JsonWriter* writer) const +// ***************************************** +{ + jsonWrite( writer, "+instanceMap", getInstances() ); + jsonWrite( writer, "+netMap" , getNets() ); + Inherit::_toJsonCollections( writer ); +} // **************************************************************************************************** // Cell::Flags implementation @@ -1105,6 +1211,45 @@ void Cell::MarkerSet::_setNextElement(Marker* marker, Marker* nextMarker) const marker->_setNextOfCellMarkerSet(nextMarker); } + + +// **************************************************************************************************** +// JsonCell implementation +// **************************************************************************************************** + +JsonCell::JsonCell(unsigned long flags) +// ************************************ + : JsonEntity(flags) +{ + remove( ".Cell" ); + add( "_library" , typeid(string) ); + add( "_name" , typeid(string) ); + add( "_abutmentBox" , typeid(Box) ); + add( "+instanceMap" , typeid(JsonArray) ); + add( "+netMap" , typeid(JsonArray) ); +} + +string JsonCell::getTypeName() const +// ********************************* +{ return "Cell"; } + +JsonCell* JsonCell::clone(unsigned long flags) const +// ************************************************* +{ return new JsonCell ( flags ); } + +void JsonCell::toData(JsonStack& stack) +// ************************************ +{ + check( stack, "JsonCell::toData" ); + presetId( stack ); + + Cell* cell = Cell::create( DataBase::getDB()->getLibrary( get(stack,"_library") ) + , get(stack,"_name") ); + cell->setAbutmentBox( stack.as("_abutmentBox") ); + + update( stack, cell ); +} + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Component.cpp b/hurricane/src/hurricane/Component.cpp index 70f7463a..4405a6df 100644 --- a/hurricane/src/hurricane/Component.cpp +++ b/hurricane/src/hurricane/Component.cpp @@ -378,6 +378,25 @@ void Component::invalidate(bool propagateFlag) } } + +void Component::forceId(unsigned int id) +// ************************************* +{ + if (not inForcedIdMode()) + throw Error( "Component::forceId(): DataBase *must* be in forced id mode to call this method." ); + + if (getId() == id) return; + + bool materialized = isMaterialized(); + if (materialized) unmaterialize(); + if (_net) _net->_getComponentSet()._remove(this); + + setId( id ); + + if (_net) _net->_getComponentSet()._insert(this); + if (materialized) materialize(); +} + void Component::_postCreate() // ************************** { @@ -454,6 +473,20 @@ void Component::_preDestroy() // trace_out(); } +void Component::_toJson( JsonWriter* writer ) const +// ************************************************ +{ + Inherit::_toJson( writer ); + jsonWrite( writer, "_bodyHook", _bodyHook.getNextHook()->toJson() ); +} + +void Component::_toJsonSignature( JsonWriter* writer ) const +// ********************************************************* +{ + jsonWrite( writer, "_net" , getNet()->getName() ); + _toJson( writer ); +} + string Component::_getString() const // ********************************* { @@ -523,10 +556,12 @@ Component::BodyHook::BodyHook(Component* component) : Inherit() { if (!component) - throw Error("Can't create " + _TName("Component::BodyHook") + " : null component"); + throw Error("Can't create " + _getTypeName() + " : null component"); - if (BODY_HOOK_OFFSET == -1) + if (BODY_HOOK_OFFSET == -1) { BODY_HOOK_OFFSET = (unsigned long)this - (unsigned long)component; + Hook::addCompToHook(_getTypeName(),_compToHook); + } } Component* Component::BodyHook::getComponent() const @@ -541,6 +576,11 @@ string Component::BodyHook::_getString() const return "<" + _TName("Component::BodyHook") + " " + getString(getComponent()) + ">"; } +Hook* Component::BodyHook::_compToHook(Component* component) +// ************************************************************* +{ return &(component->_bodyHook); } + + // **************************************************************************************************** // Component_Hooks implementation // **************************************************************************************************** @@ -941,6 +981,16 @@ double getArea ( Component* component ) } +// **************************************************************************************************** +// JsonComponent implementation +// **************************************************************************************************** + +JsonComponent::JsonComponent(unsigned long flags) +// ********************************************** + : JsonEntity(flags) +{ + add( "_bodyHook", typeid(string) ); +} } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Contact.cpp b/hurricane/src/hurricane/Contact.cpp index ddbaa333..4ec194a5 100644 --- a/hurricane/src/hurricane/Contact.cpp +++ b/hurricane/src/hurricane/Contact.cpp @@ -17,6 +17,8 @@ // not, see . // **************************************************************************************************** +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" #include "hurricane/Contact.h" #include "hurricane/Net.h" #include "hurricane/Layer.h" @@ -334,6 +336,19 @@ void Contact::_preDestroy() // trace_out(); } +void Contact::_toJson(JsonWriter* writer) const +// ******************************************** +{ + Inherit::_toJson( writer ); + + jsonWrite( writer, "_anchorHook", _anchorHook.getNextHook()->toJson() ); + jsonWrite( writer, "_layer" , _layer->getName() ); + jsonWrite( writer, "_dx" , _dx ); + jsonWrite( writer, "_dy" , _dy ); + jsonWrite( writer, "_width" , _width ); + jsonWrite( writer, "_height" , _height ); +} + string Contact::_getString() const // ******************************* { @@ -373,10 +388,12 @@ Contact::AnchorHook::AnchorHook(Contact* contact) : Inherit() { if (!contact) - throw Error("Can't create " + _TName("Contact::AnchorHook") + " : null contact"); + throw Error("Can't create " + _getTypeName() + " : null contact"); - if (ANCHOR_HOOK_OFFSET == -1) - ANCHOR_HOOK_OFFSET = (unsigned long)this - (unsigned long)contact; + if (ANCHOR_HOOK_OFFSET == -1) { + ANCHOR_HOOK_OFFSET = (unsigned long)this - (unsigned long)contact; + Hook::addCompToHook(_getTypeName(),_compToHook); + } } Component* Contact::AnchorHook::getComponent() const @@ -391,6 +408,16 @@ string Contact::AnchorHook::_getString() const return "<" + _TName("Contact::AnchorHook") + " " + getString(getComponent()) + ">"; } +Hook* Contact::AnchorHook::_compToHook(Component* component) +// *************************************************************** +{ + Contact* contact = dynamic_cast(component); + if (not contact) { + throw Error( "AnchorHook::_compToAnchorhook(): Unable to cast %s into Contact*." + , getString(component).c_str() ); + } + return &(contact->_anchorHook); +} // **************************************************************************************************** @@ -508,6 +535,54 @@ string Contact_Hooks::Locator::_getString() const return s; } + + +// **************************************************************************************************** +// JsonContact implementation +// **************************************************************************************************** + +JsonContact::JsonContact(unsigned long flags) +// ****************************************** + : JsonComponent(flags) +{ + add( "_anchorHook", typeid(string) ); + add( "_layer" , typeid(string) ); + add( "_dx" , typeid(int64_t) ); + add( "_dy" , typeid(int64_t) ); + add( "_width" , typeid(int64_t) ); + add( "_height" , typeid(int64_t) ); +} + +string JsonContact::getTypeName() const +// ************************************ +{ return "Contact"; } + +JsonContact* JsonContact::clone(unsigned long flags) const +// ******************************************************* +{ return new JsonContact ( flags ); } + +void JsonContact::toData(JsonStack& stack) +// *************************************** +{ + check( stack, "JsonContact::toData" ); + unsigned int jsonId = presetId( stack ); + + Contact* contact = Contact::create + ( get(stack,".Net") + , DataBase::getDB()->getTechnology()->getLayer( get(stack,"_layer") ) + , DbU::fromDb( get(stack,"_dx" ) ) + , DbU::fromDb( get(stack,"_dy" ) ) + , DbU::fromDb( get(stack,"_width" ) ) + , DbU::fromDb( get(stack,"_height") ) + ); + + stack.addHookLink( contact->getBodyHook (), jsonId, get(stack,"_bodyHook" ) ); + stack.addHookLink( contact->getAnchorHook(), jsonId, get(stack,"_anchorHook") ); + +// Hook/Ring rebuild are done as a post-process. + update( stack, contact ); +} + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/DBo.cpp b/hurricane/src/hurricane/DBo.cpp index 53431460..300434eb 100644 --- a/hurricane/src/hurricane/DBo.cpp +++ b/hurricane/src/hurricane/DBo.cpp @@ -18,8 +18,6 @@ // License along with Hurricane. If not, see // . // -// =================================================================== -// // +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | @@ -65,7 +63,6 @@ namespace Hurricane { void DBo::destroy () { _preDestroy(); - delete this; } @@ -151,6 +148,22 @@ namespace Hurricane { } + void DBo::_toJson ( JsonWriter* writer ) const + { } + + + void DBo::_toJsonSignature ( JsonWriter* writer ) const + { _toJson( writer ); } + + + void DBo::_toJsonCollections ( JsonWriter* writer ) const + { + writer->key( "+propertySet" ); + writer->startArray(); + writer->endArray(); + } + + string DBo::_getTypeName () const { return "DBo"; @@ -171,4 +184,36 @@ namespace Hurricane { } + void DBo::toJsonSignature ( JsonWriter* w ) const + { + w->startObject(); + std::string tname = "Signature." + _getTypeName(); + jsonWrite( w, "@typename", tname ); + _toJsonSignature( w ); + w->endObject(); + } + + + void DBo::toJson ( JsonWriter* w ) const + { + w->startObject(); + std::string tname = _getTypeName(); + if (w->issetFlags(JsonWriter::UsePlugReference) and (tname == "Plug")) { + tname.insert( 0, "&" ); + } + jsonWrite( w, "@typename", tname ); + _toJson( w ); + _toJsonCollections( w ); + w->endObject(); + } + + +// ------------------------------------------------------------------- +// Class : "Hurricane::JsonDBo". + + JsonDBo::JsonDBo ( unsigned int flags ) + : JsonObject(flags) + { } + + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/DataBase.cpp b/hurricane/src/hurricane/DataBase.cpp index a8971688..d3b8b2d9 100644 --- a/hurricane/src/hurricane/DataBase.cpp +++ b/hurricane/src/hurricane/DataBase.cpp @@ -18,6 +18,7 @@ // **************************************************************************************************** #include "hurricane/DataBase.h" +#include "hurricane/SharedPath.h" #include "hurricane/Technology.h" #include "hurricane/Library.h" #include "hurricane/Error.h" @@ -81,7 +82,7 @@ string DataBase::_getString() const } Record* DataBase::_getRecord() const -// *************************** +// ********************************* { Record* record = Inherit::_getRecord(); if (record) { @@ -100,7 +101,55 @@ DataBase* DataBase::getDB() return _db; } +Library* DataBase::getLibrary(string rpath) const +// ********************************************** +{ + Library* current = getRootLibrary(); + if (not current) return NULL; + char separator = SharedPath::getNameSeparator(); + Name childName; + size_t dot = rpath.find( separator ); + if (dot != string::npos) { + childName = rpath.substr( 0, dot ); + rpath = rpath.substr( dot+1 ); + } else + childName = rpath; + + if (childName != current->getName()) + return NULL; + + while ( dot != string::npos ) { + dot = rpath.find( separator ); + if (dot != string::npos) { + childName = rpath.substr( 0, dot ); + rpath = rpath.substr( dot+1 ); + } else + childName = rpath; + + current = current->getLibrary( childName ); + } + return current; +} + +Cell* DataBase::getCell(string rpath) const +// **************************************** +{ + + char separator = SharedPath::getNameSeparator(); + size_t dot = rpath.rfind( separator ); + string cellName = rpath.substr(dot+1); + Library* library = getLibrary( rpath.substr(0,dot) ); + Cell* cell = NULL; + + if (library) + cell = library->getCell( rpath.substr(dot+1) ); + + if (not cell and _cellLoader) return _cellLoader( rpath ); + + return cell; + +} } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/DeepNet.cpp b/hurricane/src/hurricane/DeepNet.cpp index 00794bd0..21854632 100644 --- a/hurricane/src/hurricane/DeepNet.cpp +++ b/hurricane/src/hurricane/DeepNet.cpp @@ -49,7 +49,6 @@ namespace Hurricane { // ------------------------------------------------------------------- // Class : "DeepNet". - DeepNet::DeepNet ( Occurrence& netOccurrence ) : Net(netOccurrence.getOwnerCell() ,netOccurrence.getName() @@ -122,4 +121,61 @@ namespace Hurricane { } + void DeepNet::_toJson( JsonWriter* writer ) const + { + Inherit::_toJson( writer ); + + jsonWrite( writer, "_netOccurrence", &_netOccurrence ); + } + + +// ------------------------------------------------------------------- +// Class : "JsonDeepNet". + + JsonDeepNet::JsonDeepNet ( unsigned long flags ) + : JsonNet(flags) + { + ltrace(51) << "JsonDeepNet::JsonDeepNet()" << endl; + + add( "_netOccurrence", typeid(Occurrence) ); + } + + + JsonDeepNet::~JsonDeepNet () + { } + + + string JsonDeepNet::getTypeName () const + { return "DeepNet"; } + + + JsonDeepNet* JsonDeepNet::clone ( unsigned long flags ) const + { return new JsonDeepNet ( flags ); } + + + void JsonDeepNet::toData(JsonStack& stack) + { + ltracein(51); + + _stack = &stack; + + check( stack, "JsonDeepNet::toData" ); + presetId( stack ); + + HyperNet hyperNet ( get(stack,"_netOccurrence") ); + + _net = DeepNet::create( hyperNet ); + _net->setGlobal ( get(stack,"_isGlobal" ) ); + _net->setExternal ( get(stack,"_isExternal" ) ); + _net->setAutomatic( get(stack,"_isAutomatic") ); + _net->setType ( Net::Type (get(stack,"_type")) ); + _net->setDirection( Net::Direction(get(stack,"_direction")) ); + + setName( ".Net" ); + update( stack, _net ); + + ltraceout(51); + } + + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/DesignBlob.cpp b/hurricane/src/hurricane/DesignBlob.cpp new file mode 100644 index 00000000..2db3868b --- /dev/null +++ b/hurricane/src/hurricane/DesignBlob.cpp @@ -0,0 +1,74 @@ +// -*- mode: C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./DesignBlob.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include "hurricane/DesignBlob.h" +#include "hurricane/DataBase.h" +#include "hurricane/Library.h" +#include "hurricane/DesignBlob.h" + + +namespace Hurricane { + + using std::cerr; + using std::endl; + + +// ------------------------------------------------------------------- +// Class : "DesignBlob". + + void DesignBlob::toJson( JsonWriter* w ) const + { + w->startObject(); + jsonWrite( w, "@typename", _getTypeName() ); + jsonWrite( w, "_topCell" , getTopCell()->getHierarchicalName() ); + jsonWrite( w, "_library" , DataBase::getDB()->getRootLibrary() ); + w->endObject(); + } + + +// ------------------------------------------------------------------- +// Class : "JsonDesignBlob". + + JsonDesignBlob::JsonDesignBlob ( unsigned long flags ) + : JsonObject(flags) + { + ltrace(51) << "JsonDesignblob::JsonDesignblob()" << endl; + + add( "_library", typeid(Library*) ); + add( "_topCell", typeid(string) ); + } + + + string JsonDesignBlob::getTypeName () const + { return "DesignBlob"; } + + + JsonDesignBlob* JsonDesignBlob::clone ( unsigned long flags ) const + { return new JsonDesignBlob ( flags ); } + + + void JsonDesignBlob::toData ( JsonStack& stack ) + { + check( stack, "JsonDesignBlob::toData" ); + + DesignBlob* designBlob = new DesignBlob ( DataBase::getDB()->getCell(get(stack,"_topCell")) ); + + update( stack, designBlob ); + } + + +} // Hurricane namespace. diff --git a/hurricane/src/hurricane/Entity.cpp b/hurricane/src/hurricane/Entity.cpp index 34e74d95..8a455e71 100644 --- a/hurricane/src/hurricane/Entity.cpp +++ b/hurricane/src/hurricane/Entity.cpp @@ -28,22 +28,73 @@ namespace Hurricane { - // **************************************************************************************************** // Entity implementation // **************************************************************************************************** - unsigned int Entity::_idCounter = 0; + unsigned long Entity::_flags = 0; + unsigned int Entity::_nextId = 0; + unsigned int Entity::_idCounter = 1; unsigned int Entity::getIdCounter () { return _idCounter; } + bool Entity::inForcedIdMode () + { return _flags & ForcedIdMode; } + + + void Entity::enableForcedIdMode () + { + if (_flags & ForcedIdMode) return; + if (_idCounter != 1) { + throw Error( "Entity::enableForcedIdMode(): DataBase must be reset before forcind ids." ); + } + _flags |= ForcedIdMode; + } + + + void Entity::disableForcedIdMode () + { + if (not (_flags & ForcedIdMode)) return; + _flags &= ~ForcedIdMode; + } + + + void Entity::setNextId ( unsigned int nid ) + { + if (not (_flags & ForcedIdMode)) { + cerr << Error("Entity::setNextId(): Not in forced id mode, ignored.") << endl; + return; + } + _nextId = nid; + if (nid > _idCounter) _idCounter = nid; + _flags |= NextIdSet; + } + + + unsigned int Entity::getNextId () + { + if (_flags & ForcedIdMode) { + if (_flags & NextIdSet) { + _flags &= ~NextIdSet; + ltrace(51) << demangle(typeid(*this).name()) + << "::getNextId(): Consuming the preset id:" << _nextId << endl; + return _nextId; + } else { + throw Error("Entity::getNextId(): Next id is not set, while in forced id mode."); + } + } + + return _idCounter++; + } + + Entity::Entity() : Inherit() - , _id(_idCounter++) + , _id (getNextId()) { if (_idCounter == std::numeric_limits::max()) { throw Error( "Entity::Entity(): Identifier counter has reached it's limit (%d bits)." @@ -96,28 +147,53 @@ namespace Hurricane { //ltraceout(10); } -string Entity::_getString() const -// ****************************** -{ - string s = Inherit::_getString(); - s.insert(1, "id:"+getString(_id)+" "); - return s; -} -Record* Entity::_getRecord() const -// ************************* -{ + void Entity::setId ( unsigned int id ) + { + if (_flags & ForcedIdMode) { + _id = id; + if (_id > _idCounter) _idCounter = _id; + } else { + throw Error("Entity::setId(): Attempt to set id while not in forced id mode."); + } + } + + + void Entity::_toJson ( JsonWriter* writer ) const + { + Inherit::_toJson( writer ); + + jsonWrite( writer, "_id", getId() ); + } + + + string Entity::_getString() const + { + string s = Inherit::_getString(); + s.insert( 1, "id:"+getString(_id)+" " ); + return s; + } + + + Record* Entity::_getRecord() const + { Record* record = Inherit::_getRecord(); if (record) { - record->add(getSlot("_id", _id)); - Occurrence occurrence = Occurrence(this); - if (occurrence.hasProperty()) - record->add(getSlot("Occurrence", occurrence)); + record->add( getSlot("_id", _id) ); + Occurrence occurrence = Occurrence(this); + if (occurrence.hasProperty()) + record->add( getSlot("Occurrence", occurrence) ); } return record; -} + } + JsonEntity::JsonEntity (unsigned long flags) + : JsonDBo(flags) + { + add( "_id", typeid(uint64_t) ); + } + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Hook.cpp b/hurricane/src/hurricane/Hook.cpp index aab27b2e..b20c0742 100644 --- a/hurricane/src/hurricane/Hook.cpp +++ b/hurricane/src/hurricane/Hook.cpp @@ -187,6 +187,9 @@ class Hook_SlaveHooks : public Collection { // Hook implementation // **************************************************************************************************** +map Hook::_compToHookMap; + + Hook::Hook() // ********* : _nextHook(this) @@ -385,7 +388,30 @@ Record* Hook::_getRecord() const return record; } +string Hook::toJson() const +// ************************ +{ + if (_nextHook == this) return ""; + string s = _getTypeName()+"."+getString(getComponent()->getId()); + return s; +} +void Hook::addCompToHook(const string& tname, Hook::compToHook_t converter) +// ************************************************************************ +{ + _compToHookMap.insert( make_pair(tname,converter) ); +} + +Hook* Hook::compToHook(const string& tname, Component* component) +// ************************************************************** +{ + map::const_iterator iconv = _compToHookMap.find(tname); + if (iconv == _compToHookMap.end()) { + throw Error( "Hook::fromJson(): No converter registered for type name \"%s\"" + , tname.c_str() ); + } + return (*iconv).second(component); +} // **************************************************************************************************** // Hook_Hooks implementation diff --git a/hurricane/src/hurricane/Horizontal.cpp b/hurricane/src/hurricane/Horizontal.cpp index 0d013308..67d478df 100644 --- a/hurricane/src/hurricane/Horizontal.cpp +++ b/hurricane/src/hurricane/Horizontal.cpp @@ -17,6 +17,8 @@ // not, see . // **************************************************************************************************** +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" #include "hurricane/Horizontal.h" #include "hurricane/Layer.h" #include "hurricane/BasicLayer.h" @@ -173,6 +175,16 @@ void Horizontal::translate(const DbU::Unit& dy) } } +void Horizontal::_toJson(JsonWriter* writer) const +// *********************************************** +{ + Inherit::_toJson( writer ); + + jsonWrite( writer, "_y" , _y ); + jsonWrite( writer, "_dxSource", _dxSource ); + jsonWrite( writer, "_dxTarget", _dxTarget ); +} + string Horizontal::_getString() const // ********************************** { @@ -191,6 +203,51 @@ Record* Horizontal::_getRecord() const return record; } + +// **************************************************************************************************** +// JsonHorizontal implementation +// **************************************************************************************************** + +JsonHorizontal::JsonHorizontal(unsigned long flags) +// ************************************************ + : JsonSegment(flags) +{ + add( "_y" , typeid(uint64_t) ); + add( "_dxSource", typeid(uint64_t) ); + add( "_dxTarget", typeid(uint64_t) ); +} + +string JsonHorizontal::getTypeName() const +// *************************************** +{ return "Horizontal"; } + +JsonHorizontal* JsonHorizontal::clone(unsigned long flags) const +// ************************************************************* +{ return new JsonHorizontal ( flags ); } + +void JsonHorizontal::toData(JsonStack& stack) +// ****************************************** +{ + check( stack, "JsonHorizontal::toData" ); + unsigned int jsonId = presetId( stack ); + + Horizontal* horizontal = Horizontal::create + ( get(stack,".Net") + , DataBase::getDB()->getTechnology()->getLayer( get(stack,"_layer") ) + , DbU::fromDb( get(stack,"_y" ) ) + , DbU::fromDb( get(stack,"_width" ) ) + , DbU::fromDb( get(stack,"_dxSource") ) + , DbU::fromDb( get(stack,"_dxTarget") ) + ); + + stack.addHookLink( horizontal->getBodyHook (), jsonId, get(stack,"_bodyHook" ) ); + stack.addHookLink( horizontal->getSourceHook(), jsonId, get(stack,"_sourceHook") ); + stack.addHookLink( horizontal->getTargetHook(), jsonId, get(stack,"_targetHook") ); + +// Hook/Ring rebuild are done as a post-process. + update( stack, horizontal ); +} + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Instance.cpp b/hurricane/src/hurricane/Instance.cpp index ae5dbb9e..260ed11b 100644 --- a/hurricane/src/hurricane/Instance.cpp +++ b/hurricane/src/hurricane/Instance.cpp @@ -20,6 +20,7 @@ #include "hurricane/Warning.h" #include "hurricane/UpdateSession.h" #include "hurricane/SharedPath.h" +#include "hurricane/DataBase.h" #include "hurricane/Instance.h" #include "hurricane/Cell.h" #include "hurricane/Net.h" @@ -30,7 +31,6 @@ namespace Hurricane { - // **************************************************************************************************** // Filters declaration & implementation // **************************************************************************************************** @@ -201,7 +201,10 @@ Instance* Instance::create(Cell* cell, const Name& name, Cell* masterCell, bool // **************************************************************************************** { if (not cell) - throw Error( "Instance::create(): NULL master Cell argument." ); + throw Error( "Instance::create(): NULL owner Cell argument for %s.", getString(name).c_str() ); + + if (not masterCell) + throw Error( "Instance::create(): NULL master Cell argument for %s.", getString(name).c_str() ); // if (cell->isUniquified()) // throw Error( "Instance::create(): %s master Cell is an uniquified copy.", getString(cell).c_str() ); @@ -217,7 +220,10 @@ Instance* Instance::create(Cell* cell, const Name& name, Cell* masterCell, const // ********************************************************************************************************************************************************************** { if (not cell) - throw Error( "Instance::create(): NULL master Cell argument." ); + throw Error( "Instance::create(): NULL owner Cell argument for %s.", getString(name).c_str() ); + + if (not masterCell) + throw Error( "Instance::create(): NULL master Cell argument for %s.", getString(name).c_str() ); // if (cell->isUniquified()) // throw Error( "Instance::create(): %s master Cell is an uniquified copy.", getString(cell).c_str() ); @@ -489,6 +495,15 @@ void Instance::uniquify() ) << endl; return; } + + if (not _getSharedPathMap().isEmpty()) { + cerr << Warning( "Instance::uniquify(): While uniquifying model %s of instance %s, SharedPathMap is not empty.\n" + " (Entity's Occurrences will still uses the original master Cell)" + , getString(_masterCell->getName()).c_str() + , getString(getName()).c_str() + ) << endl; + } + setMasterCell( _masterCell->getClone() ); } @@ -512,6 +527,13 @@ Instance* Instance::getClone(Cell* cloneCell) const , getPlacementStatus() ); + if (not clone->_getSharedPathMap().isEmpty()) { + cerr << Warning( "Instance::getClone(): While cloning instance %s, SharedPathMap is not empty.\n" + " (Occurrence will still uses the original instance)" + , getString(getName()).c_str() + ) << endl; + } + for( Plug* iplug : getPlugs() ) { if (iplug->isConnected()) { Plug* clonePlug = clone->getPlug( iplug->getMasterNet() ); @@ -595,6 +617,24 @@ Record* Instance::_getRecord() const return record; } +void Instance::_toJson( JsonWriter* writer ) const +// *********************************************** +{ + Inherit::_toJson( writer ); + + jsonWrite( writer, "_name" , getName() ); + jsonWrite( writer, "_masterCell" , _masterCell->getHierarchicalName() ); + jsonWrite( writer, "_transformation" , &_transformation ); + jsonWrite( writer, "_placementStatus", _placementStatus ); +} + +void Instance::_toJsonCollections(JsonWriter* writer) const +// ******************************************************** +{ + jsonWrite( writer, "+plugMap", getPlugs() ); + Inherit::_toJsonCollections( writer ); +} + // **************************************************************************************************** // Instance::PlugMap implementation // **************************************************************************************************** @@ -672,13 +712,20 @@ void Instance::SharedPathMap::_setNextElement(SharedPath* sharedPath, SharedPath Instance::PlacementStatus::PlacementStatus(const Code& code) // ********************************************************* : _code(code) -{ -} +{ } Instance::PlacementStatus::PlacementStatus(const PlacementStatus& placementstatus) // ******************************************************************************* : _code(placementstatus._code) +{ } + +Instance::PlacementStatus::PlacementStatus(string s) +// ************************************************* +: _code(UNPLACED) { + if (s == "UNPLACED") _code = UNPLACED; + else if (s == "PLACED" ) _code = PLACED; + else if (s == "FIXED" ) _code = FIXED; } Instance::PlacementStatus& Instance::PlacementStatus::operator=(const PlacementStatus& placementstatus) @@ -702,6 +749,47 @@ Record* Instance::PlacementStatus::_getRecord() const return record; } + +// **************************************************************************************************** +// JsonInstance implementation +// **************************************************************************************************** + +JsonInstance::JsonInstance(unsigned long flags) +// ******************************************** + : JsonEntity(flags) +{ + add( "_name" , typeid(string) ); + add( "_masterCell" , typeid(string) ); + add( "_transformation" , typeid(Transformation*) ); + add( "_placementStatus", typeid(string) ); + add( "+plugMap" , typeid(JsonArray) ); +} + +string JsonInstance::getTypeName() const +// ************************************* +{ return "Instance"; } + +JsonInstance* JsonInstance::clone(unsigned long flags) const +// ********************************************************* +{ return new JsonInstance ( flags ); } + +void JsonInstance::toData(JsonStack& stack) +// **************************************** +{ + check( stack, "JsonInstance::toData" ); + presetId( stack ); + + Instance* instance = Instance::create + ( get(stack,".Cell") + , get(stack,"_name") + , DataBase::getDB()->getCell( get(stack,"_masterCell") ) + , get(stack,"_transformation") + , Instance::PlacementStatus(get(stack,"_placementStatus") ) + ); + + update( stack, instance ); +} + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/JsonReader.cpp b/hurricane/src/hurricane/JsonReader.cpp new file mode 100644 index 00000000..beb50f92 --- /dev/null +++ b/hurricane/src/hurricane/JsonReader.cpp @@ -0,0 +1,821 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2015-2015, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./JsonReader.cpp" | +// +-----------------------------------------------------------------+ + + +#include "rapidjson/filereadstream.h" +#include "rapidjson/reader.h" +// Needed for registering. May be deleted later. +#include "hurricane/DebugSession.h" +#include "hurricane/Warning.h" +#include "hurricane/JsonReader.h" +#include "hurricane/Library.h" +#include "hurricane/Cell.h" +#include "hurricane/Net.h" +#include "hurricane/DeepNet.h" +#include "hurricane/Instance.h" +#include "hurricane/RoutingPad.h" +#include "hurricane/Contact.h" +#include "hurricane/Vertical.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Pad.h" +#include "hurricane/UpdateSession.h" +#include "hurricane/DesignBlob.h" + + +namespace { + + using namespace std; + using namespace rapidjson; + using namespace Hurricane; + + class JsonReader; + + +// ------------------------------------------------------------------- +// Class : "HurricaneHandler" (declaration). + + class HurricaneHandler { + public: + HurricaneHandler ( JsonReader& ); + public: + bool Null (); + bool Bool ( bool ); + bool Int ( int ); + bool Int64 ( int64_t ); + bool Uint ( unsigned int ); + bool Uint64 ( uint64_t ); + bool Double ( double ); + bool String ( const char*, SizeType, bool copy ); + bool Key ( const char*, SizeType, bool copy ); + bool StartObject (); + bool EndObject ( SizeType ); + bool StartArray (); + bool EndArray ( SizeType ); + inline bool isDummy () const; + inline bool doCallToData () const; + inline JsonStack& stack (); + inline unsigned long flags (); + private: + enum Flags { TypenameKey = (1<<0) + }; + private: + unsigned long _state; + string _key; + string _objectName; + vector _objects; + JsonReader& _reader; + }; + + +// ------------------------------------------------------------------- +// Class : "JsonReader" (declaration). + + class JsonReader { + public: + JsonReader ( unsigned long flags ); + ~JsonReader (); + inline JsonReader* setFlags ( unsigned long mask ); + inline JsonReader* resetFlags ( unsigned long mask ); + inline bool issetFlags ( unsigned long mask ) const; + inline unsigned long getFlags () const; + inline JsonStack& getStack (); + void parse ( std::string fileName ); + void close (); + private: + JsonReader ( const JsonReader& ); + JsonReader& operator= ( const JsonReader& ) const; + private: + unsigned long _flags; + size_t _bufferSize; + char* _buffer; + FILE* _file; + FileReadStream* _stream; + JsonStack _stack; + Reader _reader; + HurricaneHandler _handler; + }; + + +// ------------------------------------------------------------------- +// Class : "HurricaneHandler" (definition). + + HurricaneHandler::HurricaneHandler ( JsonReader& reader ) + : _state (0) + , _key () + , _objectName() + , _objects () + , _reader (reader) + { } + + + inline JsonStack& HurricaneHandler::stack () { return _reader.getStack(); } + inline unsigned long HurricaneHandler::flags () { return _reader.getFlags(); } + + + inline bool HurricaneHandler::isDummy () const + { return _objects.empty() or _objects.back()->isDummy(); } + + + inline bool HurricaneHandler::doCallToData () const + { return not _objects.empty() and _objects.back() and not _objects.back()->isBound(); } + + + bool HurricaneHandler::Null () + { + if (isDummy()) return true; + stack().push_back( _key, NULL ); + return true; + } + + + bool HurricaneHandler::Bool ( bool v ) + { + if (isDummy()) return true; + stack().push_back( _key, v ); + return true; + } + + + bool HurricaneHandler::Int ( int v ) + { + if (isDummy()) return true; + stack().push_back( _key, v ); + return true; + } + + + bool HurricaneHandler::Int64 ( int64_t v ) + { + if (isDummy()) return true; + stack().push_back( _key, v ); + return true; + } + + + bool HurricaneHandler::Uint ( unsigned int v ) + { + if (isDummy()) return true; + stack().push_back( _key, v ); + return true; + } + + + bool HurricaneHandler::Uint64 ( uint64_t v ) + { + if (isDummy()) return true; + stack().push_back( _key, v ); + return true; + } + + + bool HurricaneHandler::Double ( double v ) + { + if (isDummy()) return true; + stack().push_back( _key, v ); + return true; + } + + + bool HurricaneHandler::String ( const char* value, SizeType, bool copy ) + { + if (isDummy() and not (_state & TypenameKey)) return true; + if (_state & TypenameKey) { + _state &= ~TypenameKey; + + if (_key != "@typename") { + cerr << Warning("JsonReader::parse(): First field is not @typename, skipping object." ) << endl; + return true; + } + + string svalue = value; + JsonObject* object = NULL; + JsonSignature* signature = NULL; + if (svalue.compare(0,10,"Signature.") == 0) object = JsonTypes::find( "Signature" ); + else object = JsonTypes::find( value ); + + if (not object) { + // Keep the dummy object on top of the stack. + cerr << Warning( "JsonReader::parse(): Do not know how to parse type \"%s\" (ignored)." + , value ) << endl; + dynamic_cast(_objects.back())->setTypeName( value ); + } else { + // Replace the dummy object on top of the stack. + delete _objects.back(); + _objects[_objects.size()-1] = object->clone( flags() ); + _objects.back()->setName( _objectName ); + + signature = dynamic_cast( _objects.back() ); + if (signature) { + size_t dot = svalue.find('.'); + signature->setSubType( svalue.substr(dot+1) ); + } + } + + ltrace(51) << "HurricaneHandler::String() [key/typename] \"" << value << "\"." << endl; + return true; + } + + stack().push_back( _key, value ); + return true; + } + + + bool HurricaneHandler::Key ( const char* key, SizeType, bool copy ) + { + if (isDummy() and not (_state & TypenameKey)) return true; + + _key = key; + if (_state & TypenameKey) return true; + + //ltrace(51) << "HurricaneHandler::Key() key:" << _key << " _objects.size():" << _objects.size() << endl; + + if (_objects.back()) { + if ( doCallToData() and not _key.empty() and (_key[0] != '_') ) { + // The key is no longer a simple attribute of the object. + // Triggers it's creation in the Json stack. + ltrace(51) << "HurricaneHandler::key() Calling " + << _objects.back()->getTypeName() << "::toData(JsonStack&)." << endl; + _objects.back()->toData( stack() ); + } + } + + return true; + } + + + bool HurricaneHandler::StartObject () + { + ltrace(50) << "Hurricane::StartObject()" << endl; + ltracein(50); + + _state |= TypenameKey; + _objectName = (_key == ".Array") ? "" : _key; + _objects.push_back( new JsonDummy() ); + ltrace(51) << "_objects.push_back(NULL), size():" << _objects.size() << "." << endl; + + ltracein(50); + return true; + } + + + bool HurricaneHandler::EndObject ( SizeType ) + { + ltraceout(50,2); + ltrace(50) << "HurricaneHandler::EndObject()" << endl; + ltracein(50); + + _objectName.clear(); + if (not isDummy()) { + if (doCallToData()) { + ltrace(51) << "Calling " << _objects.back()->getTypeName() << "::toData(JsonStack&)." << endl; + _objects.back()->toData( stack() ); + } + if (stack().size() > 1) { + if (stack()[-1].first[0] != '_') stack().pop_back(); + } + } + + //if (_objects.size() > 1) { + ltrace(51) << "_objects.pop_back(), size():" << _objects.size() << "." << endl; + delete _objects.back(); + _objects.pop_back(); + //} + + ltraceout(50); + return true; + } + + + bool HurricaneHandler::StartArray() + { + ltrace(50) << "HurricaneHandler::StartArray() key:\"" << _key << "\"." << endl; + ltracein(50); + + _objectName.clear(); + if (_key[0] != '+') { + cerr << Warning("JsonReader::parse(): Array attributes must start by \'+\' %s.", _key.c_str() ) << endl; + return true; + } + + _key = ".Array"; + return true; + } + + bool HurricaneHandler::EndArray ( SizeType ) + { + ltraceout(50); + ltrace(50) << "HurricaneHandler::EndArray()" << endl; + ltracein(50); + + _key.clear(); + + ltraceout(50); + return true; + } + + +// ------------------------------------------------------------------- +// Class : "JsonReader" (definition). + + JsonReader::JsonReader ( unsigned long flags ) + : _flags (flags) + , _bufferSize(65536) + , _buffer (new char [_bufferSize]) + , _file (NULL) + , _stream (NULL) + , _stack () + , _reader () + , _handler (*this) + { + } + + + JsonReader::~JsonReader () + { + close(); + delete _buffer; + } + + + void JsonReader::close () + { + if (_stream) { delete _stream; _stream = NULL; } + if (_file ) { fclose(_file); _file = NULL; } + } + + + inline JsonReader* JsonReader::setFlags ( unsigned long mask ) { _flags |= mask; return this; } + inline JsonReader* JsonReader::resetFlags ( unsigned long mask ) { _flags &= ~mask; return this; } + inline bool JsonReader::issetFlags ( unsigned long mask ) const { return _flags & mask; } + inline unsigned long JsonReader::getFlags () const { return _flags; } + inline JsonStack& JsonReader::getStack () { return _stack; } + + + void JsonReader::parse ( string fileName ) + { + close(); + + DebugSession::open( 50 ); + + fileName += ".json"; + _file = fopen( fileName.c_str(), "r" ); + ltrace(50) << "_file:" << _file << ", _buffer:" << (void*)_buffer << endl; + + if (not _file) { + throw Error( "JsonReader::parse(): Cannot open file \"%s\"." + , fileName.c_str() ); + } + + _stream = new FileReadStream ( _file, _buffer, _bufferSize ); + + if (issetFlags(JsonWriter::DesignBlobMode)) + Entity::enableForcedIdMode(); + _reader.Parse( *_stream, _handler ); + _stack.print( cerr ); + if (issetFlags(JsonWriter::DesignBlobMode)) + Entity::disableForcedIdMode(); + + DebugSession::close(); + close(); + } + + +} // local namespace. + + +namespace Hurricane { + + using namespace std; + + +// ------------------------------------------------------------------- +// Class : "JsonObject". + + JsonObject::JsonObject ( unsigned long flags ) + : _flags (flags) + , _name () + , _stackeds () + , _attributes () + , _collections() + , _object () + { } + + + JsonObject::~JsonObject () + { } + + + bool JsonObject::isDummy () const + { return false; } + + + void JsonObject::add ( const string& key, type_index tid ) + { + if (key.empty()) { + cerr << "[ERROR] JsonObject::add(): Attempt to add attribute with an empty name, ignored." + << endl; + return; + } + if (has(key)) { + cerr << "[ERROR] JsonObject::add(): Attempt to add attribute \"" << key << "\" twice, cancelled." + << endl; + return; + } + + switch ( key[0] ) { + case '.': _stackeds .push_back( JsonAttribute(key,tid) ); return; + case '_': _attributes .push_back( JsonAttribute(key,tid) ); return; + case '+': _collections.push_back( JsonAttribute(key,tid) ); return; + default: break; + } + + cerr << "[ERROR] JsonObject::add(): Key name \"" << key + << "\" do not follow naming convention, cancelled." << endl; + } + + + void JsonObject::remove ( const std::string& key ) + { + if (key.empty()) { + cerr << Error( "JsonObject::remove(): Attempt to remove attribute with an empty name, ignored." ) << endl; + return; + } + + switch ( key[0] ) { + case '.': + for ( auto it = _stackeds.begin() ; it != _stackeds.end() ; ++it ) + if (key == (*it).key()) { _stackeds.erase(it); break; } + break; + case '_': + for ( auto it = _attributes.begin() ; it != _attributes.end() ; ++it ) + if (key == (*it).key()) { _attributes.erase(it); break; } + break; + case '+': + for ( auto it = _collections.begin() ; it != _collections.end() ; ++it ) + if (key == (*it).key()) { _collections.erase(it); break; } + break; + } + } + + + bool JsonObject::has ( const std::string& key ) const + { + if (key.empty()) return false; + switch ( key[0] ) { + case '.': + for ( size_t i=0 ; i<_stackeds.size() ; ++i ) + if (key == _stackeds[i].key()) return true; + break; + case '_': + for ( size_t i=0 ; i<_attributes.size() ; ++i ) + if (key == _attributes[i].key()) return true; + break; + case '+': + for ( size_t i=0 ; i<_collections.size() ; ++i ) + if (key == _collections[i].key()) return true; + break; + } + return false; + } + + + bool JsonObject::check ( JsonStack& stack, string fname ) const + { + for ( size_t i=0 ; i<_stackeds.size() ; ++i ) { + if (not stack.rhas(_stackeds[i].key())) { + cerr << Error( "%s(): Stack is missing context element with key \"%s\"" + , fname.c_str(), _stackeds[i].key().c_str() ) << endl; + return false; + } + } + for ( size_t i=0 ; i<_attributes.size() ; ++i ) { + if (not stack.rhas(_attributes[i].key())) { + cerr << Error( "%s(): Stack is missing attribute element with key \"%s\"" + , fname.c_str(), _attributes[i].key().c_str() ) << endl; + return false; + } + } + return true; + } + + + void JsonObject::toData ( JsonStack& ) + { } + + + unsigned int JsonObject::presetId ( JsonStack& stack ) + { + unsigned int jsonId = get( stack, "_id" ); + if (issetFlags(JsonWriter::DesignBlobMode)) { + Entity::setNextId( jsonId ); + } + return jsonId; + } + + + void JsonObject::print ( ostream& o ) const + { + o << tab << "JsonObject for type: " << getTypeName() << endl; + for ( size_t i=0 ; i<_stackeds.size() ; ++i ) + o << tab << "key:" << left << setw(20) << _stackeds[i].key() + << " type:" << _stackeds[i].tid().name() << endl; + + for ( size_t i=0 ; i<_attributes.size() ; ++i ) + o << tab << "key:" << left << setw(20) << _attributes[i].key() + << " type:" << _attributes[i].tid().name() << endl; + + for ( size_t i=0 ; i<_collections.size() ; ++i ) + o << tab << "key:" << left << setw(20) << _collections[i].key() + << " type:" << _collections[i].tid().name() << endl; + } + + +// ------------------------------------------------------------------- +// Class : "JsonKey". + + JsonKey::JsonKey ( const string& key ) + : JsonObject(0) + , _key (key) + { } + + + string JsonKey::getTypeName () const { return _key; } + JsonKey* JsonKey::clone ( unsigned long ) const { return new JsonKey ( *this ); } + + +// ------------------------------------------------------------------- +// Class : "JsonDummy". + + JsonDummy::JsonDummy () + : JsonObject(0) + , _typename ("dummy") + { } + + + bool JsonDummy::isDummy () const { return true; } + string JsonDummy::getTypeName () const { return _typename; } + void JsonDummy::setTypeName ( const string& name ) { _typename=name; } + JsonDummy* JsonDummy::clone ( unsigned long ) const { return new JsonDummy ( *this ); } + + +// ------------------------------------------------------------------- +// Class : "JsonTypes". + + JsonTypes* JsonTypes::_jsonTypes = NULL; + + + JsonTypes::JsonTypes () + : _jsonObjects() + { } + + + JsonTypes::~JsonTypes () + { + for ( JsonObject* object : _jsonObjects ) delete object; + } + + + void JsonTypes::_registerType ( JsonObject* object ) + { + if (_find(object->getTypeName())) { + throw Error( "JsonTypes::_registerType(): Attempt to register <%s> twice.", object->getTypeName().c_str() ); + } + _jsonObjects.insert( object ); + } + + + JsonObject* JsonTypes::_find ( const string& tname ) + { + JsonKey key( tname ); + set::iterator it = _jsonObjects.find( &key ); + if (it != _jsonObjects.end()) return (*it); + return NULL; + } + + + void JsonTypes::registerType ( JsonObject* object ) + { + if (not _jsonTypes) initialize(); + _jsonTypes->_registerType( object ); + } + + + JsonObject* JsonTypes::find ( const string& tname ) + { + if (not _jsonTypes) initialize(); + return _jsonTypes->_find( tname ); + } + + + void JsonTypes::initialize () + { + if (_jsonTypes) return; + + _jsonTypes = new JsonTypes (); + _jsonTypes->_registerType( new JsonPoint (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonBox (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonTransformation(JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonLibrary (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonCell (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonNet (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonDeepNet (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonPlugRef (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonRoutingPad (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonContact (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonVertical (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonHorizontal (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonPad (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonInstance (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonPlug (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonOccurrence (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonSignature (JsonWriter::RegisterMode) ); + _jsonTypes->_registerType( new JsonDesignBlob (JsonWriter::RegisterMode) ); + } + + +// ------------------------------------------------------------------- +// Class : "JsonStack". + + void JsonStack::addEntity ( unsigned int jsonId, Entity* entity ) + { _entities.insert( std::make_pair(jsonId,entity) ); } + + + void JsonStack::addHookLink ( Hook* hook, unsigned int jsonId, const string& jsonNext ) + { + if (jsonNext.empty()) return; + + unsigned int id = jsonId; + string tname = hook->_getTypeName(); + + auto ielement = _hooks.find( HookKey(id,tname) ); + if (ielement == _hooks.end()) { + auto r = _hooks.insert( make_pair( HookKey(id,tname), HookElement(hook) ) ); + ielement = r.first; + (*ielement).second.setFlags( HookElement::OpenRingStart ); + } + HookElement* current = &((*ielement).second); + if (not current->hook()) current->setHook( hook ); + + hookFromString( jsonNext, id, tname ); + ielement = _hooks.find( HookKey(id,tname) ); + if (ielement == _hooks.end()) { + auto r = _hooks.insert( make_pair( HookKey(id,tname), HookElement(NULL) ) ); + ielement = r.first; + } else { + (*ielement).second.resetFlags( HookElement::OpenRingStart ); + } + current->setNext( &((*ielement).second) ); + } + + + Hook* JsonStack::getHook ( unsigned int jsonId, const std::string& tname ) const + { + auto ihook = _hooks.find( HookKey(jsonId,tname) ); + if (ihook == _hooks.end()) return NULL; + + return (*ihook).second.hook(); + } + + + bool JsonStack::hookFromString ( std::string s, unsigned int& id, std::string& tname ) + { + size_t dot = s.rfind('.'); + if (dot == string::npos) return false; + + tname = s.substr( 0, dot ); + id = stoul( s.substr(dot+1) ); + return true; + } + + + bool JsonStack::checkRings () const + { + bool status = true; + + for ( auto kv : _hooks ) { + HookElement* ringStart = &(kv.second); + if (ringStart->issetFlags(HookElement::ClosedRing)) continue; + + if (ringStart->issetFlags(HookElement::OpenRingStart)) { + cerr << Error( "JsonStack::checkRing(): Open ring found, starting with %s.\n" + " Closing the ring..." + , getString(ringStart->hook()).c_str() ) << endl; + + status = false; + HookElement* element = ringStart; + while ( true ) { + if (not element->next()) { + // The ring is open: close it (loop on ringStart). + element->setNext( ringStart ); + element->setFlags( HookElement::ClosedRing ); + + cerr << Error( "Simple open ring." ) << endl; + break; + } + if (element->next()->issetFlags(HookElement::ClosedRing)) { + // The ring is half merged with itself, or another ring. + // (i.e. *multiple* hooks pointing the *same* next element) + element->setNext( ringStart ); + element->setFlags( HookElement::ClosedRing ); + + cerr << Error( "Complex fault: ring partially merged (convergent)." ) << endl; + break; + } + element = element->next(); + } + } + } + + return status; + } + + + void JsonStack::buildRings () const + { + for ( auto kv : _hooks ) { + kv.second.hook()->_setNextHook( kv.second.next()->hook() ); + } + } + + + void JsonStack::print ( ostream& o ) const + { + o << tab << "JsonStack::print() Stack contains " << _stack.size() << " elements." << endl; + for ( size_t i=0 ; i<_stack.size() ; ++i ) { + o << "[" << right << setw(2) << i << "] key: \"" << left << setw(20) << _stack[i].first + << "\", type: \"" << demangle(_stack[i].second.type()) << "\"." << endl; + } + } + + +// ------------------------------------------------------------------- +// Function : Json Cell parser. + + Cell* jsonCellParse ( string filename ) + { + UpdateSession::open(); + + JsonReader reader ( JsonWriter::CellMode ); + reader.parse( filename ); + + UpdateSession::close(); + + const JsonStack& stack = reader.getStack(); + if (stack.rhas(".Cell")) return stack.as(".Cell"); + + return NULL; + } + + +// ------------------------------------------------------------------- +// Function : Json Blob parser. + + Cell* jsonBlobParse ( string filename ) + { + UpdateSession::open(); + + JsonReader reader ( JsonWriter::DesignBlobMode ); + reader.parse( filename ); + + UpdateSession::close(); + + const JsonStack& stack = reader.getStack(); + if (stack.rhas(".DesignBlob")) { + DesignBlob* blob = stack.as(".DesignBlob"); + Cell* cell = blob->getTopCell(); + delete blob; + return cell; + } + + return NULL; + } + + +} // Hurricane namespace. diff --git a/hurricane/src/hurricane/JsonWriter.cpp b/hurricane/src/hurricane/JsonWriter.cpp new file mode 100644 index 00000000..a00e28e0 --- /dev/null +++ b/hurricane/src/hurricane/JsonWriter.cpp @@ -0,0 +1,101 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2015-2015, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./JsonWriter.cpp" | +// +-----------------------------------------------------------------+ + + +#include "rapidjson/filewritestream.h" +#include "rapidjson/prettywriter.h" +#include "hurricane/Commons.h" + + +//namespace Hurricane { + + typedef rapidjson::PrettyWriter JsonOfstream; + +#define _WRITER reinterpret_cast(_writer) + + +// ------------------------------------------------------------------- +// Class : "JsonWriter". + + JsonWriter::JsonWriter ( std::string fileName ) + : _flags (0) + , _bufferSize(65536) + , _buffer (new char [_bufferSize]) + , _file (NULL) + , _stream (NULL) + , _writer (NULL) + { + _file = fopen( fileName.c_str(), "w" ); + _stream = new rapidjson::FileWriteStream ( _file, _buffer, _bufferSize ); + _writer = new JsonOfstream ( *_stream ); + _WRITER->SetIndent( ' ', 2 ); + } + + + JsonWriter::~JsonWriter () + { close(); } + + + void JsonWriter::close () + { + if (_writer) { delete _WRITER; _writer = NULL; } + if (_stream) { delete _stream; _stream = NULL; } + if (_file ) { fclose(_file); _file = NULL; } + } + + + void JsonWriter::key ( const char* k ) { _WRITER->Key(k); }; + void JsonWriter::key ( std::string k ) { _WRITER->Key(k.c_str()); }; + void JsonWriter::startObject() { _WRITER->StartObject(); }; + void JsonWriter::startArray () { _WRITER->StartArray(); }; + void JsonWriter::endObject () { _WRITER->EndObject(); }; + void JsonWriter::endArray () { _WRITER->EndArray(); }; + void JsonWriter::write () { _WRITER->Null(); }; + void JsonWriter::write ( const char* s ) { _WRITER->String(s); }; + void JsonWriter::write ( const std::string* s ) { _WRITER->String(s->c_str()); }; + void JsonWriter::write ( std::string s ) { _WRITER->String(s.c_str()); }; + void JsonWriter::write ( const bool* v ) { _WRITER->Bool (*v); } + void JsonWriter::write ( bool v ) { _WRITER->Bool ( v); } + void JsonWriter::write ( const int* v ) { _WRITER->Int (*v); } + void JsonWriter::write ( int v ) { _WRITER->Int ( v); } + void JsonWriter::write ( const long* v ) { _WRITER->Int64 (*v); } + void JsonWriter::write ( long v ) { _WRITER->Int64 ( v); } + void JsonWriter::write ( const unsigned int* v ) { _WRITER->Uint (*v); } + void JsonWriter::write ( unsigned int v ) { _WRITER->Uint ( v); } + void JsonWriter::write ( const unsigned long* v ) { _WRITER->Uint64(*v); } + void JsonWriter::write ( unsigned long v ) { _WRITER->Uint64( v); } + JsonWriter* JsonWriter::setFlags ( unsigned long mask ) { _flags |= mask; return this; } + JsonWriter* JsonWriter::resetFlags ( unsigned long mask ) { _flags &= ~mask; return this; } + bool JsonWriter::issetFlags ( unsigned long mask ) const { return _flags & mask; } + unsigned long JsonWriter::getFlags () const { return _flags; } + + + +//} // Hurricane namespace. diff --git a/hurricane/src/hurricane/Layer.cpp b/hurricane/src/hurricane/Layer.cpp index b2eacc8a..5f790eed 100644 --- a/hurricane/src/hurricane/Layer.cpp +++ b/hurricane/src/hurricane/Layer.cpp @@ -219,7 +219,7 @@ namespace Hurricane { } - string Layer::_getString() const + string Layer::_getString () const { string s = DBo::_getString(); s.insert(s.length() - 1, " " + getString(_name)); @@ -227,7 +227,7 @@ namespace Hurricane { } - Record* Layer::_getRecord() const + Record* Layer::_getRecord () const { Record* record = DBo::_getRecord(); if (record) { @@ -242,4 +242,7 @@ namespace Hurricane { } + const Name& Layer::_sgetName ( const Layer* layer ) + { return layer->getName(); } + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Library.cpp b/hurricane/src/hurricane/Library.cpp index c348b9be..329c104b 100644 --- a/hurricane/src/hurricane/Library.cpp +++ b/hurricane/src/hurricane/Library.cpp @@ -97,6 +97,19 @@ void Library::setName(const Name& name) } } +string Library::getHierarchicalName () const +// ***************************************** +{ + string rpath; + Library* library = getLibrary(); + do { + rpath.insert( 0, getString(library->getName())+"." ); + + library = library->getLibrary(); + } while ( library ); + + return rpath + getString(getName()); +} void Library::_postCreate() // ************************ { @@ -215,6 +228,70 @@ void Library::CellMap::_setNextElement(Cell* cell, Cell* nextCell) const cell->_setNextOfLibraryCellMap(nextCell); }; +void Library::_toJson(JsonWriter* w) const +// *************************************** +{ + Inherit::_toJson( w ); + + jsonWrite( w, "_name" , getName() ); + jsonWrite( w, "+cellMap" , getCells() ); + jsonWrite( w, "+libraryMap", getLibraries() ); +} + + +// **************************************************************************************************** +// JsonLibrary implementation +// **************************************************************************************************** + +JsonLibrary::JsonLibrary(unsigned long flags) +// ************************************ + : JsonDBo(flags) +{ + add( ".Library" , typeid(Library*) ); + add( "_name" , typeid(string) ); + add( "+cellMap" , typeid(JsonArray) ); + add( "+libraryMap", typeid(JsonArray) ); +} + +string JsonLibrary::getTypeName() const +// ********************************* +{ return "Library"; } + +JsonLibrary* JsonLibrary::clone(unsigned long flags) const +// ************************************************* +{ return new JsonLibrary ( flags ); } + +void JsonLibrary::toData(JsonStack& stack) +// *************************************** +{ + check( stack, "JsonLibrary::toData" ); + + Name libName ( get ( stack, "_name" ) ); + Library* parent = get( stack, ".Library" ); + if (not parent) + parent = get( stack, "_library" ); + + Library* library = NULL; + if (parent) { + library = parent->getLibrary( libName ); + if (not library) + library = Library::create( parent, libName ); + } else { + library = DataBase::getDB()->getRootLibrary(); + if (not library) + library = Library::create( DataBase::getDB(), libName ); + else { + if (library->getName() != libName) { + throw Error( "JsonLibrary::toData(): Root library name discrepency, \"%s\" vs. \"%s\"." + , getString(library->getName()).c_str() + , getString(libName).c_str() + ); + } + } + } + + update( stack, library ); +} } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Net.cpp b/hurricane/src/hurricane/Net.cpp index 56e75993..3bf41410 100644 --- a/hurricane/src/hurricane/Net.cpp +++ b/hurricane/src/hurricane/Net.cpp @@ -738,6 +738,37 @@ Record* Net::_getRecord() const return record; } +void Net::_toJson(JsonWriter* writer) const +// **************************************** +{ + Inherit::_toJson( writer ); + + jsonWrite( writer, "_name" , getName() ); + jsonWrite( writer, "_isGlobal" , isGlobal() ); + jsonWrite( writer, "_isExternal" , isExternal() ); + jsonWrite( writer, "_isAutomatic" , isAutomatic() ); + jsonWrite( writer, "_type" , getString(getType()) ); + jsonWrite( writer, "_direction" , getString(getDirection()) ); +} + +void Net::_toJsonSignature(JsonWriter* writer) const +// ************************************************* +{ + jsonWrite( writer, "_name", getName() ); +} + +void Net::_toJsonCollections(JsonWriter* writer) const +// *************************************************** +{ + jsonWrite( writer, "+aliases", getAliases() ); + writer->setFlags( JsonWriter::UsePlugReference ); + jsonWrite( writer, "+componentSet", getComponents() ); + writer->resetFlags( JsonWriter::UsePlugReference ); + + Inherit::_toJsonCollections( writer ); +} + + // **************************************************************************************************** // Net::Type implementation // **************************************************************************************************** @@ -745,13 +776,22 @@ Record* Net::_getRecord() const Net::Type::Type(const Code& code) // ****************************** : _code(code) -{ -} +{ } Net::Type::Type(const Type& type) // ****************************** : _code(type._code) +{ } + +Net::Type::Type(string s) +// ********************** +: _code(UNDEFINED) { + if (s == "UNDEFINED") _code = UNDEFINED; + else if (s == "LOGICAL" ) _code = LOGICAL; + else if (s == "CLOCK" ) _code = CLOCK; + else if (s == "POWER" ) _code = POWER; + else if (s == "GROUND" ) _code = GROUND; } Net::Type& Net::Type::operator=(const Type& type) @@ -784,13 +824,23 @@ Record* Net::Type::_getRecord() const Net::Direction::Direction(const Code& code) // **************************************** : _code(code) -{ -} +{ } Net::Direction::Direction(const Direction& direction) // ************************************************** : _code(direction._code) +{ } + +Net::Direction::Direction(string s) +// ******************************** +: _code(UNDEFINED) { + if (s.size() > 3) { + if (s[0] == 'i') *this |= DirIn; + if (s[0] == 'o') *this |= DirOut; + if (s[0] == 't') *this |= ConnTristate; + if (s[0] == 'w') *this |= ConnWiredOr; + } } Net::Direction& Net::Direction::operator=(const Direction& direction) @@ -1008,6 +1058,81 @@ string Net_SlavePlugs::Locator::_getString() const return s; } + + +// **************************************************************************************************** +// JsonNet implementation +// **************************************************************************************************** + +JsonNet::JsonNet(unsigned long flags) +// ********************************** + : JsonEntity (flags) + , _autoMaterialize(not Go::autoMaterializationIsDisabled()) + , _net (NULL) + , _stack (NULL) +{ + if (flags & JsonWriter::RegisterMode) return; + + ltrace(51) << "JsonNet::JsonNet()" << endl; + + add( "_name" , typeid(string) ); + add( "_isGlobal" , typeid(bool) ); + add( "_isExternal" , typeid(bool) ); + add( "_isAutomatic" , typeid(bool) ); + add( "_type" , typeid(string) ); + add( "_direction" , typeid(string) ); + add( "+aliases" , typeid(JsonArray) ); + add( "+componentSet", typeid(JsonArray) ); + + ltrace(51) << "Disabling auto-materialization (" << _autoMaterialize << ")." << endl; + Go::disableAutoMaterialization(); +} + +JsonNet::~JsonNet() +// **************** +{ + _stack->checkRings(); + _stack->buildRings(); + _stack->clearHookLinks(); + + _net->materialize(); + + if (_autoMaterialize) { + Go::enableAutoMaterialization(); + ltrace(51) << "Enabling auto-materialization." << endl; + } +} + +string JsonNet::getTypeName() const +// ********************************* +{ return "Net"; } + +JsonNet* JsonNet::clone(unsigned long flags) const +// *********************************************** +{ return new JsonNet ( flags ); } + +void JsonNet::toData(JsonStack& stack) +// *********************************** +{ + ltracein(51); + + _stack = &stack; + + check( stack, "JsonNet::toData" ); + presetId( stack ); + + _net = Net::create( get(stack,".Cell") , get(stack,"_name") ); + _net->setGlobal ( get(stack,"_isGlobal" ) ); + _net->setExternal ( get(stack,"_isExternal" ) ); + _net->setAutomatic( get(stack,"_isAutomatic") ); + _net->setType ( Net::Type (get(stack,"_type")) ); + _net->setDirection( Net::Direction(get(stack,"_direction")) ); + + update( stack, _net ); + + ltraceout(51); +} + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Occurrence.cpp b/hurricane/src/hurricane/Occurrence.cpp index 077a2969..f3201ffd 100644 --- a/hurricane/src/hurricane/Occurrence.cpp +++ b/hurricane/src/hurricane/Occurrence.cpp @@ -261,6 +261,23 @@ string Occurrence::getCompactString() const return s; } +void Occurrence::toJson(JsonWriter* w) const +// ****************************************** +{ + w->startObject(); + jsonWrite( w, "@typename", "Occurrence" ); + jsonWrite( w, "_path" , getPath().getJsonString(w->getFlags()) ); + + w->key( "_entity" ); + if (not w->issetFlags(JsonWriter::DesignBlobMode)) { + getEntity()->toJsonSignature( w ); + } else { + jsonWrite( w, getEntity()->getId() ); + } + + w->endObject(); +} + Record* Occurrence::_getRecord() const // **************************** { @@ -307,6 +324,77 @@ string Occurrence::getName() const return description; } +JsonOccurrence::JsonOccurrence(unsigned long flags) +// ************************************************ + : JsonObject(flags) +{ + add( ".Cell" , typeid(Cell*) ); + add( "_path" , typeid(string) ); + + if (issetFlags(JsonWriter::DesignBlobMode)) { + add( "_entity", typeid(uint64_t) ); + } else { + add( "_entity", typeid(Entity*) ); + } +} + +JsonOccurrence* JsonOccurrence::clone(unsigned long flags) const +// ************************************************************* +{ return new JsonOccurrence ( flags ); } + +string JsonOccurrence::getTypeName() const +// *************************************** +{ return "Occurrence"; } + +void JsonOccurrence::toData(JsonStack& stack) +// ****************************************** +{ + check( stack, "JsonOccurrence::toData" ); + + Path path; + Entity* entity = NULL; + if (issetFlags(JsonWriter::DesignBlobMode)) { + entity = stack.getEntity( get(stack,"_entity") ); + + //Cell* cell = get( stack, ".Cell" ); + Instance* instance = NULL; + char separator = SharedPath::getNameSeparator(); + string pathIds = get( stack, "_path" ); + unsigned long id; + size_t dot = pathIds.find( separator ); + + if (dot != string::npos) { + id = stoul( pathIds.substr( 0, dot ) ); + pathIds = pathIds.substr( dot+1 ); + } else + id = stol( pathIds ); + + instance = stack.getEntity(id); + if (not instance) + throw Error( "JsonOccurrence::toData(): No Instance id:lu% (or not an Instance) in stack LUT.", id ); + path = Path( instance ); + + while ( dot != string::npos ) { + dot = pathIds.find( separator ); + if (dot != string::npos) { + id = stoul( pathIds.substr( 0, dot ) ); + pathIds = pathIds.substr( dot+1 ); + } else + id = stol( pathIds ); + + instance = stack.getEntity(id); + if (not instance) + throw Error( "JsonOccurrence::toData(): No Instance id:lu% (or not an Instance) in stack LUT.", id ); + path = Path( path, instance ); + } + } else { + entity = get(stack,"_entity"); + path = Path( get(stack,".Cell"), get(stack,"_path") ); + } + + Occurrence occurrence ( entity, path ); + update( stack, occurrence ); +} } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Pad.cpp b/hurricane/src/hurricane/Pad.cpp index 2ad7aa36..7c23d9e9 100644 --- a/hurricane/src/hurricane/Pad.cpp +++ b/hurricane/src/hurricane/Pad.cpp @@ -17,6 +17,8 @@ // not, see . // **************************************************************************************************** +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" #include "hurricane/Pad.h" #include "hurricane/Net.h" #include "hurricane/BasicLayer.h" @@ -117,6 +119,15 @@ void Pad::setBoundingBox(const Box& boundingBox) } } +void Pad::_toJson(JsonWriter* writer) const +// **************************************** +{ + Inherit::_toJson( writer ); + + jsonWrite( writer, "_layer" , _layer->getName() ); + jsonWrite( writer, "_boundingBox", &_boundingBox ); +} + string Pad::_getString() const // *************************** { @@ -137,6 +148,45 @@ Record* Pad::_getRecord() const return record; } + +// **************************************************************************************************** +// JsonPad implementation +// **************************************************************************************************** + +JsonPad::JsonPad(unsigned long flags) +// ********************************** + : JsonComponent(flags) +{ + add( "_layer" , typeid(string) ); + add( "_boundingBox", typeid(Box) ); +} + +string JsonPad::getTypeName() const +// ******************************** +{ return "Pad"; } + +JsonPad* JsonPad::clone(unsigned long flags) const +// *********************************************** +{ return new JsonPad ( flags ); } + +void JsonPad::toData(JsonStack& stack) +// *********************************** +{ + check( stack, "JsonPad::toData" ); + unsigned int jsonId = presetId( stack ); + + Pad* pad = Pad::create + ( get(stack,".Net") + , DataBase::getDB()->getTechnology()->getLayer( get(stack,"_layer") ) + , get(stack,".Box") + ); + + stack.addHookLink( pad->getBodyHook (), jsonId, get(stack,"_bodyHook" ) ); + +// Hook/Ring rebuild are done as a post-process. + update( stack, pad ); +} + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Path.cpp b/hurricane/src/hurricane/Path.cpp index 36a17c38..49a35b4f 100644 --- a/hurricane/src/hurricane/Path.cpp +++ b/hurricane/src/hurricane/Path.cpp @@ -258,6 +258,25 @@ string Path::getCompactString() const return s; } +string Path::getJsonString(unsigned long flags) const +// ************************************************** +{ + if (isEmpty()) return ""; + + string s; + if (flags & JsonWriter::DesignBlobMode) { + //s += getString(getOwnerCell()->getId()) + "::"; + s += getString(_sharedPath->getJsonString(flags)); + //s += "::" + getString(getMasterCell()->getId()); + } else { + //s += getString(getOwnerCell()->getName()) + "::"; + s += getString(_sharedPath->getJsonString(flags)); + //s += "::" + getString(getMasterCell()->getName()); + } + + return s; +} + string Path::_getString() const // **************************** { @@ -282,7 +301,6 @@ Record* Path::_getRecord() const } - } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Plug.cpp b/hurricane/src/hurricane/Plug.cpp index e65a2c5a..6027c3de 100644 --- a/hurricane/src/hurricane/Plug.cpp +++ b/hurricane/src/hurricane/Plug.cpp @@ -153,11 +153,12 @@ void Plug::setNet(Net* net) Plug* Plug::_create(Instance* instance, Net* masterNet) // **************************************************** { - Plug* plug = new Plug(instance, masterNet); + if (Entity::inForcedIdMode()) Entity::setNextId( 0 ); - plug->_postCreate(); + Plug* plug = new Plug(instance, masterNet); - return plug; + plug->_postCreate(); + return plug; } void Plug::_postCreate() @@ -190,6 +191,18 @@ void Plug::_preDestroy() // trace_out(); } +void Plug::_toJson(JsonWriter* writer) const +// ***************************************** +{ + if (writer->issetFlags(JsonWriter::UsePlugReference)) { + jsonWrite( writer, "_id" , getId() ); + jsonWrite( writer, "_instance", getInstance()->getName() ); + } else { + Inherit::_toJson( writer ); + jsonWrite( writer, "_masterNet", getMasterNet()->getName() ); + } +} + string Plug::_getString() const // **************************** { @@ -217,6 +230,109 @@ string Plug::getName() const + getString(_masterNet->getName()); } + + +// **************************************************************************************************** +// JsonPlug implementation +// **************************************************************************************************** + +JsonPlug::JsonPlug(unsigned long flags) +// ************************************ + : JsonComponent(flags) +{ + add( "_masterNet", typeid(string) ); +} + +string JsonPlug::getTypeName() const +// ********************************* +{ return "Plug"; } + +JsonPlug* JsonPlug::clone(unsigned long flags) const +// ************************************************* +{ return new JsonPlug ( flags ); } + +void JsonPlug::toData(JsonStack& stack) +// ************************************ +{ +// We are parsing an Instance. +// Plugs are automatically createds whith the Instance. +// Here we add the Plug to the stack's entity table that +// associates the Json Ids to the actual Hurricane ones. +// At the same time, we perform some coherency checking +// (i.e. the same Plug already exists). + +// For now, simply discard "_id" & "_propertySet". + check( stack, "JsonPlug::toData" ); + + Instance* instance = get(stack,".Instance"); + Plug* plug = NULL; + if (instance) { + Net* masterNet = instance->getMasterCell()->getNet( get(stack,"_masterNet") ); + if (not masterNet) { + cerr << Error( "JsonPlug::toData(): Incoherency, instance %s master doesn't containt net %s." + , getString(instance->getName()).c_str() + , get(stack,"_masterNet").c_str() + ) << endl; + } else { + unsigned int jsonId = get(stack,"_id"); + plug = instance->getPlug( masterNet ); + if (issetFlags(JsonWriter::DesignBlobMode)) + plug->forceId( jsonId ); + stack.addHookLink( plug->getBodyHook (), jsonId, get(stack,"_bodyHook" ) ); + } + } else { + cerr << Error( "JsonPlug::toData(): Cannot find \".Instance\" in stack, skipping." ) << endl; + } + ltrace(51) << "Instance Plug contents ignored for now." << endl; + + update( stack, plug ); +} + + + +// **************************************************************************************************** +// JsonPlugRef implementation +// **************************************************************************************************** + +JsonPlugRef::JsonPlugRef(unsigned long flags) +// ****************************************** + : JsonObject(flags) +{ + add( ".Net" , typeid(Net*) ); + add( "_id" , typeid(uint64_t) ); + add( "_instance", typeid(string) ); +} + +string JsonPlugRef::getTypeName() const +// ************************************ +{ return "&Plug"; } + +JsonPlugRef* JsonPlugRef::clone(unsigned long flags) const +// ******************************************************* +{ return new JsonPlugRef ( flags ); } + +void JsonPlugRef::toData(JsonStack& stack) +// *************************************** +{ + check( stack, "JsonPlugRef::toData" ); + +// We are parsing a Net, perform only a "Plug::setNet()". + Net* net = get(stack,".Net"); + Instance* instance = net->getCell()->getInstance( get(stack,"_instance") ); + unsigned int id = get(stack,"_id"); + + Plug* plug = stack.getEntity(id); + if (plug) { + plug->setNet( net ); + } else { + cerr << Error( "JsonPlugRef::toData(): No Plug id:%u in instance %s, while building net %s." + , id, getString(instance->getName()).c_str(), getString(net->getName()).c_str() + ) << endl; + } + + update( stack, plug ); +} + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Point.cpp b/hurricane/src/hurricane/Point.cpp index 902dee17..7f6f5a05 100644 --- a/hurricane/src/hurricane/Point.cpp +++ b/hurricane/src/hurricane/Point.cpp @@ -123,7 +123,40 @@ Record* Point::_getRecord() const return record; } +void Point::toJson ( JsonWriter* w ) const +// **************************************** +{ + w->startObject(); + jsonWrite( w, "@typename", "Point" ); + jsonWrite( w, "_x", getX() ); + jsonWrite( w, "_y", getY() ); + w->endObject(); +} +JsonPoint::JsonPoint(unsigned long flags) +// ************************************** + : JsonObject(flags) +{ + add( "_x", typeid(int64_t) ); + add( "_y", typeid(int64_t) ); +} + +JsonPoint* JsonPoint::clone(unsigned long flags) const +// *************************************************** +{ return new JsonPoint ( flags ); } + +string JsonPoint::getTypeName() const +// ********************************** +{ return "Point"; } + +void JsonPoint::toData(JsonStack& stack) +// ************************************* +{ + check( stack, "JsonPoint::toData" ); + Point point ( DbU::fromDb(get(stack,"_x")) + , DbU::fromDb(get(stack,"_y")) ); + update( stack, point ); +} } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/RoutingPad.cpp b/hurricane/src/hurricane/RoutingPad.cpp index 91b18cc8..81465ada 100644 --- a/hurricane/src/hurricane/RoutingPad.cpp +++ b/hurricane/src/hurricane/RoutingPad.cpp @@ -38,6 +38,7 @@ #include "hurricane/Segment.h" #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" +#include "hurricane/Pad.h" #include "hurricane/Cell.h" #include "hurricane/Instance.h" #include "hurricane/Warning.h" @@ -50,6 +51,9 @@ namespace Hurricane { using std::ostringstream; +// ------------------------------------------------------------------- +// Class : "RoutingPad". + RoutingPad::RoutingPad ( Net* net, Occurrence occurrence ) : Inherit (net) , _occurrence(occurrence) @@ -61,18 +65,27 @@ namespace Hurricane { if ( not net ) throw Error ("Can't create RoutingPad : NULL net"); if ( not occurrence.isValid() ) throw Error ("Can't create RoutingPag : Invalid occurrence"); - Plug* plug = NULL; - Pin* pin = NULL; - Contact* contact = NULL; + Plug* plug = NULL; + Pin* pin = NULL; + Contact* contact = NULL; + Horizontal* horizontal = NULL; + Vertical* vertical = NULL; + Pad* pad = NULL; if ( (plug = dynamic_cast(occurrence.getEntity()) ) == NULL) { if ( (pin = dynamic_cast(occurrence.getEntity()) ) == NULL) { - contact = dynamic_cast(occurrence.getEntity()); + if ( (contact = dynamic_cast(occurrence.getEntity()) ) == NULL) { + if ( (horizontal = dynamic_cast(occurrence.getEntity()) ) == NULL) { + if ( (vertical = dynamic_cast(occurrence.getEntity()) ) == NULL) { + pad = dynamic_cast(occurrence.getEntity()); + } + } + } } } - if ( (not plug) and (not pin) and (not contact) ) - throw Error ("Can't create RoutingPad : Plug, Pin, or Contact Occurrence *required*"); + if ( (not plug) and (not pin) and (not contact) and (not horizontal) and (not vertical) and (not pad) ) + throw Error ("Can't create RoutingPad : Plug, Pin, Contact, Horizontal, Vertical or Pad Occurrence *required*"); RoutingPad* routingPad = new RoutingPad( net, occurrence ); routingPad->_postCreate(); @@ -156,8 +169,9 @@ namespace Hurricane { Box RoutingPad::getBoundingBox ( const BasicLayer* basicLayer ) const { Component* component = _getEntityAsComponent(); - if ( component ) + if ( component ) { return _occurrence.getPath().getTransformation().getBox ( component->getBoundingBox(basicLayer) ); + } return Box(getPosition()); } @@ -175,8 +189,9 @@ namespace Hurricane { Point RoutingPad::getPosition () const { Component* component = _getEntityAsComponent(); - if (component) + if (component) { return _occurrence.getPath().getTransformation().getPoint( component->getCenter() ); + } return Point(); } @@ -233,6 +248,12 @@ namespace Hurricane { } + void RoutingPad::_toJson ( JsonWriter* writer ) const + { + Inherit::_toJson( writer ); + jsonWrite( writer, "_occurrence", &_occurrence ); + } + string RoutingPad::_getString () const { string s = Inherit::_getString(); @@ -379,4 +400,37 @@ namespace Hurricane { } +// ------------------------------------------------------------------- +// Class : "JsonRoutingPad". + + JsonRoutingPad::JsonRoutingPad ( unsigned long flags ) + : JsonComponent(flags) + { + add( "_occurrence", typeid(Occurrence) ); + } + + string JsonRoutingPad::getTypeName () const + { return "RoutingPad"; } + + + JsonRoutingPad* JsonRoutingPad::clone ( unsigned long flags ) const + { return new JsonRoutingPad ( flags ); } + + + void JsonRoutingPad::toData ( JsonStack& stack ) + { + check( stack, "JsonRoutingPad::toData" ); + unsigned int jsonId = presetId( stack ); + + RoutingPad* rp = RoutingPad::create + ( get (stack,".Net") + , get(stack,"_occurrence") + ); + + stack.addHookLink( rp->getBodyHook (), jsonId, get(stack,"_bodyHook" ) ); + + update( stack, rp ); + } + + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Segment.cpp b/hurricane/src/hurricane/Segment.cpp index 1eba7e0c..9635d86b 100644 --- a/hurricane/src/hurricane/Segment.cpp +++ b/hurricane/src/hurricane/Segment.cpp @@ -306,6 +306,17 @@ void Segment::_preDestroy() // trace_out(); } +void Segment::_toJson(JsonWriter* writer) const +// ******************************************** +{ + Inherit::_toJson( writer ); + + jsonWrite( writer, "_sourceHook", _sourceHook.getNextHook()->toJson() ); + jsonWrite( writer, "_targetHook", _targetHook.getNextHook()->toJson() ); + jsonWrite( writer, "_layer" , _layer->getName() ); + jsonWrite( writer, "_width" , _width ); +} + string Segment::_getString() const // ******************************* { @@ -318,7 +329,7 @@ string Segment::_getString() const } Record* Segment::_getRecord() const -// ************************** +// ******************************** { Record* record = Inherit::_getRecord(); if (record) { @@ -332,6 +343,7 @@ Record* Segment::_getRecord() const return record; } + // **************************************************************************************************** // Segment::SourceHook implementation // **************************************************************************************************** @@ -342,11 +354,13 @@ Segment::SourceHook::SourceHook(Segment* segment) // ********************************************** : Inherit() { - if (!segment) - throw Error("Can't create " + _TName("Segment::SourceHook") + " (null segment)"); + if (!segment) + throw Error("Can't create " + _getTypeName() + " (null segment)"); - if (SOURCE_HOOK_OFFSET == -1) - SOURCE_HOOK_OFFSET = (unsigned long)this - (unsigned long)segment; + if (SOURCE_HOOK_OFFSET == -1) { + SOURCE_HOOK_OFFSET = (unsigned long)this - (unsigned long)segment; + Hook::addCompToHook(_getTypeName(),_compToHook); + } } Component* Segment::SourceHook::getComponent() const @@ -361,6 +375,16 @@ string Segment::SourceHook::_getString() const return "<" + _TName("Segment::SourceHook") + " " + getString(getComponent()) + ">"; } +Hook* Segment::SourceHook::_compToHook(Component* component) +// *************************************************************** +{ + Segment* segment = dynamic_cast(component); + if (not segment) { + throw Error( "SourceHook::_compToHook(): Unable to cast %s into Segment*." + , getString(component).c_str() ); + } + return &(segment->_sourceHook); +} // **************************************************************************************************** @@ -376,8 +400,10 @@ Segment::TargetHook::TargetHook(Segment* segment) if (!segment) throw Error("Can't create " + _TName("Segment::TargetHook") + " (null segment)"); - if (TARGET_HOOK_OFFSET == -1) - TARGET_HOOK_OFFSET = (unsigned long)this - (unsigned long)segment; + if (TARGET_HOOK_OFFSET == -1) { + TARGET_HOOK_OFFSET = (unsigned long)this - (unsigned long)segment; + Hook::addCompToHook(_getTypeName(),_compToHook); + } } Component* Segment::TargetHook::getComponent() const @@ -392,6 +418,18 @@ string Segment::TargetHook::_getString() const return "<" + _TName("Segment::TargetHook") + " " + getString(getComponent()) + ">"; } +Hook* Segment::TargetHook::_compToHook(Component* component) +// *************************************************************** +{ + Segment* segment = dynamic_cast(component); + if (not segment) { + throw Error( "TargetHook::_compToHook(): Unable to cast %s into Segment*." + , getString(component).c_str() ); + } + return &(segment->_targetHook); +} + + // **************************************************************************************************** // Segment_Hooks implementation // **************************************************************************************************** @@ -633,6 +671,20 @@ string Segment_Anchors::Locator::_getString() const +// **************************************************************************************************** +// JsonSegment implementation +// **************************************************************************************************** + +JsonSegment::JsonSegment(unsigned long flags) +// ****************************************** + : JsonComponent(flags) +{ + add( "_sourceHook", typeid(string) ); + add( "_targetHook", typeid(string) ); + add( "_layer" , typeid(uint64_t) ); + add( "_width" , typeid(uint64_t) ); +} + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/SharedPath.cpp b/hurricane/src/hurricane/SharedPath.cpp index 04d83f7e..a0a97575 100644 --- a/hurricane/src/hurricane/SharedPath.cpp +++ b/hurricane/src/hurricane/SharedPath.cpp @@ -186,6 +186,23 @@ string SharedPath::getName() const return name; } +string SharedPath::getJsonString(unsigned long flags) const +// ******************************************************** +{ + string name = ""; + SharedPath* sharedPath = (SharedPath*)this; + while (sharedPath) { + if (flags & JsonWriter::DesignBlobMode) + name += getString(sharedPath->getHeadInstance()->getId()); + else + name += getString(sharedPath->getHeadInstance()->getName()); + + sharedPath = sharedPath->getTailSharedPath(); + if (sharedPath) name += getNameSeparator(); + } + return name; +} + Cell* SharedPath::getOwnerCell() const // *********************************** { diff --git a/hurricane/src/hurricane/Signature.cpp b/hurricane/src/hurricane/Signature.cpp new file mode 100644 index 00000000..cbc1dc27 --- /dev/null +++ b/hurricane/src/hurricane/Signature.cpp @@ -0,0 +1,167 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2000-2015, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Authors : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./Signature.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/Path.h" +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/Net.h" +#include "hurricane/Cell.h" +#include "hurricane/Instance.h" +#include "hurricane/Contact.h" +#include "hurricane/Vertical.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Pad.h" +#include "hurricane/Signature.h" + + +namespace Hurricane { + + using std::ostringstream; + + +// ------------------------------------------------------------------- +// Class : "Signature". + + void Signature::setLayer ( const std::string& layer ) + { + _layer = DataBase::getDB()->getTechnology()->getLayer( layer ); + } + + +// ------------------------------------------------------------------- +// Class : "JsonSignature". + + JsonSignature::JsonSignature ( unsigned long flags ) + : JsonObject (flags) + , _subTypeName("unset") + { } + + string JsonSignature::getTypeName () const + { return "Signature"; } + + + void JsonSignature::setSubType ( const std::string& subTypeName ) + { + clear(); + _subTypeName = subTypeName; + + if (_subTypeName == "Instance") { + add( "_instance" , typeid(string) ); + } else if (_subTypeName == "Net") { + add( "_name", typeid(string) ); + } else if (_subTypeName == "Plug") { + add( "_masterNet", typeid(string) ); + } else if (_subTypeName == "Contact") { + add( "_net", typeid(string) ); + JsonContact jobject (0); + copyAttrs( &jobject ); + } else if (_subTypeName == "Vertical") { + add( "_net", typeid(string) ); + JsonVertical jobject (0); + copyAttrs( &jobject ); + } else if (_subTypeName == "Horizontal") { + add( "_net", typeid(string) ); + JsonHorizontal jobject (0); + copyAttrs( &jobject ); + } + } + + JsonSignature* JsonSignature::clone ( unsigned long flags ) const + { return new JsonSignature ( flags ); } + + + void JsonSignature::toData ( JsonStack& stack ) + { + ltrace(51) << (void*)this << " _subTypeName:" << _subTypeName << endl; + + check( stack, "JsonSignature::toData" ); + + Cell* ownerCell = get ( stack, ".Cell" ); + string pathName = get( stack, "_path" ); + Path path ( ownerCell, pathName ); + Cell* masterCell = path.getMasterCell(); + Entity* entity = NULL; + + if (_subTypeName == "Instance") { + entity = masterCell->getInstance( get(stack,"_name") ); + } else if (_subTypeName == "Net") { + entity = masterCell->getNet( get(stack,"_name") ); + } else if (_subTypeName == "Plug") { + Net* masterNet = masterCell->getNet( get(stack,"_masterNet") ); + entity = path.getTailInstance()->getPlug( masterNet ); + } else if (_subTypeName == "Contact") { + Signature signature; + signature.setType ( Signature::TypeContact ); + signature.setName ( get(stack,"_net" ) ); + signature.setLayer( get(stack,"_layer" ) ); + signature.setDim( Signature::ContactDx , get(stack,"_dx" ) ); + signature.setDim( Signature::ContactDy , get(stack,"_dy" ) ); + signature.setDim( Signature::ContactWidth , get(stack,"_width" ) ); + signature.setDim( Signature::ContactHeight, get(stack,"_height") ); + entity = masterCell->getEntity( signature ); + } else if (_subTypeName == "Vertical") { + Signature signature; + signature.setType ( Signature::TypeVertical ); + signature.setName ( get(stack,"_net" ) ); + signature.setLayer( get(stack,"_layer") ); + signature.setDim( Signature::VerticalWidth , get(stack,"_width" ) ); + signature.setDim( Signature::VerticalX , get(stack,"_x" ) ); + signature.setDim( Signature::VerticalDySource, get(stack,"_dySource") ); + signature.setDim( Signature::VerticalDyTarget, get(stack,"_dyTarget") ); + entity = masterCell->getEntity( signature ); + } else if (_subTypeName == "Horizontal") { + Signature signature; + signature.setType ( Signature::TypeHorizontal ); + signature.setName ( get(stack,"_net" ) ); + signature.setLayer( get(stack,"_layer") ); + signature.setDim( Signature::HorizontalWidth , get(stack,"_width" ) ); + signature.setDim( Signature::HorizontalY , get(stack,"_y" ) ); + signature.setDim( Signature::HorizontalDxSource, get(stack,"_dxSource") ); + signature.setDim( Signature::HorizontalDxTarget, get(stack,"_dxTarget") ); + entity = masterCell->getEntity( signature ); + } else if (_subTypeName == "Pad") { + Signature signature; + signature.setType ( Signature::TypePad ); + signature.setName ( get(stack,"_net" ) ); + signature.setLayer( get(stack,"_layer") ); + Box bb = get(stack, "_boundingBox" ); + signature.setDim( Signature::PadXMin, bb.getXMin() ); + signature.setDim( Signature::PadYMin, bb.getYMin() ); + signature.setDim( Signature::PadXMax, bb.getXMax() ); + signature.setDim( Signature::PadYMax, bb.getYMax() ); + entity = masterCell->getEntity( signature ); + } + + update( stack, entity ); + } + + +} // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Tabulation.cpp b/hurricane/src/hurricane/Tabulation.cpp index 39a0ac42..c491fe0c 100644 --- a/hurricane/src/hurricane/Tabulation.cpp +++ b/hurricane/src/hurricane/Tabulation.cpp @@ -17,7 +17,8 @@ // not, see . // **************************************************************************************************** -#include "hurricane/Tabulation.h" + +#include "hurricane/Commons.h" namespace Hurricane { diff --git a/hurricane/src/hurricane/Transformation.cpp b/hurricane/src/hurricane/Transformation.cpp index fd83a29a..904779e0 100644 --- a/hurricane/src/hurricane/Transformation.cpp +++ b/hurricane/src/hurricane/Transformation.cpp @@ -255,6 +255,16 @@ Record* Transformation::_getRecord() const return record; } +void Transformation::toJson ( JsonWriter* w ) const +// ************************************************* +{ + w->startObject(); + jsonWrite( w, "@typename", "Transformation" ); + jsonWrite( w, "_tx", getTx() ); + jsonWrite( w, "_ty", getTy() ); + jsonWrite( w, "_orientation", getString( &(getOrientation().getCode()) ) ); + w->endObject(); +} // **************************************************************************************************** @@ -273,6 +283,20 @@ Transformation::Orientation::Orientation(const Orientation& orientation) { } +Transformation::Orientation::Orientation(const string& s) +// ****************************************************** +: _code(ID) +{ + if (s == "ID") _code = ID; + else if (s == "R1") _code = R1; + else if (s == "R2") _code = R2; + else if (s == "R3") _code = R3; + else if (s == "MX") _code = MX; + else if (s == "XR") _code = XR; + else if (s == "MY") _code = MY; + else if (s == "YR") _code = YR; +} + Transformation::Orientation& Transformation::Orientation::operator=(const Orientation& orientation) // ************************************************************************************************ { @@ -295,6 +319,38 @@ Record* Transformation::Orientation::_getRecord() const } +// **************************************************************************************************** +// Transformation::Orientation implementation +// **************************************************************************************************** + +JsonTransformation::JsonTransformation(unsigned long flags) +// ******************************************************** + : JsonObject(flags) +{ + add( "_tx" , typeid(int64_t) ); + add( "_ty" , typeid(int64_t) ); + add( "_orientation", typeid(string) ); +} + +string JsonTransformation::getTypeName() const +// ******************************************* +{ return "Transformation"; } + +JsonTransformation* JsonTransformation::clone(unsigned long flags) const +// ********************************************************************* +{ return new JsonTransformation ( flags ); } + +void JsonTransformation::toData(JsonStack& stack) +// ********************************************** +{ + check( stack, "JsonTransformation::toData" ); + + Transformation transf ( get(stack,"_tx") + , get(stack,"_ty") + , Transformation::Orientation(get(stack,"_orientation")) ); + + update( stack, transf ); +} } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/Vertical.cpp b/hurricane/src/hurricane/Vertical.cpp index 8a0b0948..e34b14eb 100644 --- a/hurricane/src/hurricane/Vertical.cpp +++ b/hurricane/src/hurricane/Vertical.cpp @@ -17,6 +17,8 @@ // not, see . // **************************************************************************************************** +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" #include "hurricane/Vertical.h" #include "hurricane/Layer.h" #include "hurricane/BasicLayer.h" @@ -176,6 +178,16 @@ void Vertical::translate(const DbU::Unit& dx) } } +void Vertical::_toJson(JsonWriter* writer) const +// ******************************************** +{ + Inherit::_toJson( writer ); + + jsonWrite( writer, "_x" , _x ); + jsonWrite( writer, "_dySource", _dySource ); + jsonWrite( writer, "_dyTarget", _dyTarget ); +} + string Vertical::_getString() const // ******************************** { @@ -194,6 +206,51 @@ Record* Vertical::_getRecord() const return record; } + +// **************************************************************************************************** +// JsonVertical implementation +// **************************************************************************************************** + +JsonVertical::JsonVertical(unsigned long flags) +// ******************************************** + : JsonSegment(flags) +{ + add( "_x" , typeid(uint64_t) ); + add( "_dySource", typeid(uint64_t) ); + add( "_dyTarget", typeid(uint64_t) ); +} + +string JsonVertical::getTypeName() const +// ************************************* +{ return "Vertical"; } + +JsonVertical* JsonVertical::clone(unsigned long flags) const +// ********************************************************* +{ return new JsonVertical ( flags ); } + +void JsonVertical::toData(JsonStack& stack) +// **************************************** +{ + check( stack, "JsonVertical::toData" ); + unsigned int jsonId = presetId( stack ); + + Vertical* vertical = Vertical::create + ( get(stack,".Net") + , DataBase::getDB()->getTechnology()->getLayer( get(stack,"_layer") ) + , DbU::fromDb( get(stack,"_x" ) ) + , DbU::fromDb( get(stack,"_width" ) ) + , DbU::fromDb( get(stack,"_dySource") ) + , DbU::fromDb( get(stack,"_dyTarget") ) + ); + + stack.addHookLink( vertical->getBodyHook (), jsonId, get(stack,"_bodyHook" ) ); + stack.addHookLink( vertical->getSourceHook(), jsonId, get(stack,"_sourceHook") ); + stack.addHookLink( vertical->getTargetHook(), jsonId, get(stack,"_targetHook") ); + +// Hook/Ring rebuild are done as a post-process. + update( stack, vertical ); +} + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/grenier/json/DBo.cpp b/hurricane/src/hurricane/grenier/json/DBo.cpp new file mode 100644 index 00000000..1302dc93 --- /dev/null +++ b/hurricane/src/hurricane/grenier/json/DBo.cpp @@ -0,0 +1,198 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2000-2015, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Remy Escassut | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./DBo.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/Property.h" +#include "hurricane/DBo.h" +#include "hurricane/Quark.h" +#include "hurricane/Error.h" + + +namespace Hurricane { + + +// ------------------------------------------------------------------- +// Class : "Hurricane::DBo". + + + DBo::DBo (): _propertySet() + { } + + + DBo::~DBo () + { } + + + void DBo::_postCreate () + { } + + + void DBo::_preDestroy () + { + clearProperties (); + } + + + void DBo::destroy () + { + _preDestroy(); + + delete this; + } + + + Property* DBo::getProperty ( const Name& name ) const + { + set::const_iterator iterator = _propertySet.begin(); + while ( iterator != _propertySet.end() ) { + Property* property = *iterator; + if (property->getName() == name) return property; + ++iterator; + } + return NULL; + } + + + Properties DBo::getProperties () const + { + return getCollection(_propertySet); + } + + + void DBo::put ( Property* property ) + { + if ( !property ) + throw Error("DBo::put(): Can't put property : NULL property."); + + Property* oldProperty = getProperty ( property->getName() ); + if ( property != oldProperty ) { + if ( oldProperty ) { + _propertySet.erase ( oldProperty ); + oldProperty->onReleasedBy ( this ); + } + _propertySet.insert ( property ); + property->onCapturedBy ( this ); + } + } + + + void DBo::remove ( Property* property ) + { + if ( !property ) + throw Error("DBo::remove(): Can't remove property : NULL property."); + + if ( _propertySet.find(property) != _propertySet.end() ) { + _propertySet.erase ( property ); + property->onReleasedBy ( this ); + if ( dynamic_cast(this) && _propertySet.empty() ) + destroy(); + } + } + + + void DBo::removeProperty ( const Name& name ) + { + Property* property = getProperty ( name ); + if ( property ) { + _propertySet.erase ( property ); + property->onReleasedBy ( this ); + if ( dynamic_cast(this) && _propertySet.empty() ) + destroy(); + } + } + + + void DBo::_onDestroyed ( Property* property ) + { + if ( property && ( _propertySet.find(property) != _propertySet.end() ) ) { + _propertySet.erase ( property ); + if ( dynamic_cast(this) && _propertySet.empty() ) + destroy(); + } + } + + + void DBo::clearProperties () + { + while ( !_propertySet.empty() ) { + Property* property = *_propertySet.begin(); + _propertySet.erase ( property ); + property->onReleasedBy ( this ); + } + } + + + void DBo::_toJson ( JsonWriter* writer ) const + { + // writer->key( "+propertySet" ); + // writer->startArray(); + // writer->endArray(); + } + + + void DBo::_toJsonProperties ( JsonWriter* writer ) const + { + writer->key( "+propertySet" ); + writer->startArray(); + writer->endArray(); + } + + + string DBo::_getTypeName () const + { + return "DBo"; + } + + + string DBo::_getString () const + { + return "<" + _getTypeName() + ">"; + } + + + Record* DBo::_getRecord () const + { + Record* record = new Record ( getString(this) ); + record->add ( getSlot("_propertySet", &_propertySet) ); + return record; + } + + +// ------------------------------------------------------------------- +// Class : "Hurricane::JsonDBo". + + JsonDBo::JsonDBo ( unsigned long flags ) + : JsonObject() + { + add( "+propertySet", &DBo::getProperties ); + } + + +} // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/grenier/json/DBo.h b/hurricane/src/hurricane/grenier/json/DBo.h new file mode 100644 index 00000000..01edbabd --- /dev/null +++ b/hurricane/src/hurricane/grenier/json/DBo.h @@ -0,0 +1,114 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2000-2015, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Remy Escassut | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/DBo.h" | +// +-----------------------------------------------------------------+ + + +#ifndef HURRICANE_DBO_H +#define HURRICANE_DBO_H + +#include "hurricane/DBos.h" +#include "hurricane/Name.h" +#include "hurricane/Properties.h" + + +namespace Hurricane { + + class JsonDBo; + + +// ------------------------------------------------------------------- +// Class : "Hurricane::DBo". + + class DBo { + friend class JsonDBo; + public: + virtual void destroy (); + inline set& _getPropertySet (); + void _onDestroyed ( Property* property ); + Property* getProperty ( const Name& ) const; + Properties getProperties () const; + inline bool hasProperty () const; + void put ( Property* ); + void remove ( Property* ); + void removeProperty ( const Name& ); + void clearProperties (); + virtual void _toJson ( JsonWriter* ) const; + virtual void _toJsonProperties ( JsonWriter* ) const; + virtual string _getTypeName () const; + virtual string _getString () const; + virtual Record* _getRecord () const; + + private: + mutable set _propertySet; + + protected: + DBo (); + virtual ~DBo (); + virtual void _postCreate (); + virtual void _preDestroy (); + + private: + DBo ( const DBo& ); + DBo& operator= ( const DBo& ); + }; + + +// Inline Functions. + inline set& DBo::_getPropertySet () { return _propertySet; } + inline bool DBo::hasProperty () const { return !_propertySet.empty(); } + + +// ------------------------------------------------------------------- +// Class : "Hurricane::JsonDBo". + + class JsonDBo : public JsonObject { + public: + JsonDBo ( unsigned long flags ); +}; + + +} // Hurricane namespace. + + +// inline void jsonWrite ( JsonWriter* w, const Hurricane::DBo* dbo ) +// { +// w->startObject(); +// std::string tname = dbo->_getTypeName(); +// if (w->issetFlags(JsonWriter::UsePlugReference) and (tname == "Plug")) { +// tname.insert( 0, "&" ); +// } +// jsonWrite( w, "@typename", tname ); +// dbo->_toJson( w ); +// dbo->_toJsonProperties( w ); +// w->endObject(); +// } + +INSPECTOR_P_SUPPORT(Hurricane::DBo); + +#endif // HURRICANE_DBO_H diff --git a/hurricane/src/hurricane/grenier/json/JsonReader.cpp b/hurricane/src/hurricane/grenier/json/JsonReader.cpp new file mode 100644 index 00000000..74c3b5c0 --- /dev/null +++ b/hurricane/src/hurricane/grenier/json/JsonReader.cpp @@ -0,0 +1,650 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2015-2015, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./JsonReader.cpp" | +// +-----------------------------------------------------------------+ + + +#include "rapidjson/filereadstream.h" +#include "rapidjson/reader.h" +// Needed for registering. May be deleted later. +#include "hurricane/DebugSession.h" +#include "hurricane/Warning.h" +#include "hurricane/JsonReader.h" +#include "hurricane/Cell.h" +#include "hurricane/Net.h" +#include "hurricane/Instance.h" +#include "hurricane/RoutingPad.h" +#include "hurricane/Contact.h" +#include "hurricane/Vertical.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Pad.h" + + +namespace { + + using namespace std; + using namespace rapidjson; + using namespace Hurricane; + + +// ------------------------------------------------------------------- +// Struct : "HurricaneHandler". + + class HurricaneHandler { + public: + HurricaneHandler ( JsonStack& ); + public: + bool Null (); + bool Bool ( bool ); + bool Int ( int ); + bool Int64 ( int64_t ); + bool Uint ( unsigned int ); + bool Uint64 ( uint64_t ); + bool Double ( double ); + bool String ( const char*, SizeType, bool copy ); + bool Key ( const char*, SizeType, bool copy ); + bool StartObject (); + bool EndObject ( SizeType ); + bool StartArray (); + bool EndArray ( SizeType ); + bool doCallToData () const; + private: + enum Flags { TypenameKey = (1<<0) + , ArrayMode = (1<<2) + , SkipObject = (1<<3) + , SkipArray = (1<<4) + , SkipMask = SkipObject | SkipArray + }; + private: + unsigned long _state; + string _key; + string _objectName; + vector _objects; + JsonStack& _stack; + }; + + + HurricaneHandler::HurricaneHandler ( JsonStack& stack ) + : _state (0) + , _key () + , _objectName() + , _objects () + , _stack (stack) + { } + + + bool HurricaneHandler::doCallToData () const + { return not _objects.empty() and _objects.back() and not _objects.back()->isCreated(); } + + + bool HurricaneHandler::Null () + { + //if (not _objects.empty()) ltrace(59) << "null _objects.back(): " << _objects.back() << endl; + + if (_state & SkipMask) return true; + _stack.push_back( _key, NULL ); + return true; + } + + + bool HurricaneHandler::Bool ( bool v ) + { + if (_state & SkipMask) return true; + _stack.push_back( _key, v ); + return true; + } + + + bool HurricaneHandler::Int ( int v ) + { + if (_state & SkipMask) return true; + _stack.push_back( _key, v ); + return true; + } + + + bool HurricaneHandler::Int64 ( int64_t v ) + { + if (_state & SkipMask) return true; + _stack.push_back( _key, v ); + return true; + } + + + bool HurricaneHandler::Uint ( unsigned int v ) + { + if (_state & SkipMask) return true; + _stack.push_back( _key, v ); + return true; + } + + + bool HurricaneHandler::Uint64 ( uint64_t v ) + { + if (_state & SkipMask) return true; + _stack.push_back( _key, v ); + return true; + } + + + bool HurricaneHandler::Double ( double v ) + { + if (_state & SkipMask) return true; + _stack.push_back( _key, v ); + return true; + } + + + bool HurricaneHandler::String ( const char* value, SizeType, bool copy ) + { + if (_state & SkipMask) return true; + if (_state & TypenameKey) { + _state &= ~TypenameKey; + + JsonObject* object = JsonTypes::find( value ); + _objects[_objects.size()-1] = object->clone(); + + if (not object) { + cerr << Warning("JsonReader::parse(): Do not know how to parse type %s.", value ) << endl; + _state |= SkipObject; + } else { + _objects[_objects.size()-1]->setName( _objectName ); + } + + ltrace(51) << "HurricaneHandler::String() [key/typename] " << value << endl; + return true; + } + + _stack.push_back( _key, value ); + return true; + } + + + bool HurricaneHandler::Key ( const char* key, SizeType, bool copy ) + { + _key = key; + if (_state & SkipMask) { + _key.clear(); + return true; + } + + if (_state & TypenameKey) { + if (_key != "@typename") { + _state |= SkipObject; + _key.clear(); + } + return true; + } + + //ltrace(51) << "HurricaneHandler::Key() key:" << _key << " _objects.size():" << _objects.size() << endl; + + if (_objects.back()) { + if ( doCallToData() and not _key.empty() and (_key[0] != '_') ) { + // The key is no longer a simple attribute of the object. + // Triggers it's creation in the Json stack. + ltrace(51) << "HurricaneHandler::key() Calling " + << _objects.back()->getTypeName() << "::toData(JsonStack&)." << endl; + _objects.back()->toData( _stack ); + } + } + + return true; + } + + + bool HurricaneHandler::StartObject () + { + ltrace(50) << "Hurricane::StartObject()" << endl; + ltracein(50); + + _state |= TypenameKey; + // if (doCallToData()) { + // ltrace(51) << "Calling " << _objects.back()->getTypeName() << "::toData(JsonStack&)." << endl; + // _objects.back()->toData( _stack ); + // } + _objectName = (_key == ".Array") ? "" : _key; + _objects.push_back( NULL ); + ltrace(51) << "_objects.push_back(NULL), size():" << _objects.size() << "." << endl; + + ltracein(50); + return true; + } + + + bool HurricaneHandler::EndObject ( SizeType ) + { + ltraceout(50,2); + ltrace(50) << "HurricaneHandler::EndObject()" << endl; + ltracein(50); + + _objectName.clear(); + if (_state & SkipObject) { + _state &= ~SkipObject; + } else { + if (doCallToData()) { + ltrace(51) << "Calling " << _objects.back()->getTypeName() << "::toData(JsonStack&)." << endl; + _objects.back()->toData( _stack ); + } + if (_objects.size() > 1) { + ltrace(51) << "_objects.pop_back(), size():" << _objects.size() << "." << endl; + delete _objects.back(); + _objects.pop_back(); + } + if (_stack.size() > 1) { + if (_stack[-1].first[0] != '_') _stack.pop_back(); + } + } + ltraceout(50); + return true; + } + + + bool HurricaneHandler::StartArray() + { + ltrace(50) << "HurricaneHandler::StartArray() key:\"" << _key << "\"." << endl; + ltracein(50); + + _objectName.clear(); + if (_key.empty()) { _state |= SkipArray; return true; } + if (_key[0] != '+') { + cerr << Warning("JsonReader::parse(): Array attributes must start by \'+\' %s.", _key.c_str() ) << endl; + _state |= SkipArray; + return true; + } + + _state |= ArrayMode; + _key = ".Array"; + + return true; + } + + bool HurricaneHandler::EndArray ( SizeType ) + { + ltraceout(50); + ltrace(50) << "HurricaneHandler::EndArray()" << endl; + ltracein(50); + + _state &= ~(ArrayMode | SkipArray); + _key.clear(); + + ltraceout(50); + return true; + } + + +// ------------------------------------------------------------------- +// Class : "JsonReader". + + class JsonReader { + public: + enum Mode { CellMode = (1<<0) }; + public: + JsonReader (); + ~JsonReader (); + JsonReader* setFlags ( unsigned long mask ); + JsonReader* resetFlags ( unsigned long mask ); + bool issetFlags ( unsigned long mask ) const; + const JsonStack& getStack () const; + void parse ( std::string fileName, unsigned int flags ); + void close (); + private: + JsonReader ( const JsonReader& ); + JsonReader& operator= ( const JsonReader& ) const; + private: + unsigned long _flags; + size_t _bufferSize; + char* _buffer; + FILE* _file; + FileReadStream* _stream; + JsonStack _stack; + Reader _reader; + HurricaneHandler _handler; + }; + + + JsonReader::JsonReader () + : _flags (0) + , _bufferSize(65536) + , _buffer (new char [_bufferSize]) + , _file (NULL) + , _stream (NULL) + , _stack () + , _reader () + , _handler (_stack) + { + } + + + JsonReader::~JsonReader () + { + close(); + delete _buffer; + } + + + void JsonReader::close () + { + if (_stream) { delete _stream; _stream = NULL; } + if (_file ) { fclose(_file); _file = NULL; } + } + + + const JsonStack& JsonReader::getStack () const + { return _stack; } + + + void JsonReader::parse ( string fileName, unsigned int flags ) + { + close(); + + DebugSession::open( 50 ); + + fileName += ".json"; + _file = fopen( fileName.c_str(), "r" ); + cerr << "_file:" << _file << ", _buffer:" << (void*)_buffer << endl; + _stream = new FileReadStream ( _file, _buffer, _bufferSize ); + + _reader.Parse( *_stream, _handler ); + _stack.print( cerr ); + + DebugSession::close(); + close(); + } + + +} // local namespace. + + +namespace Hurricane { + + using namespace std; + + +// ------------------------------------------------------------------- +// Class : "JsonAttribute". + + JsonAttribute::~JsonAttribute () + { } + + +// ------------------------------------------------------------------- +// Class : "JsonStacked". + + JsonStacked::~JsonStacked () + { } + + + type_index JsonStacked::tid () const + { return typeid(JsonStacked); } + + + void JsonStacked::toJson ( JsonWriter*, boost::any object ) const + { + cerr << Error("JsonStacked::toJson() is a dummy method that should never be called.") << endl; + } + + + JsonStacked* JsonStacked::clone () const + { return new JsonStacked( *this ); } + + +// ------------------------------------------------------------------- +// Class : "JsonObject". + + JsonObject::JsonObject () + : _name () + , _stackeds () + , _attributes () + , _collections() + , _object () + { } + + + JsonObject::JsonObject ( const JsonObject& other ) + : _name (other._name) + , _stackeds () + , _attributes () + , _collections() + , _object () + { + for ( JsonAttribute* attribute : other._stackeds ) _stackeds.push_back( attribute->clone() ); + for ( JsonAttribute* attribute : other._attributes ) _stackeds.push_back( attribute->clone() ); + for ( JsonAttribute* attribute : other._collections ) _stackeds.push_back( attribute->clone() ); + } + + + JsonObject::~JsonObject () + { clear(); } + + + bool JsonObject::isJsonObject () const + { return _flags & IsJsonObject; } + + + void JsonObject::remove ( const std::string& key ) + { + if (key.empty()) { + cerr << Error( "JsonObject::remove(): Attempt to remove attribute with an empty name, ignored." ) << endl; + return; + } + + switch ( key[0] ) { + case '.': + for ( auto it = _stackeds.begin() ; it != _stackeds.end() ; ++it ) + if (key == (*it)->key()) { delete (*it); _stackeds.erase(it); break; } + break; + case '_': + for ( auto it = _attributes.begin() ; it != _attributes.end() ; ++it ) + if (key == (*it)->key()) { delete (*it); _attributes.erase(it); break; } + break; + case '+': + for ( auto it = _collections.begin() ; it != _collections.end() ; ++it ) + if (key == (*it)->key()) { delete (*it); _collections.erase(it); break; } + break; + } + } + + + bool JsonObject::has ( const std::string& key ) const + { + if (key.empty()) return false; + switch ( key[0] ) { + case '.': + for ( size_t i=0 ; i<_stackeds.size() ; ++i ) + if (key == _stackeds[i]->key()) return true; + break; + case '_': + for ( size_t i=0 ; i<_attributes.size() ; ++i ) + if (key == _attributes[i]->key()) return true; + break; + case '+': + for ( size_t i=0 ; i<_collections.size() ; ++i ) + if (key == _collections[i]->key()) return true; + break; + } + return false; + } + + + bool JsonObject::check ( JsonStack& stack, string fname ) const + { + for ( size_t i=0 ; i<_stackeds.size() ; ++i ) { + if (not stack.rhas(_stackeds[i]->key())) { + cerr << Error( "%s(): Stack is missing context element with key \"%s\"" + , fname.c_str(), _stackeds[i]->key().c_str() ) << endl; + return false; + } + } + for ( size_t i=0 ; i<_attributes.size() ; ++i ) { + if (not stack.rhas(_attributes[i]->key())) { + cerr << Error( "%s(): Stack is missing attribute element with key \"%s\"" + , fname.c_str(), _attributes[i]->key().c_str() ) << endl; + return false; + } + } + return true; + } + + + void JsonObject::toData ( JsonStack& ) + { } + + + void JsonObject::print ( ostream& o ) const + { + o << tab << "JsonObject for type: " << getTypeName() << endl; + for ( size_t i=0 ; i<_stackeds.size() ; ++i ) + o << tab << "key:" << left << setw(20) << _stackeds[i]->key() + << " type:" << _stackeds[i]->tid().name() << endl; + + for ( size_t i=0 ; i<_attributes.size() ; ++i ) + o << tab << "key:" << left << setw(20) << _attributes[i]->key() + << " type:" << _attributes[i]->tid().name() << endl; + + for ( size_t i=0 ; i<_collections.size() ; ++i ) + o << tab << "key:" << left << setw(20) << _collections[i]->key() + << " type:" << _collections[i]->tid().name() << endl; + } + + + JsonKey::JsonKey ( const string& key ) + : JsonObject() + , _key (key) + { } + + + string JsonKey::getTypeName () const + { return _key; } + + + JsonKey* JsonKey::clone () const + { return new JsonKey ( *this ); } + + +// ------------------------------------------------------------------- +// Class : "JsonTypes". + + JsonTypes* JsonTypes::_jsonTypes = NULL; + + + JsonTypes::JsonTypes () + : _jsonObjects() + { } + + + JsonTypes::~JsonTypes () + { + for ( JsonObject* object : _jsonObjects ) delete object; + } + + + void JsonTypes::_registerType ( JsonObject* object ) + { + if (_find(object->getTypeName())) { + throw Error( "JsonTypes::_registerType(): Attempt to register <%s> twice.", object->getTypeName().c_str() ); + } + _jsonObjects.insert( object ); + } + + + JsonObject* JsonTypes::_find ( const string& tname ) + { + JsonKey key( tname ); + set::iterator it = _jsonObjects.find( &key ); + if (it != _jsonObjects.end()) return (*it); + return NULL; + } + + + void JsonTypes::registerType ( JsonObject* object ) + { + if (not _jsonTypes) initialize(); + _jsonTypes->_registerType( object ); + } + + + JsonObject* JsonTypes::find ( const string& tname ) + { + if (not _jsonTypes) initialize(); + return _jsonTypes->_find( tname ); + } + + + void JsonTypes::initialize () + { + if (_jsonTypes) return; + + _jsonTypes = new JsonTypes (); + _jsonTypes->_registerType( new JsonPoint (0) ); + _jsonTypes->_registerType( new JsonBox (0) ); + _jsonTypes->_registerType( new JsonTransformation(0) ); + _jsonTypes->_registerType( new JsonCell (0) ); + _jsonTypes->_registerType( new JsonNet (0) ); + _jsonTypes->_registerType( new JsonPlugRef (0) ); + _jsonTypes->_registerType( new JsonRoutingPad (0) ); + _jsonTypes->_registerType( new JsonContact (0) ); + _jsonTypes->_registerType( new JsonVertical (0) ); + _jsonTypes->_registerType( new JsonHorizontal (0) ); + _jsonTypes->_registerType( new JsonPad (0) ); + _jsonTypes->_registerType( new JsonInstance (0) ); + _jsonTypes->_registerType( new JsonPlug (0) ); + } + + +// ------------------------------------------------------------------- +// Class : "JsonStack". + + void JsonStack::addEntity ( unsigned int jsonId, Entity* entity ) + { _entities.insert( std::make_pair(jsonId,entity) ); } + + + void JsonStack::print ( ostream& o ) const + { + o << tab << "JsonStack::print() Stack contains " << _stack.size() << " elements." << endl; + for ( size_t i=0 ; i<_stack.size() ; ++i ) { + o << "[" << right << setw(2) << i << "] key: \"" << left << setw(20) << _stack[i].first + << "\", type: \"" << demangle(_stack[i].second.type()) << "\"." << endl; + } + } + + +// ------------------------------------------------------------------- +// Function : Json Cell parser. + + Cell* jsonCellParse ( string filename ) + { + JsonReader reader; + reader.parse( filename, JsonReader::CellMode ); + + const JsonStack& stack = reader.getStack(); + if (stack.rhas(".Cell")) return stack.as(".Cell"); + return NULL; + } + + +} // Hurricane namespace. diff --git a/hurricane/src/hurricane/grenier/json/JsonReader.h b/hurricane/src/hurricane/grenier/json/JsonReader.h new file mode 100644 index 00000000..79e2d5f0 --- /dev/null +++ b/hurricane/src/hurricane/grenier/json/JsonReader.h @@ -0,0 +1,790 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2015-2015, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/JsonReader.h" | +// +-----------------------------------------------------------------+ + + +#ifndef HURRICANE_JSON_READER_H +#define HURRICANE_JSON_READER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Hurricane { + + class Entity; + class Cell; + +// ------------------------------------------------------------------- +// Class : "JsonObject". + + class JsonStack; + class JsonArray { }; + + +// ------------------------------------------------------------------- +// Class : "JsonAttribute". + + class JsonAttribute { + public: + inline JsonAttribute ( const std::string& key, unsigned long flags ); + virtual ~JsonAttribute (); + inline std::string key () const; + virtual std::type_index tid () const = 0; + virtual void toJson ( JsonWriter*, boost::any object ) const = 0; + virtual JsonAttribute* clone () const = 0; + inline void setFlags ( unsigned long mask ); + inline void resetFlags ( unsigned long mask ); + inline bool issetFlags ( unsigned long mask ) const; + private: + std::string _key; + unsigned long _flags; + }; + + inline JsonAttribute::JsonAttribute ( const std::string& key, unsigned long flags ): _key(key), _flags(flags) { } + inline std::string JsonAttribute::key () const { return _key; } + inline void JsonAttribute::setFlags ( unsigned long mask ) { _flags |= mask; } + inline void JsonAttribute::resetFlags ( unsigned long mask ) { _flags &= ~mask; } + inline bool JsonAttribute::issetFlags ( unsigned long mask ) const { return _flags & mask; } + + +// ------------------------------------------------------------------- +// Class : "JsonStacked". + + class JsonStacked : public JsonAttribute { + public: + inline JsonStacked ( const std::string& key ); + virtual ~JsonStacked (); + virtual std::type_index tid () const; + virtual void toJson ( JsonWriter*, boost::any object ) const; + virtual JsonStacked* clone () const; + }; + + inline JsonStacked::JsonStacked ( const std::string& key ): JsonAttribute(key,0) { } + + +// ------------------------------------------------------------------- +// Class : "JsonAnyAttribute". + + template + class JsonAnyAttribute : public JsonAttribute { + public: + JsonAnyAttribute ( const std::string& key + , unsigned long flags + , T C::* attr + ); + virtual ~JsonAnyAttribute (); + virtual std::type_index tid () const; + virtual JsonAnyAttribute* clone () const; + virtual void toJson ( JsonWriter*, boost::any object ) const; + private: + T C::* _attribute; + }; + + + template + JsonAnyAttribute::JsonAnyAttribute ( const std::string& key + , unsigned long flags + , T C::* attr + ) + : JsonAttribute(key,flags) + , _attribute (attr) + { } + + template + JsonAnyAttribute::~JsonAnyAttribute () + { } + + template + std::type_index JsonAnyAttribute::tid () + { return typeid(T); } + + template + JsonAnyAttribute* JsonAnyAttribute::clone () const + { return new JsonAnyAttribute( *this ); } + + +// ------------------------------------------------------------------- +// Class : "JsonStrAttribute". + + template + class JsonStrAttribute : public JsonAttribute { + public: + JsonStrAttribute ( const std::string& key + , unsigned long flags + , T C::* attr + ); + virtual ~JsonStrAttribute (); + virtual std::type_index tid () const; + virtual JsonStrAttribute* clone () const; + virtual void toJson ( JsonWriter*, boost::any object ) const; + private: + T C::* _attribute; + }; + + + template + JsonStrAttribute::JsonStrAttribute ( const std::string& key + , unsigned long flags + , T C::* attr + ) + : JsonAttribute(key,flags) + , _attribute (attr) + { } + + template + JsonStrAttribute::~JsonStrAttribute () + { } + + template + std::type_index JsonStrAttribute::tid () + { return typeid(T); } + + template + JsonStrAttribute* JsonStrAttribute::clone () const + { return new JsonStrAttribute( *this ); } + + template + void JsonStrAttribute::toJson ( JsonWriter* w, boost::any object ) const + { jsonWrite( w, key(), getString( boost::any_cast(object)->*_attribute ) ); } + + +// ------------------------------------------------------------------- +// Class : "JsonFtrrAttribute". + + template + class JsonFtrrAttribute : public JsonAttribute { + public: + JsonFtrrAttribute ( const std::string& key + , unsigned long flags + , T C::* attr + , std::function tr + ); + virtual ~JsonFtrrAttribute (); + virtual std::type_index tid () const; + virtual JsonFtrrAttribute* clone () const; + virtual void toJson ( JsonWriter*, boost::any object ) const; + private: + T C::* _attribute; + std::function _tr; + }; + + + template + JsonFtrrAttribute::JsonFtrrAttribute ( const std::string& key + , unsigned long flags + , T C::* attr + , std::function tr + ) + : JsonAttribute(key,flags) + , _attribute (attr) + , _tr (tr) + { } + + template + JsonFtrrAttribute::~JsonFtrrAttribute () + { } + + template + std::type_index JsonFtrrAttribute::tid () + { return typeid(T); } + + template + JsonFtrrAttribute* JsonFtrrAttribute::clone () const + { return new JsonFtrrAttribute( *this ); } + + template + void JsonFtrrAttribute::toJson ( JsonWriter* w, boost::any object ) const + { jsonWrite( w, key(), _tr( boost::any_cast(object)->*_attribute ) ); } + + +// ------------------------------------------------------------------- +// Class : "JsonFtrpAttribute". + + template + class JsonFtrpAttribute : public JsonAttribute { + public: + JsonFtrpAttribute ( const std::string& key + , unsigned long flags + , T* C::* attr + , std::function tr + ); + virtual ~JsonFtrpAttribute (); + virtual std::type_index tid () const; + virtual JsonFtrpAttribute* clone () const; + virtual void toJson ( JsonWriter*, boost::any object ) const; + private: + T* C::* _attribute; + std::function _tr; + }; + + + template + JsonFtrpAttribute::JsonFtrpAttribute ( const std::string& key + , unsigned long flags + , T* C::* attr + , std::function tr + ) + : JsonAttribute(key,flags) + , _attribute (attr) + , _tr (tr) + { } + + template + JsonFtrpAttribute::~JsonFtrpAttribute () + { } + + template + std::type_index JsonFtrpAttribute::tid () + { return typeid(T); } + + template + JsonFtrpAttribute* JsonFtrpAttribute::clone () const + { return new JsonFtrpAttribute( *this ); } + + template + void JsonFtrpAttribute::toJson ( JsonWriter* w, boost::any object ) const + { jsonWrite( w, key(), _tr( boost::any_cast(object)->*_attribute ) ); } + + +// ------------------------------------------------------------------- +// Class : "JsonMethAttribute". + + template + class JsonMethAttribute : public JsonAttribute { + public: + JsonMethAttribute ( const std::string& key + , unsigned long flags + , R (C::* meth )() const + ); + virtual ~JsonMethAttribute (); + virtual std::type_index tid () const; + virtual JsonMethAttribute* clone () const; + virtual void toJson ( JsonWriter*, boost::any object ) const; + private: + R (C::* _meth)() const; + }; + + + template + JsonMethAttribute::JsonMethAttribute ( const std::string& key + , unsigned long flags + , R (C::* meth)() const + ) + : JsonAttribute(key,flags) + , _meth (meth) + { } + + template + JsonMethAttribute::~JsonMethAttribute () + { } + + template + std::type_index JsonMethAttribute::tid () + { return typeid(R); } + + template + JsonMethAttribute* JsonMethAttribute::clone () const + { return new JsonMethAttribute( *this ); } + + template + void JsonMethAttribute::toJson ( JsonWriter* w, boost::any object ) const + { jsonWrite( w, key(), (boost::any_cast(object)->*_meth)() ); } + + +// ------------------------------------------------------------------- +// Class : "JsonAnyAttribute". + +#define JSON_POD_ATTRIBUTE(pod_t) \ + template \ + class JsonAnyAttribute : public JsonAttribute { \ + public: \ + JsonAnyAttribute ( const std::string& key \ + , unsigned long flags \ + , pod_t C::* attr \ + ); \ + virtual ~JsonAnyAttribute (); \ + virtual std::type_index tid () const; \ + virtual JsonAnyAttribute* clone () const; \ + virtual void toJson ( JsonWriter*, boost::any object ) const; \ + private: \ + pod_t C::* _attribute; \ + }; \ + \ + \ + template \ + JsonAnyAttribute::JsonAnyAttribute ( const std::string& key \ + , unsigned long flags \ + , pod_t C::* attr \ + ) \ + : JsonAttribute(key,flags) \ + , _attribute (attr) \ + { } \ + \ + template \ + JsonAnyAttribute::~JsonAnyAttribute () \ + { } \ + \ + template \ + std::type_index JsonMethAttribute::tid () \ + { return typeid(pod_t); } \ + \ + template \ + JsonAnyAttribute* JsonAnyAttribute::clone () const \ + { return new JsonAnyAttribute( *this ); } \ + \ + template \ + void JsonAnyAttribute::toJson ( JsonWriter* w, boost::any object ) const \ + { jsonWrite( w, key(), boost::any_cast(object)->*_attribute ); } + + +// Build a specialized JsonAnyAttribute for all POD types. + JSON_POD_ATTRIBUTE(bool) + JSON_POD_ATTRIBUTE(int) + JSON_POD_ATTRIBUTE(long) + JSON_POD_ATTRIBUTE(unsigned int) + JSON_POD_ATTRIBUTE(unsigned long) + + +// ------------------------------------------------------------------- +// Class : "JsonObject". + + class JsonObject { + public: + enum Flags { IsJsonObject = (1<<0) + , UsePlugReference = (1<<1) + , UseReference = (1<<3) + }; + public: + JsonObject (); + JsonObject ( const JsonObject& ); + virtual ~JsonObject (); + virtual std::string getTypeName () const = 0; + inline std::string getStackName () const; + virtual bool isJsonObject () const; + bool check ( JsonStack&, string fname ) const; + void print ( std::ostream& ) const; + bool has ( const std::string& key ) const; + template + inline T get ( JsonStack&, const std::string& key ) const; + void add ( const std::string& key, unsigned long flags ); + template + void add ( const std::string& key, T C::* attr, unsigned long flags ); + template + void add ( const std::string& key, T C::* attr, R(*tr)(T&), unsigned long flags ); + template + void add ( const std::string& key, T* C::* attr, R(*tr)(T*), unsigned long flags ); + template + void add ( const std::string& key, R(C::* meth)() const, unsigned long flags ); + template + void addS ( const std::string& key, T C::* attr, unsigned long flags ); + void remove ( const std::string& key ); + template + T access ( const std::string& key ); + inline void clear (); + inline std::string getName () const; + inline void setName ( const string& ); + template inline T& getObject () const; + template inline void setObject ( T& ) ; + inline bool isCreated () const; + virtual JsonObject* clone () const = 0; + template void toJson ( JsonWriter*, C* object ) const; + virtual void toData ( JsonStack& ); + template inline void update ( JsonStack&, T ); + inline void setFlags ( unsigned long mask ); + inline void resetFlags ( unsigned long mask ); + inline bool issetFlags ( unsigned long mask ) const; + protected: + inline bool _checkKey ( const std::string& key ) const; + protected: + unsigned long _flags; + std::string _name; + std::vector _stackeds; + std::vector _attributes; + std::vector _collections; + boost::any _object; + }; + + + inline bool JsonObject::isCreated () const { return not _object.empty(); } + inline std::string JsonObject::getName () const { return _name; } + inline void JsonObject::setName ( const string& name ) { _name=name; } + inline void JsonObject::setFlags ( unsigned long mask ) { _flags |= mask; } + inline void JsonObject::resetFlags ( unsigned long mask ) { _flags &= ~mask; } + inline bool JsonObject::issetFlags ( unsigned long mask ) const { return _flags & mask; } + + inline std::string JsonObject::getStackName () const + { return (_name.empty()) ? std::string(".")+getTypeName(): _name; } + + template inline T& JsonObject::getObject () const + { return boost::any_cast(_object); } + + template inline void JsonObject::setObject ( T& t ) + { _object = t; } + + + bool JsonObject::checkKey ( const std::string& key ) const + { + if (key.empty()) { + cerr << "[ERROR] JsonObject::add(): Attempt to add attribute with an empty name, ignored." + << endl; + return false; + } + if (has(key)) { + cerr << "[ERROR] JsonObject::add(): Attempt to add attribute \"" << key << "\" twice, cancelled." + << endl; + return false; + } + return true; + } + + + void JsonObject::add ( const std::string& key ) + { + if ( _checkKey(key) and (key[0] == '.') ) { + _stackeds.push_back( new JsonStacked(key) ); + return; + } + cerr << "[ERROR] JsonObject::add(): Stack requirement key \"" << key + << "\" do not follow naming convention, cancelled." << endl; + } + + + template + void JsonObject::add( const std::string& key, T C::* attr, unsigned long flags ) + { + if (not _checkKey(key)) return; + switch ( key[0] ) { + case '_': _attributes.push_back( new JsonAnyAttribute(key,flags,attr) ); + case '+': _attributes.push_back( new JsonAnyAttribute(key,flags,attr) ); + return; + } + cerr << "[ERROR] JsonObject::add(): Key name \"" << key + << "\" do not follow naming convention, cancelled." << endl; + } + + + template + void JsonObject::add( const std::string& key, T C::* attr, R(*tr)(T&), unsigned long flags ) + { + if (not _checkKey(key)) return; + switch ( key[0] ) { + case '_': _attributes.push_back( new JsonFtrrAttribute(key,flags,attr,std::function(tr)) ); + case '+': _attributes.push_back( new JsonFtrrAttribute(key,flags,attr,std::function(tr)) ); + return; + } + cerr << "[ERROR] JsonObject::add(): Key name \"" << key + << "\" do not follow naming convention, cancelled." << endl; + } + + + template + void JsonObject::add( const std::string& key, T* C::* attr, R(*tr)(T*), unsigned long flags ) + { + if (not _checkKey(key)) return; + switch ( key[0] ) { + case '_': _attributes.push_back( new JsonFtrpAttribute(key,flags,attr,std::function(tr)) ); + case '+': _attributes.push_back( new JsonFtrpAttribute(key,flags,attr,std::function(tr)) ); + return; + } + cerr << "[ERROR] JsonObject::add(): Key name \"" << key + << "\" do not follow naming convention, cancelled." << endl; + } + + + template + void JsonObject::add( const std::string& key, R(C::*meth)() const, unsigned long flags ) + { + if (not _checkKey(key)) return; + switch ( key[0] ) { + case '_': _attributes.push_back( new JsonMethAttribute(key,flags,meth) ); + case '+': _attributes.push_back( new JsonMethAttribute(key,flags,meth) ); + return; + } + cerr << "[ERROR] JsonObject::add(): Key name \"" << key + << "\" do not follow naming convention, cancelled." << endl; + } + + + template + void JsonObject::addS( const std::string& key, T C::* attr, unsigned int flags ) + { + if (not _checkKey(key)) return; + switch ( key[0] ) { + case '_': _attributes.push_back( new JsonStrAttribute(key,flags,attr) ); + return; + } + cerr << "[ERROR] JsonObject::addS(): Key name \"" << key + << "\" do not follow naming convention, cancelled." << endl; + } + + + template void JsonObject::toJson ( JsonWriter* w, C* object ) const + { + if (isJsonObject()) { + w->startObject(); + jsonWrite( w, "@typename", getTypeName() ); + for ( JsonAttribute* attribute : _attributes ) attribute ->toJson( w, object ); + for ( JsonAttribute* collection : _collections ) collection->toJson( w, object ); + w->endObject(); + } + } + + + inline void JsonObject::clear () + { + for ( JsonAttribute* attribute : _stackeds ) delete attribute; + for ( JsonAttribute* attribute : _attributes ) delete attribute; + for ( JsonAttribute* attribute : _collections ) delete attribute; + + _stackeds .clear(); + _attributes .clear(); + _collections.clear(); + } + + + class JsonKey : public JsonObject { + public: + inline JsonKey ( const std::string& ); + virtual std::string getTypeName () const; + virtual JsonKey* clone () const; + private: + std::string _key; + }; + + +} // Hurricane namespace. + + +namespace std { + + template<> + struct less { + inline bool operator() ( const Hurricane::JsonObject* lhs, const Hurricane::JsonObject* rhs ) + { return lhs->getTypeName() < rhs->getTypeName(); } + }; + +} // std namespace. + + +namespace Hurricane { + +// ------------------------------------------------------------------- +// Class : "JsonTypes". + + class JsonTypes { + public: + static void initialize (); + static void registerType ( JsonObject* ); + static JsonObject* find ( const std::string& tname ); + private: + JsonTypes (); + ~JsonTypes (); + JsonTypes ( const JsonTypes& ); + void _registerType ( JsonObject* ); + JsonObject* _find ( const std::string& tname ); + private: + static JsonTypes* _jsonTypes; + std::set _jsonObjects; + }; + + +// ------------------------------------------------------------------- +// Class : "JsonStack". + + class JsonStack { + public: + typedef std::pair Element; + public: + inline JsonStack (); + inline size_t size () const; + template inline void push_back ( const std::string&, T ); + inline void pop_back ( size_t count=1 ); + inline int rhas ( const std::string& ) const; + template inline T as ( const std::string& ) const; + template inline T as ( int ) const; + template inline T getEntity ( unsigned int ) const; + void addEntity ( unsigned int jsonId, Entity* ); + void print ( std::ostream& ) const; + inline JsonStack* setFlags ( unsigned long mask ); + inline JsonStack* resetFlags ( unsigned long mask ); + inline bool issetFlags ( unsigned long mask ) const; + inline const Element& operator[] ( int index ) const; + private: + unsigned long _flags; + vector _stack; + std::map _entities; + }; + + + inline JsonStack::JsonStack () + : _flags(0), _stack(), _entities() + { } + + template inline void JsonStack::push_back ( const std::string& key, T t ) { + ltrace(51) << "JsonStack::push_back() key:" << key << " t:" << t + << " (" << demangle(typeid(T)) << ")." << endl; + _stack.push_back(std::make_pair(key,boost::any(t))); + } + + inline void JsonStack::pop_back ( size_t count ) + { while (count--) { + if (_stack.empty()) { + std::cerr << "[ERROR] JsonStack::pop_back(): Stack is empty, but " + << (count+1) << " elements remains to pop." << std::endl; + break; + } + ltrace(51) << "| _stack.pop_back() " << _stack.back().first << endl; + _stack.pop_back(); + } + } + + inline const JsonStack::Element& JsonStack::operator[] ( int index ) const + { + if (index < 0) return _stack[_stack.size()+index]; + return _stack[index]; + } + + inline int JsonStack::rhas ( const std::string& key ) const + { + if (_stack.empty()) return 0; + + int i = _stack.size()-1; + do { + if (_stack[i].first == key) { + ltrace(51) << "JsonStack::rhas(): key \"" << key << "\" found at index:" + << (i-(int)_stack.size()) << " (i:" << i << ")." << endl; + return i-(int)_stack.size(); + } + if (i == 0) break; + --i; + } while ( true ); + + ltrace(51) << "JsonStack::rhas(): key \"" << key << "\" not found (returning index: 0)." << endl; + return 0; + } + + template inline T JsonStack::as ( const std::string& key ) const + { + if (not _stack.empty()) { + int i = _stack.size()-1; + do { + if (_stack[i].first == key) { + ltrace(51) << "JsonStack::as() k:" << key + << " t:" << _stack[i].second.type().name() << std::endl; + return boost::any_cast( _stack[i].second ); + } + if (i == 0) break; + --i; + } while ( true ); + + std::cerr << "[ERROR] JsonStack::as(key): No element with key \"" + << key << "\" in stack." << std::endl; + } else { + std::cerr << "[ERROR] JsonStack::as(key): Stack is empty while searching for key \"" + << key << "\"." << std::endl; + } + + return T(); + } + + template inline T JsonStack::as ( int index ) const + { + size_t i = (index >= 0) ? index : (_stack.size()+index); + return boost::any_cast( _stack[i].second ); + } + + template inline T JsonStack::getEntity ( unsigned int id ) const { + std::map::const_iterator it = _entities.find(id); + if (it == _entities.end()) return NULL; + return dynamic_cast((*it).second); + } + + inline size_t JsonStack::size () const { return _stack.size(); } + inline JsonStack* JsonStack::setFlags ( unsigned long mask ) { _flags |= mask; return this; } + inline JsonStack* JsonStack::resetFlags ( unsigned long mask ) { _flags &= ~mask; return this; } + inline bool JsonStack::issetFlags ( unsigned long mask ) const { return _flags & mask; } + + + template + T JsonObject::get ( JsonStack& stack, const std::string& key ) const + { + int index = stack.rhas(key); + if (index == 0) return T();; + + return stack.as( index ); + } + + template inline void JsonObject::update ( JsonStack& stack, T hobject ) + { + stack.pop_back( _attributes.size() ); + stack.push_back( getStackName(), hobject ); + setObject( hobject ); + } + + +// ------------------------------------------------------------------- +// Function : Json Cell parser. + + Cell* jsonCellParse ( std::string filename ); + + +} // Hurricane namespace. + + +template +inline void jsonWrite ( JsonWriter* w, const std::string& key, const C* object, unsigned long flags ) +{ + w->key( key ); + Hurricane::JsonObject* jobject = C::getJsonObject(flags); + jobject->toJson( w, object ); + delete jobject; +} + + +namespace Hurricane { + +// Delayed "void JsonAnyAttribute::toJson()" template definition, because +// it needs the jsonWrite<> template specialisation for "const T*", which can +// be only declared after "JsonObject". + + template + void JsonAnyAttribute::toJson ( JsonWriter* w, boost::any object ) const + { jsonWrite( w, key(), &(boost::any_cast(object)->*_attribute) ); } + +} // Hurricane namespace. + +#endif // HURRICANE_JSON_READER_H diff --git a/hurricane/src/hurricane/grenier/json/Net.cpp b/hurricane/src/hurricane/grenier/json/Net.cpp new file mode 100644 index 00000000..e2e9c1e9 --- /dev/null +++ b/hurricane/src/hurricane/grenier/json/Net.cpp @@ -0,0 +1,1106 @@ +// **************************************************************************************************** +// File: ./Net.cpp +// Authors: R. Escassut +// Copyright (c) BULL S.A. 2000-2015, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify it under the terms of the GNU +// Lesser General Public License as published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public License along with Hurricane. If +// not, see . +// **************************************************************************************************** + +#include "hurricane/Warning.h" +#include "hurricane/Net.h" +#include "hurricane/Cell.h" +#include "hurricane/Instance.h" +#include "hurricane/Plug.h" +#include "hurricane/RoutingPad.h" +#include "hurricane/RoutingPads.h" +#include "hurricane/Pin.h" +#include "hurricane/Contact.h" +#include "hurricane/Vertical.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Pad.h" +#include "hurricane/UpdateSession.h" +#include "hurricane/Error.h" + +namespace Hurricane { + + + +// **************************************************************************************************** +// Filters declaration & implementation +// **************************************************************************************************** + +class Net_IsCellNetFilter : public Filter { +// ******************************************* + + public: Net_IsCellNetFilter() {}; + + public: Net_IsCellNetFilter(const Net_IsCellNetFilter& filter) {}; + + public: Net_IsCellNetFilter& operator=(const Net_IsCellNetFilter& filter) {return *this;}; + + public: virtual Filter* getClone() const {return new Net_IsCellNetFilter(*this);}; + + public: virtual bool accept(Net* net) const {return !net->isDeepNet();}; + + public: virtual string _getString() const {return "<" + _TName("Net::IsCellNetFilter>");}; + +}; + +class Net_IsDeepNetFilter : public Filter { +// ******************************************* + + public: Net_IsDeepNetFilter() {}; + + public: Net_IsDeepNetFilter(const Net_IsDeepNetFilter& filter) {}; + + public: Net_IsDeepNetFilter& operator=(const Net_IsDeepNetFilter& filter) {return *this;}; + + public: virtual Filter* getClone() const {return new Net_IsDeepNetFilter(*this);}; + + public: virtual bool accept(Net* net) const {return net->isDeepNet();}; + + public: virtual string _getString() const {return "<" + _TName("Net::IsDeepNetFilter>");}; + +}; + +class Net_IsGlobalFilter : public Filter { +// ******************************************* + + public: Net_IsGlobalFilter() {}; + + public: Net_IsGlobalFilter(const Net_IsGlobalFilter& filter) {}; + + public: Net_IsGlobalFilter& operator=(const Net_IsGlobalFilter& filter) {return *this;}; + + public: virtual Filter* getClone() const {return new Net_IsGlobalFilter(*this);}; + + public: virtual bool accept(Net* net) const {return net->isGlobal();}; + + public: virtual string _getString() const {return "<" + _TName("Net::IsGlobalFilter>");}; + +}; + +class Net_IsExternalFilter : public Filter { +// ********************************************* + + public: Net_IsExternalFilter() {}; + + public: Net_IsExternalFilter(const Net_IsExternalFilter& filter) {}; + + public: Net_IsExternalFilter& operator=(const Net_IsExternalFilter& filter) {return *this;}; + + public: virtual Filter* getClone() const {return new Net_IsExternalFilter(*this);}; + + public: virtual bool accept(Net* net) const {return net->isExternal();}; + + public: virtual string _getString() const {return "<" + _TName("Net::IsExternalFilter>");}; + +}; + +class Net_IsClockFilter : public Filter { +// ****************************************** + + public: Net_IsClockFilter() {}; + + public: Net_IsClockFilter(const Net_IsClockFilter& filter) {}; + + public: Net_IsClockFilter& operator=(const Net_IsClockFilter& filter) {return *this;}; + + public: virtual Filter* getClone() const {return new Net_IsClockFilter(*this);}; + + public: virtual bool accept(Net* net) const {return net->isClock();}; + + public: virtual string _getString() const {return "<" + _TName("Net::IsClockFilter>");}; + +}; + +class Net_IsSupplyFilter : public Filter { +// ******************************************* + + public: Net_IsSupplyFilter() {}; + + public: Net_IsSupplyFilter(const Net_IsSupplyFilter& filter) {}; + + public: Net_IsSupplyFilter& operator=(const Net_IsSupplyFilter& filter) {return *this;}; + + public: virtual Filter* getClone() const {return new Net_IsSupplyFilter(*this);}; + + public: virtual bool accept(Net* net) const {return net->isSupply();}; + + public: virtual string _getString() const {return "<" + _TName("Net::IsSupplyFilter>");}; + +}; + +class Net_IsPowerFilter : public Filter { +// ******************************************* + + public: Net_IsPowerFilter() {}; + + public: Net_IsPowerFilter(const Net_IsPowerFilter& filter) {}; + + public: Net_IsPowerFilter& operator=(const Net_IsPowerFilter& filter) {return *this;}; + + public: virtual Filter* getClone() const {return new Net_IsPowerFilter(*this);}; + + public: virtual bool accept(Net* net) const {return net->isPower();}; + + public: virtual string _getString() const {return "<" + _TName("Net::IsPowerFilter>");}; + +}; + +class Net_IsGroundFilter : public Filter { +// ******************************************* + + public: Net_IsGroundFilter() {}; + + public: Net_IsGroundFilter(const Net_IsGroundFilter& filter) {}; + + public: Net_IsGroundFilter& operator=(const Net_IsGroundFilter& filter) {return *this;}; + + public: virtual Filter* getClone() const {return new Net_IsGroundFilter(*this);}; + + public: virtual bool accept(Net* net) const {return net->isGround();}; + + public: virtual string _getString() const {return "<" + _TName("Net::IsGroundFilter>");}; + +}; + + + +// **************************************************************************************************** +// Net_SlavePlugs implementation +// **************************************************************************************************** + +class Net_SlavePlugs : public Collection { +// ******************************************** + +// Types +// ***** + + public: typedef Collection Inherit; + + public: class Locator : public Hurricane::Locator { + // ***************************************************** + + public: typedef Hurricane::Locator Inherit; + + private: const Net* _net; + private: Plug* _plug; + private: InstanceLocator _instanceLocator; + + public: Locator(const Net* net = NULL); + public: Locator(const Locator& locator); + + public: Locator& operator=(const Locator& locator); + + public: virtual Plug* getElement() const; + public: virtual Hurricane::Locator* getClone() const; + + public: virtual bool isValid() const; + + public: virtual void progress(); + + public: virtual string _getString() const; + + }; + +// Attributes +// ********** + + private: const Net* _net; + +// Constructors +// ************ + + public: Net_SlavePlugs(const Net* net = NULL); + public: Net_SlavePlugs(const Net_SlavePlugs& slavePlugs); + +// Operators +// ********* + + public: Net_SlavePlugs& operator=(const Net_SlavePlugs& slavePlugs); + +// Accessors +// ********* + + public: virtual Collection* getClone() const; + public: virtual Hurricane::Locator* getLocator() const; + +// Others +// ****** + + public: virtual string _getString() const; + +}; + + + +// **************************************************************************************************** +// Net implementation +// **************************************************************************************************** + +Net::Net(Cell* cell, const Name& name) +// *********************************** +: Inherit(), + _cell(cell), + _name(name), + _arity(1), + _isGlobal(false), + _isExternal(false), + _isAutomatic(false), + _type(Type::LOGICAL), // default is Type::LOGICAL : no more Type::Undefined - Damien.Dupuis 01/10/2010 + _direction(), + _position(0,0), + _componentSet(), + _rubberSet(), + _nextOfCellNetMap(NULL), + _mainName(this) +{ + if (!_cell) + throw Error("Can't create " + _TName("Net") + " : null cell"); + + if (name.isEmpty()) + throw Error("Can't create " + _TName("Net") + " : empty name"); + + if (_cell->getNet(_name)) + throw Error("Can't create " + _TName("Net ") + getString(_name) + " : already exists"); +} + +Net* Net::create(Cell* cell, const Name& name) +// ******************************************* +{ + Net* net = new Net(cell, name); + + net->_postCreate(); + + return net; +} + +Box Net::getBoundingBox() const +// **************************** +{ + Box boundingBox; + for_each_component(component, getComponents()) { + boundingBox.merge(component->getBoundingBox()); + end_for; + } + return boundingBox; +} + +RoutingPads Net::getRoutingPads() const +// ************************ +{ + // return getComponents().getSubSet(); + return SubTypeCollection(getComponents()); +} + +Plugs Net::getPlugs() const +// ************************ +{ + // return getComponents().getSubSet(); + return SubTypeCollection(getComponents()); +} + +Pins Net::getPins() const +// ********************** +{ + // return getComponents().getSubSet(); + return SubTypeCollection(getComponents()); +} + +Contacts Net::getContacts() const +// ****************************** +{ + // return getComponents().getSubSet(); + return SubTypeCollection(getComponents()); +} + +Segments Net::getSegments() const +// ****************************** +{ + // return getComponents().getSubSet(); + return SubTypeCollection(getComponents()); +} + +Verticals Net::getVerticals() const +// ******************************** +{ + // return getComponents().getSubSet(); + return SubTypeCollection(getComponents()); +} + +Horizontals Net::getHorizontals() const +// ************************************ +{ + // return getComponents().getSubSet(); + return SubTypeCollection(getComponents()); +} + +Pads Net::getPads() const +// ********************** +{ + // return getComponents().getSubSet(); + return SubTypeCollection(getComponents()); +} + +Plugs Net::getSlavePlugs() const +// ***************************** +{ + return Net_SlavePlugs(this); +} + +Plugs Net::getConnectedSlavePlugs() const +// ************************************** +{ + return getSlavePlugs().getSubSet(Plug::getIsConnectedFilter()); +} + +Plugs Net::getUnconnectedSlavePlugs() const +// **************************************** +{ + return getSlavePlugs().getSubSet(Plug::getIsUnconnectedFilter()); +} + +NetFilter Net::getIsCellNetFilter() +// ******************************* +{ + return Net_IsCellNetFilter(); +} + +NetFilter Net::getIsDeepNetFilter() +// ******************************* +{ + return Net_IsDeepNetFilter(); +} + +NetFilter Net::getIsGlobalFilter() +// ******************************* +{ + return Net_IsGlobalFilter(); +} + +NetFilter Net::getIsExternalFilter() +// ********************************* +{ + return Net_IsExternalFilter(); +} + +NetFilter Net::getIsInternalFilter() +// ********************************* +{ + return !Net_IsExternalFilter(); +} + +NetFilter Net::getIsClockFilter() +// ****************************** +{ + return Net_IsClockFilter(); +} + +NetFilter Net::getIsSupplyFilter() +// ******************************* +{ + return Net_IsSupplyFilter(); +} + +NetFilter Net::getIsPowerFilter() +// ******************************* +{ + return Net_IsPowerFilter(); +} + +NetFilter Net::getIsGroundFilter() +// ******************************* +{ + return Net_IsGroundFilter(); +} + +void Net::setName(const Name& name) +// ******************************** +{ + if (name != _name) { + if (name.isEmpty()) + throw Error("Can't change net name : empty name"); + + if (_cell->getNet(name)) + throw Error("Can't change net name : already exists"); + + _cell->_getNetMap()._remove(this); + _name = name; + _cell->_getNetMap()._insert(this); + } +} + +void Net::setArity(const Arity& arity) +// *********************************** +{ + _arity = arity; +} + +void Net::setGlobal(bool isGlobal) +// ******************************* +{ + _isGlobal = isGlobal; +} + +void Net::setExternal(bool isExternal) +// *********************************** +{ + if (isExternal != _isExternal) { + if (!isExternal) { + if (!getConnectedSlavePlugs().isEmpty()) + throw Error("Can't set internal : has connected slave plugs"); + _direction = Direction::UNDEFINED; + } + _isExternal = isExternal; + if (_isExternal) { + UpdateSession::open(); + setPosition(Point(0,0)); + for_each_instance(instance, _cell->getSlaveInstances()) { + Plug::_create(instance, this); + end_for; + } + UpdateSession::close(); + } + } +} + +void Net::setAutomatic(bool isAutomatic) +// ************************************* +{ + _isAutomatic = isAutomatic; +} + +void Net::setType(const Type& type) +// ******************************** +{ + _type = type; +} + +void Net::setPosition(const Point& position) +// ***************************************** +{ + if (_position != position) { + for_each_plug(plug, getSlavePlugs()) { + plug->invalidate(true); + end_for; + } + _position = position; + } +} + +void Net::setDirection(const Direction& direction) +// *********************************************** +{ + _direction = direction; +} + +bool Net::addAlias(const Name& name ) +// ********************************** +{ + if (getCell()->getNet(name)) { + cerr << Warning( "Net::addAlias(): Cannot add alias %s to net %s, already taken." + , getString(name).c_str() + , getString(getName()).c_str() + ) << endl; + return false; + } + + NetAliasName* slave = new NetAliasName ( name ); + _mainName.attach( slave ); + getCell()->_addNetAlias( slave ); + + return true; +} + +bool Net::removeAlias(const Name& name ) +// ************************************* +{ + NetAliasName* slave = _mainName.find( name ); + if (slave) { + slave->detach(); + getCell()->_removeNetAlias( slave ); + return true; + } + return false; +} + +Net* Net::getClone(Cell* clonedCell) +// ********************************* +{ + Net* clonedNet = Net::create( clonedCell, getName() ); + clonedNet->setArity ( getArity() ); + clonedNet->setGlobal ( isGlobal() ); + clonedNet->setExternal ( isExternal() ); + clonedNet->setType ( getType() ); + clonedNet->setDirection( getDirection() ); + + return clonedNet; +} + +void Net::materialize() +// ******************** +{ + for_each_component(component, getComponents()) { + component->materialize(); + end_for; + } + for_each_rubber(rubber, getRubbers()) { + rubber->materialize(); + end_for; + } +} + +void Net::unmaterialize() +// ********************** +{ + for_each_rubber(rubber, getRubbers()) { + rubber->unmaterialize(); + end_for; + } + for_each_component(component, getComponents()) { + component->unmaterialize(); + end_for; + } +} + +static void mergeNets(Net* net1, Net* net2) +// **************************************** +{ + assert(net1); + assert(net2); + + if (net2->getName()[0] != '~') { + if ((net1->getName()[0] == '~') || + (net2->isGlobal() && !net1->isGlobal()) || + (net2->isExternal() && !net1->isExternal())) { + Net* tmpNet = net1; + net1 = net2; + net2 = tmpNet; + } + } + + if (net2->isExternal() && !net1->isExternal()) { + Net* tmpNet = net1; + net1 = net2; + net2 = tmpNet; + } + + net1->merge(net2); +} + +void Net::merge(Net* net) +// ********************** +{ + if (!net) + throw Error("Can't merge net : null net"); + + if (net == this) + throw Error("Can't merge net : itself"); + + if (net->getCell() != _cell) + throw Error("Can't merge net : incompatible net"); + + if (!isExternal() && net->isExternal() && !net->getConnectedSlavePlugs().isEmpty()) + throw Error("Can't merge net : incompatible net"); + + for_each_rubber(rubber, net->getRubbers()) rubber->_setNet(this); end_for; + for_each_component(component, net->getComponents()) component->_setNet(this); end_for; + + if (isExternal() && net->isExternal()) { + for_each_plug(plug, net->getConnectedSlavePlugs()) { + Plug* mainPlug = plug->getInstance()->getPlug(this); + if (mainPlug->isConnected() && (mainPlug->getNet() != plug->getNet())) + mergeNets(mainPlug->getNet(), plug->getNet()); + end_for; + } + for_each_plug(plug, net->getConnectedSlavePlugs()) { + Plug* mainPlug = plug->getInstance()->getPlug(this); + if (!mainPlug->isConnected()) mainPlug->setNet(plug->getNet()); + Hook* masterHook = plug->getBodyHook(); + Hook* nextMasterHook = masterHook->getNextMasterHook(); + if (nextMasterHook != masterHook) { + masterHook->detach(); + mainPlug->getBodyHook()->merge(nextMasterHook); + } + Hooks slaveHooks = masterHook->getSlaveHooks(); + while (!slaveHooks.isEmpty()) { + Hook* slaveHook = slaveHooks.getFirst(); + slaveHook->detach(); + slaveHook->attach(mainPlug->getBodyHook()); + } + plug->_destroy(); + end_for; + } + } + + Name mergedName = net->getName(); + NetAliasName* slaves = NULL; + if (net->_mainName.isAttached()) { + slaves = dynamic_cast( net->_mainName.getNext() ); + net->_mainName.detach(); + } + + if (net->isExternal() and not isExternal()) + setExternal( true ); + net->destroy(); + + if (slaves) _mainName.attach( slaves ); + addAlias( mergedName ); +} + +void Net::_postCreate() +// ******************** +{ + _cell->_getNetMap()._insert(this); + + if (_isExternal) { + for_each_instance(instance, _cell->getSlaveInstances()) { + Plug::_create(instance, this); + end_for; + } + } + + Inherit::_postCreate(); +} + +void Net::_preDestroy() +// ******************* +{ + Inherit::_preDestroy(); + + for_each_plug(slavePlug, getSlavePlugs()) slavePlug->_destroy(); end_for; + + unmaterialize(); + + for_each_rubber(rubber, getRubbers()) rubber->_destroy(); end_for; + + for_each_component(component, getComponents()) { + for_each_hook(hook, component->getHooks()) { + // 15 05 2006 xtof : detach all hooks in rings when + // a net deletion occurs, can't see why master hooks were not detached. + //if (!hook->IsMaster()) hook->detach(); + hook->detach(); + end_for; + } + end_for; + } + + for_each_component(component, getComponents()) { + if (!dynamic_cast(component)) + component->destroy(); + else + ((Plug*)component)->setNet(NULL); + end_for; + } + + _mainName.clear(); + _cell->_getNetMap()._remove(this); +} + +string Net::_getString() const +// *************************** +{ + string s = Inherit::_getString(); + s.insert(s.length() - 1, " " + getString(_name)); + return s; +} + +Record* Net::_getRecord() const +// ********************** +{ + Record* record = Inherit::_getRecord(); + if (record) { + record->add(getSlot("_cell", _cell)); + record->add(getSlot("_name", &_name)); + record->add(getSlot("_arity", &_arity)); + record->add(getSlot("_isGlobal", &_isGlobal)); + record->add(getSlot("_isExternal", &_isExternal)); + record->add(getSlot("_isAutomatic", &_isAutomatic)); + record->add(getSlot("_type", &_type)); + record->add(getSlot("_direction", &_direction)); + record->add(getSlot("_position", &_position)); + record->add(getSlot("_componentsSet", &_componentSet)); + record->add(getSlot("_rubberSet", &_rubberSet)); + record->add(getSlot("_mainName", &_mainName)); + } + return record; +} + +void Net::_toJson( JsonWriter* writer ) const +// ****************************************** +{ + // Inherit::_toJson( writer ); + + // jsonWrite( writer, "_name" , getName() ); + // jsonWrite( writer, "_isGlobal" , isGlobal() ); + // jsonWrite( writer, "_isExternal" , isExternal() ); + // jsonWrite( writer, "_isAutomatic" , isAutomatic() ); + // jsonWrite( writer, "_type" , getType() ); + // jsonWrite( writer, "_direction" , getDirection() ); + // jsonWrite( writer, "+aliases" , getAliases() ); + + // writer->setFlags( JsonWriter::UsePlugReference ); + // jsonWrite( writer, "+componentSet", getComponents() ); + // writer->setFlags( JsonWriter::UsePlugReference ); +} + +JsonObject* Net::getJsonObject(unsigned long flags) +// ************************************************ +{ + return new JsonNet ( flags ); +} + +// **************************************************************************************************** +// Net::Type implementation +// **************************************************************************************************** + +Net::Type::Type(const Code& code) +// ****************************** +: _code(code) +{ } + +Net::Type::Type(const Type& type) +// ****************************** +: _code(type._code) +{ } + +Net::Type::Type(string s) +// ********************** +: _code(UNDEFINED) +{ + if (s == "UNDEFINED") _code = UNDEFINED; + else if (s == "LOGICAL" ) _code = LOGICAL; + else if (s == "CLOCK" ) _code = CLOCK; + else if (s == "POWER" ) _code = POWER; + else if (s == "GROUND" ) _code = GROUND; +} + +Net::Type& Net::Type::operator=(const Type& type) +// ********************************************** +{ + _code = type._code; + return *this; +} + +string Net::Type::_getString() const +// ********************************* +{ + return getString(&_code); +} + +Record* Net::Type::_getRecord() const +// **************************** +{ + Record* record = new Record(getString(this)); + record->add(getSlot("Code", &_code)); + return record; +} + + + +// **************************************************************************************************** +// Net::Direction implementation +// **************************************************************************************************** + +Net::Direction::Direction(const Code& code) +// **************************************** +: _code(code) +{ } + +Net::Direction::Direction(const Direction& direction) +// ************************************************** +: _code(direction._code) +{ } + +Net::Direction::Direction(string s) +// ******************************** +: _code(UNDEFINED) +{ + if (s.size() > 3) { + if (s[0] == 'i') *this |= DirIn; + if (s[0] == 'o') *this |= DirOut; + if (s[0] == 't') *this |= ConnTristate; + if (s[0] == 'w') *this |= ConnWiredOr; + } +} + +Net::Direction& Net::Direction::operator=(const Direction& direction) +// ****************************************************************** +{ + _code = direction._code; + return *this; +} + +Net::Direction& Net::Direction::operator|=(const Direction& direction) +// ****************************************************************** +{ + _code = (Code)((unsigned int)_code | (unsigned int)direction._code); + return *this; +} + +string Net::Direction::_getString() const +// ************************************** +{ + return getString(&_code); +} + +Record* Net::Direction::_getRecord() const +// ********************************* +{ + Record* record = new Record(getString(this)); + record->add(getSlot("Code", &_code)); + return record; +} + + + +// **************************************************************************************************** +// Net::ComponentSet implementation +// **************************************************************************************************** + +Net::ComponentSet::ComponentSet() +// ****************************** +: Inherit() +{ +} + +unsigned Net::ComponentSet::_getHashValue(Component* component) const +// ****************************************************************** +{ + return component->getId() / 8; +} + +Component* Net::ComponentSet::_getNextElement(Component* component) const +// ********************************************************************** +{ + return component->_getNextOfNetComponentSet(); +} + +void Net::ComponentSet::_setNextElement(Component* component, Component* nextComponent) const +// ****************************************************************************************** +{ + component->_setNextOfNetComponentSet(nextComponent); +} + + + +// **************************************************************************************************** +// Net::RubberSet implementation +// **************************************************************************************************** + +Net::RubberSet::RubberSet() +// ************************ +: Inherit() +{ +} + +unsigned Net::RubberSet::_getHashValue(Rubber* rubber) const +// ********************************************************* +{ + return rubber->getId() / 8; +} + +Rubber* Net::RubberSet::_getNextElement(Rubber* rubber) const +// ********************************************************** +{ + return rubber->_getNextOfNetRubberSet(); +} + +void Net::RubberSet::_setNextElement(Rubber* rubber, Rubber* nextRubber) const +// *************************************************************************** +{ + rubber->_setNextOfNetRubberSet(nextRubber); +} + + + +// **************************************************************************************************** +// Net_SlavePlugs implementation +// **************************************************************************************************** + +Net_SlavePlugs::Net_SlavePlugs(const Net* net) +// ******************************************* +: Inherit(), + _net(net) +{ +} + +Net_SlavePlugs::Net_SlavePlugs(const Net_SlavePlugs& slavePlugs) +// ************************************************************* +: Inherit(), + _net(slavePlugs._net) +{ +} + +Net_SlavePlugs& Net_SlavePlugs::operator=(const Net_SlavePlugs& slavePlugs) +// ************************************************************************ +{ + _net = slavePlugs._net; + return *this; +} + +Collection* Net_SlavePlugs::getClone() const +// ************************************************ +{ + return new Net_SlavePlugs(*this); +} + +Locator* Net_SlavePlugs::getLocator() const +// *********************************************** +{ + return new Locator(_net); +} + +string Net_SlavePlugs::_getString() const +// ************************************** +{ + string s = "<" + _TName("Net::SlavePlugs"); + if (_net) s += " " + getString(_net); + s += ">"; + return s; +} + + + +// **************************************************************************************************** +// Net_SlavePlugs::Locator implementation +// **************************************************************************************************** + +Net_SlavePlugs::Locator::Locator(const Net* net) +// ********************************************* +: Inherit(), + _net(net), + _plug(NULL), + _instanceLocator() +{ + if (_net) { + _instanceLocator = _net->getCell()->getSlaveInstances().getLocator(); + while (!_plug && _instanceLocator.isValid()) { + _plug = _instanceLocator.getElement()->getPlug(_net); + _instanceLocator.progress(); + } + } +} + +Net_SlavePlugs::Locator::Locator(const Locator& locator) +// ***************************************************** +: Inherit(), + _net(locator._net), + _plug(locator._plug), + _instanceLocator(locator._instanceLocator) +{ +} + +Net_SlavePlugs::Locator& Net_SlavePlugs::Locator::operator=(const Locator& locator) +// ******************************************************************************** +{ + _net = locator._net; + _plug = locator._plug; + _instanceLocator = locator._instanceLocator; + return *this; +} + +Plug* Net_SlavePlugs::Locator::getElement() const +// ********************************************** +{ + return _plug; +} + +Locator* Net_SlavePlugs::Locator::getClone() const +// ****************************************************** +{ + return new Locator(*this); +} + +bool Net_SlavePlugs::Locator::isValid() const +// ****************************************** +{ + return (_plug != NULL); +} + +void Net_SlavePlugs::Locator::progress() +// ************************************* +{ + if (isValid()) { + _plug = NULL; + while (!_plug && _instanceLocator.isValid()) { + _plug = _instanceLocator.getElement()->getPlug(_net); + _instanceLocator.progress(); + } + } +} + +string Net_SlavePlugs::Locator::_getString() const +// *********************************************** +{ + string s = "<" + _TName("Net::SlavePlugs::Locator"); + if (_net) s += " " + getString(_net); + s += ">"; + return s; +} + + + +// **************************************************************************************************** +// JsonNet implementation +// **************************************************************************************************** + +JsonNet::JsonNet(unsigned long flags) +// ********************************** + : JsonEntity(flags) +{ + addS( "_name" , &Net::_name ); + add ( "_isGlobal" , &Net::_isGlobal ); + add ( "_isExternal" , &Net::_isExternal ); + add ( "_isAutomatic" , &Net::_isAutomatic ); + addS( "_type" , &Net::_type ); + addS( "_direction" , &Net::_direction ); +//addC( "+aliases" , &Net::getAliases ); + add ( "+componentSet", &Net::getComponents ); +} + +string JsonNet::getTypeName() const +// ********************************* +{ return "Net"; } + +JsonNet* JsonNet::clone() const +// **************************** +{ return new JsonNet ( *this ); } + +void JsonNet::toData(JsonStack& stack) +// *********************************** +{ + ltracein(51); + check( stack, "JsonNet::toData" ); + +//unsigned int jsonId = get(stack,"_id"); + Net* net = Net::create ( get(stack,".Cell") , get(stack,"_name") ); + net->setGlobal ( get(stack,"_isGlobal" ) ); + net->setExternal ( get(stack,"_isExternal" ) ); + net->setAutomatic( get(stack,"_isAutomatic") ); + net->setType ( Net::Type (get(stack,"_type")) ); + net->setDirection( Net::Direction(get(stack,"_direction")) ); + + update( stack, net ); + + ltraceout(51); +} + +} // End of Hurricane namespace. + + +// **************************************************************************************************** +// Copyright (c) BULL S.A. 2000-2015, All Rights Reserved +// **************************************************************************************************** diff --git a/hurricane/src/hurricane/grenier/json/Net.h b/hurricane/src/hurricane/grenier/json/Net.h new file mode 100644 index 00000000..e765fb67 --- /dev/null +++ b/hurricane/src/hurricane/grenier/json/Net.h @@ -0,0 +1,363 @@ +// **************************************************************************************************** +// File: ./hurricane/Net.h +// Authors: R. Escassut +// Copyright (c) BULL S.A. 2000-2015, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify it under the terms of the GNU +// Lesser General Public License as published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public License along with Hurricane. If +// not, see . +// **************************************************************************************************** + +#ifndef HURRICANE_NET +#define HURRICANE_NET + +#include +#include "hurricane/Entity.h" +#include "hurricane/Nets.h" +#include "hurricane/Component.h" +#include "hurricane/Rubbers.h" +#include "hurricane/Rubber.h" +#include "hurricane/RoutingPads.h" +#include "hurricane/Plugs.h" +#include "hurricane/Pins.h" +#include "hurricane/Contacts.h" +#include "hurricane/Segments.h" +#include "hurricane/Verticals.h" +#include "hurricane/Horizontals.h" +#include "hurricane/Pads.h" +#include "hurricane/IntrusiveSet.h" +#include "hurricane/Path.h" +#include "hurricane/NetAlias.h" + +namespace Hurricane { + + class JsonNet; + +// **************************************************************************************************** +// Net declaration +// **************************************************************************************************** + +class Net : public Entity { +// ********************** + + friend class JsonNet; + +// Types +// ***** + + public: typedef Entity Inherit; + + public: typedef unsigned Arity; + + public: class Type { + // *************** + + public: enum Code {UNDEFINED=0, LOGICAL=1, CLOCK=2, POWER=3, GROUND=4}; + + private: Code _code; + + public: Type(const Code& code = UNDEFINED); + public: Type(const Type& type); + public: Type(string); + + public: Type& operator=(const Type& type); + + public: operator const Code&() const {return _code;}; + + public: const Code& getCode() const {return _code;}; + + public: string _getTypeName() const { return _TName("Net::type"); }; + public: string _getString() const; + public: Record* _getRecord() const; + + }; + + public: class Direction { + // ******************** + + public: enum Code { DirIn = 0x0001 + , DirOut = 0x0002 + , DirUndefined = 0x0000 + , ConnTristate = 0x0100 + , ConnWiredOr = 0x0200 + , UNDEFINED = DirUndefined + , IN = DirIn + , OUT = DirOut + , INOUT = DirIn | DirOut + , TRISTATE = DirOut | ConnTristate + , TRANSCV = DirIn | DirOut | ConnTristate + , WOR_OUT = DirOut | ConnWiredOr + , WOR_INOUT = DirIn | DirOut | ConnWiredOr + , DirMask = DirIn | DirOut | DirUndefined + }; + + private: Code _code; + + public: Direction(const Code& code = UNDEFINED); + public: Direction(const Direction& direction); + public: Direction(string); + + public: Direction& operator =(const Direction& direction); + public: Direction& operator|=(const Direction& direction); + + public: operator const Code&() const {return _code;}; + + public: const Code& getCode() const {return _code;}; + + public: string _getTypeName() const { return _TName("Net::Direction"); }; + public: string _getString() const; + public: Record* _getRecord() const; + + }; + + class ComponentSet : public IntrusiveSet { + // ************************************************ + + public: typedef IntrusiveSet Inherit; + + public: ComponentSet(); + + public: virtual unsigned _getHashValue(Component* component) const; + public: virtual Component* _getNextElement(Component* component) const; + public: virtual void _setNextElement(Component* component, Component* nextComponent) const; + + }; + + class RubberSet : public IntrusiveSet { + // ****************************************** + + public: typedef IntrusiveSet Inherit; + + public: RubberSet(); + + public: virtual unsigned _getHashValue(Rubber* rubber) const; + public: virtual Rubber* _getNextElement(Rubber* rubber) const; + public: virtual void _setNextElement(Rubber* rubber, Rubber* nextRubber) const; + + }; + +// Attributes +// ********** + + private: Cell* _cell; + private: Name _name; + private: Arity _arity; + private: bool _isGlobal; + private: bool _isExternal; + private: bool _isAutomatic; + private: Type _type; + private: Direction _direction; + private: Point _position; + private: ComponentSet _componentSet; + private: RubberSet _rubberSet; + private: Net* _nextOfCellNetMap; + private: NetMainName _mainName; + +// Constructors +// ************ + + protected: Net(Cell* cell, const Name& name); + + public: static Net* create(Cell* cell, const Name& name); + +// Accessors +// ********* + + public: virtual Cell* getCell() const {return _cell;}; + public: virtual Box getBoundingBox() const; + public: const Name& getName() const {return _name;}; + public: const NetMainName* getMainName() const { return &_mainName; } + public: const Arity& getArity() const {return _arity;}; + public: const Type& getType() const {return _type;}; + public: const Direction& getDirection() const {return _direction;}; + public: const Point& getPosition() const {return _position;}; + public: const DbU::Unit& getX() const {return _position.getX();}; + public: const DbU::Unit& getY() const {return _position.getY();}; + public: Components getComponents() const {return _componentSet.getElements();}; + public: Rubbers getRubbers() const {return _rubberSet.getElements();}; + public: RoutingPads getRoutingPads() const; + public: Plugs getPlugs() const; + public: Pins getPins() const; + public: Contacts getContacts() const; + public: Segments getSegments() const; + public: Verticals getVerticals() const; + public: Horizontals getHorizontals() const; + public: Pads getPads() const; + public: Plugs getSlavePlugs() const; + public: Plugs getConnectedSlavePlugs() const; + public: Plugs getUnconnectedSlavePlugs() const; + public: Aliases getAliases() const { return new AliasList(this); }; + +// Filters +// ******* + + public: static NetFilter getIsCellNetFilter(); + public: static NetFilter getIsDeepNetFilter(); + public: static NetFilter getIsGlobalFilter(); + public: static NetFilter getIsExternalFilter(); + public: static NetFilter getIsInternalFilter(); + public: static NetFilter getIsClockFilter(); + public: static NetFilter getIsSupplyFilter(); + public: static NetFilter getIsPowerFilter(); + public: static NetFilter getIsGroundFilter(); + +// Predicates +// ********** + + public: virtual bool isDeepNet () const {return false;}; + public: bool isGlobal () const {return _isGlobal;}; + public: bool isExternal () const {return _isExternal;}; + public: bool isAutomatic() const {return _isAutomatic;}; + public: bool isLogical () const {return (_type == Type::LOGICAL);}; + public: bool isClock () const {return (_type == Type::CLOCK);}; + public: bool isPower () const {return (_type == Type::POWER);}; + public: bool isGround () const {return (_type == Type::GROUND);}; + public: bool isSupply () const {return (isPower() || isGround());}; + +// Updators +// ******** + + public: void setName(const Name& name); + public: void setArity(const Arity& arity); + public: void setGlobal(bool isGlobal); + public: void setExternal(bool isExternal); + public: void setAutomatic(bool isAutomatic); + public: void setType(const Type& type); + public: void setDirection(const Direction& direction); + public: void setPosition(const Point& position); + public: void materialize(); + public: void unmaterialize(); + public: bool addAlias(const Name& name); + public: bool removeAlias(const Name& name); + public: void merge(Net* net); + public: Net* getClone(Cell* cloneCell); + +// Others +// ****** + + protected: virtual void _postCreate(); + protected: virtual void _preDestroy(); + + public: virtual void _toJson ( JsonWriter* ) const; + public: static JsonObject* getJsonObject(unsigned long flags); + public: virtual string _getTypeName() const {return _TName("Net");}; + public: virtual string _getString() const; + public: virtual Record* _getRecord() const; + public: NetMainName& _getMainName() { return _mainName; } + public: ComponentSet& _getComponentSet() {return _componentSet;}; + public: RubberSet& _getRubberSet() {return _rubberSet;}; + public: Net* _getNextOfCellNetMap() const {return _nextOfCellNetMap;}; + + public: void _setNextOfCellNetMap(Net* net) {_nextOfCellNetMap = net;}; + +}; + +class JsonNet : public JsonEntity { +// ******************************** + + public: JsonNet(unsigned long flags); + public: virtual string getTypeName() const; + public: virtual JsonNet* clone() const; + public: virtual void toData(JsonStack&); +}; + +} // End of Hurricane namespace. + + +// ------------------------------------------------------------------- +// Inspector Support for : Net::Type::Code*". + +template<> +inline std::string getString + ( const Hurricane::Net::Type::Code* object ) + { + switch ( *object ) { + case Hurricane::Net::Type::UNDEFINED: return "UNDEFINED"; + case Hurricane::Net::Type::LOGICAL: return "LOGICAL"; + case Hurricane::Net::Type::CLOCK: return "CLOCK"; + case Hurricane::Net::Type::POWER: return "POWER"; + case Hurricane::Net::Type::GROUND: return "GROUND"; + } + return "ABNORMAL"; + } + +template<> +inline Hurricane::Record* getRecord + ( const Hurricane::Net::Type::Code* object ) + { + Hurricane::Record* record = new Hurricane::Record(getString(object)); + record->add(getSlot("Code", (unsigned int*)object)); + return record; + } + + +// ------------------------------------------------------------------- +// Inspector Support for : "const Net::Direction::Code*". + +template<> +inline std::string getString + ( const Hurricane::Net::Direction::Code* object ) + { + std::ostringstream s; + s << (((*object) & Hurricane::Net::Direction::DirIn ) ? 'i' : '-'); + s << (((*object) & Hurricane::Net::Direction::DirOut ) ? 'o' : '-'); + s << (((*object) & Hurricane::Net::Direction::ConnTristate) ? 't' : '-'); + s << (((*object) & Hurricane::Net::Direction::ConnWiredOr ) ? 'w' : '-'); + + switch ( (int)*object ) { + case Hurricane::Net::Direction::UNDEFINED: s << " (UNDEFINED)"; break; + case Hurricane::Net::Direction::IN: s << " (IN)"; break; + case Hurricane::Net::Direction::OUT: s << " (OUT)"; break; + case Hurricane::Net::Direction::INOUT: s << " (INOUT)"; break; + case Hurricane::Net::Direction::TRISTATE: s << " (TRISTATE)"; break; + case Hurricane::Net::Direction::TRANSCV: s << " (TRANSCV)"; break; + case Hurricane::Net::Direction::WOR_OUT: s << " (WOR_OUT)"; break; + case Hurricane::Net::Direction::WOR_INOUT: s << " (WOR_INOUT)"; break; + } + return s.str(); + } + +template<> +inline Hurricane::Record* getRecord + ( const Hurricane::Net::Direction::Code* object ) + { + Hurricane::Record* record = new Hurricane::Record(getString(object)); + record->add(getSlot("Code", (unsigned int*)object)); + return record; + } + + +INSPECTOR_P_SUPPORT(Hurricane::Net); +INSPECTOR_P_SUPPORT(Hurricane::Net::ComponentSet); +INSPECTOR_P_SUPPORT(Hurricane::Net::RubberSet); +INSPECTOR_PV_SUPPORT(Hurricane::Net::Type); +INSPECTOR_PV_SUPPORT(Hurricane::Net::Direction); +IOSTREAM_POINTER_SUPPORT(Hurricane::Net::Type::Code); +IOSTREAM_VALUE_SUPPORT(Hurricane::Net::Type::Code); +IOSTREAM_POINTER_SUPPORT(Hurricane::Net::Direction::Code); +IOSTREAM_VALUE_SUPPORT(Hurricane::Net::Direction::Code); + + +namespace Hurricane { + +// Force SlotTemplate<> expansion on Net* type. +// Because sometimes it didn't happens (?). + const SlotTemplate dummyNetSlot ( string("dummyNetSlot"), NULL ); + +} + +#endif // HURRICANE_NET + + +// **************************************************************************************************** +// Copyright (c) BULL S.A. 2000-2015, All Rights Reserved +// **************************************************************************************************** diff --git a/hurricane/src/hurricane/hurricane/Box.h b/hurricane/src/hurricane/hurricane/Box.h index e8b18f5f..37c37337 100644 --- a/hurricane/src/hurricane/hurricane/Box.h +++ b/hurricane/src/hurricane/hurricane/Box.h @@ -24,8 +24,6 @@ namespace Hurricane { - - // **************************************************************************************************** // Box declaration // **************************************************************************************************** @@ -36,7 +34,6 @@ class Box { // Attributes // ********** - private: DbU::Unit _xMin; private: DbU::Unit _yMin; private: DbU::Unit _xMax; @@ -125,10 +122,20 @@ class Box { public: string _getTypeName() const { return _TName("Box"); }; public: string _getString() const; public: Record* _getRecord() const; + public: void toJson(JsonWriter*) const; }; +class JsonBox : public JsonObject { +// ******************************** + + public: JsonBox(unsigned long); + public: virtual string getTypeName() const; + public: virtual JsonBox* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Cell.h b/hurricane/src/hurricane/hurricane/Cell.h index 0ea136a4..55107f02 100644 --- a/hurricane/src/hurricane/hurricane/Cell.h +++ b/hurricane/src/hurricane/hurricane/Cell.h @@ -23,6 +23,7 @@ #include #include "hurricane/Flags.h" #include "hurricane/Observer.h" +#include "hurricane/Signature.h" #include "hurricane/Relation.h" #include "hurricane/Pathes.h" #include "hurricane/Entity.h" @@ -54,7 +55,6 @@ namespace Hurricane { class Library; class BasicLayer; - typedef multimap SlaveEntityMap; @@ -302,6 +302,9 @@ class Cell : public Entity { public: void _changeQuadTree(Cell*); public: void _setShuntedPath(Path path) { _shuntedPath=path; } + public: virtual void _toJson(JsonWriter*) const; + public: virtual void _toJsonCollections(JsonWriter*) const; + // Constructors // ************ @@ -313,9 +316,11 @@ class Cell : public Entity { public: virtual Cell* getCell() const {return (Cell*)this;}; public: virtual Box getBoundingBox() const; public: Library* getLibrary() const {return _library;}; + public: string getHierarchicalName() const; public: const Name& getName() const {return _name;}; public: const Flags& getFlags() const { return _flags; } public: Path getShuntedPath() const { return _shuntedPath; } + public: Entity* getEntity(const Signature&) const; public: Instance* getInstance(const Name& name) const {return _instanceMap.getElement(name);}; public: Instances getInstances() const {return _instanceMap.getElements();}; public: Instances getPlacedInstances() const; @@ -441,6 +446,15 @@ inline Cell::ClonedSet::ClonedSet ( const ClonedSet& other ) { } +class JsonCell : public JsonEntity { +// ********************************* + + public: JsonCell(unsigned long flags); + public: virtual string getTypeName() const; + public: virtual JsonCell* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Collection.h b/hurricane/src/hurricane/hurricane/Collection.h index 0064f0ab..805d5e68 100644 --- a/hurricane/src/hurricane/hurricane/Collection.h +++ b/hurricane/src/hurricane/hurricane/Collection.h @@ -27,6 +27,7 @@ namespace Hurricane { template class GenericCollection; template class SubTypeCollection; +template class NotSubTypeCollection; template class SubSetCollection; @@ -113,6 +114,12 @@ template class Collection { return getSubSet().getSubSet(filter); } + public: template GenericCollection getNotSubSet() const + // **************************************************************************** + { + return NotSubTypeCollection(this); + } + // Predicates // ********** @@ -627,6 +634,171 @@ template class SubTypeCollection : public Collection< }; +// **************************************************************************************************** +// NotSubTypeCollection declaration +// **************************************************************************************************** + +template class NotSubTypeCollection : public Collection { +// ****************************************************************************************** + +// Types +// ***** + + public: typedef Collection Inherit; + + public: class Locator : public Hurricane::Locator { + // ******************************************************* + + // Types + // ***** + + public: typedef Hurricane::Locator Inherit; + + // Attributes + // ********** + + private: GenericLocator _locator; + + // Constructors + // ************ + + public: Locator(const GenericCollection& collection) + // ******************************************************** + : Inherit(), + _locator(collection.getLocator()) + { + while (_locator.isValid() && dynamic_cast(_locator.getElement())) + _locator.progress(); + } + + public: Locator(const GenericLocator& genericLocator) + // ******************************************************** + : Inherit(), + _locator(genericLocator.getClone()) + { + while (_locator.isValid() && !dynamic_cast(_locator.getElement())) + _locator.progress(); + } + + // Accessors + // ********* + + public: virtual SubType getElement() const + // *************************************** + { + return (_locator.isValid()) ? (SubType)_locator.getElement() : SubType(); + } + + public: virtual Hurricane::Locator* getClone() const + // ********************************************************** + { + return new Locator(_locator); + } + + public: virtual Hurricane::Locator* getLocator() // 21-10-03 + // ************************************************* + { + return dynamic_cast*> ( + _locator.getLocator()->getLocator() ); + } + + + // Predicates + // ********** + + public: virtual bool isValid() const + // ********************************* + { + return _locator.isValid(); + } + + // Updators + // ******** + + public: virtual void progress() + // **************************** + { + if (_locator.isValid()) { + do { + _locator.progress(); + } while (_locator.isValid() && !dynamic_cast(_locator.getElement())); + } + } + + }; + +// Attributes +// ********** + + private: GenericCollection _collection; + +// Constructors +// ************ + + public: NotSubTypeCollection() + // ******************** + : Inherit(), + _collection() + { + } + + public: NotSubTypeCollection(const Collection* collection) + // ********************************************************** + : Inherit(), + _collection(collection->getClone()) + { + } + + public: NotSubTypeCollection(const GenericCollection& collection) + // ***************************************************************** + : Inherit(), + _collection(collection) + { + } + + public: NotSubTypeCollection(const NotSubTypeCollection& subTypeCollection) + // ****************************************************************** + : Inherit(), + _collection(subTypeCollection._collection) + { + } + +// Operators +// ********* + + public: NotSubTypeCollection& operator=(const NotSubTypeCollection& subTypeCollection) + // ***************************************************************************** + { + _collection = subTypeCollection._collection; + return *this; + } + +// Accessors +// ********* + + public: virtual Collection* getClone() const + // ************************************************** + { + return new NotSubTypeCollection(_collection); + } + + public: virtual Hurricane::Locator* getLocator() const + // ************************************************************ + { + return new Locator(_collection); + } + +// Accessors +// ********* + + public: virtual string _getString() const + // ************************************** + { + return "<" + _TName("NotSubTypeCollection") + " " + getString(_collection) + ">"; + } + +}; + // **************************************************************************************************** // SubSetCollection implementation @@ -909,7 +1081,6 @@ inline ForEachIterator& ForEachIterator::operator++ (int) for ( ForEachIterator iterator(collection); iterator.isValid() ; iterator++ ) - } // End of Hurricane namespace. @@ -932,6 +1103,24 @@ template inline Hurricane::Record* getRecord ( const Hurricane::C { return collection->_getRecord(); } +template +inline void jsonWrite ( JsonWriter* w, const std::string& key, Hurricane::GenericCollection collection ) +{ + if (Hurricane::inltrace(50)) + std::cerr << Hurricane::tab + << "jsonWrite< GenericCollection<" << Hurricane::demangle(typeid(Type).name()) + << "> >(w,key,coll)" << " key:\"" << key << "\"" << std::endl; + Hurricane::ltracein(50); + + w->key( key ); + w->startArray(); + for ( Type element : collection ) jsonWrite( w, element ); + w->endArray(); + + Hurricane::ltraceout(50); +} + + #include "hurricane/MultisetCollection.h" #include "hurricane/SetCollection.h" #include "hurricane/MapCollection.h" diff --git a/hurricane/src/hurricane/hurricane/Commons.h b/hurricane/src/hurricane/hurricane/Commons.h index 9825b625..7ccabc15 100644 --- a/hurricane/src/hurricane/hurricane/Commons.h +++ b/hurricane/src/hurricane/hurricane/Commons.h @@ -740,6 +740,8 @@ inline Hurricane::Record* getRecord ( const std::multiset* s ) #include "hurricane/Slot.h" #include "hurricane/Tabulation.h" +#include "hurricane/JsonWriter.h" +#include "hurricane/JsonReader.h" #endif // HURRICANE_COMMONS_H diff --git a/hurricane/src/hurricane/hurricane/Component.h b/hurricane/src/hurricane/hurricane/Component.h index 232b1e1d..b330fd21 100644 --- a/hurricane/src/hurricane/hurricane/Component.h +++ b/hurricane/src/hurricane/hurricane/Component.h @@ -33,7 +33,6 @@ class Rubber; class Layer; - // **************************************************************************************************** // Component declaration // **************************************************************************************************** @@ -59,8 +58,9 @@ class Component : public Go { public: virtual bool isMaster() const {return true;}; - public: virtual string _getTypeName() const { return _TName("Component::BodyHook"); }; + public: virtual string _getTypeName() const { return "Component::BodyHook"; }; public: virtual string _getString() const; + public: static Hook* _compToHook(Component*); }; @@ -101,6 +101,7 @@ class Component : public Go { public: virtual void materialize(); public: virtual void unmaterialize(); public: virtual void invalidate(bool propagateFlag = true); + public: virtual void forceId(unsigned int id); // Filters // ******* @@ -114,6 +115,8 @@ class Component : public Go { protected: virtual void _preDestroy(); + public: virtual void _toJson ( JsonWriter* ) const; + public: virtual void _toJsonSignature(JsonWriter*) const; public: virtual string _getString() const; public: virtual Record* _getRecord() const; public: Component* _getNextOfNetComponentSet() const {return _nextOfNetComponentSet;}; @@ -128,6 +131,12 @@ class Component : public Go { double getArea ( Component* component ); +class JsonComponent : public JsonEntity { +// ************************************ + + public: JsonComponent(unsigned long flags); +}; + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Contact.h b/hurricane/src/hurricane/hurricane/Contact.h index 942c5b29..93b91c44 100644 --- a/hurricane/src/hurricane/hurricane/Contact.h +++ b/hurricane/src/hurricane/hurricane/Contact.h @@ -26,7 +26,6 @@ namespace Hurricane { - // **************************************************************************************************** // Contact declaration // **************************************************************************************************** @@ -52,8 +51,9 @@ class Contact : public Component { public: virtual bool isMaster() const {return false;}; - public: virtual string _getTypeName() const { return _TName("Contact::AnchorHook"); }; + public: virtual string _getTypeName() const { return "Contact::AnchorHook"; }; public: virtual string _getString() const; + public: static Hook* _compToHook(Component*); }; // Attributes @@ -141,6 +141,7 @@ class Contact : public Component { protected: virtual void _preDestroy(); + public: virtual void _toJson(JsonWriter*) const; public: virtual string _getTypeName() const {return _TName("Contact");}; public: virtual string _getString() const; public: virtual Record* _getRecord() const; @@ -148,6 +149,15 @@ class Contact : public Component { }; +class JsonContact : public JsonComponent { +// *************************************** + + public: JsonContact(unsigned long flags); + public: virtual string getTypeName() const; + public: virtual JsonContact* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/DBo.h b/hurricane/src/hurricane/hurricane/DBo.h index 197ae473..44714b2b 100644 --- a/hurricane/src/hurricane/hurricane/DBo.h +++ b/hurricane/src/hurricane/hurricane/DBo.h @@ -1,4 +1,3 @@ - // -*- C++ -*- // // Copyright (c) BULL S.A. 2000-2015, All Rights Reserved @@ -19,12 +18,7 @@ // License along with Hurricane. If not, see // . // -// =================================================================== -// -// $Id$ -// -// x-----------------------------------------------------------------x -// | | +// +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | // | | @@ -32,14 +26,11 @@ // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Header : "./hurricane/DBo.h" | -// | *************************************************************** | -// | U p d a t e s | -// | | -// x-----------------------------------------------------------------x +// +-----------------------------------------------------------------+ -#ifndef __HURRICANE_DBO__ -#define __HURRICANE_DBO__ +#ifndef HURRICANE_DBO_H +#define HURRICANE_DBO_H #include "hurricane/DBos.h" #include "hurricane/Name.h" @@ -52,40 +43,39 @@ namespace Hurricane { // ------------------------------------------------------------------- // Class : "Hurricane::DBo". - class DBo { - public: - // Methods. - virtual void destroy(); - inline set& _getPropertySet (); - void _onDestroyed ( Property* property ); - Property* getProperty ( const Name& ) const; - Properties getProperties () const; - inline bool hasProperty () const; - void put ( Property* ); - void remove ( Property* ); - void removeProperty ( const Name& ); - void clearProperties (); - // Hurricane Managment. - virtual string _getTypeName () const; - virtual string _getString () const; - virtual Record* _getRecord () const; - - private: - // Internal: Attributes. - mutable set _propertySet; - - protected: - // Internal: Constructors & Destructors. - DBo (); - virtual ~DBo (); - virtual void _postCreate (); - virtual void _preDestroy (); - private: - // Forbidden: Copies. - DBo ( const DBo& ); - DBo& operator= ( const DBo& ); + virtual void destroy (); + inline set& _getPropertySet (); + void _onDestroyed ( Property* property ); + Property* getProperty ( const Name& ) const; + Properties getProperties () const; + inline bool hasProperty () const; + void put ( Property* ); + void remove ( Property* ); + void removeProperty ( const Name& ); + void clearProperties (); + virtual string _getTypeName () const; + virtual string _getString () const; + virtual Record* _getRecord () const; + virtual void _toJson ( JsonWriter* ) const; + virtual void _toJsonCollections ( JsonWriter* ) const; + virtual void _toJsonSignature ( JsonWriter* ) const; + void toJson ( JsonWriter* ) const; + void toJsonSignature ( JsonWriter* ) const; + + private: + mutable set _propertySet; + + protected: + DBo (); + virtual ~DBo (); + virtual void _postCreate (); + virtual void _preDestroy (); + + private: + DBo ( const DBo& ); + DBo& operator= ( const DBo& ); }; @@ -94,10 +84,17 @@ namespace Hurricane { inline bool DBo::hasProperty () const { return !_propertySet.empty(); } -} // End of Hurricane namespace. +// ------------------------------------------------------------------- +// Class : "Hurricane::JsonDBo". + class JsonDBo : public JsonObject { + public: + JsonDBo ( unsigned int flags ); +}; + + +} // Hurricane namespace. INSPECTOR_P_SUPPORT(Hurricane::DBo); - -#endif // __HURRICANE_DBO__ +#endif // HURRICANE_DBO_H diff --git a/hurricane/src/hurricane/hurricane/DataBase.h b/hurricane/src/hurricane/hurricane/DataBase.h index 81054082..efd1bc22 100644 --- a/hurricane/src/hurricane/hurricane/DataBase.h +++ b/hurricane/src/hurricane/hurricane/DataBase.h @@ -20,11 +20,13 @@ #ifndef HURRICANE_DATA_BASE #define HURRICANE_DATA_BASE +#include #include "hurricane/DBo.h" #include "hurricane/DbU.h" namespace Hurricane { +class Cell; class Library; class Technology; @@ -37,8 +39,6 @@ class Technology; class DataBase : public DBo { // ************************ -# if !defined(__DOXYGEN_PROCESSOR__) - // Types // ***** @@ -50,6 +50,7 @@ class DataBase : public DBo { private: static DataBase* _db; private: Technology* _technology; private: Library* _rootLibrary; + private: function _cellLoader; // Constructors // ************ @@ -69,8 +70,7 @@ class DataBase : public DBo { public: void _setTechnology(Technology* technology) {_technology = technology;}; public: void _setRootLibrary(Library* rootLibrary) {_rootLibrary = rootLibrary;}; - -# endif + public: void _setCellLoader(function loader) { _cellLoader=loader; }; public: static DataBase* create(); @@ -79,6 +79,8 @@ class DataBase : public DBo { public: Technology* getTechnology() const {return _technology;}; public: Library* getRootLibrary() const {return _rootLibrary;}; + public: Library* getLibrary(string) const; + public: Cell* getCell(string) const; public: static DataBase* getDB(); }; diff --git a/hurricane/src/hurricane/hurricane/DbU.h b/hurricane/src/hurricane/hurricane/DbU.h index 11b03828..18a19eb1 100644 --- a/hurricane/src/hurricane/hurricane/DbU.h +++ b/hurricane/src/hurricane/hurricane/DbU.h @@ -180,4 +180,8 @@ namespace Hurricane { } // End of Hurricane namespace. +// inline void jsonWriteDbU ( JsonWriter* w, const std::string& key, long* value ) +// { w->key( key ); w->write( value ); } + + #endif // HURRICANE_DBU_H diff --git a/hurricane/src/hurricane/hurricane/DeepNet.h b/hurricane/src/hurricane/hurricane/DeepNet.h index e41c0d0a..6ff462d3 100644 --- a/hurricane/src/hurricane/hurricane/DeepNet.h +++ b/hurricane/src/hurricane/hurricane/DeepNet.h @@ -36,45 +36,47 @@ #include "hurricane/HyperNet.h" #include "hurricane/Occurrence.h" - namespace Hurricane { - class DeepNet : public Net { - // Attributes. +// ------------------------------------------------------------------- +// Class : "DeepNet". + + class DeepNet : public Net { + public: + typedef Net Inherit; + public: + static DeepNet* create ( HyperNet& hyperNet ); + inline Occurrence getRootNetOccurrence () const; + virtual bool isDeepNet () const { return true; }; + size_t _createRoutingPads ( unsigned int flags=0 ); + virtual Record* _getRecord () const; + virtual string _getTypeName () const { return "DeepNet"; }; + virtual void _toJson ( JsonWriter* ) const; + protected: + DeepNet ( Occurrence& netOccurrence ); protected: Occurrence _netOccurrence; - // Constructors. - protected: - DeepNet ( Occurrence& netOccurrence ); + }; - // Inspector Management. + + inline Occurrence DeepNet::getRootNetOccurrence() const { return _netOccurrence; } + + Net* getDeepNet(HyperNet& hyperNet); + + +// ------------------------------------------------------------------- +// Class : "JsonDeepNet". + + class JsonDeepNet : public JsonNet { public: - virtual Record* _getRecord () const; - virtual string _getTypeName() const { return "DeepNet"; }; - - // Constructors. - public: - static DeepNet* create ( HyperNet& hyperNet ); - - // Accessors. - public: - inline Occurrence getRootNetOccurrence () const; - - // Predicates. - public: - virtual bool isDeepNet () const { return true; }; - - // Internal Modifiers. - public: - size_t _createRoutingPads ( unsigned int flags=0 ); - -}; - -inline Occurrence DeepNet::getRootNetOccurrence() const { return _netOccurrence; } - -Net* getDeepNet(HyperNet& hyperNet); + JsonDeepNet ( unsigned long flags ); + virtual ~JsonDeepNet (); + virtual string getTypeName () const; + virtual JsonDeepNet* clone ( unsigned long ) const; + virtual void toData ( JsonStack&); + }; } // Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/DesignBlob.h b/hurricane/src/hurricane/hurricane/DesignBlob.h new file mode 100644 index 00000000..c5c9adaf --- /dev/null +++ b/hurricane/src/hurricane/hurricane/DesignBlob.h @@ -0,0 +1,60 @@ +// -*- mode: C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/DesignBlob.h" | +// +-----------------------------------------------------------------+ + + +#ifndef HURRICANE_DESIGN_BLOB_H +#define HURRICANE_DESIGN_BLOB_H + +#include "hurricane/Commons.h" + + +namespace Hurricane { + + class Cell; + +// ------------------------------------------------------------------- +// Classes : "DesignBlob". + + class DesignBlob { + public: + inline DesignBlob ( Cell* ); + inline Cell* getTopCell () const; + void toJson ( JsonWriter* ) const; + inline std::string _getTypeName () const; + private: + Cell* _topCell; + }; + + + inline DesignBlob::DesignBlob ( Cell* topCell ) : _topCell(topCell) { } + inline Cell* DesignBlob::getTopCell () const { return _topCell; } + inline std::string DesignBlob::_getTypeName () const { return "DesignBlob"; } + + +// ------------------------------------------------------------------- +// Class : "Hurricane::JsonDesignBlob". + + class JsonDesignBlob : public JsonObject { + public: + JsonDesignBlob ( unsigned long flags ); + virtual std::string getTypeName () const; + virtual JsonDesignBlob* clone ( unsigned long ) const; + virtual void toData ( JsonStack& ); +}; + + +} // Hurricane namespace. + +#endif diff --git a/hurricane/src/hurricane/hurricane/Entity.h b/hurricane/src/hurricane/hurricane/Entity.h index b3c5679f..2fe01aec 100644 --- a/hurricane/src/hurricane/hurricane/Entity.h +++ b/hurricane/src/hurricane/hurricane/Entity.h @@ -35,26 +35,38 @@ namespace Hurricane { // ------------------------------------------------------------------- // Class : "Hurricane::Entity". - class Entity : public DBo { public: typedef DBo Inherit; public: - static unsigned int getIdCounter (); + enum Flags { ForcedIdMode = (1<<0) + , NextIdSet = (1<<1) + }; public: - inline unsigned int getId () const; - virtual Cell* getCell () const = 0; - virtual Box getBoundingBox() const = 0; - virtual string _getString () const; - virtual Record* _getRecord () const; - Quark* _getQuark ( SharedPath* sharedPath = NULL ) const; - protected: - Entity (); - virtual void _preDestroy (); + static unsigned int getIdCounter (); + unsigned int getNextId (); + static void setNextId ( unsigned int ); + static bool inForcedIdMode (); + static void enableForcedIdMode (); + static void disableForcedIdMode (); + public: + inline unsigned int getId () const; + virtual Cell* getCell () const = 0; + virtual Box getBoundingBox () const = 0; + void setId ( unsigned int ); + virtual void _toJson ( JsonWriter* ) const; + virtual string _getString () const; + virtual Record* _getRecord () const; + Quark* _getQuark ( SharedPath* sharedPath = NULL ) const; + protected: + Entity (); + virtual void _preDestroy (); private: - static unsigned int _idCounter; - unsigned int _id; + static unsigned long _flags; + static unsigned int _nextId; + static unsigned int _idCounter; + unsigned int _id; public: struct CompareById : public std::binary_function { @@ -68,6 +80,24 @@ namespace Hurricane { { return ((lhs)?lhs->getId():0) < ((rhs)?rhs->getId():0); } +// ------------------------------------------------------------------- +// Class : "Hurricane::JsonEntity". + + class JsonEntity : public JsonDBo { + public: + JsonEntity ( unsigned long flags ); + template inline void update ( JsonStack&, T ); +}; + + + template inline void JsonEntity::update ( JsonStack& stack, T hobject ) + { + unsigned int jsonId = get(stack,"_id"); + + JsonObject::update( stack, hobject ); + stack.addEntity( jsonId, hobject ); + } + } // Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Hook.h b/hurricane/src/hurricane/hurricane/Hook.h index 8cc8de2d..c9f1ce57 100644 --- a/hurricane/src/hurricane/hurricane/Hook.h +++ b/hurricane/src/hurricane/hurricane/Hook.h @@ -35,9 +35,12 @@ class Component; class Hook { // ********* + typedef Hook* (*compToHook_t)(Component*); + // Attributes // ********** + private: static map _compToHookMap; private: Hook* _nextHook; // Constructors @@ -95,13 +98,16 @@ class Hook { // Others // ****** + public: static void addCompToHook(const string&, compToHook_t ); + public: static Hook* compToHook(const string& tname, Component* ); + public: string toJson() const; + public: virtual string _getTypeName() const = 0; public: virtual string _getString() const = 0; public: virtual Record* _getRecord() const; }; - } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Horizontal.h b/hurricane/src/hurricane/hurricane/Horizontal.h index d2e3c1d0..2a2cdcd7 100644 --- a/hurricane/src/hurricane/hurricane/Horizontal.h +++ b/hurricane/src/hurricane/hurricane/Horizontal.h @@ -104,6 +104,8 @@ class Horizontal : public Segment { // Others // ****** + public: virtual void _toJson(JsonWriter*) const; + public: static JsonObject* getJsonObject(unsigned long flags); public: virtual string _getTypeName() const {return _TName("Horizontal");}; public: virtual string _getString() const; public: virtual Record* _getRecord() const; @@ -111,6 +113,15 @@ class Horizontal : public Segment { }; +class JsonHorizontal : public JsonSegment { +// **************************************** + + public: JsonHorizontal(unsigned long flags); + public: virtual string getTypeName() const; + public: virtual JsonHorizontal* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Instance.h b/hurricane/src/hurricane/hurricane/Instance.h index 538714b7..19cab0d0 100644 --- a/hurricane/src/hurricane/hurricane/Instance.h +++ b/hurricane/src/hurricane/hurricane/Instance.h @@ -51,6 +51,7 @@ class Instance : public Go { public: PlacementStatus(const Code& code = UNPLACED); public: PlacementStatus(const PlacementStatus& placementstatus); + public: PlacementStatus(string); public: PlacementStatus& operator=(const PlacementStatus& placementstatus); @@ -178,6 +179,8 @@ class Instance : public Go { public: virtual string _getTypeName() const {return _TName("Instance");}; public: virtual string _getString() const; public: virtual Record* _getRecord() const; + public: virtual void _toJson(JsonWriter*) const; + public: virtual void _toJsonCollections(JsonWriter*) const; public: PlugMap& _getPlugMap() {return _plugMap;}; public: SharedPath* _getSharedPath(const SharedPath* tailSharedPath) const {return _sharedPathMap.getElement(tailSharedPath);} public: SharedPathes _getSharedPathes() const {return _sharedPathMap.getElements();}; @@ -191,6 +194,15 @@ class Instance : public Go { }; +class JsonInstance : public JsonEntity { +// ************************************* + + public: JsonInstance(unsigned long flags); + public: virtual string getTypeName() const; + public: virtual JsonInstance* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; + } // End of Hurricane namespace. @@ -245,6 +257,11 @@ INSPECTOR_P_SUPPORT(Hurricane::Instance::PlacementStatus); INSPECTOR_P_SUPPORT(Hurricane::Instance::PlugMap); INSPECTOR_P_SUPPORT(Hurricane::Instance::SharedPathMap); +inline void jsonWrite ( JsonWriter* w, const std::string& key, const Hurricane::Instance::PlacementStatus& status ) +{ + w->key( key ); + w->write( getString(status.getCode()) ); +} #endif // HURRICANE_INSTANCE diff --git a/hurricane/src/hurricane/hurricane/Interval.h b/hurricane/src/hurricane/hurricane/Interval.h index e62c2841..7ee2f263 100644 --- a/hurricane/src/hurricane/hurricane/Interval.h +++ b/hurricane/src/hurricane/hurricane/Interval.h @@ -108,6 +108,15 @@ class Interval { } // End of Hurricane namespace. +inline void jsonWrite ( JsonWriter* w, const std::string& key, const Hurricane::Interval* interval ) +{ + w->key( key ); + w->startArray(); + w->write( &interval->getVMin() ); + w->write( &interval->getVMax() ); + w->endArray(); +} + INSPECTOR_PV_SUPPORT(Hurricane::Interval); diff --git a/hurricane/src/hurricane/hurricane/IntrusiveMap.h b/hurricane/src/hurricane/hurricane/IntrusiveMap.h index cffd7474..bb2cd8ca 100644 --- a/hurricane/src/hurricane/hurricane/IntrusiveMap.h +++ b/hurricane/src/hurricane/hurricane/IntrusiveMap.h @@ -449,6 +449,13 @@ template class IntrusiveMap { }; + template + inline GenericCollection getCollection(const IntrusiveMap& intrusiveMap) + // ******************************************************************************************** + { + return intrusiveMap.getElements(); + } + } // End of Hurricane namespace. @@ -470,6 +477,15 @@ inline Hurricane::Record* getRecord ( const Hurricane::IntrusiveMap { return intrusiveMap->_getRecord(); } +template +inline void jsonWrite ( JsonWriter* w, const std::string& key, Hurricane::IntrusiveMap* intrusiveMap ) +{ + w->key( key ); + w->startArray(); + for ( Element* element : intrusiveMap->getElements() ) jsonWrite( w, element ); + w->endArray(); +} + #endif // HURRICANE_INTRUSIVE_MAP diff --git a/hurricane/src/hurricane/hurricane/IntrusiveSet.h b/hurricane/src/hurricane/hurricane/IntrusiveSet.h index 97b9f04b..7f245de7 100644 --- a/hurricane/src/hurricane/hurricane/IntrusiveSet.h +++ b/hurricane/src/hurricane/hurricane/IntrusiveSet.h @@ -470,6 +470,11 @@ template class IntrusiveSet { }; + template + inline GenericCollection getCollection(const IntrusiveSet& intrusiveSet) + // **************************************************************************************** + { return intrusiveSet.getElements(); } + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/JsonReader.h b/hurricane/src/hurricane/hurricane/JsonReader.h new file mode 100644 index 00000000..16f62490 --- /dev/null +++ b/hurricane/src/hurricane/hurricane/JsonReader.h @@ -0,0 +1,439 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2015-2015, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/JsonReader.h" | +// +-----------------------------------------------------------------+ + + +#ifndef HURRICANE_JSON_READER_H +#define HURRICANE_JSON_READER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Hurricane { + + class Hook; + class Entity; + class Cell; + class Component; + + +// ------------------------------------------------------------------- +// Class : "JsonObject". + + class JsonStack; + class JsonArray { }; + + +// ------------------------------------------------------------------- +// Class : "JsonAttribute". + + class JsonAttribute { + public: + inline JsonAttribute ( const std::string& key, std::type_index tid ); + inline std::string key () const; + inline std::type_index tid () const; + private: + std::string _key; + std::type_index _tid; + }; + + inline JsonAttribute::JsonAttribute ( const std::string& key, std::type_index tid ) : _key(key), _tid(tid) { } + inline std::string JsonAttribute::key () const { return _key; } + inline std::type_index JsonAttribute::tid () const { return _tid; } + + +// ------------------------------------------------------------------- +// Class : "JsonObject". + + class JsonObject { + public: + JsonObject ( unsigned long flags ); + virtual ~JsonObject (); + virtual bool isDummy () const; + virtual std::string getTypeName () const = 0; + inline std::string getStackName () const; + bool check ( JsonStack&, string fname ) const; + void print ( std::ostream& ) const; + bool has ( const std::string& key ) const; + void add ( const std::string& key, std::type_index tid ); + void remove ( const std::string& key ); + template inline T get ( JsonStack&, const std::string& key ) const; + inline void copyAttrs ( const JsonObject*, bool reset=false ); + inline void clear (); + inline std::string getName () const; + inline void setName ( const string& ); + template inline T& getObject () const; + template inline void setObject ( T& ) ; + inline bool isBound () const; + virtual JsonObject* clone ( unsigned long flags ) const = 0; + template void toJson ( JsonWriter*, C* object ) const; + virtual void toData ( JsonStack& ); + unsigned int presetId ( JsonStack& ); + template inline void update ( JsonStack&, T ); + inline JsonObject* setFlags ( unsigned long mask ); + inline JsonObject* resetFlags ( unsigned long mask ); + inline bool issetFlags ( unsigned long mask ) const; + protected: + unsigned long _flags; + std::string _name; + std::vector _stackeds; + std::vector _attributes; + std::vector _collections; + boost::any _object; + }; + + + inline bool JsonObject::isBound () const { return not _object.empty(); } + inline std::string JsonObject::getName () const { return _name; } + inline void JsonObject::setName ( const string& name ) { _name=name; } + inline JsonObject* JsonObject::setFlags ( unsigned long mask ) { _flags |= mask; return this; } + inline JsonObject* JsonObject::resetFlags ( unsigned long mask ) { _flags &= ~mask; return this; } + inline bool JsonObject::issetFlags ( unsigned long mask ) const { return _flags & mask; } + + inline std::string JsonObject::getStackName () const + { return (_name.empty()) ? std::string(".")+getTypeName(): _name; } + + template inline T& JsonObject::getObject () const + { return boost::any_cast(_object); } + + template inline void JsonObject::setObject ( T& t ) + { _object = t; } + + inline void JsonObject::copyAttrs ( const JsonObject* other, bool reset ) + { + if (reset) _attributes.clear(); + for ( size_t i=0 ; i_attributes.size() ; ++i ) + _attributes.push_back( other->_attributes[i] ); + } + + void JsonObject::clear () + { + _stackeds.clear(); + _attributes.clear(); + _collections.clear(); + boost::any emptyAny; + _object.swap( emptyAny ); + } + + +// ------------------------------------------------------------------- +// Class : "JsonKey". + + class JsonKey : public JsonObject { + public: + inline JsonKey ( const std::string& ); + virtual std::string getTypeName () const; + virtual JsonKey* clone ( unsigned long ) const; + private: + std::string _key; + }; + + +// ------------------------------------------------------------------- +// Class : "JsonDummy". + + class JsonDummy : public JsonObject { + public: + inline JsonDummy (); + virtual bool isDummy () const; + virtual std::string getTypeName () const; + void setTypeName ( const std::string& name ); + virtual JsonDummy* clone ( unsigned long ) const; + private: + std::string _typename; + }; + + +} // Hurricane namespace. + + +namespace std { + + template<> + struct less { + inline bool operator() ( const Hurricane::JsonObject* lhs, const Hurricane::JsonObject* rhs ) + { return lhs->getTypeName() < rhs->getTypeName(); } + }; + +} // std namespace. + + +namespace Hurricane { + +// ------------------------------------------------------------------- +// Class : "JsonTypes". + + class JsonTypes { + public: + static void initialize (); + static void registerType ( JsonObject* ); + static JsonObject* find ( const std::string& tname ); + private: + JsonTypes (); + ~JsonTypes (); + JsonTypes ( const JsonTypes& ); + void _registerType ( JsonObject* ); + JsonObject* _find ( const std::string& tname ); + private: + static JsonTypes* _jsonTypes; + std::set _jsonObjects; + }; + + +// ------------------------------------------------------------------- +// Class : "HookKey". + + class HookKey { + public: + inline HookKey ( unsigned int id, const std::string& tname ); + inline unsigned int id () const; + inline std::string tname () const; + private: + unsigned int _id; + std::string _tname; + }; + + + inline HookKey::HookKey ( unsigned int id, const std::string& tname ) : _id(id), _tname(tname) { } + inline unsigned int HookKey::id () const { return _id; } + inline std::string HookKey::tname () const { return _tname; } + + inline bool operator< ( const HookKey& lhs, const HookKey& rhs ) + { + if (lhs.id() != rhs.id()) return lhs.id() < rhs.id(); + return lhs.tname() < rhs.tname(); + } + + +// ------------------------------------------------------------------- +// Class : "HookElement". + + class HookElement { + public: + enum Flags { OpenRingStart = (1<<0) + , ClosedRing = (1<<1) + }; + public: + inline HookElement ( Hook*, unsigned long flags=0 ); + inline Hook* hook () const; + inline HookElement* next () const; + inline void setHook ( Hook* ); + inline void setNext ( HookElement* ); + inline unsigned long flags () const; + inline HookElement& setFlags ( unsigned long mask ); + inline HookElement& resetFlags ( unsigned long mask ); + inline bool issetFlags ( unsigned long mask ) const; + private: + Hook* _hook; + HookElement* _next; + unsigned long _flags; + }; + + + inline HookElement::HookElement ( Hook* hook, unsigned long flags ) : _hook(hook), _next(NULL), _flags(flags) { } + inline Hook* HookElement::hook () const { return _hook; } + inline HookElement* HookElement::next () const { return _next; } + inline void HookElement::setHook ( Hook* hook ) { _hook = hook; } + inline void HookElement::setNext ( HookElement* element ) { _next = element; } + inline unsigned long HookElement::flags () const { return _flags; } + inline HookElement& HookElement::setFlags ( unsigned long mask ) { _flags |= mask; return *this; } + inline HookElement& HookElement::resetFlags ( unsigned long mask ) { _flags &= ~mask; return *this; } + inline bool HookElement::issetFlags ( unsigned long mask ) const { return _flags & mask; } + + + typedef map HookLut; + + +// ------------------------------------------------------------------- +// Class : "JsonStack". + + class JsonStack { + public: + typedef std::pair Element; + public: + static bool hookFromString ( std::string s, unsigned int& id, std::string& tname ); + public: + inline JsonStack (); + inline size_t size () const; + template inline void push_back ( const std::string&, T ); + inline void pop_back ( size_t count=1 ); + inline int rhas ( const std::string& ) const; + template inline T as ( const std::string& ) const; + template inline T as ( int ) const; + template inline T getEntity ( unsigned int ) const; + void addEntity ( unsigned int jsonId, Entity* ); + void addHookLink ( Hook*, unsigned int jsonId, const std::string& jsonNext ); + Hook* getHook ( unsigned int jsonId, const std::string& tname ) const; + bool checkRings () const; + void buildRings () const; + inline void clearHookLinks (); + void print ( std::ostream& ) const; + inline JsonStack* setFlags ( unsigned long mask ); + inline JsonStack* resetFlags ( unsigned long mask ); + inline bool issetFlags ( unsigned long mask ) const; + inline const Element& operator[] ( int index ) const; + private: + unsigned long _flags; + vector _stack; + std::map _entities; + HookLut _hooks; + }; + + + inline JsonStack::JsonStack () + : _flags(0), _stack(), _entities(), _hooks() + { } + + template inline void JsonStack::push_back ( const std::string& key, T t ) + { + ltrace(51) << "JsonStack::push_back() key:" << key << " value:" << t + << " (" << demangle(typeid(T)) << ")." << endl; + _stack.push_back(std::make_pair(key,boost::any(t))); + } + + inline void JsonStack::pop_back ( size_t count ) + { + while (count--) { + if (_stack.empty()) { + std::cerr << "[ERROR] JsonStack::pop_back(): Stack is empty, but " + << (count+1) << " elements remains to pop." << std::endl; + break; + } + ltrace(51) << "| _stack.pop_back() " << _stack.back().first << endl; + _stack.pop_back(); + } + } + + inline const JsonStack::Element& JsonStack::operator[] ( int index ) const + { + if (index < 0) return _stack[_stack.size()+index]; + return _stack[index]; + } + + inline int JsonStack::rhas ( const std::string& key ) const + { + if (_stack.empty()) return 0; + + int i = _stack.size()-1; + do { + if (_stack[i].first == key) { + ltrace(51) << "JsonStack::rhas(): key \"" << key << "\" found at index:" + << (i-(int)_stack.size()) << " (i:" << i << ") " + << "(" << demangle(_stack[i].second.type().name()) << ")." + << endl; + return i-(int)_stack.size(); + } + if (i == 0) break; + --i; + } while ( true ); + + ltrace(51) << "JsonStack::rhas(): key \"" << key << "\" not found (returning index: 0)." << endl; + return 0; + } + + template inline T JsonStack::as ( const std::string& key ) const + { + if (not _stack.empty()) { + int i = _stack.size()-1; + do { + if (_stack[i].first == key) { + ltrace(51) << "JsonStack::as() k:" << key + << " value:" << demangle(_stack[i].second.type().name()) << std::endl; + return boost::any_cast( _stack[i].second ); + } + if (i == 0) break; + --i; + } while ( true ); + + std::cerr << "[ERROR] JsonStack::as(key): No element with key \"" + << key << "\" in stack." << std::endl; + } else { + std::cerr << "[ERROR] JsonStack::as(key): Stack is empty while searching for key \"" + << key << "\"." << std::endl; + } + + return T(); + } + + template inline T JsonStack::as ( int index ) const + { + size_t i = (index >= 0) ? index : (_stack.size()+index); + return boost::any_cast( _stack[i].second ); + } + + template inline T JsonStack::getEntity ( unsigned int id ) const + { + std::map::const_iterator it = _entities.find(id); + if (it == _entities.end()) return NULL; + return dynamic_cast((*it).second); + } + + inline void JsonStack::clearHookLinks () { _hooks.clear(); } + inline size_t JsonStack::size () const { return _stack.size(); } + inline JsonStack* JsonStack::setFlags ( unsigned long mask ) { _flags |= mask; return this; } + inline JsonStack* JsonStack::resetFlags ( unsigned long mask ) { _flags &= ~mask; return this; } + inline bool JsonStack::issetFlags ( unsigned long mask ) const { return _flags & mask; } + + + template + T JsonObject::get ( JsonStack& stack, const std::string& key ) const + { + int index = stack.rhas(key); + if (index == 0) return T();; + if (stack[index].second.type() == typeid(void*)) return T(); + + return stack.as( index ); + } + + template inline void JsonObject::update ( JsonStack& stack, T hobject ) + { + stack.pop_back( _attributes.size() ); + stack.push_back( getStackName(), hobject ); + setObject( hobject ); + } + + +// ------------------------------------------------------------------- +// Function : Json Parsers. + + Cell* jsonCellParse ( std::string filename ); + Cell* jsonBlobParse ( std::string filename ); + + +} // Hurricane namespace. + +#endif // HURRICANE_JSON_READER_H diff --git a/hurricane/src/hurricane/hurricane/JsonWriter.h b/hurricane/src/hurricane/hurricane/JsonWriter.h new file mode 100644 index 00000000..93304d27 --- /dev/null +++ b/hurricane/src/hurricane/hurricane/JsonWriter.h @@ -0,0 +1,207 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2015-2015, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/JsonWriter.h" | +// +-----------------------------------------------------------------+ + + +#ifndef HURRICANE_SLOT_H +#error "JsonWriter.h must be included through Commons.h" +#endif + +#ifndef HURRICANE_JSON_WRITER_H +#define HURRICANE_JSON_WRITER_H + +#include +#include + +namespace rapidjson { + class FileWriteStream; +} + +//namespace Hurricane { + + +// ------------------------------------------------------------------- +// Class : "JsonWriter". + + class JsonWriter { + public: + enum Mode { UsePlugReference = (1<<0) + , DesignBlobMode = (1<<1) + , CellMode = (1<<2) + , RegisterMode = (1<<3) + }; + public: + JsonWriter ( std::string fileName ); + ~JsonWriter (); + void key ( const char* ); + void key ( std::string ); + void startObject (); + void startArray (); + void endObject (); + void endArray (); + void write (); + void write ( const char* ); + void write ( std::string ); + void write ( const std::string* ); + void write ( bool ); + void write ( const bool* ); + void write ( int ); + void write ( const int* ); + void write ( long ); + void write ( const long* ); + void write ( unsigned int ); + void write ( const unsigned int* ); + void write ( unsigned long ); + void write ( const unsigned long* ); + void close (); + JsonWriter* setFlags ( unsigned long mask ); + JsonWriter* resetFlags ( unsigned long mask ); + bool issetFlags ( unsigned long mask ) const; + unsigned long getFlags () const; + private: + JsonWriter ( const JsonWriter& ); + JsonWriter& operator= ( const JsonWriter& ) const; + private: + unsigned long _flags; + size_t _bufferSize; + char* _buffer; + FILE* _file; + rapidjson::FileWriteStream* _stream; + void* _writer; + }; + + +//} // Hurricane namespace. + + +// All jsonWrite() overload are put in the top level namespace, +// in order to facilitate additions from other tools. + +inline void jsonWrite ( JsonWriter* w ) { w->write( ); } +inline void jsonWrite ( JsonWriter* w, const char* s ) { w->write(s); } +inline void jsonWrite ( JsonWriter* w, const std::string* s ) { w->write(s); } +inline void jsonWrite ( JsonWriter* w, std::string s ) { w->write(s); } +inline void jsonWrite ( JsonWriter* w, const bool* v ) { w->write(v); } +inline void jsonWrite ( JsonWriter* w, bool v ) { w->write(v); } +inline void jsonWrite ( JsonWriter* w, const int* v ) { w->write(v); } +inline void jsonWrite ( JsonWriter* w, int v ) { w->write(v); } +inline void jsonWrite ( JsonWriter* w, const long* v ) { w->write(v); } +inline void jsonWrite ( JsonWriter* w, long v ) { w->write(v); } +inline void jsonWrite ( JsonWriter* w, const unsigned int* v ) { w->write(v); } +inline void jsonWrite ( JsonWriter* w, unsigned int v ) { w->write(v); } +inline void jsonWrite ( JsonWriter* w, const unsigned long* v ) { w->write(v); } +inline void jsonWrite ( JsonWriter* w, unsigned long v ) { w->write(v); } + + +//template +//inline void jsonWrite ( JsonWriter* w, const std::string& key, const Type value ) +//{ w->key( key ); w->write( getString(value).c_str() ); } + + +inline void jsonWrite ( JsonWriter* w, const std::string& key, const bool* value ) +{ w->key( key ); w->write( value ); } + + +inline void jsonWrite ( JsonWriter* w, const std::string& key, bool value ) +{ w->key( key ); w->write( value ); } + + +inline void jsonWrite ( JsonWriter* w, const std::string& key, const int* value ) +{ w->key( key ); w->write( value ); } + + +inline void jsonWrite ( JsonWriter* w, const std::string& key, int value ) +{ w->key( key ); w->write( value ); } + + +inline void jsonWrite ( JsonWriter* w, const std::string& key, const long* value ) +{ w->key( key ); w->write( value ); } + + +inline void jsonWrite ( JsonWriter* w, const std::string& key, long value ) +{ w->key( key ); w->write( value ); } + + +inline void jsonWrite ( JsonWriter* w, const std::string& key, const unsigned int* value ) +{ w->key( key ); w->write( value ); } + + +inline void jsonWrite ( JsonWriter* w, const std::string& key, unsigned int value ) +{ w->key( key ); w->write( value ); } + + +inline void jsonWrite ( JsonWriter* w, const std::string& key, const unsigned long* value ) +{ w->key( key ); w->write( value ); } + + +inline void jsonWrite ( JsonWriter* w, const std::string& key, unsigned long value ) +{ w->key( key ); w->write( value ); } + + +inline void jsonWrite ( JsonWriter* w, const std::string& key, const char* value ) +{ w->key( key ); w->write( value ); } + + +inline void jsonWrite ( JsonWriter* w, const std::string& key, const std::string& value ) +{ w->key( key ); w->write( value ); } + + +template +inline void jsonWrite ( JsonWriter* w, const C* object ) +{ + if (Hurricane::inltrace(50)) + std::cerr << Hurricane::tab + << "jsonWrite<" << Hurricane::demangle(typeid(C).name()) << "*>(w,object)" << std::endl; + Hurricane::ltracein(50); + + if (object) object->toJson( w ); + else jsonWrite(w); + + Hurricane::ltraceout(50); +} + + +template +inline void jsonWrite ( JsonWriter* w, const std::string& key, const C* object ) +{ + if (Hurricane::inltrace(50)) + std::cerr << Hurricane::tab + << "jsonWrite<" << Hurricane::demangle(typeid(C).name()) << "*>(w,key,object)" + << " key:\"" << key << "\"" << std::endl; + Hurricane::ltracein(50); + + w->key( key ); + if (object) object->toJson( w ); + else jsonWrite(w); + + Hurricane::ltraceout(50); +} + + +#endif // HURRICANE_JSON_WRITER_H diff --git a/hurricane/src/hurricane/hurricane/Layer.h b/hurricane/src/hurricane/hurricane/Layer.h index a32b7372..3d4968c3 100644 --- a/hurricane/src/hurricane/hurricane/Layer.h +++ b/hurricane/src/hurricane/hurricane/Layer.h @@ -95,6 +95,7 @@ namespace Hurricane { inline void _setExtractMask ( const Mask& extractMask ); inline void _setNextOfTechnologyLayerMap ( Layer* layer ); virtual void _onDbuChange ( float scale ); + static const Name& _sgetName ( const Layer* ); private: // Internal: Attributes diff --git a/hurricane/src/hurricane/hurricane/Library.h b/hurricane/src/hurricane/hurricane/Library.h index dbfa24f6..f36ee18a 100644 --- a/hurricane/src/hurricane/hurricane/Library.h +++ b/hurricane/src/hurricane/hurricane/Library.h @@ -95,6 +95,7 @@ class Library : public DBo { public: DataBase* getDataBase() const {return _dataBase;}; public: Library* getLibrary() const {return _library;}; public: const Name& getName() const {return _name;}; + public: string getHierarchicalName () const; public: Library* getLibrary(const Name& name) const {return _libraryMap.getElement(name);}; public: Libraries getLibraries() const {return _libraryMap.getElements();}; public: Cell* getCell(const Name& name) const {return _cellMap.getElement(name);}; @@ -115,6 +116,7 @@ class Library : public DBo { public: virtual string _getTypeName() const {return _TName("Library");}; public: virtual string _getString() const; public: virtual Record* _getRecord() const; + public: virtual void _toJson( JsonWriter* ) const; public: LibraryMap& _getLibraryMap() {return _libraryMap;}; public: CellMap& _getCellMap() {return _cellMap;}; public: Library* _getNextOfLibraryLibraryMap() const {return _nextOfLibraryLibraryMap;}; @@ -124,6 +126,16 @@ class Library : public DBo { }; +class JsonLibrary : public JsonDBo { +// ******************************* + + public: JsonLibrary(unsigned long flags); + public: virtual string getTypeName() const; + public: virtual JsonLibrary* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; + + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Name.h b/hurricane/src/hurricane/hurricane/Name.h index 0d7452f1..6dcbe0ed 100644 --- a/hurricane/src/hurricane/hurricane/Name.h +++ b/hurricane/src/hurricane/hurricane/Name.h @@ -95,6 +95,12 @@ class Name { INSPECTOR_PV_SUPPORT(Hurricane::Name); +inline void jsonWrite ( JsonWriter* w, Hurricane::Name name ) +{ w->write( getString(name).c_str() ); } + +inline void jsonWrite ( JsonWriter* w, const std::string& key, Hurricane::Name name ) +{ w->key( key ); w->write( getString(name).c_str() ); } + #endif // HURRICANE_NAME diff --git a/hurricane/src/hurricane/hurricane/Net.h b/hurricane/src/hurricane/hurricane/Net.h index 195b3302..587e8ffc 100644 --- a/hurricane/src/hurricane/hurricane/Net.h +++ b/hurricane/src/hurricane/hurricane/Net.h @@ -41,7 +41,6 @@ namespace Hurricane { - // **************************************************************************************************** // Net declaration // **************************************************************************************************** @@ -65,6 +64,7 @@ class Net : public Entity { public: Type(const Code& code = UNDEFINED); public: Type(const Type& type); + public: Type(string); public: Type& operator=(const Type& type); @@ -101,6 +101,7 @@ class Net : public Entity { public: Direction(const Code& code = UNDEFINED); public: Direction(const Direction& direction); + public: Direction(string); public: Direction& operator =(const Direction& direction); public: Direction& operator|=(const Direction& direction); @@ -241,9 +242,11 @@ class Net : public Entity { // ****** protected: virtual void _postCreate(); - protected: virtual void _preDestroy(); + public: virtual void _toJson(JsonWriter*) const; + public: virtual void _toJsonSignature(JsonWriter*) const; + public: virtual void _toJsonCollections(JsonWriter*) const; public: virtual string _getTypeName() const {return _TName("Net");}; public: virtual string _getString() const; public: virtual Record* _getRecord() const; @@ -256,6 +259,22 @@ class Net : public Entity { }; +class JsonNet : public JsonEntity { +// ******************************** + + public: JsonNet(unsigned long flags); + public: virtual ~JsonNet(); + public: virtual string getTypeName() const; + public: virtual JsonNet* clone(unsigned long) const; + public: virtual void toData(JsonStack&); + +// Attributes +// ********** + + protected: bool _autoMaterialize; + protected: Net* _net; + protected: JsonStack* _stack; +}; } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/NetAlias.h b/hurricane/src/hurricane/hurricane/NetAlias.h index 655239d8..161b241c 100644 --- a/hurricane/src/hurricane/hurricane/NetAlias.h +++ b/hurricane/src/hurricane/hurricane/NetAlias.h @@ -60,6 +60,7 @@ namespace Hurricane { void attach ( NetAliasHook* ); void detach (); void detachAll (); + inline void toJson ( JsonWriter* ) const; virtual std::string _getString () const = 0; virtual Record* _getRecord () const; public: @@ -187,5 +188,7 @@ namespace Hurricane { INSPECTOR_P_SUPPORT(Hurricane::NetAliasHook); INSPECTOR_P_SUPPORT(Hurricane::NetMainName); INSPECTOR_P_SUPPORT(Hurricane::NetAliasName); + +inline void jsonWrite ( JsonWriter* w, const Hurricane::NetAliasHook* alias ) { jsonWrite(w,alias->getName()); } #endif // HURRICANE_NET_ALIAS_H diff --git a/hurricane/src/hurricane/hurricane/Occurrence.h b/hurricane/src/hurricane/hurricane/Occurrence.h index 0a477269..bcb67a2a 100644 --- a/hurricane/src/hurricane/hurricane/Occurrence.h +++ b/hurricane/src/hurricane/hurricane/Occurrence.h @@ -32,9 +32,8 @@ class Quark; class BasicLayer; - // **************************************************************************************************** -// Occurente declaration +// Occurrence declaration // **************************************************************************************************** class Occurrence { @@ -98,6 +97,7 @@ class Occurrence { public: string _getTypeName() const { return _TName("Occurrence"); }; public: string _getString() const; public: string getCompactString() const; + public: void toJson(JsonWriter*) const; public: Record* _getRecord() const; public: SharedPath* _getSharedPath() const {return _sharedPath;}; public: Quark* _getQuark() const; @@ -105,6 +105,19 @@ class Occurrence { }; +// **************************************************************************************************** +// JsonOccurrence declaration +// **************************************************************************************************** + + +class JsonOccurrence : public JsonObject { +// ********************************** + + public: JsonOccurrence(unsigned long); + public: virtual string getTypeName() const; + public: virtual JsonOccurrence* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Pad.h b/hurricane/src/hurricane/hurricane/Pad.h index 0a72e0f5..2350e977 100644 --- a/hurricane/src/hurricane/hurricane/Pad.h +++ b/hurricane/src/hurricane/hurricane/Pad.h @@ -73,6 +73,8 @@ class Pad : public Component { // Others // ****** + public: virtual void _toJson(JsonWriter*) const; + public: static JsonObject* getJsonObject(unsigned long flags); public: virtual string _getTypeName() const {return _TName("Pad");}; public: virtual string _getString() const; public: virtual Record* _getRecord() const; @@ -80,6 +82,15 @@ class Pad : public Component { }; +class JsonPad : public JsonComponent { +// *********************************** + + public: JsonPad(unsigned long flags); + public: virtual string getTypeName() const; + public: virtual JsonPad* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Path.h b/hurricane/src/hurricane/hurricane/Path.h index bd5d4fc6..231c864e 100644 --- a/hurricane/src/hurricane/hurricane/Path.h +++ b/hurricane/src/hurricane/hurricane/Path.h @@ -98,6 +98,7 @@ class Path { // ****** public: string getCompactString() const; + public: string getJsonString(unsigned long flags) const; public: string _getTypeName() const { return _TName("Occurrence"); }; public: string _getString() const; public: Record* _getRecord() const; diff --git a/hurricane/src/hurricane/hurricane/Plug.h b/hurricane/src/hurricane/hurricane/Plug.h index 0fac5488..245d0399 100644 --- a/hurricane/src/hurricane/hurricane/Plug.h +++ b/hurricane/src/hurricane/hurricane/Plug.h @@ -103,6 +103,7 @@ class Plug : public Component { protected: virtual void _preDestroy(); public: virtual string getName() const; + public: virtual void _toJson(JsonWriter*) const; public: virtual string _getTypeName() const {return _TName("Plug");}; public: virtual string _getString() const; public: virtual Record* _getRecord() const; @@ -114,6 +115,25 @@ class Plug : public Component { }; +class JsonPlug : public JsonComponent { +// ************************************ + + public: JsonPlug(unsigned long flags); + public: virtual string getTypeName() const; + public: virtual JsonPlug* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; + + +class JsonPlugRef : public JsonObject { +// ************************************ + + public: JsonPlugRef(unsigned long flags); + public: virtual string getTypeName() const; + public: virtual JsonPlugRef* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Point.h b/hurricane/src/hurricane/hurricane/Point.h index 72e8f532..caceb531 100644 --- a/hurricane/src/hurricane/hurricane/Point.h +++ b/hurricane/src/hurricane/hurricane/Point.h @@ -25,7 +25,6 @@ namespace Hurricane { - // **************************************************************************************************** // Point declaration // **************************************************************************************************** @@ -83,14 +82,23 @@ class Point { public: string _getTypeName() const { return _TName("Point"); }; public: string _getString() const; public: Record* _getRecord() const; + public: void toJson(JsonWriter*) const; }; +class JsonPoint : public JsonObject { +// ********************************** + + public: JsonPoint(unsigned long); + public: virtual string getTypeName() const; + public: virtual JsonPoint* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; + } // End of Hurricane namespace. - INSPECTOR_PV_SUPPORT(Hurricane::Point); diff --git a/hurricane/src/hurricane/hurricane/RoutingPad.h b/hurricane/src/hurricane/hurricane/RoutingPad.h index 9c54bc32..bf53293a 100644 --- a/hurricane/src/hurricane/hurricane/RoutingPad.h +++ b/hurricane/src/hurricane/hurricane/RoutingPad.h @@ -1,7 +1,6 @@ - // -*- C++ -*- // -// Copyright (c) BULL S.A. 2000-2013, All Rights Reserved +// Copyright (c) BULL S.A. 2000-2015, All Rights Reserved // // This file is part of Hurricane. // @@ -19,10 +18,6 @@ // License along with Hurricane. If not, see // . // -// =================================================================== -// -// $Id$ -// // +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | @@ -47,6 +42,9 @@ namespace Hurricane { class Segment; +// ------------------------------------------------------------------- +// Class : "RoutingPad". + class RoutingPad : public Component { public: typedef Component Inherit; @@ -85,6 +83,7 @@ namespace Hurricane { // Miscellaeous. Component* _getEntityAsComponent () const; Segment* _getEntityAsSegment () const; + virtual void _toJson ( JsonWriter* ) const; virtual std::string _getTypeName () const {return _TName("RoutingPad");}; virtual std::string _getString () const; virtual Record* _getRecord () const; @@ -99,6 +98,17 @@ namespace Hurricane { }; +// ------------------------------------------------------------------- +// Class : "JsonRoutingPad". + + class JsonRoutingPad : public JsonComponent { + public: + JsonRoutingPad ( unsigned long flags ); + virtual std::string getTypeName () const; + virtual JsonRoutingPad* clone ( unsigned long flags ) const; + virtual void toData ( JsonStack& ); + }; + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Segment.h b/hurricane/src/hurricane/hurricane/Segment.h index 9632fa3c..78e7ab35 100644 --- a/hurricane/src/hurricane/hurricane/Segment.h +++ b/hurricane/src/hurricane/hurricane/Segment.h @@ -26,7 +26,6 @@ namespace Hurricane { - // **************************************************************************************************** // Segment declaration // **************************************************************************************************** @@ -52,8 +51,9 @@ class Segment : public Component { public: virtual bool isMaster() const {return false;}; - public: virtual string _getTypeName() const { return _TName("Segment::SourceHook"); }; + public: virtual string _getTypeName() const { return "Segment::SourceHook"; }; public: virtual string _getString() const; + public: static Hook* _compToHook(Component*); }; public: class TargetHook : public Hook { @@ -69,8 +69,9 @@ class Segment : public Component { public: virtual bool isMaster() const {return false;}; - public: virtual string _getTypeName() const { return _TName("Segment::TargetHook"); }; + public: virtual string _getTypeName() const { return "Segment::TargetHook"; }; public: virtual string _getString() const; + public: static Hook* _compToHook(Component*); }; // Attributes @@ -127,12 +128,24 @@ class Segment : public Component { protected: virtual void _preDestroy(); + public: virtual void _toJson(JsonWriter*) const; public: virtual string _getString() const; public: virtual Record* _getRecord() const; }; +// **************************************************************************************************** +// JsonSegment declaration +// **************************************************************************************************** + +class JsonSegment : public JsonComponent { +// *************************************** + + public: JsonSegment(unsigned long flags); +}; + + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/SharedPath.h b/hurricane/src/hurricane/hurricane/SharedPath.h index 3f2619a2..20ff5d1f 100644 --- a/hurricane/src/hurricane/hurricane/SharedPath.h +++ b/hurricane/src/hurricane/hurricane/SharedPath.h @@ -97,6 +97,7 @@ class SharedPath { public: SharedPath* getHeadSharedPath() const; public: Instance* getTailInstance() const; public: string getName() const; + public: string getJsonString(unsigned long flags) const; public: Cell* getOwnerCell() const; public: Cell* getMasterCell() const; public: Instances getInstances() const; diff --git a/hurricane/src/hurricane/hurricane/Signature.h b/hurricane/src/hurricane/hurricane/Signature.h new file mode 100644 index 00000000..1ea2d777 --- /dev/null +++ b/hurricane/src/hurricane/hurricane/Signature.h @@ -0,0 +1,149 @@ +// -*- C++ -*- +// +// Copyright (c) BULL S.A. 2015-2015, All Rights Reserved +// +// This file is part of Hurricane. +// +// Hurricane is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// Hurricane is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- +// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU +// General Public License for more details. +// +// You should have received a copy of the Lesser GNU General Public +// License along with Hurricane. If not, see +// . +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Authors : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/Signature.h" | +// +-----------------------------------------------------------------+ + + +#ifndef HURRICANE_SIGNATURE_H +#define HURRICANE_SIGNATURE_H + +#include "hurricane/DbU.h" + + +namespace Hurricane { + + class Layer; + + +// ------------------------------------------------------------------- +// Class : "Signature". + + class Signature { + public: + enum Type { TypeContact = 1 + , TypeVertical = 2 + , TypeHorizontal = 3 + , TypePad = 4 + , TypePlug = 5 + , TypeNet = 6 + , TypeInstance = 7 + }; + enum DimContacts { ContactDx = 0 + , ContactDy = 1 + , ContactWidth = 2 + , ContactHeight = 3 + }; + enum DimVertical { VerticalWidth = 0 + , VerticalX = 1 + , VerticalDySource = 2 + , VerticalDyTarget = 3 + }; + enum DimHorizontal { HorizontalWidth = 0 + , HorizontalY = 1 + , HorizontalDxSource = 2 + , HorizontalDxTarget = 3 + }; + enum DimPad { PadXMin = 0 + , PadYMin = 1 + , PadXMax = 2 + , PadYMax = 3 + }; + public: + inline Signature (); + inline Signature ( const Signature& ); + inline Type getType () const; + inline std::string getName () const; + inline std::string getMasterNet () const; + inline const Layer* getLayer () const; + inline DbU::Unit getDim ( size_t index ) const; + inline void setType ( Type ); + inline void setName ( const std::string& ); + inline void setMasterNet ( const std::string& ); + void setLayer ( const std::string& ); + inline void setDim ( size_t index, DbU::Unit ); + private: + // Attributes. + Type _type; + std::string _name; // For Cell, Instance & Net. + std::string _masterNet; // For Plug. + const Layer* _layer; // For Components (save Plug). + DbU::Unit _dims[4]; // Dimensions. + }; + + + inline Signature::Signature () + : _type () + , _name () + , _masterNet() + , _layer (NULL) + { + for ( size_t i=0 ; i<4 ; ++i ) _dims[i] = 0; + } + + + inline Signature::Signature ( const Signature& other ) + : _type (other._type ) + , _name (other._name ) + , _masterNet(other._masterNet) + , _layer (other._layer ) + { + for ( size_t i=0 ; i<4 ; ++i ) _dims[i] = other._dims[i]; + } + + + inline Signature::Type Signature::getType () const { return _type; } + inline std::string Signature::getName () const { return _name; } + inline std::string Signature::getMasterNet () const { return _masterNet; } + inline const Layer* Signature::getLayer () const { return _layer; } + inline DbU::Unit Signature::getDim ( size_t index ) const { return _dims[index]; } + inline void Signature::setType ( Signature::Type type ) { _type=type; } + inline void Signature::setName ( const std::string& name ) { _name=name; } + inline void Signature::setMasterNet ( const std::string& masterNet ) { _masterNet=masterNet; } + inline void Signature::setDim ( size_t index, DbU::Unit u ) { _dims[index]=u; } + + +// ------------------------------------------------------------------- +// Class : "Signature". + + class JsonSignature : public JsonObject { + public: + JsonSignature ( unsigned long flags ); + void setSubType ( const std::string& ); + virtual std::string getTypeName () const; + virtual JsonSignature* clone ( unsigned long flags ) const; + virtual void toData ( JsonStack& ); + private: + JsonSignature ( const JsonSignature& ); + JsonSignature& operator= ( const JsonSignature& ) const; + private: + std::string _subTypeName; + }; + +} // End of Hurricane namespace. + +#endif // HURRICANE_SIGNATURE_H diff --git a/hurricane/src/hurricane/hurricane/Tabulation.h b/hurricane/src/hurricane/hurricane/Tabulation.h index b3163116..9202dcb9 100644 --- a/hurricane/src/hurricane/hurricane/Tabulation.h +++ b/hurricane/src/hurricane/hurricane/Tabulation.h @@ -23,7 +23,7 @@ #include "hurricane/Commons.h" #ifndef HURRICANE_SLOT_H -#error "Tabulation.h must be included after Commons.h" +#error "Tabulation.h must be included through Commons.h" #endif namespace Hurricane { diff --git a/hurricane/src/hurricane/hurricane/Transformation.h b/hurricane/src/hurricane/hurricane/Transformation.h index 67c8b5bb..0043fdd9 100644 --- a/hurricane/src/hurricane/hurricane/Transformation.h +++ b/hurricane/src/hurricane/hurricane/Transformation.h @@ -25,7 +25,6 @@ namespace Hurricane { - // **************************************************************************************************** // Transformation declaration // **************************************************************************************************** @@ -45,6 +44,7 @@ class Transformation { public: Orientation(const Code& code = ID); public: Orientation(const Orientation& orientation); + public: Orientation(const string& ); public: Orientation& operator=(const Orientation& orientation); @@ -135,9 +135,18 @@ class Transformation { public: string _getTypeName() const { return _TName("Transformation"); }; public: string _getString() const; public: Record* _getRecord() const; + public: void toJson(JsonWriter*) const; }; +class JsonTransformation : public JsonObject { +// ******************************************* + + public: JsonTransformation(unsigned long); + public: virtual string getTypeName() const; + public: virtual JsonTransformation* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; } // End of Hurricane namespace. @@ -203,7 +212,6 @@ INSPECTOR_PV_SUPPORT(Hurricane::Transformation); INSPECTOR_PV_SUPPORT(Hurricane::Transformation::Orientation); IOSTREAM_POINTER_SUPPORT(Hurricane::Transformation::Orientation::Code); - #endif // HURRICANE_TRANSFORMATION diff --git a/hurricane/src/hurricane/hurricane/Vertical.h b/hurricane/src/hurricane/hurricane/Vertical.h index bb3d6c28..28f98cff 100644 --- a/hurricane/src/hurricane/hurricane/Vertical.h +++ b/hurricane/src/hurricane/hurricane/Vertical.h @@ -105,6 +105,8 @@ class Vertical : public Segment { // Others // ****** + public: virtual void _toJson(JsonWriter*) const; + public: static JsonObject* getJsonObject(unsigned long flags); public: virtual string _getTypeName() const {return _TName("Vertical");}; public: virtual string _getString() const; public: virtual Record* _getRecord() const; @@ -112,6 +114,15 @@ class Vertical : public Segment { }; +class JsonVertical : public JsonSegment { +// ************************************** + + public: JsonVertical(unsigned long flags); + public: virtual string getTypeName() const; + public: virtual JsonVertical* clone(unsigned long) const; + public: virtual void toData(JsonStack&); +}; + } // End of Hurricane namespace. diff --git a/hurricane/src/isobar/CMakeLists.txt b/hurricane/src/isobar/CMakeLists.txt index 66ea5835..43ae1e09 100644 --- a/hurricane/src/isobar/CMakeLists.txt +++ b/hurricane/src/isobar/CMakeLists.txt @@ -4,6 +4,7 @@ include_directories( ${HURRICANE_SOURCE_DIR}/src/hurricane ${HURRICANE_SOURCE_DIR}/src/viewer ${HURRICANE_SOURCE_DIR}/src/isobar + ${CONFIGURATION_INCLUDE_DIR} ${PYTHON_INCLUDE_PATH} ) set( pyCpps ProxyProperty.cpp diff --git a/hurricane/src/viewer/CMakeLists.txt b/hurricane/src/viewer/CMakeLists.txt index 344b80eb..067890cd 100644 --- a/hurricane/src/viewer/CMakeLists.txt +++ b/hurricane/src/viewer/CMakeLists.txt @@ -28,6 +28,7 @@ hurricane/viewer/CellViewer.h hurricane/viewer/CellPrinter.h hurricane/viewer/CellImage.h + hurricane/viewer/OpenBlobDialog.h hurricane/viewer/RecordModel.h hurricane/viewer/InspectorWidget.h hurricane/viewer/SelectionPopupModel.h @@ -96,6 +97,7 @@ CellViewer.cpp CellPrinter.cpp CellImage.cpp + OpenBlobDialog.cpp RecordModel.cpp InspectorWidget.cpp SelectionPopupModel.cpp diff --git a/hurricane/src/viewer/CellPrinter.cpp b/hurricane/src/viewer/CellPrinter.cpp index 53ef93a3..40acd879 100644 --- a/hurricane/src/viewer/CellPrinter.cpp +++ b/hurricane/src/viewer/CellPrinter.cpp @@ -294,8 +294,8 @@ namespace Hurricane { _paperWidth = _printer->width (); _paperHeight = _printer->height (); - _drawingWidth = _paperWidth - (frameMargin()<<1); - _drawingHeight = _paperHeight - (frameMargin()<<1); + _drawingWidth = _paperWidth /4 - (frameMargin()<<1); + _drawingHeight = _paperHeight/4 - (frameMargin()<<1); _xpaper = (imageOnly) ? 0 : frameMargin(); _ypaper = (imageOnly) ? 0 : frameMargin(); diff --git a/hurricane/src/viewer/CellViewer.cpp b/hurricane/src/viewer/CellViewer.cpp index f7dff57d..cdfe7f43 100644 --- a/hurricane/src/viewer/CellViewer.cpp +++ b/hurricane/src/viewer/CellViewer.cpp @@ -32,8 +32,11 @@ #include "vlsisapd/utilities/Path.h" #include "vlsisapd/configuration/Configuration.h" +#include "hurricane/DebugSession.h" #include "hurricane/DataBase.h" +#include "hurricane/Library.h" #include "hurricane/Cell.h" +#include "hurricane/DesignBlob.h" //#include "MapView.h" #include "hurricane/isobar/PyCell.h" #include "hurricane/viewer/Script.h" @@ -46,6 +49,7 @@ #include "hurricane/viewer/ScriptWidget.h" #include "hurricane/viewer/ExceptionWidget.h" #include "hurricane/viewer/GotoWidget.h" +#include "hurricane/viewer/OpenBlobDialog.h" #include "hurricane/viewer/SelectCommand.h" #include "hurricane/viewer/PyCellViewer.h" @@ -393,6 +397,22 @@ namespace Hurricane { action->setVisible( false ); addToMenu( "file.========" ); + action = addToMenu( "file.openDesignBlob" + , tr("&Open Design Blob") + , tr("Reload (restore) the whole Hurricane DataBase state") + , QKeySequence() + , QIcon(":/images/stock_open.png") + ); + connect( action, SIGNAL(triggered()), this, SLOT(openDesignBlob()) ); + action = addToMenu( "file.saveDesignBlob" + , tr("&Save Design Blob") + , tr("Save (dump) the whole Hurricane DataBase state") + , QKeySequence() + , QIcon(":/images/stock_save.png") + ); + connect( action, SIGNAL(triggered()), this, SLOT(saveDesignBlob()) ); + addToMenu( "file.========" ); + action = addToMenu( "file.importCell" , tr("&Import Cell") , tr("Import (convert) a new Cell") @@ -702,6 +722,36 @@ namespace Hurricane { } + void CellViewer::openDesignBlob () + { + QString blobName; + if (OpenBlobDialog::runDialog(this,blobName)) { + string fileName = blobName.toStdString() + ".blob"; + DebugSession::open( 50 ); + Cell* topCell = jsonBlobParse( fileName ); + DebugSession::close(); + + setCell ( topCell ); + } + } + + + void CellViewer::saveDesignBlob () + { + Cell* cell = getCell(); + if (not cell) return; + + string blobName = getString(cell->getName()) + ".blob.json"; + DesignBlob blob ( cell ); + + DebugSession::open( 50 ); + JsonWriter writer ( blobName ); + writer.setFlags( JsonWriter::DesignBlobMode ); + jsonWrite( &writer, &blob ); + DebugSession::close(); + } + + void CellViewer::select ( Occurrence& occurrence ) { if ( _cellWidget ) _cellWidget->select ( occurrence ); } diff --git a/hurricane/src/viewer/CellWidget.cpp b/hurricane/src/viewer/CellWidget.cpp index 4a4a99d9..a7a49d32 100644 --- a/hurricane/src/viewer/CellWidget.cpp +++ b/hurricane/src/viewer/CellWidget.cpp @@ -1042,7 +1042,7 @@ namespace Hurricane { // Class : "Hurricane::CellWidget". - int CellWidget::_initialSide = 400; + int CellWidget::_initialSide = 250; CellWidget::CellWidget ( QWidget* parent ) diff --git a/hurricane/src/viewer/OpenBlobDialog.cpp b/hurricane/src/viewer/OpenBlobDialog.cpp new file mode 100644 index 00000000..eb87dd89 --- /dev/null +++ b/hurricane/src/viewer/OpenBlobDialog.cpp @@ -0,0 +1,97 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./OpenBlobDialog.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hurricane/Warning.h" +#include "hurricane/viewer/Graphics.h" +#include "hurricane/viewer/OpenBlobDialog.h" + + +namespace Hurricane { + + using namespace std; + + +// ------------------------------------------------------------------- +// Class : "OpenBlobDialog". + + + OpenBlobDialog::OpenBlobDialog ( QWidget* parent ) + : QDialog (parent) + , _lineEdit(NULL) + { + setWindowTitle( tr("Open Design Blob") ); + + QLabel* label = new QLabel (); + label->setText( tr("Enter the Blob name (without extention \".blob.json\")") ); + label->setFont( Graphics::getNormalFont(true) ); + + _lineEdit = new QLineEdit (); + _lineEdit->setMinimumWidth( 400 ); + + QPushButton* okButton = new QPushButton (); + okButton->setText ( "OK" ); + okButton->setDefault( true ); + + QPushButton* cancelButton = new QPushButton (); + cancelButton->setText( "Cancel" ); + + QHBoxLayout* hLayout1 = new QHBoxLayout (); + hLayout1->addStretch(); + hLayout1->addWidget ( okButton ); + hLayout1->addStretch(); + hLayout1->addWidget ( cancelButton ); + hLayout1->addStretch(); + + QVBoxLayout* vLayout = new QVBoxLayout (); + vLayout->setSizeConstraint ( QLayout::SetFixedSize ); + vLayout->addWidget( label ); + vLayout->addWidget( _lineEdit ); + vLayout->addLayout( hLayout1 ); + + setLayout ( vLayout ); + + connect ( okButton, SIGNAL(clicked()), this, SLOT(accept()) ); + connect ( cancelButton, SIGNAL(clicked()), this, SLOT(reject()) ); + } + + + const QString OpenBlobDialog::getBlobName () const + { return _lineEdit->text(); } + + + bool OpenBlobDialog::runDialog ( QWidget* parent, QString& name ) + { + OpenBlobDialog* dialog = new OpenBlobDialog ( parent ); + bool dialogResult = (dialog->exec() == Accepted); + + name = dialog->getBlobName(); + + delete dialog; + + return dialogResult; + } + + +} // Hurricane namespace. diff --git a/hurricane/src/viewer/hurricane/viewer/CellViewer.h b/hurricane/src/viewer/hurricane/viewer/CellViewer.h index 15705490..0bb9ce08 100644 --- a/hurricane/src/viewer/hurricane/viewer/CellViewer.h +++ b/hurricane/src/viewer/hurricane/viewer/CellViewer.h @@ -136,6 +136,8 @@ namespace Hurricane { void setShowSelection ( bool ); void setState ( shared_ptr& ); void openHistoryCell (); + void openDesignBlob (); + void saveDesignBlob (); void printDisplay (); void print ( QPrinter* ); void imageDisplay (); diff --git a/hurricane/src/viewer/hurricane/viewer/OpenBlobDialog.h b/hurricane/src/viewer/hurricane/viewer/OpenBlobDialog.h new file mode 100644 index 00000000..b895d4ce --- /dev/null +++ b/hurricane/src/viewer/hurricane/viewer/OpenBlobDialog.h @@ -0,0 +1,42 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2015-2015, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | H U R R I C A N E | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/viewer/OpenBlobDialog.h" | +// +-----------------------------------------------------------------+ + + +#ifndef HURRICANE_OPEN_BLOB_DIALOG_H +#define HURRICANE_OPEN_BLOB_DIALOG_H + +#include + +class QLineEdit; + + +namespace Hurricane { + + + class OpenBlobDialog : public QDialog { + Q_OBJECT; + public: + static bool runDialog ( QWidget* parent, QString& name ); + const QString getBlobName () const; + protected: + OpenBlobDialog ( QWidget* parent=NULL ); + protected: + QLineEdit* _lineEdit; + }; + + +} // Hurricane namespace. + +#endif // HURRICANE_OPEN_BLOB_DIALOG_H diff --git a/unicorn/src/ExportCellDialog.cpp b/unicorn/src/ExportCellDialog.cpp index caefb8cf..0073c010 100644 --- a/unicorn/src/ExportCellDialog.cpp +++ b/unicorn/src/ExportCellDialog.cpp @@ -78,6 +78,7 @@ namespace Unicorn { formatLabel->setFont ( Graphics::getNormalFont(true) ); hLayout2->addWidget ( formatLabel ); + _formatComboBox->addItem ( tr("JSON (experimental)") , Json ); _formatComboBox->addItem ( tr("Alliance compliant DEF"), AllianceDef ); _formatComboBox->addItem ( tr("ASCII/GDSII (AGDS)") , AsciiGds ); hLayout2->addWidget ( _formatComboBox ); diff --git a/unicorn/src/UnicornGui.cpp b/unicorn/src/UnicornGui.cpp index ccdb0c75..08c5e9bd 100644 --- a/unicorn/src/UnicornGui.cpp +++ b/unicorn/src/UnicornGui.cpp @@ -17,6 +17,7 @@ #include #include #include +#include "hurricane/DebugSession.h" #include "hurricane/Warning.h" #include "hurricane/viewer/Script.h" #include "hurricane/viewer/CellViewer.h" @@ -45,8 +46,10 @@ namespace Unicorn { using Hurricane::dbo_ptr; + using Hurricane::DebugSession; using Hurricane::Warning; using Hurricane::PyCellViewer_Link; + using Hurricane::jsonCellParse; using CRL::System; using CRL::Catalog; using CRL::AllianceFramework; @@ -89,6 +92,7 @@ namespace Unicorn { _runUnicornInit(); _importCell.setDialog( _importDialog ); + _importCell.addImporter( "JSON (experimental)" , std::bind( &jsonCellParse , placeholders::_1 ) ); _importCell.addImporter( "BLIF (Yosys/ABC)" , std::bind( &Blif::load , placeholders::_1 ) ); _importCell.addImporter( "ACM/SIGDA (aka MCNC, .bench)", std::bind( &AcmSigda::load , placeholders::_1 ) ); _importCell.addImporter( "ISPD'04 (Bookshelf)" , std::bind( &Ispd04::load , placeholders::_1 ) ); @@ -282,8 +286,16 @@ namespace Unicorn { DefExport::drive ( cell, DefExport::WithLEF ); break; case ExportCellDialog::AsciiGds: - GdsDriver gdsDriver ( cell ); - gdsDriver.save( getString(cell->getName())+".agds" ); + { GdsDriver gdsDriver ( cell ); + gdsDriver.save( getString(cell->getName())+".agds" ); + } + break; + case ExportCellDialog::Json: + { DebugSession::open( 50 ); + JsonWriter writer ( cellName.toStdString()+".json" ); + jsonWrite( &writer, cell ); + DebugSession::close(); + } break; } } diff --git a/unicorn/src/unicorn/ExportCellDialog.h b/unicorn/src/unicorn/ExportCellDialog.h index cbc2a44b..652ca747 100644 --- a/unicorn/src/unicorn/ExportCellDialog.h +++ b/unicorn/src/unicorn/ExportCellDialog.h @@ -31,7 +31,7 @@ namespace Unicorn { Q_OBJECT; public: - enum Formats { AllianceDef=1, AsciiGds=2 }; + enum Formats { AllianceDef=1, AsciiGds=2, Json=3 }; public: ExportCellDialog ( QWidget* parent=NULL ); bool runDialog ( QString& name, int& format ); From 5baddeb558e9376219ed831c0265106c2d282470 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Thu, 21 Jan 2016 00:25:39 +0100 Subject: [PATCH 11/60] Implementation of DataBase native save/restore in JSON (step 2). * New: In boostrap, in ccb.py, added support for the "support" project which contains external dependencies. Currently contains only RapidJSON. Those dependencies must be cloned here manually. * New: In Hurricane, Initializer class for an ordered static initialization across different compilation modules. * Change: In Hurricane, at DataBase level, no longer save the Cells in the libraries, but create and ordered list of Cell. Deepest cells (leaf cells) first. To avoid dependency problems. * New: In Hurricane, JSON support for Property. * New; In CRL, added JSON support for AllianceFramework, Environement & Catalog and their associated properties. Adjustment of the AllianceLibrary creation policy. --- Makefile | 4 +- README.rst | 5 +- bootstrap/build.conf | 7 +- bootstrap/builder/Builder.py | 12 +- crlcore/etc/cmos/alliance.conf | 1 + crlcore/src/LibraryManager/CellsModel.cpp | 2 + crlcore/src/LibraryManager/CellsWidget.cpp | 4 + crlcore/src/LibraryManager/LibraryManager.cpp | 3 + .../src/LibraryManager/crlcore/CellsModel.h | 4 +- .../src/LibraryManager/crlcore/CellsWidget.h | 1 + .../LibraryManager/crlcore/LibraryManager.h | 3 +- crlcore/src/ccore/AllianceFramework.cpp | 154 +++++++++-- crlcore/src/ccore/AllianceLibrary.cpp | 156 ++++++++---- crlcore/src/ccore/Catalog.cpp | 158 +++++++++++- crlcore/src/ccore/Environment.cpp | 86 +++++++ crlcore/src/ccore/crlcore/AllianceFramework.h | 41 ++- crlcore/src/ccore/crlcore/AllianceLibrary.h | 17 +- crlcore/src/ccore/crlcore/Catalog.h | 34 ++- crlcore/src/ccore/crlcore/Environment.h | 23 +- documentation/UsersGuide/UsersGuide.html | 228 +++++++++-------- documentation/UsersGuide/UsersGuide.pdf | Bin 562761 -> 1546296 bytes documentation/UsersGuide/UsersGuide.rst | 37 ++- etesian/src/EtesianEngine.cpp | 1 + hurricane/CMakeLists.txt | 1 + hurricane/doc/hurricane/Initializer.dox | 29 +++ hurricane/doc/hurricane/JsonObject.dox | 198 ++++++++++++++ hurricane/doc/hurricane/JsonSupport.dox | 241 ++++++++++++++++++ .../doc/hurricane/StandardSharedProperty.dox | 3 - hurricane/doc/hurricane/doxyfile | 5 + hurricane/src/hurricane/Box.cpp | 9 +- hurricane/src/hurricane/CMakeLists.txt | 9 +- hurricane/src/hurricane/Cell.cpp | 197 +++++++++++++- hurricane/src/hurricane/Contact.cpp | 7 + hurricane/src/hurricane/DBo.cpp | 8 +- hurricane/src/hurricane/DataBase.cpp | 195 ++++++++++++-- hurricane/src/hurricane/DeepNet.cpp | 6 + hurricane/src/hurricane/DesignBlob.cpp | 19 +- hurricane/src/hurricane/FileReadGzStream.cpp | 83 ++++++ hurricane/src/hurricane/FileWriteGzStream.cpp | 79 ++++++ hurricane/src/hurricane/Horizontal.cpp | 7 + hurricane/src/hurricane/Initializer.cpp | 78 ++++++ hurricane/src/hurricane/Instance.cpp | 11 +- hurricane/src/hurricane/JsonReader.cpp | 88 +++---- hurricane/src/hurricane/JsonWriter.cpp | 9 +- hurricane/src/hurricane/Library.cpp | 23 +- hurricane/src/hurricane/Net.cpp | 18 +- .../src/hurricane/NetRoutingProperty.cpp | 98 ++++++- hurricane/src/hurricane/Occurrence.cpp | 32 ++- hurricane/src/hurricane/Pad.cpp | 7 + hurricane/src/hurricane/Plug.cpp | 13 + hurricane/src/hurricane/Point.cpp | 7 + hurricane/src/hurricane/Property.cpp | 78 +++++- hurricane/src/hurricane/RoutingPad.cpp | 7 + hurricane/src/hurricane/Signature.cpp | 7 + hurricane/src/hurricane/Transformation.cpp | 8 +- hurricane/src/hurricane/UpdateSession.cpp | 18 +- hurricane/src/hurricane/Vertical.cpp | 7 + hurricane/src/hurricane/hurricane/Box.h | 1 + hurricane/src/hurricane/hurricane/Cell.h | 31 ++- hurricane/src/hurricane/hurricane/Commons.h | 1 + hurricane/src/hurricane/hurricane/Contact.h | 1 + hurricane/src/hurricane/hurricane/DBo.h | 12 +- hurricane/src/hurricane/hurricane/DataBase.h | 26 +- hurricane/src/hurricane/hurricane/DeepNet.h | 1 + .../src/hurricane/hurricane/DesignBlob.h | 1 + hurricane/src/hurricane/hurricane/Entity.h | 4 +- .../hurricane/hurricane/FileReadGzStream.h | 73 ++++++ .../hurricane/hurricane/FileWriteGzStream.h | 100 ++++++++ .../src/hurricane/hurricane/Horizontal.h | 1 + .../src/hurricane/hurricane/Initializer.h | 72 ++++++ hurricane/src/hurricane/hurricane/Instance.h | 1 + .../src/hurricane/hurricane/JsonReader.h | 33 ++- .../src/hurricane/hurricane/JsonWriter.h | 37 ++- hurricane/src/hurricane/hurricane/Library.h | 1 + hurricane/src/hurricane/hurricane/Net.h | 1 + .../hurricane/hurricane/NetRoutingProperty.h | 21 +- .../src/hurricane/hurricane/Occurrence.h | 1 + hurricane/src/hurricane/hurricane/Pad.h | 1 + hurricane/src/hurricane/hurricane/Plug.h | 2 + hurricane/src/hurricane/hurricane/Point.h | 1 + hurricane/src/hurricane/hurricane/Property.h | 227 ++++++++++++----- hurricane/src/hurricane/hurricane/Relation.h | 1 + .../src/hurricane/hurricane/RoutingPad.h | 1 + hurricane/src/hurricane/hurricane/Signature.h | 1 + .../src/hurricane/hurricane/Transformation.h | 1 + hurricane/src/hurricane/hurricane/Vertical.h | 1 + hurricane/src/viewer/CellViewer.cpp | 7 +- hurricane/src/viewer/OpenBlobDialog.cpp | 2 +- .../src/viewer/hurricane/viewer/CellViewer.h | 1 + unicorn/src/UnicornGui.cpp | 9 +- 90 files changed, 2813 insertions(+), 447 deletions(-) create mode 100644 hurricane/doc/hurricane/Initializer.dox create mode 100644 hurricane/doc/hurricane/JsonObject.dox create mode 100644 hurricane/doc/hurricane/JsonSupport.dox create mode 100644 hurricane/src/hurricane/FileReadGzStream.cpp create mode 100644 hurricane/src/hurricane/FileWriteGzStream.cpp create mode 100644 hurricane/src/hurricane/Initializer.cpp create mode 100644 hurricane/src/hurricane/hurricane/FileReadGzStream.h create mode 100644 hurricane/src/hurricane/hurricane/FileWriteGzStream.h create mode 100644 hurricane/src/hurricane/hurricane/Initializer.h diff --git a/Makefile b/Makefile index 5f491ea1..92fbcec1 100644 --- a/Makefile +++ b/Makefile @@ -55,8 +55,8 @@ check_dir: install: check_dir - @./bootstrap/ccb.py $(DEVTOOLSET_OPTION) --project=coriolis --make="$(SMP_FLAGS) install" - @./bootstrap/ccb.py $(DEVTOOLSET_OPTION) --project=coriolis --make="-j1 install" --doc + @./bootstrap/ccb.py $(DEVTOOLSET_OPTION) --project=support --project=coriolis --make="$(SMP_FLAGS) install" + @./bootstrap/ccb.py $(DEVTOOLSET_OPTION) --project=support --project=coriolis --make="-j1 install" --doc @echo ""; \ echo "============================================================================"; \ echo "Coriolis has been successfully built"; \ diff --git a/README.rst b/README.rst index 91cef49b..3227ae9f 100644 --- a/README.rst +++ b/README.rst @@ -47,13 +47,16 @@ To build Coriolis, ensure the following prerequisites are met: * bison & flex. * Qt 4 or 5. * libxml2. +* RapidJSON * A C++11 compliant compiler. The build system relies on a fixed directory tree from the root of the user currently building it. Thus first step is to get a clone of the repository in the right place. Proceed as follow: :: - ego@home:~$ mkdir -p ~/coriolis-2.x/src + ego@home:~$ mkdir -p ~/coriolis-2.x/src/support + ego@home:~$ cd ~/coriolis-2.x/src/support + ego@home:~$ git clone http://github.com/miloyip/rapidjson ego@home:~$ cd ~/coriolis-2.x/src ego@home:src$ git clone https://www-soc.lip6.fr/git/coriolis.git ego@home:src$ cd coriolis diff --git a/bootstrap/build.conf b/bootstrap/build.conf index 8447c0e8..388ae4c4 100644 --- a/bootstrap/build.conf +++ b/bootstrap/build.conf @@ -6,7 +6,12 @@ projectdir = 'coriolis-2.x' projects = [ - { 'name' : "coriolis" + { 'name' : "support" + , 'tools' : [ "rapidjson" + ] + , 'repository': 'No_repository_for_support' + } + , { 'name' : "coriolis" , 'tools' : [ "bootstrap" , "vlsisapd" , "hurricane" diff --git a/bootstrap/builder/Builder.py b/bootstrap/builder/Builder.py index fc8031c9..b2ff8c1b 100644 --- a/bootstrap/builder/Builder.py +++ b/bootstrap/builder/Builder.py @@ -150,8 +150,9 @@ class Builder: def _build ( self, tool ): - toolSourceDir = os.path.join ( self.sourceDir, tool.getToolDir() ) - toolBuildDir = os.path.join ( self.buildDir , tool.name ) + toolSourceDir = os.path.join ( self.sourceDir, tool.getToolDir() ) + toolBuildDir = os.path.join ( self.buildDir , tool.name ) + cmakeInstallDir = os.path.join ( self.installDir, "share", "cmake", "Modules" ) # Supplied directly in the CMakeLists.txt. #cmakeModules = os.path.join ( self.installDir, "share", "cmake", "Modules" ) @@ -170,8 +171,10 @@ class Builder: if self._qt5: command += [ "-D", "WITH_QT5:STRING=TRUE" ] if self._openmp: command += [ "-D", "WITH_OPENMP:STRING=TRUE" ] - command += [ "-D", "CMAKE_BUILD_TYPE:STRING=%s" % self.buildMode - , "-D", "BUILD_SHARED_LIBS:STRING=%s" % self.enableShared + command += [ "-D", "CMAKE_BUILD_TYPE:STRING=%s" % self.buildMode + , "-D", "BUILD_SHARED_LIBS:STRING=%s" % self.enableShared + , "-D", "CMAKE_INSTALL_PREFIX:STRING=%s" % self.installDir + , "-D", "CMAKE_INSTALL_DIR:STRING=%s" % cmakeInstallDir #, "-D", "CMAKE_MODULE_PATH:STRING=%s" % cmakeModules , toolSourceDir ] @@ -191,6 +194,7 @@ class Builder: , "-D", "CHECK_DETERMINISM:STRING=%s" % self._checkDeterminism , "-D", "CMAKE_VERBOSE_MAKEFILE:STRING=%s" % self._verboseMakefile , "-D", "CMAKE_INSTALL_PREFIX:STRING=%s" % self.installDir + , "-D", "CMAKE_INSTALL_DIR:STRING=%s" % cmakeInstallDir ] if self.libSuffix: command += [ "-D", "LIB_SUFFIX:STRING=%s" % self.libSuffix ] diff --git a/crlcore/etc/cmos/alliance.conf b/crlcore/etc/cmos/alliance.conf index 05c99819..5e937d65 100644 --- a/crlcore/etc/cmos/alliance.conf +++ b/crlcore/etc/cmos/alliance.conf @@ -11,6 +11,7 @@ cellsTop = allianceTop+'/cells/' allianceConfig = \ ( ( 'CATALOG' , 'CATAL') , ( 'WORKING_LIBRARY' , '.') +# , ( 'SYSTEM_LIBRARY' , ( (cellsTop+'ramlib' , AddMode.Append), ) ) , ( 'SYSTEM_LIBRARY' , ( (cellsTop+'sxlib' , AddMode.Append) , (cellsTop+'dp_sxlib', AddMode.Append) , (cellsTop+'ramlib' , AddMode.Append) diff --git a/crlcore/src/LibraryManager/CellsModel.cpp b/crlcore/src/LibraryManager/CellsModel.cpp index 12410cb4..5e82a0fb 100644 --- a/crlcore/src/LibraryManager/CellsModel.cpp +++ b/crlcore/src/LibraryManager/CellsModel.cpp @@ -226,6 +226,7 @@ namespace CRL { Catalog* catalog = AllianceFramework::get()->getCatalog(); CellLoaders* loaders = CellLoaders::get(); + getCellsDatas().clear(); forEach ( Cell*, icell, library->getLibrary()->getCells() ) { CellDatas* datas = new CellDatas(*icell); getCellsDatas().push_back( datas ); @@ -245,6 +246,7 @@ namespace CRL { CellDatas* key = new CellDatas( cellName ); auto idatas = lower_bound( getCellsDatas().begin(), getCellsDatas().end(), key, LessCellDatas ); + if ( (idatas == getCellsDatas().end()) or ((*idatas)->getName() != cellName ) ) { getCellsDatas().push_back( key ); diff --git a/crlcore/src/LibraryManager/CellsWidget.cpp b/crlcore/src/LibraryManager/CellsWidget.cpp index b181039b..d95fef05 100644 --- a/crlcore/src/LibraryManager/CellsWidget.cpp +++ b/crlcore/src/LibraryManager/CellsWidget.cpp @@ -86,6 +86,10 @@ namespace CRL { } + void CellsWidget::updateLibrary () + { _baseModel->updateLibrary(); } + + void CellsWidget::updateSelected () { if (_selected.isValid()) _baseModel->emitDataChanged(_selected); } diff --git a/crlcore/src/LibraryManager/LibraryManager.cpp b/crlcore/src/LibraryManager/LibraryManager.cpp index e95c7cb0..a37c8e06 100644 --- a/crlcore/src/LibraryManager/LibraryManager.cpp +++ b/crlcore/src/LibraryManager/LibraryManager.cpp @@ -139,5 +139,8 @@ namespace CRL { } + void LibraryManager::updateLibrary ( Cell* ) + { _cellsWidget->updateLibrary(); } + } // CRL namespace. diff --git a/crlcore/src/LibraryManager/crlcore/CellsModel.h b/crlcore/src/LibraryManager/crlcore/CellsModel.h index 56324b3a..c8fe59c4 100644 --- a/crlcore/src/LibraryManager/crlcore/CellsModel.h +++ b/crlcore/src/LibraryManager/crlcore/CellsModel.h @@ -60,7 +60,9 @@ namespace CRL { }; - inline const AllianceLibrary* CellsModel::getLibrary () const { return (const AllianceLibrary*)_ilibrary->first; } + inline const AllianceLibrary* CellsModel::getLibrary () const + { return (_ilibrary != _libraries.end()) ? (const AllianceLibrary*)_ilibrary->first : NULL; } + inline const std::vector& CellsModel::getCellsDatas () const { return _ilibrary->second; } inline std::vector& CellsModel::getCellsDatas () { return _ilibrary->second; } diff --git a/crlcore/src/LibraryManager/crlcore/CellsWidget.h b/crlcore/src/LibraryManager/crlcore/CellsWidget.h index 2719e236..243f9909 100644 --- a/crlcore/src/LibraryManager/crlcore/CellsWidget.h +++ b/crlcore/src/LibraryManager/crlcore/CellsWidget.h @@ -47,6 +47,7 @@ namespace CRL { void selectedCell ( CellDatas* ); public slots: void updateSelected (); + void updateLibrary (); void selectCurrent ( const QModelIndex& index, const QModelIndex& ); void setLibrary ( const AllianceLibrary* ); private: diff --git a/crlcore/src/LibraryManager/crlcore/LibraryManager.h b/crlcore/src/LibraryManager/crlcore/LibraryManager.h index 50cfbfc5..4dd2ec6b 100644 --- a/crlcore/src/LibraryManager/crlcore/LibraryManager.h +++ b/crlcore/src/LibraryManager/crlcore/LibraryManager.h @@ -50,10 +50,11 @@ namespace CRL { LibraryManager ( QWidget* parent=NULL ); inline void setCellViewer ( CellViewer* ); inline CellViewer* getCellViewer () const; - public slots: + public slots: void toggleShow (); void setLibrary ( const AllianceLibrary* library ); CellViewer* openCell ( Cell*, unsigned int flags ); + void updateLibrary ( Cell* ); private: LibrariesWidget* _librariesWidget; CellsWidget* _cellsWidget; diff --git a/crlcore/src/ccore/AllianceFramework.cpp b/crlcore/src/ccore/AllianceFramework.cpp index 01b83216..d11f8010 100644 --- a/crlcore/src/ccore/AllianceFramework.cpp +++ b/crlcore/src/ccore/AllianceFramework.cpp @@ -15,9 +15,10 @@ #include #include "vlsisapd/utilities/Path.h" +#include "hurricane/Initializer.h" #include "hurricane/Warning.h" -#include "hurricane/Technology.h" #include "hurricane/DataBase.h" +#include "hurricane/Technology.h" #include "hurricane/Library.h" #include "hurricane/Cell.h" #include "hurricane/Instance.h" @@ -35,10 +36,14 @@ namespace CRL { using namespace std::placeholders; + using Hurricane::Initializer; + using Hurricane::JsonTypes; + using Hurricane::JsonArray; using Hurricane::Warning; using Hurricane::tab; using Hurricane::Graphics; using Hurricane::ForEachIterator; + using Hurricane::getCollection; using Hurricane::Instance; using Hurricane::PrivateProperty; @@ -53,6 +58,8 @@ namespace CRL { static Name getPropertyName (); virtual Name getName () const; inline AllianceFramework* getFramework () const; + virtual bool hasJson () const; + virtual void toJson ( JsonWriter*, const DBo* ) const; virtual string _getTypeName () const; virtual Record* _getRecord () const; private: @@ -60,10 +67,19 @@ namespace CRL { AllianceFramework* _framework; private: inline AllianceFrameworkProperty ( AllianceFramework* ); + public: + class JsonProperty : public JsonObject { + public: + static void initialize (); + JsonProperty ( unsigned long flags ); + virtual string getTypeName () const; + virtual JsonProperty* clone ( unsigned long ) const; + virtual void toData ( JsonStack& ); + }; }; - Name AllianceFrameworkProperty::_name = "AllianceFramework"; + Name AllianceFrameworkProperty::_name = "AllianceFrameworkProperty"; inline AllianceFrameworkProperty::AllianceFrameworkProperty ( AllianceFramework* af ) @@ -107,6 +123,56 @@ namespace CRL { } + bool AllianceFrameworkProperty::hasJson () const + { return true; } + + + void AllianceFrameworkProperty::toJson ( JsonWriter* w, const DBo* ) const + { + w->startObject(); + std::string tname = getString(getPropertyName()); + jsonWrite( w, "@typename" , tname ); + jsonWrite( w, "_framework", _framework ); + w->endObject(); + } + + + Initializer jsonFrameworkPropertyInit ( 20 ); + + + AllianceFrameworkProperty::JsonProperty::JsonProperty ( unsigned long flags ) + : JsonObject(flags) + { + add( "_framework", typeid(AllianceFramework*) ); + } + + + string AllianceFrameworkProperty::JsonProperty::getTypeName () const + { return getString(AllianceFrameworkProperty::getPropertyName()); } + + + void AllianceFrameworkProperty::JsonProperty::initialize () + { JsonTypes::registerType( new JsonProperty (JsonWriter::RegisterMode) ); } + + + AllianceFrameworkProperty::JsonProperty* AllianceFrameworkProperty::JsonProperty::clone ( unsigned long flags ) const + { return new JsonProperty ( flags ); } + + + void AllianceFrameworkProperty::JsonProperty::toData ( JsonStack& stack ) + { + check( stack, "AllianceFrameworkProperty::JsonProperty::toData" ); + + DBo* dbo = stack.back_dbo(); + AllianceFramework* framework = get(stack,"_framework"); + AllianceFrameworkProperty* property + = AllianceFrameworkProperty::create(framework); + if (dbo) dbo->put( property ); + + update( stack, property ); + } + + // ------------------------------------------------------------------- // Class : "CRL::AllianceFramework". @@ -173,7 +239,7 @@ namespace CRL { void AllianceFramework::_bindLibraries () { DataBase* db = DataBase::getDB (); - unsigned int flags = InSearchPath; + unsigned int flags = AppendLibrary; SearchPath& LIBRARIES = _environment.getLIBRARIES (); Library* rootLibrary = db->getRootLibrary (); @@ -239,7 +305,7 @@ namespace CRL { } - AllianceLibrary* AllianceFramework::getAllianceLibrary ( const Name &libName, unsigned int& flags ) + AllianceLibrary* AllianceFramework::getAllianceLibrary ( const Name &libName, unsigned int flags ) { for ( size_t ilib=0 ; ilib<_libraries.size() ; ++ilib ) { if ( _libraries[ilib]->getLibrary()->getName() == libName ) @@ -331,7 +397,7 @@ namespace CRL { } - AllianceLibrary* AllianceFramework::createLibrary ( const string& path, unsigned int& flags, string libName ) + AllianceLibrary* AllianceFramework::createLibrary ( const string& path, unsigned int flags, string libName ) { if ( libName.empty() ) libName = SearchPath::extractLibName(path); @@ -339,7 +405,7 @@ namespace CRL { string dupLibName = libName; for ( size_t duplicate=1 ; true ; ++duplicate ) { - AllianceLibrary* library = getAllianceLibrary ( dupLibName, flags ); + AllianceLibrary* library = getAllianceLibrary ( dupLibName, flags & ~CreateLibrary ); if (library == NULL) break; ostringstream oss; @@ -355,31 +421,38 @@ namespace CRL { // } SearchPath& LIBRARIES = _environment.getLIBRARIES (); - if ( not (flags & InSearchPath) ) LIBRARIES.prepend ( path, dupLibName ); - else LIBRARIES.select ( path ); + if ( not (flags & AppendLibrary) ) LIBRARIES.prepend ( path, dupLibName ); + else LIBRARIES.select ( path ); - AllianceLibrary* library = new AllianceLibrary ( path, Library::create(getParentLibrary(),dupLibName) ); + Library* hlibrary = getParentLibrary()->getLibrary( dupLibName ); + if (not hlibrary) + hlibrary = Library::create( getParentLibrary(), dupLibName ); + + AllianceLibrary* alibrary = new AllianceLibrary ( path, hlibrary ); AllianceLibraries::iterator ilib = _libraries.begin(); - for ( size_t i=0 ; igetLibrary()) ) flags |= HasCatalog; + if ( _catalog.loadFromFile(catalog,alibrary->getLibrary()) ) flags |= HasCatalog; ParserFormatSlot& parser = _parsers.getParserSlot ( path, Catalog::State::Physical, _environment ); - if ( not parser.loadByLib() ) return library; + if ( not parser.loadByLib() ) return alibrary; // Load the whole library. - if ( ! _readLocate(dupLibName,Catalog::State::State::Logical,true) ) return library; + if ( ! _readLocate(dupLibName,Catalog::State::State::Logical,true) ) return alibrary; // Call the parser function. - (parser.getParsLib())( _environment.getLIBRARIES().getSelected() , library->getLibrary() , _catalog ); + (parser.getParsLib())( _environment.getLIBRARIES().getSelected() , alibrary->getLibrary() , _catalog ); - return library; + return alibrary; } @@ -673,4 +746,53 @@ namespace CRL { } + void AllianceFramework::toJson ( JsonWriter* w ) const + { + w->startObject(); + jsonWrite( w, "@typename" , _getTypeName() ); + jsonWrite( w, "_environment", &_environment ); + jsonWrite( w, "+libraries" , getCollection(getAllianceLibraries()) ); + // Environement & Catalog... + w->endObject(); + } + + +// ------------------------------------------------------------------- +// Class : "CRL::JsonAllianceFramework". + + Initializer jsonFrameworkInit ( 20 ); + + + JsonAllianceFramework::JsonAllianceFramework (unsigned long flags ) + : JsonObject(flags) + { + // Environement & Catalog... + add( "_environment", typeid(Environment*) ); + add( "+libraries" , typeid(JsonArray) ); + } + + + string JsonAllianceFramework::getTypeName () const + { return "AllianceFramework"; } + + + void JsonAllianceFramework::initialize () + { JsonTypes::registerType( new JsonAllianceFramework (JsonWriter::RegisterMode) ); } + + + JsonAllianceFramework* JsonAllianceFramework::clone ( unsigned long flags ) const + { return new JsonAllianceFramework ( flags ); } + + + void JsonAllianceFramework::toData ( JsonStack& stack ) + { + check( stack, "JsonAllianceFramework::toData" ); + + // It's a singleton. Do not create it... + AllianceFramework* framework = AllianceFramework::get(); + + update( stack, framework ); + } + + } // End of CRL namespace. diff --git a/crlcore/src/ccore/AllianceLibrary.cpp b/crlcore/src/ccore/AllianceLibrary.cpp index 2e468d3f..7d5f3e8e 100644 --- a/crlcore/src/ccore/AllianceLibrary.cpp +++ b/crlcore/src/ccore/AllianceLibrary.cpp @@ -1,67 +1,38 @@ - // -*- C++ -*- // -// This file is part of the Coriolis Project. -// Copyright (C) Laboratoire LIP6 - Departement ASIM -// Universite Pierre et Marie Curie +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2008-2015, All Rights Reserved // -// Main contributors : -// Christophe Alexandre -// Sophie Belloeil -// Hugo Clment -// Jean-Paul Chaput -// Damien Dupuis -// Christian Masson -// Marek Sroka -// -// The Coriolis Project is free software; you can redistribute it -// and/or modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 of -// the License, or (at your option) any later version. -// -// The Coriolis Project is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with the Coriolis Project; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -// USA -// -// License-Tag -// Authors-Tag -// =================================================================== -// -// $Id$ -// -// x-----------------------------------------------------------------x -// | | +// +-----------------------------------------------------------------+ // | C O R I O L I S | // | Alliance / Hurricane Interface | // | | -// | Author : Rmy Escassut | -// | E-mail : Remy.Escassut@silvaco.com | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | -// | C++ Header : "./AllianceLibrary.cpp" | -// | *************************************************************** | -// | U p d a t e s | -// | | -// x-----------------------------------------------------------------x - - - - -# include "hurricane/Library.h" - -# include "crlcore/Utilities.h" -# include "crlcore/AllianceLibrary.h" +// | C++ Module : "./AllianceLibrary.cpp" | +// +-----------------------------------------------------------------+ +#include "hurricane/Warning.h" +#include "hurricane/SharedPath.h" +#include "hurricane/Library.h" +#include "hurricane/DataBase.h" +#include "crlcore/Utilities.h" +#include "crlcore/AllianceLibrary.h" +#include "crlcore/AllianceFramework.h" namespace CRL { + using namespace std; + using Hurricane::Initializer; + using Hurricane::JsonTypes; + using Hurricane::Warning; + using Hurricane::Name; + using Hurricane::SharedPath; + using Hurricane::DataBase; + // ------------------------------------------------------------------- // Class : "AllianceDirectory". @@ -113,6 +84,89 @@ namespace CRL { } + void AllianceLibrary::toJson ( JsonWriter* w ) const + { + w->startObject(); + jsonWrite( w, "@typename", _getTypeName() ); + jsonWrite( w, "_path" , _path ); + jsonWrite( w, "_library" , _library->getHierarchicalName() ); + w->endObject(); + } + + +// ------------------------------------------------------------------- +// Class : "JsonAllianceLibrary". + + Initializer jsonAllianceLibraryInit ( 0 ); + + + void JsonAllianceLibrary::initialize () + { JsonTypes::registerType( new JsonAllianceLibrary (JsonWriter::RegisterMode) ); } + + + JsonAllianceLibrary::JsonAllianceLibrary ( unsigned long flags ) + : JsonObject(flags) + { + add( "_path" , typeid(string) ); + add( "_library", typeid(string) ); + } + + string JsonAllianceLibrary::getTypeName () const + { return "AllianceLibrary"; } + + + JsonAllianceLibrary* JsonAllianceLibrary::clone ( unsigned long flags ) const + { return new JsonAllianceLibrary ( flags ); } + + + void JsonAllianceLibrary::toData ( JsonStack& stack ) + { + check( stack, "JsonAllianceLibrary::toData" ); + + string libDbPath = get( stack,"_library" ); + string libOsPath = get( stack,"_path" ); + + AllianceFramework* af = AllianceFramework::get(); + Library* library = DataBase::getDB()->getLibrary( libDbPath + , DataBase::CreateLib|DataBase::WarnCreateLib ); + AllianceLibrary* aLibrary = NULL; + + if (library) { + aLibrary = af->getAllianceLibrary( library ); + } + if (not aLibrary) { + char separator = SharedPath::getNameSeparator(); + size_t dot = libDbPath.rfind( separator ); + Name libName = libDbPath.substr(dot+1); + aLibrary = af->getAllianceLibrary( libName, AllianceFramework::AppendLibrary ); + + if (not aLibrary) { + aLibrary = af->getAllianceLibrary( libOsPath + , AllianceFramework::CreateLibrary + | AllianceFramework::AppendLibrary ); + } + if (not library) library = aLibrary->getLibrary(); + } + + if (aLibrary->getLibrary() != library) { + cerr << Warning( "JsonAllianceLibrary::toData(): Underlying Hurricane Library discrepency for \"%s\".\n" + " (may be caused by a change in search path order)" + , getString(library->getName()).c_str() + ) << endl; + } + if (aLibrary->getPath() != Name(libOsPath)) { + cerr << Warning( "JsonAllianceLibrary::toData(): Underlying OS path discrepency for \"%s\":\n" + " - Blob: %s\n" + " - System: %s" + , getString(library->getName()).c_str() + , libOsPath.c_str() + , getString(aLibrary->getPath()).c_str() + ) << endl; + } + + update( stack, aLibrary ); + } + } // End of CRL namespace. diff --git a/crlcore/src/ccore/Catalog.cpp b/crlcore/src/ccore/Catalog.cpp index 8f691bd8..dae1542b 100644 --- a/crlcore/src/ccore/Catalog.cpp +++ b/crlcore/src/ccore/Catalog.cpp @@ -17,15 +17,25 @@ # include using namespace std; +#include "hurricane/Initializer.h" +#include "hurricane/SharedPath.h" #include "hurricane/Collection.h" +#include "hurricane/DataBase.h" #include "hurricane/Library.h" #include "hurricane/Name.h" #include "crlcore/Utilities.h" #include "crlcore/Catalog.h" +#include "crlcore/AllianceFramework.h" namespace CRL { + using Hurricane::inltrace; + using Hurricane::tab; + using Hurricane::Initializer; + using Hurricane::JsonTypes; + using Hurricane::SharedPath; + using Hurricane::DataBase; const char* MissingStateProperty = "%s:\n\n Missing Catalog State Property in cell \"%s\".\n"; @@ -89,6 +99,81 @@ namespace CRL { return record; } + + void Catalog::State::toJson ( JsonWriter* w ) const + { + w->startObject(); + jsonWrite( w, "@typename", _getTypeName() ); + jsonWrite( w, "_flags" , _getString() ); + jsonWrite( w, "_depth" , _depth ); + + string cellName = ""; + if (_cell) cellName = getString( _cell->getHierarchicalName() ); + jsonWrite( w, "_cell", cellName ); + w->endObject(); + } + + + Initializer jsonCatalogStateInit ( 20 ); + + + Catalog::State::JsonState::JsonState ( unsigned long flags ) + : JsonObject(flags) + { + add( "_flags", typeid(string) ); + add( "_depth", typeid(int64_t) ); + add( "_cell" , typeid(string) ); + } + + + string Catalog::State::JsonState::getTypeName () const + { return "Catalog::State"; } + + + void Catalog::State::JsonState::initialize () + { JsonTypes::registerType( new JsonState (JsonWriter::RegisterMode) ); } + + + Catalog::State::JsonState* Catalog::State::JsonState::clone ( unsigned long flags ) const + { return new JsonState ( flags ); } + + + void Catalog::State::JsonState::toData ( JsonStack& stack ) + { + check( stack, "Catalog::State::JsonState::toData" ); + + string cellPath = get ( stack, "_cell" ); + string sflags = get ( stack, "_flags" ); + unsigned int depth = get( stack, "_depth" ); + + char separator = SharedPath::getNameSeparator(); + size_t dot = cellPath.rfind( separator ); + string cellName = cellPath.substr(dot+1); + string libraryName = cellPath.substr(0,dot); + + Library* library = DataBase::getDB()->getLibrary( libraryName + , DataBase::CreateLib|DataBase::WarnCreateLib ); + Cell* cell = library->getCell( cellName ); + + Catalog* catalog = AllianceFramework::get()->getCatalog(); + Catalog::State* state = catalog->getState( cellName ); + + if (not state) state = catalog->getState( cellName, true ); + if (state->getCell () != cell ) state->setCell ( cell ); + if (state->getLibrary() != library) state->setLibrary( library ); + + state->setDepth( depth ); + state->setFlattenLeaf( (sflags[0] == 'C') ); + state->setFeed( (sflags[1] == 'F') ); + state->setPad( (sflags[2] == 'P') ); + state->setGds( (sflags[3] == 'G') ); + state->setDelete( (sflags[4] == 'D') ); + state->setInMemory( (sflags[5] == 'm') ); + + update( stack, state ); + } + + // ------------------------------------------------------------------- // Class : "Catalog". @@ -248,8 +333,7 @@ namespace CRL { // ------------------------------------------------------------------- // Class : "CatalogProperty" - - Name CatalogProperty::_name = "Alliance Catalog State"; + Name CatalogProperty::_name = "Catalog::State::Property"; CatalogProperty* CatalogProperty::create ( Catalog::State* state ) @@ -306,6 +390,76 @@ namespace CRL { } + bool CatalogProperty::hasJson () const + { return true; } + + + void CatalogProperty::toJson ( JsonWriter* w, const DBo* ) const + { + w->startObject(); + std::string tname = getString(getPropertyName()); + jsonWrite( w, "@typename", tname ); + jsonWrite( w, "_state" , _state ); + w->endObject(); + } + + +// ------------------------------------------------------------------- +// Class : "JsonCatalogProperty" + + Initializer jsonCatalogPropertyInit ( 20 ); + + + JsonCatalogProperty::JsonCatalogProperty ( unsigned long flags ) + : JsonObject(flags) + { + add( "_state", typeid(Catalog::State*) ); + } + + + string JsonCatalogProperty::getTypeName () const + { return getString(CatalogProperty::getPropertyName()); } + + + void JsonCatalogProperty::initialize () + { JsonTypes::registerType( new JsonCatalogProperty (JsonWriter::RegisterMode) ); } + + + JsonCatalogProperty* JsonCatalogProperty::clone ( unsigned long flags ) const + { return new JsonCatalogProperty ( flags ); } + + + void JsonCatalogProperty::toData ( JsonStack& stack ) + { + check( stack, "JsonCatalogProperty::toData" ); + + DBo* dbo = stack.back_dbo(); + Catalog::State* state = get( stack, "_state" ); + CatalogProperty* property = NULL; + + ltrace(51) << "topDBo:" << dbo << endl; + + Cell* cell = dynamic_cast( dbo ); + if (cell) { + Property* base = cell->getProperty( CatalogProperty::getPropertyName() ); + if (base) { + property = static_cast( base ); + if (property->getState() != state) { + cerr << Error( "JsonCatalogProperty::toData(): State object incoherency on Cell \"%s\"." + , getString(cell->getName()).c_str() + ) << endl; + } + } else { + property = CatalogProperty::create( state ); + cell->put( property ); + } + } + // NULL Cell means we are parsing the Catalog. + + update( stack, property ); + } + + // ------------------------------------------------------------------- // Class : "CatalogExtension" diff --git a/crlcore/src/ccore/Environment.cpp b/crlcore/src/ccore/Environment.cpp index 9bc6bcc6..016ad3ff 100644 --- a/crlcore/src/ccore/Environment.cpp +++ b/crlcore/src/ccore/Environment.cpp @@ -22,6 +22,7 @@ #include "crlcore/Utilities.h" #include "crlcore/XmlParser.h" #include "crlcore/Environment.h" +#include "crlcore/AllianceFramework.h" namespace { @@ -505,6 +506,12 @@ namespace { namespace CRL { + using Hurricane::Initializer; + using Hurricane::JsonTypes; + + +// ------------------------------------------------------------------- +// Class : "Environment". Environment::Environment () : _CORIOLIS_TOP (CORIOLIS_TOP) @@ -753,4 +760,83 @@ namespace CRL { } + void Environment::toJson ( JsonWriter* w ) const + { + w->startObject(); + jsonWrite( w, "@typename" , _getTypeName() ); + jsonWrite( w, "_CORIOLIS_TOP", _CORIOLIS_TOP ); + jsonWrite( w, "_displayStyle", _displayStyle ); + jsonWrite( w, "_SCALE_X" , _SCALE_X ); + jsonWrite( w, "_IN_LO" , _IN_LO ); + jsonWrite( w, "_IN_PH" , _IN_PH ); + jsonWrite( w, "_OUT_LO" , _OUT_LO ); + jsonWrite( w, "_OUT_PH" , _OUT_PH ); + jsonWrite( w, "_POWER" , _POWER ); + jsonWrite( w, "_GROUND" , _GROUND ); + jsonWrite( w, "_CLOCK" , _CLOCK ); + jsonWrite( w, "_BLOCKAGE" , _BLOCKAGE ); + jsonWrite( w, "_pad" , _pad ); + jsonWrite( w, "_CATALOG" , _CATALOG ); + w->endObject(); + } + + +// ------------------------------------------------------------------- +// Class : "JsonEnvironment". + + Initializer jsonEnvironmentInit ( 0 ); + + + void JsonEnvironment::initialize () + { JsonTypes::registerType( new JsonEnvironment (JsonWriter::RegisterMode) ); } + + + JsonEnvironment::JsonEnvironment ( unsigned long flags ) + : JsonObject(flags) + { + add( "_CORIOLIS_TOP", typeid(string) ); + add( "_displayStyle", typeid(string) ); + add( "_SCALE_X" , typeid(int64_t) ); + add( "_IN_LO" , typeid(string) ); + add( "_IN_PH" , typeid(string) ); + add( "_OUT_LO" , typeid(string) ); + add( "_OUT_PH" , typeid(string) ); + add( "_POWER" , typeid(string) ); + add( "_GROUND" , typeid(string) ); + add( "_BLOCKAGE" , typeid(string) ); + add( "_pad" , typeid(string) ); + add( "_CATALOG" , typeid(string) ); + add( "_CLOCK" , typeid(string) ); + } + + string JsonEnvironment::getTypeName () const + { return "Environment"; } + + + JsonEnvironment* JsonEnvironment::clone ( unsigned long flags ) const + { return new JsonEnvironment ( flags ); } + + + void JsonEnvironment::toData ( JsonStack& stack ) + { + check( stack, "JsonEnvironment::toData" ); + + Environment* environement = AllianceFramework::get()->getEnvironment(); + environement->setDisplayStyle( get (stack,"_displayStyle").c_str() ); + environement->setSCALE_X ( get(stack,"_SCALE_X" ) ); + environement->setIN_LO ( get (stack,"_IN_LO" ).c_str() ); + environement->setIN_PH ( get (stack,"_IN_PH" ).c_str() ); + environement->setOUT_LO ( get (stack,"_OUT_LO" ).c_str() ); + environement->setOUT_PH ( get (stack,"_OUT_PH" ).c_str() ); + environement->setPOWER ( get (stack,"_POWER" ).c_str() ); + environement->setGROUND ( get (stack,"_GROUND" ).c_str() ); + environement->setCLOCK ( get (stack,"_CLOCK" ).c_str() ); + environement->setBLOCKAGE ( get (stack,"_BLOCKAGE" ).c_str() ); + environement->setPad ( get (stack,"_pad" ).c_str() ); + environement->setCATALOG ( get (stack,"_CATALOG" ).c_str() ); + + update( stack, environement ); + } + + } // End of CRL namespace. diff --git a/crlcore/src/ccore/crlcore/AllianceFramework.h b/crlcore/src/ccore/crlcore/AllianceFramework.h index e41b43f1..be5ca85f 100644 --- a/crlcore/src/ccore/crlcore/AllianceFramework.h +++ b/crlcore/src/ccore/crlcore/AllianceFramework.h @@ -1,4 +1,3 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. @@ -18,17 +17,19 @@ #ifndef CRL_ALLIANCE_FRAMEWORK_H #define CRL_ALLIANCE_FRAMEWORK_H -#include -#include -#include "hurricane/Cell.h" -#include "crlcore/Environment.h" -#include "crlcore/AllianceLibrary.h" -#include "crlcore/Catalog.h" -#include "crlcore/ParsersDrivers.h" +#include +#include +#include "hurricane/Cell.h" +#include "crlcore/Environment.h" +#include "crlcore/AllianceLibrary.h" +#include "crlcore/Catalog.h" +#include "crlcore/ParsersDrivers.h" namespace CRL { + using Hurricane::JsonObject; + using Hurricane::JsonStack; using Hurricane::Cell; using Hurricane::Net; class RoutingGauge; @@ -37,8 +38,13 @@ namespace CRL { class AllianceFramework { public: - enum InstancesCountFlags { Recursive=0x1, IgnoreFeeds=0x2 }; - enum LibraryFlags { CreateLibrary=0x1, InSearchPath=0x2, HasCatalog=0x4 }; + enum InstancesCountFlags { Recursive = (1<<0) + , IgnoreFeeds = (1<<1) + }; + enum LibraryFlags { CreateLibrary = (1<<0) + , AppendLibrary = (1<<1) + , HasCatalog = (1<<2) + }; public: // Constructors. static AllianceFramework* create (); @@ -72,9 +78,9 @@ namespace CRL { inline Library* getParentLibrary (); Library* getLibrary ( unsigned int index ); AllianceLibrary* getAllianceLibrary ( unsigned int index ); - AllianceLibrary* getAllianceLibrary ( const Name& libName, unsigned int& flags ); + AllianceLibrary* getAllianceLibrary ( const Name& libName, unsigned int flags ); AllianceLibrary* getAllianceLibrary ( Library* ); - AllianceLibrary* createLibrary ( const string& path, unsigned int& flags, string libName="" ); + AllianceLibrary* createLibrary ( const string& path, unsigned int flags, string libName="" ); inline const AllianceLibraries& getAllianceLibraries () const; void saveLibrary ( Library* ); void saveLibrary ( AllianceLibrary* ); @@ -95,6 +101,7 @@ namespace CRL { unsigned int loadLibraryCells ( const Name& ); static size_t getInstancesCount ( Cell*, unsigned int flags ); // Hurricane Managment. + void toJson ( JsonWriter* ) const; inline string _getTypeName () const; string _getString () const; Record* _getRecord () const; @@ -159,6 +166,16 @@ namespace CRL { inline string AllianceFramework::_getTypeName () const { return "AllianceFramework"; } + class JsonAllianceFramework : public JsonObject { + public: + static void initialize (); + JsonAllianceFramework( unsigned long ); + virtual string getTypeName () const; + virtual JsonAllianceFramework* clone ( unsigned long ) const; + virtual void toData ( JsonStack& ); + }; + + } // CRL namespace. diff --git a/crlcore/src/ccore/crlcore/AllianceLibrary.h b/crlcore/src/ccore/crlcore/AllianceLibrary.h index 64e8cd70..2bce1864 100644 --- a/crlcore/src/ccore/crlcore/AllianceLibrary.h +++ b/crlcore/src/ccore/crlcore/AllianceLibrary.h @@ -30,7 +30,8 @@ namespace Hurricane { namespace CRL { using std::vector; - + using Hurricane::JsonObject; + using Hurricane::JsonStack; using Hurricane::Name; using Hurricane::Library; using Hurricane::Record; @@ -53,6 +54,7 @@ namespace CRL { inline const Name& getPath () const; inline Library* getLibrary () const; // Hurricane management. + void toJson ( JsonWriter* ) const; inline std::string _getTypeName () const; std::string _getString () const; Record* _getRecord () const; @@ -74,6 +76,19 @@ namespace CRL { inline std::string AllianceLibrary::_getTypeName () const { return _TName("AllianceLibrary"); } +// ------------------------------------------------------------------- +// Class : "JsonAllianceLibrary". + + class JsonAllianceLibrary : public JsonObject { + public: + static void initialize (); + JsonAllianceLibrary ( unsigned long flags ); + virtual std::string getTypeName () const; + virtual JsonAllianceLibrary* clone ( unsigned long flags ) const; + virtual void toData ( JsonStack& ); + }; + + } // CRL namespace. diff --git a/crlcore/src/ccore/crlcore/Catalog.h b/crlcore/src/ccore/crlcore/Catalog.h index 0b272450..820c54a8 100644 --- a/crlcore/src/ccore/crlcore/Catalog.h +++ b/crlcore/src/ccore/crlcore/Catalog.h @@ -34,6 +34,8 @@ namespace CRL { using std::string; using std::map; + using Hurricane::JsonObject; + using Hurricane::JsonStack; using Hurricane::_TName; using Hurricane::Name; using Hurricane::Record; @@ -106,6 +108,7 @@ namespace CRL { inline bool setDelete ( bool value ); inline bool setPhysical ( bool value ); inline bool setLogical ( bool value ); + inline bool setInMemory ( bool value ); // Accessors. inline Cell* getCell () const; inline Library* getLibrary () const; @@ -116,6 +119,7 @@ namespace CRL { inline Library* setLibrary ( Library* library ); inline void setDepth ( unsigned int depth ); // Hurricane Management. + void toJson ( JsonWriter* w ) const; inline string _getTypeName () const; string _getString () const; Record* _getRecord () const; @@ -126,7 +130,18 @@ namespace CRL { unsigned int _depth; Cell* _cell; Library* _library; - }; + + // Json Property. + public: + class JsonState : public JsonObject { + public: + static void initialize (); + JsonState ( unsigned long flags ); + virtual string getTypeName () const; + virtual JsonState* clone ( unsigned long ) const; + virtual void toData ( JsonStack& ); + }; + }; private: // Attributes. @@ -142,7 +157,6 @@ namespace CRL { // ------------------------------------------------------------------- // Class : "CRL::CatalogProperty". - class CatalogProperty : public PrivateProperty { public: @@ -154,6 +168,8 @@ namespace CRL { inline Catalog::State* getState () const; inline void setState ( Catalog::State* state ); virtual void onReleasedBy ( DBo* owner ); + virtual bool hasJson () const; + virtual void toJson ( JsonWriter* w, const DBo* ) const; virtual string _getTypeName () const; virtual string _getString () const; virtual Record* _getRecord () const; @@ -168,6 +184,19 @@ namespace CRL { }; +// ------------------------------------------------------------------- +// Class : "CRL::JsonCatalogProperty". + + class JsonCatalogProperty : public JsonObject { + public: + static void initialize (); + JsonCatalogProperty ( unsigned long ); + virtual string getTypeName () const; + virtual JsonCatalogProperty* clone ( unsigned long ) const; + virtual void toData ( JsonStack& ); + }; + + // ------------------------------------------------------------------- // Inline Functions. @@ -193,6 +222,7 @@ namespace CRL { inline bool Catalog::State::setDelete ( bool value ) { return setFlags(Delete ,value); } inline bool Catalog::State::setPhysical ( bool value ) { return setFlags(Physical ,value); } inline bool Catalog::State::setLogical ( bool value ) { return setFlags(Logical ,value); } + inline bool Catalog::State::setInMemory ( bool value ) { return setFlags(InMemory ,value); } inline Library* Catalog::State::setLibrary ( Library* library ) { return _library = library; } inline void Catalog::State::setDepth ( unsigned int depth ) { _depth = depth; } inline Cell* Catalog::State::getCell () const { return _cell; } diff --git a/crlcore/src/ccore/crlcore/Environment.h b/crlcore/src/ccore/crlcore/Environment.h index facceecd..0824bedf 100644 --- a/crlcore/src/ccore/crlcore/Environment.h +++ b/crlcore/src/ccore/crlcore/Environment.h @@ -19,11 +19,18 @@ #include #include -#include +#include "hurricane/Commons.h" +#include "crlcore/SearchPath.h" namespace CRL { + using Hurricane::JsonObject; + using Hurricane::JsonStack; + + +// ------------------------------------------------------------------- +// Class : "Environment". class Environment { public: @@ -76,6 +83,7 @@ namespace CRL { void addSYSTEM_LIBRARY ( const char* value, const char* libName, unsigned int mode=Append ); // Methods. std::string getPrint () const; + void toJson ( JsonWriter* ) const; inline std::string _getTypeName () const; std::string _getString () const; Record* _getRecord () const; @@ -134,6 +142,19 @@ namespace CRL { inline std::string Environment::_getTypeName () const { return "Environment"; } +// ------------------------------------------------------------------- +// Class : "JsonEnvironment". + + class JsonEnvironment : public JsonObject { + public: + static void initialize (); + JsonEnvironment ( unsigned long flags ); + virtual std::string getTypeName () const; + virtual JsonEnvironment* clone ( unsigned long flags ) const; + virtual void toData ( JsonStack& ); + }; + + } // CRL namespace. diff --git a/documentation/UsersGuide/UsersGuide.html b/documentation/UsersGuide/UsersGuide.html index affefcb6..de7cb191 100644 --- a/documentation/UsersGuide/UsersGuide.html +++ b/documentation/UsersGuide/UsersGuide.html @@ -41,79 +41,80 @@
  • Release 1.0.1963
  • Release 1.0.2049
  • Release v2.0.1
  • -
  • Release v2.1
  • +
  • Release v2.1
  • +
  • Release v2.2
  • -
  • Installation