Add & fix GDS parser for PATH of type 4 (seen in the PLL).

* New: In CRL::GdsStream::xyToPath(), now manage BGNEXTN & ENDEXTN for
    PATHTYPE 4.
      The begin/end Contact are created to use exactly the area of the
    extension. Otherwise there were overspill when the size of the
    extension is greater than the width of the path. Also need to do
    a sligth shift if the extension is an odd number of foundry grid.
      This fix the offgrid problems.
This commit is contained in:
Jean-Paul Chaput 2021-05-25 15:08:57 +02:00
parent 39231d5191
commit 5b6bc7c91b
1 changed files with 107 additions and 19 deletions

View File

@ -27,6 +27,7 @@
using namespace std; using namespace std;
#include "vlsisapd/configuration/Configuration.h" #include "vlsisapd/configuration/Configuration.h"
#include "hurricane/DebugSession.h"
#include "hurricane/Warning.h" #include "hurricane/Warning.h"
#include "hurricane/DataBase.h" #include "hurricane/DataBase.h"
#include "hurricane/Technology.h" #include "hurricane/Technology.h"
@ -203,6 +204,8 @@ namespace {
void readUnits (); void readUnits ();
void readLayer (); void readLayer ();
void readWidth (); void readWidth ();
void readBgnextn ();
void readEndextn ();
void readPathtype (); void readPathtype ();
void readStrname (); void readStrname ();
void readXy (); void readXy ();
@ -381,8 +384,8 @@ namespace {
case BOX: readDummy( false ); break; case BOX: readDummy( false ); break;
case BOXTYPE: readDummy( false ); break; case BOXTYPE: readDummy( false ); break;
case PLEX: readDummy( false ); break; case PLEX: readDummy( false ); break;
case BGNEXTN: readDummy( false ); break; case BGNEXTN: readBgnextn(); break;
case ENDEXTN: readDummy( false ); break; case ENDEXTN: readEndextn(); break;
case TAPENUM: readDummy( false ); break; case TAPENUM: readDummy( false ); break;
case TAPECODE: readDummy( false ); break; case TAPECODE: readDummy( false ); break;
case STRCLASS: readDummy( false ); break; case STRCLASS: readDummy( false ); break;
@ -543,6 +546,14 @@ namespace {
{ _int32s.push_back( _readInt<uint32_t>() ); } { _int32s.push_back( _readInt<uint32_t>() ); }
void GdsRecord::readBgnextn ()
{ _int32s.push_back( _readInt<uint32_t>() ); }
void GdsRecord::readEndextn ()
{ _int32s.push_back( _readInt<uint32_t>() ); }
void GdsRecord::readPathtype () void GdsRecord::readPathtype ()
{ _int16s.push_back( _readInt<uint16_t>() ); } { _int16s.push_back( _readInt<uint16_t>() ); }
@ -650,7 +661,11 @@ namespace {
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 xyToPath ( uint16_t pathtype
, const Layer*
, DbU::Unit width
, DbU::Unit bgnextn
, DbU::Unit endextn );
void makeInstances (); void makeInstances ();
void makeExternals (); void makeExternals ();
Net* fusedNet (); Net* fusedNet ();
@ -1077,6 +1092,8 @@ namespace {
const Layer* layer = NULL; const Layer* layer = NULL;
DbU::Unit width = 0; DbU::Unit width = 0;
uint16_t pathtype = 0; uint16_t pathtype = 0;
DbU::Unit bgnextn = 0;
DbU::Unit endextn = 0;
if (_record.isELFLAGS()) { _stream >> _record; } if (_record.isELFLAGS()) { _stream >> _record; }
if (_record.isPLEX ()) { _stream >> _record; } if (_record.isPLEX ()) { _stream >> _record; }
@ -1114,11 +1131,17 @@ namespace {
width = _record.getInt32s()[0] * _scale; width = _record.getInt32s()[0] * _scale;
_stream >> _record; _stream >> _record;
} }
if (_record.isBGNEXTN ()) { _stream >> _record; } if (_record.isBGNEXTN ()) {
if (_record.isENDEXTN ()) { _stream >> _record; } bgnextn = _record.getInt32s()[0] * _scale;
_stream >> _record;
}
if (_record.isENDEXTN ()) {
endextn = _record.getInt32s()[0] * _scale;
_stream >> _record;
}
if (_record.isXY()) { if (_record.isXY()) {
if (_cell and layer) xyToPath( pathtype, layer, width ); if (_cell and layer) xyToPath( pathtype, layer, width, bgnextn, endextn );
} else { } else {
_validSyntax = false; _validSyntax = false;
cdebug_tabw(101,-1); cdebug_tabw(101,-1);
@ -1409,11 +1432,17 @@ namespace {
} }
void GdsStream::xyToPath ( uint16_t pathtype, const Layer* layer, DbU::Unit width ) void GdsStream::xyToPath ( uint16_t pathtype
, const Layer* layer
, DbU::Unit width
, DbU::Unit bgnextn
, DbU::Unit endextn )
{ {
cdebug_log(101,0) << "GdsStream::xyToPath(): pathtype=" << pathtype cdebug_log(101,0) << "GdsStream::xyToPath(): pathtype=" << pathtype
<< " layer=" << layer->getName() << " layer=" << layer->getName()
<< " width=" << DbU::getValueString(width) << endl; << " width=" << DbU::getValueString(width)
<< " bgnextn=" << DbU::getValueString(bgnextn)
<< " endextn=" << DbU::getValueString(endextn) << endl;
vector<Point> points; vector<Point> points;
vector<int32_t> coordinates = _record.getInt32s(); vector<int32_t> coordinates = _record.getInt32s();
@ -1428,7 +1457,10 @@ namespace {
Net* net = fusedNet(); Net* net = fusedNet();
cdebug_log(101,0) << "Points" << endl;
cdebug_log(101,0) << " 0 | " << points[0] << endl;
for ( size_t i=1 ; i<points.size() ; ++i ) { for ( size_t i=1 ; i<points.size() ; ++i ) {
cdebug_log(101,0) << " " << i << " | " << points[i] << endl;
if ( (points[i-1].getX() != points[i].getX()) if ( (points[i-1].getX() != points[i].getX())
and (points[i-1].getY() != points[i].getY()) ) { and (points[i-1].getY() != points[i].getY()) ) {
cerr << Error( "GdsStream::xyToPath(): Non-rectilinear paths are not supporteds (skipped)." cerr << Error( "GdsStream::xyToPath(): Non-rectilinear paths are not supporteds (skipped)."
@ -1437,35 +1469,86 @@ namespace {
} }
} }
DbU::Unit twoGrid = DbU::fromGrid( 2 );
DbU::Unit xadjust = 0;
DbU::Unit yadjust = 0;
DbU::Unit hWidthCap = width; DbU::Unit hWidthCap = width;
DbU::Unit vWidthCap = width; DbU::Unit vWidthCap = width;
if (pathtype == 0) { if (pathtype == 0) {
if (points[0].getX() == points[1].getX()) vWidthCap = 0; if (points[0].getX() == points[1].getX()) vWidthCap = 0;
else hWidthCap = 0; else hWidthCap = 0;
} }
if (pathtype == 4) {
if (not (bgnextn % twoGrid)) twoGrid = 0;
else {
cdebug_log(101,0) << "bgnextn is an odd number of grid." << endl;
twoGrid >>= 1;
}
if (points[0].getX() == points[1].getX()) {
hWidthCap = width;
vWidthCap = bgnextn + twoGrid;
yadjust = -vWidthCap/2 + twoGrid;
if (points[0].getY() > points[1].getY())
yadjust = -yadjust;
} else {
hWidthCap = bgnextn + twoGrid;
vWidthCap = width;
xadjust = -hWidthCap/2 + twoGrid;
if (points[0].getX() > points[1].getX())
xadjust = -xadjust;
}
}
Contact* source = Contact::create( net Contact* source = Contact::create( net
, layer , layer
, points[0].getX() , points[0].getX() + xadjust
, points[0].getY() , points[0].getY() + yadjust
, hWidthCap , hWidthCap
, vWidthCap ); , vWidthCap );
hWidthCap = width; cdebug_log(101,0) << "+ " << source << endl;
vWidthCap = width;
Contact* target = NULL; Contact* target = NULL;
Segment* segment = NULL; Segment* segment = NULL;
for ( size_t i=1 ; i<points.size() ; ++i ) { for ( size_t i=1 ; i<points.size() ; ++i ) {
hWidthCap = width;
vWidthCap = width;
xadjust = 0;
yadjust = 0;
if (i == points.size()-1) { if (i == points.size()-1) {
if (pathtype == 0) { if (pathtype == 0) {
if (points[0].getX() == points[1].getX()) vWidthCap = 0; if (points[i].getX() == points[i-1].getX()) vWidthCap = 0;
else hWidthCap = 0; else hWidthCap = 0;
} }
if (pathtype == 4) {
twoGrid = DbU::fromGrid( 2 );
if (not (endextn % twoGrid)) twoGrid = 0;
else {
cdebug_log(101,0) << "endextn is an odd number of grid." << endl;
twoGrid >>= 1;
}
if (points[i-1].getX() == points[i].getX()) {
hWidthCap = width;
vWidthCap = endextn + twoGrid;
yadjust = vWidthCap/2 - twoGrid;
if (points[i-1].getY() > points[i].getY())
yadjust = -yadjust;
} else {
cdebug_log(101,0) << "endextn=" << DbU::getValueString(endextn)
<< " twoGrid=" << DbU::getValueString(twoGrid) << endl;
hWidthCap = endextn + twoGrid;
vWidthCap = width;
xadjust = hWidthCap/2 - twoGrid;
if (points[i-1].getX() > points[i].getX())
xadjust = -xadjust;
cdebug_log(101,0) << "xadjust=" << DbU::getValueString(xadjust) << endl;
}
}
} }
target = Contact::create( net target = Contact::create( net
, layer , layer
, points[i].getX() , points[i].getX() + xadjust
, points[i].getY() , points[i].getY() + yadjust
, hWidthCap , hWidthCap
, vWidthCap ); , vWidthCap );
cdebug_log(101,0) << "+ " << target << endl;
if (points[i-1].getY() == points[i].getY()) { if (points[i-1].getY() == points[i].getY()) {
segment = Horizontal::create( source segment = Horizontal::create( source
, target , target
@ -1481,6 +1564,7 @@ namespace {
, width , width
, 0, 0 ); , 0, 0 );
} }
cdebug_log(101,0) << "| " << segment << endl;
if (not net->isAutomatic()) NetExternalComponents::setExternal( segment ); if (not net->isAutomatic()) NetExternalComponents::setExternal( segment );
source = target; source = target;
} }
@ -1620,7 +1704,9 @@ namespace CRL {
bool Gds::load ( Library* library, string gdsPath ) bool Gds::load ( Library* library, string gdsPath )
{ {
//DebugSession::open( 101, 110 );
UpdateSession::open(); UpdateSession::open();
Contact::disableCheckMinSize();
GdsStream gstream ( gdsPath ); GdsStream gstream ( gdsPath );
@ -1630,7 +1716,9 @@ namespace CRL {
, gdsPath.c_str() , gdsPath.c_str()
) << endl; ) << endl;
Contact::enableCheckMinSize();
UpdateSession::close(); UpdateSession::close();
//DebugSession::close();
return true; return true;
} }