Added support for GF180MCU, part 1.

* New: In LefImport::LefParser, add support for LEF Polygons that are
    translated into Hurricane Rectilinears.
* Change: In LefImport::setMergeLibrary(), the default behavior for the
    LEF parser is to create a new separate library under LEF/<lib_name>
    for each file. But if the various cells are put each one in it's own
    cell, this is suitable. So we can now set a library beforehand into
    which they will be all put.
* New: in CRL/technos.node180.gf180mcu, configuration files for the
    GF180MCU open PDK.
* New: in cumulus/designflow.technos, added a setupGF180MCU_GF() to
    initialize the GF PDK.
This commit is contained in:
Jean-Paul Chaput 2023-06-22 14:13:19 +02:00 committed by Gabriel Gouvine
parent 06ea3d6e09
commit 76e9da0b64
4 changed files with 121 additions and 4 deletions

View File

@ -29,8 +29,9 @@ namespace CRL {
class LefImport { class LefImport {
public: public:
static void reset (); static void reset ();
static Hurricane::Library* load ( std::string fileName ); static Hurricane::Library* load ( std::string fileName );
static void setMergeLibrary ( Hurricane::Library* );
}; };

View File

@ -33,6 +33,7 @@
#include "hurricane/Contact.h" #include "hurricane/Contact.h"
#include "hurricane/Horizontal.h" #include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h" #include "hurricane/Vertical.h"
#include "hurricane/Rectilinear.h"
#include "hurricane/Cell.h" #include "hurricane/Cell.h"
#include "hurricane/Library.h" #include "hurricane/Library.h"
#include "hurricane/UpdateSession.h" #include "hurricane/UpdateSession.h"
@ -71,6 +72,7 @@ namespace {
class LefParser { class LefParser {
public: public:
static void setMergeLibrary ( Library* );
static DbU::Unit fromLefUnits ( int ); static DbU::Unit fromLefUnits ( int );
static Layer* getLayer ( string ); static Layer* getLayer ( string );
static void addLayer ( string, Layer* ); static void addLayer ( string, Layer* );
@ -121,6 +123,7 @@ namespace {
void _pinStdPostProcess (); void _pinStdPostProcess ();
void _pinPadPostProcess (); void _pinPadPostProcess ();
private: private:
static Library* _mergeLibrary;
string _file; string _file;
string _libraryName; string _libraryName;
Library* _library; Library* _library;
@ -174,11 +177,16 @@ namespace {
inline void LefParser::clearPinSegments () { _pinSegments.clear(); } inline void LefParser::clearPinSegments () { _pinSegments.clear(); }
Library* LefParser::_mergeLibrary = nullptr;
map<string,Layer*> LefParser::_layerLut; map<string,Layer*> LefParser::_layerLut;
DbU::Unit LefParser::_coreSiteX = 0; DbU::Unit LefParser::_coreSiteX = 0;
DbU::Unit LefParser::_coreSiteY = 0; DbU::Unit LefParser::_coreSiteY = 0;
void LefParser::setMergeLibrary ( Library* library )
{ _mergeLibrary = library; }
void LefParser::reset () void LefParser::reset ()
{ {
_layerLut.clear(); _layerLut.clear();
@ -272,6 +280,11 @@ namespace {
Library* LefParser::createLibrary () Library* LefParser::createLibrary ()
{ {
if (_mergeLibrary) {
_library = _mergeLibrary;
return _library;
}
DataBase* db = DataBase::getDB(); DataBase* db = DataBase::getDB();
Library* rootLibrary = db->getRootLibrary(); Library* rootLibrary = db->getRootLibrary();
if (not rootLibrary) rootLibrary = Library::create( db, "RootLibrary" ); if (not rootLibrary) rootLibrary = Library::create( db, "RootLibrary" );
@ -499,6 +512,17 @@ namespace {
} }
cdebug_log(100,0) << "| " << segment << endl; cdebug_log(100,0) << "| " << segment << endl;
} }
if (geoms->itemType(igeom) == lefiGeomPolygonE) {
lefiGeomPolygon* polygon = geoms->getPolygon(igeom);
vector<Point> points;
for ( int ipoint=0 ; ipoint<polygon->numPoints ; ++ipoint ) {
points.push_back( Point( parser->fromUnitsMicrons(polygon->x[ipoint])
, parser->fromUnitsMicrons(polygon->y[ipoint]) ));
}
Rectilinear::create( blockageNet, blockageLayer, points );
continue;
}
} }
return 0; return 0;
@ -647,6 +671,16 @@ namespace {
//cerr << " | " << segment << endl; //cerr << " | " << segment << endl;
continue; continue;
} }
if (geoms->itemType(igeom) == lefiGeomPolygonE) {
lefiGeomPolygon* polygon = geoms->getPolygon(igeom);
vector<Point> points;
for ( int ipoint=0 ; ipoint<polygon->numPoints ; ++ipoint ) {
points.push_back( Point( parser->fromUnitsMicrons(polygon->x[ipoint])
, parser->fromUnitsMicrons(polygon->y[ipoint]) ));
}
Rectilinear::create( net, layer, points );
continue;
}
if (geoms->itemType(igeom) == lefiGeomClassE) { if (geoms->itemType(igeom) == lefiGeomClassE) {
// Ignore CLASS <site>. Deduced from segments positions. // Ignore CLASS <site>. Deduced from segments positions.
continue; continue;
@ -963,4 +997,12 @@ namespace CRL {
} }
void LefImport::setMergeLibrary ( Library* library )
{
#if defined(HAVE_LEFDEF)
LefParser::setMergeLibrary( library );
#endif
}
} // End of CRL namespace. } // End of CRL namespace.

View File

@ -43,6 +43,8 @@ namespace CRL {
using Isobar::ParseTwoArg; using Isobar::ParseTwoArg;
using Isobar::__cs; using Isobar::__cs;
using Isobar::PyLibrary_Link; using Isobar::PyLibrary_Link;
using Isobar::PyTypeLibrary;
using Isobar::PyLibrary;
extern "C" { extern "C" {
@ -86,14 +88,37 @@ extern "C" {
} }
static PyObject* PyLefImport_setMergeLibrary ( PyObject*, PyObject* args )
{
cdebug_log(30,0) << "PyLefImport_setMergeLibrary()" << endl;
HTRY
PyObject* pyLibrary = NULL;
if (PyArg_ParseTuple( args, "O:LefImport.setMergeLibrary", &pyLibrary )) {
if (IsPyLibrary(pyLibrary)) {
LefImport::setMergeLibrary( PYLIBRARY_O(pyLibrary) );
} else {
PyErr_SetString( ConstructorError, "LefImport.setMergeLibrary(): Bad parameter type (not a Library)." );
return NULL;
}
} else {
PyErr_SetString( ConstructorError, "LefImport.setMergeLibrary(): Bad number of parameters." );
return NULL;
}
HCATCH
Py_RETURN_NONE;
}
// Standart Destroy (Attribute). // Standart Destroy (Attribute).
PyMethodDef PyLefImport_Methods[] = PyMethodDef PyLefImport_Methods[] =
{ { "load" , (PyCFunction)PyLefImport_load , METH_VARARGS|METH_STATIC { { "load" , (PyCFunction)PyLefImport_load , METH_VARARGS|METH_STATIC
, "Load a complete Cadence LEF library." } , "Load a complete Cadence LEF library." }
, { "reset" , (PyCFunction)PyLefImport_reset , METH_NOARGS|METH_STATIC , { "reset" , (PyCFunction)PyLefImport_reset , METH_NOARGS|METH_STATIC
, "Reset the Cadence LEF parser (clear technology)." } , "Reset the Cadence LEF parser (clear technology)." }
, { "setMergeLibrary" , (PyCFunction)PyLefImport_setMergeLibrary, METH_VARARGS|METH_STATIC
, "Merge into this library instead of creating a new one." }
//, { "destroy" , (PyCFunction)PyLefImport_destroy , METH_VARARGS //, { "destroy" , (PyCFunction)PyLefImport_destroy , METH_VARARGS
// , "Destroy the associated hurricane object. The python object remains." } // , "Destroy the associated hurricane object. The python object remains." }
, {NULL, NULL, 0, NULL} /* sentinel */ , {NULL, NULL, 0, NULL} /* sentinel */

View File

@ -304,3 +304,52 @@ def setupTSMC_c180_c4m ( checkToolkit=None, ndaTop=None ):
Yosys.setLiberty( liberty ) Yosys.setLiberty( liberty )
ShellEnv.CHECK_TOOLKIT = Where.checkToolkit.as_posix() ShellEnv.CHECK_TOOLKIT = Where.checkToolkit.as_posix()
def setupGF180MCU_GF ( checkToolkit=None, pdkTop=None ):
from .. import Cfg
from .. import Viewer
from .. import CRL
from ..helpers import setNdaTopDir, overlay, l, u, n
from .yosys import Yosys
if isinstance(pdkTop,str):
pdkTop = Path( pdkTop )
if not pdkTop:
print( '[ERROR] technos.setupGF180MCU_GF(): pdkTop directory has *not* been set.' )
if not pdkTop.is_dir():
print( '[ERROR] technos.setupSky130_c4m(): pdkTop directory do *not* exists:' )
print( ' "{}"'.format(pdkTop.as_posix()) )
Where( checkToolkit )
cellsTop = pdkTop / 'libraries' / 'gf180mcu_fd_sc_mcu9t5v0' / 'latest' / 'cells'
#liberty = pdkTop / 'libraries' / 'gf180mcu_fd_sc_mcu9t5v0' / 'latest' / 'liberty' / 'gf180mcu_fd_sc_mcu9t5v0__tt_025C_5v00.lib'
liberty = pdkTop / 'FULL.lib'
from coriolis.technos.node180.gf180mcu import techno
from coriolis.technos.node180.gf180mcu import mcu9t5v0
techno.setup()
mcu9t5v0.setup( cellsTop )
with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg:
cfg.misc.catchCore = False
cfg.misc.minTraceLevel = 12300
cfg.misc.maxTraceLevel = 12400
cfg.misc.info = False
cfg.misc.paranoid = False
cfg.misc.bug = False
cfg.misc.logMode = True
cfg.misc.verboseLevel1 = False
cfg.misc.verboseLevel2 = False
cfg.etesian.graphics = 2
cfg.anabatic.topRoutingLayer = 'm4'
cfg.katana.eventsLimit = 4000000
af = CRL.AllianceFramework.get()
#lg5 = af.getRoutingGauge( 'mcu9t' ).getLayerGauge( 5 )
#lg5.setType( CRL.RoutingLayerGauge.PowerSupply )
env = af.getEnvironment()
env.setCLOCK( '^sys_clk$|^ck|^jtag_tck$' )
Yosys.setLiberty( liberty )
ShellEnv.CHECK_TOOLKIT = Where.checkToolkit.as_posix()