Added support for external connectors in GDS parser/driver.

* New: In CRL::GdsDriver, create TEXT record under each external
    Net component. Seems to be the aknoweledged way to signal
    external pins.
* New: In CRL::GdsParser, read TEXT record and create Net and
    external components that are in the same layer and at the
    same position.
This commit is contained in:
Jean-Paul Chaput 2020-12-19 23:04:50 +01:00
parent 8fdaf47f3d
commit ead11f8b93
2 changed files with 470 additions and 113 deletions

View File

@ -16,6 +16,7 @@
#include <ctime> #include <ctime>
#include <cmath> #include <cmath>
#include <cstdio>
#include <cfenv> #include <cfenv>
#include <string> #include <string>
#include <sstream> #include <sstream>
@ -36,6 +37,7 @@ using namespace std;
#include "hurricane/Polygon.h" #include "hurricane/Polygon.h"
#include "hurricane/Pad.h" #include "hurricane/Pad.h"
#include "hurricane/Net.h" #include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/Cell.h" #include "hurricane/Cell.h"
#include "hurricane/Plug.h" #include "hurricane/Plug.h"
#include "hurricane/Instance.h" #include "hurricane/Instance.h"
@ -262,7 +264,7 @@ namespace {
//static const uint16_t PATH = 0x0900 | NoData; //static const uint16_t PATH = 0x0900 | NoData;
static const uint16_t SREF = 0x0a00 | NoData; static const uint16_t SREF = 0x0a00 | NoData;
//static const uint16_t AREF = 0x0b00 | NoData; //static const uint16_t AREF = 0x0b00 | NoData;
//static const uint16_t TEXT = 0x0c00 | NoData; static const uint16_t TEXT = 0x0c00 | NoData;
static const uint16_t LAYER = 0x0d00 | TwoByteInteger; static const uint16_t LAYER = 0x0d00 | TwoByteInteger;
static const uint16_t DATATYPE = 0x0e00 | TwoByteInteger; static const uint16_t DATATYPE = 0x0e00 | TwoByteInteger;
//static const uint16_t WIDTH = 0x0f00 | FourByteInteger; //static const uint16_t WIDTH = 0x0f00 | FourByteInteger;
@ -272,10 +274,10 @@ namespace {
//static const uint16_t COLROW = 0x1300 | TwoByteInteger; //static const uint16_t COLROW = 0x1300 | TwoByteInteger;
//static const uint16_t TEXTNODE = 0x1400 | NoData; // Unused. //static const uint16_t TEXTNODE = 0x1400 | NoData; // Unused.
//static const uint16_t NODE = 0x1500 | NoData; //static const uint16_t NODE = 0x1500 | NoData;
//static const uint16_t TEXTTYPE = 0x1600 | TwoByteInteger; static const uint16_t TEXTTYPE = 0x1600 | TwoByteInteger;
//static const uint16_t PRESENTATION = 0x1700 | BitArray; static const uint16_t PRESENTATION = 0x1700 | BitArray;
//static const uint16_t SPACING = 0x1800 | NoData; // Discontinued. //static const uint16_t SPACING = 0x1800 | NoData; // Discontinued.
//static const uint16_t STRING = 0x1900 | String; static const uint16_t STRING = 0x1900 | String;
static const uint16_t STRANS = 0x1a00 | BitArray; static const uint16_t STRANS = 0x1a00 | BitArray;
//static const uint16_t MAG = 0x1b00 | EightByteReal; //static const uint16_t MAG = 0x1b00 | EightByteReal;
static const uint16_t ANGLE = 0x1c00 | EightByteReal; static const uint16_t ANGLE = 0x1c00 | EightByteReal;
@ -428,13 +430,27 @@ namespace {
void GdsRecord::toStream ( ostream& stream ) const void GdsRecord::toStream ( ostream& stream ) const
{ {
static size_t count = 0;
uint16_t length = (uint16_t)( _bytes.size()+2 ); uint16_t length = (uint16_t)( _bytes.size()+2 );
const unsigned char* bytearray = reinterpret_cast<const unsigned char*>( &length ); const unsigned char* bytearray = reinterpret_cast<const unsigned char*>( &length );
// char buffer[512];
// sprintf( buffer, "0x%02x", bytearray[1] );
// cerr << setw(6) << hex << count++ << " | " << buffer << endl;
// sprintf( buffer, "0x%02x", bytearray[0] );
// cerr << setw(6) << hex << count++ << " | " << buffer << endl;
// Little endian (x86). // Little endian (x86).
stream.put( bytearray[1] ); stream.put( bytearray[1] );
stream.put( bytearray[0] ); stream.put( bytearray[0] );
for ( char byte : _bytes ) stream.put( byte ); for ( unsigned char byte : _bytes ) {
uint32_t b = byte;
// sprintf( buffer, "0x%02x", b );
// cerr << setw(6) << hex << count++ << " | " << buffer << endl;
stream.put( byte );
}
} }
@ -452,25 +468,31 @@ namespace {
static const GdsRecord ENDEL; static const GdsRecord ENDEL;
static const GdsRecord ENDSTR; static const GdsRecord ENDSTR;
static const GdsRecord SREF; static const GdsRecord SREF;
static const GdsRecord TEXT;
public: public:
GdsStream ( string filename ); GdsStream ( string filename );
~GdsStream (); ~GdsStream ();
inline int32_t toGdsDbu ( DbU::Unit ) const; inline int32_t toGdsDbu ( DbU::Unit ) const;
static inline GdsRecord PROPATTR ( int16_t ); static inline GdsRecord PROPATTR ( int16_t );
static inline GdsRecord DATATYPE ( int16_t ); static inline GdsRecord DATATYPE ( int16_t );
static inline GdsRecord PROPVALUE ( string ); static inline GdsRecord TEXTTYPE ( int16_t );
static inline GdsRecord STRNAME ( string ); static inline GdsRecord LAYER ( int16_t );
static inline GdsRecord STRNAME ( const Name& ); static inline GdsRecord PRESENTATION ( int16_t );
static inline GdsRecord LIBNAME ( string ); static inline GdsRecord PROPVALUE ( string );
static inline GdsRecord SNAME ( string ); static inline GdsRecord STRNAME ( string );
static inline GdsRecord SNAME ( const Name& ); static inline GdsRecord STRNAME ( const Name& );
GdsStream& operator<< ( const GdsRecord& ); static inline GdsRecord LIBNAME ( string );
GdsStream& operator<< ( const BasicLayer* ); static inline GdsRecord SNAME ( string );
GdsStream& operator<< ( const Box& ); static inline GdsRecord SNAME ( const Name& );
GdsStream& operator<< ( const Points ); static inline GdsRecord STRING ( const Name& );
GdsStream& operator<< ( const vector<Point>& points ); static inline GdsRecord STRING ( const string );
GdsStream& operator<< ( const Cell* ); GdsStream& operator<< ( const GdsRecord& );
GdsStream& operator<< ( const Transformation& ); GdsStream& operator<< ( const Box& );
GdsStream& operator<< ( const Points );
GdsStream& operator<< ( const Point& point );
GdsStream& operator<< ( const vector<Point>& points );
GdsStream& operator<< ( const Cell* );
GdsStream& operator<< ( const Transformation& );
private: private:
ofstream _ostream; ofstream _ostream;
double _dbuPerUu; double _dbuPerUu;
@ -483,16 +505,22 @@ namespace {
const GdsRecord GdsStream::ENDEL = GdsRecord(GdsRecord::ENDEL); const GdsRecord GdsStream::ENDEL = GdsRecord(GdsRecord::ENDEL);
const GdsRecord GdsStream::ENDSTR = GdsRecord(GdsRecord::ENDSTR); const GdsRecord GdsStream::ENDSTR = GdsRecord(GdsRecord::ENDSTR);
const GdsRecord GdsStream::SREF = GdsRecord(GdsRecord::SREF); const GdsRecord GdsStream::SREF = GdsRecord(GdsRecord::SREF);
const GdsRecord GdsStream::TEXT = GdsRecord(GdsRecord::TEXT);
inline GdsRecord GdsStream::PROPATTR ( int16_t v ) { return GdsRecord(GdsRecord::PROPATTR,v); } inline GdsRecord GdsStream::PROPATTR ( int16_t v ) { return GdsRecord(GdsRecord::PROPATTR,v); }
inline GdsRecord GdsStream::DATATYPE ( int16_t v ) { return GdsRecord(GdsRecord::DATATYPE,v); } inline GdsRecord GdsStream::DATATYPE ( int16_t v ) { return GdsRecord(GdsRecord::DATATYPE,v); }
inline GdsRecord GdsStream::PROPVALUE ( string s ) { return GdsRecord(GdsRecord::PROPVALUE,s); } inline GdsRecord GdsStream::TEXTTYPE ( int16_t v ) { return GdsRecord(GdsRecord::TEXTTYPE,v); }
inline GdsRecord GdsStream::STRNAME ( string s ) { return GdsRecord(GdsRecord::STRNAME,s); } inline GdsRecord GdsStream::LAYER ( int16_t v ) { return GdsRecord(GdsRecord::LAYER,v); }
inline GdsRecord GdsStream::STRNAME ( const Name& n ) { return GdsRecord(GdsRecord::STRNAME,getString(n)); } inline GdsRecord GdsStream::PRESENTATION ( int16_t v ) { return GdsRecord(GdsRecord::PRESENTATION,v); }
inline GdsRecord GdsStream::LIBNAME ( string s ) { return GdsRecord(GdsRecord::LIBNAME,s); } inline GdsRecord GdsStream::PROPVALUE ( string s ) { return GdsRecord(GdsRecord::PROPVALUE,s); }
inline GdsRecord GdsStream::SNAME ( string s ) { return GdsRecord(GdsRecord::SNAME,s); } inline GdsRecord GdsStream::STRNAME ( string s ) { return GdsRecord(GdsRecord::STRNAME,s); }
inline GdsRecord GdsStream::SNAME ( const Name& n ) { return GdsRecord(GdsRecord::SNAME,getString(n)); } inline GdsRecord GdsStream::STRNAME ( const Name& n ) { return GdsRecord(GdsRecord::STRNAME,getString(n)); }
inline int32_t GdsStream::toGdsDbu ( DbU::Unit v ) const inline GdsRecord GdsStream::LIBNAME ( string s ) { return GdsRecord(GdsRecord::LIBNAME,s); }
inline GdsRecord GdsStream::SNAME ( string s ) { return GdsRecord(GdsRecord::SNAME,s); }
inline GdsRecord GdsStream::SNAME ( const Name& n ) { return GdsRecord(GdsRecord::SNAME,getString(n)); }
inline GdsRecord GdsStream::STRING ( const Name& n ) { return GdsRecord(GdsRecord::STRING,getString(n)); }
inline GdsRecord GdsStream::STRING ( const string s ) { return GdsRecord(GdsRecord::STRING,s); }
inline int32_t GdsStream::toGdsDbu ( DbU::Unit v ) const
{ return uint32_t( std::lrint( DbU::toPhysical( v, DbU::UnitPower::Unity ) / _metricDbU )); } { return uint32_t( std::lrint( DbU::toPhysical( v, DbU::UnitPower::Unity ) / _metricDbU )); }
@ -502,7 +530,7 @@ namespace {
, _metricDbU(Cfg::getParamDouble("gdsDriver.metricDbu",10e-9)->asDouble()) // 1um. , _metricDbU(Cfg::getParamDouble("gdsDriver.metricDbu",10e-9)->asDouble()) // 1um.
{ {
std::fesetround( FE_TONEAREST ); std::fesetround( FE_TONEAREST );
_ostream.open( filename, ios_base::out ); _ostream.open( filename, ios_base::out|ios_base::binary );
GdsRecord record ( GdsRecord::HEADER ); GdsRecord record ( GdsRecord::HEADER );
record.push( (uint16_t)600 ); record.push( (uint16_t)600 );
@ -552,18 +580,22 @@ namespace {
{ _ostream << record; return *this; } { _ostream << record; return *this; }
#if 0
GdsStream& GdsStream::operator<< ( const BasicLayer* layer ) GdsStream& GdsStream::operator<< ( const BasicLayer* layer )
{ {
cdebug_log(101,0) << "LAYER" << endl;
GdsRecord record ( GdsRecord::LAYER ); GdsRecord record ( GdsRecord::LAYER );
record.push( (int16_t)layer->getGds2Layer() ); record.push( (int16_t)layer->getGds2Layer() );
_ostream << record; _ostream << record;
cdebug_log(101,0) << "DATATYPE" << endl;
record = GdsRecord( GdsRecord::DATATYPE ); record = GdsRecord( GdsRecord::DATATYPE );
record.push( (int16_t)layer->getGds2Datatype() ); record.push( (int16_t)layer->getGds2Datatype() );
_ostream << record; _ostream << record;
return *this; return *this;
} }
#endif
GdsStream& GdsStream::operator<< ( const Transformation& transf ) GdsStream& GdsStream::operator<< ( const Transformation& transf )
@ -657,6 +689,16 @@ namespace {
} }
GdsStream& GdsStream::operator<< ( const Point& point )
{
GdsRecord record ( GdsRecord::XY );
record.push( (int32_t)toGdsDbu(point.getX()) );
record.push( (int32_t)toGdsDbu(point.getY()) );
_ostream << record;
return *this;
}
GdsStream& GdsStream::operator<< ( const vector<Point>& points ) GdsStream& GdsStream::operator<< ( const vector<Point>& points )
{ {
GdsRecord record ( GdsRecord::XY ); GdsRecord record ( GdsRecord::XY );
@ -720,7 +762,8 @@ namespace {
for ( const vector<Point>& subpolygon : subpolygons ) { for ( const vector<Point>& subpolygon : subpolygons ) {
for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) { for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) {
(*this) << BOUNDARY; (*this) << BOUNDARY;
(*this) << layer; (*this) << LAYER(layer->getGds2Layer());
(*this) << DATATYPE(layer->getGds2Datatype());
(*this) << subpolygon; (*this) << subpolygon;
(*this) << ENDEL; (*this) << ENDEL;
} }
@ -730,7 +773,8 @@ namespace {
if (rectilinear) { if (rectilinear) {
for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) { for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) {
(*this) << BOUNDARY; (*this) << BOUNDARY;
(*this) << layer; (*this) << LAYER(layer->getGds2Layer());
(*this) << DATATYPE(layer->getGds2Datatype());
(*this) << rectilinear->getPoints(); (*this) << rectilinear->getPoints();
(*this) << ENDEL; (*this) << ENDEL;
isOnGrid( component, rectilinear->getPoints() ); isOnGrid( component, rectilinear->getPoints() );
@ -740,7 +784,8 @@ namespace {
if (diagonal) { if (diagonal) {
for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) { for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) {
(*this) << BOUNDARY; (*this) << BOUNDARY;
(*this) << layer; (*this) << LAYER(layer->getGds2Layer());
(*this) << DATATYPE(layer->getGds2Datatype());
(*this) << diagonal->getContour(); (*this) << diagonal->getContour();
(*this) << ENDEL; (*this) << ENDEL;
} }
@ -753,10 +798,34 @@ namespace {
if ((bb.getWidth() == 0) or (bb.getHeight() == 0)) if ((bb.getWidth() == 0) or (bb.getHeight() == 0))
continue; continue;
(*this) << BOUNDARY; (*this) << BOUNDARY;
(*this) << layer; (*this) << LAYER(layer->getGds2Layer());
(*this) << DATATYPE(layer->getGds2Datatype());
(*this) << bb; (*this) << bb;
(*this) << ENDEL; (*this) << ENDEL;
isOnGrid( component, bb ); isOnGrid( component, bb );
if (NetExternalComponents::isExternal(component)) {
string name = getString( component->getNet()->getName() );
if (name.size() > 511) {
cerr << getString(
Warning( "GdsStream::operator<<(): Truncate Net name to 511 first characters,\n"
" on \"%s\"."
, name.c_str() )) << endl;
name.erase( 511 );
}
// PRESENTATION: 0b000101 means font:00, vpres:01 (center), hpres:01 (center)
cdebug_log(101,0) << "TEXT" << endl;
(*this) << TEXT;
(*this) << LAYER(layer->getGds2Layer());
cdebug_log(101,0) << "TEXTTYPE" << endl;
(*this) << TEXTTYPE( 0 );
cdebug_log(101,0) << "TEXTYPE end record" << endl;
(*this) << PRESENTATION( 5 );
(*this) << bb.getCenter();
(*this) << STRING( name );
(*this) << ENDEL;
cdebug_log(101,0) << "TEXT ENDEL" << endl;
}
} }
} }
} }

View File

@ -15,6 +15,7 @@
#include <ctime> #include <ctime>
#include <cstdio>
#include <string> #include <string>
#include <bitset> #include <bitset>
#include <sstream> #include <sstream>
@ -201,6 +202,8 @@ namespace {
void readString (); void readString ();
void readUnits (); void readUnits ();
void readLayer (); void readLayer ();
void readWidth ();
void readPathtype ();
void readStrname (); void readStrname ();
void readXy (); void readXy ();
static string toStrType ( uint16_t ); static string toStrType ( uint16_t );
@ -211,6 +214,7 @@ namespace {
double _readDouble (); double _readDouble ();
private: private:
istream* _stream; istream* _stream;
uint32_t _offset;
uint16_t _length; uint16_t _length;
uint16_t _count; uint16_t _count;
uint16_t _type; uint16_t _type;
@ -220,6 +224,7 @@ namespace {
vector<int16_t> _int16s; vector<int16_t> _int16s;
vector<int32_t> _int32s; vector<int32_t> _int32s;
vector<double> _doubles; vector<double> _doubles;
char _buffer[64];
}; };
@ -293,6 +298,7 @@ namespace {
GdsRecord::GdsRecord () GdsRecord::GdsRecord ()
: _stream (NULL) : _stream (NULL)
, _offset (0)
, _length (0) , _length (0)
, _count (0) , _count (0)
, _type (0) , _type (0)
@ -344,7 +350,7 @@ namespace {
case TEXT: readDummy( false ); break; case TEXT: readDummy( false ); break;
case LAYER: readLayer(); break; case LAYER: readLayer(); break;
case DATATYPE: readDummy( false ); break; case DATATYPE: readDummy( false ); break;
case WIDTH: readDummy( false ); break; case WIDTH: readWidth(); break;
case XY: readXy(); break; case XY: readXy(); break;
case ENDEL: readDummy( false ); break; case ENDEL: readDummy( false ); break;
case SNAME: readStrname(); break; case SNAME: readStrname(); break;
@ -360,7 +366,7 @@ namespace {
case ANGLE: _doubles.push_back( _readDouble() ); break; case ANGLE: _doubles.push_back( _readDouble() ); break;
case REFLIBS: readDummy( false ); break; case REFLIBS: readDummy( false ); break;
case FONTS: readDummy( false ); break; case FONTS: readDummy( false ); break;
case PATHTYPE: readDummy( false ); break; case PATHTYPE: readPathtype(); break;
case GENERATIONS: readDummy( false ); break; case GENERATIONS: readDummy( false ); break;
case ATTRTABLE: readDummy( false ); break; case ATTRTABLE: readDummy( false ); break;
case STYPTABLE: readDummy( false ); break; case STYPTABLE: readDummy( false ); break;
@ -389,7 +395,13 @@ namespace {
case LIBSECUR: readDummy( false ); break; case LIBSECUR: readDummy( false ); break;
} }
cerr << " GdsRecord::read() " << toStrType(_type) << endl; ostringstream s;
s << " (0x" << std::setfill('0') << std::setw(4) << std::hex << _type << ")";
cdebug_log(101,0) << "GdsRecord::read() " << toStrType(_type)
<< s.str()
<< " _bytes:" << _length
<< " (offset:" << (_offset-4) << ")"
<< endl;
} }
@ -417,9 +429,15 @@ namespace {
unsigned char bytes[ typeSize ]; unsigned char bytes[ typeSize ];
}; };
char bytes[typeSize]; unsigned char bytes[typeSize];
_stream->read( bytes, typeSize ); _stream->read( (char*)(&bytes[0]), typeSize );
_count += typeSize; _count += typeSize;
// cdebug_log(101,0) << "GdsRecord::_readInt() " << endl;
// for ( size_t i=0 ; i<typeSize ; ++i ) {
// sprintf( _buffer, "0x%02x", bytes[i] );
// cdebug(101,0) << setw(6) << hex << _offset++ << " | " << _buffer << endl;
// }
UType uvalue; UType uvalue;
// Little endian (x86). // Little endian (x86).
@ -440,6 +458,12 @@ namespace {
_stream->read( bytes, 8 ); _stream->read( bytes, 8 );
_count += 8; _count += 8;
// cdebug_log(101,0) << "GdsRecord::_readDouble() " << endl;
// for ( size_t i=0 ; i<8 ; ++i ) {
// sprintf( _buffer, "0x%02x", bytes[i] );
// cdebug(101,0) << setw(6) << hex << _offset++ << " | " << _buffer << endl;
// }
gdsUInt64 mantisse; gdsUInt64 mantisse;
for ( size_t i=0 ; i<7 ; ++i ) mantisse.bytes[i] = bytes[7-i]; for ( size_t i=0 ; i<7 ; ++i ) mantisse.bytes[i] = bytes[7-i];
mantisse.bytes[7] = 0; mantisse.bytes[7] = 0;
@ -456,31 +480,38 @@ namespace {
string GdsRecord::_readString () string GdsRecord::_readString ()
{ {
cdebug_log(101,0) << "GdsRecord::_readDouble() " << endl;
string s; string s;
char c; char c;
for ( ; _count<_length ; ++_count ) { for ( ; _count<_length ; ++_count ) {
_stream->get( c ); _stream->get( c );
// sprintf( _buffer, "0x%02x", c );
// cdebug_log(101,0) << setw(6) << hex << _offset++ << " | " << _buffer << endl;
if (c != (char)0) s.push_back(c); if (c != (char)0) s.push_back(c);
} }
cerr << "GdsRecord::_readString(): \"" << s << "\"" << endl; cdebug_log(101,0) << "GdsRecord::_readString(): \"" << s << "\"" << endl;
return s; return s;
} }
void GdsRecord::readDummy ( bool showError ) void GdsRecord::readDummy ( bool showError )
{ {
cdebug_log(101,0) << "GdsRecord::readDummy() " << endl;
char c; char c;
for ( ; _count<_length ; ++_count ) _stream->get( c ); for ( ; _count<_length ; ++_count ) {
_stream->get( c );
sprintf( _buffer, "0x%02x", c );
cdebug_log(101,0) << setw(6) << hex << _offset++ << " | " << _buffer << endl;
}
if (showError) { if (showError) {
cerr << Error( "GdsRecord type %s unsupported.", toStrType(_type).c_str() ) << endl; cdebug_log(101,0) << Error( "GdsRecord type %s unsupported.", toStrType(_type).c_str() ) << endl;
} }
} }
void GdsRecord::readStrans () void GdsRecord::readStrans ()
{ {
const uint16_t XRMask = 0x8000; const uint16_t XRMask = 0x8000;
uint16_t flags = _readInt<uint16_t>(); uint16_t flags = _readInt<uint16_t>();
_xReflection = (flags & XRMask); _xReflection = (flags & XRMask);
@ -508,6 +539,14 @@ namespace {
{ _int16s.push_back( _readInt<uint16_t>() ); } { _int16s.push_back( _readInt<uint16_t>() ); }
void GdsRecord::readWidth ()
{ _int32s.push_back( _readInt<uint32_t>() ); }
void GdsRecord::readPathtype ()
{ _int16s.push_back( _readInt<uint16_t>() ); }
void GdsRecord::readXy () void GdsRecord::readXy ()
{ while ( _count < _length ) _int32s.push_back( _readInt<int32_t>() ); } { while ( _count < _length ) _int32s.push_back( _readInt<int32_t>() ); }
@ -607,12 +646,15 @@ namespace {
bool readNode (); bool readNode ();
bool readBox (); bool readBox ();
bool readText (); bool readText ();
bool readTextbody (); bool readTextbody ( const Layer* );
bool readStrans (); bool readStrans ();
bool readProperty (); bool readProperty ();
void xyToComponent ( const Layer* ); void xyToComponent ( const Layer* );
void xyToPath ( uint16_t pathtype, const Layer*, DbU::Unit width );
void makeInstances (); void makeInstances ();
void makeExternals ();
Net* fusedNet (); Net* fusedNet ();
void addNetReference ( Net*, const Layer*, DbU::Unit x, DbU::Unit y );
private: private:
struct DelayedInstance { struct DelayedInstance {
inline DelayedInstance ( Cell* owner, string masterName, const Transformation& ); inline DelayedInstance ( Cell* owner, string masterName, const Transformation& );
@ -621,6 +663,12 @@ namespace {
string _masterName; string _masterName;
Transformation _transformation; Transformation _transformation;
}; };
private:
struct PinPoint {
inline PinPoint ( const Layer*, DbU::Unit x, DbU::Unit y );
const Layer* _layer;
Point _position;
};
private: private:
static vector<const Layer*> _gdsLayerTable; static vector<const Layer*> _gdsLayerTable;
vector<DelayedInstance> _delayedInstances; vector<DelayedInstance> _delayedInstances;
@ -637,6 +685,9 @@ namespace {
int64_t _SREFCount; int64_t _SREFCount;
bool _validSyntax; bool _validSyntax;
bool _skipENDEL; bool _skipENDEL;
map< Net*
, vector<PinPoint>
, DBo::CompareById > _netReferences;
}; };
@ -647,6 +698,11 @@ namespace {
{ } { }
inline GdsStream::PinPoint::PinPoint ( const Layer* layer, DbU::Unit x, DbU::Unit y )
: _layer(layer), _position(x,y)
{ }
vector<const Layer*> GdsStream::_gdsLayerTable; vector<const Layer*> GdsStream::_gdsLayerTable;
@ -688,7 +744,7 @@ namespace {
{ {
if (_gdsLayerTable.empty()) _staticInit(); if (_gdsLayerTable.empty()) _staticInit();
_stream.open( gdsPath, ios_base::in ); _stream.open( gdsPath, ios_base::in|ios_base::binary );
_stream >> _record; _stream >> _record;
if (not _record.isHEADER()) { if (not _record.isHEADER()) {
@ -715,7 +771,7 @@ namespace {
bool GdsStream::read ( Library* library ) bool GdsStream::read ( Library* library )
{ {
//cerr << "GdsStream::read(Library*)" << endl; cdebug_log(101,1) << "GdsStream::read(Library*)" << endl;
_library = library; _library = library;
@ -724,6 +780,7 @@ namespace {
" in \"%s\"" " in \"%s\""
, _gdsPath.c_str() ) << endl; , _gdsPath.c_str() ) << endl;
_validSyntax = false; _validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax; return _validSyntax;
} }
_stream >> _record; _stream >> _record;
@ -737,13 +794,20 @@ namespace {
" in \"%s\"" " in \"%s\""
, _gdsPath.c_str() ) << endl; , _gdsPath.c_str() ) << endl;
_validSyntax = false; _validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax; return _validSyntax;
} }
if (_record.isREFLIBS ()) { _stream >> _record; } if (_record.isREFLIBS ()) { _stream >> _record; }
if (_record.isFONTS ()) { _stream >> _record; } if (_record.isFONTS ()) { _stream >> _record; }
if (_record.isATTRTABLE ()) { _stream >> _record; } if (_record.isATTRTABLE ()) { _stream >> _record; }
if (_record.isGENERATIONS()) { _stream >> _record; } if (_record.isGENERATIONS()) { _stream >> _record; }
if (_record.isFORMAT ()) { readFormatType(); if (not _validSyntax) return _validSyntax; } if (_record.isFORMAT ()) {
readFormatType();
if (not _validSyntax) {
cdebug_tabw(101,-1);
return _validSyntax;
}
}
if (_record.isUNITS()) { if (_record.isUNITS()) {
_scale = DbU::fromPhysical( _record.getDoubles()[1], DbU::Unity ); _scale = DbU::fromPhysical( _record.getDoubles()[1], DbU::Unity );
@ -757,17 +821,20 @@ namespace {
if (_validSyntax and not _record.isENDLIB()) { misplacedRecord(); } if (_validSyntax and not _record.isENDLIB()) { misplacedRecord(); }
if (_validSyntax) makeInstances(); if (_validSyntax) {
makeInstances();
makeExternals();
}
_library = NULL; _library = NULL;
//cerr << "GdsStream::read(Library*) - return:" << _validSyntax << endl; cdebug_log(101,-1) << " GdsStream::read(Library*) - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
bool GdsStream::readFormatType () bool GdsStream::readFormatType ()
{ {
//cerr << "GdsStream::readFormatType()" << endl; cdebug_log(101,0) << "GdsStream::readFormatType()" << endl;
if (_record.isMASK()) { if (_record.isMASK()) {
_stream >> _record; _stream >> _record;
@ -779,14 +846,14 @@ namespace {
else { _validSyntax = false; return _validSyntax; } else { _validSyntax = false; return _validSyntax; }
} }
//cerr << "GdsStream::readFormatType() - return:" << _validSyntax << endl; //cdebug(101,0) << "GdsStream::readFormatType() - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
bool GdsStream::readStructure () bool GdsStream::readStructure ()
{ {
//cerr << "GdsStream::readStructure()" << endl; cdebug_log(101,1) << "GdsStream::readStructure()" << endl;
if (_record.isSTRNAME()) { if (_record.isSTRNAME()) {
if (_library) { if (_library) {
@ -819,7 +886,9 @@ namespace {
if (not _skipENDEL) { if (not _skipENDEL) {
if (_record.isENDEL()) { _stream >> _record; } if (_record.isENDEL()) { _stream >> _record; }
else { else {
_validSyntax = false; break; _validSyntax = false;
cdebug_log(101,0) << "Missing ENDEL inside STRUCTURE loop" << endl;
break;
} }
} else } else
_skipENDEL = false; _skipENDEL = false;
@ -832,7 +901,7 @@ namespace {
_cell->setAbutmentBox( _cell->getBoundingBox() ); _cell->setAbutmentBox( _cell->getBoundingBox() );
UpdateSession::open(); UpdateSession::open();
_cell = NULL; _cell = NULL;
cerr << "GdsStream::readStructure() - return:" << _validSyntax << endl; cdebug_log(101,-1) << " GdsStream::readStructure() - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
@ -840,25 +909,41 @@ namespace {
bool GdsStream::readText () bool GdsStream::readText ()
{ {
//cerr << "GdsStream::readText()" << endl; const Layer* layer = NULL;
cdebug_log(101,0) << "GdsStream::readText()" << endl;
if (_record.isELFLAGS()) { _stream >> _record; } if (_record.isELFLAGS()) { _stream >> _record; }
if (_record.isPLEX ()) { _stream >> _record; } if (_record.isPLEX ()) { _stream >> _record; }
if (_record.isLAYER ()) { _stream >> _record; } if (_record.isLAYER ()) {
else { _validSyntax = false; return _validSyntax; } layer = gdsToLayer( _record.getInt16s()[0] );
if (not layer) {
cerr << Error( "GdsStream::readText(): No BasicLayer id:%d in GDS conversion table (skipped)."
, _record.getInt16s()[0]
) << endl;
}
_stream >> _record;
} else { _validSyntax = false; return _validSyntax; }
readTextbody(); readTextbody( layer );
//cerr << "GdsStream::readText() - return:" << _validSyntax << endl; //cdebug(101,0) << "GdsStream::readText() - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
bool GdsStream::readTextbody () bool GdsStream::readTextbody ( const Layer* layer )
{ {
//cerr << "GdsStream::readTextbody()" << endl; cdebug_log(101,1) << "GdsStream::readTextbody()" << endl;
DbU::Unit xpos = 0;
DbU::Unit ypos = 0;
if (_record.isTEXTTYPE()) { _stream >> _record; } if (_record.isTEXTTYPE()) { _stream >> _record; }
else { _validSyntax = false; return _validSyntax; } else {
_validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
}
if (_record.isPRESENTATION()) { _stream >> _record; } if (_record.isPRESENTATION()) { _stream >> _record; }
if (_record.isPATH ()) { _stream >> _record; } if (_record.isPATH ()) { _stream >> _record; }
@ -867,27 +952,55 @@ namespace {
if (_record.isSTRANS()) { if (_record.isSTRANS()) {
_stream >> _record; _stream >> _record;
readStrans(); readStrans();
if (not _validSyntax) return _validSyntax; if (not _validSyntax) {
cdebug_tabw(101,-1);
return _validSyntax;
}
} }
if (_record.isXY()) { _stream >> _record; } if (_record.isXY()) {
else { _validSyntax = false; return _validSyntax; } vector<int32_t> coordinates = _record.getInt32s();
if (coordinates.size() != 2) {
_validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
}
xpos = coordinates[ 0 ]*_scale;
ypos = coordinates[ 1 ]*_scale;
_stream >> _record;
} else {
_validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
}
if (_record.isSTRING()) { if (_record.isSTRING()) {
_text = _record.getName(); _text = _record.getName();
_stream >> _record; _stream >> _record;
cerr << "_text:\"" << _text << "\"" << endl;
} }
else { _validSyntax = false; return _validSyntax; } else {
_validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
}
//cerr << "GdsStream::readTextbody() - return:" << _validSyntax << endl; if (not _text.empty()) {
Net* net = _cell->getNet( _text );
if (not net) {
net = Net::create( _cell, _text );
net->setExternal( true );
}
addNetReference( net, layer, xpos, ypos );
}
cdebug_log(101,-1) << "GdsStream::readTextbody() - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
bool GdsStream::readStrans () bool GdsStream::readStrans ()
{ {
//cerr << "GdsStream::readStrans()" << endl; cdebug_log(101,0) << "GdsStream::readStrans()" << endl;
_angle = 0.0; _angle = 0.0;
_xReflection = _record.hasXReflection(); _xReflection = _record.hasXReflection();
@ -895,14 +1008,14 @@ namespace {
if (_record.isMAG ()) { _stream >> _record; } if (_record.isMAG ()) { _stream >> _record; }
if (_record.isANGLE()) { _angle = _record.getDoubles()[0]; _stream >> _record; } if (_record.isANGLE()) { _angle = _record.getDoubles()[0]; _stream >> _record; }
//cerr << "GdsStream::readStrans() - return:" << _validSyntax << endl; //cdebug(101,0) << "GdsStream::readStrans() - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
bool GdsStream::readBoundary () bool GdsStream::readBoundary ()
{ {
//cerr << "GdsStream::readBoundary()" << endl; cdebug_log(101,1) << "GdsStream::readBoundary()" << endl;
const Layer* layer = NULL; const Layer* layer = NULL;
@ -918,29 +1031,39 @@ namespace {
} }
_stream >> _record; _stream >> _record;
} else { } else {
_validSyntax = false; return _validSyntax; _validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
} }
if (_record.isDATATYPE()) { _stream >> _record; } if (_record.isDATATYPE()) { _stream >> _record; }
else { _validSyntax = false; return _validSyntax; } else {
_validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
}
if (_record.isXY()) { if (_record.isXY()) {
if (_cell and layer) xyToComponent( layer ); if (_cell and layer) xyToComponent( layer );
else _stream >> _record; else _stream >> _record;
} else { } else {
_validSyntax = false; return _validSyntax; _validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
} }
//cerr << "GdsStream::readBoundary() - return:" << _validSyntax << endl; cdebug_log(101,-1) << "GdsStream::readBoundary() - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
bool GdsStream::readPath () bool GdsStream::readPath ()
{ {
//cerr << "GdsStream::readPath()" << endl; cdebug_log(101,1) << "GdsStream::readPath()" << endl;
const Layer* layer = NULL; const Layer* layer = NULL;
DbU::Unit width = 0;
uint16_t pathtype = 0;
if (_record.isELFLAGS()) { _stream >> _record; } if (_record.isELFLAGS()) { _stream >> _record; }
if (_record.isPLEX ()) { _stream >> _record; } if (_record.isPLEX ()) { _stream >> _record; }
@ -953,33 +1076,50 @@ namespace {
) << endl; ) << endl;
} }
_stream >> _record; _stream >> _record;
cdebug_log(101,0) << layer << endl;
} else { } else {
_validSyntax = false; return _validSyntax; _validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
} }
if (_record.isDATATYPE()) { _stream >> _record; } if (_record.isDATATYPE()) { _stream >> _record; }
else { _validSyntax = false; return _validSyntax; } else {
cerr << Error( "GdsStream::readPath(): Expecting DATATYPE record, got %s."
, GdsRecord::toStrType(_record.getType()).c_str()
) << endl;
_validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
}
if (_record.isPATHTYPE()) { _stream >> _record; } if (_record.isPATHTYPE()) {
if (_record.isWIDTH ()) { _stream >> _record; } pathtype = _record.getInt16s()[0];
_stream >> _record;
}
if (_record.isWIDTH ()) {
width = _record.getInt32s()[0] * _scale;
_stream >> _record;
}
if (_record.isBGNEXTN ()) { _stream >> _record; } if (_record.isBGNEXTN ()) { _stream >> _record; }
if (_record.isENDEXTN ()) { _stream >> _record; } if (_record.isENDEXTN ()) { _stream >> _record; }
if (_record.isXY()) { if (_record.isXY()) {
if (_cell and layer) xyToComponent( layer ); if (_cell and layer) xyToPath( pathtype, layer, width );
_stream >> _record;
} else { } else {
_validSyntax = false; return _validSyntax; _validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
} }
//cerr << "GdsStream::readPath() - return:" << _validSyntax << endl; cdebug_log(101,-1) << "GdsStream::readPath() - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
bool GdsStream::readSref () bool GdsStream::readSref ()
{ {
//cerr << "GdsStream::readSref()" << endl; cdebug_log(101,1) << "GdsStream::readSref()" << endl;
resetStrans(); resetStrans();
string masterName; string masterName;
@ -991,22 +1131,28 @@ namespace {
if (_record.isSNAME()) { if (_record.isSNAME()) {
masterName = _record.getName(); masterName = _record.getName();
_stream >> _record; _stream >> _record;
} else { } else {
_validSyntax = false; return _validSyntax; _validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
} }
if (_record.isSTRANS()) { if (_record.isSTRANS()) {
readStrans(); readStrans();
//_stream >> _record; //_stream >> _record;
if (not _validSyntax) return _validSyntax; if (not _validSyntax) {
cdebug_tabw(101,-1);
return _validSyntax;
}
} }
if (_record.isXY()) { if (_record.isXY()) {
vector<int32_t> coordinates = _record.getInt32s(); vector<int32_t> coordinates = _record.getInt32s();
if (coordinates.size() != 2) { if (coordinates.size() != 2) {
_validSyntax = false; return _validSyntax; _validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
} }
xpos = coordinates[ 0 ]*_scale; xpos = coordinates[ 0 ]*_scale;
@ -1014,7 +1160,9 @@ namespace {
_stream >> _record; _stream >> _record;
} else { } else {
_validSyntax = false; return _validSyntax; _validSyntax = false;
cdebug_tabw(101,-1);
return _validSyntax;
} }
if (not masterName.empty()) { if (not masterName.empty()) {
@ -1048,14 +1196,14 @@ namespace {
, Transformation(xpos,ypos,orient)) ); , Transformation(xpos,ypos,orient)) );
} }
//cerr << "GdsStream::readSref() - return:" << _validSyntax << endl; cdebug_log(101,-1) << "GdsStream::readSref() - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
bool GdsStream::readAref () bool GdsStream::readAref ()
{ {
//cerr << "GdsStream::readAref()" << endl; cdebug_log(101,0) << "GdsStream::readAref()" << endl;
const Layer* layer = NULL; const Layer* layer = NULL;
@ -1087,14 +1235,14 @@ namespace {
_validSyntax = false; return _validSyntax; _validSyntax = false; return _validSyntax;
} }
//cerr << "GdsStream::readAref() - return:" << _validSyntax << endl; cdebug_log(101,0) << "GdsStream::readAref() - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
bool GdsStream::readNode () bool GdsStream::readNode ()
{ {
//cerr << "GdsStream::readNode()" << endl; cdebug_log(101,0) << "GdsStream::readNode()" << endl;
const Layer* layer = NULL; const Layer* layer = NULL;
@ -1117,14 +1265,14 @@ namespace {
_validSyntax = false; return _validSyntax; _validSyntax = false; return _validSyntax;
} }
//cerr << "GdsStream::readNode() - return:" << _validSyntax << endl; cdebug_log(101,0) << "GdsStream::readNode() - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
bool GdsStream::readBox () bool GdsStream::readBox ()
{ {
//cerr << "GdsStream::readBox()" << endl; cdebug_log(101,0) << "GdsStream::readBox()" << endl;
const Layer* layer = NULL; const Layer* layer = NULL;
@ -1147,19 +1295,19 @@ namespace {
_validSyntax = false; return _validSyntax; _validSyntax = false; return _validSyntax;
} }
//cerr << "GdsStream::readBox() - return:" << _validSyntax << endl; cdebug_log(101,0) << "GdsStream::readBox() - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
bool GdsStream::readProperty () bool GdsStream::readProperty ()
{ {
//cerr << "GdsStream::readProperty()" << endl; cdebug_log(101,0) << "GdsStream::readProperty()" << endl;
if (_record.isPROPVALUE ()) { _stream >> _record; } if (_record.isPROPVALUE ()) { _stream >> _record; }
else { _validSyntax = false; return _validSyntax; } else { _validSyntax = false; return _validSyntax; }
//cerr << "GdsStream::readProperty() - return:" << _validSyntax << endl; cdebug_log(101,0) << "GdsStream::readProperty() - return:" << _validSyntax << endl;
return _validSyntax; return _validSyntax;
} }
@ -1174,8 +1322,9 @@ namespace {
_stream >> _record; _stream >> _record;
if (_record.getType() == GdsRecord::ENDEL) { if ( (_record.getType() == GdsRecord::ENDEL)
_stream >> _record; or (_record.getType() == GdsRecord::STRING)) {
//_stream >> _record;
} else { } else {
_validSyntax = false; _validSyntax = false;
return; return;
@ -1184,9 +1333,7 @@ namespace {
Net* net = NULL; Net* net = NULL;
if (_record.getType() == GdsRecord::TEXT) { if (_record.getType() == GdsRecord::TEXT) {
_stream >> _record; _stream >> _record;
cerr << " BOUNDARY --> TEXT record" << endl;
readText(); readText();
cerr << " AFTER readText()" << endl;
if (not _text.empty()) { if (not _text.empty()) {
net = _cell->getNet( _text ); net = _cell->getNet( _text );
@ -1214,33 +1361,174 @@ namespace {
Box boundingBox; Box boundingBox;
for ( Point p : points ) boundingBox.merge( p ); for ( Point p : points ) boundingBox.merge( p );
_component = Pad::create( net, layer, boundingBox ); _component = Pad::create( net, layer, boundingBox );
cerr << _component << endl;
} else { } else {
_component = Rectilinear::create( net, layer, points ); _component = Rectilinear::create( net, layer, points );
} }
// cdebug(101,0) << "| " << net->getCell() << endl;
// cdebug(101,0) << "| " << _component << endl;
if (not net->isAutomatic()) NetExternalComponents::setExternal( _component ); if (not net->isAutomatic()) NetExternalComponents::setExternal( _component );
} }
} }
void GdsStream::xyToPath ( uint16_t pathtype, const Layer* layer, DbU::Unit width )
{
cdebug_log(101,0) << "GdsStream::xyToPath(): pathtype=" << pathtype
<< " layer=" << layer->getName()
<< " width=" << DbU::getValueString(width) << endl;
vector<Point> points;
vector<int32_t> coordinates = _record.getInt32s();
for ( size_t i=0 ; i<coordinates.size() ; i += 2 )
points.push_back( Point( coordinates[i ]*_scale
, coordinates[i+1]*_scale ) );
_stream >> _record;
if (_record.getType() != GdsRecord::ENDEL) {
_validSyntax = false;
return;
}
Net* net = fusedNet();
for ( size_t i=1 ; i<points.size() ; ++i ) {
if ( (points[i-1].getX() != points[i].getX())
and (points[i-1].getY() != points[i].getY()) ) {
cerr << Error( "GdsStream::xyToPath(): Non-rectilinear paths are not supporteds (skipped)."
) << endl;
return;
}
}
DbU::Unit hWidthCap = width;
DbU::Unit vWidthCap = width;
if (pathtype == 0) {
if (points[0].getX() == points[1].getX()) vWidthCap = 0;
else hWidthCap = 0;
}
Contact* source = Contact::create( net
, layer
, points[0].getX()
, points[0].getY()
, hWidthCap
, vWidthCap );
hWidthCap = width;
vWidthCap = width;
Contact* target = NULL;
Segment* segment = NULL;
for ( size_t i=1 ; i<points.size() ; ++i ) {
if (i == points.size()-1) {
if (pathtype == 0) {
if (points[0].getX() == points[1].getX()) vWidthCap = 0;
else hWidthCap = 0;
}
}
target = Contact::create( net
, layer
, points[i].getX()
, points[i].getY()
, hWidthCap
, vWidthCap );
if (points[i-1].getY() == points[i].getY()) {
segment = Horizontal::create( source
, target
, layer
, points[i].getY()
, width
, 0, 0 );
} else {
segment = Vertical::create( source
, target
, layer
, points[i].getX()
, width
, 0, 0 );
}
if (not net->isAutomatic()) NetExternalComponents::setExternal( segment );
source = target;
}
}
void GdsStream::makeInstances () void GdsStream::makeInstances ()
{ {
//cerr << "GdsStream::makeInstances(): " << endl; cdebug_log(101,1) << "GdsStream::makeInstances(): " << endl;
for ( const DelayedInstance& di : _delayedInstances ) { for ( const DelayedInstance& di : _delayedInstances ) {
Cell* masterCell = _library->getCell( di._masterName ); Cell* masterCell = _library->getCell( di._masterName );
if (masterCell) { if (masterCell) {
string insName = "sref_" + getString(_SREFCount++); string insName = "sref_" + getString(_SREFCount++);
//Instance* instance = Instance* instance =
Instance::create( di._owner Instance::create( di._owner
, insName , insName
, masterCell , masterCell
, di._transformation , di._transformation
, Instance::PlacementStatus::FIXED , Instance::PlacementStatus::FIXED
); );
//cerr << "| " << instance << " @" << di._transformation << " in " << di._owner << endl; cdebug_log(101,0) << "| " << instance << " @" << di._transformation << " in " << di._owner << endl;
}
}
cdebug_tabw(101,-1);
}
void GdsStream::addNetReference ( Net* net, const Layer* layer, DbU::Unit x, DbU::Unit y )
{
if (not layer) return;
auto inet = _netReferences.find( net );
if (inet == _netReferences.end()) {
_netReferences[ net ] = vector<PinPoint>();
}
_netReferences[ net ].push_back( PinPoint(layer,x,y) );
}
void GdsStream::makeExternals ()
{
UpdateSession::close();
UpdateSession::open();
for ( auto netPins : _netReferences ) {
Net* net = netPins.first;
for ( const PinPoint& ref : netPins.second ) {
const Layer* layer = ref._layer;
string layerName = getString( layer->getName() );
if (layerName.substr(layerName.size()-4) == ".pin") {
layer = DataBase::getDB()->getTechnology()->getLayer( layerName.substr(0,layerName.size()-4) );
}
cdebug_log(101,0) << "Looking for components of \"" << net->getName()
<< "\" in " << layer
<< " @" << ref._position
<< endl;
if (not layer) continue;
for ( Component* component : net->getCell()
->getComponentsUnder( Box(ref._position).inflate(1),layer->getMask() ) ) {
cdebug_log(101,0) << "| " << component << endl;
Horizontal* href = dynamic_cast<Horizontal*>( component );
if (href) {
Horizontal* h = Horizontal::create( net
, href->getLayer()
, href->getY()
, href->getWidth()
, href->getSourceX()
, href->getTargetX()
);
NetExternalComponents::setExternal( h );
} else {
Vertical* vref = dynamic_cast<Vertical*>( component );
if (vref) {
Vertical* v = Vertical::create( net
, vref->getLayer()
, vref->getX()
, vref->getWidth()
, vref->getSourceY()
, vref->getTargetY()
);
NetExternalComponents::setExternal( v );
}
}
}
} }
} }
} }