2016-05-23 09:15:25 -05:00
|
|
|
// -*- mode: C++; explicit-buffer-name: "Matrix.cpp<anabatic>" -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
2018-01-06 10:55:44 -06:00
|
|
|
// Copyright (c) UPMC 2016-2018, All Rights Reserved
|
2016-05-23 09:15:25 -05:00
|
|
|
//
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
// | C O R I O L I S |
|
|
|
|
// | A n a b a t i c - Global Routing Toolbox |
|
|
|
|
// | |
|
|
|
|
// | Author : Jean-Paul CHAPUT |
|
|
|
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
|
|
|
// | =============================================================== |
|
|
|
|
// | C++ Module : "./Matrix.cpp" |
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
#include <iostream>
|
2016-06-03 10:29:22 -05:00
|
|
|
#include <iomanip>
|
2016-05-23 09:15:25 -05:00
|
|
|
#include "hurricane/Cell.h"
|
|
|
|
#include "anabatic/Matrix.h"
|
|
|
|
#include "anabatic/GCell.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace Anabatic {
|
|
|
|
|
|
|
|
using std::cout;
|
|
|
|
using std::cerr;
|
|
|
|
using std::endl;
|
2016-06-03 10:29:22 -05:00
|
|
|
using std::setw;
|
|
|
|
using std::setfill;
|
2016-05-23 09:15:25 -05:00
|
|
|
using std::ostringstream;
|
|
|
|
using Hurricane::Error;
|
|
|
|
|
|
|
|
|
|
|
|
Matrix::Matrix ()
|
|
|
|
: _area ()
|
|
|
|
, _side (1)
|
|
|
|
, _gcells()
|
|
|
|
, _imax (0)
|
|
|
|
, _jmax (0)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
Matrix::Matrix ( Box area, DbU::Unit side )
|
|
|
|
: _area (area)
|
|
|
|
, _side (side)
|
|
|
|
, _gcells()
|
|
|
|
, _imax (0)
|
|
|
|
, _jmax (0)
|
|
|
|
{
|
2016-06-03 10:29:22 -05:00
|
|
|
_imax = _area.getWidth () / side + ((_area.getWidth () % side) ? 1 : 0);
|
|
|
|
_jmax = _area.getHeight() / side + ((_area.getHeight() % side) ? 1 : 0);
|
2016-05-23 09:15:25 -05:00
|
|
|
_gcells.resize( _imax*_jmax );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Matrix::~Matrix ()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
void Matrix::setCell ( Cell* cell, DbU::Unit side )
|
|
|
|
{
|
|
|
|
_area = cell->getAbutmentBox();
|
|
|
|
_side = side;
|
2016-06-03 10:29:22 -05:00
|
|
|
_imax = _area.getWidth () / side + ((_area.getWidth () % side) ? 1 : 0);
|
|
|
|
_jmax = _area.getHeight() / side + ((_area.getHeight() % side) ? 1 : 0);
|
2016-05-23 09:15:25 -05:00
|
|
|
_gcells.resize( _imax*_jmax );
|
2016-06-03 10:29:22 -05:00
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Matrix::setCell(): " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-26 06:56:16 -05:00
|
|
|
GCell* Matrix::getUnder ( DbU::Unit x, DbU::Unit y ) const
|
2016-06-03 10:29:22 -05:00
|
|
|
{
|
2016-08-27 08:59:12 -05:00
|
|
|
if (x == _area.getXMax()) --x;
|
|
|
|
if (y == _area.getYMax()) --y;
|
|
|
|
|
2016-06-03 10:29:22 -05:00
|
|
|
int index = xy2maxIndex(x,y);
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Matrix::getUnder() ("
|
2018-03-05 18:48:44 -06:00
|
|
|
<< DbU::getValueString(x) << " "
|
|
|
|
<< DbU::getValueString(y) << ") index:" << index
|
|
|
|
<< " " << ((index < 0) ? NULL : _gcells[index]->getUnder(x,y)) << endl;
|
|
|
|
|
2016-08-27 08:59:12 -05:00
|
|
|
|
2016-06-03 10:29:22 -05:00
|
|
|
return (index < 0) ? NULL : _gcells[index]->getUnder(x,y);
|
|
|
|
}
|
2016-05-26 06:56:16 -05:00
|
|
|
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
void Matrix::updateLookup ( GCell* gcell )
|
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,1) << "Matrix::updateLookup(): " << gcell << endl;
|
2016-05-26 06:56:16 -05:00
|
|
|
|
2016-06-03 10:29:22 -05:00
|
|
|
if (gcell->isFlat()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << " GCell is flat, no update." << endl;
|
|
|
|
cdebug_tabw(110,-1);
|
2016-06-03 10:29:22 -05:00
|
|
|
return;
|
|
|
|
}
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
Box gcellBb = gcell->getBoundingBox();
|
|
|
|
Box updateArea = _area.getIntersection( gcellBb );
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
cdebug_log(110,0) << "_side: " << DbU::getValueString(_side) << endl;
|
|
|
|
cdebug_log(110,0) << "_area: " << _area << endl;
|
|
|
|
cdebug_log(110,0) << "updateArea: " << updateArea << endl;
|
2016-06-03 10:29:22 -05:00
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
if (updateArea.isEmpty()) {
|
|
|
|
cerr << Error( "Matrix::updateLookup(): %s is not under area of %s."
|
|
|
|
, getString(gcell).c_str()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
|
2016-06-03 10:29:22 -05:00
|
|
|
Index indexMin = Index::asMin( this, updateArea.getXMin(), updateArea.getYMin() );
|
|
|
|
Index indexMax = Index::asMax( this, updateArea.getXMax(), updateArea.getYMax() );
|
2016-05-23 09:15:25 -05:00
|
|
|
int xspan = indexMax.i() - indexMin.i();
|
|
|
|
|
2016-06-03 10:29:22 -05:00
|
|
|
DbU::Unit dx = updateArea.getXMin() - _area.getXMin();
|
|
|
|
DbU::Unit dy = updateArea.getYMin() - _area.getYMin();
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "raw_i:" << (dx / _side + ((dx%_side) ? 1 : 0))
|
Added support for 2-Metal block routing in Anabatic & Katana.
* New: In AnabaticEngine::invalidateRoutingPads() this method is a temporary
workaround for a Hurricane problems. When an instance is moved, the
RoutingPads that use it must be moved accordingly, but they are not
invalidated so they stay in the wrong QuadTree.
New method ::_resizeMatrix() to be called when the associated Cell
is resized.
* Bug: In AutoHorizontal::getConstraints() and AutoVertical::getConstraints(),
the *target* constraints where never merged.
* Change: In AutoHorizontal::getCells() and AutoVertical::getGCells(),
now return a boolean to tell if it was ok (must not encounter a NULL
GCell while progessing from source to target).
* New: In Anabatic::Configuration and Anabatic:Session, create new methods:
- getDHorizontalLayer()
- getDhorizontalDepth()
- getDHorizontalWidth()
- getDHorizontalPitch()
And so on for Vertical and Contact.
They supply depth-independant informations about the H/V layers to
build the initial detailed routing.
The AutoSegment::create() methods have been modificated accordingly.
* New: In Anabatic::GCell, add two new types "StdCellRow" and "ChannelRow"
for implementing 2-Metal blocks.
Rename the GCell::setXY() method in GCell::setSouthWestCorner(),
move the contents of GCell::updateContactsPosition() into it and
suppress it.
WARNING: In case of a GCell shrink this may cause problems. But for
now we only expand...
New method GCell::getNetCount() to count the number of Net going
though the GCell.
* Change: In Anabatic::Edge, add specific support for capacity of 2-Metal
routing channels.
* Change: In Anabatic::Dijsktra various methods, replace the "gcell->isMatrix()"
calls by "not gcell->isAnalog()". Add more check so that the methods
pertaining to the analog routing (GRData) are not called in digital
mode.
* New: In Anabatic::Dijkstra::materialize(), add support for 2-Metal specific
cases. That is, always break in case of vertical pass-through or
U-turn. The global routing must always be broken in H-Channel.
* New: In Anabatic::GCell & Anabatic::Edge, make use of the Session mechanism
to ensure the revalidation. The "::revalidate()" method is then moved
as "::materialize()" (overload of Go) and "::_invalidate()" becomes
"::invalidate()"
* Change: In LoadGlobalRouting, cosmetic rename of SortHkByX in SortHookByX.
* New: In GCellTopology, added support for building 2-Metal topologies.
* ForkStack is now an object attribute as many methods do need it.
* To push segments/hook on the stack, a new method "push()" is
available. Perform NULL and fromHook checking. Can also setup
_southWestContact or _northEastContact if it is the "from" edge.
* N/S/E/W edges are now vector as in digital channel mode there
can be more than one.
* Added build topological build methods:
- doRp_2m_Access() RoutingPad stem access.
- _do_2m_1G_1M1() North or south access.
- _do_2m_2G_1M1() North AND south access.
- _do_2m_xG() H-Channel routing.
* New: In Anabatic::Matrix, new ::resize() function, as Cell can be resizeds.
* New: In Anabatic::Vertex, new static method ::getValueString() for a
friendly text rendering.
* New: In Katana::DigitalDistance, support for channel routing.
* Change: In KatanaEngine::digitalSetup() and KatanaEngine::runGlobalrouter(),
for channel routing, calls to setupPowerRails() and
protectRoutingPads() must be called after the core block has
been fully dimensionned.
::runGlobalrouter() contains the code tasked with the grid creation
and channel sizing.
* New: In KatanaEngine: Added support for core block, for 2-Metal routing.
May be expanded for over-the-cell routing in the future.
Added methods :
- isDigitalMode()
- isAnalogMode()
- isMixedMode()
- isChannelMode()
- getBlock() / addBlock()
- setupChannelMode()
- createChannel()
* New: In Katana, new class Block to manage core blocks and perform
channel routing.
* New: In Katana::Session, new convenience method "isOpen()".
2017-08-18 16:56:23 -05:00
|
|
|
<< " raw_j:" << (dy / _side + ((dy%_side) ? 1 : 0)) << endl;
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "indexMin:" << indexMin << endl;
|
|
|
|
cdebug_log(110,0) << "indexMax:" << indexMax << endl;
|
|
|
|
cdebug_log(110,0) << "xspan: " << xspan << endl;
|
2016-06-03 10:29:22 -05:00
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
if (not indexMin.valid() or not indexMax.valid()) { cdebug_tabw(110,-1); return; }
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
int index = indexMin.index();
|
|
|
|
while ( index <= indexMax.index() ) {
|
2016-08-18 04:59:19 -05:00
|
|
|
cdebug_log(110,0) << "i,j = " << index2i(index) << "," << index2j(index)
|
|
|
|
<< " " << getGridPoint(index) << endl;
|
2016-05-26 06:56:16 -05:00
|
|
|
if (updateArea.contains(getGridPoint(index))) _gcells[index] = gcell;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
2016-08-18 04:59:19 -05:00
|
|
|
if (index2j(index) <= indexMax.j()) ++index;
|
|
|
|
else index += _imax - xspan;
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-06-03 10:29:22 -05:00
|
|
|
}
|
|
|
|
|
2016-08-27 08:59:12 -05:00
|
|
|
|
Added support for 2-Metal block routing in Anabatic & Katana.
* New: In AnabaticEngine::invalidateRoutingPads() this method is a temporary
workaround for a Hurricane problems. When an instance is moved, the
RoutingPads that use it must be moved accordingly, but they are not
invalidated so they stay in the wrong QuadTree.
New method ::_resizeMatrix() to be called when the associated Cell
is resized.
* Bug: In AutoHorizontal::getConstraints() and AutoVertical::getConstraints(),
the *target* constraints where never merged.
* Change: In AutoHorizontal::getCells() and AutoVertical::getGCells(),
now return a boolean to tell if it was ok (must not encounter a NULL
GCell while progessing from source to target).
* New: In Anabatic::Configuration and Anabatic:Session, create new methods:
- getDHorizontalLayer()
- getDhorizontalDepth()
- getDHorizontalWidth()
- getDHorizontalPitch()
And so on for Vertical and Contact.
They supply depth-independant informations about the H/V layers to
build the initial detailed routing.
The AutoSegment::create() methods have been modificated accordingly.
* New: In Anabatic::GCell, add two new types "StdCellRow" and "ChannelRow"
for implementing 2-Metal blocks.
Rename the GCell::setXY() method in GCell::setSouthWestCorner(),
move the contents of GCell::updateContactsPosition() into it and
suppress it.
WARNING: In case of a GCell shrink this may cause problems. But for
now we only expand...
New method GCell::getNetCount() to count the number of Net going
though the GCell.
* Change: In Anabatic::Edge, add specific support for capacity of 2-Metal
routing channels.
* Change: In Anabatic::Dijsktra various methods, replace the "gcell->isMatrix()"
calls by "not gcell->isAnalog()". Add more check so that the methods
pertaining to the analog routing (GRData) are not called in digital
mode.
* New: In Anabatic::Dijkstra::materialize(), add support for 2-Metal specific
cases. That is, always break in case of vertical pass-through or
U-turn. The global routing must always be broken in H-Channel.
* New: In Anabatic::GCell & Anabatic::Edge, make use of the Session mechanism
to ensure the revalidation. The "::revalidate()" method is then moved
as "::materialize()" (overload of Go) and "::_invalidate()" becomes
"::invalidate()"
* Change: In LoadGlobalRouting, cosmetic rename of SortHkByX in SortHookByX.
* New: In GCellTopology, added support for building 2-Metal topologies.
* ForkStack is now an object attribute as many methods do need it.
* To push segments/hook on the stack, a new method "push()" is
available. Perform NULL and fromHook checking. Can also setup
_southWestContact or _northEastContact if it is the "from" edge.
* N/S/E/W edges are now vector as in digital channel mode there
can be more than one.
* Added build topological build methods:
- doRp_2m_Access() RoutingPad stem access.
- _do_2m_1G_1M1() North or south access.
- _do_2m_2G_1M1() North AND south access.
- _do_2m_xG() H-Channel routing.
* New: In Anabatic::Matrix, new ::resize() function, as Cell can be resizeds.
* New: In Anabatic::Vertex, new static method ::getValueString() for a
friendly text rendering.
* New: In Katana::DigitalDistance, support for channel routing.
* Change: In KatanaEngine::digitalSetup() and KatanaEngine::runGlobalrouter(),
for channel routing, calls to setupPowerRails() and
protectRoutingPads() must be called after the core block has
been fully dimensionned.
::runGlobalrouter() contains the code tasked with the grid creation
and channel sizing.
* New: In KatanaEngine: Added support for core block, for 2-Metal routing.
May be expanded for over-the-cell routing in the future.
Added methods :
- isDigitalMode()
- isAnalogMode()
- isMixedMode()
- isChannelMode()
- getBlock() / addBlock()
- setupChannelMode()
- createChannel()
* New: In Katana, new class Block to manage core blocks and perform
channel routing.
* New: In Katana::Session, new convenience method "isOpen()".
2017-08-18 16:56:23 -05:00
|
|
|
void Matrix::resize ( Cell* cell, const vector<GCell*>& gcells )
|
|
|
|
{
|
|
|
|
setCell( cell, _side );
|
|
|
|
for ( GCell* gcell : gcells ) updateLookup( gcell );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-03 10:29:22 -05:00
|
|
|
void Matrix::show () const
|
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(111,0) << this << endl;
|
2016-06-03 10:29:22 -05:00
|
|
|
for ( size_t i=0 ; i<_gcells.size() ; ++i ) {
|
2016-08-18 04:59:19 -05:00
|
|
|
//cdebug_log(111,0) << "[" << setw(3) << setfill('0') << i << setfill(' ') << "] ("
|
|
|
|
// << setw(3) << index2i(i) << ","
|
|
|
|
// << setw(3) << index2j(i) << ") " << _gcells[i] << endl;
|
|
|
|
cdebug_log(111,0) << "[" << i << "] ("
|
|
|
|
<< index2i(i) << ","
|
|
|
|
<< index2j(i) << ") " << _gcells[i] << endl;
|
2016-06-03 10:29:22 -05:00
|
|
|
}
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string Matrix::_getTypeName () const
|
|
|
|
{ return "Matrix"; }
|
|
|
|
|
|
|
|
|
|
|
|
string Matrix::_getString () const
|
|
|
|
{
|
|
|
|
ostringstream os;
|
|
|
|
os << "<" << _getTypeName() << " " << _imax << "x" << _jmax
|
|
|
|
<< " " << _area << "/" << DbU::getValueString(_side) << ">";
|
|
|
|
return os.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Record* Matrix::_getRecord () const
|
|
|
|
{
|
|
|
|
Record* record = new Record( _getString() );
|
|
|
|
record->add( getSlot ("_area" , _area ) );
|
|
|
|
record->add( DbU::getValueSlot("_side" , &_side ) );
|
|
|
|
record->add( getSlot ("_imax" , _imax ) );
|
|
|
|
record->add( getSlot ("_jmax" , _jmax ) );
|
|
|
|
record->add( getSlot ("_gcells", &_gcells) );
|
|
|
|
return record;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // Anabatic namespace;
|