Added support for SPICE terminal ordering from .spi files.
After a Cell has been created in memory (by parsers or Python scripts) we can annotate it with the Spice parser so it will know the right order with which to create the subcircuit call ('x'). * New: In CRL::Spice::load(), add support to read the ".subckt" card and guess the right ordering for generating the 'x' (subcircuit card call). * Bug: In Spice::SpiceBit & Spice::BitExtension, when a Net bit property is removed, if it's the currently cached property in BitExtension it may lead to a crash. So when a property is destroyed, we must also clear the cache (see remove(), clearCache() & onReleasedby()). I'm wary that this could also happen on other kind of cached extensions... * New: In CRL::NamingScheme, new method vhdlToVlog() to translate back VHDL net name into Verilog. Currently only changes "()" into "[]". Used to generate the commented SPICE interface for Alliance compliance. * Change: In Spice::Entity, previously all the ordering where removed between each run of the SPICE parser, but the orders read from SPICE file (mostly standard cells) must be kept. So add a flag ReferenceCell to prevent the removal by ::destroyAll().
This commit is contained in:
parent
fd624f03b6
commit
4ffd91822f
|
@ -31,9 +31,11 @@ namespace CRL {
|
|||
|
||||
|
||||
class Spice {
|
||||
public:
|
||||
static const uint64_t PIN_ORDERING = (1<<0);
|
||||
public:
|
||||
static bool save ( Cell*, uint64_t flags );
|
||||
static bool load ( Library*, std::string spicePath );
|
||||
static bool load ( Library*, std::string spicePath, uint64_t mode );
|
||||
static void clearProperties ();
|
||||
};
|
||||
|
||||
|
|
|
@ -61,9 +61,6 @@ namespace Spice {
|
|||
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(); }
|
||||
|
@ -82,6 +79,7 @@ namespace Spice {
|
|||
static Name getPropertyName ();
|
||||
virtual Name getName () const;
|
||||
inline Bit* getBit ();
|
||||
inline Net* getNet ();
|
||||
inline std::string getBitName () const;
|
||||
virtual void onReleasedBy ( DBo* owner );
|
||||
virtual std::string _getTypeName () const;
|
||||
|
@ -100,6 +98,7 @@ namespace Spice {
|
|||
: PrivateProperty(), _bit(this,owner,index)
|
||||
{ }
|
||||
|
||||
inline Net* BitProperty::getNet () { return const_cast<Net*>( _bit.getNet() ); }
|
||||
inline Bit* BitProperty::getBit () { return &_bit; }
|
||||
inline std::string BitProperty::getBitName () const { return _bit.getName(); }
|
||||
|
||||
|
@ -112,7 +111,9 @@ namespace Spice {
|
|||
static inline size_t getIndex ( const Net* );
|
||||
static inline std::string getName ( const Net* );
|
||||
static Bit* get ( const Net* );
|
||||
static void remove ( const Net* );
|
||||
static Bit* create ( Net*, size_t index=Bit::nindex );
|
||||
static inline void clearCache ( Net* );
|
||||
private:
|
||||
static const Net* _owner;
|
||||
static Bit* _cache;
|
||||
|
@ -125,13 +126,15 @@ namespace Spice {
|
|||
return (bit == NULL) ? false : bit->getIndex();
|
||||
}
|
||||
|
||||
|
||||
inline std::string BitExtension::getName ( const Net* net )
|
||||
{
|
||||
Bit* bit = get( net );
|
||||
return (bit == NULL) ? "?" : bit->getName();
|
||||
}
|
||||
|
||||
inline void BitExtension::clearCache ( Net* net )
|
||||
{ if (_owner == net) { _owner = NULL; _cache = NULL; } }
|
||||
|
||||
|
||||
inline BitProperty* Bit::getProperty () const { return (BitProperty*)((ptrdiff_t)(this) - _offset); }
|
||||
inline const Net* Bit::getNet () const { return (const Net*)getProperty()->getOwner(); }
|
||||
|
|
|
@ -51,6 +51,7 @@ namespace Spice {
|
|||
class Entity {
|
||||
public:
|
||||
static const uint64_t TopCell = (1 << 0);
|
||||
static const uint64_t ReferenceCell = (1 << 1);
|
||||
public:
|
||||
static std::vector<Entity*>&
|
||||
getAllEntities ();
|
||||
|
@ -58,9 +59,14 @@ namespace Spice {
|
|||
public:
|
||||
Entity ( EntityProperty*, Cell*, uint64_t flags );
|
||||
~Entity ();
|
||||
inline bool isTopCell () const;
|
||||
inline bool isReferenceCell () const;
|
||||
inline uint64_t getFlags () const;
|
||||
const Cell* getCell () const;
|
||||
inline const BitVector& getBits () const;
|
||||
inline const std::vector<Bit*>&
|
||||
getBits () const;
|
||||
inline void setFlags ( uint64_t );
|
||||
void setOrder ( const std::vector<Net*>& );
|
||||
void toNodeList ( ostream&, bool asInterf=true ) const;
|
||||
void toEntity ( ostream& ) const;
|
||||
std::string _getString () const;
|
||||
|
@ -68,15 +74,18 @@ namespace Spice {
|
|||
private:
|
||||
static std::vector<Entity*> _entities;
|
||||
static std::ptrdiff_t _offset;
|
||||
BitVector _bits;
|
||||
std::vector<Bit*> _bits;
|
||||
size_t _powerNode;
|
||||
size_t _groundNode;
|
||||
uint64_t _flags;
|
||||
};
|
||||
|
||||
|
||||
inline bool Entity::isTopCell () const { return _flags & TopCell; }
|
||||
inline bool Entity::isReferenceCell () const { return _flags & ReferenceCell; }
|
||||
inline uint64_t Entity::getFlags () const { return _flags; }
|
||||
inline const BitVector& Entity::getBits () const { return _bits; }
|
||||
inline const std::vector<Bit*>& Entity::getBits () const { return _bits; }
|
||||
inline void Entity::setFlags ( uint64_t flags ) { _flags |= flags; }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
|
|
@ -74,6 +74,7 @@ namespace CRL {
|
|||
public:
|
||||
typedef std::function< Name(const Name&,uint32_t) > converter_t;
|
||||
public:
|
||||
static Name vhdlToVlog ( const Name& vhdlName );
|
||||
static Name vlogToVhdl ( const Name& vlogName, uint32_t flags );
|
||||
static void toVhdl ( Cell* topCell, uint32_t flags );
|
||||
NamingScheme ( uint32_t flags );
|
||||
|
|
|
@ -102,7 +102,10 @@ namespace Spice {
|
|||
|
||||
|
||||
void BitProperty::onReleasedBy ( DBo* owner )
|
||||
{ PrivateProperty::onReleasedBy( owner ); }
|
||||
{
|
||||
BitExtension::clearCache( static_cast<Net*>(owner) );
|
||||
PrivateProperty::onReleasedBy( owner );
|
||||
}
|
||||
|
||||
|
||||
Name BitProperty::getPropertyName ()
|
||||
|
@ -145,6 +148,16 @@ namespace Spice {
|
|||
Bit* BitExtension::_cache = NULL;
|
||||
|
||||
|
||||
void BitExtension::remove ( const Net* net )
|
||||
{
|
||||
Property* property = net->getProperty( BitProperty::getPropertyName() );
|
||||
if (property) {
|
||||
const_cast<Net*>( net )->remove( property );
|
||||
}
|
||||
if (net == _owner) _owner = NULL;
|
||||
}
|
||||
|
||||
|
||||
Bit* BitExtension::get ( const Net* net )
|
||||
{
|
||||
if (net == _owner) return _cache;
|
||||
|
|
|
@ -21,18 +21,6 @@
|
|||
#include "crlcore/SpiceEntity.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using Hurricane::Net;
|
||||
using Hurricane::Instance;
|
||||
using Hurricane::Occurrence;
|
||||
using Spice::Bit;
|
||||
using Spice::Entity;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace Spice {
|
||||
|
||||
using namespace std;
|
||||
|
@ -41,6 +29,8 @@ namespace Spice {
|
|||
using Hurricane::Property;
|
||||
using Hurricane::_TName;
|
||||
using Hurricane::Plug;
|
||||
using Hurricane::Occurrence;
|
||||
using CRL::NamingScheme;
|
||||
|
||||
|
||||
class ComparePlugBySpiceIndex {
|
||||
|
@ -64,6 +54,7 @@ namespace Spice {
|
|||
, _groundNode(Bit::nindex)
|
||||
, _flags(flags)
|
||||
{
|
||||
//cerr << "Entity::Entity() on " << cell << endl;
|
||||
if (not _offset) {
|
||||
//_offset = offsetof(EntityProperty,_entity);
|
||||
_offset = (ptrdiff_t)this - (ptrdiff_t)property;
|
||||
|
@ -84,15 +75,31 @@ namespace Spice {
|
|||
}
|
||||
|
||||
|
||||
void Entity::setOrder ( const vector<Net*>& orderedNets )
|
||||
{
|
||||
for ( auto bit : _bits )
|
||||
BitExtension::remove( bit->getNet() );
|
||||
_bits.clear();
|
||||
|
||||
for ( auto net : orderedNets ) {
|
||||
Bit* bit = BitExtension::create( net, _bits.size() );
|
||||
_bits.push_back( bit );
|
||||
if (net->isPower ()) _powerNode = bit->getIndex();
|
||||
if (net->isGround()) _groundNode = bit->getIndex();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Entity::~Entity ()
|
||||
{
|
||||
for ( auto bit : _bits ) bit->destroy();
|
||||
for ( auto ientity=_entities.begin() ; ientity!=_entities.end() ; ++ientity ) {
|
||||
if (*ientity == this) {
|
||||
_entities.erase( ientity );
|
||||
break;
|
||||
}
|
||||
}
|
||||
for ( auto bit : _bits )
|
||||
BitExtension::remove( bit->getNet() );
|
||||
}
|
||||
|
||||
|
||||
|
@ -122,9 +129,13 @@ namespace Spice {
|
|||
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";
|
||||
if (asInterf) {
|
||||
out << "* " << "INTERF" //<< setw(6) << BitExtension::getName(net)
|
||||
<< " " << NamingScheme::vhdlToVlog(net->getName()) << "\n";
|
||||
} else {
|
||||
out << "* " << "NET" << setw(6) << BitExtension::getName(net)
|
||||
<< " = " << NamingScheme::vhdlToVlog(net->getName()) << "\n";
|
||||
}
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
@ -233,7 +244,7 @@ namespace Spice {
|
|||
{
|
||||
Record* record = new Record ( "<Entity " + _getString() + " >" );
|
||||
if (record != NULL) {
|
||||
record->add( getSlot("_bits" , _bits ) );
|
||||
record->add( getSlot("_bits" , &_bits ) );
|
||||
record->add( getSlot("_powerNode" , _powerNode ) );
|
||||
record->add( getSlot("_groundNode", _groundNode ) );
|
||||
record->add( getSlot("_flags" , _flags ) );
|
||||
|
@ -340,8 +351,17 @@ namespace Spice {
|
|||
void EntityExtension::destroyAll ()
|
||||
{
|
||||
vector<Entity*>& entities = Entity::getAllEntities();
|
||||
size_t current = 0;
|
||||
while ( current < entities.size() ) {
|
||||
if (entities[current]->isReferenceCell()) {
|
||||
++current;
|
||||
} else {
|
||||
//cerr << "Destroy SPICE entity on " << entities[current]->getCell() << endl;
|
||||
destroy( const_cast<Cell*>(entities[current]->getCell()) );
|
||||
}
|
||||
}
|
||||
|
||||
while ( not entities.empty() ) destroy( const_cast<Cell*>(entities.back()->getCell()) );
|
||||
//while ( not entities.empty() ) destroy( const_cast<Cell*>(entities.back()->getCell()) );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include <cctype>
|
||||
#include <ctime>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
@ -23,7 +24,7 @@
|
|||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
using namespace std;
|
||||
|
||||
#include "hurricane/configuration/Configuration.h"
|
||||
|
@ -51,29 +52,293 @@ using namespace Hurricane;
|
|||
#include "crlcore/NetExtension.h"
|
||||
#include "crlcore/ToolBox.h"
|
||||
#include "crlcore/Spice.h"
|
||||
#include "crlcore/SpiceBit.h"
|
||||
#include "crlcore/SpiceEntity.h"
|
||||
using namespace CRL;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace std;
|
||||
using CRL::NamingScheme;
|
||||
|
||||
|
||||
string& uppercase ( string& s )
|
||||
{
|
||||
for ( size_t i=0 ; i<s.size() ; ++i )
|
||||
s[i] = toupper( s[i] );
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "::Tokenize".
|
||||
|
||||
|
||||
class Tokenize {
|
||||
public:
|
||||
static const uint32_t COMMENT = (1<< 0);
|
||||
static const uint32_t END = (1<< 1);
|
||||
static const uint32_t RESISTOR = (1<< 2);
|
||||
static const uint32_t CAPACITOR = (1<< 3);
|
||||
static const uint32_t INDUCTOR = (1<< 4);
|
||||
static const uint32_t COUPLED_INDUCTOR = (1<< 5);
|
||||
static const uint32_t DIODE = (1<< 6);
|
||||
static const uint32_t BJT = (1<< 7);
|
||||
static const uint32_t JFET = (1<< 8);
|
||||
static const uint32_t MOSFET = (1<< 9);
|
||||
static const uint32_t MODEL = (1<< 0);
|
||||
static const uint32_t SUBCKT = (1<<10);
|
||||
static const uint32_t ENDS = (1<<11);
|
||||
static const uint32_t SUBCIRCUIT = (1<<12);
|
||||
public:
|
||||
Tokenize ( string blifFile );
|
||||
inline size_t lineno () const;
|
||||
inline uint32_t flags () const;
|
||||
list<string>& tokens ();
|
||||
bool readEntry ();
|
||||
private:
|
||||
bool _readline ();
|
||||
private:
|
||||
size_t _lineno;
|
||||
uint32_t _flags;
|
||||
ifstream _stream;
|
||||
list<string> _tokens;
|
||||
};
|
||||
|
||||
|
||||
Tokenize::Tokenize ( string spiceFile )
|
||||
: _lineno (0)
|
||||
, _flags (0)
|
||||
, _stream ()
|
||||
, _tokens ()
|
||||
{
|
||||
_stream.open( spiceFile );
|
||||
if (_stream.fail())
|
||||
throw Error( "Unable to open SPICE file %s\n", spiceFile.c_str() );
|
||||
}
|
||||
|
||||
|
||||
inline size_t Tokenize::lineno () const { return (_lineno) ? _lineno-1 : 0; }
|
||||
inline uint32_t Tokenize::flags () const { return _flags; }
|
||||
inline list<string>& Tokenize::tokens () { return _tokens; }
|
||||
|
||||
|
||||
bool Tokenize::readEntry ()
|
||||
{
|
||||
_flags = 0;
|
||||
|
||||
if (_stream.eof()) return false;
|
||||
|
||||
if (not _readline()) return false;
|
||||
string first = _tokens.front();
|
||||
uppercase( first );
|
||||
if (first[0] == '*' ) { _flags |= COMMENT; }
|
||||
else if (first[0] == '.' ) {
|
||||
if (first == ".MODEL" ) { _flags |= MODEL; }
|
||||
else if (first == ".END" ) { _flags |= END; }
|
||||
else if (first == ".SUBCKT" ) { _flags |= SUBCKT; }
|
||||
else if (first == ".ENDS" ) { _flags |= ENDS; }
|
||||
}
|
||||
else if (first[0] == 'R') { _flags |= RESISTOR; }
|
||||
else if (first[0] == 'C') { _flags |= CAPACITOR; }
|
||||
else if (first[0] == 'L') { _flags |= INDUCTOR; }
|
||||
else if (first[0] == 'K') { _flags |= COUPLED_INDUCTOR; }
|
||||
else if (first[0] == 'D') { _flags |= DIODE; }
|
||||
else if (first[0] == 'Q') { _flags |= BJT; }
|
||||
else if (first[0] == 'J') { _flags |= JFET; }
|
||||
else if (first[0] == 'M') { _flags |= MOSFET; }
|
||||
else if (first[0] == 'X') { _flags |= SUBCIRCUIT; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Tokenize::_readline ()
|
||||
{
|
||||
_tokens.clear();
|
||||
|
||||
bool nextLine = true;
|
||||
|
||||
while ( nextLine ) {
|
||||
if (_stream.eof()) return false;
|
||||
|
||||
nextLine = false;
|
||||
++_lineno;
|
||||
|
||||
string line;
|
||||
getline( _stream, line );
|
||||
|
||||
size_t tokstart = 0;
|
||||
for ( size_t i=0 ; i<line.size() ; ++i ) {
|
||||
if ((i == 0) and (line[i] == '*')) {
|
||||
_tokens.push_back( line );
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t nextTokstart = i+1;
|
||||
switch ( line[i] ) {
|
||||
case ' ':
|
||||
case '\t': break;
|
||||
default: continue;
|
||||
}
|
||||
if (i > tokstart)
|
||||
_tokens.push_back( line.substr(tokstart,i-tokstart) );
|
||||
tokstart = nextTokstart;
|
||||
}
|
||||
|
||||
if (tokstart < line.size()) {
|
||||
if (line.substr(tokstart) == ";")
|
||||
nextLine = true;
|
||||
else
|
||||
_tokens.push_back( line.substr(tokstart) );
|
||||
}
|
||||
|
||||
if (_tokens.empty())
|
||||
nextLine = true;
|
||||
}
|
||||
|
||||
return not _tokens.empty();
|
||||
}
|
||||
|
||||
|
||||
} // Anonymous namespace.
|
||||
|
||||
|
||||
namespace CRL {
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "CRL::Spice".
|
||||
|
||||
bool Spice::load ( Library* library, string spicePath )
|
||||
bool Spice::load ( Library* library, string spiceFile, uint64_t mode )
|
||||
{
|
||||
if (mode != PIN_ORDERING) {
|
||||
cerr << Error( "Spice::load(): SPICE parser only support PIN_ORDERING mode.\n"
|
||||
" \"%s\"."
|
||||
, spiceFile.c_str()
|
||||
) << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
//DebugSession::open( 101, 110 );
|
||||
UpdateSession::open();
|
||||
|
||||
cerr << Error( "Spice::load(): SPICE parser is not implemented yet.\n"
|
||||
" \"%s\"."
|
||||
, spicePath.c_str()
|
||||
Tokenize tokenize ( spiceFile );
|
||||
|
||||
while ( tokenize.readEntry() ) {
|
||||
if (tokenize.flags() & Tokenize::SUBCKT) {
|
||||
list<string>& tokens = tokenize.tokens();
|
||||
// cerr << "Found SUBCKT:";
|
||||
// for ( const string& item : tokens )
|
||||
// cerr << " " << item;
|
||||
// cerr << endl;
|
||||
|
||||
if (tokens.size() < 2) {
|
||||
cerr << Error( "Spice::load(): Invalid SUBCKT, no parameters at all.\n"
|
||||
" File %s at line %u."
|
||||
, spiceFile.c_str()
|
||||
, tokenize.lineno()
|
||||
) << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
string cellName = *(next( tokens.begin(), 1));
|
||||
Cell* cell = library->getCell( cellName );
|
||||
if (not cell) {
|
||||
cerr << Error( "Spice::load(): Library \"%s\" has no Cell named \"%s\".\n"
|
||||
" File %s at line %u."
|
||||
, getString( library->getName() ).c_str()
|
||||
, getString( cellName ).c_str()
|
||||
, spiceFile.c_str()
|
||||
, tokenize.lineno()
|
||||
) << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
tokens.pop_front();
|
||||
tokens.pop_front();
|
||||
// cerr << "Net order of " << cell;
|
||||
// for ( auto& name : tokens )
|
||||
// cerr << " " << name;
|
||||
// cerr << endl;
|
||||
bool hasErrors = false;
|
||||
vector<Net*> orderedNets;
|
||||
for ( const string& netName : tokens ) {
|
||||
Net* net = cell->getNet( netName );
|
||||
if (not net) {
|
||||
cerr << Error( "Spice::load(): Cell \"%s\" has no Net \"%s\".\n"
|
||||
" File %s at line %u."
|
||||
, getString( cell->getName() ).c_str()
|
||||
, netName.c_str()
|
||||
, spiceFile.c_str()
|
||||
, tokenize.lineno()
|
||||
) << endl;
|
||||
hasErrors = true;
|
||||
continue;
|
||||
}
|
||||
if (not net->isExternal()) {
|
||||
cerr << Error( "Spice::load(): In cell \"%s\", net \"%s\" is *not* external.\n"
|
||||
" File %s at line %u."
|
||||
, getString( cell->getName() ).c_str()
|
||||
, getString( net ->getName() ).c_str()
|
||||
, spiceFile.c_str()
|
||||
, tokenize.lineno()
|
||||
) << endl;
|
||||
hasErrors = true;
|
||||
continue;
|
||||
}
|
||||
orderedNets.push_back( net );
|
||||
}
|
||||
map< string, Net*, greater<string> > internalNets;
|
||||
for ( Net* net : cell->getNets() ) {
|
||||
if (net->isExternal()) continue;
|
||||
internalNets.insert( make_pair( getString(net->getName()), net ) );
|
||||
}
|
||||
for ( auto item : internalNets ) {
|
||||
orderedNets.push_back( item.second );
|
||||
}
|
||||
// for ( Net* net : orderedNets )
|
||||
// cerr << " " << net->getName();
|
||||
// cerr << endl;
|
||||
|
||||
for ( Net* net : cell->getExternalNets() ) {
|
||||
if (find( orderedNets.begin(), orderedNets.end(), net) == orderedNets.end()) {
|
||||
cerr << Error( "Spice::load(): In cell \"%s\", external net \"%s\" *not* ordered.\n"
|
||||
" File %s at line %u."
|
||||
, getString( cell->getName() ).c_str()
|
||||
, getString( net ->getName() ).c_str()
|
||||
, spiceFile.c_str()
|
||||
, tokenize.lineno()
|
||||
) << endl;
|
||||
hasErrors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasErrors) continue;
|
||||
|
||||
::Spice::Entity* spiceEntity = ::Spice::EntityExtension::get( cell );
|
||||
if (spiceEntity) {
|
||||
if (spiceEntity->getFlags() & ::Spice::Entity::ReferenceCell) {
|
||||
cerr << Warning( "Spice::load(): Redefinition of external net order of \"%s\".\n"
|
||||
" (from file: \"%s\")"
|
||||
, getString( cell->getName() ).c_str()
|
||||
, spiceFile.c_str()
|
||||
) << endl;
|
||||
} else {
|
||||
spiceEntity->setFlags( ::Spice::Entity::ReferenceCell );
|
||||
}
|
||||
} else {
|
||||
spiceEntity = ::Spice::EntityExtension::create( cell, ::Spice::Entity::ReferenceCell );
|
||||
}
|
||||
spiceEntity->setOrder( orderedNets );
|
||||
}
|
||||
}
|
||||
|
||||
UpdateSession::close();
|
||||
//DebugSession::close();
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -29,6 +29,20 @@ namespace CRL {
|
|||
using Hurricane::Instance;
|
||||
|
||||
|
||||
Name NamingScheme::vhdlToVlog ( const Name& vhdlName )
|
||||
{
|
||||
string vlogName;
|
||||
|
||||
for ( size_t i=0 ; i<vhdlName.size() ; ++i ) {
|
||||
char translated = vhdlName[i];
|
||||
if (translated == '(' ) translated = '[';
|
||||
if (translated == ')' ) translated = ']';
|
||||
vlogName += translated;
|
||||
}
|
||||
return Name(vlogName);
|
||||
}
|
||||
|
||||
|
||||
Name NamingScheme::vlogToVhdl ( const Name& vlogName, uint32_t flags )
|
||||
{
|
||||
string vhdlName;
|
||||
|
|
|
@ -89,13 +89,14 @@ extern "C" {
|
|||
{
|
||||
cdebug_log(30,0) << "PySpice_load()" << endl;
|
||||
|
||||
char* path = NULL;
|
||||
|
||||
HTRY
|
||||
unsigned long mode = 0;
|
||||
char* path = NULL;
|
||||
PyObject* pyLibrary = NULL;
|
||||
if (PyArg_ParseTuple( args, "Os:Spice.load", &pyLibrary, &path )) {
|
||||
if (PyArg_ParseTuple( args, "Osk:Spice.load", &pyLibrary, &path, &mode )) {
|
||||
if (IsPyLibrary(pyLibrary)) {
|
||||
Spice::load( PYLIBRARY_O(pyLibrary), string(path) );
|
||||
Spice::load( PYLIBRARY_O(pyLibrary), string(path), (uint64_t)mode );
|
||||
} else {
|
||||
PyErr_SetString( ConstructorError, "Spice.load(): Bad parameter type (not a Library)." );
|
||||
return NULL;
|
||||
|
@ -153,7 +154,8 @@ extern "C" {
|
|||
{
|
||||
PyObject* constant;
|
||||
|
||||
LoadObjectConstant(PyTypeSpice.tp_dict,::Spice::Entity::TopCell,"TopCell");
|
||||
LoadObjectConstant(PyTypeSpice.tp_dict,::Spice::Entity::TopCell ,"TopCell");
|
||||
LoadObjectConstant(PyTypeSpice.tp_dict,::CRL::Spice::PIN_ORDERING,"PIN_ORDERING");
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue