diff --git a/crlcore/src/ccore/CMakeLists.txt b/crlcore/src/ccore/CMakeLists.txt index 728e51cd..42d6f7d6 100644 --- a/crlcore/src/ccore/CMakeLists.txt +++ b/crlcore/src/ccore/CMakeLists.txt @@ -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} ) diff --git a/crlcore/src/ccore/crlcore/Spice.h b/crlcore/src/ccore/crlcore/Spice.h new file mode 100644 index 00000000..d288e29f --- /dev/null +++ b/crlcore/src/ccore/crlcore/Spice.h @@ -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 + + +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. diff --git a/crlcore/src/ccore/crlcore/SpiceBit.h b/crlcore/src/ccore/crlcore/SpiceBit.h new file mode 100644 index 00000000..16f9bb06 --- /dev/null +++ b/crlcore/src/ccore/crlcore/SpiceBit.h @@ -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 +#include +#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 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); diff --git a/crlcore/src/ccore/crlcore/SpiceEntity.h b/crlcore/src/ccore/crlcore/SpiceEntity.h new file mode 100644 index 00000000..b2442cbb --- /dev/null +++ b/crlcore/src/ccore/crlcore/SpiceEntity.h @@ -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 +#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& + getAllEntities (); + static void orderPlugs ( Instance*, std::vector& ); + 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 _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); diff --git a/crlcore/src/ccore/spice/SpiceBit.cpp b/crlcore/src/ccore/spice/SpiceBit.cpp new file mode 100644 index 00000000..128198dd --- /dev/null +++ b/crlcore/src/ccore/spice/SpiceBit.cpp @@ -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::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 ( "" ); + 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(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. diff --git a/crlcore/src/ccore/spice/SpiceDriver.cpp b/crlcore/src/ccore/spice/SpiceDriver.cpp new file mode 100644 index 00000000..38a42527 --- /dev/null +++ b/crlcore/src/ccore/spice/SpiceDriver.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +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. diff --git a/crlcore/src/ccore/spice/SpiceEntity.cpp b/crlcore/src/ccore/spice/SpiceEntity.cpp new file mode 100644 index 00000000..4e5f8ac2 --- /dev/null +++ b/crlcore/src/ccore/spice/SpiceEntity.cpp @@ -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 +#include +#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::_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 > 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::getAllEntities () + { return _entities; } + + + void Entity::orderPlugs ( Instance* instance, vector& 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 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 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 ( "" ); + 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(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& entities = Entity::getAllEntities(); + + while ( not entities.empty() ) destroy( const_cast(entities.back()->getCell()) ); + } + + + +} // Spice namespace. diff --git a/crlcore/src/ccore/spice/SpiceParser.cpp b/crlcore/src/ccore/spice/SpiceParser.cpp new file mode 100644 index 00000000..e82b8116 --- /dev/null +++ b/crlcore/src/ccore/spice/SpiceParser.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +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. diff --git a/crlcore/src/pyCRL/CMakeLists.txt b/crlcore/src/pyCRL/CMakeLists.txt index d7319e74..a19f6adc 100644 --- a/crlcore/src/pyCRL/CMakeLists.txt +++ b/crlcore/src/pyCRL/CMakeLists.txt @@ -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 diff --git a/crlcore/src/pyCRL/PyCRL.cpp b/crlcore/src/pyCRL/PyCRL.cpp index 084669aa..5752a1db 100644 --- a/crlcore/src/pyCRL/PyCRL.cpp +++ b/crlcore/src/pyCRL/PyCRL.cpp @@ -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 ); diff --git a/crlcore/src/pyCRL/PySpice.cpp b/crlcore/src/pyCRL/PySpice.cpp new file mode 100644 index 00000000..7528ed8b --- /dev/null +++ b/crlcore/src/pyCRL/PySpice.cpp @@ -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 +#include + + +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. diff --git a/crlcore/src/pyCRL/crlcore/PySpice.h b/crlcore/src/pyCRL/crlcore/PySpice.h new file mode 100644 index 00000000..24e2856d --- /dev/null +++ b/crlcore/src/pyCRL/crlcore/PySpice.h @@ -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. diff --git a/cumulus/src/plugins/alpha/block/configuration.py b/cumulus/src/plugins/alpha/block/configuration.py index a7604cf5..ee52136e 100644 --- a/cumulus/src/plugins/alpha/block/configuration.py +++ b/cumulus/src/plugins/alpha/block/configuration.py @@ -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 ): diff --git a/cumulus/src/plugins/rsave.py b/cumulus/src/plugins/rsave.py index c69fdcdb..0df225fa 100644 --- a/cumulus/src/plugins/rsave.py +++ b/cumulus/src/plugins/rsave.py @@ -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