From ead11f8b93f3c768f544092884d6c6ed1ec8e258 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sat, 19 Dec 2020 23:04:50 +0100 Subject: [PATCH] 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. --- crlcore/src/ccore/gds/GdsDriver.cpp | 143 ++++++--- crlcore/src/ccore/gds/GdsParser.cpp | 440 +++++++++++++++++++++++----- 2 files changed, 470 insertions(+), 113 deletions(-) diff --git a/crlcore/src/ccore/gds/GdsDriver.cpp b/crlcore/src/ccore/gds/GdsDriver.cpp index 71e13f45..c618cc24 100644 --- a/crlcore/src/ccore/gds/GdsDriver.cpp +++ b/crlcore/src/ccore/gds/GdsDriver.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -36,6 +37,7 @@ using namespace std; #include "hurricane/Polygon.h" #include "hurricane/Pad.h" #include "hurricane/Net.h" +#include "hurricane/NetExternalComponents.h" #include "hurricane/Cell.h" #include "hurricane/Plug.h" #include "hurricane/Instance.h" @@ -262,7 +264,7 @@ namespace { //static const uint16_t PATH = 0x0900 | NoData; static const uint16_t SREF = 0x0a00 | 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 DATATYPE = 0x0e00 | TwoByteInteger; //static const uint16_t WIDTH = 0x0f00 | FourByteInteger; @@ -272,10 +274,10 @@ namespace { //static const uint16_t COLROW = 0x1300 | TwoByteInteger; //static const uint16_t TEXTNODE = 0x1400 | NoData; // Unused. //static const uint16_t NODE = 0x1500 | NoData; - //static const uint16_t TEXTTYPE = 0x1600 | TwoByteInteger; - //static const uint16_t PRESENTATION = 0x1700 | BitArray; + static const uint16_t TEXTTYPE = 0x1600 | TwoByteInteger; + static const uint16_t PRESENTATION = 0x1700 | BitArray; //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 MAG = 0x1b00 | EightByteReal; static const uint16_t ANGLE = 0x1c00 | EightByteReal; @@ -428,13 +430,27 @@ namespace { void GdsRecord::toStream ( ostream& stream ) const { + static size_t count = 0; + uint16_t length = (uint16_t)( _bytes.size()+2 ); const unsigned char* bytearray = reinterpret_cast( &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). stream.put( bytearray[1] ); 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 ENDSTR; static const GdsRecord SREF; + static const GdsRecord TEXT; public: - GdsStream ( string filename ); - ~GdsStream (); - inline int32_t toGdsDbu ( DbU::Unit ) const; - static inline GdsRecord PROPATTR ( int16_t ); - static inline GdsRecord DATATYPE ( int16_t ); - static inline GdsRecord PROPVALUE ( string ); - static inline GdsRecord STRNAME ( string ); - static inline GdsRecord STRNAME ( const Name& ); - static inline GdsRecord LIBNAME ( string ); - static inline GdsRecord SNAME ( string ); - static inline GdsRecord SNAME ( const Name& ); - GdsStream& operator<< ( const GdsRecord& ); - GdsStream& operator<< ( const BasicLayer* ); - GdsStream& operator<< ( const Box& ); - GdsStream& operator<< ( const Points ); - GdsStream& operator<< ( const vector& points ); - GdsStream& operator<< ( const Cell* ); - GdsStream& operator<< ( const Transformation& ); + GdsStream ( string filename ); + ~GdsStream (); + inline int32_t toGdsDbu ( DbU::Unit ) const; + static inline GdsRecord PROPATTR ( int16_t ); + static inline GdsRecord DATATYPE ( int16_t ); + static inline GdsRecord TEXTTYPE ( int16_t ); + static inline GdsRecord LAYER ( int16_t ); + static inline GdsRecord PRESENTATION ( int16_t ); + static inline GdsRecord PROPVALUE ( string ); + static inline GdsRecord STRNAME ( string ); + static inline GdsRecord STRNAME ( const Name& ); + static inline GdsRecord LIBNAME ( string ); + static inline GdsRecord SNAME ( string ); + static inline GdsRecord SNAME ( const Name& ); + static inline GdsRecord STRING ( const Name& ); + static inline GdsRecord STRING ( const string ); + GdsStream& operator<< ( const GdsRecord& ); + GdsStream& operator<< ( const Box& ); + GdsStream& operator<< ( const Points ); + GdsStream& operator<< ( const Point& point ); + GdsStream& operator<< ( const vector& points ); + GdsStream& operator<< ( const Cell* ); + GdsStream& operator<< ( const Transformation& ); private: ofstream _ostream; double _dbuPerUu; @@ -483,16 +505,22 @@ namespace { const GdsRecord GdsStream::ENDEL = GdsRecord(GdsRecord::ENDEL); const GdsRecord GdsStream::ENDSTR = GdsRecord(GdsRecord::ENDSTR); 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::DATATYPE ( int16_t v ) { return GdsRecord(GdsRecord::DATATYPE,v); } - inline GdsRecord GdsStream::PROPVALUE ( string s ) { return GdsRecord(GdsRecord::PROPVALUE,s); } - inline GdsRecord GdsStream::STRNAME ( string s ) { return GdsRecord(GdsRecord::STRNAME,s); } - inline GdsRecord GdsStream::STRNAME ( const Name& n ) { return GdsRecord(GdsRecord::STRNAME,getString(n)); } - 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 int32_t GdsStream::toGdsDbu ( DbU::Unit v ) const + 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::TEXTTYPE ( int16_t v ) { return GdsRecord(GdsRecord::TEXTTYPE,v); } + inline GdsRecord GdsStream::LAYER ( int16_t v ) { return GdsRecord(GdsRecord::LAYER,v); } + inline GdsRecord GdsStream::PRESENTATION ( int16_t v ) { return GdsRecord(GdsRecord::PRESENTATION,v); } + inline GdsRecord GdsStream::PROPVALUE ( string s ) { return GdsRecord(GdsRecord::PROPVALUE,s); } + inline GdsRecord GdsStream::STRNAME ( string s ) { return GdsRecord(GdsRecord::STRNAME,s); } + inline GdsRecord GdsStream::STRNAME ( const Name& n ) { return GdsRecord(GdsRecord::STRNAME,getString(n)); } + 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 )); } @@ -502,7 +530,7 @@ namespace { , _metricDbU(Cfg::getParamDouble("gdsDriver.metricDbu",10e-9)->asDouble()) // 1um. { std::fesetround( FE_TONEAREST ); - _ostream.open( filename, ios_base::out ); + _ostream.open( filename, ios_base::out|ios_base::binary ); GdsRecord record ( GdsRecord::HEADER ); record.push( (uint16_t)600 ); @@ -552,18 +580,22 @@ namespace { { _ostream << record; return *this; } +#if 0 GdsStream& GdsStream::operator<< ( const BasicLayer* layer ) { + cdebug_log(101,0) << "LAYER" << endl; GdsRecord record ( GdsRecord::LAYER ); record.push( (int16_t)layer->getGds2Layer() ); _ostream << record; + cdebug_log(101,0) << "DATATYPE" << endl; record = GdsRecord( GdsRecord::DATATYPE ); record.push( (int16_t)layer->getGds2Datatype() ); _ostream << record; return *this; } +#endif 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& points ) { GdsRecord record ( GdsRecord::XY ); @@ -720,7 +762,8 @@ namespace { for ( const vector& subpolygon : subpolygons ) { for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) { (*this) << BOUNDARY; - (*this) << layer; + (*this) << LAYER(layer->getGds2Layer()); + (*this) << DATATYPE(layer->getGds2Datatype()); (*this) << subpolygon; (*this) << ENDEL; } @@ -730,7 +773,8 @@ namespace { if (rectilinear) { for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) { (*this) << BOUNDARY; - (*this) << layer; + (*this) << LAYER(layer->getGds2Layer()); + (*this) << DATATYPE(layer->getGds2Datatype()); (*this) << rectilinear->getPoints(); (*this) << ENDEL; isOnGrid( component, rectilinear->getPoints() ); @@ -740,7 +784,8 @@ namespace { if (diagonal) { for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) { (*this) << BOUNDARY; - (*this) << layer; + (*this) << LAYER(layer->getGds2Layer()); + (*this) << DATATYPE(layer->getGds2Datatype()); (*this) << diagonal->getContour(); (*this) << ENDEL; } @@ -753,10 +798,34 @@ namespace { if ((bb.getWidth() == 0) or (bb.getHeight() == 0)) continue; (*this) << BOUNDARY; - (*this) << layer; + (*this) << LAYER(layer->getGds2Layer()); + (*this) << DATATYPE(layer->getGds2Datatype()); (*this) << bb; (*this) << ENDEL; 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; + } } } } diff --git a/crlcore/src/ccore/gds/GdsParser.cpp b/crlcore/src/ccore/gds/GdsParser.cpp index ad87f780..2c6e4d49 100644 --- a/crlcore/src/ccore/gds/GdsParser.cpp +++ b/crlcore/src/ccore/gds/GdsParser.cpp @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -201,6 +202,8 @@ namespace { void readString (); void readUnits (); void readLayer (); + void readWidth (); + void readPathtype (); void readStrname (); void readXy (); static string toStrType ( uint16_t ); @@ -211,6 +214,7 @@ namespace { double _readDouble (); private: istream* _stream; + uint32_t _offset; uint16_t _length; uint16_t _count; uint16_t _type; @@ -220,6 +224,7 @@ namespace { vector _int16s; vector _int32s; vector _doubles; + char _buffer[64]; }; @@ -293,6 +298,7 @@ namespace { GdsRecord::GdsRecord () : _stream (NULL) + , _offset (0) , _length (0) , _count (0) , _type (0) @@ -344,7 +350,7 @@ namespace { case TEXT: readDummy( false ); break; case LAYER: readLayer(); break; case DATATYPE: readDummy( false ); break; - case WIDTH: readDummy( false ); break; + case WIDTH: readWidth(); break; case XY: readXy(); break; case ENDEL: readDummy( false ); break; case SNAME: readStrname(); break; @@ -360,7 +366,7 @@ namespace { case ANGLE: _doubles.push_back( _readDouble() ); break; case REFLIBS: readDummy( false ); break; case FONTS: readDummy( false ); break; - case PATHTYPE: readDummy( false ); break; + case PATHTYPE: readPathtype(); break; case GENERATIONS: readDummy( false ); break; case ATTRTABLE: readDummy( false ); break; case STYPTABLE: readDummy( false ); break; @@ -389,7 +395,13 @@ namespace { 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 ]; }; - char bytes[typeSize]; - _stream->read( bytes, typeSize ); - _count += typeSize; + unsigned char bytes[typeSize]; + _stream->read( (char*)(&bytes[0]), typeSize ); + _count += typeSize; + + // cdebug_log(101,0) << "GdsRecord::_readInt() " << endl; + // for ( size_t i=0 ; iread( bytes, 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; for ( size_t i=0 ; i<7 ; ++i ) mantisse.bytes[i] = bytes[7-i]; mantisse.bytes[7] = 0; @@ -456,31 +480,38 @@ namespace { string GdsRecord::_readString () { + cdebug_log(101,0) << "GdsRecord::_readDouble() " << endl; string s; char c; for ( ; _count<_length ; ++_count ) { _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); } - cerr << "GdsRecord::_readString(): \"" << s << "\"" << endl; + cdebug_log(101,0) << "GdsRecord::_readString(): \"" << s << "\"" << endl; return s; } void GdsRecord::readDummy ( bool showError ) { + cdebug_log(101,0) << "GdsRecord::readDummy() " << endl; 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) { - 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 () { - const uint16_t XRMask = 0x8000; uint16_t flags = _readInt(); _xReflection = (flags & XRMask); @@ -508,6 +539,14 @@ namespace { { _int16s.push_back( _readInt() ); } + void GdsRecord::readWidth () + { _int32s.push_back( _readInt() ); } + + + void GdsRecord::readPathtype () + { _int16s.push_back( _readInt() ); } + + void GdsRecord::readXy () { while ( _count < _length ) _int32s.push_back( _readInt() ); } @@ -607,12 +646,15 @@ namespace { bool readNode (); bool readBox (); bool readText (); - bool readTextbody (); + bool readTextbody ( const Layer* ); bool readStrans (); bool readProperty (); void xyToComponent ( const Layer* ); + void xyToPath ( uint16_t pathtype, const Layer*, DbU::Unit width ); void makeInstances (); + void makeExternals (); Net* fusedNet (); + void addNetReference ( Net*, const Layer*, DbU::Unit x, DbU::Unit y ); private: struct DelayedInstance { inline DelayedInstance ( Cell* owner, string masterName, const Transformation& ); @@ -621,6 +663,12 @@ namespace { string _masterName; Transformation _transformation; }; + private: + struct PinPoint { + inline PinPoint ( const Layer*, DbU::Unit x, DbU::Unit y ); + const Layer* _layer; + Point _position; + }; private: static vector _gdsLayerTable; vector _delayedInstances; @@ -637,6 +685,9 @@ namespace { int64_t _SREFCount; bool _validSyntax; bool _skipENDEL; + map< Net* + , vector + , 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 GdsStream::_gdsLayerTable; @@ -688,7 +744,7 @@ namespace { { if (_gdsLayerTable.empty()) _staticInit(); - _stream.open( gdsPath, ios_base::in ); + _stream.open( gdsPath, ios_base::in|ios_base::binary ); _stream >> _record; if (not _record.isHEADER()) { @@ -715,7 +771,7 @@ namespace { bool GdsStream::read ( Library* library ) { - //cerr << "GdsStream::read(Library*)" << endl; + cdebug_log(101,1) << "GdsStream::read(Library*)" << endl; _library = library; @@ -724,6 +780,7 @@ namespace { " in \"%s\"" , _gdsPath.c_str() ) << endl; _validSyntax = false; + cdebug_tabw(101,-1); return _validSyntax; } _stream >> _record; @@ -737,13 +794,20 @@ namespace { " in \"%s\"" , _gdsPath.c_str() ) << endl; _validSyntax = false; + cdebug_tabw(101,-1); return _validSyntax; } if (_record.isREFLIBS ()) { _stream >> _record; } if (_record.isFONTS ()) { _stream >> _record; } if (_record.isATTRTABLE ()) { _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()) { _scale = DbU::fromPhysical( _record.getDoubles()[1], DbU::Unity ); @@ -757,17 +821,20 @@ namespace { if (_validSyntax and not _record.isENDLIB()) { misplacedRecord(); } - if (_validSyntax) makeInstances(); + if (_validSyntax) { + makeInstances(); + makeExternals(); + } _library = NULL; - //cerr << "GdsStream::read(Library*) - return:" << _validSyntax << endl; + cdebug_log(101,-1) << " GdsStream::read(Library*) - return:" << _validSyntax << endl; return _validSyntax; } bool GdsStream::readFormatType () { - //cerr << "GdsStream::readFormatType()" << endl; + cdebug_log(101,0) << "GdsStream::readFormatType()" << endl; if (_record.isMASK()) { _stream >> _record; @@ -779,14 +846,14 @@ namespace { else { _validSyntax = false; return _validSyntax; } } - //cerr << "GdsStream::readFormatType() - return:" << _validSyntax << endl; + //cdebug(101,0) << "GdsStream::readFormatType() - return:" << _validSyntax << endl; return _validSyntax; } bool GdsStream::readStructure () { - //cerr << "GdsStream::readStructure()" << endl; + cdebug_log(101,1) << "GdsStream::readStructure()" << endl; if (_record.isSTRNAME()) { if (_library) { @@ -819,7 +886,9 @@ namespace { if (not _skipENDEL) { if (_record.isENDEL()) { _stream >> _record; } else { - _validSyntax = false; break; + _validSyntax = false; + cdebug_log(101,0) << "Missing ENDEL inside STRUCTURE loop" << endl; + break; } } else _skipENDEL = false; @@ -832,7 +901,7 @@ namespace { _cell->setAbutmentBox( _cell->getBoundingBox() ); UpdateSession::open(); _cell = NULL; - cerr << "GdsStream::readStructure() - return:" << _validSyntax << endl; + cdebug_log(101,-1) << " GdsStream::readStructure() - return:" << _validSyntax << endl; return _validSyntax; } @@ -840,25 +909,41 @@ namespace { 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.isPLEX ()) { _stream >> _record; } - if (_record.isLAYER ()) { _stream >> _record; } - else { _validSyntax = false; return _validSyntax; } + if (_record.isLAYER ()) { + 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; } - 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; } - else { _validSyntax = false; return _validSyntax; } + else { + _validSyntax = false; + cdebug_tabw(101,-1); + return _validSyntax; + } if (_record.isPRESENTATION()) { _stream >> _record; } if (_record.isPATH ()) { _stream >> _record; } @@ -867,27 +952,55 @@ namespace { if (_record.isSTRANS()) { _stream >> _record; readStrans(); - if (not _validSyntax) return _validSyntax; + if (not _validSyntax) { + cdebug_tabw(101,-1); + return _validSyntax; + } } - if (_record.isXY()) { _stream >> _record; } - else { _validSyntax = false; return _validSyntax; } + if (_record.isXY()) { + vector 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()) { _text = _record.getName(); _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; } bool GdsStream::readStrans () { - //cerr << "GdsStream::readStrans()" << endl; + cdebug_log(101,0) << "GdsStream::readStrans()" << endl; _angle = 0.0; _xReflection = _record.hasXReflection(); @@ -895,14 +1008,14 @@ namespace { if (_record.isMAG ()) { _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; } bool GdsStream::readBoundary () { - //cerr << "GdsStream::readBoundary()" << endl; + cdebug_log(101,1) << "GdsStream::readBoundary()" << endl; const Layer* layer = NULL; @@ -918,29 +1031,39 @@ namespace { } _stream >> _record; } else { - _validSyntax = false; return _validSyntax; + _validSyntax = false; + cdebug_tabw(101,-1); + return _validSyntax; } if (_record.isDATATYPE()) { _stream >> _record; } - else { _validSyntax = false; return _validSyntax; } + else { + _validSyntax = false; + cdebug_tabw(101,-1); + return _validSyntax; + } if (_record.isXY()) { if (_cell and layer) xyToComponent( layer ); else _stream >> _record; } 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; } 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.isPLEX ()) { _stream >> _record; } @@ -953,33 +1076,50 @@ namespace { ) << endl; } _stream >> _record; + cdebug_log(101,0) << layer << endl; } else { - _validSyntax = false; return _validSyntax; + _validSyntax = false; + cdebug_tabw(101,-1); + return _validSyntax; } 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.isWIDTH ()) { _stream >> _record; } + if (_record.isPATHTYPE()) { + pathtype = _record.getInt16s()[0]; + _stream >> _record; + } + if (_record.isWIDTH ()) { + width = _record.getInt32s()[0] * _scale; + _stream >> _record; + } if (_record.isBGNEXTN ()) { _stream >> _record; } if (_record.isENDEXTN ()) { _stream >> _record; } if (_record.isXY()) { - if (_cell and layer) xyToComponent( layer ); - _stream >> _record; + if (_cell and layer) xyToPath( pathtype, layer, width ); } 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; } bool GdsStream::readSref () { - //cerr << "GdsStream::readSref()" << endl; + cdebug_log(101,1) << "GdsStream::readSref()" << endl; resetStrans(); string masterName; @@ -991,22 +1131,28 @@ namespace { if (_record.isSNAME()) { masterName = _record.getName(); - _stream >> _record; } else { - _validSyntax = false; return _validSyntax; + _validSyntax = false; + cdebug_tabw(101,-1); + return _validSyntax; } if (_record.isSTRANS()) { readStrans(); //_stream >> _record; - if (not _validSyntax) return _validSyntax; + if (not _validSyntax) { + cdebug_tabw(101,-1); + return _validSyntax; + } } if (_record.isXY()) { vector coordinates = _record.getInt32s(); if (coordinates.size() != 2) { - _validSyntax = false; return _validSyntax; + _validSyntax = false; + cdebug_tabw(101,-1); + return _validSyntax; } xpos = coordinates[ 0 ]*_scale; @@ -1014,7 +1160,9 @@ namespace { _stream >> _record; } else { - _validSyntax = false; return _validSyntax; + _validSyntax = false; + cdebug_tabw(101,-1); + return _validSyntax; } if (not masterName.empty()) { @@ -1048,14 +1196,14 @@ namespace { , Transformation(xpos,ypos,orient)) ); } - //cerr << "GdsStream::readSref() - return:" << _validSyntax << endl; + cdebug_log(101,-1) << "GdsStream::readSref() - return:" << _validSyntax << endl; return _validSyntax; } bool GdsStream::readAref () { - //cerr << "GdsStream::readAref()" << endl; + cdebug_log(101,0) << "GdsStream::readAref()" << endl; const Layer* layer = NULL; @@ -1087,14 +1235,14 @@ namespace { _validSyntax = false; return _validSyntax; } - //cerr << "GdsStream::readAref() - return:" << _validSyntax << endl; + cdebug_log(101,0) << "GdsStream::readAref() - return:" << _validSyntax << endl; return _validSyntax; } bool GdsStream::readNode () { - //cerr << "GdsStream::readNode()" << endl; + cdebug_log(101,0) << "GdsStream::readNode()" << endl; const Layer* layer = NULL; @@ -1117,14 +1265,14 @@ namespace { _validSyntax = false; return _validSyntax; } - //cerr << "GdsStream::readNode() - return:" << _validSyntax << endl; + cdebug_log(101,0) << "GdsStream::readNode() - return:" << _validSyntax << endl; return _validSyntax; } bool GdsStream::readBox () { - //cerr << "GdsStream::readBox()" << endl; + cdebug_log(101,0) << "GdsStream::readBox()" << endl; const Layer* layer = NULL; @@ -1147,19 +1295,19 @@ namespace { _validSyntax = false; return _validSyntax; } - //cerr << "GdsStream::readBox() - return:" << _validSyntax << endl; + cdebug_log(101,0) << "GdsStream::readBox() - return:" << _validSyntax << endl; return _validSyntax; } bool GdsStream::readProperty () { - //cerr << "GdsStream::readProperty()" << endl; + cdebug_log(101,0) << "GdsStream::readProperty()" << endl; if (_record.isPROPVALUE ()) { _stream >> _record; } else { _validSyntax = false; return _validSyntax; } - //cerr << "GdsStream::readProperty() - return:" << _validSyntax << endl; + cdebug_log(101,0) << "GdsStream::readProperty() - return:" << _validSyntax << endl; return _validSyntax; } @@ -1174,8 +1322,9 @@ namespace { _stream >> _record; - if (_record.getType() == GdsRecord::ENDEL) { - _stream >> _record; + if ( (_record.getType() == GdsRecord::ENDEL) + or (_record.getType() == GdsRecord::STRING)) { + //_stream >> _record; } else { _validSyntax = false; return; @@ -1184,9 +1333,7 @@ namespace { Net* net = NULL; if (_record.getType() == GdsRecord::TEXT) { _stream >> _record; - cerr << " BOUNDARY --> TEXT record" << endl; readText(); - cerr << " AFTER readText()" << endl; if (not _text.empty()) { net = _cell->getNet( _text ); @@ -1214,33 +1361,174 @@ namespace { Box boundingBox; for ( Point p : points ) boundingBox.merge( p ); _component = Pad::create( net, layer, boundingBox ); - cerr << _component << endl; } else { _component = Rectilinear::create( net, layer, points ); } + // cdebug(101,0) << "| " << net->getCell() << endl; + // cdebug(101,0) << "| " << _component << endl; 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 points; + vector coordinates = _record.getInt32s(); + for ( size_t i=0 ; i> _record; + if (_record.getType() != GdsRecord::ENDEL) { + _validSyntax = false; + return; + } + + Net* net = fusedNet(); + + for ( size_t i=1 ; iisAutomatic()) NetExternalComponents::setExternal( segment ); + source = target; + } + } + + void GdsStream::makeInstances () { - //cerr << "GdsStream::makeInstances(): " << endl; + cdebug_log(101,1) << "GdsStream::makeInstances(): " << endl; for ( const DelayedInstance& di : _delayedInstances ) { Cell* masterCell = _library->getCell( di._masterName ); if (masterCell) { string insName = "sref_" + getString(_SREFCount++); - //Instance* instance = + Instance* instance = Instance::create( di._owner , insName , masterCell , di._transformation , 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(); + } + _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( 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( component ); + if (vref) { + Vertical* v = Vertical::create( net + , vref->getLayer() + , vref->getX() + , vref->getWidth() + , vref->getSourceY() + , vref->getTargetY() + ); + NetExternalComponents::setExternal( v ); + } + } + } } } }