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 <cmath>
#include <cstdio>
#include <cfenv>
#include <string>
#include <sstream>
@ -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<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).
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,22 +468,28 @@ 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 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 BasicLayer* );
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& );
@ -483,15 +505,21 @@ 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::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<Point>& points )
{
GdsRecord record ( GdsRecord::XY );
@ -720,7 +762,8 @@ namespace {
for ( const vector<Point>& 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;
}
}
}
}

View File

@ -15,6 +15,7 @@
#include <ctime>
#include <cstdio>
#include <string>
#include <bitset>
#include <sstream>
@ -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<int16_t> _int16s;
vector<int32_t> _int32s;
vector<double> _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,10 +429,16 @@ namespace {
unsigned char bytes[ typeSize ];
};
char bytes[typeSize];
_stream->read( bytes, 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 ; i<typeSize ; ++i ) {
// sprintf( _buffer, "0x%02x", bytes[i] );
// cdebug(101,0) << setw(6) << hex << _offset++ << " | " << _buffer << endl;
// }
UType uvalue;
// Little endian (x86).
for ( size_t i=0 ; i<typeSize ; ++i ) uvalue.bytes[i] = bytes[typeSize-i-1];
@ -440,6 +458,12 @@ namespace {
_stream->read( 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<uint16_t>();
_xReflection = (flags & XRMask);
@ -508,6 +539,14 @@ namespace {
{ _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 ()
{ while ( _count < _length ) _int32s.push_back( _readInt<int32_t>() ); }
@ -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<const Layer*> _gdsLayerTable;
vector<DelayedInstance> _delayedInstances;
@ -637,6 +685,9 @@ namespace {
int64_t _SREFCount;
bool _validSyntax;
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;
@ -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<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()) {
_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;
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<int32_t> 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<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 ()
{
//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<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 );
}
}
}
}
}
}