Stricter layer management in the GDS parser.

* In CRL::GdsStream::_staticInit(), all the layers where added to the
    translation table, whether or not they where configured for the
    GDS stream. So the non GDS configured layers got a GDS layer
    id of 0 and were using this case. Either overwriting the legit
    layer or creating a new one while it should have been invalid.
      Now we check for the hasGds() predicate of the layers.
* In CRL::GdsStream, add a new option to tell that, layer id 0,
    if undefined, may be used as the definition of the boudary of
    the cell (abutment box).
* In CRL::PyGds, now also export the flags to the Python interface.
This commit is contained in:
Jean-Paul Chaput 2022-10-27 19:45:20 +02:00
parent 5a07033172
commit 81920c622e
4 changed files with 126 additions and 40 deletions

View File

@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2018-2018, All Rights Reserved // Copyright (c) Sorbonne Université 2018-2022, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
@ -13,11 +13,8 @@
// | C++ Header : "./crlcore/Gds.h" | // | C++ Header : "./crlcore/Gds.h" |
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#pragma once
#ifndef CRL_GDS_H #include <string>
#define CRL_GDS_H
#include <string>
namespace Hurricane { namespace Hurricane {
@ -33,12 +30,13 @@ namespace CRL {
class Gds { class Gds {
public:
static const uint32_t NoGdsPrefix = (1<<0);
static const uint32_t Layer_0_IsBoundary = (1<<1);
public: public:
static bool save ( Cell* ); static bool save ( Cell* );
static bool load ( Library*, std::string gdsPath ); static bool load ( Library*, std::string gdsPath, uint32_t flags=0 );
}; };
} // CRL namespace. } // CRL namespace.
# endif

View File

@ -648,7 +648,9 @@ namespace {
static const Layer* gdsToLayer ( uint16_t gdsLayer, uint16_t datatype ); static const Layer* gdsToLayer ( uint16_t gdsLayer, uint16_t datatype );
public: public:
static void _staticInit (); static void _staticInit ();
GdsStream ( string gdsPath ); GdsStream ( string gdsPath, uint32_t flags );
inline bool useGdsPrefix () const;
inline bool useLayer0AsBoundary () const;
inline bool isValidSyntax () const; inline bool isValidSyntax () const;
bool misplacedRecord (); bool misplacedRecord ();
inline void resetStrans (); inline void resetStrans ();
@ -666,6 +668,7 @@ namespace {
bool readTextbody ( const Layer* ); bool readTextbody ( const Layer* );
bool readStrans (); bool readStrans ();
bool readProperty (); bool readProperty ();
void xyToAbutmentBox ();
void xyToComponent ( const Layer* ); void xyToComponent ( const Layer* );
void xyToPath ( uint16_t pathtype void xyToPath ( uint16_t pathtype
, const Layer* , const Layer*
@ -693,6 +696,7 @@ namespace {
private: private:
static map<uint32_t,const Layer*> _gdsLayerTable; static map<uint32_t,const Layer*> _gdsLayerTable;
vector<DelayedInstance> _delayedInstances; vector<DelayedInstance> _delayedInstances;
uint32_t _flags;
string _gdsPath; string _gdsPath;
ifstream _stream; ifstream _stream;
GdsRecord _record; GdsRecord _record;
@ -730,8 +734,10 @@ namespace {
void GdsStream::_staticInit () void GdsStream::_staticInit ()
{ {
for ( const BasicLayer* layer : DataBase::getDB()->getTechnology()->getBasicLayers() ) { for ( const BasicLayer* layer : DataBase::getDB()->getTechnology()->getBasicLayers() ) {
uint32_t gdsNumber = (layer->getGds2Layer() << 16) + layer->getGds2Datatype(); if (layer->hasGds()) {
_gdsLayerTable[gdsNumber] = layer; uint32_t gdsNumber = (layer->getGds2Layer() << 16) + layer->getGds2Datatype();
_gdsLayerTable[gdsNumber] = layer;
}
} }
} }
@ -749,11 +755,14 @@ namespace {
} }
inline bool GdsStream::isValidSyntax () const { return _validSyntax; } inline bool GdsStream::isValidSyntax () const { return _validSyntax; }
inline bool GdsStream::useGdsPrefix () const { return not(_flags & Gds::NoGdsPrefix); }
inline bool GdsStream::useLayer0AsBoundary () const { return (_flags & Gds::Layer_0_IsBoundary); }
GdsStream::GdsStream ( string gdsPath ) GdsStream::GdsStream ( string gdsPath, uint32_t flags )
: _delayedInstances() : _delayedInstances()
, _flags (flags)
, _gdsPath (gdsPath) , _gdsPath (gdsPath)
, _stream () , _stream ()
, _record () , _record ()
@ -890,11 +899,12 @@ namespace {
if (_record.isSTRNAME()) { if (_record.isSTRNAME()) {
if (_library) { if (_library) {
string cellName = "gds_" + _record.getName(); string cellName = _record.getName();
if (useGdsPrefix()) cellName.insert( 0, "gds_" );
_cell = _library->getCell( cellName ); _cell = _library->getCell( cellName );
if (not _cell) { if (not _cell) {
cparanoid << Warning( "GdsStream::readStructure(): No Cell named \"gds_%s\" in Library \"%s\" (created)." cparanoid << Warning( "GdsStream::readStructure(): No Cell named \"%s\" in Library \"%s\" (created)."
, _record.getName().c_str() , cellName.c_str()
, getString(_library).c_str() , getString(_library).c_str()
) << endl; ) << endl;
_cell = Cell::create( _library, cellName ); _cell = Cell::create( _library, cellName );
@ -969,11 +979,13 @@ namespace {
} }
const Layer* layer = gdsToLayer( gdsLayer, gdsDatatype ); const Layer* layer = gdsToLayer( gdsLayer, gdsDatatype );
cdebug_log(101,0) << "Layer id+datatype:" << gdsLayer << "+" << gdsDatatype << " " << layer << endl; if ((gdsLayer == 0) and not useLayer0AsBoundary()) {
if (not layer) { cdebug_log(101,0) << "Layer id+datatype:" << gdsLayer << "+" << gdsDatatype << " " << layer << endl;
cerr << Error( "GdsStream::readLayerAndDatatype(): No BasicLayer id:%d+%d in GDS conversion table (skipped)." if (not layer) {
, gdsLayer, gdsDatatype cerr << Error( "GdsStream::readLayerAndDatatype(): No BasicLayer id:%d+%d in GDS conversion table (skipped)."
) << endl; , gdsLayer, gdsDatatype
) << endl;
}
} }
return layer; return layer;
@ -1105,8 +1117,13 @@ namespace {
} }
if (_record.isXY()) { if (_record.isXY()) {
if (_cell and layer) xyToComponent( layer ); if (_cell and layer)
else _stream >> _record; xyToComponent( layer );
else if (not layer and useLayer0AsBoundary()) {
xyToAbutmentBox();
}
else
_stream >> _record;
} else { } else {
_validSyntax = false; _validSyntax = false;
cdebug_tabw(101,-1); cdebug_tabw(101,-1);
@ -1240,8 +1257,9 @@ namespace {
// << " XR:" << _xReflection << " angle:" << _angle // << " XR:" << _xReflection << " angle:" << _angle
// << " " << Transformation(xpos,ypos,orient) // << " " << Transformation(xpos,ypos,orient)
// << " in " << _cell << endl; // << " in " << _cell << endl;
if (useGdsPrefix()) masterName.insert( 0, "gds_" );
_delayedInstances.push_back( DelayedInstance( _cell _delayedInstances.push_back( DelayedInstance( _cell
, "gds_" + masterName , masterName
, Transformation(xpos,ypos,orient)) ); , Transformation(xpos,ypos,orient)) );
} }
@ -1379,6 +1397,70 @@ namespace {
} }
void GdsStream::xyToAbutmentBox ()
{
DbU::Unit oneGrid = DbU::fromGrid( 1 );
vector<Point> points;
vector<int32_t> coordinates = _record.getInt32s();
vector<size_t> offgrids;
for ( size_t i=0 ; i<coordinates.size() ; i += 2 ) {
points.push_back( Point( coordinates[i ]*_scale
, coordinates[i+1]*_scale ) );
if ( (points.back().getX() % oneGrid) or (points.back().getX() % oneGrid) ) {
offgrids.push_back( i );
}
}
if (not offgrids.empty()) {
size_t offgrid = 0;
ostringstream m;
for ( size_t i=0 ; i<points.size() ; ++i ) {
if (i) m << "\n";
m << " | " << points[i];
if ((offgrid < offgrids.size()) and (i == offgrid)) {
m << " offgrid";
++offgrid;
}
}
cerr << Error( "GdsStream::xyToComponent(): Offgrid points on abutment box (foundry grid: %s).\n"
"%s"
, DbU::getValueString(oneGrid).c_str()
, m.str().c_str() ) << endl;
}
_stream >> _record;
if ( (_record.getType() == GdsRecord::ENDEL)
or (_record.getType() == GdsRecord::STRING)) {
//_stream >> _record;
} else {
_validSyntax = false;
return;
}
if (_record.getType() == GdsRecord::TEXT) {
_stream >> _record;
readText();
} else
_skipENDEL = true;
bool isRectilinear = true;
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()) ) {
isRectilinear = false;
break;
}
}
if (isRectilinear and (points.size() == 5)) {
Box ab;
for ( Point p : points ) ab.merge( p );
_cell->setAbutmentBox( ab );
cdebug_log(101,0) << "| Abutment box =" << ab << endl;
}
}
void GdsStream::xyToComponent ( const Layer* layer ) void GdsStream::xyToComponent ( const Layer* layer )
{ {
DbU::Unit oneGrid = DbU::fromGrid( 1 ); DbU::Unit oneGrid = DbU::fromGrid( 1 );
@ -1651,7 +1733,7 @@ namespace {
for ( const PinPoint& ref : netPins.second ) { for ( const PinPoint& ref : netPins.second ) {
const Layer* layer = ref._layer; const Layer* layer = ref._layer;
string layerName = getString( layer->getName() ); string layerName = getString( layer->getName() );
if (layerName.substr(layerName.size()-4) == ".pin") { if ((layerName.size() > 4) and layerName.substr(layerName.size()-4) == ".pin") {
layer = DataBase::getDB()->getTechnology()->getLayer( layerName.substr(0,layerName.size()-4) ); layer = DataBase::getDB()->getTechnology()->getLayer( layerName.substr(0,layerName.size()-4) );
} }
cdebug_log(101,0) << "Looking for components of \"" << net->getName() cdebug_log(101,0) << "Looking for components of \"" << net->getName()
@ -1737,13 +1819,13 @@ namespace CRL {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "CRL::Gds". // Class : "CRL::Gds".
bool Gds::load ( Library* library, string gdsPath ) bool Gds::load ( Library* library, string gdsPath, uint32_t flags )
{ {
//DebugSession::open( 101, 110 ); //DebugSession::open( 101, 110 );
UpdateSession::open(); UpdateSession::open();
Contact::disableCheckMinSize(); Contact::disableCheckMinSize();
GdsStream gstream ( gdsPath ); GdsStream gstream ( gdsPath, flags );
if (not gstream.read( library )) if (not gstream.read( library ))
cerr << Error( "Gds::load(): An error occurred while reading GDSII stream\n" cerr << Error( "Gds::load(): An error occurred while reading GDSII stream\n"

View File

@ -87,13 +87,14 @@ extern "C" {
{ {
cdebug_log(30,0) << "PyGds_load()" << endl; cdebug_log(30,0) << "PyGds_load()" << endl;
char* path = NULL; char* path = NULL;
uint32_t flags = 0;
HTRY HTRY
PyObject* pyLibrary = NULL; PyObject* pyLibrary = NULL;
if (PyArg_ParseTuple( args, "Os:Gds.load", &pyLibrary, &path )) { if (PyArg_ParseTuple( args, "Os|I:Gds.load", &pyLibrary, &path, &flags )) {
if (IsPyLibrary(pyLibrary)) { if (IsPyLibrary(pyLibrary)) {
Gds::load( PYLIBRARY_O(pyLibrary), string(path) ); Gds::load( PYLIBRARY_O(pyLibrary), string(path), flags );
} else { } else {
PyErr_SetString( ConstructorError, "Gds.load(): Bad parameter type (not a Library)." ); PyErr_SetString( ConstructorError, "Gds.load(): Bad parameter type (not a Library)." );
return NULL; return NULL;
@ -135,6 +136,14 @@ extern "C" {
PyTypeObjectDefinitionsOfModule(CRL,Gds) PyTypeObjectDefinitionsOfModule(CRL,Gds)
extern void PyGds_postModuleInit ()
{
PyObject* constant;
LoadObjectConstant(PyTypeGds.tp_dict,Gds::NoGdsPrefix ,"NoGdsPrefix");
LoadObjectConstant(PyTypeGds.tp_dict,Gds::Layer_0_IsBoundary,"Layer_0_IsBoundary");
}
#endif // End of Shared Library Code Part. #endif // End of Shared Library Code Part.
} // extern "C". } // extern "C".

View File

@ -2,22 +2,20 @@
// -*- C++ -*- // -*- C++ -*-
// //
// This file is part of the Coriolis Software. // This file is part of the Coriolis Software.
// Copyright (c) UPMC 2018-2018, All Rights Reserved // Copyright (c) Sorbonne Université 2018-2022, All Rights Reserved
// //
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
// | C O R I O L I S | // | C O R I O L I S |
// | Alliance / Hurricane Interface | // | Alliance / Hurricane Interface |
// | | // | |
// | Author : Jean-Paul CHAPUT | // | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | // | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== | // | =============================================================== |
// | C++ Header : "./crlcore/PyGds.h" | // | C++ Header : "./crlcore/PyGds.h" |
// +-----------------------------------------------------------------+ // +-----------------------------------------------------------------+
#ifndef CRL_PY_GDS_H #pragma once
#define CRL_PY_GDS_H
#include "hurricane/isobar/PyHurricane.h" #include "hurricane/isobar/PyHurricane.h"
#include "crlcore/Gds.h" #include "crlcore/Gds.h"
@ -41,7 +39,8 @@ extern "C" {
extern PyTypeObject PyTypeGds; extern PyTypeObject PyTypeGds;
extern PyMethodDef PyGds_Methods[]; extern PyMethodDef PyGds_Methods[];
extern void PyGds_LinkPyType(); extern void PyGds_LinkPyType ();
extern void PyGds_postModuleInit ();
#define IsPyGds(v) ( (v)->ob_type == &PyTypeGds ) #define IsPyGds(v) ( (v)->ob_type == &PyTypeGds )
@ -51,5 +50,3 @@ extern "C" {
} // extern "C". } // extern "C".
} // Hurricane namespace. } // Hurricane namespace.
#endif // CRL_PY_GDS_H