Redesigning access to analog terminals in devices.

* New: In Anabatic::AutoContact, added forceOnGrid() method to allow
    a AutoContactTerminal to be set (and fixed) outside it's constraint
    Box. Be aware that this may generate gaps in the routing.
      Stored using the UserNativeConstraints mechanism.
* New: In Anabatic::Session() new method getNearestgridpoint() to
    easily compute the nearest grid point from a position.
* Change: In Anabatic::AutoSegment::_revalidate(), use layer mask to
    compute the spin of the segment instead of the layers (more robust
    for analogic).
* New: In ::GCellTopology::doRp_Access() new method to create terminal
    contacts in _doDevice(). Issue more warnings and force the terminal
    to on grid (even if it create gaps). This a temporary hack.
This commit is contained in:
Jean-Paul Chaput 2016-10-05 23:43:07 +02:00
parent 47c9961ef3
commit dc46340d6a
8 changed files with 127 additions and 195 deletions

View File

@ -385,6 +385,16 @@ namespace Anabatic {
}
void AutoContact::forceOnGrid ( Point )
{
cerr << Warning( "AutoContact::forcedOnGrid() not implemented for this derived class.\n"
" %s\n"
, getString(this).c_str()
) << endl;
}
bool AutoContact::isTee ( unsigned int direction ) const
{
return (isHTee() and (direction & Flags::Horizontal))

View File

@ -145,6 +145,12 @@ namespace Anabatic {
{
cdebug_log(145,1) << "AutoContactTerminal::getNativeConstraintBox()" << endl;
if (isUserNativeConstraints()) {
cdebug_log(145,1) << " Native constraints sets by user:" << getConstraintBox() << endl;
cdebug_tabw(145,-1);
return getConstraintBox();
}
Component* component = getAnchor();
if (component == NULL) {
cerr << Error( "%s is not anchored.", getString(this).c_str() ) << endl;
@ -224,7 +230,8 @@ namespace Anabatic {
order( xMin, xMax );
order( yMin, yMax );
cdebug_log(145,0) << "| Using (y): " << DbU::getValueString(yMin) << " "
cdebug_log(145,0) << "| Using (y): "
<< DbU::getValueString(yMin) << " "
<< DbU::getValueString(yMax) << endl;
cdebug_tabw(145,-1);
@ -405,6 +412,13 @@ namespace Anabatic {
}
void AutoContactTerminal::forceOnGrid ( Point gridPoint )
{
setFlags( CntUserNativeConstraints );
setConstraintBox( Box(gridPoint) );
}
string AutoContactTerminal::_getTypeName () const
{ return "ContactTerminal"; }

View File

@ -472,7 +472,7 @@ namespace Anabatic {
cdebug_log(149,0) << "Changed source: " << source << endl;
unsetFlags( SegSourceTop|SegSourceBottom );
if (contactLayer != segmentLayer)
if (contactLayer->getMask() != segmentLayer->getMask())
setFlags( (segmentLayer == contactLayer->getTop()) ? SegSourceBottom : SegSourceTop );
if (source->isTurn() and source->getPerpandicular(this)->isReduced())
incReduceds();
@ -485,7 +485,7 @@ namespace Anabatic {
cdebug_log(149,0) << "Changed target: " << target << endl;
unsetFlags( SegTargetTop|SegTargetBottom );
if (contactLayer != segmentLayer)
if (contactLayer->getMask() != segmentLayer->getMask())
setFlags( (segmentLayer == contactLayer->getTop()) ? SegTargetBottom : SegTargetTop );
if (target->isTurn() and target->getPerpandicular(this)->isReduced())
incReduceds();
@ -1971,11 +1971,11 @@ namespace Anabatic {
state += isReduced () ? "r": "-";
state += isInvalidated () ? "i": "-";
if (_flags & SegSourceTop) state += 'T';
else if (_flags & SegSourceBottom) state += 'B';
if (_flags & SegSourceTop) state += 't';
else if (_flags & SegSourceBottom) state += 'b';
else state += '-';
if (_flags & SegTargetTop) state += 'T';
else if (_flags & SegTargetBottom) state += 'B';
if (_flags & SegTargetTop) state += 't';
else if (_flags & SegTargetBottom) state += 'b';
else state += '-';
return state;

View File

@ -697,6 +697,7 @@ namespace {
static void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, unsigned int flags );
static AutoContact* doRp_Access ( GCell*, Component*, unsigned int flags );
static AutoContact* doRp_AccessPad ( RoutingPad*, unsigned int flags );
static AutoContact* doRp_AccessAnalog ( GCell*, RoutingPad*, unsigned int flags );
static void doRp_StairCaseH ( GCell*, Component* rp1, Component* rp2 );
static void doRp_StairCaseV ( GCell*, Component* rp1, Component* rp2 );
private:
@ -1448,6 +1449,42 @@ namespace {
}
AutoContact* GCellTopology::doRp_AccessAnalog ( GCell* gcell, RoutingPad* rp, unsigned int flags )
{
cdebug_log(145,1) << "doRp_AccessAnalog()" << endl;
cdebug_log(145,0) << rp << endl;
const Layer* rpLayer = rp->getLayer();
size_t rpDepth = Session::getLayerDepth( rpLayer );
DbU::Unit viaSide = Session::getWireWidth ( rpDepth );
Point position = rp->getCenter();
Point onGrid = Session::getNearestGridPoint( position, gcell->getConstraintBox() );
AutoContact* contact = AutoContactTerminal::create( gcell, rp, rpLayer, position, viaSide, viaSide );
if (position != onGrid) {
cerr << Bug( "GCellTopology::doRp_AccessAnalog(): RoutingPad is not under any grid point.\n"
" %s\n"
" Using nearest grid point: %s"
, getString(rp).c_str()
, getString(onGrid).c_str()
) << endl;
contact->forceOnGrid( onGrid );
}
if (rpDepth != 1) {
cerr << Bug( "GCellTopology::doRp_AccessAnalog(): RoutingPad must be in METAL2 layer.\n"
" %s"
, getString(rp).c_str()
) << endl;
}
cdebug_log(145,0) << contact << endl;
cdebug_tabw(145,-1);
return contact;
}
void GCellTopology::doRp_StairCaseH ( GCell* gcell, Component* rp1, Component* rp2 )
{
cdebug_log(145,0) << "doRp_StairCaseH()" << endl;
@ -2157,6 +2194,7 @@ namespace {
);
}
bool isHorizontal ( RoutingPad* rp )
{
return ( (rp->getSourcePosition().getY() == rp->getTargetPosition().getY())
@ -2164,8 +2202,9 @@ namespace {
);
}
RoutingPad* returnSW ( GCell* gcell, RoutingPad* rp1, RoutingPad* rp2 ){
RoutingPad* returnSW ( GCell* gcell, RoutingPad* rp1, RoutingPad* rp2 )
{
DbU::Unit c1SW = (rp1->getSourcePosition().getX() - gcell->getXMin()) + (rp1->getSourcePosition().getY() - gcell->getYMin());
DbU::Unit c2SW = (rp2->getSourcePosition().getX() - gcell->getXMin()) + (rp2->getSourcePosition().getY() - gcell->getYMin());
@ -2176,8 +2215,9 @@ namespace {
}
}
RoutingPad* returnNE ( GCell* gcell, RoutingPad* rp1, RoutingPad* rp2 ){
RoutingPad* returnNE ( GCell* gcell, RoutingPad* rp1, RoutingPad* rp2 )
{
DbU::Unit c1NE = (gcell->getXMax() - rp1->getTargetPosition().getX()) + (gcell->getYMax() - rp1->getTargetPosition().getY());
DbU::Unit c2NE = (gcell->getXMax() - rp2->getTargetPosition().getX()) + (gcell->getYMax() - rp2->getTargetPosition().getY());
@ -2189,31 +2229,6 @@ namespace {
}
AutoContact* doRp_AC ( GCell* gcell , RoutingPad* rp, bool isSW, bool singleSeg = false )
{
const Layer* rpLayer = rp->getLayer();
size_t rpDepth = Session::getLayerDepth( rpLayer );
DbU::Unit viaSide = Session::getWireWidth ( rpDepth );
Point position;
if (singleSeg == false){
if (isSW) position = rp->getSourcePosition();
else position = rp->getTargetPosition();
} else {
position = Point ( abs(rp->getSourcePosition().getX() + rp->getTargetPosition().getX())/2
, abs(rp->getSourcePosition().getY() + rp->getTargetPosition().getY())/2
);
}
return AutoContactTerminal::create( gcell
, rp
, rpLayer
, position
, viaSide, viaSide
);
}
AutoContact* GCellTopology::_doDevice ( ForkStack& forks )
{
cdebug_log(145,1) << "void GCellTopology::_doDevice ()" << _gcell << endl;
@ -2272,69 +2287,25 @@ namespace {
if ((rpNE != NULL) && (rpSW != NULL)){
if (_east){
cdebug_log(145,0) << "East" << endl;
const Layer* rpLayer = rpNE->getLayer();
size_t rpDepth = Session::getLayerDepth( rpLayer );
DbU::Unit viaSide = Session::getWireWidth ( rpDepth );
Point position;
position = Point ( abs(rpNE->getSourcePosition().getX() + rpNE->getTargetPosition().getX())/2
, abs(rpNE->getSourcePosition().getY() + rpNE->getTargetPosition().getY())/2
);
AutoContact* ac = AutoContactTerminal::create( _gcell, rpNE, rpLayer, position
, viaSide, viaSide
);
cdebug_log(145,0) << "[Create AutoContact]: " << ac << endl;
AutoContact* ac = doRp_AccessAnalog( _gcell, rpNE, NoFlags );
if ( _fromHook != _east) forks.push( getSegmentOppositeHook( _east ), ac );
else targetContact = ac;
}
if (_west){
cdebug_log(145,0) << "West" << endl;
const Layer* rpLayer = rpSW->getLayer();
size_t rpDepth = Session::getLayerDepth( rpLayer );
DbU::Unit viaSide = Session::getWireWidth ( rpDepth );
Point position;
position = Point ( abs(rpSW->getSourcePosition().getX() + rpSW->getTargetPosition().getX())/2
, abs(rpSW->getSourcePosition().getY() + rpSW->getTargetPosition().getY())/2
);
AutoContact* ac = AutoContactTerminal::create( _gcell, rpSW, rpLayer, position
, viaSide, viaSide
);
cdebug_log(145,0) << "[Create AutoContact]: " << ac << endl;
AutoContact* ac = doRp_AccessAnalog( _gcell, rpSW, NoFlags );
if ( _fromHook != _west) forks.push( getSegmentOppositeHook( _west ), ac );
else targetContact = ac;
}
if (_south){
cdebug_log(145,0) << "South" << endl;
const Layer* rpLayer = rpSW->getLayer();
size_t rpDepth = Session::getLayerDepth( rpLayer );
DbU::Unit viaSide = Session::getWireWidth ( rpDepth );
Point position;
position = Point ( abs(rpSW->getSourcePosition().getX() + rpSW->getTargetPosition().getX())/2
, abs(rpSW->getSourcePosition().getY() + rpSW->getTargetPosition().getY())/2
);
AutoContact* ac = AutoContactTerminal::create( _gcell, rpSW, rpLayer, position
, viaSide, viaSide
);
cdebug_log(145,0) << "[Create AutoContact]: " << ac << endl;
AutoContact* ac = doRp_AccessAnalog( _gcell, rpSW, NoFlags );
if ( _fromHook != _south) forks.push( getSegmentOppositeHook( _south ), ac );
else targetContact = ac;
}
if (_north){
cdebug_log(145,0) << "North" << endl;
const Layer* rpLayer = rpNE->getLayer();
size_t rpDepth = Session::getLayerDepth( rpLayer );
DbU::Unit viaSide = Session::getWireWidth ( rpDepth );
Point position;
position = Point ( abs(rpNE->getSourcePosition().getX() + rpNE->getTargetPosition().getX())/2
, abs(rpNE->getSourcePosition().getY() + rpNE->getTargetPosition().getY())/2
);
AutoContact* ac = AutoContactTerminal::create( _gcell, rpNE, rpLayer, position
, viaSide, viaSide
);
cdebug_log(145,0) << "[Create AutoContact]: " << ac << endl;
AutoContact* ac = doRp_AccessAnalog( _gcell, rpNE, NoFlags );
if ( _fromHook != _north) forks.push( getSegmentOppositeHook( _north ), ac );
else targetContact = ac;
}
@ -2343,104 +2314,6 @@ namespace {
cdebug_tabw(145,-1);
return targetContact;
}
/*
AutoContact* GCellTopology::_doDevice ( ForkStack& forks )
{
cdebug_log(145,1) << "void GCellTopology::_doDevice ()" << _gcell << endl;
// #0: Check if all RoutingPads are set to a component.
for ( unsigned int i=0; i<_routingPads.size() ; i++ ) {
if ( ( _routingPads[i]->getSourcePosition().getX() == _routingPads[i]->getTargetPosition().getX() )
&&( _routingPads[i]->getSourcePosition().getY() == _routingPads[i]->getTargetPosition().getY() )
){
throw Error( "GCellTopology::_doDevice() Some RoutingPads are not set to a component.\n"
" On: %s."
, getString(_gcell).c_str()
);
}
}
cdebug_log(145,0) << "_routingPads.size(): " << _routingPads.size() << endl;
if ( _routingPads.size() > 1 ){
// #1: Find RoutingPads to use for AutoContacts NE+SW
RoutingPad* rpNE = _routingPads[0];
RoutingPad* rpSW = _routingPads[0];
for ( unsigned int i=1 ; i<_routingPads.size() ; i++ ) {
rpNE = returnNE( _gcell, rpNE, _routingPads[i] );
rpSW = returnSW( _gcell, rpSW, _routingPads[i] );
}
cdebug_log(145,0) << "rpNE: " << rpNE << endl;
cdebug_log(145,0) << "rpSW: " << rpSW << endl;
// #2: Check if 1 or 2 AutoContacts is necessary.
bool ne = false;
bool sw = false;
if ( (!_north) || (!_east) ){
_northEastContact = doRp_AC ( _gcell , rpSW, true );
ne = true;
}
if ( (!_south) || (!_west) ){
_southWestContact = doRp_AC ( _gcell , rpNE, false );
sw = true;
}
if ( ne == false ) _northEastContact = _southWestContact;
if ( sw == false ) _southWestContact = _northEastContact;
cdebug_log(145,0) << "AutoContact NE: " << _northEastContact << endl;
cdebug_log(145,0) << "AutoContact SW: " << _southWestContact << endl;
} else if (_routingPads.size() == 0){
cdebug_log(145,0) << "Pas de RoutingPad trouvé." << endl;
} else {
// #1: Find RoutingPads to use for AutoContacts NE+SW
// Only 1 RoutingPads => 1 Component
cdebug_log(145,0) << "rp: " << _routingPads[0] << endl;
// #2: Check if 1 or 2 AutoContacts is necessary.
bool ne = false;
bool sw = false;
if ( (_north) || (_east) ){
_northEastContact = doRp_AC ( _gcell , _routingPads[0], true );
ne = true;
}
if ( (_south) || (_west) ){
_southWestContact = doRp_AC ( _gcell , _routingPads[0], false );
sw = true;
}
if ( ne == false ) _northEastContact = _southWestContact;
if ( sw == false ) _southWestContact = _northEastContact;
cdebug_log(145,0) << "AutoContact NE: " << _northEastContact << endl;
cdebug_log(145,0) << "AutoContact SW: " << _southWestContact << endl;
}
AutoContact* targetContact = NULL;
if (_sourceContact){
targetContact = ( getSegmentHookType(_fromHook) & (NorthBound|EastBound) )
? _northEastContact : _southWestContact ;
}
cdebug_log(145,0) << "fromHook: " << _fromHook << endl;
cdebug_log(145,0) << "North : " << _north << endl;
cdebug_log(145,0) << "East : " << _east << endl;
cdebug_log(145,0) << "South : " << _south << endl;
cdebug_log(145,0) << "West : " << _west << endl;
if ( _east and (_fromHook != _east) ) {
forks.push( getSegmentOppositeHook( _east ), _northEastContact );
}
if ( _west and (_fromHook != _west) ) {
forks.push( getSegmentOppositeHook( _west ), _southWestContact );
}
if ( _north and (_fromHook != _north) ) {
forks.push( getSegmentOppositeHook( _north ), _northEastContact );
}
if ( _south and (_fromHook != _south) ) {
forks.push( getSegmentOppositeHook( _south ), _southWestContact );
}
cdebug_log(145,0) << "doDevice done" << endl;
cdebug_tabw(145,-1);
return targetContact;
}*/
AutoContact* GCellTopology::_doHChannel ( ForkStack& forks )

View File

@ -22,6 +22,7 @@
#include "hurricane/Cell.h"
#include "hurricane/UpdateSession.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/RoutingLayerGauge.h"
#include "anabatic/Configuration.h"
#include "anabatic/Session.h"
#include "anabatic/AutoContact.h"
@ -51,6 +52,7 @@ namespace Anabatic {
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::Cell;
using CRL::RoutingLayerGauge;
// -------------------------------------------------------------------
@ -336,6 +338,32 @@ namespace Anabatic {
}
Point Session::_getNearestGridPoint ( Point p, Box constraint )
{
Box ab = _anabatic->getCell()->getAbutmentBox();
RoutingLayerGauge* lg = _routingGauge->getLayerGauge( 1 );
DbU::Unit x = lg->getTrackPosition( ab.getXMin()
, lg->getTrackIndex( ab.getXMin()
, ab.getXMax()
, p.getX()
, Constant::Nearest ) );
if (x < constraint.getXMin()) x += lg->getPitch();
if (x > constraint.getXMax()) x -= lg->getPitch();
lg = _routingGauge->getLayerGauge( 2 );
DbU::Unit y = lg->getTrackPosition( ab.getYMin()
, lg->getTrackIndex( ab.getYMin()
, ab.getYMax()
, p.getY()
, Constant::Nearest ) );
if (y < constraint.getYMin()) y += lg->getPitch();
if (y > constraint.getYMax()) y -= lg->getPitch();
return Point(x,y);
}
bool Session::isInDemoMode ()
{ return get("isInDemoMode()")->_anabatic->isInDemoMode(); }

View File

@ -52,18 +52,18 @@ namespace Anabatic {
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContact".
enum AutoContactFlag { CntFixed = 0x00000001
, CntTerminal = 0x00000002
, CntTurn = 0x00000004
, CntHTee = 0x00000008
, CntVTee = 0x00000010
, CntInvalidated = 0x00000020
, CntInvalidatedCache = 0x00000040
, CntInCreationStage = 0x00000080
, CntBadTopology = 0x00000100
, CntIgnoreAnchor = 0x00000200
, CntWeakTerminal = 0x00000400
, CntUserNativeConstraints = 0x00000800
enum AutoContactFlag { CntFixed = (1 << 0)
, CntTerminal = (1 << 1)
, CntTurn = (1 << 2)
, CntHTee = (1 << 3)
, CntVTee = (1 << 4)
, CntInvalidated = (1 << 6)
, CntInvalidatedCache = (1 << 7)
, CntInCreationStage = (1 << 8)
, CntBadTopology = (1 << 9)
, CntIgnoreAnchor = (1 << 10)
, CntWeakTerminal = (1 << 11)
, CntUserNativeConstraints = (1 << 12)
};
class AutoContact {
@ -149,6 +149,7 @@ namespace Anabatic {
virtual void updateTopology () = 0;
void showTopologyError ( const std::string&, unsigned int flags=0 );
virtual void checkTopology ();
virtual void forceOnGrid ( Point );
inline void setFlags ( unsigned int );
inline void unsetFlags ( unsigned int );
void setGCell ( GCell* );

View File

@ -59,6 +59,7 @@ namespace Anabatic {
virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const;
virtual void updateGeometry ();
virtual void updateTopology ();
virtual void forceOnGrid ( Point );
virtual void cacheDetach ( AutoSegment* );
virtual void cacheAttach ( AutoSegment* );
virtual void updateCache ();

View File

@ -23,7 +23,7 @@
#include <map>
#include <boost/function.hpp>
#include "hurricane/Commons.h"
#include "hurricane/DbU.h"
#include "hurricane/Box.h"
#include "crlcore/CellGauge.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/Constants.h"
@ -53,6 +53,8 @@ namespace Anabatic {
using Hurricane::Layer;
using Hurricane::Technology;
using Hurricane::DbU;
using Hurricane::Point;
using Hurricane::Box;
using Hurricane::Net;
using Hurricane::Contact;
using Hurricane::Segment;
@ -103,6 +105,7 @@ namespace Anabatic {
static inline DbU::Unit getWireWidth ( const Layer* );
static inline DbU::Unit getViaWidth ( const Layer* );
static inline DbU::Unit getExtensionCap ( const Layer* );
static inline Point getNearestGridPoint ( Point, Box constraints );
static inline size_t getSegmentStackSize ();
static inline size_t getContactStackSize ();
static inline const vector<AutoSegment*>& getInvalidateds ();
@ -143,6 +146,7 @@ namespace Anabatic {
void _revalidateTopology ();
virtual size_t _revalidate ();
DbU::Unit _getPitch ( size_t depth, unsigned int flags ) const;
Point _getNearestGridPoint ( Point, Box constraints );
Record* _getRecord () const;
string _getString () const;
inline string _getTypeName () const;
@ -218,6 +222,7 @@ namespace Anabatic {
inline DbU::Unit Session::getViaWidth ( const Layer* layer ) { return getViaWidth ( getViaDepth(layer) ); }
inline DbU::Unit Session::getExtensionCap ( const Layer* layer ) { return getConfiguration()->getExtensionCap(layer); }
inline unsigned int Session::getDirection ( const Layer* layer ) { return getDirection( getLayerDepth(layer) ); }
inline Point Session::getNearestGridPoint ( Point p, Box b ) { return get("getNearestGridPoint()")->_getNearestGridPoint(p,b); }
inline void Session::_dogleg ( AutoSegment* segment ) { _doglegs.push_back(segment); }
inline void Session::_doglegReset () { _doglegs.clear(); }