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:
parent
5a07033172
commit
81920c622e
|
@ -1,7 +1,7 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// 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 |
|
||||
|
@ -13,11 +13,8 @@
|
|||
// | C++ Header : "./crlcore/Gds.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#ifndef CRL_GDS_H
|
||||
#define CRL_GDS_H
|
||||
|
||||
#include <string>
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace Hurricane {
|
||||
|
@ -33,12 +30,13 @@ namespace CRL {
|
|||
|
||||
|
||||
class Gds {
|
||||
public:
|
||||
static const uint32_t NoGdsPrefix = (1<<0);
|
||||
static const uint32_t Layer_0_IsBoundary = (1<<1);
|
||||
public:
|
||||
static bool save ( Cell* );
|
||||
static bool load ( Library*, std::string gdsPath );
|
||||
static bool load ( Library*, std::string gdsPath, uint32_t flags=0 );
|
||||
};
|
||||
|
||||
|
||||
} // CRL namespace.
|
||||
|
||||
# endif
|
||||
|
|
|
@ -648,7 +648,9 @@ namespace {
|
|||
static const Layer* gdsToLayer ( uint16_t gdsLayer, uint16_t datatype );
|
||||
public:
|
||||
static void _staticInit ();
|
||||
GdsStream ( string gdsPath );
|
||||
GdsStream ( string gdsPath, uint32_t flags );
|
||||
inline bool useGdsPrefix () const;
|
||||
inline bool useLayer0AsBoundary () const;
|
||||
inline bool isValidSyntax () const;
|
||||
bool misplacedRecord ();
|
||||
inline void resetStrans ();
|
||||
|
@ -666,6 +668,7 @@ namespace {
|
|||
bool readTextbody ( const Layer* );
|
||||
bool readStrans ();
|
||||
bool readProperty ();
|
||||
void xyToAbutmentBox ();
|
||||
void xyToComponent ( const Layer* );
|
||||
void xyToPath ( uint16_t pathtype
|
||||
, const Layer*
|
||||
|
@ -693,6 +696,7 @@ namespace {
|
|||
private:
|
||||
static map<uint32_t,const Layer*> _gdsLayerTable;
|
||||
vector<DelayedInstance> _delayedInstances;
|
||||
uint32_t _flags;
|
||||
string _gdsPath;
|
||||
ifstream _stream;
|
||||
GdsRecord _record;
|
||||
|
@ -730,8 +734,10 @@ namespace {
|
|||
void GdsStream::_staticInit ()
|
||||
{
|
||||
for ( const BasicLayer* layer : DataBase::getDB()->getTechnology()->getBasicLayers() ) {
|
||||
uint32_t gdsNumber = (layer->getGds2Layer() << 16) + layer->getGds2Datatype();
|
||||
_gdsLayerTable[gdsNumber] = layer;
|
||||
if (layer->hasGds()) {
|
||||
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()
|
||||
, _flags (flags)
|
||||
, _gdsPath (gdsPath)
|
||||
, _stream ()
|
||||
, _record ()
|
||||
|
@ -890,11 +899,12 @@ namespace {
|
|||
|
||||
if (_record.isSTRNAME()) {
|
||||
if (_library) {
|
||||
string cellName = "gds_" + _record.getName();
|
||||
string cellName = _record.getName();
|
||||
if (useGdsPrefix()) cellName.insert( 0, "gds_" );
|
||||
_cell = _library->getCell( cellName );
|
||||
if (not _cell) {
|
||||
cparanoid << Warning( "GdsStream::readStructure(): No Cell named \"gds_%s\" in Library \"%s\" (created)."
|
||||
, _record.getName().c_str()
|
||||
cparanoid << Warning( "GdsStream::readStructure(): No Cell named \"%s\" in Library \"%s\" (created)."
|
||||
, cellName.c_str()
|
||||
, getString(_library).c_str()
|
||||
) << endl;
|
||||
_cell = Cell::create( _library, cellName );
|
||||
|
@ -969,11 +979,13 @@ namespace {
|
|||
}
|
||||
|
||||
const Layer* layer = gdsToLayer( gdsLayer, gdsDatatype );
|
||||
cdebug_log(101,0) << "Layer id+datatype:" << gdsLayer << "+" << gdsDatatype << " " << layer << endl;
|
||||
if (not layer) {
|
||||
cerr << Error( "GdsStream::readLayerAndDatatype(): No BasicLayer id:%d+%d in GDS conversion table (skipped)."
|
||||
, gdsLayer, gdsDatatype
|
||||
) << endl;
|
||||
if ((gdsLayer == 0) and not useLayer0AsBoundary()) {
|
||||
cdebug_log(101,0) << "Layer id+datatype:" << gdsLayer << "+" << gdsDatatype << " " << layer << endl;
|
||||
if (not layer) {
|
||||
cerr << Error( "GdsStream::readLayerAndDatatype(): No BasicLayer id:%d+%d in GDS conversion table (skipped)."
|
||||
, gdsLayer, gdsDatatype
|
||||
) << endl;
|
||||
}
|
||||
}
|
||||
|
||||
return layer;
|
||||
|
@ -1105,8 +1117,13 @@ namespace {
|
|||
}
|
||||
|
||||
if (_record.isXY()) {
|
||||
if (_cell and layer) xyToComponent( layer );
|
||||
else _stream >> _record;
|
||||
if (_cell and layer)
|
||||
xyToComponent( layer );
|
||||
else if (not layer and useLayer0AsBoundary()) {
|
||||
xyToAbutmentBox();
|
||||
}
|
||||
else
|
||||
_stream >> _record;
|
||||
} else {
|
||||
_validSyntax = false;
|
||||
cdebug_tabw(101,-1);
|
||||
|
@ -1240,8 +1257,9 @@ namespace {
|
|||
// << " XR:" << _xReflection << " angle:" << _angle
|
||||
// << " " << Transformation(xpos,ypos,orient)
|
||||
// << " in " << _cell << endl;
|
||||
if (useGdsPrefix()) masterName.insert( 0, "gds_" );
|
||||
_delayedInstances.push_back( DelayedInstance( _cell
|
||||
, "gds_" + masterName
|
||||
, masterName
|
||||
, 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 )
|
||||
{
|
||||
DbU::Unit oneGrid = DbU::fromGrid( 1 );
|
||||
|
@ -1651,7 +1733,7 @@ namespace {
|
|||
for ( const PinPoint& ref : netPins.second ) {
|
||||
const Layer* layer = ref._layer;
|
||||
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) );
|
||||
}
|
||||
cdebug_log(101,0) << "Looking for components of \"" << net->getName()
|
||||
|
@ -1737,13 +1819,13 @@ namespace CRL {
|
|||
// -------------------------------------------------------------------
|
||||
// Class : "CRL::Gds".
|
||||
|
||||
bool Gds::load ( Library* library, string gdsPath )
|
||||
bool Gds::load ( Library* library, string gdsPath, uint32_t flags )
|
||||
{
|
||||
//DebugSession::open( 101, 110 );
|
||||
UpdateSession::open();
|
||||
Contact::disableCheckMinSize();
|
||||
|
||||
GdsStream gstream ( gdsPath );
|
||||
GdsStream gstream ( gdsPath, flags );
|
||||
|
||||
if (not gstream.read( library ))
|
||||
cerr << Error( "Gds::load(): An error occurred while reading GDSII stream\n"
|
||||
|
|
|
@ -87,13 +87,14 @@ extern "C" {
|
|||
{
|
||||
cdebug_log(30,0) << "PyGds_load()" << endl;
|
||||
|
||||
char* path = NULL;
|
||||
char* path = NULL;
|
||||
uint32_t flags = 0;
|
||||
|
||||
HTRY
|
||||
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)) {
|
||||
Gds::load( PYLIBRARY_O(pyLibrary), string(path) );
|
||||
Gds::load( PYLIBRARY_O(pyLibrary), string(path), flags );
|
||||
} else {
|
||||
PyErr_SetString( ConstructorError, "Gds.load(): Bad parameter type (not a Library)." );
|
||||
return NULL;
|
||||
|
@ -135,6 +136,14 @@ extern "C" {
|
|||
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.
|
||||
|
||||
} // extern "C".
|
||||
|
|
|
@ -2,22 +2,20 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// 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 |
|
||||
// | Alliance / Hurricane Interface |
|
||||
// | |
|
||||
// | 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
|
||||
#define CRL_PY_GDS_H
|
||||
|
||||
#pragma once
|
||||
#include "hurricane/isobar/PyHurricane.h"
|
||||
#include "crlcore/Gds.h"
|
||||
|
||||
|
@ -41,7 +39,8 @@ extern "C" {
|
|||
extern PyTypeObject PyTypeGds;
|
||||
extern PyMethodDef PyGds_Methods[];
|
||||
|
||||
extern void PyGds_LinkPyType();
|
||||
extern void PyGds_LinkPyType ();
|
||||
extern void PyGds_postModuleInit ();
|
||||
|
||||
|
||||
#define IsPyGds(v) ( (v)->ob_type == &PyTypeGds )
|
||||
|
@ -51,5 +50,3 @@ extern "C" {
|
|||
} // extern "C".
|
||||
|
||||
} // Hurricane namespace.
|
||||
|
||||
#endif // CRL_PY_GDS_H
|
||||
|
|
Loading…
Reference in New Issue