From 2705226cd0e7abbcfafbab8be3c4217659c5bb44 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Thu, 24 Jun 2021 11:17:21 +0200 Subject: [PATCH] Manage .include in SPICE driver so they occurs only once. SPICE simulators don't like to have the same model defined twice. As we have a "one file per model policy", then we must include the model file only once. This is particularly critical for standard cells. So now, the driver include all the models in the top level, both terminals ans intermediate. And the sub-models include nothing. We stop at the "TerminalNetlist" level. Add an option flag througout all the Spice driver hierarchy to convey that information. --- crlcore/src/ccore/crlcore/Spice.h | 2 +- crlcore/src/ccore/crlcore/SpiceEntity.h | 19 +++++++----- crlcore/src/ccore/spice/SpiceDriver.cpp | 4 +-- crlcore/src/ccore/spice/SpiceEntity.cpp | 41 +++++++++++++++++-------- crlcore/src/pyCRL/PyCRL.cpp | 1 + crlcore/src/pyCRL/PySpice.cpp | 14 +++++++-- crlcore/src/pyCRL/crlcore/PySpice.h | 3 +- 7 files changed, 58 insertions(+), 26 deletions(-) diff --git a/crlcore/src/ccore/crlcore/Spice.h b/crlcore/src/ccore/crlcore/Spice.h index d288e29f..13a4c4d5 100644 --- a/crlcore/src/ccore/crlcore/Spice.h +++ b/crlcore/src/ccore/crlcore/Spice.h @@ -32,7 +32,7 @@ namespace CRL { class Spice { public: - static bool save ( Cell* ); + static bool save ( Cell*, uint64_t flags ); static bool load ( Library*, std::string spicePath ); static void clearProperties (); }; diff --git a/crlcore/src/ccore/crlcore/SpiceEntity.h b/crlcore/src/ccore/crlcore/SpiceEntity.h index b2442cbb..bf74b830 100644 --- a/crlcore/src/ccore/crlcore/SpiceEntity.h +++ b/crlcore/src/ccore/crlcore/SpiceEntity.h @@ -49,13 +49,16 @@ namespace Spice { class Entity { + public: + static const uint64_t TopCell = (1 << 0); public: static std::vector& getAllEntities (); static void orderPlugs ( Instance*, std::vector& ); public: - Entity ( EntityProperty*, Cell* ); + Entity ( EntityProperty*, Cell*, uint64_t flags ); ~Entity (); + inline uint64_t getFlags () const; const Cell* getCell () const; inline const BitVector& getBits () const; void toNodeList ( ostream&, bool asInterf=true ) const; @@ -68,10 +71,12 @@ namespace Spice { BitVector _bits; size_t _powerNode; size_t _groundNode; + uint64_t _flags; }; - inline const BitVector& Entity::getBits () const { return _bits; } + inline uint64_t Entity::getFlags () const { return _flags; } + inline const BitVector& Entity::getBits () const { return _bits; } // ------------------------------------------------------------------- @@ -82,7 +87,7 @@ namespace Spice { public: static Name _name; public: - static EntityProperty* create ( Cell* owner ); + static EntityProperty* create ( Cell* owner, uint64_t flags ); static Name getPropertyName (); virtual Name getName () const; inline Entity* getEntity (); @@ -96,12 +101,12 @@ namespace Spice { protected: // Constructor. - inline EntityProperty ( Cell* owner ); + inline EntityProperty ( Cell* owner, uint64_t flags ); }; - inline EntityProperty::EntityProperty ( Cell* owner ) - : PrivateProperty(), _entity(this,owner) + inline EntityProperty::EntityProperty ( Cell* owner, uint64_t flags ) + : PrivateProperty(), _entity(this,owner,flags) { } @@ -115,7 +120,7 @@ namespace Spice { public: static void destroyAll (); static Entity* get ( const Cell* ); - static Entity* create ( Cell* ); + static Entity* create ( Cell*, uint64_t flags ); static void destroy ( Cell* ); private: static const Cell* _owner; diff --git a/crlcore/src/ccore/spice/SpiceDriver.cpp b/crlcore/src/ccore/spice/SpiceDriver.cpp index 38a42527..c123a92c 100644 --- a/crlcore/src/ccore/spice/SpiceDriver.cpp +++ b/crlcore/src/ccore/spice/SpiceDriver.cpp @@ -62,9 +62,9 @@ namespace CRL { // ------------------------------------------------------------------- // Class : "CRL::Spice". - bool Spice::save ( Cell* cell ) + bool Spice::save ( Cell* cell, uint64_t flags ) { - ::Spice::Entity* spiceEntity = ::Spice::EntityExtension::create( cell ); + ::Spice::Entity* spiceEntity = ::Spice::EntityExtension::create( cell, flags ); string cellFile = getString(cell->getName()) + ".spi"; ofstream cellStream ( cellFile ); diff --git a/crlcore/src/ccore/spice/SpiceEntity.cpp b/crlcore/src/ccore/spice/SpiceEntity.cpp index 02657d9f..baf4af9f 100644 --- a/crlcore/src/ccore/spice/SpiceEntity.cpp +++ b/crlcore/src/ccore/spice/SpiceEntity.cpp @@ -25,6 +25,7 @@ namespace { using Hurricane::Net; using Hurricane::Instance; + using Hurricane::Occurrence; using Spice::Bit; using Spice::Entity; @@ -57,10 +58,11 @@ namespace Spice { ptrdiff_t Entity::_offset = 0; - Entity::Entity ( EntityProperty* property, Cell* cell ) + Entity::Entity ( EntityProperty* property, Cell* cell, uint64_t flags ) : _bits() , _powerNode (Bit::nindex) , _groundNode(Bit::nindex) + , _flags(flags) { if (not _offset) { //_offset = offsetof(EntityProperty,_entity); @@ -143,14 +145,26 @@ namespace Spice { out << "* \n"; toNodeList( out, true ); - for ( Instance* instance : getCell()->getInstances() ) { - Cell* model = instance->getMasterCell(); - if (processedsModels.find(model) != processedsModels.end()) - continue; - out << ".include " << model->getName() << ".spi\n"; - processedsModels.insert( model ); + if (_flags & TopCell) { + out << "* Terminal models (aka standard cells) used througout all the hierarchy.\n"; + for ( Occurrence occurrence : getCell()->getTerminalNetlistInstanceOccurrences() ) { + Cell* model = static_cast( occurrence.getEntity() )->getMasterCell(); + if (processedsModels.find(model) != processedsModels.end()) + continue; + out << ".include " << model->getName() << ".spi\n"; + processedsModels.insert( model ); + } + out << "\n"; + out << "* Non-terminal models (part of the user's design hierarchy).\n"; + for ( Occurrence occurrence : getCell()->getNonTerminalNetlistInstanceOccurrences() ) { + Cell* model = static_cast( occurrence.getEntity() )->getMasterCell(); + if (processedsModels.find(model) != processedsModels.end()) + continue; + out << ".include " << model->getName() << ".spi\n"; + processedsModels.insert( model ); + } + out << "\n"; } - out << "\n"; out << ".subckt " << getCell()->getName(); for ( Bit* bit : _bits ) { @@ -161,7 +175,7 @@ namespace Spice { toNodeList( out, false ); for ( Instance* instance : getCell()->getInstances() ) { - Entity* masterEntity = EntityExtension::create( instance->getMasterCell() ); + Entity* masterEntity = EntityExtension::create( instance->getMasterCell(), 0 ); out << "x" << instance->getName(); vector sortedPlugs; masterEntity->orderPlugs( instance, sortedPlugs ); @@ -222,6 +236,7 @@ namespace Spice { record->add( getSlot("_bits" , _bits ) ); record->add( getSlot("_powerNode" , _powerNode ) ); record->add( getSlot("_groundNode", _groundNode ) ); + record->add( getSlot("_flags" , _flags ) ); } return record; } @@ -233,9 +248,9 @@ namespace Spice { Name EntityProperty::_name = "Spice::Entity"; - EntityProperty* EntityProperty::create ( Cell* owner ) + EntityProperty* EntityProperty::create ( Cell* owner, uint64_t flags ) { - EntityProperty *property = new EntityProperty( owner ); + EntityProperty *property = new EntityProperty( owner, flags ); property->_postCreate (); return property; @@ -299,11 +314,11 @@ namespace Spice { } - Entity* EntityExtension::create ( Cell* cell ) + Entity* EntityExtension::create ( Cell* cell, uint64_t flags ) { get( cell ); if (not _cache) { - EntityProperty* property = new EntityProperty( cell ); + EntityProperty* property = new EntityProperty( cell, flags ); cell->put( property ); _cache = property->getEntity(); diff --git a/crlcore/src/pyCRL/PyCRL.cpp b/crlcore/src/pyCRL/PyCRL.cpp index 5752a1db..889ce1ac 100644 --- a/crlcore/src/pyCRL/PyCRL.cpp +++ b/crlcore/src/pyCRL/PyCRL.cpp @@ -220,6 +220,7 @@ extern "C" { PyRoutingGauge_postModuleInit (); PyRoutingLayerGauge_postModuleInit (); PyAllianceFramework_postModuleInit (); + PySpice_postModuleInit (); //PyObject* dictionnary = PyModule_GetDict ( module ); //DbULoadConstants ( dictionnary ); diff --git a/crlcore/src/pyCRL/PySpice.cpp b/crlcore/src/pyCRL/PySpice.cpp index 7528ed8b..02b51830 100644 --- a/crlcore/src/pyCRL/PySpice.cpp +++ b/crlcore/src/pyCRL/PySpice.cpp @@ -17,6 +17,7 @@ #include "crlcore/PySpice.h" #include "hurricane/isobar/PyCell.h" #include "hurricane/isobar/PyLibrary.h" +#include "crlcore/SpiceEntity.h" #include #include @@ -65,10 +66,11 @@ extern "C" { cdebug_log(30,0) << "PySpice_save()" << endl; HTRY + long flags = 0; PyObject* pyCell = NULL; - if (PyArg_ParseTuple( args, "O:Spice.save", &pyCell )) { + if (PyArg_ParseTuple( args, "Ol:Spice.save", &pyCell, &flags )) { if (IsPyCell(pyCell)) { - Spice::save( PYCELL_O(pyCell) ); + Spice::save( PYCELL_O(pyCell), flags ); } else { PyErr_SetString( ConstructorError, "Spice.save(): Bad parameter type (not a Cell)." ); return NULL; @@ -147,6 +149,14 @@ extern "C" { PyTypeObjectDefinitionsOfModule(CRL,Spice) + extern void PySpice_postModuleInit () + { + PyObject* constant; + + LoadObjectConstant(PyTypeSpice.tp_dict,::Spice::Entity::TopCell,"TopCell"); + } + + #endif // End of Shared Library Code Part. } // extern "C". diff --git a/crlcore/src/pyCRL/crlcore/PySpice.h b/crlcore/src/pyCRL/crlcore/PySpice.h index 24e2856d..fe06cfb2 100644 --- a/crlcore/src/pyCRL/crlcore/PySpice.h +++ b/crlcore/src/pyCRL/crlcore/PySpice.h @@ -39,7 +39,8 @@ extern "C" { extern PyTypeObject PyTypeSpice; extern PyMethodDef PySpice_Methods[]; - extern void PySpice_LinkPyType(); + extern void PySpice_LinkPyType (); + extern void PySpice_postModuleInit (); #define IsPySpice(v) ( (v)->ob_type == &PyTypeSpice )