Adding spice parser/driver (only database right now, examples code will follow)

Supported grammar is :
    .INCLUDE
    .LIB
    .PARAM
    .OPTION
    .SUBCKT
    Xxxx
    Rxxx
    Cxxx
    Ixxx
    Vxxx

    Mxxx and Dxxx are on the todo list
This commit is contained in:
Damien Dupuis 2011-05-06 09:21:01 +00:00
parent e2f77eb7ee
commit 2f17ce7b37
13 changed files with 925 additions and 0 deletions

View File

@ -6,6 +6,9 @@ ENDIF(IS_DIRECTORY ${VLSISAPD_SOURCE_DIR}/src/openChams)
IF(IS_DIRECTORY ${VLSISAPD_SOURCE_DIR}/src/dtr)
ADD_SUBDIRECTORY(dtr)
ENDIF(IS_DIRECTORY ${VLSISAPD_SOURCE_DIR}/src/dtr)
IF(IS_DIRECTORY ${VLSISAPD_SOURCE_DIR}/src/spice)
ADD_SUBDIRECTORY(spice)
ENDIF(IS_DIRECTORY ${VLSISAPD_SOURCE_DIR}/src/spice)
ADD_SUBDIRECTORY(bookshelf)
ADD_SUBDIRECTORY(configuration)
ADD_SUBDIRECTORY(liberty)

View File

@ -0,0 +1 @@
ADD_SUBDIRECTORY(src)

View File

@ -0,0 +1,33 @@
INCLUDE_DIRECTORIES(${VLSISAPD_SOURCE_DIR}/src/spice/src ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_PATH})
SET ( hpps vlsisapd/spice/Circuit.h
vlsisapd/spice/Subckt.h
vlsisapd/spice/Instance.h
vlsisapd/spice/Instances.h
vlsisapd/spice/Value.h
vlsisapd/spice/Sources.h
vlsisapd/spice/SpiceException.h
)
SET ( cpps Circuit.cpp
Instance.cpp
Value.cpp
)
#SET ( pycpps PySpice.cpp
# )
ADD_LIBRARY(spice ${cpps})
TARGET_LINK_LIBRARIES(spice)
SET_TARGET_PROPERTIES(spice PROPERTIES VERSION 1.0 SOVERSION 1)
INSTALL(TARGETS spice DESTINATION lib${LIB_SUFFIX} )
#IF(Boost_FOUND)
# ADD_LIBRARY(pySPICE MODULE ${pycpps})
# SET_TARGET_PROPERTIES(pySPICE PROPERTIES
# OUTPUT_NAME "SPICE"
# PREFIX ""
# )
# TARGET_LINK_LIBRARIES(pySPICE spice ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
# INSTALL(TARGETS pySPICE DESTINATION ${PYTHON_SITE_PACKAGES})
#ENDIF(Boost_FOUND)
INSTALL(FILES ${hpps} DESTINATION include/vlsisapd/spice)

View File

@ -0,0 +1,435 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <iterator>
using namespace std;
#include "vlsisapd/spice/Circuit.h"
#include "vlsisapd/spice/Value.h"
#include "vlsisapd/spice/Subckt.h"
#include "vlsisapd/spice/Instances.h"
#include "vlsisapd/spice/Sources.h"
#include "vlsisapd/spice/SpiceException.h"
namespace SPICE {
#define DEBUG
void Circuit::addOption(string name, string value) {
map<string, string>::iterator it = _options.find(name);
if (it != _options.end()) {
cerr << "[WARNING] SPICE:: Cannot add option " << name
<< " to Circuit since it already exists." << endl;
return;
}
_options[name] = value;
}
void Circuit::addParameter(string name, string value) {
map<string, string>::iterator pit = _parameters.find(name);
if (pit != _parameters.end()) {
cerr << "[WARNING] SPICE:: Cannot add parameter " << name
<< " to Circuit since it already exists." << endl;
return;
}
_parameters[name] = value;
}
Subckt* Circuit::addSubckt(string name) {
Subckt* sub = new Subckt(name);
if (!sub)
throw SpiceException("SPICE::Circuit::addSubckt: Could not create new Subckt !");
_subckts.push_back(sub);
return sub;
}
Circuit* Circuit::readFromFile(const string& filename) {
cerr << "reading file: " << filename << endl;
std::ifstream spfile(filename.c_str());
if (!spfile)
throw SpiceException("SPICE::Circuit::readFromFile: Cannot open file: "+filename+" !");
Circuit* circuit = new Circuit();
if (!circuit)
throw SpiceException("SPICE::Circuit::readFromFile: Cannot create new Circuit !");
string line;
// catch first line
if (getNextLineType(spfile, line) != Circuit::ENDFILE) {
#ifdef DEBUG
cerr << "TITLE | " << line << endl;
#endif
circuit->setTitle(line);
} else {
throw SpiceException("SPICE::Circuit::readFromFile: File seems empty !");
}
bool inSubckt = false; // to know whether parsed line is in subckt or not
Subckt* sub = NULL;
Circuit::LineType type = getNextFullLineType(spfile, line);
while (type != Circuit::ENDFILE) {
// decompose line into tokens
vector<string> tokens;
tokenize(line, tokens);
// based on line type: do something
switch(type) {
case Circuit::INCLUDE:
{
#ifdef DEBUG
cerr << "INCLUDE | " << line << endl;
#endif
circuit->addInclude(tokens[1]);
break;
}
case Circuit::LIBRARY:
{
#ifdef DEBUG
cerr << "LIBRARY | " << line << endl;
#endif
if (tokens.size() == 3)
circuit->addLibrary(tokens[1], tokens[2]); // with LIBTYPE
else
circuit->addLibrary(tokens[1]); // without LIBTYPE
break;
}
case Circuit::PARAM:
{
#ifdef DEBUG
cerr << "PARAM | " << line << endl;
#endif
string name, value;
parametrize(tokens[1], name, value); // value must be a numeric value
circuit->addParameter(name, value);
break;
}
case Circuit::OPTION:
{
#ifdef DEBUG
cerr << "OPTION | " << line << endl;
#endif
for (size_t i = 1 ; i < tokens.size() ; i++) {
string name, value;
parametrize(tokens[i], name, value);
circuit->addOption(name, value);
}
break;
}
case Circuit::SUBCKT:
{
#ifdef DEBUG
cerr << "SUBCKT | " << line << endl;
#endif
if (inSubckt) throw SpiceException("SPICE::Circuit::readFromFile: Found hierarchic .subckt !");
inSubckt = true;
sub = circuit->addSubckt(tokens[1]);
for (size_t i = 2 ; i < tokens.size() ; i++)
sub->addInterface(tokens[i]);
break;
}
case Circuit::ENDSUB:
#ifdef DEBUG
cerr << "ENDSUB | " << line << endl;
#endif
if (!inSubckt) throw SpiceException("SPICE::Circuit::readFromFile: Cannot close Subckt since it was not opened !");
inSubckt = false;
break;
case Circuit::END:
#ifdef DEBUG
cerr << "END | " << line << endl;
#endif
break;
case Circuit::INSTANCE:
{
#ifdef DEBUG
cerr << "INSTANCE | " << line << endl;
#endif
size_t modelIdx = 0;
for (size_t i = tokens.size()-1 ; i >= 1 ; i--) {
if(tokens[i].find("=") == string::npos) {
modelIdx = i;
break;
}
}
Instance* inst = new Instance(tokens[0], tokens[modelIdx]);
for (size_t i = 1 ; i < modelIdx ; i++)
inst->addConnector(tokens[i]);
for (size_t i = modelIdx+1 ; i < tokens.size() ; i++) {
string name, value;
parametrize(tokens[i], name, value);
inst->addParameter(name, value);
}
if (inSubckt) { // must add instance to current subckt
sub->addInstance(inst);
} else { // instance is added to top-level circuit
circuit->addInstance(inst);
}
break;
}
case Circuit::VOLTAGE:
{
#ifdef DEBUG
cerr << "VOLTAGE | " << line << endl;
#endif
circuit->addSource(new Voltage(tokens[0], tokens[1], tokens[2], tokens[3]));
break;
}
case Circuit::CURRENT:
#ifdef DEBUG
cerr << "CURRENT | " << line << endl;
#endif
break;
case Circuit::MOSFET:
{
#ifdef DEBUG
cerr << "MOSFET | " << line << endl;
#endif
break;
}
case Circuit::CAPACITOR:
{
#ifdef DEBUG
cerr << "CAPACITOR| " << line << endl;
#endif
Instance* inst = new Capacitor(tokens[0], tokens[1], tokens[2], tokens[3]);
if (inSubckt) { // must add instance to current subckt
sub->addInstance(inst);
} else { // instance is added to top-level circuit
circuit->addInstance(inst);
}
break;
}
case Circuit::RESISTOR:
{
#ifdef DEBUG
cerr << "RESISTOR | " << line << endl;
#endif
Instance* inst = new Resistor(tokens[0], tokens[1], tokens[2], tokens[3]);
if (inSubckt) { // must add instance to current subckt
sub->addInstance(inst);
} else { // instance is added to top-level circuit
circuit->addInstance(inst);
}
break;
}
case Circuit::DIODE:
#ifdef DEBUG
cerr << "DIODE | " << line << endl;
#endif
break;
case Circuit::UNDEF:
#ifdef DEBUG
cerr << "UNDEF | " << line << endl;
#endif
break;
default:
{
ostringstream oss;
oss << type;
throw SpiceException("SPICE::Circuit::readFromFile: Unkown LineType "+oss.str()+" !");
}
}
// prepare to process next line
type = getNextFullLineType(spfile, line);
}
spfile.close();
return circuit;
}
void Circuit::writeToFile(const string& filename) {
cerr << "writing file: " << filename << endl;
std::ofstream spfile(filename.c_str());
if (!spfile)
throw SpiceException("SPICE::Circuit::writeToFile: Cannot open file: "+filename+" !");
spfile << _title << endl;
spfile << "* generated with VLSISAPD - SPICE parser/driver" << endl << endl;
if (_includes.size()) {
spfile << "* includes" << endl;
for (size_t i = 0 ; i < _includes.size() ; i++)
spfile << ".INCLUDE " << _includes[i] << endl;
spfile << endl;
}
if ( _libraries.size()) {
spfile << "* libraries" << endl;
for (size_t i = 0 ; i < _libraries.size() ; i++)
spfile << ".LIB " << _libraries[i].first << " " << _libraries[i].second << endl;
spfile << endl;
}
if (_parameters.size()) {
spfile << "* parameters" << endl;
for (map<string, string>::const_iterator it = _parameters.begin() ; it != _parameters.end() ; ++it)
spfile << ".PARAM " << (*it).first << "=" << (*it).second << endl;
spfile << endl;
}
if (_options.size()) {
spfile << "* options" << endl;
for (map<string, string>::const_iterator it = _options.begin() ; it != _options.end() ; ++it) {
spfile << ".OPTION " << (*it).first;
if ((*it).second != "")
spfile << "=" << (*it).second;
spfile << endl;
}
spfile << endl;
}
if (_sources.size()) {
spfile << "* sources" << endl;
for (size_t i = 0 ; i < _sources.size() ; i++) {
Source* s = _sources[i];
spfile << s->getName() << " " << s->getPositive() << " " << s->getNegative() << " " << s->getValue() << endl;
}
spfile << endl;
}
if (_subckts.size()) {
spfile << "* subckts" << endl;
for (size_t i = 0 ; i < _subckts.size() ; i++) {
Subckt* sub = _subckts[i];
spfile << ".SUBCKT " << sub->getName();
for (size_t j = 0 ; j < sub->getInterfaces().size() ; j++)
spfile << " " << sub->getInterfaces()[j];
spfile << endl;
for (size_t j = 0 ; j < sub->getInstances().size() ; j++) {
Instance* inst = sub->getInstances()[j];
writeInstance(spfile, inst);
}
spfile << ".ENDS " << sub->getName()<< endl << endl; // to separate consecutive subckts
}
}
if (_instances.size()) {
spfile << "* instances" << endl;
for (size_t i = 0 ; i < _instances.size() ; i++) {
Instance* inst = _instances[i];
writeInstance(spfile, inst);
}
}
spfile << ".END" << endl;
spfile.close();
}
// this method ignores comment/empty lines and concatenates "+ lines"
Circuit::LineType Circuit::getNextFullLineType(std::ifstream& file, string& fullLine) {
string line;
Circuit::LineType type = getNextLineType(file, line);
while ((type == Circuit::COMMENT) || (type == Circuit::EMPTY)) {
type = getNextLineType(file, line);
}
Circuit::LineType baseType = type; // non empty/comment line
fullLine = string(line);
int lineStart = file.tellg();
type = getNextLineType(file, line);
while ((type == Circuit::CONTINUE) || (type == Circuit::EMPTY) || (type == Circuit::COMMENT)) {
if (type == Circuit::CONTINUE) {
fullLine += line.erase(0,1); // remove the '+' sign
} else {
// // it is a comment/empty line
}
lineStart = file.tellg();
type = getNextLineType(file, line);
}
//
file.seekg(lineStart); // unget last line which is needed (at worst we wil reread a comment)
return baseType;
}
Circuit::LineType Circuit::getNextLineType(std::ifstream& file, string& line) {
if (getline(file, line)) {
if (lineBeginsWith(line, "*")) return Circuit::COMMENT;
else if (lineBeginsWith(line, ".include")) return Circuit::INCLUDE;
else if (lineBeginsWith(line, ".lib")) return Circuit::LIBRARY;
else if (lineBeginsWith(line, ".param")) return Circuit::PARAM;
else if (lineBeginsWith(line, ".option")) return Circuit::OPTION;
else if (lineBeginsWith(line, ".subckt")) return Circuit::SUBCKT;
else if (lineBeginsWith(line, ".ends")) return Circuit::ENDSUB;
else if (lineBeginsWith(line, ".end")) return Circuit::END;
else if (lineBeginsWith(line, "+")) return Circuit::CONTINUE;
else if (lineBeginsWith(line, "x")) return Circuit::INSTANCE;
else if (lineBeginsWith(line, "m")) return Circuit::MOSFET;
else if (lineBeginsWith(line, "v")) return Circuit::VOLTAGE;
else if (lineBeginsWith(line, "i")) return Circuit::CURRENT;
else if (lineBeginsWith(line, "c")) return Circuit::CAPACITOR;
else if (lineBeginsWith(line, "r")) return Circuit::RESISTOR;
else if (lineBeginsWith(line, "d")) return Circuit::DIODE;
else if (line == "") return Circuit::EMPTY;
else return Circuit::UNDEF;
} else {
return Circuit::ENDFILE;
}
}
bool Circuit::lineBeginsWith(string line, string substr) {
int size = substr.size();
string substrU (substr);
transform(substrU.begin(), substrU.end(), substrU.begin(), ::toupper);
if((!line.compare(0, size, substr)) or (!line.compare(0, size, substrU)))
return true;
return false;
}
void Circuit::cleanMultipleSpaces(string& line) {
size_t it;
// first replace all tabs with spaces
string search = "\t";
while ((it = line.find(search)) != string::npos)
line.replace(it, 1, " ");
// then remove multiple spaces
search = " ";
while ((it = line.find(search)) != string::npos)
line.erase(it, 1);
// finally replace ' = ' with '=' in two steps
search = " =";
while ((it = line.find(search)) != string::npos)
line.erase(it, 1);
search = "= ";
while ((it = line.find(search)) != string::npos)
line.erase(it+1, 1);
}
void Circuit::tokenize(string line, vector<string>& tokens) {
cleanMultipleSpaces(line);
istringstream iss(line);
copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter<vector<string> >(tokens));
}
void Circuit::parametrize(string param, string& name, string& value) {
size_t it = param.find("=");
if (it == string::npos) {
name = param;
value = "";
} else {
name = param.substr(0, it);
value = param.substr(it+1, param.size()-it);
}
cerr << "parametrize: " << name << "=" << value << endl;
}
void Circuit::writeInstance(std::ofstream& file, Instance* inst) {
if (dynamic_cast<Mosfet*>(inst)) {
} else if (dynamic_cast<Capacitor*>(inst)) {
Capacitor* capa = static_cast<Capacitor*>(inst);
file << capa->getName() << " " << capa->getPositive() << " " << capa->getNegative() << " " << capa->getValue();
} else if (dynamic_cast<Resistor*>(inst)) {
Resistor* res = static_cast<Resistor*>(inst);
file << res->getName() << " " << res->getFirst() << " " << res->getSecond() << " " << res->getValue();
} else {
file << inst->getName();
for (vector<string>::const_iterator it = inst->getConnectors().begin() ; it != inst->getConnectors().end() ; ++it) {
file << " " << (*it);
}
file << " " << inst->getModel();
int j=0;
for (map<string, string>::const_iterator it = inst->getParameters().begin() ; it != inst->getParameters().end() ; ++it, j++) {
if (j%6 == 0)
file << endl << "+";
file << " " << (*it).first << "=" << (*it).second;
}
}
file << endl << endl; // to separate to consecutive instances
}
}

View File

@ -0,0 +1,29 @@
#include <iostream>
using namespace std;
#include "vlsisapd/spice/Instance.h"
#include "vlsisapd/spice/Value.h"
namespace SPICE {
Instance::Instance(string name, string model) : _name(name), _model(model)
{}
string Instance::getParameterValue(string name) {
map<string, string>::iterator pit = _parameters.find(name);
if (pit != _parameters.end()) {
return (*pit).second;
} else {
return "";
}
}
void Instance::addParameter(string name, string value) {
map<string, string>::iterator pit = _parameters.find(name);
if (pit != _parameters.end()) {
cerr << "[WARNING] SPICE:: Cannot add parameter " << name
<< " to instance " << _name << " since it already exists." << endl;
return;
}
_parameters[name] = value;
}
}

View File

@ -0,0 +1,69 @@
#include <iostream>
#include <sstream>
using namespace std;
#include "vlsisapd/spice/Value.h"
#include "vlsisapd/spice/SpiceException.h"
namespace SPICE {
Value::Value(double value, Value::Unit unit): _value(value), _unit(unit)
{}
double Value::getUnitAsDouble(Value::Unit unit) {
switch(unit) {
case Value::T: return 1e12; // T
case Value::G: return 1e9; // G
case Value::Meg: return 1e6; // Meg
case Value::K: return 1e3; // K
case Value::Unity: return 1; // Unity
case Value::m: return 1e-3; // m
case Value::u: return 1e-6; // u
case Value::n: return 1e-9; // n
case Value::p: return 1e-12; // p
case Value::f: return 1e-15; // f
default: throw SpiceException("SPICE:: Unknown unit for Value !");
}
}
double Value::getConvertedDouble(Value::Unit unit) {
return _value * (getUnitAsDouble(_unit)/getUnitAsDouble(unit));
}
void Value::print() {
switch(_unit) {
case Value::T: cerr << _value << " T" << endl; break;
case Value::G: cerr << _value << " G" << endl; break;
case Value::Meg: cerr << _value << " Meg" << endl; break;
case Value::K: cerr << _value << " K" << endl; break;
case Value::m: cerr << _value << " m" << endl; break;
case Value::u: cerr << _value << " u" << endl; break;
case Value::n: cerr << _value << " n" << endl; break;
case Value::p: cerr << _value << " p" << endl; break;
case Value::f: cerr << _value << " f" << endl; break;
default: cerr << _value << endl; break;
}
}
Value* Value::string2Value(string str) {
size_t it = str.find_last_of("0123456789");
if (it == string::npos)
throw SpiceException("SPICE::Value::string2Value: Could not correctly identify value.");
istringstream iss;
iss.str(str.substr(0, it+1));
double val;
iss >> val;
string unit = str.substr(it+1);
Value* value= NULL;
if (!unit.compare(0, 1, "T") ) value = new Value(val, Value::T);
else if (!unit.compare(0, 1, "G") ) value = new Value(val, Value::G);
else if (!unit.compare(0, 3, "Meg")) value = new Value(val, Value::Meg);
else if (!unit.compare(0, 1, "K") ) value = new Value(val, Value::K);
else if (!unit.compare(0, 1, "m") ) value = new Value(val, Value::m);
else if (!unit.compare(0, 1, "u") ) value = new Value(val, Value::u);
else if (!unit.compare(0, 1, "n") ) value = new Value(val, Value::n);
else if (!unit.compare(0, 1, "p") ) value = new Value(val, Value::p);
else if (!unit.compare(0, 1, "f") ) value = new Value(val, Value::f);
else value = new Value(val, Value::Unity);
return value;
}
}

View File

@ -0,0 +1,108 @@
#ifndef __SPICE_CIRCUIT_H
#define __SPICE_CIRCUIT_H
#include <string>
#include <vector>
#include <map>
class ifstream;
namespace SPICE {
class Value;
class Subckt;
class Instance;
class Source;
class Circuit {
public:
enum LineType { ENDFILE = -2 // means the getline failed : should only happens at end of file
, UNDEF = -1 // not recognized
, EMPTY = 0 // empty line
, COMMENT = 1 // begins with '*...'
, INCLUDE = 2 // begins with '.include '
, LIBRARY = 3 // begins with '.lib '
, OPTION = 4 // begins with '.option '
, PARAM = 5 // begins with '.param '
, SUBCKT = 6 // begins with '.subckt '
, CONTINUE = 7 // begins with '+ '
, ENDSUB = 8 // begins with '.ends '
, END = 9 // begins with '.end '
, INSTANCE = 20 // begins with 'x...'
, MOSFET = 21 // begins with 'm...'
, CAPACITOR = 22 // begins with 'c...'
, RESISTOR = 23 // begins with 'r...'
, INDUCTOR = 24 // begins with 'l...'
, DIODE = 25 // begins with 'd...'
, VOLTAGE = 30 // begins with 'v...' voltage source
, CURRENT = 31 // begins with 'i...' current source
};
typedef std::pair<std::string, std::string> string_pair;
typedef std::vector<string_pair> strpair_vector;
typedef std::vector<std::string> string_vector;
typedef std::map<std::string, std::string> strings_map;
private:
unsigned _line;
std::string _title;
string_vector _includes;
strpair_vector _libraries;
strings_map _options;
strings_map _parameters;
std::vector<Subckt*> _subckts;
std::vector<Instance*> _instances;
std::vector<Source*> _sources;
public:
Circuit(): _line(0), _title(""), _includes(), _libraries(), _options(), _parameters(), _subckts(), _instances() {};
~Circuit() {};
inline std::string getTitle();
inline const string_vector& getIncludes();
inline const strpair_vector& getLibraries();
inline const strings_map& getOptions();
inline const strings_map& getParameters();
inline const std::vector<Subckt*>& getSubckts();
inline const std::vector<Instance*>& getInstances();
inline const std::vector<Source*>& getSources();
inline void setTitle (std::string);
inline void addInclude (std::string);
inline void addLibrary (std::string file, std::string type = "");
inline void addInstance(Instance*);
inline void addSource (Source*);
void addOption (std::string, std::string);
void addParameter(std::string, std::string);
Subckt* addSubckt (std::string);
static Circuit* readFromFile(const std::string&);
void writeToFile (const std::string&);
private:
static Circuit::LineType getNextLineType (std::ifstream& file, std::string& line);
static Circuit::LineType getNextFullLineType(std::ifstream& file, std::string& fullLine);
static bool lineBeginsWith (std::string line, std::string substr);
static void cleanMultipleSpaces(std::string&);
static void tokenize (std::string line, std::vector<std::string>& tokens);
static void parametrize (std::string param, std::string& name, std::string& value);
static void writeInstance (std::ofstream& file, Instance* inst);
};
inline std::string Circuit::getTitle() { return _title; }
inline const Circuit::string_vector& Circuit::getIncludes() { return _includes; }
inline const Circuit::strpair_vector& Circuit::getLibraries() { return _libraries; }
inline const Circuit::strings_map& Circuit::getOptions() { return _options; }
inline const Circuit::strings_map& Circuit::getParameters() { return _parameters; }
inline const std::vector<Subckt*>& Circuit::getSubckts() { return _subckts; }
inline const std::vector<Instance*>& Circuit::getInstances() { return _instances; }
inline const std::vector<Source*>& Circuit::getSources() { return _sources; }
inline void Circuit::setTitle (std::string title) { _title = title; }
inline void Circuit::addInclude (std::string include) { _includes.push_back(include); }
inline void Circuit::addLibrary (std::string file, std::string type) { _libraries.push_back(Circuit::string_pair(file, type)); }
inline void Circuit::addInstance(Instance* inst) { _instances.push_back(inst); }
inline void Circuit::addSource (Source* source) {_sources.push_back(source); }
}
#endif

View File

@ -0,0 +1,43 @@
#ifndef __SPICE_INSTANCE_H
#define __SPICE_INSTANCE_H
#include <string>
#include <vector>
#include <map>
namespace SPICE {
class Value;
class Instance {
protected:
std::string _name;
std::string _model;
std::vector<std::string> _connectors;
std::map<std::string, std::string> _parameters;
public:
Instance(std::string name, std::string model);
virtual ~Instance() {};
inline std::string getName();
inline std::string getModel();
inline const std::vector<std::string>& getConnectors();
inline const std::map<std::string, std::string>& getParameters();
std::string getParameterValue(std::string name);
inline void addConnector(std::string connector);
void addParameter(std::string name, std::string value);
};
inline std::string Instance::getName() { return _name; }
inline std::string Instance::getModel() { return _model; }
inline const std::vector<std::string>& Instance::getConnectors() { return _connectors; }
inline const std::map<std::string, std::string>& Instance::getParameters() { return _parameters; }
inline void Instance::addConnector(std::string connector) { _connectors.push_back(connector); } // no verification : same net can be used on several interfaces
}
#endif

View File

@ -0,0 +1,69 @@
#ifndef __SPICE_INSTANCES_H
#define __SPICE_INSTANCES_H
#include <string>
#include "vlsisapd/spice/Instance.h"
namespace SPICE {
class Mosfet : public Instance {
public:
Mosfet(std::string name, std::string nd, std::string ng, std::string ns, std::string nb, std::string model)
: Instance(name, model), _nd(nd), _ng(ng), _ns(ns), _nb(nb) {}
virtual ~Mosfet() {};
inline std::string getDrain();
inline std::string getGrid();
inline std::string getSource();
inline std::string getBulk();
private:
std::string _nd;
std::string _ng;
std::string _ns;
std::string _nb;
};
inline std::string Mosfet::getDrain() { return _nd; }
inline std::string Mosfet::getGrid() { return _ng; }
inline std::string Mosfet::getSource() { return _ns; }
inline std::string Mosfet::getBulk() { return _nb; }
class Resistor : public Instance {
public:
Resistor(std::string name, std::string first, std::string second, std::string value)
: Instance(name, ""), _first(first), _second(second), _value(value) {}
virtual ~Resistor() {};
inline std::string getFirst();
inline std::string getSecond();
inline std::string getValue();
private:
std::string _first;
std::string _second;
std::string _value;
};
inline std::string Resistor::getFirst() { return _first; }
inline std::string Resistor::getSecond() { return _second; }
inline std::string Resistor::getValue() { return _value; }
class Capacitor : public Instance {
public:
Capacitor(std::string name, std::string pos, std::string neg, std::string value)
: Instance(name, ""), _pos(pos), _neg(neg), _value(value) {}
virtual ~Capacitor() {};
inline std::string getPositive();
inline std::string getNegative();
inline std::string getValue();
private:
std::string _pos;
std::string _neg;
std::string _value;
};
inline std::string Capacitor::getPositive() { return _pos; };
inline std::string Capacitor::getNegative() { return _neg; };
inline std::string Capacitor::getValue() { return _value; };
}
#endif

View File

@ -0,0 +1,39 @@
#ifndef __SPICE_SOURCES_H
#define __SPICE_SOURCES_H
namespace SPICE {
class Source {
private:
std::string _name;
std::string _pos;
std::string _neg;
std::string _value;
protected:
Source(std::string name, std::string pos, std::string neg, std::string value): _name(name), _pos(pos), _neg(neg), _value(value) {}
virtual ~Source() {}
public:
inline std::string getName();
inline std::string getPositive();
inline std::string getNegative();
inline std::string getValue();
};
inline std::string Source::getName() { return _name; }
inline std::string Source::getPositive() { return _pos; }
inline std::string Source::getNegative() { return _neg; }
inline std::string Source::getValue() { return _value; }
class Voltage: public Source {
public:
Voltage(std::string name, std::string pos, std::string neg, std::string value): Source(name, pos, neg, value) {}
~Voltage() {}
};
class Current: public Source {
public:
Current(std::string name, std::string pos, std::string neg, std::string value): Source(name, pos, neg, value) {}
~Current() {}
};
}
#endif

View File

@ -0,0 +1,20 @@
#ifndef __SPICE_EXCEPTION_H
#define __SPICE_EXCEPTION_H
#include <exception>
#include <string>
namespace SPICE {
class SpiceException {
public:
SpiceException(const std::string& what) throw() : _what(what) {}
virtual const char* what() const throw() { return _what.c_str(); }
virtual ~SpiceException() throw() {}
private:
std::string _what;
};
} // namespace
#endif

View File

@ -0,0 +1,35 @@
#ifndef __SPICE_SUBCKT_H
#define __SPICE_SUBCKT_H
#include <string>
#include <vector>
namespace SPICE {
class Instance;
class Subckt {
private:
std::string _name;
std::vector<std::string> _interfaces;
std::vector<Instance*> _instances;
public:
Subckt(std::string name): _name(name), _interfaces(), _instances() {}
~Subckt() {}
inline std::string getName();
inline std::vector<std::string>& getInterfaces();
inline std::vector<Instance*>& getInstances();
inline void addInterface(std::string);
inline void addInstance (Instance*);
};
inline std::string Subckt::getName() { return _name; }
inline std::vector<std::string>& Subckt::getInterfaces() { return _interfaces; }
inline std::vector<Instance*>& Subckt::getInstances() { return _instances; }
inline void Subckt::addInterface(std::string name) { _interfaces.push_back(name); }
inline void Subckt::addInstance(Instance* inst) { _instances.push_back(inst); }
}
#endif

View File

@ -0,0 +1,41 @@
#ifndef __SPICE_VALUE_H
#define __SPICE_VALUE_H
#include <string>
namespace SPICE {
class Value {
public:
enum Unit { T = 0
, G = 1
, Meg = 2
, K = 3
, Unity = 4
, m = 5
, u = 6
, n = 7
, p = 8
, f = 9
};
private:
double _value;
Unit _unit;
public:
Value(double value, Unit unit);
virtual ~Value() {};
inline double getDouble();
inline Unit getUnit();
static double getUnitAsDouble(Unit unit);
double getConvertedDouble(Unit unit);
void print();
static Value* string2Value(std::string);
};
inline double Value::getDouble() { return _value; }
inline Value::Unit Value::getUnit() { return _unit; }
}
#endif