2010-06-08 07:09:50 -05:00
|
|
|
|
|
|
|
|
|
// This file is part of the Coriolis Project.
|
|
|
|
|
// Copyright (C) Laboratoire LIP6 - Departement ASIM
|
|
|
|
|
// Universite Pierre et Marie Curie
|
|
|
|
|
//
|
|
|
|
|
// Main contributors :
|
|
|
|
|
// Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
|
|
|
|
// Sophie Belloeil <Sophie.Belloeil@lip6.fr>
|
|
|
|
|
// Hugo Cl<43>ment <Hugo.Clement@lip6.fr>
|
|
|
|
|
// Jean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
|
|
|
|
|
// Damien Dupuis <Damien.Dupuis@lip6.fr>
|
|
|
|
|
// Christian Masson <Christian.Masson@lip6.fr>
|
|
|
|
|
// Marek Sroka <Marek.Sroka@lip6.fr>
|
|
|
|
|
//
|
|
|
|
|
// 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
|
|
|
|
|
//
|
|
|
|
|
// Date : 29/01/2004
|
|
|
|
|
// Author : Christophe Alexandre <Christophe.Alexandre@lip6.fr>
|
|
|
|
|
//
|
|
|
|
|
// Authors-Tag
|
|
|
|
|
|
|
|
|
|
#include "hurricane/Warning.h"
|
|
|
|
|
#include "hurricane/Cell.h"
|
|
|
|
|
#include "nimbus/NimbusEngine.h"
|
|
|
|
|
|
|
|
|
|
#include "mauka/MaukaEngine.h"
|
|
|
|
|
#include "mauka/SimAnnealingPlacer.h"
|
|
|
|
|
#include "mauka/SubRow.h"
|
|
|
|
|
#include "mauka/Row.h"
|
|
|
|
|
#include "mauka/Surface.h"
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
using namespace Hurricane;
|
|
|
|
|
using namespace Mauka;
|
|
|
|
|
|
|
|
|
|
void VerifyInstanceQuadtreeInsertion(Cell *cell)
|
|
|
|
|
{
|
|
|
|
|
cerr << "VerifyInstanceQuadtreeInsertion" << endl;
|
|
|
|
|
for_each_instance(instance, cell->getInstances())
|
|
|
|
|
{
|
|
|
|
|
if (!instance->isMaterialized())
|
|
|
|
|
{
|
|
|
|
|
Cell* masterCell = instance->getMasterCell();
|
|
|
|
|
cerr << tab << instance << " of " << masterCell << " is not materialized..." << endl;
|
|
|
|
|
tab++;
|
|
|
|
|
VerifyInstanceQuadtreeInsertion(masterCell);
|
|
|
|
|
tab--;
|
|
|
|
|
}
|
|
|
|
|
end_for;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DisplayInstanceOccurrence(Occurrence& instanceOccurrence)
|
|
|
|
|
{
|
|
|
|
|
cerr << instanceOccurrence << " " << instanceOccurrence.getBoundingBox() << endl;
|
|
|
|
|
Instance* instance = static_cast<Instance*>(instanceOccurrence.getEntity());
|
|
|
|
|
Path path = instanceOccurrence.getPath();
|
|
|
|
|
cerr << path.getTransformation() << endl;
|
|
|
|
|
cerr << instance->getTransformation() << endl;
|
|
|
|
|
while (!path.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
cerr << path.getTailInstance() << " " << path.getTailInstance()->getTransformation() << endl;
|
|
|
|
|
cerr << path.getTailInstance()->getMasterCell() << endl;
|
|
|
|
|
cerr << path.getTailInstance()->getMasterCell()->getAbutmentBox() << endl;
|
|
|
|
|
cerr << path.getTailInstance()->getMasterCell()->getBoundingBox() << endl;
|
|
|
|
|
cerr << path.getTailInstance()->getAbutmentBox() << endl;
|
|
|
|
|
cerr << path.getTailInstance()->getBoundingBox() << endl;
|
|
|
|
|
path = path.getHeadPath();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Clarify semantic of flatten Collections (walkthrough).
In the Cell/Instance hierarchy, the "terminal" and "leaf cell" concepts
where not clearly defined and partially overlapping. Now, "Terminal" is
the refer to the physical hierarchy (layout) and "TerminalNetlist" to
the logical hierarchy (netlist). The logical hierarchy can be less deep
than the physical one thanks to a Cell dedicated cell flags. Collections
related to the physical hierarchy keep their old names, the one related
to the logical hierarchy are renamed from "Leaf" to "TerminalNetlist".
The name "Leaf" was too ambiguous (leaf for *what* hierarchy).
* Change: In Hurricane::Device, set the "TerminalNetlist" flag once and
for all. No need set it in all the derived classes again.
* New: In Hurricane::MultiCapacitor, added new parameter "dummy" to
create dummies around the capacity matrix.
* Change: In Hurricane::Cell, remove "Leaf" related methods, replace
them by "TerminalNetlist" one, especially Collections. Now we have
two clear sets of Collections to walkthough the layout or the
netlist.
Change the "Terminal" flag into "TerminalNetlist".
* Change: In Hurricane::CellCollections, rename "Leaf" into
"TerminalNetlist" collections and apply the new semantic to the
locators.
* Change: In Hurricane::DataBase, Leaf to TerminalInstance renaming.
* Change: In Hurricane::DeepNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::HyperNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Instance, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Viewer::HierarchyInformations, Leaf to
TerminalInstance renaming.
* Change: In CRL::AllianceFramework, Leaf to TerminalInstance renaming.
* Change: In CRL::Catalog, Leaf to TerminalInstance renaming.
* Change: In CRL::ApParser, Leaf to TerminalInstance renaming.
* Change: In EtesianEngine::AddFeeds, Leaf to TerminalInstance renaming.
* Bug: In EtesianEngine::resetPlacement, move there the loop over
non terminal netlist instances to flag fully placed sub-blocks
as terminal for the netlist. Only then remove the feed cells
from unplaced instances. Previously, the feed cells where stripped
even from already placed instances.
* Change: In Katana, Leaf to TerminalInstance renaming.
* Bug: In Bora::PyDSlicingNode, allow the range parameter to be the
Python None object when we do not want to pass one but need to
have it as positional parameter.
* Change: In Cumulus/clocktree/ClockTree.py, Leaf to TerminalInstance
renaming.
2020-03-10 06:10:53 -05:00
|
|
|
|
void DisplayNonTerminalNetlistInstances(Cell* cell, Box area)
|
2010-06-08 07:09:50 -05:00
|
|
|
|
{
|
|
|
|
|
ltrace(100) << "display of " << cell << " in " << area << endl;
|
Clarify semantic of flatten Collections (walkthrough).
In the Cell/Instance hierarchy, the "terminal" and "leaf cell" concepts
where not clearly defined and partially overlapping. Now, "Terminal" is
the refer to the physical hierarchy (layout) and "TerminalNetlist" to
the logical hierarchy (netlist). The logical hierarchy can be less deep
than the physical one thanks to a Cell dedicated cell flags. Collections
related to the physical hierarchy keep their old names, the one related
to the logical hierarchy are renamed from "Leaf" to "TerminalNetlist".
The name "Leaf" was too ambiguous (leaf for *what* hierarchy).
* Change: In Hurricane::Device, set the "TerminalNetlist" flag once and
for all. No need set it in all the derived classes again.
* New: In Hurricane::MultiCapacitor, added new parameter "dummy" to
create dummies around the capacity matrix.
* Change: In Hurricane::Cell, remove "Leaf" related methods, replace
them by "TerminalNetlist" one, especially Collections. Now we have
two clear sets of Collections to walkthough the layout or the
netlist.
Change the "Terminal" flag into "TerminalNetlist".
* Change: In Hurricane::CellCollections, rename "Leaf" into
"TerminalNetlist" collections and apply the new semantic to the
locators.
* Change: In Hurricane::DataBase, Leaf to TerminalInstance renaming.
* Change: In Hurricane::DeepNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::HyperNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Instance, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Viewer::HierarchyInformations, Leaf to
TerminalInstance renaming.
* Change: In CRL::AllianceFramework, Leaf to TerminalInstance renaming.
* Change: In CRL::Catalog, Leaf to TerminalInstance renaming.
* Change: In CRL::ApParser, Leaf to TerminalInstance renaming.
* Change: In EtesianEngine::AddFeeds, Leaf to TerminalInstance renaming.
* Bug: In EtesianEngine::resetPlacement, move there the loop over
non terminal netlist instances to flag fully placed sub-blocks
as terminal for the netlist. Only then remove the feed cells
from unplaced instances. Previously, the feed cells where stripped
even from already placed instances.
* Change: In Katana, Leaf to TerminalInstance renaming.
* Bug: In Bora::PyDSlicingNode, allow the range parameter to be the
Python None object when we do not want to pass one but need to
have it as positional parameter.
* Change: In Cumulus/clocktree/ClockTree.py, Leaf to TerminalInstance
renaming.
2020-03-10 06:10:53 -05:00
|
|
|
|
for_each_instance(instance, cell->getNonTerminalNetlistInstancesUnder(area))
|
2010-06-08 07:09:50 -05:00
|
|
|
|
{
|
|
|
|
|
ltrace(100) << instance << " " << instance->getBoundingBox() << endl;
|
|
|
|
|
Cell* masterCell = instance->getMasterCell();
|
|
|
|
|
ltracein(20);
|
Clarify semantic of flatten Collections (walkthrough).
In the Cell/Instance hierarchy, the "terminal" and "leaf cell" concepts
where not clearly defined and partially overlapping. Now, "Terminal" is
the refer to the physical hierarchy (layout) and "TerminalNetlist" to
the logical hierarchy (netlist). The logical hierarchy can be less deep
than the physical one thanks to a Cell dedicated cell flags. Collections
related to the physical hierarchy keep their old names, the one related
to the logical hierarchy are renamed from "Leaf" to "TerminalNetlist".
The name "Leaf" was too ambiguous (leaf for *what* hierarchy).
* Change: In Hurricane::Device, set the "TerminalNetlist" flag once and
for all. No need set it in all the derived classes again.
* New: In Hurricane::MultiCapacitor, added new parameter "dummy" to
create dummies around the capacity matrix.
* Change: In Hurricane::Cell, remove "Leaf" related methods, replace
them by "TerminalNetlist" one, especially Collections. Now we have
two clear sets of Collections to walkthough the layout or the
netlist.
Change the "Terminal" flag into "TerminalNetlist".
* Change: In Hurricane::CellCollections, rename "Leaf" into
"TerminalNetlist" collections and apply the new semantic to the
locators.
* Change: In Hurricane::DataBase, Leaf to TerminalInstance renaming.
* Change: In Hurricane::DeepNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::HyperNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Instance, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Viewer::HierarchyInformations, Leaf to
TerminalInstance renaming.
* Change: In CRL::AllianceFramework, Leaf to TerminalInstance renaming.
* Change: In CRL::Catalog, Leaf to TerminalInstance renaming.
* Change: In CRL::ApParser, Leaf to TerminalInstance renaming.
* Change: In EtesianEngine::AddFeeds, Leaf to TerminalInstance renaming.
* Bug: In EtesianEngine::resetPlacement, move there the loop over
non terminal netlist instances to flag fully placed sub-blocks
as terminal for the netlist. Only then remove the feed cells
from unplaced instances. Previously, the feed cells where stripped
even from already placed instances.
* Change: In Katana, Leaf to TerminalInstance renaming.
* Bug: In Bora::PyDSlicingNode, allow the range parameter to be the
Python None object when we do not want to pass one but need to
have it as positional parameter.
* Change: In Cumulus/clocktree/ClockTree.py, Leaf to TerminalInstance
renaming.
2020-03-10 06:10:53 -05:00
|
|
|
|
DisplayNonTerminalNetlistInstances(masterCell, area);
|
2010-06-08 07:09:50 -05:00
|
|
|
|
ltraceout(20);
|
|
|
|
|
end_for;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // End of anonymous namespace.
|
|
|
|
|
|
|
|
|
|
namespace Mauka {
|
|
|
|
|
|
|
|
|
|
using Nimbus::NimbusEngine;
|
|
|
|
|
using Nimbus::GCellLocator;
|
|
|
|
|
|
|
|
|
|
Surface::Surface(MaukaEngine* mauka, const Box& placementbox) :
|
|
|
|
|
Inherit(mauka->getCell(), placementbox),
|
|
|
|
|
_mauka(mauka),
|
|
|
|
|
_rowVector(),
|
|
|
|
|
_rowYMax(),
|
|
|
|
|
_rowYMinInv(),
|
|
|
|
|
_rowZeroOrientation(false),
|
|
|
|
|
_margin(0.0),
|
|
|
|
|
_binWidthMax(0),
|
|
|
|
|
_binWidthMin(0),
|
|
|
|
|
_searchWidth(0),
|
|
|
|
|
_searchHeight(0)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
Surface* Surface::create(MaukaEngine* mauka, const Box& placementbox) {
|
|
|
|
|
if (!mauka) {
|
|
|
|
|
throw Error("Can't create " + _TName("Surface") + " : empty mauka");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!mauka->getCell()) {
|
|
|
|
|
throw Error("Can't create " + _TName("Surface") + " : empty cell on mauka");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Surface* surface = new Surface(mauka, placementbox);
|
|
|
|
|
|
|
|
|
|
surface->_postCreate();
|
|
|
|
|
|
|
|
|
|
return surface;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
void PlacementVerification(Cell* cell, Box& box) {
|
|
|
|
|
set<Occurrence> occurrenceSet;
|
Clarify semantic of flatten Collections (walkthrough).
In the Cell/Instance hierarchy, the "terminal" and "leaf cell" concepts
where not clearly defined and partially overlapping. Now, "Terminal" is
the refer to the physical hierarchy (layout) and "TerminalNetlist" to
the logical hierarchy (netlist). The logical hierarchy can be less deep
than the physical one thanks to a Cell dedicated cell flags. Collections
related to the physical hierarchy keep their old names, the one related
to the logical hierarchy are renamed from "Leaf" to "TerminalNetlist".
The name "Leaf" was too ambiguous (leaf for *what* hierarchy).
* Change: In Hurricane::Device, set the "TerminalNetlist" flag once and
for all. No need set it in all the derived classes again.
* New: In Hurricane::MultiCapacitor, added new parameter "dummy" to
create dummies around the capacity matrix.
* Change: In Hurricane::Cell, remove "Leaf" related methods, replace
them by "TerminalNetlist" one, especially Collections. Now we have
two clear sets of Collections to walkthough the layout or the
netlist.
Change the "Terminal" flag into "TerminalNetlist".
* Change: In Hurricane::CellCollections, rename "Leaf" into
"TerminalNetlist" collections and apply the new semantic to the
locators.
* Change: In Hurricane::DataBase, Leaf to TerminalInstance renaming.
* Change: In Hurricane::DeepNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::HyperNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Instance, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Viewer::HierarchyInformations, Leaf to
TerminalInstance renaming.
* Change: In CRL::AllianceFramework, Leaf to TerminalInstance renaming.
* Change: In CRL::Catalog, Leaf to TerminalInstance renaming.
* Change: In CRL::ApParser, Leaf to TerminalInstance renaming.
* Change: In EtesianEngine::AddFeeds, Leaf to TerminalInstance renaming.
* Bug: In EtesianEngine::resetPlacement, move there the loop over
non terminal netlist instances to flag fully placed sub-blocks
as terminal for the netlist. Only then remove the feed cells
from unplaced instances. Previously, the feed cells where stripped
even from already placed instances.
* Change: In Katana, Leaf to TerminalInstance renaming.
* Bug: In Bora::PyDSlicingNode, allow the range parameter to be the
Python None object when we do not want to pass one but need to
have it as positional parameter.
* Change: In Cumulus/clocktree/ClockTree.py, Leaf to TerminalInstance
renaming.
2020-03-10 06:10:53 -05:00
|
|
|
|
for_each_occurrence(occurrence, cell->getTerminalNetlistInstanceOccurrencesUnder(box)) {
|
2010-06-08 07:09:50 -05:00
|
|
|
|
occurrenceSet.insert(occurrence);
|
|
|
|
|
end_for;
|
|
|
|
|
}
|
Clarify semantic of flatten Collections (walkthrough).
In the Cell/Instance hierarchy, the "terminal" and "leaf cell" concepts
where not clearly defined and partially overlapping. Now, "Terminal" is
the refer to the physical hierarchy (layout) and "TerminalNetlist" to
the logical hierarchy (netlist). The logical hierarchy can be less deep
than the physical one thanks to a Cell dedicated cell flags. Collections
related to the physical hierarchy keep their old names, the one related
to the logical hierarchy are renamed from "Leaf" to "TerminalNetlist".
The name "Leaf" was too ambiguous (leaf for *what* hierarchy).
* Change: In Hurricane::Device, set the "TerminalNetlist" flag once and
for all. No need set it in all the derived classes again.
* New: In Hurricane::MultiCapacitor, added new parameter "dummy" to
create dummies around the capacity matrix.
* Change: In Hurricane::Cell, remove "Leaf" related methods, replace
them by "TerminalNetlist" one, especially Collections. Now we have
two clear sets of Collections to walkthough the layout or the
netlist.
Change the "Terminal" flag into "TerminalNetlist".
* Change: In Hurricane::CellCollections, rename "Leaf" into
"TerminalNetlist" collections and apply the new semantic to the
locators.
* Change: In Hurricane::DataBase, Leaf to TerminalInstance renaming.
* Change: In Hurricane::DeepNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::HyperNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Instance, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Viewer::HierarchyInformations, Leaf to
TerminalInstance renaming.
* Change: In CRL::AllianceFramework, Leaf to TerminalInstance renaming.
* Change: In CRL::Catalog, Leaf to TerminalInstance renaming.
* Change: In CRL::ApParser, Leaf to TerminalInstance renaming.
* Change: In EtesianEngine::AddFeeds, Leaf to TerminalInstance renaming.
* Bug: In EtesianEngine::resetPlacement, move there the loop over
non terminal netlist instances to flag fully placed sub-blocks
as terminal for the netlist. Only then remove the feed cells
from unplaced instances. Previously, the feed cells where stripped
even from already placed instances.
* Change: In Katana, Leaf to TerminalInstance renaming.
* Bug: In Bora::PyDSlicingNode, allow the range parameter to be the
Python None object when we do not want to pass one but need to
have it as positional parameter.
* Change: In Cumulus/clocktree/ClockTree.py, Leaf to TerminalInstance
renaming.
2020-03-10 06:10:53 -05:00
|
|
|
|
// for_each_occurrence(occurrence, cell->getTerminalNetlistInstanceOccurrences()) {
|
2010-06-08 07:09:50 -05:00
|
|
|
|
// if (occurrenceSet.find(occurrence) == occurrenceSet.end()) {
|
|
|
|
|
// cerr << occurrence << ":" << occurrence.getBoundingBox() << endl;
|
|
|
|
|
// throw Error("occurrence is badly placed");
|
|
|
|
|
// }
|
|
|
|
|
// end_for;
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef list<Occurrence> InstanceOccurrencesList;
|
|
|
|
|
|
|
|
|
|
class PlacementProblem {
|
|
|
|
|
public: GCell* _gcell;
|
|
|
|
|
public: InstanceOccurrencesList _fixedInstanceOccurrenceList;
|
|
|
|
|
public: MaukaEngine::UVector _toPlaceInstanceOccurrencesUVector;
|
|
|
|
|
public: Surface::SubRowList _subRowList;
|
|
|
|
|
PlacementProblem(GCell* gcell)
|
|
|
|
|
: _gcell(gcell)
|
|
|
|
|
, _fixedInstanceOccurrenceList()
|
|
|
|
|
, _toPlaceInstanceOccurrencesUVector()
|
|
|
|
|
, _subRowList()
|
|
|
|
|
{}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef list<PlacementProblem*> PlacementProblemList;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Surface::_postCreate ()
|
|
|
|
|
{
|
|
|
|
|
typedef set<Occurrence> OccurrenceSet;
|
|
|
|
|
|
|
|
|
|
Inherit::_postCreate();
|
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
bool partitionned = false;
|
|
|
|
|
NimbusEngine* nimbus = NULL;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
if (_box.isEmpty()) {
|
|
|
|
|
nimbus = NimbusEngine::get ( getCell() );
|
|
|
|
|
if (nimbus == NULL) {
|
|
|
|
|
throw Error("Can't create Mauka::Surface, no Box and no Nimbus");
|
|
|
|
|
}
|
|
|
|
|
_box = nimbus->getGrid()->getRoot()->getBox();
|
2010-06-13 16:02:45 -05:00
|
|
|
|
partitionned = (nimbus->getDepth() > 1);
|
|
|
|
|
|
|
|
|
|
if ( partitionned )
|
|
|
|
|
cmess2 << " - Design is partionned (depth:" << nimbus->getDepth() << ")" << endl;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlacementVerification ( getCell(), _box );
|
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
DbU::Unit sliceHeight = _mauka->getSliceHeight();
|
|
|
|
|
DbU::Unit pitch = _mauka->getPitch();
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
|
|
|
|
if ( _box.isEmpty() or _box.isPonctual() or _box.isFlat())
|
|
|
|
|
throw Error("Wrong Box for Area: %s",getString(_box).c_str());
|
|
|
|
|
|
|
|
|
|
if ( getHeight() % sliceHeight )
|
|
|
|
|
throw Error("Box Height %s must be a multiple of Slice Height %s"
|
|
|
|
|
,DbU::getValueString(getHeight()).c_str()
|
|
|
|
|
,DbU::getValueString(sliceHeight).c_str());
|
|
|
|
|
|
|
|
|
|
DbU::Unit instanceToPlaceWidthMax = 0;
|
2010-06-13 16:02:45 -05:00
|
|
|
|
double instanceToPlaceWidthSum = 0.0;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
|
|
|
|
for ( unsigned int id = 0; id < _mauka->_instanceWidths.size(); ++id ) {
|
|
|
|
|
DbU::Unit instanceWidth = _mauka->_instanceWidths[id];
|
2010-06-13 16:02:45 -05:00
|
|
|
|
instanceToPlaceWidthSum += (double)instanceWidth;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
|
|
|
|
if ( instanceWidth % pitch )
|
|
|
|
|
throw Error("Width of %s (%s) is not a multiple of pitch (%s)."
|
|
|
|
|
,getString(_mauka->_instanceOccurrencesVector[id]).c_str()
|
|
|
|
|
,DbU::getValueString(instanceWidth).c_str()
|
|
|
|
|
,DbU::getValueString(pitch).c_str());
|
|
|
|
|
|
|
|
|
|
if (instanceWidth > instanceToPlaceWidthMax)
|
|
|
|
|
instanceToPlaceWidthMax = instanceWidth;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
// _binWidthMax = DbU::lambda
|
|
|
|
|
// ((unsigned)( 3.0 * DbU::getLambda(instanceToPlaceWidthMax) / DbU::getLambda(pitch))
|
|
|
|
|
// * DbU::getLambda(pitch));
|
|
|
|
|
// _binWidthMin = DbU::lambda
|
|
|
|
|
// ((unsigned)(DbU::getLambda(_binWidthMax) / (DbU::getLambda(pitch) * 2)) * DbU::getLambda(pitch));
|
|
|
|
|
|
|
|
|
|
_binWidthMax = 2 * (instanceToPlaceWidthMax / pitch) * pitch;
|
|
|
|
|
_binWidthMin = (_binWidthMax / (pitch * 2)) * pitch;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
// cerr << "_binWidthMax:" << DbU::getValueString(_binWidthMax) << endl;
|
|
|
|
|
// cerr << "_binWidthMin:" << DbU::getValueString(_binWidthMin) << endl;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
double surfaceTotalWidth = 0.0;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
PlacementProblemList placementProblemList;
|
|
|
|
|
OccurrenceSet verifyInstanceOccurrencesSet;
|
|
|
|
|
|
|
|
|
|
if ( nimbus ) {
|
|
|
|
|
forEach ( GCell*, igcell, nimbus->getPlacementLeaves() ) {
|
|
|
|
|
PlacementProblem* placementProblem = new PlacementProblem(*igcell);
|
|
|
|
|
placementProblemList.push_back(placementProblem);
|
|
|
|
|
|
|
|
|
|
InstanceOccurrencesList toPlaceInstanceOccurrencesList;
|
|
|
|
|
// Search for preplaced leaf instances
|
|
|
|
|
forEach ( Occurrence
|
Clarify semantic of flatten Collections (walkthrough).
In the Cell/Instance hierarchy, the "terminal" and "leaf cell" concepts
where not clearly defined and partially overlapping. Now, "Terminal" is
the refer to the physical hierarchy (layout) and "TerminalNetlist" to
the logical hierarchy (netlist). The logical hierarchy can be less deep
than the physical one thanks to a Cell dedicated cell flags. Collections
related to the physical hierarchy keep their old names, the one related
to the logical hierarchy are renamed from "Leaf" to "TerminalNetlist".
The name "Leaf" was too ambiguous (leaf for *what* hierarchy).
* Change: In Hurricane::Device, set the "TerminalNetlist" flag once and
for all. No need set it in all the derived classes again.
* New: In Hurricane::MultiCapacitor, added new parameter "dummy" to
create dummies around the capacity matrix.
* Change: In Hurricane::Cell, remove "Leaf" related methods, replace
them by "TerminalNetlist" one, especially Collections. Now we have
two clear sets of Collections to walkthough the layout or the
netlist.
Change the "Terminal" flag into "TerminalNetlist".
* Change: In Hurricane::CellCollections, rename "Leaf" into
"TerminalNetlist" collections and apply the new semantic to the
locators.
* Change: In Hurricane::DataBase, Leaf to TerminalInstance renaming.
* Change: In Hurricane::DeepNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::HyperNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Instance, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Viewer::HierarchyInformations, Leaf to
TerminalInstance renaming.
* Change: In CRL::AllianceFramework, Leaf to TerminalInstance renaming.
* Change: In CRL::Catalog, Leaf to TerminalInstance renaming.
* Change: In CRL::ApParser, Leaf to TerminalInstance renaming.
* Change: In EtesianEngine::AddFeeds, Leaf to TerminalInstance renaming.
* Bug: In EtesianEngine::resetPlacement, move there the loop over
non terminal netlist instances to flag fully placed sub-blocks
as terminal for the netlist. Only then remove the feed cells
from unplaced instances. Previously, the feed cells where stripped
even from already placed instances.
* Change: In Katana, Leaf to TerminalInstance renaming.
* Bug: In Bora::PyDSlicingNode, allow the range parameter to be the
Python None object when we do not want to pass one but need to
have it as positional parameter.
* Change: In Cumulus/clocktree/ClockTree.py, Leaf to TerminalInstance
renaming.
2020-03-10 06:10:53 -05:00
|
|
|
|
, ioccurrence, _mauka->getCell()->getTerminalNetlistInstanceOccurrencesUnder(igcell->getBox()) ) {
|
2010-06-08 07:09:50 -05:00
|
|
|
|
Instance* instance = static_cast<Instance*>((*ioccurrence).getEntity());
|
|
|
|
|
|
|
|
|
|
if ( instance->isFixed() ) {
|
|
|
|
|
placementProblem->_fixedInstanceOccurrenceList.push_back(*ioccurrence);
|
|
|
|
|
} else {
|
|
|
|
|
MaukaEngine::InstanceOccurrencesMap::const_iterator
|
|
|
|
|
iomit = _mauka->_instanceOccurrencesMap.find(*ioccurrence);
|
|
|
|
|
|
|
|
|
|
if ( iomit == _mauka->_instanceOccurrencesMap.end() )
|
|
|
|
|
throw Error("Instance occurrence unexpectedly appeared:\n"
|
|
|
|
|
" %s",getString(*ioccurrence).c_str());
|
|
|
|
|
|
|
|
|
|
placementProblem->_toPlaceInstanceOccurrencesUVector.push_back(iomit->second);
|
|
|
|
|
verifyInstanceOccurrencesSet.insert(*ioccurrence);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
// Special case: no Nimbus run, Instances are *not* in the quadtree yet.
|
|
|
|
|
if ( not partitionned ) {
|
Clarify semantic of flatten Collections (walkthrough).
In the Cell/Instance hierarchy, the "terminal" and "leaf cell" concepts
where not clearly defined and partially overlapping. Now, "Terminal" is
the refer to the physical hierarchy (layout) and "TerminalNetlist" to
the logical hierarchy (netlist). The logical hierarchy can be less deep
than the physical one thanks to a Cell dedicated cell flags. Collections
related to the physical hierarchy keep their old names, the one related
to the logical hierarchy are renamed from "Leaf" to "TerminalNetlist".
The name "Leaf" was too ambiguous (leaf for *what* hierarchy).
* Change: In Hurricane::Device, set the "TerminalNetlist" flag once and
for all. No need set it in all the derived classes again.
* New: In Hurricane::MultiCapacitor, added new parameter "dummy" to
create dummies around the capacity matrix.
* Change: In Hurricane::Cell, remove "Leaf" related methods, replace
them by "TerminalNetlist" one, especially Collections. Now we have
two clear sets of Collections to walkthough the layout or the
netlist.
Change the "Terminal" flag into "TerminalNetlist".
* Change: In Hurricane::CellCollections, rename "Leaf" into
"TerminalNetlist" collections and apply the new semantic to the
locators.
* Change: In Hurricane::DataBase, Leaf to TerminalInstance renaming.
* Change: In Hurricane::DeepNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::HyperNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Instance, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Viewer::HierarchyInformations, Leaf to
TerminalInstance renaming.
* Change: In CRL::AllianceFramework, Leaf to TerminalInstance renaming.
* Change: In CRL::Catalog, Leaf to TerminalInstance renaming.
* Change: In CRL::ApParser, Leaf to TerminalInstance renaming.
* Change: In EtesianEngine::AddFeeds, Leaf to TerminalInstance renaming.
* Bug: In EtesianEngine::resetPlacement, move there the loop over
non terminal netlist instances to flag fully placed sub-blocks
as terminal for the netlist. Only then remove the feed cells
from unplaced instances. Previously, the feed cells where stripped
even from already placed instances.
* Change: In Katana, Leaf to TerminalInstance renaming.
* Bug: In Bora::PyDSlicingNode, allow the range parameter to be the
Python None object when we do not want to pass one but need to
have it as positional parameter.
* Change: In Cumulus/clocktree/ClockTree.py, Leaf to TerminalInstance
renaming.
2020-03-10 06:10:53 -05:00
|
|
|
|
forEach(Occurrence, ioccurrence, _mauka->getCell()->getTerminalNetlistInstanceOccurrences() ) {
|
2010-06-13 16:02:45 -05:00
|
|
|
|
Instance* instance = static_cast<Instance*>((*ioccurrence).getEntity());
|
|
|
|
|
if ( instance->isFixed() ) continue;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
MaukaEngine::InstanceOccurrencesMap::const_iterator iomit
|
|
|
|
|
= _mauka->_instanceOccurrencesMap.find(*ioccurrence);
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
if (iomit == _mauka->_instanceOccurrencesMap.end())
|
|
|
|
|
throw Error("Instance occurrence unexpectedly appeared:\n"
|
|
|
|
|
" %s",getString(*ioccurrence).c_str());
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
placementProblem->_toPlaceInstanceOccurrencesUVector.push_back(iomit->second);
|
|
|
|
|
verifyInstanceOccurrencesSet.insert(*ioccurrence);
|
|
|
|
|
}
|
2010-06-08 07:09:50 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DbU::Unit searchWidth = DbU::lambda(_mauka->getSearchRatio() * DbU::getLambda(igcell->getWidth()));
|
|
|
|
|
if (_searchWidth < searchWidth) _searchWidth = searchWidth;
|
|
|
|
|
|
|
|
|
|
DbU::Unit searchHeight = DbU::lambda(_mauka->getSearchRatio() * DbU::getLambda(igcell->getHeight()));
|
|
|
|
|
if (_searchHeight < searchHeight) _searchHeight = searchHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( PlacementProblemList::iterator pplit = placementProblemList.begin();
|
|
|
|
|
pplit != placementProblemList.end(); pplit++) {
|
|
|
|
|
PlacementProblem* placementProblem = *pplit;
|
|
|
|
|
GCell* gcell = placementProblem->_gcell;
|
|
|
|
|
|
|
|
|
|
if ( placementProblem->_fixedInstanceOccurrenceList.size() != 0 ) {
|
|
|
|
|
bool rowZeroOrientation = false;
|
|
|
|
|
int width = (unsigned)(gcell->getWidth () / pitch); // Number of X pitch
|
|
|
|
|
int height = (unsigned)(gcell->getHeight() / sliceHeight); // Number of Y slices
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MaukaEngine::PrePlaceTab prePlaceTab(height, MaukaEngine::PrePlaceRow(width, false));
|
|
|
|
|
|
|
|
|
|
InstanceOccurrencesList::const_iterator iolit
|
|
|
|
|
= placementProblem->_fixedInstanceOccurrenceList.begin();
|
|
|
|
|
|
|
|
|
|
// Find the orientation of the first row.
|
|
|
|
|
Instance* refInstance = static_cast<Instance*>(iolit->getEntity());
|
|
|
|
|
Box refAbutmentBox = refInstance->getAbutmentBox();
|
|
|
|
|
Transformation refTransformation = refInstance->getTransformation();
|
|
|
|
|
|
|
|
|
|
iolit->getPath().getTransformation().applyOn(refAbutmentBox);
|
|
|
|
|
iolit->getPath().getTransformation().applyOn(refTransformation);
|
|
|
|
|
|
|
|
|
|
Box preplacedBox = gcell->getIntersection(refAbutmentBox);
|
|
|
|
|
|
|
|
|
|
// Position en y ramene au slice
|
|
|
|
|
int refInsYPos = (int)((preplacedBox.getYMin() - gcell->getYMin()) / sliceHeight);
|
|
|
|
|
// Hauteur ramene a la hauteur du slice
|
|
|
|
|
int refInsSliceHeight = (int)(preplacedBox.getHeight() / sliceHeight);
|
|
|
|
|
Transformation::Orientation orientation = refTransformation.getOrientation();
|
|
|
|
|
|
|
|
|
|
if ( refInsYPos % 2 == 0 ) {
|
|
|
|
|
if ( (refInsSliceHeight % 2 == 0)
|
|
|
|
|
or (orientation == Transformation::Orientation::ID)
|
|
|
|
|
or (orientation == Transformation::Orientation::MX))
|
|
|
|
|
rowZeroOrientation = false;
|
2010-07-12 10:19:31 -05:00
|
|
|
|
else
|
|
|
|
|
rowZeroOrientation = true;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
} else {
|
|
|
|
|
if ( (refInsSliceHeight % 2 == 0)
|
|
|
|
|
or (orientation == Transformation::Orientation::ID)
|
|
|
|
|
or (orientation == Transformation::Orientation::MX))
|
|
|
|
|
rowZeroOrientation = true;
|
2010-07-12 10:19:31 -05:00
|
|
|
|
else
|
|
|
|
|
rowZeroOrientation = false;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests for each Instance.
|
|
|
|
|
for ( InstanceOccurrencesList::iterator iolit = placementProblem->_fixedInstanceOccurrenceList.begin();
|
|
|
|
|
iolit != placementProblem->_fixedInstanceOccurrenceList.end(); iolit++ ) {
|
|
|
|
|
Instance* instance = static_cast<Instance*>(iolit->getEntity());
|
|
|
|
|
Box instanceAbutmentBox = instance->getAbutmentBox();
|
|
|
|
|
|
|
|
|
|
iolit->getPath().getTransformation().applyOn(instanceAbutmentBox);
|
|
|
|
|
|
|
|
|
|
Box preplacedBox = gcell->getIntersection(instanceAbutmentBox);
|
|
|
|
|
DbU::Unit insWidth = preplacedBox.getWidth();
|
|
|
|
|
DbU::Unit insHeight = preplacedBox.getHeight();
|
|
|
|
|
|
|
|
|
|
int insPitchWidth = (int)(insWidth / pitch); // Largeur ramene au pitch
|
|
|
|
|
int insSliceHeight = (int)(insHeight / sliceHeight); // Hauteur ramene a la hauteur du slice
|
|
|
|
|
|
|
|
|
|
int ypos = (int)((preplacedBox.getYMin() - gcell->getYMin()) / sliceHeight); // Position en Y ramene au slice
|
|
|
|
|
int xpos = (int)((preplacedBox.getXMin() - gcell->getXMin()) / pitch); // Position en X ramene au pitch
|
|
|
|
|
|
|
|
|
|
for ( int yit = ypos; yit < ypos + insSliceHeight; ++yit ) {
|
|
|
|
|
for ( int xit = xpos; xit < xpos + insPitchWidth; ++xit ) {
|
|
|
|
|
if ( (xit > width - 1) or (yit > height - 1) or (xit < 0) or (yit < 0) )
|
|
|
|
|
throw Error("%s is out of the abutment box"
|
|
|
|
|
,getString(*iolit).c_str());
|
|
|
|
|
if ( prePlaceTab[yit][xit] == false )
|
|
|
|
|
prePlaceTab[yit][xit] = true;
|
|
|
|
|
else
|
|
|
|
|
throw Error("%s is badly placed. There is another instance at it's position"
|
|
|
|
|
,getString(*iolit).c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rowOrientation = rowZeroOrientation;
|
|
|
|
|
for ( int y = 0; y < (int)prePlaceTab.size(); ++y ) {
|
|
|
|
|
int x = 0;
|
|
|
|
|
|
|
|
|
|
while ( x < (int)prePlaceTab[y].size() ) {
|
|
|
|
|
while ( (x < (int)prePlaceTab[y].size()) and (prePlaceTab[y][x] == true) ) ++x;
|
|
|
|
|
|
|
|
|
|
DbU::Unit subRowXMin = gcell->getXMin() + x * pitch;
|
|
|
|
|
|
|
|
|
|
if (x >= (int)prePlaceTab[y].size()) break;
|
|
|
|
|
|
|
|
|
|
while ( (x < (int)prePlaceTab[y].size()) and (prePlaceTab[y][x] == false) ) ++x;
|
|
|
|
|
|
|
|
|
|
DbU::Unit subRowXMax = gcell->getXMin() + x * pitch;
|
|
|
|
|
if ( subRowXMax - subRowXMin > _binWidthMin ) {
|
|
|
|
|
SubRow* subRow = SubRow::create ( getCell()
|
|
|
|
|
, this
|
|
|
|
|
, Box(subRowXMin, gcell->getYMin() + y * sliceHeight
|
|
|
|
|
,subRowXMax, gcell->getYMin() + (y+1) * sliceHeight)
|
|
|
|
|
, rowOrientation );
|
|
|
|
|
placementProblem->_subRowList.push_back(subRow);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rowOrientation = not rowOrientation;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
bool rowOrientation = false;
|
|
|
|
|
for ( DbU::Unit ymin = gcell->getYMin()
|
|
|
|
|
; ymin <= gcell->getYMax() - sliceHeight
|
|
|
|
|
; ymin += sliceHeight ) {
|
|
|
|
|
SubRow* subRow = SubRow::create ( getCell()
|
|
|
|
|
, this
|
|
|
|
|
, Box(gcell->getXMin(), ymin
|
|
|
|
|
,gcell->getXMax(), ymin + sliceHeight)
|
|
|
|
|
, rowOrientation );
|
|
|
|
|
placementProblem->_subRowList.push_back(subRow);
|
|
|
|
|
rowOrientation = not rowOrientation;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
PlacementProblem* placementProblem = new PlacementProblem(NULL);
|
|
|
|
|
_searchHeight = getHeight();
|
|
|
|
|
_searchWidth = getWidth();
|
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
bool rowOrientation = false;
|
|
|
|
|
unsigned int nRows = getHeight() / sliceHeight;
|
|
|
|
|
|
|
|
|
|
surfaceTotalWidth = ((double)getWidth()) * nRows;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
|
|
|
|
for ( DbU::Unit ymin = getYMin(); ymin <= getYMax() - sliceHeight; ymin += sliceHeight ) {
|
|
|
|
|
SubRow* subRow = SubRow::create ( getCell()
|
|
|
|
|
, this
|
|
|
|
|
, Box(getXMin(), ymin,getXMax(), ymin + sliceHeight)
|
|
|
|
|
, rowOrientation );
|
|
|
|
|
placementProblem->_subRowList.push_back(subRow);
|
|
|
|
|
rowOrientation = not rowOrientation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( unsigned int id=0; id < _mauka->_instanceOccurrencesVector.size(); ++id ) {
|
|
|
|
|
placementProblem->_toPlaceInstanceOccurrencesUVector.push_back(id);
|
|
|
|
|
}
|
|
|
|
|
throw Error("MaukaEngine needs NimbusEngine");
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
_computeCapacity();
|
|
|
|
|
|
|
|
|
|
linefill output (" ",cmess2);
|
2010-06-08 07:09:50 -05:00
|
|
|
|
for (PlacementProblemList::iterator pplit = placementProblemList.begin();
|
|
|
|
|
pplit != placementProblemList.end(); pplit++) {
|
2010-06-13 16:02:45 -05:00
|
|
|
|
//cmess2 << " - Initial placement of " << (*pplit)->_gcell->getBox() << endl;
|
|
|
|
|
output << (*pplit)->_gcell->getBox();
|
2010-06-08 07:09:50 -05:00
|
|
|
|
_DisplayInstances((*pplit)->_toPlaceInstanceOccurrencesUVector, (*pplit)->_subRowList);
|
|
|
|
|
delete *pplit;
|
|
|
|
|
}
|
2010-06-13 16:02:45 -05:00
|
|
|
|
output << endl;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
|
|
|
|
placementProblemList.clear ();
|
|
|
|
|
|
|
|
|
|
if ( verifyInstanceOccurrencesSet.size() != _mauka->_instanceOccurrencesVector.size() ) {
|
|
|
|
|
cerr << Error("There are %d Instances not taken into account"
|
|
|
|
|
,(_mauka->_instanceOccurrencesVector.size() - verifyInstanceOccurrencesSet.size())) << endl;
|
|
|
|
|
|
|
|
|
|
VerifyInstanceQuadtreeInsertion(_mauka->getCell());
|
|
|
|
|
|
|
|
|
|
for ( MaukaEngine::InstanceOccurrencesVector::iterator iovit = _mauka->_instanceOccurrencesVector.begin();
|
|
|
|
|
iovit != _mauka->_instanceOccurrencesVector.end(); iovit++ ) {
|
|
|
|
|
OccurrenceSet::iterator osit = verifyInstanceOccurrencesSet.find(*iovit);
|
|
|
|
|
|
|
|
|
|
if ( osit == verifyInstanceOccurrencesSet.end() ) {
|
|
|
|
|
cerr << " o Problem with " << *iovit << endl;
|
|
|
|
|
DisplayInstanceOccurrence ( *iovit );
|
Clarify semantic of flatten Collections (walkthrough).
In the Cell/Instance hierarchy, the "terminal" and "leaf cell" concepts
where not clearly defined and partially overlapping. Now, "Terminal" is
the refer to the physical hierarchy (layout) and "TerminalNetlist" to
the logical hierarchy (netlist). The logical hierarchy can be less deep
than the physical one thanks to a Cell dedicated cell flags. Collections
related to the physical hierarchy keep their old names, the one related
to the logical hierarchy are renamed from "Leaf" to "TerminalNetlist".
The name "Leaf" was too ambiguous (leaf for *what* hierarchy).
* Change: In Hurricane::Device, set the "TerminalNetlist" flag once and
for all. No need set it in all the derived classes again.
* New: In Hurricane::MultiCapacitor, added new parameter "dummy" to
create dummies around the capacity matrix.
* Change: In Hurricane::Cell, remove "Leaf" related methods, replace
them by "TerminalNetlist" one, especially Collections. Now we have
two clear sets of Collections to walkthough the layout or the
netlist.
Change the "Terminal" flag into "TerminalNetlist".
* Change: In Hurricane::CellCollections, rename "Leaf" into
"TerminalNetlist" collections and apply the new semantic to the
locators.
* Change: In Hurricane::DataBase, Leaf to TerminalInstance renaming.
* Change: In Hurricane::DeepNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::HyperNet, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Instance, Leaf to TerminalInstance renaming.
* Change: In Hurricane::Viewer::HierarchyInformations, Leaf to
TerminalInstance renaming.
* Change: In CRL::AllianceFramework, Leaf to TerminalInstance renaming.
* Change: In CRL::Catalog, Leaf to TerminalInstance renaming.
* Change: In CRL::ApParser, Leaf to TerminalInstance renaming.
* Change: In EtesianEngine::AddFeeds, Leaf to TerminalInstance renaming.
* Bug: In EtesianEngine::resetPlacement, move there the loop over
non terminal netlist instances to flag fully placed sub-blocks
as terminal for the netlist. Only then remove the feed cells
from unplaced instances. Previously, the feed cells where stripped
even from already placed instances.
* Change: In Katana, Leaf to TerminalInstance renaming.
* Bug: In Bora::PyDSlicingNode, allow the range parameter to be the
Python None object when we do not want to pass one but need to
have it as positional parameter.
* Change: In Cumulus/clocktree/ClockTree.py, Leaf to TerminalInstance
renaming.
2020-03-10 06:10:53 -05:00
|
|
|
|
DisplayNonTerminalNetlistInstances ( _mauka->getCell(), iovit->getBoundingBox() );
|
2010-06-08 07:09:50 -05:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
throw Error("There are %d Instances not taken into account"
|
|
|
|
|
,(_mauka->_instanceOccurrencesVector.size() - verifyInstanceOccurrencesSet.size()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( RowVector::const_iterator rvit = _rowVector.begin(); rvit != _rowVector.end(); rvit++ ) {
|
2010-06-13 16:02:45 -05:00
|
|
|
|
surfaceTotalWidth += (double)((*rvit)->getSubRowsWidth());
|
2010-06-08 07:09:50 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_computeRowsAndSubRows();
|
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
_margin = 1.0 - instanceToPlaceWidthSum / surfaceTotalWidth;
|
|
|
|
|
if ( _margin < 0.0 ) {
|
2010-06-08 07:09:50 -05:00
|
|
|
|
throw Error("There is not enough free space to place the circuit %s < %s"
|
|
|
|
|
,DbU::getValueString(surfaceTotalWidth).c_str()
|
|
|
|
|
,DbU::getValueString(instanceToPlaceWidthSum).c_str()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
if (_margin < 0.15)
|
2014-06-21 10:59:56 -05:00
|
|
|
|
cerr << Warning("Low margin %f, may not be able to complete successfully",_margin) << endl;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
|
|
|
|
_computeCapacity();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Surface::_preDestroy()
|
|
|
|
|
{
|
|
|
|
|
Inherit::_preDestroy();
|
|
|
|
|
for (RowVector::const_iterator rvit = _rowVector.begin();
|
|
|
|
|
rvit != _rowVector.end();
|
|
|
|
|
rvit++)
|
|
|
|
|
(*rvit)->destroy();
|
|
|
|
|
_rowVector.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Surface::_computeCapacity()
|
|
|
|
|
{
|
|
|
|
|
for (RowVector::const_iterator rvit = _rowVector.begin();
|
|
|
|
|
rvit != _rowVector.end();
|
|
|
|
|
rvit++)
|
|
|
|
|
(*rvit)->_computeCapacity(_margin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
struct RowSortByY
|
|
|
|
|
{
|
|
|
|
|
bool operator()(const Container* row1, const Container* row2) const
|
|
|
|
|
{
|
|
|
|
|
return row1->getYMin() < row2->getYMin();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Row* Surface::InsertSubRowInRow(SubRow* subrow, bool orientation)
|
|
|
|
|
{
|
|
|
|
|
Row* row = NULL;
|
|
|
|
|
if (_rowVector.size() == 0)
|
|
|
|
|
{
|
|
|
|
|
row = Row::create(getCell(), this, subrow->getBox(), orientation);
|
|
|
|
|
_rowVector.push_back(row);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RowVector::iterator rvit = lower_bound(_rowVector.begin(), _rowVector.end(), subrow, RowSortByY());
|
|
|
|
|
if (rvit == _rowVector.end())
|
|
|
|
|
{
|
|
|
|
|
row = Row::create(getCell(), this, subrow->getBox(), orientation);
|
|
|
|
|
_rowVector.push_back(row);
|
|
|
|
|
}
|
|
|
|
|
else if ((*rvit)->getYMin() == subrow->getYMin())
|
|
|
|
|
{
|
|
|
|
|
row = *rvit;
|
|
|
|
|
if (row->_orientation != orientation)
|
|
|
|
|
{
|
|
|
|
|
cerr << "PROBLEM in " << row << " orientation with " << subrow << endl;
|
|
|
|
|
}
|
|
|
|
|
//assert(row->_orientation == orientation);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
row = Row::create(getCell(), this, subrow->getBox(), orientation);
|
|
|
|
|
_rowVector.insert(rvit, row);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
row->_InsertSubRow(subrow);
|
|
|
|
|
return row;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Surface::_computeRowsAndSubRows()
|
|
|
|
|
{
|
|
|
|
|
_rowYMax.clear();
|
|
|
|
|
_rowYMinInv.clear();
|
|
|
|
|
for (unsigned i = 0; i < _rowVector.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
Row* row = _rowVector[i];
|
|
|
|
|
_rowYMax[row->getYMax()] = i;
|
|
|
|
|
_rowYMinInv[row->getYMin()] = i;
|
|
|
|
|
row->_computeSubRows();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bin* Surface::getBinInSurface(Bin* srcbin, double dist)
|
|
|
|
|
{
|
|
|
|
|
Point srcPos = srcbin->getCenter();
|
|
|
|
|
|
|
|
|
|
DbU::Unit lowerY = srcPos.getY() - DbU::lambda((dist * DbU::getLambda(_searchHeight)));
|
|
|
|
|
if (lowerY < getYMin())
|
|
|
|
|
lowerY = getYMin();
|
|
|
|
|
DbU::Unit upperY = srcPos.getY() + DbU::lambda((dist * DbU::getLambda(_searchHeight)));
|
|
|
|
|
if (upperY > getYMax())
|
|
|
|
|
upperY = getYMax();
|
|
|
|
|
|
Bug in Python proxy deallocation. Update to latest Coloquinte.
* Bug: In Bootstrap, in coriolisEnv.py, check if devtoolset-2 is already
active before launching it as a sub-shell.
* Bug: In Isobar, In PyHurricane.h, DBoDestroyAttribute() set the proxy
pointer toward the C++ object to NULL. So when the Python object is
deleted no double-deletion occurs on the C++ object.
Add some more trace information in Python link/dealloc.
* Change: In CRL Core, in cyclop, make CMakeLists.txt automatically
choose the right rule for linking the binary wether we use Qt 4 or
Qt 5. Very irksome problem.
* New: In EtesianEngine::addFeed(), do not take into account instances
that are not placed entirely inside the top cell abutment box (was
causing a core dump).
* Bug: In Katabatic, in GCellQueue, correct a mismatch between a GCell
set and the iterators used upon it.
* Bug: In Mauka, in Row & Surface correct a mismatch between a container
and it's iterator.
* New: In Etesian, updated to work with the latest Coloquinte, patch
contributed by G. Gouvine.
Added EtesianEngine::setDefaultAb() to compute an abutment box if
the Cell is completly unplaced.
* New: In cumulus, in ClockTree, now the placer can be configured to be
either Mauka (slow simulated annealing) or Etesian (fast analytic).
New setting 'clockTree.placerEngine' in plugin settings.
2015-02-13 16:38:55 -06:00
|
|
|
|
RowYMax::iterator rinf = _rowYMax.upper_bound(lowerY);
|
|
|
|
|
RowYMinInv::iterator rsup = _rowYMinInv.upper_bound(upperY);
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned randidx = rinf->second +
|
|
|
|
|
(unsigned)((rsup->second - rinf->second + 1) * (rand() / (RAND_MAX+1.0)));
|
|
|
|
|
|
|
|
|
|
Row* searchRow = _rowVector[randidx];
|
|
|
|
|
|
|
|
|
|
DbU::Unit lowerX = srcPos.getX() - DbU::lambda((dist * DbU::getLambda(_searchWidth)));
|
|
|
|
|
if ((lowerX < searchRow->getXMin()) || (lowerX > searchRow->getXMax()))
|
|
|
|
|
lowerX = searchRow->getXMin();
|
|
|
|
|
DbU::Unit upperX = srcPos.getX() + DbU::lambda((dist * DbU::getLambda(_searchWidth)));
|
|
|
|
|
if ((upperX > searchRow->getXMax()) || (upperX < searchRow->getXMin()))
|
|
|
|
|
upperX = searchRow->getXMax();
|
|
|
|
|
|
|
|
|
|
SubRow* subRow = searchRow->getSubRowBetween(lowerX, upperX);
|
|
|
|
|
|
|
|
|
|
if ((lowerX < subRow->getXMin()) || (lowerX > subRow->getXMax()))
|
|
|
|
|
lowerX = subRow->getXMin();
|
|
|
|
|
if ((upperX > subRow->getXMax()) || (upperX < subRow->getXMin()))
|
|
|
|
|
upperX = subRow->getXMax();
|
|
|
|
|
|
|
|
|
|
Bin* dstBin = subRow->getBinBetween(lowerX, upperX, srcbin);
|
|
|
|
|
return dstBin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double Surface::getBinCost() const
|
|
|
|
|
{
|
|
|
|
|
double binCost = 0.0;
|
|
|
|
|
for (RowVector::const_iterator rvit = _rowVector.begin();
|
|
|
|
|
rvit != _rowVector.end();
|
|
|
|
|
rvit++)
|
|
|
|
|
binCost += (*rvit)->getBinCost();
|
|
|
|
|
return binCost;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double Surface::getRowCost() const
|
|
|
|
|
{
|
|
|
|
|
double rowCost = 0.0;
|
|
|
|
|
for (RowVector::const_iterator rvit = _rowVector.begin();
|
|
|
|
|
rvit != _rowVector.end();
|
|
|
|
|
rvit++)
|
|
|
|
|
rowCost += (*rvit)->getCost();
|
|
|
|
|
return rowCost;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
double Surface::getBinsSize() const
|
2010-06-08 07:09:50 -05:00
|
|
|
|
{
|
2010-06-13 16:02:45 -05:00
|
|
|
|
double totalBinsSize = 0.0;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
for (RowVector::const_iterator rvit = _rowVector.begin();
|
|
|
|
|
rvit != _rowVector.end();
|
|
|
|
|
rvit++)
|
2010-06-13 16:02:45 -05:00
|
|
|
|
totalBinsSize += (double)(*rvit)->getBinsSize();
|
2010-06-08 07:09:50 -05:00
|
|
|
|
return totalBinsSize;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
double Surface::getBinsCapa() const
|
2010-06-08 07:09:50 -05:00
|
|
|
|
{
|
2010-06-13 16:02:45 -05:00
|
|
|
|
double totalBinsCapa = 0.0;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
for (RowVector::const_iterator rvit = _rowVector.begin();
|
|
|
|
|
rvit != _rowVector.end();
|
|
|
|
|
rvit++)
|
2010-06-13 16:02:45 -05:00
|
|
|
|
totalBinsCapa += (double)(*rvit)->getBinsCapa();
|
2010-06-08 07:09:50 -05:00
|
|
|
|
return totalBinsCapa;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
double Surface::getSubRowsCapa() const
|
2010-06-08 07:09:50 -05:00
|
|
|
|
{
|
2010-06-13 16:02:45 -05:00
|
|
|
|
double totalSubRowsCapa = 0.0;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
for (RowVector::const_iterator rvit = _rowVector.begin();
|
|
|
|
|
rvit != _rowVector.end();
|
|
|
|
|
rvit++)
|
|
|
|
|
{
|
2010-06-13 16:02:45 -05:00
|
|
|
|
totalSubRowsCapa += (double)(*rvit)->getSubRowsCapa();
|
2010-06-08 07:09:50 -05:00
|
|
|
|
}
|
|
|
|
|
return totalSubRowsCapa;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
class sortInstanceOccurrencesIdsByWidth
|
|
|
|
|
{
|
|
|
|
|
private: MaukaEngine* _mauka;
|
|
|
|
|
public: sortInstanceOccurrencesIdsByWidth(MaukaEngine* mauka): _mauka(mauka) {}
|
|
|
|
|
public:
|
|
|
|
|
bool operator()(unsigned instanceoccurrenceid1, unsigned instanceoccurrenceid2) const
|
|
|
|
|
{
|
|
|
|
|
DbU::Unit width1 = _mauka->getInstanceIdWidth(instanceoccurrenceid1);
|
|
|
|
|
DbU::Unit width2 = _mauka->getInstanceIdWidth(instanceoccurrenceid2);
|
|
|
|
|
return width1 > width2;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Surface::_DisplayInstances(MaukaEngine::UVector& instanceids, SubRowList& subrowlist)
|
|
|
|
|
{
|
|
|
|
|
// Insert instances in subrows
|
|
|
|
|
sort(instanceids.begin(), instanceids.end(), sortInstanceOccurrencesIdsByWidth(_mauka));
|
|
|
|
|
|
|
|
|
|
SubRowList::iterator srlit = subrowlist.begin();
|
|
|
|
|
MaukaEngine::UVector::const_iterator insIterator = instanceids.begin();
|
|
|
|
|
MaukaEngine::UVector::const_iterator lastLoopInsertedInsIterator = insIterator;
|
2010-06-13 16:02:45 -05:00
|
|
|
|
size_t nbInstancesPlaced = 0;
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
// First instance.
|
|
|
|
|
// if ( insIterator != instanceids.end() ) {
|
|
|
|
|
// Cell* master = (static_cast<Instance*>(_mauka->_instanceOccurrencesVector[*insIterator].getEntity()))->getMasterCell();
|
|
|
|
|
// DbU::Unit instanceWidth = _mauka->_instanceWidths[*insIterator];
|
|
|
|
|
// cerr << " Trying to add #0 id:" << *insIterator
|
|
|
|
|
// << " w:" << DbU::getValueString(instanceWidth)<< " " << master << endl;
|
|
|
|
|
// }
|
2010-06-08 07:09:50 -05:00
|
|
|
|
|
2010-06-13 16:02:45 -05:00
|
|
|
|
while (true)
|
2010-06-08 07:09:50 -05:00
|
|
|
|
{
|
|
|
|
|
if (insIterator == instanceids.end())
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
// end of insertion
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (srlit == subrowlist.end())
|
|
|
|
|
{
|
2014-06-21 10:59:56 -05:00
|
|
|
|
//if ( cmess2.enabled() ) cerr << "\n";
|
2010-06-22 09:10:08 -05:00
|
|
|
|
cerr << Warning("Mauka::_DisplayInstances(): Cannot honor Bin margin, bypassing.") << endl;
|
2010-06-13 16:02:45 -05:00
|
|
|
|
|
2010-06-08 07:09:50 -05:00
|
|
|
|
srlit = subrowlist.begin();
|
|
|
|
|
if (lastLoopInsertedInsIterator != insIterator)
|
|
|
|
|
lastLoopInsertedInsIterator = insIterator;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// insertion of instances with respect of Bins margin
|
2010-06-13 16:02:45 -05:00
|
|
|
|
// did not succeed, inserting what's left.
|
2010-06-08 07:09:50 -05:00
|
|
|
|
while (insIterator != instanceids.end())
|
|
|
|
|
{
|
|
|
|
|
for (SubRow::BinVector::iterator bvit = (*srlit)->_binVector.begin();
|
|
|
|
|
bvit != (*srlit)->_binVector.end();
|
|
|
|
|
bvit++)
|
|
|
|
|
{
|
|
|
|
|
Bin* bin = *bvit;
|
|
|
|
|
unsigned instanceId = *insIterator;
|
|
|
|
|
DbU::Unit instanceWidth = _mauka->_instanceWidths[instanceId];
|
|
|
|
|
if (instanceWidth > (*srlit)->getWidthVsSize())
|
|
|
|
|
break;
|
|
|
|
|
bin->addInstance(instanceId);
|
|
|
|
|
++insIterator;
|
|
|
|
|
if (insIterator == instanceids.end())
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (insIterator == instanceids.end())
|
|
|
|
|
break;
|
|
|
|
|
++srlit;
|
|
|
|
|
if (srlit == subrowlist.end())
|
|
|
|
|
{
|
|
|
|
|
if (lastLoopInsertedInsIterator == insIterator)
|
|
|
|
|
{
|
|
|
|
|
//impossible to succeed
|
|
|
|
|
// try to merge all bins in subrows
|
|
|
|
|
bool merged = false;
|
|
|
|
|
for (srlit = subrowlist.begin();
|
|
|
|
|
srlit != subrowlist.end();
|
|
|
|
|
srlit++)
|
|
|
|
|
{
|
|
|
|
|
merged = (*srlit)->_MergeBins();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (merged)
|
|
|
|
|
{
|
|
|
|
|
insIterator = instanceids.begin();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//count instances to place
|
|
|
|
|
unsigned nbInstancesToPlace = 0;
|
|
|
|
|
while (insIterator++ != instanceids.end())
|
|
|
|
|
++nbInstancesToPlace;
|
2010-06-13 16:02:45 -05:00
|
|
|
|
//cerr << "Box: " << getBoundingBox() << endl;
|
|
|
|
|
throw Error("Not enough free space to place all the instances.<br>\n"
|
|
|
|
|
"Please increase the abutment box: %s %d placeds (%d instances remains to place)"
|
2010-06-08 07:09:50 -05:00
|
|
|
|
,getString(getBoundingBox()).c_str()
|
2010-06-13 16:02:45 -05:00
|
|
|
|
,nbInstancesPlaced
|
2010-06-22 09:10:08 -05:00
|
|
|
|
,(nbInstancesToPlace - nbInstancesPlaced)
|
2010-06-08 07:09:50 -05:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
srlit = subrowlist.begin();
|
|
|
|
|
lastLoopInsertedInsIterator = insIterator;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (insIterator != instanceids.end())
|
|
|
|
|
{
|
|
|
|
|
SubRow* subRow = *srlit;
|
|
|
|
|
for (SubRow::BinVector::iterator bvit = (*srlit)->_binVector.begin();
|
|
|
|
|
bvit != (*srlit)->_binVector.end();
|
|
|
|
|
bvit++)
|
|
|
|
|
{
|
|
|
|
|
Bin* bin = *bvit;
|
2010-06-13 16:02:45 -05:00
|
|
|
|
// cerr << " Bin: " << bin->getBoundingBox()
|
|
|
|
|
// << " capa:" << DbU::getValueString(bin->getCapa())
|
|
|
|
|
// << " size:" << DbU::getValueString(bin->getSize())
|
|
|
|
|
// << " SubRow:"
|
|
|
|
|
// << " capa:" << DbU::getValueString(subRow->getCapa())
|
|
|
|
|
// << " size:" << DbU::getValueString(subRow->getSize())
|
|
|
|
|
// << endl;
|
|
|
|
|
|
|
|
|
|
if (insIterator == instanceids.end()) break;
|
|
|
|
|
|
2010-06-08 07:09:50 -05:00
|
|
|
|
unsigned instanceId = *insIterator;
|
|
|
|
|
DbU::Unit instanceWidth = _mauka->_instanceWidths[instanceId];
|
2010-06-13 16:02:45 -05:00
|
|
|
|
if (instanceWidth > subRow->getCapaVsSize()) {
|
|
|
|
|
// cerr << " SubRow capacity exceeded" << endl;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (bin->TryAddInstance(instanceId)) {
|
|
|
|
|
srlit = subrowlist.begin();
|
|
|
|
|
++nbInstancesPlaced;
|
|
|
|
|
++insIterator;
|
|
|
|
|
|
|
|
|
|
// if ( insIterator != instanceids.end() ) {
|
|
|
|
|
// Instance* instance = static_cast<Instance*>(_mauka->_instanceOccurrencesVector[instanceId].getEntity());
|
|
|
|
|
// instanceWidth = _mauka->_instanceWidths[instanceId];
|
|
|
|
|
// cerr << " Trying to add #" << nbInstancesPlaced
|
|
|
|
|
// << " id:" << *insIterator
|
|
|
|
|
// << " w:" << DbU::getValueString(instanceWidth)<< " " << instance << endl;
|
|
|
|
|
// cerr << " " << _mauka->_instanceOccurrencesVector[instanceId]<< endl;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-06-08 07:09:50 -05:00
|
|
|
|
}
|
|
|
|
|
++srlit;
|
2010-06-13 16:02:45 -05:00
|
|
|
|
// if ( srlit != subrowlist.end() ) {
|
|
|
|
|
// cerr << " SubRow capaVsSize: " << DbU::getValueString((*srlit)->getCapaVsSize()) << endl;
|
|
|
|
|
// }
|
2010-06-08 07:09:50 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Record* Surface::_getRecord() const
|
|
|
|
|
{
|
|
|
|
|
Record* record = Inherit::_getRecord();
|
|
|
|
|
if (record) {
|
|
|
|
|
record->add(getSlot("MaukaEngine", _mauka));
|
|
|
|
|
}
|
|
|
|
|
return record;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Surface::DisplayBinHits() const
|
|
|
|
|
{
|
|
|
|
|
for (RowVector::const_iterator rvit = _rowVector.begin();
|
|
|
|
|
rvit != _rowVector.end();
|
|
|
|
|
rvit++)
|
|
|
|
|
(*rvit)->DisplayBinHits();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Surface::PlotBinsStats(ofstream& out) const
|
|
|
|
|
{
|
|
|
|
|
out << "plot [:] '-' w l 2" << endl ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Surface::Plot(ofstream& out) const
|
|
|
|
|
{
|
|
|
|
|
out << getXMin() << " " << getYMin() << endl
|
|
|
|
|
<< getXMin() << " " << getYMax() << endl
|
|
|
|
|
<< getXMax() << " " << getYMax() << endl
|
|
|
|
|
<< getXMax() << " " << getYMin() << endl
|
|
|
|
|
<< getXMin() << " " << getYMin() << endl << endl;
|
|
|
|
|
out << "EOF" << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|