Update of the DefExport (work in progress).

* New: In CRL::DefExport, checkStatus() has a second argument to display
    a more comprehensive error message.
      Applied throughout all the DEF callbacks.
* Bug: In CRL::DefExport, the UNIT statement and associated toDefUnits()
    functions where wrong. Now always use a UNITS of 1000 in microns.
    Then toDefUnits() converts DbU into microns and multiply by 1000.
* Change: In CRL::defExport::_netCbk(), enable the net name renaming
    only when the ProtectNetNames flag is set.
* New: In CRL::PyDefExport, also export the flag values to Python.
This commit is contained in:
Jean-Paul Chaput 2022-10-27 19:47:17 +02:00
parent 775b6bf1fc
commit dbfcfae1e8
5 changed files with 100 additions and 88 deletions

View File

@ -2,31 +2,20 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved
// Copyright (c) Sorbonne Université 2010-2022, All Rights Reserved
//
// ===================================================================
//
// $Id$
//
// x-----------------------------------------------------------------x
// | |
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | C a d e n c e D E F E x p o r t e r |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./crlcore/DefExport.h" |
// | *************************************************************** |
// | U p d a t e s |
// | |
// x-----------------------------------------------------------------x
#ifndef __CRL_DEF_EXPORT__
#define __CRL_DEF_EXPORT__
// +-----------------------------------------------------------------+
#pragma once
namespace Hurricane {
class Cell;
}
@ -35,15 +24,17 @@ namespace Hurricane {
namespace CRL {
// -------------------------------------------------------------------
// Class : "CRL::DefExport".
class DefExport {
public:
enum Flag { WithLEF=0x1, ExpandDieArea=0x2 };
static const uint32_t WithLEF = (1 << 0);
static const uint32_t ExpandDieArea = (1 << 1);
static const uint32_t ProtectNetNames = (1 << 2);
public:
static void drive ( Hurricane::Cell*, unsigned int flags );
static void drive ( Hurricane::Cell*, uint32_t flags );
};
} // End of CRL namespace.
#endif // __CRL_DEF_EXPORT__
} // CRL namespace.

View File

@ -1,14 +1,14 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2010-2013, All Rights Reserved
// Copyright (c) Sorbonne Université 2010-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | C a d e n c e D E F E x p o r t e r |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./crlcore/DefExport.cpp" |
// +-----------------------------------------------------------------+
@ -87,15 +87,15 @@ namespace {
}
#define CHECK_STATUS_CBK(status) if ((status) != 0) return driver->checkStatus(status);
#define CHECK_STATUS_DRV(status) if ((status) != 0) return checkStatus(status);
#define RETURN_CHECK_STATUS_CBK(status) return driver->checkStatus(status);
#define RETURN_CHECK_STATUS_DRV(status) return checkStatus(status);
#define CHECK_STATUS_CBK(status,info) if ((status) != 0) return driver->checkStatus(status,info);
#define CHECK_STATUS_DRV(status,info) if ((status) != 0) return checkStatus(status,info);
#define RETURN_CHECK_STATUS_CBK(status,info) return driver->checkStatus(status,info);
#define RETURN_CHECK_STATUS_DRV(status,info) return checkStatus(status,info);
class DefDriver {
public:
static void drive ( Cell* cell, unsigned int flags );
static void drive ( Cell* cell, uint32_t flags );
static int getUnits ();
static int toDefUnits ( DbU::Unit );
static int toDefOrient ( Transformation::Orientation );
@ -105,12 +105,12 @@ namespace {
~DefDriver ();
int write ();
private:
DefDriver ( Cell*, const string& designName, FILE*, unsigned int flags );
DefDriver ( Cell*, const string& designName, FILE*, uint32_t flags );
inline Cell* getCell ();
inline const string& getDesignName () const;
inline unsigned int getFlags () const;
inline uint32_t getFlags () const;
inline int getStatus () const;
int checkStatus ( int status );
int checkStatus ( int status, string info );
static int writeRouting ( Net*, bool special );
private:
static int _designCbk ( defwCallbackType_e, defiUserData );
@ -143,22 +143,22 @@ namespace {
Cell* _cell;
string _designName;
FILE* _defStream;
unsigned int _flags;
uint32_t _flags;
int _status;
};
int DefDriver::_units = 100;
int DefDriver::_units = 1000;
DbU::Unit DefDriver::_sliceHeight = 0;
DbU::Unit DefDriver::_pitchWidth = 0;
int DefDriver::getUnits () { return _units; }
int DefDriver::toDefUnits ( DbU::Unit u ) { return (int)round(DbU::getGrid(u)); }
int DefDriver::toDefUnits ( DbU::Unit u ) { return (int)(round(DbU::toMicrons(u)*_units)); }
DbU::Unit DefDriver::getSliceHeight () { return _sliceHeight; }
DbU::Unit DefDriver::getPitchWidth () { return _pitchWidth; };
inline Cell* DefDriver::getCell () { return _cell; }
inline unsigned int DefDriver::getFlags () const { return _flags; }
inline uint32_t DefDriver::getFlags () const { return _flags; }
inline int DefDriver::getStatus () const { return _status; }
inline const string& DefDriver::getDesignName () const { return _designName; }
@ -211,7 +211,7 @@ namespace {
}
DefDriver::DefDriver ( Cell* cell, const string& designName, FILE* defStream, unsigned int flags )
DefDriver::DefDriver ( Cell* cell, const string& designName, FILE* defStream, uint32_t flags )
: _cell (cell)
, _designName(designName)
, _defStream (defStream)
@ -223,7 +223,8 @@ namespace {
_sliceHeight = cg->getSliceHeight ();
_pitchWidth = cg->getPitch ();
_units = DbU::toGrid(DbU::fromMicrons(1.0));
//_units = DbU::toGrid( DbU::fromMicrons(1.0) );
_units = 1000;
_status = defwInitCbk ( _defStream );
if ( _status != 0 ) return;
@ -261,16 +262,18 @@ namespace {
int DefDriver::write ()
{
_cell->flattenNets( Cell::Flags::NoFlags );
return checkStatus ( defwWrite(_defStream,_designName.c_str(),(void*)this) );
return checkStatus( defwWrite(_defStream,_designName.c_str(), (void*)this )
, "write(): Problem while writing DEF." );
}
int DefDriver::checkStatus ( int status )
int DefDriver::checkStatus ( int status, string info )
{
if ( (_status=status) != 0 ) {
defwPrintError ( _status );
if ((_status=status) != 0) {
defwPrintError( _status );
ostringstream message;
message << "DefDriver::drive(): Error occured while driving <" << _designName << ">.";
message << "DefDriver::checkStatus(): Error occured while driving \"" << _designName << "\".\n";
message << " " << info;
cerr << Error(message.str()) << endl;
}
return _status;
@ -285,7 +288,7 @@ namespace {
defwAddComment ( "DEF generated by Coriolis2 DEF exporter." );
defwNewLine ();
return driver->checkStatus ( defwVersion(5,7) );
return driver->checkStatus( defwVersion(5,7), "_versionCnk(): Failed to write VERSION" );
}
@ -293,14 +296,15 @@ namespace {
{
DefDriver* driver = (DefDriver*)udata;
defwNewLine ();
return driver->checkStatus ( defwDesignName(driver->getDesignName().c_str()) );
return driver->checkStatus( defwDesignName(driver->getDesignName().c_str())
, "_designCbk(): Failed to write DESIGN" );
}
int DefDriver::_designEndCbk ( defwCallbackType_e, defiUserData udata )
{
DefDriver* driver = (DefDriver*)udata;
return driver->checkStatus ( defwEnd() );
return driver->checkStatus( defwEnd(), "_designEndCbk(): Failed to END design" );
}
@ -315,14 +319,15 @@ namespace {
{
DefDriver* driver = (DefDriver*)udata;
defwNewLine ();
return driver->checkStatus ( defwDividerChar(".") );
return driver->checkStatus( defwDividerChar("."), "_dividerCbk(): Failed to drive DIVIDER" );
}
int DefDriver::_busBitCbk ( defwCallbackType_e, defiUserData udata )
{
DefDriver* driver = (DefDriver*)udata;
return driver->checkStatus ( defwBusBitChars("()") );
return driver->checkStatus( defwBusBitChars("()")
, "_busBitCbk(): Failed to drive BUSBITCHAR" );
}
@ -330,14 +335,17 @@ namespace {
{
DefDriver* driver = (DefDriver*)udata;
defwNewLine ();
return driver->checkStatus ( defwUnits (DefDriver::getUnits()) );
ostringstream info;
info << "_unitsCnk(): Failed to drive UNITS (" << DefDriver::getUnits() << ")";
return driver->checkStatus( defwUnits(DefDriver::getUnits()), info.str() );
}
int DefDriver::_technologyCbk ( defwCallbackType_e, defiUserData udata )
{
DefDriver* driver = (DefDriver*)udata;
return driver->checkStatus ( defwTechnology( getString(driver->getCell()->getLibrary()->getName()).c_str() ) );
return driver->checkStatus( defwTechnology( getString(driver->getCell()->getLibrary()->getName()).c_str() )
, "_technologycbk(): Failed to drive TECHNOLOGY" );
}
@ -358,6 +366,7 @@ namespace {
, (int)( toDefUnits(abutmentBox.getXMax()) )
, (int)( toDefUnits(abutmentBox.getYMax()) )
)
, "_dieAreaCbk(): Failed to write DIEAERA"
);
}
return driver->getStatus();
@ -408,6 +417,7 @@ namespace {
, stepX
, stepY
)
, "_rowCbk(): Failed to write ROW"
);
if ( status != 0 ) break;
@ -453,10 +463,10 @@ namespace {
}
status = defwTracks ( master, doStart, doCount, doStep, 1, layerName );
CHECK_STATUS_CBK(status);
CHECK_STATUS_CBK(status,"_trackCbk(): Direction neither vertical nor horizontal.");
}
RETURN_CHECK_STATUS_CBK(status);
RETURN_CHECK_STATUS_CBK(status,"_trackCbk(): Did not complete properly");
}
@ -479,7 +489,8 @@ namespace {
}
status = defwStartPins ( pinsNb );
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 )
return driver->checkStatus( status, "_pinCbk(): Failed to start PINS" );
forEach ( Net*, inet, cell->getNets() ) {
if ( not (*inet)->isExternal() ) continue;
@ -501,10 +512,10 @@ namespace {
, NULL // layer.
, 0, 0, 0, 0 // geometry.
);
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 ) return driver->checkStatus(status,"_pinCbk(): Failed to write PIN");
}
return driver->checkStatus ( defwEndPins() );
return driver->checkStatus ( defwEndPins(), "_pinCbk(): Failed to close PINS" );
}
@ -522,10 +533,10 @@ namespace {
Cell* cell = driver->getCell();
status = defwNewLine ();
CHECK_STATUS_CBK(status);
CHECK_STATUS_CBK(status,"_componentCbk(): Did not start properly");
status = defwStartComponents ( cell->getTerminalNetlistInstanceOccurrences().getSize() );
CHECK_STATUS_CBK(status);
CHECK_STATUS_CBK(status,"_componentCbk(): Cannot create instance count");
for ( Occurrence occurrence : cell->getTerminalNetlistInstanceOccurrences() ) {
Instance* instance = static_cast<Instance*>(occurrence.getEntity());
@ -570,19 +581,18 @@ namespace {
, NULL // region (disabled).
, 0, 0, 0, 0 // region coordinates.
);
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 ) return driver->checkStatus(status,"_componentCbk(): Failed to write COMPONENT");
}
return driver->checkStatus ( defwEndComponents() );
return driver->checkStatus ( defwEndComponents(),"_componentCbk(): Failed to close COMPONENTS" );
}
int DefDriver::writeRouting ( Net* net, bool special )
int DefDriver::writeRouting ( Net* net, bool special )
{
int status = 0;
int i = 0;
for ( Component *component : net->getComponents() ) {
std::string layer = component->getLayer() ? getString(component->getLayer()->getName()) : "";
if (layer.size() >= 4 && layer.substr(layer.size() - 4) == ".pin")
continue;
@ -657,20 +667,23 @@ namespace {
}
status = defwStartNets ( netsNb );
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 )
return driver->checkStatus(status,"_netCbk(): Failed to begin NETS");
for ( Net* net : cell->getNets() ) {
if ( net->isSupply() or net->isClock() ) continue;
size_t pos = string::npos;
string netName = getString( net->getName() );
if (netName[netName.size()-1] == ')') pos = netName.rfind('(');
if (pos == string::npos) pos = netName.size();
netName.insert( pos, "_net" );
if ( driver->getFlags() & DefExport::ProtectNetNames) {
size_t pos = string::npos;
if (netName[netName.size()-1] == ')') pos = netName.rfind('(');
if (pos == string::npos) pos = netName.size();
netName.insert( pos, "_net" );
}
netName = toDefName( netName );
status = defwNet ( netName.c_str() );
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 ) return driver->checkStatus(status,"_netCbk(): Failed to begin NET");
for ( RoutingPad* rp : net->getRoutingPads() ) {
Plug *plug = dynamic_cast<Plug*>(rp->getPlugOccurrence().getEntity());
@ -685,15 +698,15 @@ namespace {
throw Error("RP PlugOccurrence neither a plug nor a pin!");
// TODO: do we need to write something ?
}
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 ) return driver->checkStatus(status,"_netCbk(): Failed to write RoutingPad");
}
status = writeRouting(net, false);
status = defwNetEndOneNet ();
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 ) return driver->checkStatus( status, "_neCbk(): Failed to end NET" );
}
return driver->checkStatus ( defwEndNets() );
return driver->checkStatus ( defwEndNets(), "_neCbk(): Failed to end NETS" );
}
@ -709,7 +722,7 @@ namespace {
}
status = defwStartSpecialNets ( netsNb );
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 ) return driver->checkStatus(status,"_snetCbk(): Failed to begin SNETS");
forEach ( Net*, inet, cell->getNets() ) {
const char* netUse = NULL;
@ -719,25 +732,25 @@ namespace {
if ( netUse == NULL ) continue;
status = defwSpecialNet ( getString((*inet)->getName()).c_str() );
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 ) return driver->checkStatus(status,"_snetCbk(): Failed to write SNET");
status = defwSpecialNetConnection ( "*"
, getString((*inet)->getName()).c_str()
, 0
);
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 ) return driver->checkStatus(status,"_snetCbk(): Failed to write CONNEXION");
status = defwSpecialNetUse ( netUse );
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 ) return driver->checkStatus(status,"_snetCnk(): Failed to write NET USE");
status = writeRouting(*inet, true);
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 ) return driver->checkStatus(status,"_snetCnk(): Failed to write special wiring");
status = defwSpecialNetEndOneNet ();
if ( status != 0 ) return driver->checkStatus(status);
if ( status != 0 ) return driver->checkStatus(status,"_snetCnk(): Failed to end SNET");
}
return driver->checkStatus ( defwEndSpecialNets() );
return driver->checkStatus( defwEndSpecialNets(), "_snetCnk(): Failed to end SPECIALNETS" );
}
@ -776,7 +789,7 @@ namespace {
}
void DefDriver::drive ( Cell* cell, unsigned int flags )
void DefDriver::drive ( Cell* cell, uint32_t flags )
{
FILE* defStream = NULL;
try {
@ -816,7 +829,7 @@ namespace CRL {
using Hurricane::UpdateSession;
void DefExport::drive ( Cell* cell, unsigned int flags )
void DefExport::drive ( Cell* cell, uint32_t flags )
{
#if defined(HAVE_LEFDEF)
DefDriver::drive ( cell, flags );

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2010-2021, All Rights Reserved
// Copyright (c) Sorbonne Université 2010-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
@ -246,6 +246,8 @@ extern "C" {
PyRoutingLayerGauge_postModuleInit ();
PyAllianceFramework_postModuleInit ();
PySpice_postModuleInit ();
PyGds_postModuleInit ();
PyDefExport_postModuleInit ();
//PyObject* dictionnary = PyModule_GetDict ( module );
//DbULoadConstants ( dictionnary );

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2017-2018, All Rights Reserved
// Copyright (c) Sorbonne Université 2017-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
@ -101,6 +101,15 @@ extern "C" {
PyTypeObjectDefinitionsOfModule(CRL,DefExport)
extern void PyDefExport_postModuleInit ()
{
PyObject* constant;
LoadObjectConstant(PyTypeDefExport.tp_dict,DefExport::WithLEF ,"WithLEF");
LoadObjectConstant(PyTypeDefExport.tp_dict,DefExport::ExpandDieArea ,"ExpandDieArea");
LoadObjectConstant(PyTypeDefExport.tp_dict,DefExport::ProtectNetNames,"ProtectNetNames");
}
#endif // End of Shared Library Code Part.
} // extern "C".

View File

@ -2,7 +2,7 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2017-2018, All Rights Reserved
// Copyright (c) Sorbonne Université 2017-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
@ -15,9 +15,7 @@
// +-----------------------------------------------------------------+
#ifndef CRL_PY_DEF_EXPORT_H
#define CRL_PY_DEF_EXPORT_H
#pragma once
#include "hurricane/isobar/PyHurricane.h"
#include "crlcore/DefExport.h"
@ -41,7 +39,8 @@ extern "C" {
extern PyTypeObject PyTypeDefExport;
extern PyMethodDef PyDefExport_Methods[];
extern void PyDefExport_LinkPyType();
extern void PyDefExport_LinkPyType ();
extern void PyDefExport_postModuleInit ();
#define IsPyDefExport(v) ( (v)->ob_type == &PyTypeDefExport )
@ -51,5 +50,3 @@ extern "C" {
} // extern "C".
} // CRL namespace.
#endif // CRL_PY_DEF_EXPORT_H