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.
This commit is contained in:
parent
f49426f2bb
commit
2705226cd0
|
@ -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 ();
|
||||
};
|
||||
|
|
|
@ -49,13 +49,16 @@ namespace Spice {
|
|||
|
||||
|
||||
class Entity {
|
||||
public:
|
||||
static const uint64_t TopCell = (1 << 0);
|
||||
public:
|
||||
static std::vector<Entity*>&
|
||||
getAllEntities ();
|
||||
static void orderPlugs ( Instance*, std::vector<Plug*>& );
|
||||
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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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<Instance*>( 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<Instance*>( 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<Plug*> 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();
|
||||
|
|
|
@ -220,6 +220,7 @@ extern "C" {
|
|||
PyRoutingGauge_postModuleInit ();
|
||||
PyRoutingLayerGauge_postModuleInit ();
|
||||
PyAllianceFramework_postModuleInit ();
|
||||
PySpice_postModuleInit ();
|
||||
|
||||
//PyObject* dictionnary = PyModule_GetDict ( module );
|
||||
//DbULoadConstants ( dictionnary );
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "crlcore/PySpice.h"
|
||||
#include "hurricane/isobar/PyCell.h"
|
||||
#include "hurricane/isobar/PyLibrary.h"
|
||||
#include "crlcore/SpiceEntity.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
|
@ -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".
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Reference in New Issue