!! Adding support for subCircuits !!!

* New <subCircuitsPathes> section in <circuit> that lists the pathes that contain subCircuits xml files

    * New Device object that inherits from simplified Instance object.
        - Instance has a name, a model, some connectors and optionnal parameters
        - Device has the same attributes plus mosType, sourceBulkConnected and transistors

    * Updated readFromFile and wrtieToFile methods to support these modifications

    * Updated parse and drive examples to support these modifications
        - Note: only C++ examples has been updated since my boost.python environment is actually totaly broken

    * New buffer.xml example that uses subCircuits.
This commit is contained in:
Damien Dupuis 2010-11-22 10:21:52 +00:00
parent 3c2062bdd0
commit 5887a0b59f
10 changed files with 194 additions and 65 deletions

View File

@ -3,6 +3,7 @@ INCLUDE_DIRECTORIES(${VLSISAPD_SOURCE_DIR}/src/openChams/src ${LIBXML2_INCLUDE_D
SET ( hpps vlsisapd/openChams/Circuit.h
vlsisapd/openChams/Netlist.h
vlsisapd/openChams/Instance.h
vlsisapd/openChams/Device.h
vlsisapd/openChams/Net.h
vlsisapd/openChams/Name.h
vlsisapd/openChams/Operator.h
@ -17,6 +18,7 @@ SET ( hpps vlsisapd/openChams/Circuit.h
SET ( cpps Circuit.cpp
Netlist.cpp
Instance.cpp
Device.cpp
Net.cpp
Name.cpp
Operator.cpp

View File

@ -17,6 +17,7 @@ using namespace std;
#include "vlsisapd/openChams/Circuit.h"
#include "vlsisapd/openChams/Netlist.h"
#include "vlsisapd/openChams/Instance.h"
#include "vlsisapd/openChams/Device.h"
#include "vlsisapd/openChams/Net.h"
#include "vlsisapd/openChams/Schematic.h"
#include "vlsisapd/openChams/SimulModel.h"
@ -38,6 +39,7 @@ namespace {
namespace OpenChams {
static bool readSubCircuitsPathesDone = false;
static bool readCircuitParametersDone = false;
static bool readSimulModelsDone = false;
static bool readNetListDone = false;
@ -48,6 +50,7 @@ static bool readSizingDone = false;
static bool readLayoutDone = false;
Circuit::Circuit(Name name, Name techno) : _name(name), _techno(techno), _netlist(NULL), _schematic(NULL), _sizing(NULL), _layout(NULL) {
readSubCircuitsPathesDone = false;
readCircuitParametersDone = false;
readSimulModelsDone = false;
readNetListDone = false;
@ -142,6 +145,32 @@ Name Circuit::readConnector(xmlNode* node) {
}
// CIRCUIT //
void Circuit::readSubCircuitsPathes(xmlNode* node) {
if (readSubCircuitsPathesDone) {
cerr << "[WARNING] Only one 'subCircuitsPathes' node is allowed in circuit, others will be ignored." << endl;
return;
}
if (node->type == XML_ELEMENT_NODE && node->children) {
for (xmlNode* pathNode = node->children ; pathNode ; pathNode = pathNode->next) {
if (pathNode->type == XML_ELEMENT_NODE) {
if (xmlStrEqual(pathNode->name, (xmlChar*)"path")) {
xmlChar* pathC = xmlGetProp(pathNode, (xmlChar*)"path");
if (pathC) {
string path((const char*)pathC);
_subCircuitsPathes.push_back(path);
} else {
throw OpenChamsException("[ERROR] 'path' node must have 'path' property.");
}
} else {
cerr << "[WARNING] Only 'path' nodes are allowed under 'subCircuitsPathes' node." << endl;
return;
}
}
}
}
readSubCircuitsPathesDone = true;
}
void Circuit::readCircuitParameters(xmlNode* node) {
if (readCircuitParametersDone) {
cerr << "[WARNING] Only one 'parameters' node is allowed in circuit, others will be ignored." << endl;
@ -281,7 +310,7 @@ Instance* Circuit::readInstance(xmlNode* node, Netlist* netlist) {
xmlChar* iMOSC = xmlGetProp(node, (xmlChar*)"mostype");
xmlChar* iSBCC = xmlGetProp(node, (xmlChar*)"sourceBulkConnected");
Instance* inst = NULL;
if (iNameC && iModelC && iMOSC && iSBCC) {
if (iNameC && iModelC && iMOSC && iSBCC) { // this is a device
Name instanceName((const char*)iNameC);
Name modelName((const char*)iModelC);
string mosStr((const char*)iMOSC);
@ -293,9 +322,13 @@ Instance* Circuit::readInstance(xmlNode* node, Netlist* netlist) {
vector<string> sbcComps(sbcComp, sbcComp+4);
check_lowercase(sourceBulkStr, sbcComps, "[ERROR] In 'instance', 'sourceBulkConnected' must 'true', 'false', 'on' or 'off'.");
bool sourceBulkConnected = ((sourceBulkStr == "true") || (sourceBulkStr == "on")) ? true : false;
inst = netlist->addInstance(instanceName, modelName, Name(mosStr), sourceBulkConnected);
inst = (Instance*)netlist->addDevice(instanceName, modelName, Name(mosStr), sourceBulkConnected);
} else if (iNameC && iModelC && !iMOSC && !iSBCC) { // this is a subcircuit
Name instanceName((const char*)iNameC);
Name modelName((const char*)iModelC);
inst = netlist->addInstance(instanceName, modelName);
} else {
throw OpenChamsException("[ERROR] 'instance' node must have 'name', 'model', 'mostype' and 'sourceBulkConnected' properties.");
throw OpenChamsException("[ERROR] 'instance' node must have ('name' and 'model') or ('name', 'model', 'mostype' and 'sourceBulkConnected') properties.");
//return inst;
}
@ -307,7 +340,9 @@ Instance* Circuit::readInstance(xmlNode* node, Netlist* netlist) {
} else if (xmlStrEqual(node->name, (xmlChar*)"parameters")) {
readInstanceParameters(node, inst);
} else if (xmlStrEqual(node->name, (xmlChar*)"transistors")) {
readInstanceTransistors(node, inst);
if (!dynamic_cast<Device*>(inst))
throw OpenChamsException("[ERROR] Only device 'instance' (with 'mostype' and 'sourceBulkConnected' properties) can have 'transistors' section.");
readInstanceTransistors(node, static_cast<Device*>(inst));
} else {
//cerr << "[WARNING] Only 'parameters' node is allowed in 'instance', others will be ignored." << endl;
cerr << "[WARNING] Only 'conectors', 'transistors' and 'parameters' nodes are allowed in 'instance', others will be ignored." << endl;
@ -352,12 +387,12 @@ void Circuit::readInstanceParameters(xmlNode* node, Instance* inst) {
}
}
void Circuit::readInstanceTransistors(xmlNode* node, Instance* inst) {
void Circuit::readInstanceTransistors(xmlNode* node, Device* dev) {
xmlNode* child = node->children;
for (xmlNode* node = child; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (xmlStrEqual(node->name, (xmlChar*)"transistor")) {
readTransistor(node, inst);
readTransistor(node, dev);
} else {
cerr << "[WARNING] Only 'transistor' nodes are allowed in 'transistors', others will be ignored." << endl;
}
@ -366,12 +401,12 @@ void Circuit::readInstanceTransistors(xmlNode* node, Instance* inst) {
}
}
void Circuit::readTransistor(xmlNode* node, Instance* inst) {
void Circuit::readTransistor(xmlNode* node, Device* dev) {
xmlChar* tNameC = xmlGetProp(node, (xmlChar*)"name");
Transistor* trans = NULL;
if (tNameC) {
Name tName((const char*)tNameC);
trans = inst->addTransistor(tName);
trans = dev->addTransistor(tName);
} else {
throw OpenChamsException("[ERROR] 'transistor' node must have 'name' property.");
//return inst;
@ -708,7 +743,10 @@ Circuit* Circuit::readFromFile(const string filePath) {
xmlNode* child = rootElement->children;
for (xmlNode* node = child; node; node = node->next) {
if (node->type == XML_ELEMENT_NODE) {
if (xmlStrEqual(node->name, (xmlChar*)"parameters")) {
if (xmlStrEqual(node->name, (xmlChar*)"subCircuitsPathes")) {
cir->readSubCircuitsPathes(node);
}
else if (xmlStrEqual(node->name, (xmlChar*)"parameters")) {
cir->readCircuitParameters(node);
}
else if (xmlStrEqual(node->name, (xmlChar*)"simulModels")) {
@ -830,6 +868,7 @@ bool Circuit::writeToFile(string filePath) {
sort(instances.begin(), instances.end(), InstanceNameSort); // sort based on instances' names
for (vector<Instance*>::iterator it = instances.begin() ; it != instances.end() ; ++it) {
Instance* inst = (*it);
Device* dev = dynamic_cast<Device*>(inst);
if (inst->hasNoConnectors()) {
string error("[ERROR] Cannot writeToFile since instance (");
error += inst->getName().getString();
@ -837,27 +876,33 @@ bool Circuit::writeToFile(string filePath) {
throw OpenChamsException(error);
//return false;
}
if (inst->hasNoTransistors()) {
string error("[ERROR] Cannot writeToFile since instance (");
error += inst->getName().getString();
if (dev && dev->hasNoTransistors()) {
string error("[ERROR] Cannot writeToFile since device instance (");
error += dev->getName().getString();
error += ") has no transistors !";
throw OpenChamsException(error);
}
string sourceBulkStr = (inst->isSourceBulkConnected()) ? "True" : "False";
file << " <instance name=\"" << inst->getName().getString() << "\" model=\"" << inst->getModel().getString() << "\" mostype=\"" << inst->getMosType().getString() << "\" sourceBulkConnected=\"" << sourceBulkStr << "\">" << endl;
if (dev) {
string sourceBulkStr = (dev->isSourceBulkConnected()) ? "True" : "False";
file << " <instance name=\"" << dev->getName().getString() << "\" model=\"" << dev->getModel().getString() << "\" mostype=\"" << dev->getMosType().getString() << "\" sourceBulkConnected=\"" << sourceBulkStr << "\">" << endl;
} else {
file << " <instance name=\"" << inst->getName().getString() << "\" model=\"" << inst->getModel().getString() << "\">" << endl;
}
file << " <connectors>" << endl;
for (map<Name, Net*>::const_iterator it = inst->getConnectors().begin() ; it != inst->getConnectors().end() ; ++it) {
file << " <connector name=\"" << (*it).first.getString() << "\"/>" << endl;
}
file << " </connectors>" << endl
<< " <transistors>" << endl;
for (vector<Transistor*>::const_iterator it = inst->getTransistors().begin() ; it != inst->getTransistors().end() ; ++it ) {
Transistor* tr = (*it);
file << " <transistor name=\"" << tr->getName().getString() << "\">" << endl
<< " <connection gate=\"" << tr->getGate().getString() << "\" source=\"" << tr->getSource().getString() << "\" drain=\"" << tr->getDrain().getString() << "\" bulk=\"" << tr->getBulk().getString() << "\"/>" << endl
<< " </transistor>" << endl;
file << " </connectors>" << endl;
if (dev) {
file << " <transistors>" << endl;
for (vector<Transistor*>::const_iterator it = dev->getTransistors().begin() ; it != dev->getTransistors().end() ; ++it ) {
Transistor* tr = (*it);
file << " <transistor name=\"" << tr->getName().getString() << "\">" << endl
<< " <connection gate=\"" << tr->getGate().getString() << "\" source=\"" << tr->getSource().getString() << "\" drain=\"" << tr->getDrain().getString() << "\" bulk=\"" << tr->getBulk().getString() << "\"/>" << endl
<< " </transistor>" << endl;
}
file << " </transistors>" << endl;
}
file << " </transistors>" << endl;
if (!inst->getParameters().isEmpty()) {
Parameters params = inst->getParameters();
file << " <parameters>" << endl;

View File

@ -0,0 +1,34 @@
/*
* Device.cpp
* openChams
*
* Created by damien dupuis on 22/11/10.
* Copyright 2010 UPMC / LIP6. All rights reserved.
*
*/
#include <iostream>
using namespace std;
#include "vlsisapd/openChams/Device.h"
#include "vlsisapd/openChams/Netlist.h"
#include "vlsisapd/openChams/Transistor.h"
#include "vlsisapd/openChams/OpenChamsException.h"
namespace OpenChams {
Device::Device(Name name, Name model, Name mosType, bool sourceBulkConnected, Netlist* netlist)
: Instance(name, model, netlist)
, _mosType(mosType)
, _sourceBulkConnected(sourceBulkConnected)
, _trans() {}
Transistor* Device::addTransistor(Name name) {
Transistor* tr = new Transistor(name, this);
if (!tr)
throw OpenChamsException("[ERROR] Cannot create transistor.");
_trans.push_back(tr);
return tr;
}
}

View File

@ -13,19 +13,15 @@ using namespace std;
#include "vlsisapd/openChams/Instance.h"
#include "vlsisapd/openChams/Netlist.h"
#include "vlsisapd/openChams/Net.h"
#include "vlsisapd/openChams/Transistor.h"
#include "vlsisapd/openChams/OpenChamsException.h"
namespace OpenChams {
Instance::Instance(Name name, Name model, Name mosType, bool sourceBulkConnected, Netlist* netlist)
Instance::Instance(Name name, Name model, Netlist* netlist)
: _name(name)
, _model(model)
, _mosType(mosType)
, _sourceBulkConnected(sourceBulkConnected)
, _netlist(netlist)
, _params()
, _netMap()
, _trans() {}
, _netMap() {}
void Instance::addConnector(Name name) {
// si name n'est pas déjà présent dans la map on ajoute name, NULL (pas de net)
@ -64,14 +60,5 @@ void Instance::connect(Name connectorName, Name netName) {
throw OpenChamsException(error);
}
}
Transistor* Instance::addTransistor(Name name) {
Transistor* tr = new Transistor(name, this);
if (!tr)
throw OpenChamsException("[ERROR] Cannot create transistor.");
_trans.push_back(tr);
return tr;
}
}

View File

@ -13,6 +13,7 @@ using namespace std;
#include "vlsisapd/openChams/Netlist.h"
#include "vlsisapd/openChams/Instance.h"
#include "vlsisapd/openChams/Device.h"
#include "vlsisapd/openChams/Net.h"
#include "vlsisapd/openChams/Circuit.h"
#include "vlsisapd/openChams/OpenChamsException.h"
@ -20,7 +21,7 @@ using namespace std;
namespace OpenChams {
Netlist::Netlist(Circuit* circuit) : _circuit(circuit) {}
Instance* Netlist::addInstance(Name name, Name model, Name mosType, bool sourceBulkConnected) {
Instance* Netlist::addInstance(Name name, Name model) {
for (vector<Instance*>::iterator it = _instances.begin() ; it != _instances.end() ; ++it) {
if ((*it)->getName() == name) {
string error("[ERROR] Cannot define two instances with the same name in netlist (");
@ -29,7 +30,7 @@ Instance* Netlist::addInstance(Name name, Name model, Name mosType, bool sourceB
throw OpenChamsException(error);
}
}
Instance* inst = new Instance(name, model, mosType, sourceBulkConnected, this);
Instance* inst = new Instance(name, model, this);
if (!inst)
throw OpenChamsException("[ERROR] Cannot creeate instance.");
_instances.push_back(inst);
@ -37,6 +38,23 @@ Instance* Netlist::addInstance(Name name, Name model, Name mosType, bool sourceB
return inst;
}
Device* Netlist::addDevice(Name name, Name model, Name mosType, bool sourceBulkConnected) {
for (vector<Instance*>::iterator it = _instances.begin() ; it != _instances.end() ; ++it) {
if ((*it)->getName() == name) {
string error("[ERROR] Cannot define two instances with the same name in netlist (");
error += name.getString();
error += ").";
throw OpenChamsException(error);
}
}
Device* dev = new Device(name, model, mosType, sourceBulkConnected, this);
if (!dev)
throw OpenChamsException("[ERROR] Cannot creeate device.");
_instances.push_back(dev);
return dev;
}
Net* Netlist::addNet(Name name, Name type, bool external) {
for (vector<Net*>::iterator it = _nets.begin() ; it != _nets.end() ; ++it ) {
if ((*it)->getName() == name) {

View File

@ -102,26 +102,26 @@ BOOST_PYTHON_MODULE(OPENCHAMS) {
.def(vector_indexing_suite<std::vector<Transistor*>, true>())
;
// class OpenChams::Instance
class_<Instance, Instance*>("Instance", init<Name, Name, Name, bool, Netlist*>())
class_<Instance, Instance*>("Instance", init<Name, Name, Netlist*>())
// properties
.add_property("name" , &Instance::getName )
.add_property("model" , &Instance::getModel )
.add_property("mosType" , &Instance::getMosType )
.add_property("sourceBulkConnected", &Instance::isSourceBulkConnected)
// .add_property("mosType" , &Instance::getMosType )
// .add_property("sourceBulkConnected", &Instance::isSourceBulkConnected)
.add_property("parameters" , &Instance::getParameters )
.add_property("netlist" , make_function(&Instance::getNetlist ,return_value_policy<reference_existing_object>())) //make_function since we need to specify a return value policy
// accessors
.def("hasNoConnectors" , &Instance::hasNoConnectors )
.def("hasNoTransistors", &Instance::hasNoTransistors)
// .def("hasNoTransistors", &Instance::hasNoTransistors)
// modifiers
.def("addConnector" , &Instance::addConnector )
.def("connect" , &Instance::connect )
.def("addTransistor", &Instance::addTransistor, return_value_policy<reference_existing_object>())
// .def("addTransistor", &Instance::addTransistor, return_value_policy<reference_existing_object>())
.def("addParameter" , static_cast<void(Transistor::*)(Name, double )>(&Transistor::addParameter))
.def("addParameter" , static_cast<void(Transistor::*)(Name, std::string)>(&Transistor::addParameter))
// stl containers
.def("getConnectors" , &Instance::getConnectors , return_internal_reference<>())
.def("getTransistors", &Instance::getTransistors, return_internal_reference<>())
// .def("getTransistors", &Instance::getTransistors, return_internal_reference<>())
;
// vector_indexing for OpenChams::Net

View File

@ -23,6 +23,7 @@
namespace OpenChams {
class Netlist;
class Instance;
class Device;
class Net;
class Schematic;
class Sizing;
@ -62,6 +63,7 @@ class Circuit {
Name readParameter(xmlNode*, double&);
Name readParameterEq(xmlNode*, std::string&);
Name readConnector(xmlNode*);
void readSubCircuitsPathes(xmlNode*);
void readCircuitParameters(xmlNode*);
void readSimulModels(xmlNode*);
void readNetList(xmlNode*);
@ -69,8 +71,8 @@ class Circuit {
Instance* readInstance (xmlNode*, Netlist*);
void readInstanceParameters(xmlNode*, Instance*);
void readInstanceConnectors(xmlNode*, Instance*);
void readInstanceTransistors(xmlNode*, Instance*);
void readTransistor(xmlNode*, Instance*);
void readInstanceTransistors(xmlNode*, Device*);
void readTransistor(xmlNode*, Device*);
void readTransistorConnection(xmlNode*, Transistor*);
void readNets(xmlNode*, Netlist*);
Net* readNet (xmlNode*, Netlist*);
@ -95,6 +97,7 @@ class Circuit {
Schematic* _schematic;
Sizing* _sizing;
Layout* _layout;
std::vector<std::string> _subCircuitsPathes;
std::map<unsigned, SimulModel*> _simulModels;
};

View File

@ -0,0 +1,51 @@
/*
* Device.h
* openChams
*
* Created by damien dupuis on 22/11/10.
* Copyright 2010 UPMC / LIP6. All rights reserved.
*
*/
#ifndef __OPENCHAMS_DEVICE_H__
#define __OPENCHAMS_DEVICE_H__
#include <map>
#include <vector>
#include "vlsisapd/openChams/Name.h"
#include "vlsisapd/openChams/Instance.h"
#include "vlsisapd/openChams/Parameters.h"
namespace OpenChams {
class Netlist;
class Transistor;
class Device : public Instance {
public:
Device(Name name, Name model, Name mosType, bool, Netlist*);
virtual ~Device() {};
inline Name getMosType();
inline bool isSourceBulkConnected();
// pour parcourir les transistors
inline bool hasNoTransistors();
inline const std::vector<Transistor*>& getTransistors();
Transistor* addTransistor(Name);
private:
Name _mosType;
bool _sourceBulkConnected;
std::vector<Transistor*> _trans;
};
inline Name Device::getMosType() { return _mosType; };
inline bool Device::isSourceBulkConnected() { return _sourceBulkConnected; };
inline bool Device::hasNoTransistors() { return (_trans.size() == 0)? true : false; };
inline const std::vector<Transistor*>& Device::getTransistors() { return _trans; };
} // namespace
#endif

View File

@ -19,10 +19,11 @@
namespace OpenChams {
class Netlist;
class Net;
class Transistor;
class Instance {
public:
Instance(Name name, Name model, Name mosType, bool, Netlist*);
Instance(Name name, Name model, Netlist*);
virtual ~Instance() {};
void addConnector(Name);
void connect(Name connectorName, Name netName);
@ -31,42 +32,28 @@ class Instance {
inline void addParameter(Name, std::string);
inline Name getName() const;
inline Name getModel();
inline Name getMosType();
inline bool isSourceBulkConnected();
inline Netlist* getNetlist();
inline Parameters getParameters();
// pour parcourir les connecteurs
inline bool hasNoConnectors();
inline const std::map<Name, Net*>& getConnectors();
// pour parcourir les transistors
inline bool hasNoTransistors();
inline const std::vector<Transistor*>& getTransistors();
Transistor* addTransistor(Name);
private:
Name _name;
Name _model;
Name _mosType;
bool _sourceBulkConnected;
Netlist* _netlist;
Parameters _params;
std::map<Name, Net*> _netMap; //map associant nom de connecteur a un net
std::vector<Transistor*> _trans;
};
inline void Instance::addParameter(Name name, double value) { _params.addParameter(name, value); };
inline void Instance::addParameter(Name name, std::string eqStr) { _params.addParameter(name, eqStr); };
inline Name Instance::getName() const { return _name; };
inline Name Instance::getModel() { return _model; };
inline Name Instance::getMosType() { return _mosType; };
inline bool Instance::isSourceBulkConnected() { return _sourceBulkConnected; };
inline Netlist* Instance::getNetlist() { return _netlist; };
inline Parameters Instance::getParameters() { return _params; };
inline bool Instance::hasNoConnectors() { return (_netMap.size() == 0)? true : false; };
inline const std::map<Name, Net*>& Instance::getConnectors() { return _netMap; };
inline bool Instance::hasNoTransistors() { return (_trans.size() == 0)? true : false; };
inline const std::vector<Transistor*>& Instance::getTransistors() { return _trans; };
} // namespace
#endif

View File

@ -15,6 +15,7 @@
namespace OpenChams {
class Name;
class Instance;
class Device;
class Net;
class Circuit;
@ -22,7 +23,8 @@ class Netlist {
public:
Netlist(Circuit*);
Instance* addInstance(Name name, Name model, Name mosType, bool);
Instance* addInstance(Name name, Name model);
Device* addDevice (Name name, Name model, Name mosType, bool);
Net* addNet (Name name, Name type , bool);
Instance* getInstance(Name);
@ -34,7 +36,7 @@ class Netlist {
inline const std::vector<Net*>& getNets();
private:
Circuit* _circuit;
Circuit* _circuit;
std::vector<Instance*> _instances;
std::vector<Net*> _nets;
};