First working recursive place & route (Libre-SOC ALU16 benchmark).

* New: In Hurricane::Cell::isLeaf(), a leaf cell was defined as one
    without instances. Now it can be software defined with the
    "FlattenLeaf" state. If it is flagged "flatten leaf" is will be
    considered as a leaf by the trans-hierarchical walkthrough.
      This flag is also set for Cells in the Alliance CATAL.
* New: In Hurricane::Cell_LeafInstanceOccurrences::progress(), add a
    test to prune leaf cells.
* Bug: In Hurricane::getComponentOccurrences(), when calling the
    locator constructor, the "withLeafCells" argument was forgotten
    and was getting the value of "doExtraction" (wich, fortunately,
    was the same).
* Change: In Hurricane::HypreNet_LeafPlugOccurrences::progress(),
    prune the leaf cells instead of the terminal ones.
* Change: In Hurricane::HypreNet_ComponentOccurrences::progress(),
    prune the leaf cells instead of the terminal ones.
* New: In Hurricane::Cell, add a "useFlattenLeaf" mode to take into
    account or ignore the "FlattenLeaf" flag when doing trans-
    hierarchical walkthrough.
      Not sure if it shouldn't be systematic.
* New: In Etesian::toColoquinte() and other, activate the "FlattenLeaf"
    mode for all walkthough. So we can stop at already placed sub-blocks.
* Bug: In Etesian::toColoquinte(), when placed sub-block where present,
    the number of instances was under estimated, so the instance array
    was oversized and the end went unitialized. So we were getting all
    kind of strange behavior from Coloquinte...
      Now throw an exception if the number of instances differs from
    the computed size.
* Bug: In Etesian::toColoquinte(), as for the instance array, now
    correctly compute the size with the ecluded nets (supplies, clocks).
* Bug: In Etesian::resetPlacement(), event if the Cell is unplaced,
    go through the instance list to remove the potential feed cells.
      The netlist is written back after placement *with* the feed
    cells added. So, when loading again, they where cluttering the
    netlist and giving feed redefintions warning. They also generated
    erratic behaviors.
* New: In Anabatic::NetBuilderHV, added configurations for:
    * 1G_1M1_1PinM3
    * 1G_xM1_1PinM2
    * 2G_xM1_1PinM2
    * doRp_AccessNorthPin
* New: In Anabatic::NetBuilderHV, added Pin management in SingleGCell.
* Bug: In Anabatic::NetBuilderHV::_do_xG_1PinM3(), the North/South
    global routing configuration was forgotten (only East/West).
* Bug: In Katana::TrackFixedSegment, the blockage net was a static
    variable initialized at the first run. So we were getting stuck
    with the blockage net of the first cell to be routed. Of course,
    it did show only when Katana was run multiple times in the same
    process.
This commit is contained in:
Jean-Paul Chaput 2020-03-04 00:50:18 +01:00
parent 757b95343b
commit 59ee8358ca
15 changed files with 708 additions and 294 deletions

View File

@ -25,6 +25,7 @@
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Pin.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/Cell.h"
#include "crlcore/Utilities.h"
@ -55,6 +56,7 @@ namespace Anabatic {
using Hurricane::BasicLayer;
using Hurricane::RegularLayer;
using Hurricane::Segment;
using Hurricane::Pin;
using Hurricane::Plug;
using Hurricane::Path;
using Hurricane::Occurrence;
@ -458,13 +460,18 @@ namespace Anabatic {
cdebug_log(112,0) << "Looking into: " << masterNet->getCell() << endl;
for ( Component* component : masterNet->getComponents() ) {
cdebug_log(112,0) << "@ " << component << endl;
if (not NetExternalComponents::isExternal(component)) continue;
if (not NetExternalComponents::isExternal(component)) {
cdebug_log(112,0) << " Not an external component, skip." << endl;
continue;
}
Segment* segment = dynamic_cast<Segment*>(component);
if (not segment) continue;
if (segment->getLayer()->getMask() != metal1->getMask()) continue;
Component* candidate = dynamic_cast<Segment*>(component);
if (not candidate
or (candidate->getLayer()->getMask() != metal1->getMask()) )
candidate = dynamic_cast<Pin*>(component);
if (not candidate) continue;
Box bb = transformation.getBox( component->getBoundingBox() );
Box bb = transformation.getBox( candidate->getBoundingBox() );
DbU::Unit trackPos = 0;
DbU::Unit minPos = DbU::Max;
DbU::Unit maxPos = DbU::Min;
@ -497,7 +504,7 @@ namespace Anabatic {
cdebug_log(112,0) << "| " << occurrence.getPath() << endl;
cdebug_log(112,0) << "| " << transformation << endl;
cdebug_log(112,0) << "| " << bb << " of:" << segment << endl;
cdebug_log(112,0) << "| " << bb << " of:" << candidate << endl;
cdebug_log(112,0) << "| Nearest Pos: " << DbU::getValueString(trackPos) << endl;
if ( (trackPos >= minPos) and (trackPos <= maxPos) ) {

View File

@ -401,14 +401,14 @@ namespace Anabatic {
for ( Hook* hook : fromHook->getHooks() ) {
cdebug_log(145,0) << "Hook: " << hook << endl;
cdebug_log(145,0) << "Topology [" << _connexity.connexity << "] = "
<< "[" << (int)_connexity.fields.globals
<< "+" << (int)_connexity.fields.M1
<< "+" << (int)_connexity.fields.M2
<< "+" << (int)_connexity.fields.M3
<< "+" << (int)_connexity.fields.Pin
<< "+" << (int)_connexity.fields.Pad
<< "] " << _gcell
<< endl;
<< "[" << (int)_connexity.fields.globals
<< "+" << (int)_connexity.fields.M1
<< "+" << (int)_connexity.fields.M2
<< "+" << (int)_connexity.fields.M3
<< "+" << (int)_connexity.fields.Pin
<< "+" << (int)_connexity.fields.Pad
<< "] " << _gcell
<< endl;
Segment* toSegment = dynamic_cast<Segment*>( hook->getComponent() );
if (toSegment) {
@ -507,6 +507,16 @@ namespace Anabatic {
if (_gcell == NULL) throw Error( missingGCell );
cdebug_log(145,0) << "Topology [" << _connexity.connexity << "] = "
<< "[" << (int)_connexity.fields.globals
<< "+" << (int)_connexity.fields.M1
<< "+" << (int)_connexity.fields.M2
<< "+" << (int)_connexity.fields.M3
<< "+" << (int)_connexity.fields.Pin
<< "+" << (int)_connexity.fields.Pad
<< "] " << _gcell
<< endl;
return *this;
}
@ -543,6 +553,15 @@ namespace Anabatic {
void NetBuilder::construct ()
{
cdebug_log(145,1) << "NetBuilder::construct() [" << _connexity.connexity << "] in " << _gcell << endl;
cdebug_log(145,0) << "Topology [" << _connexity.connexity << "] = "
<< "[" << (int)_connexity.fields.globals
<< "+" << (int)_connexity.fields.M1
<< "+" << (int)_connexity.fields.M2
<< "+" << (int)_connexity.fields.M3
<< "+" << (int)_connexity.fields.Pin
<< "+" << (int)_connexity.fields.Pad
<< "] " << _gcell
<< endl;
if (not isTwoMetals()) {
_southWestContact = NULL;
@ -617,17 +636,22 @@ namespace Anabatic {
case Conn_4G: _do_xG(); break;
// End xG cascaded cases.
// Optimized specific cases.
case Conn_1G_1PinM1: _do_1G_1PinM1 (); break;
case Conn_2G_1PinM1: _do_2G_1PinM1 (); break;
case Conn_1G_1PinM2: _do_1G_1PinM2 (); break;
case Conn_2G_1PinM2:
case Conn_3G_1PinM2: _do_xG_1PinM2 (); break;
case Conn_1G_1PinM3: _do_1G_1PinM3 (); break;
case Conn_2G_1PinM3:
case Conn_3G_1PinM3: _do_xG_1PinM3 (); break;
case Conn_1G_1M1_1M2: _do_xG_1M1_1M2(); break;
case Conn_1G_1M1_1M3: _do_1G_xM1 (); break;
case Conn_2G_1M1_1M2: _do_xG_1M1_1M2(); break;
case Conn_1G_1PinM1: _do_1G_1PinM1 (); break;
case Conn_2G_1PinM1: _do_2G_1PinM1 (); break;
case Conn_1G_1PinM2: _do_1G_1PinM2 (); break;
case Conn_2G_1PinM2:
case Conn_3G_1PinM2: _do_xG_1PinM2 (); break;
case Conn_1G_1PinM3: _do_1G_1PinM3 (); break;
case Conn_2G_1PinM3:
case Conn_3G_1PinM3: _do_xG_1PinM3 (); break;
case Conn_1G_1M1_1PinM3: _do_1G_1M1_1PinM3(); break;
case Conn_1G_1M1_1PinM2:
case Conn_1G_2M1_1PinM2: _do_1G_xM1_1PinM2(); break;
case Conn_2G_1M1_1PinM2:
case Conn_2G_2M1_1PinM2: _do_2G_xM1_1PinM2(); break;
case Conn_1G_1M1_1M2: _do_xG_1M1_1M2 (); break;
case Conn_1G_1M1_1M3: _do_1G_xM1 (); break;
case Conn_2G_1M1_1M2: _do_xG_1M1_1M2 (); break;
default:
if (not isTwoMetals())
throw Bug( "Unmanaged Configuration [%d] = [%d+%d+%d+%d,%d+%d] %s in %s\n"
@ -1069,7 +1093,28 @@ namespace Anabatic {
return false;
}
bool NetBuilder::_do_1G_1M1_1PinM3 ()
{
throw Error ( "%s::_do_1G_1M1_1PinM3() method *not* reimplemented from base class.", getTypeName().c_str() );
return false;
}
bool NetBuilder::_do_1G_xM1_1PinM2 ()
{
throw Error ( "%s::_do_1G_xM1_1PinM2() method *not* reimplemented from base class.", getTypeName().c_str() );
return false;
}
bool NetBuilder::_do_2G_xM1_1PinM2 ()
{
throw Error ( "%s::_do_2G_xM1_1PinM2() method *not* reimplemented from base class.", getTypeName().c_str() );
return false;
}
bool NetBuilder::_do_globalSegment ()
{
throw Error ( "%s::_do_globalSegment() method *not* reimplemented from base class.", getTypeName().c_str() );

View File

@ -251,6 +251,45 @@ namespace Anabatic {
}
AutoContact* NetBuilderHV::doRp_AccessNorthPin ( GCell* gcell, RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_AccessNorthPin() " << rp << endl;
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
AutoContact* turn = NULL;
doRp_AutoContacts( gcell, rp, rpSourceContact, rpContactTarget, NoProtect );
Net* net = rp->getNet();
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
if (pinDir == Pin::AccessDirection::NORTH) {
turn = AutoContactTurn::create( gcell, net, Session::getRoutingLayer(1) );
AutoSegment* segment = AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
segment->setAxis( rp->getX(), Flags::Force );
segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
rpSourceContact = turn;
turn = AutoContactTurn::create( gcell, net, Session::getContactLayer(1) );
segment = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal );
rpSourceContact = turn;
DbU::Unit axis = gcell->getYMax() - Session::getDHorizontalPitch();
cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl;
segment->setAxis( axis, Flags::Force );
//segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
cdebug_log(145,0) << segment << endl;
} else {
turn = rpSourceContact;
}
cdebug_tabw(145,-1);
return turn;
}
bool NetBuilderHV::_do_1G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1() [Managed Configuration - Optimized] " << getTopology() << endl;
@ -744,9 +783,8 @@ namespace Anabatic {
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpSourceContact = NULL;
AutoContact* rpContactTarget = NULL;
doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpSourceContact, rpContactTarget, NoFlags );
rpSourceContact = doRp_AccessNorthPin( getGCell(), getRoutingPads()[0] );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn1, Flags::Vertical );
@ -804,15 +842,19 @@ namespace Anabatic {
setSouthWestContact( turn1 );
setNorthEastContact( htee1 );
} else {
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, vtee1, Flags::Vertical );
} else if (north() and south()) {
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( vtee1, turn1, Flags::Vertical );
AutoSegment::create( rpSourceContact, turn1, Flags::Vertical );
setSouthWestContact( vtee1 );
setNorthEastContact( turn1 );
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( turn1, vtee1, Flags::Horizontal );
setBothCornerContacts( vtee1 );
} else { // Remaining case is East & West.
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, htee1, Flags::Vertical );
setBothCornerContacts( htee1 );
}
} else {
AutoContact* vtee1 = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
@ -830,6 +872,144 @@ namespace Anabatic {
}
bool NetBuilderHV::_do_1G_xM1_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_xM1_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
RoutingPad* pinM2 = NULL;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) pinM2 = rp;
else rpsM1.push_back( rp );
}
AutoContact* turn = NULL;
AutoContact* tee = NULL;
AutoContact* pinM2Contact = NULL;
AutoContact* rpM1Contact = NULL;
doRp_AutoContacts( getGCell(), pinM2, pinM2Contact, rpM1Contact, NoProtect );
rpM1Contact = doRp_Access( getGCell(), rpsM1[0], HAccess );
if (north() or south()) {
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
tee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpM1Contact , tee , Flags::Horizontal );
AutoSegment::create( pinM2Contact, turn, Flags::Horizontal );
AutoSegment::create( tee , turn, Flags::Vertical );
} else {
turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
tee = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpM1Contact , turn, Flags::Horizontal );
AutoSegment::create( pinM2Contact, tee , Flags::Horizontal );
AutoSegment::create( tee , turn, Flags::Vertical );
}
setBothCornerContacts( tee );
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_2G_xM1_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_xM1_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
RoutingPad* pinM2 = NULL;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) pinM2 = rp;
else rpsM1.push_back( rp );
}
AutoContact* pinM2Contact = NULL;
AutoContact* rpM1Contact = NULL;
doRp_AutoContacts( getGCell(), pinM2, pinM2Contact, rpM1Contact, NoFlags );
rpM1Contact = doRp_Access( getGCell(), rpsM1[0], NoFlags );
if (north() and south()) {
AutoContact* htee = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* vtee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinM2Contact, htee, Flags::Horizontal );
AutoSegment::create( rpM1Contact , htee, Flags::Vertical );
AutoSegment::create( htee , vtee, Flags::Horizontal );
setBothCornerContacts( vtee );
} else if (east() and west()) {
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* htee2 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinM2Contact, htee1, Flags::Horizontal );
AutoSegment::create( rpM1Contact , htee1, Flags::Vertical );
AutoSegment::create( htee1 , turn , Flags::Horizontal );
AutoSegment::create( htee2 , turn , Flags::Vertical );
setBothCornerContacts( htee2 );
} else {
AutoContact* htee1 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* htee2 = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinM2Contact, htee1, Flags::Horizontal );
AutoSegment::create( rpM1Contact , htee1, Flags::Vertical );
AutoSegment::create( htee1 , htee2, Flags::Horizontal );
AutoSegment::create( htee2 , turn , Flags::Vertical );
setNorthEastContact( htee2 );
setSouthWestContact( turn );
}
for ( size_t i=1 ; i<rpsM1.size() ; ++i ) {
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_1G_1M1_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpSourceContact = NULL;
RoutingPad* pinM3 = getRoutingPads()[0];
RoutingPad* rpM1 = getRoutingPads()[1];
if (dynamic_cast<Pin*>(rpM1->getOccurrence().getEntity())) std::swap( rpM1, pinM3 );
AutoContact* contact1 = doRp_Access( getGCell(), rpM1, HAccess );
AutoContact* htee = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( contact1, htee, Flags::Horizontal );
rpSourceContact = doRp_AccessNorthPin( getGCell(), pinM3 );
if (north() or south()) {
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpSourceContact, turn, Flags::Vertical );
AutoSegment::create( turn , htee, Flags::Horizontal );
} else {
AutoSegment::create( rpSourceContact, htee, Flags::Vertical );
}
setBothCornerContacts( htee );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHV::_do_2G_1M1 ()
{
return _do_xG_1M1();
@ -1349,6 +1529,120 @@ namespace Anabatic {
}
void NetBuilderHV::singleGCell ( AnabaticEngine* anbt, Net* net )
{
cdebug_log(145,1) << "NetBuilderHV::singleGCell() " << net << endl;
vector<RoutingPad*> rpM1s;
Component* rpM2 = NULL;
RoutingPad* rpPin = NULL;
for ( RoutingPad* rp : net->getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) {
rpPin = rp;
continue;
}
if (Session::getRoutingGauge()->getLayerDepth(rp->getLayer()) == 1)
rpM2 = rp;
else
rpM1s.push_back( rp );
}
if ( (rpM1s.size() < 2) and not (rpM2 or rpPin) ) {
cerr << Error( "For %s, less than two Plugs/Pins (%d)."
, getString(net).c_str()
, rpM1s.size() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (rpM1s.empty()) {
cerr << Error( "No METAL1 in Single GCell for Net \"%s\".", getString(net->getName()).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
sortRpByX( rpM1s, NetBuilder::NoFlags ); // increasing X.
GCell* gcell1 = anbt->getGCellUnder( (*rpM1s.begin ())->getCenter() );
GCell* gcell2 = anbt->getGCellUnder( (*rpM1s.rbegin())->getCenter() );
if (not gcell1) {
cerr << Error( "No GCell under %s.", getString(*(rpM1s.begin())).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (gcell1 != gcell2) {
cerr << Error( "Not under a single GCell %s.", getString(*(rpM1s.rbegin())).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
cdebug_log(145,0) << "singleGCell " << gcell1 << endl;
AutoContact* turn1 = NULL;
AutoContact* turn2 = NULL;
AutoContact* source = NULL;
AutoContact* target = NULL;
for ( size_t irp=1 ; irp<rpM1s.size() ; ++irp ) {
doRp_AutoContacts( gcell1, rpM1s[irp-1], source, turn1, DoSourceContact );
doRp_AutoContacts( gcell1, rpM1s[irp ], target, turn1, DoSourceContact );
if (source->getUConstraints(Flags::Vertical).intersect(target->getUConstraints(Flags::Vertical))) {
uint64_t flags = checkRoutingPadSize( rpM1s[irp-1] );
if ((flags & VSmall) or Session::getConfiguration()->isVH()) {
if (Session::getConfiguration()->isHV()) {
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( source, turn1, Flags::Horizontal );
source = turn1;
}
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( source, turn1 , Flags::Vertical );
source = turn1;
}
flags = checkRoutingPadSize( rpM1s[irp] );
if ((flags & VSmall) or Session::getConfiguration()->isVH()) {
if (Session::getConfiguration()->isHV()) {
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( target, turn1, Flags::Horizontal );
target = turn1;
}
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( target, turn1 , Flags::Vertical );
target = turn1;
}
AutoSegment::create( source, target, Flags::Horizontal );
} else {
turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
turn2 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() );
AutoSegment::create( source, turn1 , Flags::Horizontal );
AutoSegment::create( turn1 , turn2 , Flags::Vertical );
AutoSegment::create( turn2 , target, Flags::Horizontal );
}
}
if (rpM2) {
doRp_AutoContacts( gcell1, rpM1s[0], source, turn1, DoSourceContact );
doRp_AutoContacts( gcell1, rpM2 , target, turn1, DoSourceContact );
turn1 = AutoContactTurn::create( gcell1, rpM2->getNet(), Session::getContactLayer(1) );
AutoSegment::create( source, turn1 , Flags::Horizontal );
AutoSegment::create( turn1 , target, Flags::Vertical );
}
if (rpPin) {
doRp_AutoContacts( gcell1, rpM1s[0], source, turn1, DoSourceContact );
target = doRp_AccessNorthPin( gcell1, rpPin );
turn1 = AutoContactTurn::create( gcell1, rpPin->getNet(), Session::getContactLayer(1) );
AutoSegment::create( source, turn1 , Flags::Horizontal );
AutoSegment::create( turn1 , target, Flags::Vertical );
}
cdebug_tabw(145,-1);
}
string NetBuilderHV::getTypeName () const
{ return "NetBuilderHV"; }

View File

@ -221,6 +221,9 @@ namespace Anabatic {
virtual bool _do_xG_xM2 ();
virtual bool _do_1G_1M3 ();
virtual bool _do_xG_xM3 ();
virtual bool _do_1G_xM1_1PinM2 ();
virtual bool _do_2G_xM1_1PinM2 ();
virtual bool _do_1G_1M1_1PinM3 ();
virtual bool _do_globalSegment ();
virtual void singleGCell ( AnabaticEngine*, Net* );
AutoContact* _doHChannel ();
@ -242,74 +245,79 @@ namespace Anabatic {
+ ((pads) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize)) \
+ ((pins) << (GlobalBSize+Metal1BSize+Metal2BSize+Metal3BSize+PadsBSize))
// Connexity Name | G|M1|M2|M3|Pad|Pin|
enum ConnexityFlag { Conn_0G = CONNEXITY_VALUE( 0, 0, 0, 0, 0 , 0 )
, Conn_2G = CONNEXITY_VALUE( 2, 0, 0, 0, 0 , 0 )
, Conn_3G = CONNEXITY_VALUE( 3, 0, 0, 0, 0 , 0 )
, Conn_4G = CONNEXITY_VALUE( 4, 0, 0, 0, 0 , 0 )
, Conn_5G = CONNEXITY_VALUE( 5, 0, 0, 0, 0 , 0 )
, Conn_6G = CONNEXITY_VALUE( 6, 0, 0, 0, 0 , 0 )
, Conn_0G_2M1 = CONNEXITY_VALUE( 0, 2, 0, 0, 0 , 0 )
, Conn_1G_1M1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 0 )
, Conn_1G_2M1 = CONNEXITY_VALUE( 1, 2, 0, 0, 0 , 0 )
, Conn_1G_3M1 = CONNEXITY_VALUE( 1, 3, 0, 0, 0 , 0 )
, Conn_1G_4M1 = CONNEXITY_VALUE( 1, 4, 0, 0, 0 , 0 )
, Conn_1G_5M1 = CONNEXITY_VALUE( 1, 5, 0, 0, 0 , 0 )
, Conn_1G_1M2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 0 )
, Conn_1G_2M2 = CONNEXITY_VALUE( 1, 0, 2, 0, 0 , 0 )
, Conn_1G_3M2 = CONNEXITY_VALUE( 1, 0, 3, 0, 0 , 0 )
, Conn_1G_4M2 = CONNEXITY_VALUE( 1, 0, 4, 0, 0 , 0 )
, Conn_1G_1M3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 0 )
, Conn_1G_2M3 = CONNEXITY_VALUE( 1, 0, 0, 2, 0 , 0 )
, Conn_1G_3M3 = CONNEXITY_VALUE( 1, 0, 0, 3, 0 , 0 )
, Conn_1G_4M3 = CONNEXITY_VALUE( 1, 0, 0, 4, 0 , 0 )
, Conn_1G_1M1_1M2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 0 )
, Conn_1G_1M1_1M3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_2G_1M1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 0 )
, Conn_2G_2M1 = CONNEXITY_VALUE( 2, 2, 0, 0, 0 , 0 )
, Conn_2G_3M1 = CONNEXITY_VALUE( 2, 3, 0, 0, 0 , 0 )
, Conn_2G_4M1 = CONNEXITY_VALUE( 2, 4, 0, 0, 0 , 0 )
, Conn_2G_5M1 = CONNEXITY_VALUE( 2, 5, 0, 0, 0 , 0 )
, Conn_2G_1M2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 0 )
, Conn_2G_2M2 = CONNEXITY_VALUE( 2, 0, 2, 0, 0 , 0 )
, Conn_2G_3M2 = CONNEXITY_VALUE( 2, 0, 3, 0, 0 , 0 )
, Conn_2G_4M2 = CONNEXITY_VALUE( 2, 0, 4, 0, 0 , 0 )
, Conn_2G_1M3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 0 )
, Conn_2G_2M3 = CONNEXITY_VALUE( 2, 0, 0, 2, 0 , 0 )
, Conn_2G_3M3 = CONNEXITY_VALUE( 2, 0, 0, 3, 0 , 0 )
, Conn_2G_4M3 = CONNEXITY_VALUE( 2, 0, 0, 4, 0 , 0 )
, Conn_2G_1M1_1M2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_3G_1M1 = CONNEXITY_VALUE( 3, 1, 0, 0, 0 , 0 )
, Conn_3G_2M1 = CONNEXITY_VALUE( 3, 2, 0, 0, 0 , 0 )
, Conn_3G_3M1 = CONNEXITY_VALUE( 3, 3, 0, 0, 0 , 0 )
, Conn_3G_4M1 = CONNEXITY_VALUE( 3, 4, 0, 0, 0 , 0 )
, Conn_3G_5M1 = CONNEXITY_VALUE( 3, 5, 0, 0, 0 , 0 )
, Conn_3G_1M2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 0 )
, Conn_3G_2M2 = CONNEXITY_VALUE( 3, 0, 2, 0, 0 , 0 )
, Conn_3G_1M3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 0 )
, Conn_3G_2M3 = CONNEXITY_VALUE( 3, 0, 0, 2, 0 , 0 )
, Conn_3G_3M3 = CONNEXITY_VALUE( 3, 0, 0, 3, 0 , 0 )
, Conn_3G_4M3 = CONNEXITY_VALUE( 3, 0, 0, 4, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_4G_1M1 = CONNEXITY_VALUE( 4, 1, 0, 0, 0 , 0 )
, Conn_4G_2M1 = CONNEXITY_VALUE( 4, 2, 0, 0, 0 , 0 )
, Conn_4G_3M1 = CONNEXITY_VALUE( 4, 3, 0, 0, 0 , 0 )
, Conn_4G_4M1 = CONNEXITY_VALUE( 4, 4, 0, 0, 0 , 0 )
, Conn_4G_1M2 = CONNEXITY_VALUE( 4, 0, 1, 0, 0 , 0 )
, Conn_4G_1M3 = CONNEXITY_VALUE( 4, 0, 0, 1, 0 , 0 )
, Conn_1G_1Pad = CONNEXITY_VALUE( 1, 0, 0, 0, 1 , 0 )
, Conn_2G_1Pad = CONNEXITY_VALUE( 2, 0, 0, 0, 1 , 0 )
, Conn_3G_1Pad = CONNEXITY_VALUE( 3, 0, 0, 0, 1 , 0 )
, Conn_1G_1PinM1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 1 )
, Conn_2G_1PinM1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 1 )
, Conn_1G_1PinM2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 1 )
, Conn_2G_1PinM2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 1 )
, Conn_3G_1PinM2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 1 )
, Conn_1G_1PinM3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 1 )
, Conn_2G_1PinM3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 1 )
, Conn_3G_1PinM3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 1 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
enum ConnexityFlag { Conn_0G = CONNEXITY_VALUE( 0, 0, 0, 0, 0 , 0 )
, Conn_2G = CONNEXITY_VALUE( 2, 0, 0, 0, 0 , 0 )
, Conn_3G = CONNEXITY_VALUE( 3, 0, 0, 0, 0 , 0 )
, Conn_4G = CONNEXITY_VALUE( 4, 0, 0, 0, 0 , 0 )
, Conn_5G = CONNEXITY_VALUE( 5, 0, 0, 0, 0 , 0 )
, Conn_6G = CONNEXITY_VALUE( 6, 0, 0, 0, 0 , 0 )
, Conn_0G_2M1 = CONNEXITY_VALUE( 0, 2, 0, 0, 0 , 0 )
, Conn_1G_1M1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 0 )
, Conn_1G_2M1 = CONNEXITY_VALUE( 1, 2, 0, 0, 0 , 0 )
, Conn_1G_3M1 = CONNEXITY_VALUE( 1, 3, 0, 0, 0 , 0 )
, Conn_1G_4M1 = CONNEXITY_VALUE( 1, 4, 0, 0, 0 , 0 )
, Conn_1G_5M1 = CONNEXITY_VALUE( 1, 5, 0, 0, 0 , 0 )
, Conn_1G_1M2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 0 )
, Conn_1G_2M2 = CONNEXITY_VALUE( 1, 0, 2, 0, 0 , 0 )
, Conn_1G_3M2 = CONNEXITY_VALUE( 1, 0, 3, 0, 0 , 0 )
, Conn_1G_4M2 = CONNEXITY_VALUE( 1, 0, 4, 0, 0 , 0 )
, Conn_1G_1M3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 0 )
, Conn_1G_2M3 = CONNEXITY_VALUE( 1, 0, 0, 2, 0 , 0 )
, Conn_1G_3M3 = CONNEXITY_VALUE( 1, 0, 0, 3, 0 , 0 )
, Conn_1G_4M3 = CONNEXITY_VALUE( 1, 0, 0, 4, 0 , 0 )
, Conn_1G_1M1_1M2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 0 )
, Conn_1G_1M1_1M3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_2G_1M1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 0 )
, Conn_2G_2M1 = CONNEXITY_VALUE( 2, 2, 0, 0, 0 , 0 )
, Conn_2G_3M1 = CONNEXITY_VALUE( 2, 3, 0, 0, 0 , 0 )
, Conn_2G_4M1 = CONNEXITY_VALUE( 2, 4, 0, 0, 0 , 0 )
, Conn_2G_5M1 = CONNEXITY_VALUE( 2, 5, 0, 0, 0 , 0 )
, Conn_2G_1M2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 0 )
, Conn_2G_2M2 = CONNEXITY_VALUE( 2, 0, 2, 0, 0 , 0 )
, Conn_2G_3M2 = CONNEXITY_VALUE( 2, 0, 3, 0, 0 , 0 )
, Conn_2G_4M2 = CONNEXITY_VALUE( 2, 0, 4, 0, 0 , 0 )
, Conn_2G_1M3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 0 )
, Conn_2G_2M3 = CONNEXITY_VALUE( 2, 0, 0, 2, 0 , 0 )
, Conn_2G_3M3 = CONNEXITY_VALUE( 2, 0, 0, 3, 0 , 0 )
, Conn_2G_4M3 = CONNEXITY_VALUE( 2, 0, 0, 4, 0 , 0 )
, Conn_2G_1M1_1M2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_3G_1M1 = CONNEXITY_VALUE( 3, 1, 0, 0, 0 , 0 )
, Conn_3G_2M1 = CONNEXITY_VALUE( 3, 2, 0, 0, 0 , 0 )
, Conn_3G_3M1 = CONNEXITY_VALUE( 3, 3, 0, 0, 0 , 0 )
, Conn_3G_4M1 = CONNEXITY_VALUE( 3, 4, 0, 0, 0 , 0 )
, Conn_3G_5M1 = CONNEXITY_VALUE( 3, 5, 0, 0, 0 , 0 )
, Conn_3G_1M2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 0 )
, Conn_3G_2M2 = CONNEXITY_VALUE( 3, 0, 2, 0, 0 , 0 )
, Conn_3G_1M3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 0 )
, Conn_3G_2M3 = CONNEXITY_VALUE( 3, 0, 0, 2, 0 , 0 )
, Conn_3G_3M3 = CONNEXITY_VALUE( 3, 0, 0, 3, 0 , 0 )
, Conn_3G_4M3 = CONNEXITY_VALUE( 3, 0, 0, 4, 0 , 0 )
// Connexity Name | G|M1|M2|M3|Pad|Pin|
, Conn_4G_1M1 = CONNEXITY_VALUE( 4, 1, 0, 0, 0 , 0 )
, Conn_4G_2M1 = CONNEXITY_VALUE( 4, 2, 0, 0, 0 , 0 )
, Conn_4G_3M1 = CONNEXITY_VALUE( 4, 3, 0, 0, 0 , 0 )
, Conn_4G_4M1 = CONNEXITY_VALUE( 4, 4, 0, 0, 0 , 0 )
, Conn_4G_1M2 = CONNEXITY_VALUE( 4, 0, 1, 0, 0 , 0 )
, Conn_4G_1M3 = CONNEXITY_VALUE( 4, 0, 0, 1, 0 , 0 )
, Conn_1G_1Pad = CONNEXITY_VALUE( 1, 0, 0, 0, 1 , 0 )
, Conn_2G_1Pad = CONNEXITY_VALUE( 2, 0, 0, 0, 1 , 0 )
, Conn_3G_1Pad = CONNEXITY_VALUE( 3, 0, 0, 0, 1 , 0 )
, Conn_1G_1PinM1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 1 )
, Conn_2G_1PinM1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 1 )
, Conn_1G_1PinM2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 1 )
, Conn_2G_1PinM2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 1 )
, Conn_3G_1PinM2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 1 )
, Conn_1G_1M1_1PinM2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 1 )
, Conn_1G_2M1_1PinM2 = CONNEXITY_VALUE( 1, 2, 1, 0, 0 , 1 )
, Conn_2G_1M1_1PinM2 = CONNEXITY_VALUE( 2, 1, 1, 0, 0 , 1 )
, Conn_2G_2M1_1PinM2 = CONNEXITY_VALUE( 2, 2, 1, 0, 0 , 1 )
, Conn_1G_1PinM3 = CONNEXITY_VALUE( 1, 0, 0, 1, 0 , 1 )
, Conn_2G_1PinM3 = CONNEXITY_VALUE( 2, 0, 0, 1, 0 , 1 )
, Conn_3G_1PinM3 = CONNEXITY_VALUE( 3, 0, 0, 1, 0 , 1 )
, Conn_1G_1M1_1PinM3 = CONNEXITY_VALUE( 1, 1, 0, 1, 0 , 1 )
};
#undef CONNEXITY_VALUE

View File

@ -28,33 +28,38 @@ namespace Anabatic {
class NetBuilderHV : public NetBuilder {
public:
NetBuilderHV ();
virtual ~NetBuilderHV ();
virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags );
virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags );
NetBuilderHV ();
virtual ~NetBuilderHV ();
virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags );
virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags );
AutoContact* doRp_AccessNorthPin ( GCell*, RoutingPad* );
private:
virtual bool _do_1G_1M1 ();
virtual bool _do_1G_xM1 ();
virtual bool _do_xG ();
virtual bool _do_2G ();
virtual bool _do_2G_1M1 ();
virtual bool _do_xG_1Pad ();
virtual bool _do_1G_1PinM1 ();
virtual bool _do_2G_1PinM1 ();
virtual bool _do_1G_1PinM2 ();
virtual bool _do_xG_1PinM2 ();
virtual bool _do_1G_1PinM3 ();
virtual bool _do_xG_1PinM3 ();
virtual bool _do_xG_1M1 ();
virtual bool _do_xG_1M1_1M2 ();
virtual bool _do_xG_xM1_xM3 ();
virtual bool _do_4G_1M2 ();
virtual bool _do_xG_xM2 ();
virtual bool _do_1G_1M3 ();
virtual bool _do_xG_xM3 ();
virtual bool _do_globalSegment ();
public:
virtual string getTypeName () const;
virtual bool _do_1G_1M1 ();
virtual bool _do_1G_xM1 ();
virtual bool _do_xG ();
virtual bool _do_2G ();
virtual bool _do_2G_1M1 ();
virtual bool _do_xG_1Pad ();
virtual bool _do_1G_1PinM1 ();
virtual bool _do_2G_1PinM1 ();
virtual bool _do_1G_1PinM2 ();
virtual bool _do_xG_1PinM2 ();
virtual bool _do_1G_1PinM3 ();
virtual bool _do_xG_1PinM3 ();
virtual bool _do_xG_1M1 ();
virtual bool _do_xG_1M1_1M2 ();
virtual bool _do_xG_xM1_xM3 ();
virtual bool _do_4G_1M2 ();
virtual bool _do_xG_xM2 ();
virtual bool _do_1G_1M3 ();
virtual bool _do_xG_xM3 ();
virtual bool _do_1G_xM1_1PinM2 ();
virtual bool _do_2G_xM1_1PinM2 ();
virtual bool _do_1G_1M1_1PinM3 ();
virtual bool _do_globalSegment ();
virtual void singleGCell ( AnabaticEngine*, Net* );
public:
virtual string getTypeName () const;
};

View File

@ -370,6 +370,8 @@ namespace Etesian {
sliceHoles.setSpinSlice0( _yspinSlice0 );
Cell::setFlattenLeafMode( true );
for ( Occurrence occurrence : getBlockCell()->getLeafInstanceOccurrences() )
{
Instance* instance = static_cast<Instance*>(occurrence.getEntity());
@ -397,6 +399,8 @@ namespace Etesian {
sliceHoles.addFeeds();
Cell::setFlattenLeafMode( false );
UpdateSession::close();
if (_viewer) _viewer->getCellWidget()->refresh();

View File

@ -432,7 +432,6 @@ namespace Etesian {
{
//cerr << "EtesianEngine::resetPlacement()" << endl;
if (not getBlockCell()->isPlaced()) return;
_flatDesign = true;
Dots dots ( cmess2, " ", 80, 1000 );
@ -461,10 +460,11 @@ namespace Etesian {
Instance* instance = static_cast<Instance*>(ioccurrence.getEntity());
instance->destroy();
}
if (not getBlockCell()->getAbutmentBox().isEmpty() )
setFixedAbHeight( getBlockCell()->getAbutmentBox().getHeight() );
getBlockCell()->setAbutmentBox( Box() );
getBlockCell()->resetFlags( Cell::Flags::Placed );
// if (not getBlockCell()->getAbutmentBox().isEmpty() )
// setFixedAbHeight( getBlockCell()->getAbutmentBox().getHeight() );
// getBlockCell()->setAbutmentBox( Box() );
// getBlockCell()->resetFlags( Cell::Flags::Placed );
UpdateSession::close();
dots.finish( Dots::Reset );
@ -483,40 +483,42 @@ namespace Etesian {
cmess1 << ::Dots::asString(" - H-pitch" , DbU::getValueString(hpitch)) << endl;
cmess1 << ::Dots::asString(" - V-pitch" , DbU::getValueString(vpitch)) << endl;
resetPlacement();
Dots dots ( cmess2, " ", 80, 1000 );
if (not cmess2.enabled()) dots.disable();
size_t instancesNb = getCell()->getLeafInstanceOccurrences(getBlockInstance()).getSize() + 1; // One dummy fixed instance at the end
// Coloquinte circuit description data-structures.
vector<Transformation> idsToTransf ( instancesNb );
vector<temporary_cell> instances ( instancesNb );
vector< point<int_t> > positions ( instancesNb );
vector< point<bool> > orientations( instancesNb, point<bool>(true, true) );
cmess1 << " - Converting " << instancesNb << " instances" << endl;
cout.flush();
Box topAb = getBlockCell()->getAbutmentBox();
Transformation topTransformation;
if (getBlockInstance()) topTransformation = getBlockInstance()->getTransformation();
topTransformation.applyOn( topAb );
Cell::setFlattenLeafMode( true );
UpdateSession::open();
for ( Occurrence occurrence : getBlockCell()->getNonLeafInstanceOccurrences() )
{
Instance* instance = static_cast<Instance*>(occurrence.getEntity());
Cell* masterCell = instance->getMasterCell();
if (not masterCell->getAbutmentBox().isEmpty()
and (instance->getPlacementStatus() != Instance::PlacementStatus::PLACED)
and (instance->getPlacementStatus() != Instance::PlacementStatus::FIXED ) ) {
throw Error( "EtesianEngine::toColoquinte(): Non-leaf instance \"%s\" of \"%s\" has an abutment box but is *not* placed."
, getString(instance ->getName()).c_str()
, getString(masterCell->getName()).c_str()
);
if (not masterCell->getAbutmentBox().isEmpty()) {
if ( (instance->getPlacementStatus() != Instance::PlacementStatus::PLACED)
and (instance->getPlacementStatus() != Instance::PlacementStatus::FIXED ) ) {
throw Error( "EtesianEngine::toColoquinte(): Non-leaf instance \"%s\" of \"%s\" has an abutment box but is *not* placed."
, getString(instance ->getName()).c_str()
, getString(masterCell->getName()).c_str()
);
} else {
bool isFullyPlaced = true;
for ( Instance* subInstance : masterCell->getInstances() ) {
if ( (instance->getPlacementStatus() != Instance::PlacementStatus::PLACED)
and (instance->getPlacementStatus() != Instance::PlacementStatus::FIXED ) ) {
isFullyPlaced = false;
break;
}
}
if (isFullyPlaced) {
masterCell->setFlattenLeaf( true );
}
}
}
if ( masterCell->getAbutmentBox().isEmpty()
@ -532,13 +534,35 @@ namespace Etesian {
}
UpdateSession::close();
size_t instancesNb = getCell()->getLeafInstanceOccurrences(getBlockInstance()).getSize();
if (not instancesNb) {
cerr << Error( "EtesianEngine::toColoquinte(): No instance to place. We're gonna crash..." ) << endl;
}
// Coloquinte circuit description data-structures.
// One dummy fixed instance at the end
vector<Transformation> idsToTransf ( instancesNb+1 );
vector<temporary_cell> instances ( instancesNb+1 );
vector< point<int_t> > positions ( instancesNb+1 );
vector< point<bool> > orientations( instancesNb+1, point<bool>(true, true) );
cmess1 << " - Converting " << instancesNb << " instances" << endl;
cout.flush();
cmess1 << " - Building RoutingPads (transhierarchical) ..." << endl;
//getCell()->flattenNets( Cell::Flags::BuildRings|Cell::Flags::NoClockFlatten );
getCell()->flattenNets( getBlockInstance(), Cell::Flags::NoClockFlatten );
index_t instanceId = 0;
bool tooManyInstances = false;
index_t instanceId = 0;
for ( Occurrence occurrence : getCell()->getLeafInstanceOccurrences(getBlockInstance()) )
{
if (tooManyInstances or (instanceId == instancesNb)) {
tooManyInstances = true;
++instanceId;
continue;
}
Instance* instance = static_cast<Instance*>(occurrence.getEntity());
Cell* masterCell = instance->getMasterCell();
string instanceName = occurrence.getCompactString();
@ -547,8 +571,8 @@ namespace Etesian {
instanceName.erase( instanceName.size()-1 );
if (CatalogExtension::isFeed(masterCell)) {
cerr << Warning("Feed instance found and skipped.") << endl;
continue;
throw Error( "EtesianEngine::toColoquinte(): Feed instance \"%s\" found."
, instanceName.c_str() );
}
Box instanceAb = _bloatCells.getAb( occurrence );
@ -596,6 +620,19 @@ namespace Etesian {
dots.dot();
}
if (tooManyInstances) {
throw Error( "EtesianEngine::toColoquinte(): Too many leaf instances, %d (expected: %d)\n"
" maybe a virtual flattening problem."
, instanceId, instancesNb
);
}
if (instanceId < instancesNb) {
throw Error( "EtesianEngine::toColoquinte(): Too little leaf instances, %d (expected: %d)\n"
" maybe a virtual flattening problem."
, instanceId, instancesNb
);
}
// Dummy fixed instance at the end
instances[instanceId].size = point<int_t>( 0, 0 );
instances[instanceId].list_index = instanceId;
@ -605,7 +642,23 @@ namespace Etesian {
dots.finish( Dots::Reset|Dots::FirstDot );
size_t netsNb = getCell()->getNets().getSize();
size_t netsNb = 0;
for ( Net* net : getCell()->getNets() )
{
const char* excludedType = NULL;
if (net->getType() == Net::Type::POWER ) excludedType = "POWER";
if (net->getType() == Net::Type::GROUND) excludedType = "GROUND";
if (net->getType() == Net::Type::CLOCK ) excludedType = "CLOCK";
if (excludedType) {
cparanoid << Warning( "%s is not a routable net (%s,excluded)."
, getString(net).c_str(), excludedType ) << endl;
continue;
}
if (af->isBLOCKAGE(net->getName())) continue;
++netsNb;
}
cmess1 << " - Converting " << netsNb << " nets" << endl;
vector<temporary_net> nets ( netsNb );
@ -618,11 +671,7 @@ namespace Etesian {
if (net->getType() == Net::Type::POWER ) excludedType = "POWER";
if (net->getType() == Net::Type::GROUND) excludedType = "GROUND";
if (net->getType() == Net::Type::CLOCK ) excludedType = "CLOCK";
if (excludedType) {
cparanoid << Warning( "%s is not a routable net (%s,excluded)."
, getString(net).c_str(), excludedType ) << endl;
continue;
}
if (excludedType) continue;
if (af->isBLOCKAGE(net->getName())) continue;
dots.dot();
@ -664,8 +713,9 @@ namespace Etesian {
auto iid = _cellsToIds.find( insName );
if (iid == _cellsToIds.end()) {
if (insName != topCellInstancePin)
if (insName != topCellInstancePin) {
cerr << Error( "Unable to lookup instance \"%s\".", insName.c_str() ) << endl;
}
} else {
pins.push_back( temporary_pin( point<int_t>(xpin,ypin), (*iid).second, netId ) );
}
@ -687,6 +737,8 @@ namespace Etesian {
_placementLB.positions_ = positions;
_placementLB.orientations_ = orientations;
_placementUB = _placementLB;
Cell::setFlattenLeafMode( false );
}
@ -928,6 +980,7 @@ namespace Etesian {
getConfiguration()->print( getCell() );
adjustSliceHeight();
resetPlacement();
if (getBlockCell()->getAbutmentBox().isEmpty()) setDefaultAb();
findYSpin();
@ -1060,6 +1113,7 @@ namespace Etesian {
if (getBlockInstance()) topTransformation = getBlockInstance()->getTransformation();
topTransformation.invert();
Cell::setFlattenLeafMode( true );
for ( Occurrence occurrence : getCell()->getLeafInstanceOccurrences(getBlockInstance()) )
{
DbU::Unit hpitch = getHorizontalPitch();
@ -1094,6 +1148,7 @@ namespace Etesian {
instance->setPlacementStatus( Instance::PlacementStatus::PLACED );
}
}
Cell::setFlattenLeafMode( false );
UpdateSession::close();

View File

@ -524,6 +524,10 @@ namespace Hurricane {
// Cell implementation
// ****************************************************************************************************
bool Cell::_useFlattenLeaf = false;
Cell::Cell(Library* library, const Name& name)
// *******************************************
: Inherit(),
@ -601,7 +605,7 @@ Box Cell::getBoundingBox() const
bool Cell::isLeaf() const
// **********************
{
return _instanceMap.isEmpty();
return _instanceMap.isEmpty() or (_useFlattenLeaf and isFlattenLeaf());
}
bool Cell::isCalledBy ( Cell* cell ) const

View File

@ -1007,7 +1007,8 @@ class Cell_LeafInstanceOccurrences : public Collection<Occurrence> {
public:
typedef Hurricane::Locator<Occurrence> Inherit;
public:
Locator ( const Cell* cell=NULL, const Instance* topInstance=NULL );
Locator ( const Cell* cell =NULL
, const Instance* topInstance=NULL );
Locator ( const Locator& );
Locator& operator= ( const Locator& );
virtual Occurrence getElement () const;
@ -1025,7 +1026,8 @@ class Cell_LeafInstanceOccurrences : public Collection<Occurrence> {
};
public:
Cell_LeafInstanceOccurrences ( const Cell* cell=NULL, const Instance* topInstance=NULL );
Cell_LeafInstanceOccurrences ( const Cell* cell =NULL
, const Instance* topInstance=NULL );
Cell_LeafInstanceOccurrences ( const Cell_LeafInstanceOccurrences& );
Cell_LeafInstanceOccurrences& operator= ( const Cell_LeafInstanceOccurrences& );
virtual Collection<Occurrence>* getClone () const;
@ -1740,7 +1742,7 @@ Instances Cell::getTerminalInstances() const
}
Instances Cell::getLeafInstances() const
// *************************************
// ***************************************************
{
return getInstances().getSubSet(Instance::getIsLeafFilter());
}
@ -1820,7 +1822,7 @@ Instances Cell::getLeafInstancesUnder(const Box& area) const
Instances Cell::getNonLeafInstances() const
// ****************************************
{
return getInstances().getSubSet(!Instance::getIsLeafFilter());
return getInstances().getSubSet(not Instance::getIsLeafFilter());
}
Instances Cell::getNonLeafInstancesUnder(const Box& area) const
@ -3222,7 +3224,7 @@ Cell_LeafInstanceOccurrences::Locator::Locator ( const Cell* cell, const Instanc
if (not _topInstance or (nonLeaf == _topInstance)) {
Cell* masterCell = nonLeaf->getMasterCell();
_occurrenceLocator = masterCell->getLeafInstanceOccurrences().getLocator();
_occurrenceLocator = masterCell->getLeafInstanceOccurrences(NULL).getLocator();
if (_occurrenceLocator.isValid()) {
_state = 2;
break;
@ -3293,7 +3295,7 @@ void Cell_LeafInstanceOccurrences::Locator::progress ()
_nonLeafInstanceLocator = _cell->getNonLeafInstances().getLocator();
while (!_state && _nonLeafInstanceLocator.isValid()) {
Cell* masterCell = _nonLeafInstanceLocator.getElement()->getMasterCell();
_occurrenceLocator = masterCell->getLeafInstanceOccurrences().getLocator();
_occurrenceLocator = masterCell->getLeafInstanceOccurrences(NULL).getLocator();
if (_occurrenceLocator.isValid())
_state = 2;
else
@ -3314,7 +3316,7 @@ void Cell_LeafInstanceOccurrences::Locator::progress ()
if (not _topInstance or (nonLeaf == _topInstance)) {
Cell* masterCell = _nonLeafInstanceLocator.getElement()->getMasterCell();
_occurrenceLocator = masterCell->getLeafInstanceOccurrences().getLocator();
_occurrenceLocator = masterCell->getLeafInstanceOccurrences(NULL).getLocator();
if (_occurrenceLocator.isValid()) {
_state = 2;
break;
@ -4744,9 +4746,9 @@ bool Cell_HyperNetRootNetOccurrences::Locator::isValid() const
void Cell_HyperNetRootNetOccurrences::Locator::progress()
// ******************************************************
{
if (_netLocator.isValid())
{
if (_netLocator.isValid()) {
_netLocator.progress();
while ( _netLocator.isValid() ) {
if ( not dynamic_cast<DeepNet*>(_netLocator.getElement())
and not _netLocator.getElement()->isAutomatic()
@ -4754,18 +4756,18 @@ void Cell_HyperNetRootNetOccurrences::Locator::progress()
_netLocator.progress();
}
}
else if (_hyperNetRootNetOccurrenceLocator.isValid())
_hyperNetRootNetOccurrenceLocator.progress();
} else if (_hyperNetRootNetOccurrenceLocator.isValid())
_hyperNetRootNetOccurrenceLocator.progress();
if (!_netLocator.isValid())
while (!_hyperNetRootNetOccurrenceLocator.isValid() && _instanceLocator.isValid())
{
Instance* instance = _instanceLocator.getElement();
_hyperNetRootNetOccurrenceLocator=Locator(instance->getMasterCell(),Path(_path,instance));
_instanceLocator.progress();
if (not _netLocator.isValid()) {
while (not _hyperNetRootNetOccurrenceLocator.isValid() and _instanceLocator.isValid()) {
Instance* instance = _instanceLocator.getElement();
if (not instance->isLeaf()) {
_hyperNetRootNetOccurrenceLocator=Locator(instance->getMasterCell(),Path(_path,instance));
}
_instanceLocator.progress();
}
}
}
string Cell_HyperNetRootNetOccurrences::Locator::_getString() const

View File

@ -365,7 +365,7 @@ Occurrences HyperNet::getLeafPlugOccurrences(bool doExtraction, bool allowInterr
Occurrences HyperNet::getComponentOccurrences(bool doExtraction, bool allowInterruption) const
// *******************************************************************************************
{
return HyperNet_ComponentOccurrences(this, doExtraction, allowInterruption);
return HyperNet_ComponentOccurrences(this, false, doExtraction, allowInterruption);
}
string HyperNet::_getString() const
@ -637,12 +637,14 @@ void HyperNet_NetOccurrences::Locator::progress()
} // for component*.
}
for ( Plug* plug : net->getPlugs() ) {
Occurrence occurrence = Occurrence( plug->getMasterNet(), Path(path, plug->getInstance()) );
if (not net->getCell()->isLeaf()) {
for ( Plug* plug : net->getPlugs() ) {
Occurrence occurrence = Occurrence( plug->getMasterNet(), Path(path, plug->getInstance()) );
if (_netOccurrenceSet.find(occurrence) == _netOccurrenceSet.end()) {
_netOccurrenceSet.insert(occurrence);
_netOccurrenceStack.push(occurrence);
if (_netOccurrenceSet.find(occurrence) == _netOccurrenceSet.end()) {
_netOccurrenceSet.insert(occurrence);
_netOccurrenceStack.push(occurrence);
}
}
}
@ -991,91 +993,81 @@ string HyperNet_LeafPlugOccurrences::_getString() const
// HyperNet_LeafPlugOccurrences::Locator implementation
// ****************************************************************************************************
HyperNet_LeafPlugOccurrences::Locator::Locator()
// ***************************************
: Inherit(),
_netOccurrenceLocator(),
_plugOccurrence()
HyperNet_LeafPlugOccurrences::Locator::Locator ()
: Inherit()
, _netOccurrenceLocator()
, _plugOccurrence()
{ }
HyperNet_LeafPlugOccurrences::Locator::Locator ( const HyperNet* hyperNet
, bool doExtraction
, bool allowInterruption )
: Inherit()
, _netOccurrenceLocator()
, _plugOccurrence()
{
if (hyperNet) {
_netOccurrenceLocator = hyperNet->getNetOccurrences( doExtraction
, allowInterruption ).getLocator();
progress();
}
}
HyperNet_LeafPlugOccurrences::Locator::Locator(const HyperNet* hyperNet, bool doExtraction, bool allowInterruption)
// ****************************************************************************************************
: Inherit(),
_netOccurrenceLocator(),
_plugOccurrence()
HyperNet_LeafPlugOccurrences::Locator::Locator ( const Locator& locator )
: Inherit()
, _netOccurrenceLocator()
, _plugOccurrence()
{ }
HyperNet_LeafPlugOccurrences::Locator& HyperNet_LeafPlugOccurrences::Locator::operator= ( const Locator& locator )
{
if (hyperNet) {
_netOccurrenceLocator = hyperNet->getNetOccurrences(doExtraction,allowInterruption).getLocator();
progress();
_netOccurrenceLocator = locator._netOccurrenceLocator;
_plugOccurrence = locator._plugOccurrence;
return *this;
}
Occurrence HyperNet_LeafPlugOccurrences::Locator::getElement () const
{ return _plugOccurrence; }
Locator<Occurrence>* HyperNet_LeafPlugOccurrences::Locator::getClone () const
{ return new Locator( *this ); }
bool HyperNet_LeafPlugOccurrences::Locator::isValid () const
{ return _plugOccurrence.isValid(); }
void HyperNet_LeafPlugOccurrences::Locator::progress ()
{
_plugOccurrence = Occurrence();
while(_netOccurrenceLocator.isValid() and not _plugOccurrence.isValid()) {
Occurrence netOccurrence = _netOccurrenceLocator.getElement();
_netOccurrenceLocator.progress();
Net* net = static_cast<Net*>( netOccurrence.getEntity() );
Path path = netOccurrence.getPath();
if (not path.isEmpty() and net->getCell()->isLeaf()) {
Instance* instance = path.getTailInstance();
Plug* plug = instance->getPlug(net);
if (plug)
_plugOccurrence = Occurrence( plug,path.getHeadPath() );
}
}
HyperNet_LeafPlugOccurrences::Locator::Locator(const Locator& locator)
// *************************************************************
: Inherit(),
_netOccurrenceLocator(),
_plugOccurrence()
{
}
HyperNet_LeafPlugOccurrences::Locator& HyperNet_LeafPlugOccurrences::Locator::operator=(const Locator& locator)
// ************************************************************************************************
{
_netOccurrenceLocator = locator._netOccurrenceLocator;
_plugOccurrence = locator._plugOccurrence;
return *this;
}
Occurrence HyperNet_LeafPlugOccurrences::Locator::getElement() const
// **********************************************************
{
return _plugOccurrence;
}
Locator<Occurrence>* HyperNet_LeafPlugOccurrences::Locator::getClone() const
// ******************************************************************
{
return new Locator(*this);
}
bool HyperNet_LeafPlugOccurrences::Locator::isValid() const
// **************************************************
{
return _plugOccurrence.isValid();
}
}
void HyperNet_LeafPlugOccurrences::Locator::progress()
// *********************************************
string HyperNet_LeafPlugOccurrences::Locator::_getString () const
{
_plugOccurrence = Occurrence();
while(_netOccurrenceLocator.isValid() && !_plugOccurrence.isValid())
{
Occurrence netOccurrence = _netOccurrenceLocator.getElement();
_netOccurrenceLocator.progress();
Net* net = (Net*)netOccurrence.getEntity();
Path path = netOccurrence.getPath();
if (!path.isEmpty() && net->getCell()->isTerminal())
{
Instance *instance = path.getTailInstance();
Plug *plug=instance->getPlug(net);
if (plug)
_plugOccurrence=Occurrence(plug,path.getHeadPath());
}
}
}
string HyperNet_LeafPlugOccurrences::Locator::_getString() const
// *******************************************************
{
string s = "<" + _TName("HyperNet::LeafPlugOccurrences::Locator");
s += " " + getString(_netOccurrenceLocator);
s += ">";
return s;
string s = "<" + _TName("HyperNet::LeafPlugOccurrences::Locator");
s += " " + getString(_netOccurrenceLocator);
s += ">";
return s;
}
@ -1239,7 +1231,8 @@ void HyperNet_ComponentOccurrences::Locator::progress()
_netOccurrenceLocator.progress();
Net* net = static_cast<Net*>( netOccurrence.getEntity() );
if (_withLeafCells or not net->getCell()->isTerminal()) {
//if (_withLeafCells or not net->getCell()->isTerminal()) {
if (not net->getCell()->isLeaf()) {
_componentLocator = net->getComponents().getLocator();
}
} else

View File

@ -96,20 +96,21 @@ class Instance_IsTerminalFilter : public Filter<Instance*> {
};
class Instance_IsLeafFilter : public Filter<Instance*> {
// *******************************************************
public: Instance_IsLeafFilter() {};
public: Instance_IsLeafFilter(const Instance_IsLeafFilter& filter) {};
public: Instance_IsLeafFilter& operator=(const Instance_IsLeafFilter& filter) {return *this;};
public: virtual Filter<Instance*>* getClone() const {return new Instance_IsLeafFilter(*this);};
public: virtual bool accept(Instance* instance) const {return instance->isLeaf();};
public: virtual string _getString() const {return "<" + _TName("Instance::IsLeafFilter") + ">";};
class Instance_IsLeafFilter : public Filter<Instance*>
{
public:
Instance_IsLeafFilter () {};
Instance_IsLeafFilter ( const Instance_IsLeafFilter& filter ) {};
Instance_IsLeafFilter& operator= ( const Instance_IsLeafFilter& filter )
{ return *this; };
virtual Filter<Instance*>* getClone () const
{ return new Instance_IsLeafFilter( *this ); };
virtual bool accept ( Instance* instance ) const
{ return instance->isLeaf(); };
virtual string _getString () const
{ return "<" + _TName("Instance::IsLeafFilter") + ">"; };
private:
uint32_t _flags;
};
@ -315,7 +316,7 @@ InstanceFilter Instance::getIsTerminalFilter()
}
InstanceFilter Instance::getIsLeafFilter()
// *******************************************
// ***************************************
{
return Instance_IsLeafFilter();
}

View File

@ -342,6 +342,7 @@ class Cell : public Entity {
private: AliasNameSet _netAliasSet;
private: Observable _observers;
private: Flags _flags;
private: static bool _useFlattenLeaf;
// Constructors
// ************
@ -521,6 +522,7 @@ class Cell : public Entity {
public: void addObserver(BaseObserver*);
public: void removeObserver(BaseObserver*);
public: void notify(unsigned flags);
public: static void setFlattenLeafMode(bool state) { _useFlattenLeaf=state; };
};

View File

@ -570,10 +570,10 @@ namespace {
TrackElement* element = TrackFixedSegment::create ( track, segment );
cdebug_log(159,0) << " Insert in " << track << "+" << element << endl;
if (segment->getId() == 51904) {
cerr << " Insert in " << track << endl;
cerr << " +" << element << endl;
}
// if (segment->getId() == 51904) {
// cerr << " Insert in " << track << endl;
// cerr << " +" << element << endl;
// }
}
// if (segment->getId() == 51904) {
// DebugSession::close();

View File

@ -56,16 +56,13 @@ namespace Katana {
// Class : "TrackFixedSegment".
Net* TrackFixedSegment::_blockageNet = NULL;
TrackFixedSegment::TrackFixedSegment ( Track* track, Segment* segment )
: TrackElement (NULL)
, _segment (segment)
{
Box boundingBox = segment->getBoundingBox();
uint32_t flags = TElemFixed | ((segment->getNet() == _blockageNet) ? TElemBlockage : 0);
uint32_t flags = TElemFixed | ((segment->getNet() == Session::getBlockageNet()) ? TElemBlockage : 0);
setFlags( flags );
if (track) {
@ -123,8 +120,6 @@ namespace Katana {
TrackElement* TrackFixedSegment::create ( Track* track, Segment* segment )
{
if ( not _blockageNet ) _blockageNet = Session::getBlockageNet();
TrackFixedSegment* trackFixedSegment = NULL;
if (track) {
trackFixedSegment = new TrackFixedSegment ( track, segment );
@ -189,7 +184,7 @@ namespace Katana {
{
Net* realNet = _segment->getNet();
if (realNet->isSupply() or realNet->isClock())
return _blockageNet;
return Session::getBlockageNet();
return realNet;
}

View File

@ -71,8 +71,7 @@ namespace Katana {
virtual string _getTypeName () const;
protected:
// Attributes.
static Net* _blockageNet;
Segment* _segment;
Segment* _segment;
protected:
// Constructors & Destructors.
TrackFixedSegment ( Track*, Segment* ) ;