Added basic SPICE driver support.

The structure of the driver is copied from the Vhdl one. It is not
integrated as a an AllianceFramework one but as a standalone like
GDS. For now use numerical indexes for electrical nodes but also
support strings. The nets are ordereds in reverse alphabetical
order, but a custom order can be defined, if we read the model
from an external SPICE subckt (to be done).
  SPICE saving has also been added to the cumulus/rsave plugin
and the block/chip P&R one.
This commit is contained in:
Jean-Paul Chaput 2021-06-21 01:30:28 +02:00
parent eeda81f746
commit 51ca8ab4af
14 changed files with 1199 additions and 17 deletions

View File

@ -20,7 +20,7 @@
${CRLCORE_SOURCE_DIR}/src/ccore/ispd04
${CRLCORE_SOURCE_DIR}/src/ccore/ispd05
${CRLCORE_SOURCE_DIR}/src/ccore/iccad04
#${CRLCORE_SOURCE_DIR}/src/ccore/cspice
${CRLCORE_SOURCE_DIR}/src/ccore/spice
${CRLCORE_SOURCE_DIR}/src/ccore/lefdef
${CRLCORE_SOURCE_DIR}/src/ccore/blif
${CRLCORE_SOURCE_DIR}/src/ccore/alliance/ap
@ -105,10 +105,11 @@
ToolEngine.cpp
GraphicToolEngine.cpp
)
#set ( spice_cpps spice/SpiceParser.cpp
# spice/SpiceDriver.cpp
# spice/Spice.cpp
# )
set ( spice_cpps spice/SpiceBit.cpp
spice/SpiceEntity.cpp
spice/SpiceParser.cpp
spice/SpiceDriver.cpp
)
set ( bookshelf_cpps bookshelf/BookshelfParser.cpp
bookshelf/BookshelfDriver.cpp
)
@ -296,7 +297,7 @@
${ispd04_cpps}
${ispd05_cpps}
${blif_cpps}
#${spice_cpps}
${spice_cpps}
${lefdef_cpps}
${openaccess_cpps}
)

View File

@ -0,0 +1,41 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU/LIP6 2021-2021, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S P I C E / Hurricane Interface |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./crlcore/Spice.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <string>
namespace Hurricane {
class Cell;
class Library;
}
namespace CRL {
using Hurricane::Cell;
using Hurricane::Library;
class Spice {
public:
static bool save ( Cell* );
static bool load ( Library*, std::string spicePath );
static void clearProperties ();
};
} // CRL namespace.

View File

@ -0,0 +1,144 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2021-2021, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S P I C E / Hurricane Interface |
// | |
// | Author : Jean-Paul Chaput |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./crlcore/SpiceBit.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <cstddef>
#include <string>
#include "hurricane/Name.h"
#include "hurricane/Property.h"
#include "hurricane/Slot.h"
#include "hurricane/Net.h"
namespace Spice {
using Hurricane::Record;
using Hurricane::Name;
using Hurricane::DBo;
using Hurricane::Net;
using Hurricane::PrivateProperty;
class BitProperty;
// -------------------------------------------------------------------
// Class : "::Bit" (declaration).
class Bit {
public:
static const size_t nindex;
public:
Bit ( BitProperty*, const Net*, size_t index, std::string name="" );
Bit ( size_t index, std::string name="" );
~Bit ();
bool isExternal () const;
inline BitProperty* getProperty () const;
inline const Net* getNet () const;
inline std::string getName () const;
size_t getIndex () const;
inline void destroy ();
std::string _getString () const;
Record* _getRecord () const;
private:
static ptrdiff_t _offset;
size_t _index;
std::string _name;
};
inline std::string Bit::getName () const { return _name; }
typedef std::vector<Bit*> BitVector;
struct GreaterBitByIndex {
inline bool operator() ( const Bit* lhs, const Bit* rhs ) const
{ return lhs->getIndex() > rhs->getIndex(); }
};
// -------------------------------------------------------------------
// Class : "Spice::BitProperty".
class BitProperty : public Hurricane::PrivateProperty {
friend class BitExtension;
public:
static Name _name;
public:
static BitProperty* create ( Net* owner, size_t index );
static Name getPropertyName ();
virtual Name getName () const;
inline Bit* getBit ();
inline std::string getBitName () const;
virtual void onReleasedBy ( DBo* owner );
virtual std::string _getTypeName () const;
virtual std::string _getString () const;
virtual Record* _getRecord () const;
protected:
// Attributes.
Bit _bit;
protected:
// Constructor.
inline BitProperty ( Net* owner, size_t );
};
inline BitProperty::BitProperty ( Net* owner, size_t index )
: PrivateProperty(), _bit(this,owner,index)
{ }
inline Bit* BitProperty::getBit () { return &_bit; }
inline std::string BitProperty::getBitName () const { return _bit.getName(); }
// -------------------------------------------------------------------
// Class : "Spice::BitExtension".
class BitExtension {
public:
static inline size_t getIndex ( const Net* );
static inline std::string getName ( const Net* );
static Bit* get ( const Net* );
static Bit* create ( Net*, size_t index=Bit::nindex );
private:
static const Net* _owner;
static Bit* _cache;
};
inline size_t BitExtension::getIndex ( const Net* net )
{
Bit* bit = get( net );
return (bit == NULL) ? false : bit->getIndex();
}
inline std::string BitExtension::getName ( const Net* net )
{
Bit* bit = get( net );
return (bit == NULL) ? "?" : bit->getName();
}
inline BitProperty* Bit::getProperty () const { return (BitProperty*)((ptrdiff_t)(this) - _offset); }
inline const Net* Bit::getNet () const { return (const Net*)getProperty()->getOwner(); }
inline void Bit::destroy () { ((Net*)getProperty()->getOwner())->remove( getProperty() ); }
} // Spice Namespace.
INSPECTOR_P_SUPPORT(Spice::Bit);

View File

@ -0,0 +1,129 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2021-2021, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S P I C E / Hurricane Interface |
// | |
// | Author : Jean-Paul Chaput |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./crlcore/SpiceEntity.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <string>
#include "hurricane/Name.h"
#include "hurricane/Property.h"
#include "hurricane/Slot.h"
namespace Hurricane {
class Net;
class Instance;
}
#include "crlcore/ToolBox.h"
#include "crlcore/SpiceBit.h"
namespace Spice {
using std::ostream;
using Hurricane::Record;
using Hurricane::Name;
using Hurricane::DBo;
using Hurricane::Net;
using Hurricane::Cell;
using Hurricane::Instance;
using Hurricane::Plug;
using Hurricane::PrivateProperty;
using CRL::NamingScheme;
class Bit;
class EntityProperty;
// -------------------------------------------------------------------
// Class : "Spice::Entity".
class Entity {
public:
static std::vector<Entity*>&
getAllEntities ();
static void orderPlugs ( Instance*, std::vector<Plug*>& );
public:
Entity ( EntityProperty*, Cell* );
~Entity ();
const Cell* getCell () const;
inline const BitVector& getBits () const;
void toNodeList ( ostream&, bool asInterf=true ) const;
void toEntity ( ostream& ) const;
std::string _getString () const;
Record* _getRecord () const;
private:
static std::vector<Entity*> _entities;
static std::ptrdiff_t _offset;
BitVector _bits;
size_t _powerNode;
size_t _groundNode;
};
inline const BitVector& Entity::getBits () const { return _bits; }
// -------------------------------------------------------------------
// Class : "Spice::EntityProperty".
class EntityProperty : public Hurricane::PrivateProperty {
friend class EntityExtension;
public:
static Name _name;
public:
static EntityProperty* create ( Cell* owner );
static Name getPropertyName ();
virtual Name getName () const;
inline Entity* getEntity ();
virtual void onReleasedBy ( DBo* owner );
virtual std::string _getTypeName () const;
virtual std::string _getString () const;
virtual Record* _getRecord () const;
protected:
// Attributes.
Entity _entity;
protected:
// Constructor.
inline EntityProperty ( Cell* owner );
};
inline EntityProperty::EntityProperty ( Cell* owner )
: PrivateProperty(), _entity(this,owner)
{ }
inline Entity* EntityProperty::getEntity () { return &_entity; }
// -------------------------------------------------------------------
// Class : "Spice::EntityExtension".
class EntityExtension {
public:
static void destroyAll ();
static Entity* get ( const Cell* );
static Entity* create ( Cell* );
static void destroy ( Cell* );
private:
static const Cell* _owner;
static Entity* _cache;
};
} // Spice Namespace.
INSPECTOR_P_SUPPORT(Spice::Entity);

View File

@ -0,0 +1,173 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2021-2021, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S P I C E / Hurricane Interface |
// | |
// | Author : Jean-Paul Chaput |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./alliance/spice/SpiceBit.cpp" |
// +-----------------------------------------------------------------+
#include "crlcore/SpiceBit.h"
namespace Spice {
using namespace std;
using Hurricane::_TName;
using Hurricane::Property;
const size_t Bit::nindex = std::numeric_limits<size_t>::max();
// -------------------------------------------------------------------
// Class : "::Bit" (implementation).
ptrdiff_t Bit::_offset = 0;
Bit::Bit ( BitProperty* property, const Net* net, size_t index, string name )
: _index(index)
, _name (name)
{
if (not _offset) {
//_offset = offsetof(ScalarSignal,_toNet);
_offset = (ptrdiff_t)this - (ptrdiff_t)property;
}
if (_name.empty())
_name = to_string(_index);
// if (net->isPower ()) _name = getString(net->getName());
// if (net->isGround()) _name = getString(net->getName());
}
Bit::Bit ( size_t index, string name )
: _index(index)
, _name (name)
{ }
Bit::~Bit ()
{ }
bool Bit::isExternal () const { return getNet()->isExternal(); }
size_t Bit::getIndex () const { return _index; }
string Bit::_getString () const
{
string s = "<" + getString(getNet()->getName());
s += " order:";
if (_index != nindex) s += getString(_index);
else s += "nindex";
s += " node:\"" + _name + "\"";
s += ">";
return s;
}
Record* Bit::_getRecord () const
{
Record* record = new Record ( "<Bit " + _getString() + " >" );
if (record != NULL) {
record->add( getSlot("_index" , _index ) );
}
return record;
}
// -------------------------------------------------------------------
// Class : "BitProperty"
Name BitProperty::_name = "Spice::Bit";
BitProperty* BitProperty::create ( Net* owner, size_t index )
{
BitProperty *property = new BitProperty( owner, index );
property->_postCreate ();
return property;
}
void BitProperty::onReleasedBy ( DBo* owner )
{ PrivateProperty::onReleasedBy( owner ); }
Name BitProperty::getPropertyName ()
{ return _name; }
Name BitProperty::getName () const
{ return getPropertyName(); }
string BitProperty::_getTypeName () const
{ return "Spice::BitProperty"; }
string BitProperty::_getString () const
{
string s = PrivateProperty::_getString ();
s.insert ( s.length() - 1 , " " + getString(&_bit) );
return s;
}
Record* BitProperty::_getRecord () const
{
Record* record = PrivateProperty::_getRecord();
if ( record ) {
record->add( getSlot( "_name", _name ) );
record->add( getSlot( "_bit" , &_bit ) );
}
return record;
}
// -------------------------------------------------------------------
// Class : "BitExtension"
const Net* BitExtension::_owner = NULL;
Bit* BitExtension::_cache = NULL;
Bit* BitExtension::get ( const Net* net )
{
if (net == _owner) return _cache;
_owner = net;
Property* property = _owner->getProperty( BitProperty::getPropertyName() );
if (property) _cache = static_cast<BitProperty*>(property)->getBit();
else _cache = NULL;
return _cache;
}
Bit* BitExtension::create ( Net* net, size_t index )
{
get( net );
if (_cache) return _cache;
BitProperty* property = new BitProperty( net, index );
net->put( property );
_cache = property->getBit();
return _cache;
}
} // Spice namespace.

View File

@ -0,0 +1,84 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2021-2021, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S P I C E / Hurricane Interface |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./spice/SpiceDriver.cpp" |
// +-----------------------------------------------------------------+
#include <ctime>
#include <cmath>
#include <cstdio>
#include <cfenv>
#include <string>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
#include "vlsisapd/configuration/Configuration.h"
#include "hurricane/Warning.h"
#include "hurricane/DataBase.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/Diagonal.h"
#include "hurricane/Rectilinear.h"
#include "hurricane/Polygon.h"
#include "hurricane/Pad.h"
#include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/Cell.h"
#include "hurricane/Plug.h"
#include "hurricane/Instance.h"
using namespace Hurricane;
#include "crlcore/Utilities.h"
#include "crlcore/NetExtension.h"
#include "crlcore/ToolBox.h"
#include "crlcore/Spice.h"
#include "crlcore/SpiceBit.h"
#include "crlcore/SpiceEntity.h"
using namespace CRL;
namespace CRL {
// -------------------------------------------------------------------
// Class : "CRL::Spice".
bool Spice::save ( Cell* cell )
{
::Spice::Entity* spiceEntity = ::Spice::EntityExtension::create( cell );
string cellFile = getString(cell->getName()) + ".spi";
ofstream cellStream ( cellFile );
spiceEntity->toEntity( cellStream );
cellStream.close();
return true;
}
void Spice::clearProperties ()
{
::Spice::EntityExtension::destroyAll();
}
} // CRL namespace.

View File

@ -0,0 +1,311 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2021-2021, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S P I C E / Hurricane Interface |
// | |
// | Author : Jean-Paul Chaput |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./SpiceEntity.cpp" |
// +-----------------------------------------------------------------+
#include <iomanip>
#include <ctime>
#include "hurricane/Warning.h"
#include "hurricane/Cell.h"
#include "crlcore/SpiceEntity.h"
namespace {
using Hurricane::Net;
using Hurricane::Instance;
using Spice::Bit;
using Spice::Entity;
}
namespace Spice {
using namespace std;
using Hurricane::Warning;
using Hurricane::Property;
using Hurricane::_TName;
using Hurricane::Plug;
class ComparePlugBySpiceIndex {
public:
inline bool operator() ( const Plug* lhs, const Plug* rhs ) const
{ return BitExtension::getIndex( lhs->getMasterNet() )
< BitExtension::getIndex( rhs->getMasterNet() ); }
};
// -------------------------------------------------------------------
// Class : "::Entity".
vector<Entity*> Entity::_entities;
ptrdiff_t Entity::_offset = 0;
Entity::Entity ( EntityProperty* property, Cell* cell )
: _bits()
, _powerNode (Bit::nindex)
, _groundNode(Bit::nindex)
{
if (not _offset) {
//_offset = offsetof(EntityProperty,_entity);
_offset = (ptrdiff_t)this - (ptrdiff_t)property;
}
map< string, Net*, greater<string> > orderedNets;
for ( Net* net : cell->getNets() ) {
orderedNets.insert( make_pair( getString(net->getName()), net ) );
}
for ( auto item : orderedNets ) {
Bit* bit = BitExtension::create( item.second, _bits.size() );
_bits.push_back( bit );
if (item.second->isPower ()) _powerNode = bit->getIndex();
if (item.second->isGround()) _groundNode = bit->getIndex();
}
_entities.push_back( this );
}
Entity::~Entity ()
{
for ( auto bit : _bits ) bit->destroy();
for ( auto ientity=_entities.begin() ; ientity!=_entities.end() ; ++ientity ) {
if (*ientity == this) {
_entities.erase( ientity );
break;
}
}
}
vector<Entity*>& Entity::getAllEntities ()
{ return _entities; }
void Entity::orderPlugs ( Instance* instance, vector<Plug*>& ordereds )
{
ordereds.clear();
//Entity* entity = EntityExtension::create( instance->getMasterCell() );
for ( Plug* plug : instance->getPlugs() )
ordereds.push_back( plug );
sort( ordereds.begin(), ordereds.end(), ComparePlugBySpiceIndex() );
}
const Cell* Entity::getCell () const
{
EntityProperty* property = (EntityProperty*)((ptrdiff_t)(this) - _offset);
return (const Cell*)property->getOwner();
}
void Entity::toNodeList ( ostream& out, bool asInterf ) const
{
for ( Bit* bit : _bits ) {
const Net* net = bit->getNet();
if (not net->isExternal() and asInterf) continue;
out << "* " << ((asInterf) ? "INTERF" : "NET")
<< setw(6) << BitExtension::getName(net)
<< " " << net->getName() << ".\n";
}
out << "\n";
}
void Entity::toEntity ( ostream& out ) const
{
set<Cell*,DBo::CompareById> processedsModels;
string cellName = getString( getCell()->getName() );
time_t clock = time( nullptr );
tm tm = *localtime( &clock );
char stamp[1024];
strftime( stamp, 1024, "%b %d, %Y, %H:%M", &tm );
out << "* Coriolis Structural SPICE Driver\n";
out << "* Generated on " << stamp << "\n";
out << "* Cell/Subckt \"" << cellName << "\".\n";
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 );
}
out << "\n";
out << ".subckt " << getCell()->getName();
for ( Bit* bit : _bits ) {
if (not bit->getNet()->isExternal()) continue;
out << " " << bit->getName();
}
out << "\n";
toNodeList( out, false );
for ( Instance* instance : getCell()->getInstances() ) {
Entity* masterEntity = EntityExtension::create( instance->getMasterCell() );
out << "x" << instance->getName();
vector<Plug*> sortedPlugs;
masterEntity->orderPlugs( instance, sortedPlugs );
for ( Plug* plug : sortedPlugs ) {
Net* plugNet = plug->getNet();
if (plugNet) {
out << " " << BitExtension::getName(plugNet);
} else {
if (plug->getMasterNet()->isPower()) {
out << " " << _powerNode;
} else {
if (plug->getMasterNet()->isGround()) {
out << " " << _groundNode;
} else
out << " ?";
}
}
}
out << " " << instance->getMasterCell()->getName() << "\n";
}
out << ".ends " << getCell()->getName() << "\n";
}
string Entity::_getString () const
{
string s = getString(getCell()->getName());
return s;
}
Record* Entity::_getRecord () const
{
Record* record = new Record ( "<Entity " + _getString() + " >" );
if (record != NULL) {
record->add( getSlot("_bits" , _bits ) );
record->add( getSlot("_powerNode" , _powerNode ) );
record->add( getSlot("_groundNode", _groundNode ) );
}
return record;
}
// -------------------------------------------------------------------
// Class : "EntityProperty"
Name EntityProperty::_name = "Spice::Entity";
EntityProperty* EntityProperty::create ( Cell* owner )
{
EntityProperty *property = new EntityProperty( owner );
property->_postCreate ();
return property;
}
void EntityProperty::onReleasedBy ( DBo* owner )
{ PrivateProperty::onReleasedBy( owner ); }
Name EntityProperty::getPropertyName ()
{ return _name; }
Name EntityProperty::getName () const
{ return getPropertyName(); }
string EntityProperty::_getTypeName () const
{ return _TName( "EntityProperty" ); }
string EntityProperty::_getString () const
{
string s = PrivateProperty::_getString ();
s.insert ( s.length() - 1 , " " + getString(&_entity) );
return s;
}
Record* EntityProperty::_getRecord () const
{
Record* record = PrivateProperty::_getRecord();
if ( record ) {
record->add( getSlot( "_name" , _name ) );
record->add( getSlot( "_entity", &_entity ) );
}
return record;
}
// -------------------------------------------------------------------
// Class : "EntityExtension"
const Cell* EntityExtension::_owner = NULL;
Entity* EntityExtension::_cache = NULL;
Entity* EntityExtension::get ( const Cell* cell )
{
if (cell != _owner) {
_owner = cell;
Property* property = _owner->getProperty( EntityProperty::getPropertyName() );
if (property) _cache = static_cast<EntityProperty*>(property)->getEntity();
else _cache = NULL;
}
return _cache;
}
Entity* EntityExtension::create ( Cell* cell )
{
get( cell );
if (not _cache) {
EntityProperty* property = new EntityProperty( cell );
cell->put( property );
_cache = property->getEntity();
}
return _cache;
}
void EntityExtension::destroy ( Cell* cell )
{
Property* property = cell->getProperty( EntityProperty::getPropertyName() );
if (property) cell->remove( property );
_owner = NULL;
_cache = NULL;
}
void EntityExtension::destroyAll ()
{
vector<Entity*>& entities = Entity::getAllEntities();
while ( not entities.empty() ) destroy( const_cast<Cell*>(entities.back()->getCell()) );
}
} // Spice namespace.

View File

@ -0,0 +1,80 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2021-2021, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S P I C E / Hurricane Interface |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./spice/SpiceParser.cpp" |
// +-----------------------------------------------------------------+
#include <ctime>
#include <cstdio>
#include <string>
#include <bitset>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
#include "vlsisapd/configuration/Configuration.h"
#include "hurricane/DebugSession.h"
#include "hurricane/UpdateSession.h"
#include "hurricane/Warning.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/Diagonal.h"
#include "hurricane/Rectilinear.h"
#include "hurricane/Pad.h"
#include "hurricane/Net.h"
#include "hurricane/Cell.h"
#include "hurricane/Library.h"
#include "hurricane/Plug.h"
#include "hurricane/Instance.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/UpdateSession.h"
using namespace Hurricane;
#include "crlcore/Utilities.h"
#include "crlcore/NetExtension.h"
#include "crlcore/ToolBox.h"
#include "crlcore/Spice.h"
using namespace CRL;
namespace CRL {
// -------------------------------------------------------------------
// Class : "CRL::Spice".
bool Spice::load ( Library* library, string spicePath )
{
//DebugSession::open( 101, 110 );
UpdateSession::open();
cerr << Error( "Spice::load(): SPICE parser is not implemented yet.\n"
" \"%s\"."
, spicePath.c_str()
) << endl;
UpdateSession::close();
//DebugSession::close();
return false;
}
} // CRL namespace.

View File

@ -44,6 +44,7 @@
PyGraphicToolEngine.cpp
PyAcmSigda.cpp
PyIspd05.cpp
PySpice.cpp
PyBlif.cpp
PyGds.cpp
PyLefImport.cpp
@ -65,6 +66,7 @@
crlcore/PyGraphicToolEngine.h
crlcore/PyAcmSigda.h
crlcore/PyIspd05.h
crlcore/PySpice.h
crlcore/PyBlif.h
crlcore/PyGds.h
crlcore/PyLefImport.h

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2010-2018, All Rights Reserved
// Copyright (c) SU 2010-2021, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
@ -32,6 +32,7 @@
#include "crlcore/PyToolEngineCollection.h"
#include "crlcore/PyAcmSigda.h"
#include "crlcore/PyIspd05.h"
#include "crlcore/PySpice.h"
#include "crlcore/PyBlif.h"
#include "crlcore/PyGds.h"
#include "crlcore/PyLefImport.h"
@ -125,6 +126,7 @@ extern "C" {
PyToolEngineCollection_LinkPyType ();
PyAcmSigda_LinkPyType ();
PyIspd05_LinkPyType ();
PySpice_LinkPyType ();
PyBlif_LinkPyType ();
PyGds_LinkPyType ();
PyLefImport_LinkPyType ();
@ -147,6 +149,7 @@ extern "C" {
PYTYPE_READY ( ToolEngineCollectionLocator );
PYTYPE_READY ( AcmSigda );
PYTYPE_READY ( Ispd05 );
PYTYPE_READY ( Spice );
PYTYPE_READY ( Blif );
PYTYPE_READY ( Gds );
PYTYPE_READY ( LefImport );
@ -201,6 +204,8 @@ extern "C" {
PyModule_AddObject ( module, "AcmSigda", (PyObject*)&PyTypeAcmSigda );
Py_INCREF ( &PyTypeIspd05 );
PyModule_AddObject ( module, "Ispd05", (PyObject*)&PyTypeIspd05 );
Py_INCREF ( &PyTypeSpice );
PyModule_AddObject ( module, "Spice", (PyObject*)&PyTypeSpice );
Py_INCREF ( &PyTypeBlif );
PyModule_AddObject ( module, "Blif", (PyObject*)&PyTypeBlif );
Py_INCREF ( &PyTypeGds );

View File

@ -0,0 +1,154 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2021-2021, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | Alliance / Hurricane Interface |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./PySpice.cpp" |
// +-----------------------------------------------------------------+
#include "crlcore/PySpice.h"
#include "hurricane/isobar/PyCell.h"
#include "hurricane/isobar/PyLibrary.h"
#include <string>
#include <sstream>
namespace CRL {
using std::cerr;
using std::endl;
using std::hex;
using std::string;
using std::ostringstream;
using Hurricane::tab;
using Hurricane::Exception;
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::Warning;
using Isobar::ProxyProperty;
using Isobar::ProxyError;
using Isobar::ConstructorError;
using Isobar::HurricaneError;
using Isobar::HurricaneWarning;
using Isobar::getPyHash;
using Isobar::ParseOneArg;
using Isobar::ParseTwoArg;
using Isobar::__cs;
using Isobar::PyCell;
using Isobar::PyTypeCell;
using Isobar::PyCell_Link;
using Isobar::PyLibrary;
using Isobar::PyTypeLibrary;
using Isobar::PyLibrary_Link;
extern "C" {
#if defined(__PYTHON_MODULE__)
// +=================================================================+
// | "PySpice" Python Module Code Part |
// +=================================================================+
static PyObject* PySpice_save ( PyObject*, PyObject* args )
{
cdebug_log(30,0) << "PySpice_save()" << endl;
HTRY
PyObject* pyCell = NULL;
if (PyArg_ParseTuple( args, "O:Spice.save", &pyCell )) {
if (IsPyCell(pyCell)) {
Spice::save( PYCELL_O(pyCell) );
} else {
PyErr_SetString( ConstructorError, "Spice.save(): Bad parameter type (not a Cell)." );
return NULL;
}
} else {
PyErr_SetString( ConstructorError, "Spice.save(): Bad number of parameters." );
return NULL;
}
HCATCH
Py_RETURN_NONE;
}
static PyObject* PySpice_load ( PyObject*, PyObject* args )
{
cdebug_log(30,0) << "PySpice_load()" << endl;
char* path = NULL;
HTRY
PyObject* pyLibrary = NULL;
if (PyArg_ParseTuple( args, "Os:Spice.load", &pyLibrary, &path )) {
if (IsPyLibrary(pyLibrary)) {
Spice::load( PYLIBRARY_O(pyLibrary), string(path) );
} else {
PyErr_SetString( ConstructorError, "Spice.load(): Bad parameter type (not a Library)." );
return NULL;
}
} else {
PyErr_SetString( ConstructorError, "Spice.load(): Bad number of parameters." );
return NULL;
}
HCATCH
Py_RETURN_NONE;
}
static PyObject* PySpice_clearProperties ( PyObject* )
{
cdebug_log(30,0) << "PySpice_clearProperties()" << endl;
HTRY
Spice::clearProperties();
HCATCH
Py_RETURN_NONE;
}
// Standart Destroy (Attribute).
PyMethodDef PySpice_Methods[] =
{ { "save" , (PyCFunction)PySpice_save , METH_VARARGS|METH_STATIC
, "Save a complete Spice design." }
, { "load" , (PyCFunction)PySpice_load , METH_VARARGS|METH_STATIC
, "Load a Spice layout inside a Cell (cumulative)." }
, { "clearProperties" , (PyCFunction)PySpice_clearProperties, METH_NOARGS|METH_STATIC
, "Remove all SPICE related properties from the Cells." }
, {NULL, NULL, 0, NULL} /* sentinel */
};
NoObjectDeleteMethod(Spice)
PyTypeObjectLinkPyTypeWithoutObject(Spice,Spice)
#else // End of Python Module Code Part.
// +=================================================================+
// | "PySpice" Shared Library Code Part |
// +=================================================================+
// Type Definition.
PyTypeObjectDefinitionsOfModule(CRL,Spice)
#endif // End of Shared Library Code Part.
} // extern "C".
} // CRL namespace.

View File

@ -0,0 +1,51 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2021-2021, 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 |
// | =============================================================== |
// | C++ Header : "./crlcore/PySpice.h" |
// +-----------------------------------------------------------------+
#pragma once
#include "hurricane/isobar/PyHurricane.h"
#include "crlcore/Spice.h"
namespace CRL {
extern "C" {
// -------------------------------------------------------------------
// Python Object : "PySpice".
typedef struct {
PyObject_HEAD
} PySpice;
// -------------------------------------------------------------------
// Functions & Types exported to "PyCRL.ccp".
extern PyTypeObject PyTypeSpice;
extern PyMethodDef PySpice_Methods[];
extern void PySpice_LinkPyType();
#define IsPySpice(v) ( (v)->ob_type == &PyTypeSpice )
#define PY_SPICE(v) ( (PySpice*)(v) )
} // extern "C".
} // Hurricane namespace.

View File

@ -1236,11 +1236,12 @@ class BlockConf ( GaugeConf ):
topCell = self.chip
self.corona.setName( self.corona.getName()+'_r' )
self.chip .setName( self.chip .getName()+'_r' )
rsave( self.corona, views|flags )
rsave( self.chip , views|flags )
rsave( self.corona, views|flags, enableSpice=True )
rsave( self.chip , views|flags, enableSpice=True )
if not self.routingGauge.isSymbolic():
print( ' + {} (GDSII).'.format( topCell.getName() ))
CRL.Gds.save( topCell )
CRL.Spice.clearProperties()
return
def toXPitch ( self, x, superior=False ):

View File

@ -31,7 +31,7 @@ except Exception, e:
sys.exit(2)
def rsave ( cell, views=CRL.Catalog.State.Physical, depth=0 ):
def rsave ( cell, views=CRL.Catalog.State.Physical, depth=0, enableSpice=False ):
"""
Write back layout to disk if everything has gone fine.
Must write all the sub-blocks of the core but *not* the
@ -47,15 +47,20 @@ def rsave ( cell, views=CRL.Catalog.State.Physical, depth=0 ):
if views & CRL.Catalog.State.Logical:
sviews += 'netlist'
if views & CRL.Catalog.State.VstUseConcat:
if sviews: sviews += ','
sviews += ' uses &'
if sviews: sviews += ', '
sviews += 'uses &'
if views & CRL.Catalog.State.VstNoLowerCase:
if sviews: sviews += ', no lowercase'
if sviews: sviews += ', '
sviews += 'no lowercase'
if views & CRL.Catalog.State.VstUniquifyUpperCase:
if sviews: sviews += ', uniquify uppercase'
if sviews: sviews += ', '
sviews += 'uniquify uppercase'
if views & CRL.Catalog.State.VstNoLinkage:
if sviews: sviews += ', no linkage'
sviews += ''
if sviews: sviews += ', '
sviews += 'no linkage'
if enableSpice:
if sviews: sviews += ', '
sviews += 'SPICE'
if views & CRL.Catalog.State.Physical:
if sviews: sviews += ','
sviews += 'layout'
@ -64,11 +69,12 @@ def rsave ( cell, views=CRL.Catalog.State.Physical, depth=0 ):
if cell.getName().endswith('_cts'): views |= CRL.Catalog.State.Logical
if cell.getName().endswith('_r' ): views |= CRL.Catalog.State.Logical
framework.saveCell( cell, views )
CRL.Spice.save( cell )
for instance in cell.getInstances():
#print( ' {}| {}.'.format(' '*(depth*2), instance) )
masterCell = instance.getMasterCell()
if not masterCell.isTerminalNetlist():
rsave( masterCell, views, depth+1 )
rsave( masterCell, views, depth+1, enableSpice )
#else:
# print( ' {}| Master cell is terminal netlist {}.'.format(' '*(depth*2), instance.getMasterCell()) )
return