VLSI SAPD Documentation

Presentation AGDS CIF DTR OPENCHAMS SPICE Links & Contact


OPENCHAMS Format

Presentation

The OpenCHAMS format was developped as a part of the Chams Project (http://www-soc.lip6.fr/recherche/cian/chams/). It aims at offering a convenient way to describe analogic circuits' netlists and is based on XML. Some CHAMS specific informations, such as schematic properties, layout properties or sizing procedure, can be described in this format.

Author

Damien Dupuis: damien.dupuis(at)lip6(.)fr

Stand alone database structure

The database has many objects that can be arranged in five categories:

Using the parser

Simply load an OPENCHAMS file using the static function OpenChams::Circuit::readFromFile() and then get the netlist object (OpenChams::Circuit::getNetlist()) or the sizing procedure (OpenChams::Circuit::getSizing(), might be NULL) or any other useful information (see OpenChams::Circuit).

Using the driver

Using the driver is very simple, user has to create an OpenChams::Circuit object and simply add OpenChams::Netlist (mandatory) and OpenChams::Sizing (optionnal) or OpenChams::Schematic (optionnal) or OpenChams::Layout (optinnal) to it. Finally use the OpenChams::Circuit::writeToFile() method to dump the database to file.

Examples

As said is the global presentation, VLSI SAPD project provides C++ libraries and Python modules for each supported format. In this section we present simple code examples to parse and drive a OPENCHAMS file using C++ or Python. The OPENCHAMS files considered are the same for all examples: inverter.xml and buffer.xml

<?xml version="1.0" encoding="UTF-8"?>
<circuit name="inverter" techno="myTech">
<parameters>
<parameter name="temp" value="27.0"/>
<parameter name="Vdd" value="1.2"/>
<parameter name="Vss" value="0.0"/>
<parameter name="L" value="0.10e-6"/>
<parameter name="Ids" value="30e-6"/>
<parameter name="Veg" value="0.12"/>
<parameterEq name="complex" equation="myEq"/>
</parameters>
<netlist>
<instances>
<instance name="nmos1" model="Transistor" order="1" mostype="NMOS" sourceBulkConnected="True">
<connectors>
<connector name="G"/>
<connector name="D"/>
<connector name="S"/>
</connectors>
<transistors>
<transistor name="m1">
<connection gate="G" source="S" drain="D" bulk="S"/>
</transistor>
</transistors>
</instance>
<instance name="pmos1" model="Transistor" order="2" mostype="PMOS" sourceBulkConnected="True">
<connectors>
<connector name="G"/>
<connector name="D"/>
<connector name="S"/>
</connectors>
<transistors>
<transistor name="m1">
<connection gate="G" source="S" drain="D" bulk="S"/>
</transistor>
</transistors>
</instance>
</instances>
<nets>
<net name="vdd" type="power" isExternal="True">
<connector instance="pmos1" name="S"/>
</net>
<net name="vss" type="ground" isExternal="True">
<connector instance="nmos1" name="S"/>
</net>
<net name="in" type="logical" isExternal="True">
<connector instance="nmos1" name="G"/>
<connector instance="pmos1" name="G"/>
</net>
<net name="out" type="logical" isExternal="True">
<connector instance="nmos1" name="D"/>
<connector instance="pmos1" name="D"/>
</net>
</nets>
</netlist>
<schematic>
<instance name="nmos1" x="2490" y="2600" orient="ID"/>
<instance name="pmos1" x="2490" y="2490" orient="ID"/>
<net name="vdd">
<port type="inV" idx="0" x="2525" y="2430" orient="ID"/>
<wire>
<connector name="pmos1" plug="S"/>
<!--point x="" y=""/-->
<connector idx="0"/>
</wire>
</net>
<net name="vss">
<port type="inV" idx="0" x="2525" y="2740" orient="MY"/>
<wire>
<connector name="nmos1" plug="S"/>
<connector idx="0"/>
</wire>
</net>
<net name="in">
<port type="inH" idx="0" x="2415" y="2520" orient="ID"/>
<wire>
<connector name="pmos1" plug="G"/>
<connector name="nmos1" plug="G"/>
</wire>
<wire>
<connector idx="0"/>
<connector name="pmos1" plug="G"/>
</wire>
</net>
<net name="out">
<port type="outH" idx="0" x="2570" y="2590" orient="ID"/>
<wire>
<connector name="pmos1" plug="D"/>
<connector name="nmos1" plug="D"/>
</wire>
<wire>
<connector name="nmos1" plug="D"/>
<connector idx="0"/>
</wire>
</net>
</schematic>
<sizing>
<instance name="pmos1" operator="OPVG(Veg)" simulModel="BSIM3V3">
<constraint param="Temp" ref="design" refParam="temp"/>
<constraint param="Ids" ref="design" refParam="Ids"/>
<constraint param="L" ref="design" refParam="L"/>
<constraint param="Veg" ref="design" refParam="Veg"/>
<constraint param="Vd" ref="design" refParam="Vdd" factor="0.5"/>
<constraint param="Vs" ref="design" refParam="Vdd"/>
</instance>
<instance name="nmos1" operator="OPW(Vg,Vs)" simulModel="BSIM3V3">
<constraint param="Temp" ref="design" refParam="temp"/>
<constraint param="Ids" ref="design" refParam="Ids"/>
<constraint param="L" ref="design" refParam="L"/>
<constraint param="Vs" ref="design" refParam="Vdd"/>
<constraint param="Vg" ref="pmos1" refParam="Vg"/>
<constraint param="Vd" ref="pmos1" refParam="Vd"/>
<constraint param="another" refEquation="myEq" factor="-2.5"/>
</instance>
<equations>
<eq name="myEq" equation="A/more+complex*equation"/>
</equations>
</sizing>
<layout>
<instance name="pmos1" style="Common transistor"/>
<instance name="nmos1" style="Rotate transistor"/>
<hbtree>
<group name="g1" align="vertical">
<bloc name="nmos1">
<bloc name="pmos1" position="top"/>
</bloc>
</group>
</hbtree>
</layout>
</circuit>
<?xml version="1.0" encoding="UTF-8"?>
<circuit name="buffer" techno="myTech">
<subCircuitsPaths>
<path path="."/>
</subCircuitsPaths>
<netlist>
<instances>
<instance name="inv1" model="inverter">
<connectors>
<connector name="vdd"/>
<connector name="vss"/>
<connector name="in" />
<connector name="out"/>
</connectors>
</instance>
<instance name="inv2" model="inverter">
<connectors>
<connector name="vdd"/>
<connector name="vss"/>
<connector name="in" />
<connector name="out"/>
</connectors>
</instance>
</instances>
<nets>
<net name="vdd" type="power" isExternal="True">
<connector instance="inv1" name="vdd"/>
<connector instance="inv2" name="vdd"/>
</net>
<net name="vss" type="ground" isExternal="True">
<connector instance="inv1" name="vss"/>
<connector instance="inv2" name="vss"/>
</net>
<net name="in" type="logical" isExternal="True">
<connector instance="inv1" name="in"/>
</net>
<net name="out" type="logical" isExternal="True">
<connector instance="inv2" name="out"/>
</net>
<net name="internal" type="logical" isExternal="False">
<connector instance="inv1" name="out"/>
<connector instance="inv2" name="in"/>
</net>
</nets>
</netlist>
<schematic>
<instance name="inv1" x="2490" y="2600" orient="ID"/>
<instance name="inv2" x="2490" y="2300" orient="ID"/>
<net name="in">
<port type="inV" idx="0" x="2415" y="2700" orient="MY"/>
<wire>
<connector name="inv1" plug="in"/>
<connector idx="0"/>
</wire>
</net>
<net name="internal">
<wire>
<connector name="inv1" plug="out"/>
<connector name="inv2" plug="in"/>
</wire>
</net>
<net name="out">
<port type="outV" idx="0" x="2415" y="2200" orient="MY"/>
<wire>
<connector name="inv2" plug="out"/>
<connector idx="0"/>
</wire>
</net>
<net name="vdd">
<port type="inH" idx="0" x="2200" y="2500" orient="ID"/>
<wire>
<connector idx="0"/>
<connector name="inv2" plug="vdd"/>
</wire>
<wire>
<connector name="inv1" plug="vdd"/>
<connector name="inv2" plug="vdd"/>
</wire>
</net>
<net name="vss">
<port type="inH" idx="0" x="2700" y="2500" orient="MX"/>
<wire>
<connector idx="0"/>
<connector name="inv2" plug="vss"/>
</wire>
<wire>
<connector name="inv1" plug="vss"/>
<connector name="inv2" plug="vss"/>
</wire>
</net>
</schematic>
</circuit>

All source codes are available in the examples directory.

C++

Parser

The following code (parseOpenChams.cpp) is an example of how to parse a OPENCHAMS file using C++ library.

#include <iostream>
#include <string>
#include <map>
#include <vector>
using namespace std;
#include "vlsisapd/openChams/Circuit.h"
#include "vlsisapd/openChams/Name.h"
#include "vlsisapd/openChams/Parameters.h"
#include "vlsisapd/openChams/Netlist.h"
#include "vlsisapd/openChams/Instance.h"
#include "vlsisapd/openChams/Device.h"
#include "vlsisapd/openChams/Net.h"
#include "vlsisapd/openChams/Transistor.h"
#include "vlsisapd/openChams/Schematic.h"
#include "vlsisapd/openChams/Sizing.h"
#include "vlsisapd/openChams/Operator.h"
#include "vlsisapd/openChams/Layout.h"
#include "vlsisapd/openChams/Node.h"
#include "vlsisapd/openChams/Port.h"
#include "vlsisapd/openChams/Wire.h"
#include "vlsisapd/openChams/OpenChamsException.h"
void printHBTree(OpenChams::Node* node, unsigned indent) {
if (!node) return; // since we pass nnode->getRight and node-getTop without checking for NULL
for (unsigned i = 0 ; i < indent ; i++) {
cerr << " |";
}
string pos = "";
switch(node->getPosition()) {
case OpenChams::Node::TOP:
pos = "top";
break;
case OpenChams::Node::RIGHT:
pos = "right";
break;
default:
break;
}
OpenChams::Bloc* bloc = dynamic_cast<OpenChams::Bloc*>(node);
if (bloc) {
cerr << " bloc: " << bloc->getName().getString() << " - " << pos << endl;
printHBTree(bloc->getTop() , indent+1);
printHBTree(bloc->getRight(), indent+1);
return;
}
OpenChams::Group* group = dynamic_cast<OpenChams::Group*>(node);
if (group) {
string align = "none";
switch(group->getAlign()) {
case OpenChams::Group::VERTICAL:
align = "vertical";
break;
case OpenChams::Group::HORIZONTAL:
align = "horizontal";
break;
default:
break;
}
cerr << " group: " << group->getName().getString() << " - " << pos << " - align: " << align << " - isolated: " << group->isIsolated() << " - paired: " << group->isPaired() << endl;
printHBTree(group->getRootNode(), indent+1);
printHBTree(group->getTop() , indent+1);
printHBTree(group->getRight() , indent+1);
return;
}
cerr << "[ERROR] printHBTree: node is nor a bloc nor a group !" << endl;
return;
}
int main(int argc, char * argv[]) {
string file = "";
if (argc == 1)
file = "./inverter.xml";
else if (argc == 2)
file = argv[1];
else {
cerr << "Usage: openChamsParser [filename]" << endl;
exit(1);
}
OpenChams::Circuit* circuit = NULL;
try {
cerr << e.what() << endl;
exit(48);
}
cerr << circuit->getName().getString() << endl;
cerr << " + parameters" << endl;
OpenChams::Parameters params = circuit->getParameters();
if (!params.isEmpty()) {
for (map<OpenChams::Name, string>::const_iterator it = params.getValues().begin() ; it != params.getValues().end() ; ++it) {
cerr << " | | " << ((*it).first).getString() << " : " << (*it).second << endl;
}
}
cerr << " + netlist" << endl;
cerr << " | + instances" << endl;
OpenChams::Netlist* netlist = circuit->getNetlist();
if (netlist && !netlist->hasNoInstances()) {
for (size_t i = 0 ; i < netlist->getInstances().size() ; i++) {
OpenChams::Instance* inst = netlist->getInstances()[i];
OpenChams::Device* dev = NULL;
if (dynamic_cast<OpenChams::Device*>(inst)) {
dev = static_cast<OpenChams::Device*>(inst);
cerr << " | | + " << dev->getName().getString() << " : " << dev->getModel().getString() << " - " << dev->getOrder() << " - " << dev->getMosType().getString() << " - " << (dev->isSourceBulkConnected()?"true":"false") << endl;
} else {
cerr << " | | + " << inst->getName().getString() << " : " << inst->getModel().getString() << " - " << inst->getOrder() << endl;
}
cerr << " | | | + connectors" << endl;
for (map<OpenChams::Name, OpenChams::Net*>::const_iterator cit = inst->getConnectors().begin() ; cit != inst->getConnectors().end() ; ++cit) {
if ((*cit).second)
cerr << " | | | | " << ((*cit).first).getString() << " : " << ((*cit).second)->getName().getString() << endl;
else
cerr << " | | | | " << ((*cit).first).getString() << endl; // no net connected !
}
if (dev) {
cerr << " | | | + transistors" << endl;
for (size_t j = 0 ; j < dev->getTransistors().size() ; j++) {
cerr << " | | | | name: " << tr->getName().getString() << " - gate: " << tr->getGate().getString() << " - source: " << tr->getSource().getString() << " - drain: " << tr->getDrain().getString() << " - bulk: " << tr->getBulk().getString() << endl;
}
}
}
}
cerr << " | + nets" << endl;
bool schematicNet = false; // define wether net sections are needed in schematic section
if (!netlist->hasNoNets()) {
for (size_t i = 0 ; i < netlist->getNets().size() ; i++) {
OpenChams::Net* net = netlist->getNets()[i];
cerr << " | | + " << net->getName().getString() << " : " << net->getType().getString() << " - " << (net->isExternal()?"true":"false") << endl;
cerr << " | | | + connections" << endl;
for (size_t j = 0 ; j < net->getConnections().size() ; j++) {
cerr << " | | | | " << connect->getInstanceName().getString() << "." << connect->getConnectorName().getString() << endl;
}
if (!net->hasNoPorts() || !net->hasNoWires())
schematicNet = true;
}
}
OpenChams::Schematic* schematic = circuit->getSchematic();
if (schematic && !schematic->hasNoInstances()) {
cerr << " + schematic" << endl;
for (map<OpenChams::Name, OpenChams::Schematic::Infos*>::const_iterator sit = schematic->getInstances().begin() ; sit != schematic->getInstances().end() ; ++sit) {
OpenChams::Schematic::Infos* inf = (*sit).second;
cerr << " | + instance: name: " << ((*sit).first).getString() << " - x: " << inf->getX() << " - y: " << inf->getY() << " - orientation: " << inf->getOrientation().getString() << endl;
}
if (schematicNet) {
for (size_t i = 0 ; i < netlist->getNets().size() ; i++) {
OpenChams::Net* net = netlist->getNets()[i];
cerr << " | + net name: " << net->getName().getString() << endl;
if (!net->hasNoPorts()) {
for (size_t j = 0 ; j < net->getPorts().size() ; j++) {
OpenChams::Port* port = net->getPorts()[j];
cerr << " | | + port type: " << port->getType().getString() << " - idx: " << port->getIndex() << " - x: " << port->getX() << " - y: " << port->getY() << " - orientation: " << port->getOrientation().getString() << endl;
}
}
if (!net->hasNoWires()) {
for (size_t j = 0 ; j < net->getWires().size() ; j++) {
OpenChams::Wire* wire = net->getWires()[j];
cerr << " | | + wire ";
if (dynamic_cast<OpenChams::InstancePoint*>(start)) {
cerr << "<" << iP->getName().getString() << "," << iP->getPlug().getString() << "> ";
} else if (dynamic_cast<OpenChams::PortPoint*>(start)) {
OpenChams::PortPoint* pP = static_cast<OpenChams::PortPoint*>(start);
cerr << "<" << pP->getIndex() << "> ";
}
for (size_t k = 0 ; k < wire->getIntermediatePoints().size() ; k++) {
cerr << "<" << iP->getX() << "," << iP->getY() << "> ";
}
if (dynamic_cast<OpenChams::InstancePoint*>(end)) {
cerr << "<" << iP->getName().getString() << "," << iP->getPlug().getString() << "> ";
} else if (dynamic_cast<OpenChams::PortPoint*>(end)) {
OpenChams::PortPoint* pP = static_cast<OpenChams::PortPoint*>(end);
cerr << "<" << pP->getIndex() << "> ";
}
cerr << endl;
}
}
}
}
}
OpenChams::Sizing* sizing = circuit->getSizing();
if (sizing) {
cerr << " + sizing" << endl;
if (!sizing->hasNoOperators()) {
for (map<OpenChams::Name, OpenChams::Operator*>::const_iterator oit = sizing->getOperators().begin() ; oit != sizing->getOperators().end() ; ++oit) {
OpenChams::Operator* op = (*oit).second;
cerr << " | + instance name: " << ((*oit).first).getString() << " - operator: " << op->getName().getString() << " - simulModel: " << op->getSimulModel().getString() << endl;
if (!op->hasNoConstraints()) {
for (map<OpenChams::Name, OpenChams::Operator::Constraint*>::const_iterator cit = op->getConstraints().begin() ; cit != op->getConstraints().end() ; ++cit) {
OpenChams::Operator::Constraint* cstr = (*cit).second;
cerr << " | | + param: " << ((*cit).first).getString() << " - ref: " << cstr->getRef().getString() << " - refParam: " << cstr->getRefParam().getString() << " - factor: " << cstr->getFactor() << endl;
}
}
}
}
// To update to the new equations.
// if (!sizing->hasNoEquations()) {
// cerr << " | + equations" << endl;
// for (map<OpenChams::Name, string>::const_iterator eit = sizing->getEquations().begin() ; eit != sizing->getEquations().end() ; ++eit) {
// cerr << " | | " << ((*eit).first).getString() << " : " << (*eit).second << endl;
// }
// }
}
OpenChams::Layout* layout = circuit->getLayout();
if (layout) {
if (!layout->hasNoInstance()) {
cerr << " + layout" << endl;
for (map<OpenChams::Name, OpenChams::Name>::const_iterator lit = layout->getInstances().begin() ; lit != layout->getInstances().end() ; ++lit) {
cerr << " | | instance name: " << ((*lit).first).getString() << " - style: " << ((*lit).second).getString() << endl;
}
}
OpenChams::Node* root = layout->getHBTreeRoot();
if (root) {
cerr << " | + hbtree" << endl;
printHBTree(root, 2);
}
}
return 0;
}

Driver

This C++ code (driveOpenChams.cpp) generates an inverter.xml file equivalent to the included one.

#include <string>
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/Transistor.h"
#include "vlsisapd/openChams/Net.h"
#include "vlsisapd/openChams/Schematic.h"
#include "vlsisapd/openChams/Sizing.h"
#include "vlsisapd/openChams/Operator.h"
#include "vlsisapd/openChams/Layout.h"
#include "vlsisapd/openChams/Node.h"
#include "vlsisapd/openChams/Port.h"
#include "vlsisapd/openChams/Wire.h"
int main(int argc, char * argv[]) {
OpenChams::Circuit* circuit = new OpenChams::Circuit(OpenChams::Name("design"), OpenChams::Name("myTech"));
// value parameters
circuit->addParameter(OpenChams::Name("temp"), "27.0" );
circuit->addParameter(OpenChams::Name("Vdd") , "1.2" );
circuit->addParameter(OpenChams::Name("Vss") , "0.0" );
circuit->addParameter(OpenChams::Name("L") , "0.1e-6");
circuit->addParameter(OpenChams::Name("Ids") , "30e-6" );
circuit->addParameter(OpenChams::Name("Veg") , "0.12" );
// equation parameters
circuit->addParameter(OpenChams::Name("complex"), "myEq");
// netlist
OpenChams::Netlist* netlist = circuit->createNetlist();
// instances
// nmos1
OpenChams::Device* inst_nmos1 = netlist->addDevice(OpenChams::Name("nmos1"), OpenChams::Name("Transistor"), 1, OpenChams::Name("NMOS"), true);
inst_nmos1->addConnector(OpenChams::Name("G"));
inst_nmos1->addConnector(OpenChams::Name("S"));
inst_nmos1->addConnector(OpenChams::Name("D"));
OpenChams::Transistor* tr_nmos1 = inst_nmos1->addTransistor(OpenChams::Name("m1"));
tr_nmos1->setGate (OpenChams::Name("G")); // the name of the connector of inst_nmos1
tr_nmos1->setSource(OpenChams::Name("S"));
tr_nmos1->setDrain (OpenChams::Name("D"));
tr_nmos1->setBulk (OpenChams::Name("S"));
// pmos1
OpenChams::Device* inst_pmos1 = netlist->addDevice(OpenChams::Name("pmos1"), OpenChams::Name("Transistor"), 2, OpenChams::Name("PMOS"), true);
inst_pmos1->addConnector(OpenChams::Name("G"));
inst_pmos1->addConnector(OpenChams::Name("S"));
inst_pmos1->addConnector(OpenChams::Name("D"));
OpenChams::Transistor* tr_pmos1 = inst_pmos1->addTransistor(OpenChams::Name("m1"));
tr_pmos1->setGate (OpenChams::Name("G")); // the name of the connector of inst_pmos1
tr_pmos1->setSource(OpenChams::Name("S"));
tr_pmos1->setDrain (OpenChams::Name("D"));
tr_pmos1->setBulk (OpenChams::Name("S"));
// nets
OpenChams::Net* _vdd = netlist->addNet(OpenChams::Name("vdd"), OpenChams::Name("power") , true);
OpenChams::Net* _vss = netlist->addNet(OpenChams::Name("vss"), OpenChams::Name("ground") , true);
OpenChams::Net* _in = netlist->addNet(OpenChams::Name("in" ), OpenChams::Name("logical"), true);
OpenChams::Net* _out = netlist->addNet(OpenChams::Name("out"), OpenChams::Name("logical"), true);
_vdd->connectTo(OpenChams::Name("pmos1"), OpenChams::Name("S"));
_vss->connectTo(OpenChams::Name("nmos1"), OpenChams::Name("S"));
_in->connectTo (OpenChams::Name("nmos1"), OpenChams::Name("G"));
_in->connectTo (OpenChams::Name("pmos1"), OpenChams::Name("G"));
_out->connectTo(OpenChams::Name("nmos1"), OpenChams::Name("D"));
_out->connectTo(OpenChams::Name("pmos1"), OpenChams::Name("D"));
// schematic
OpenChams::Schematic* schematic = circuit->createSchematic();
schematic->addInstance(OpenChams::Name("nmos1"), 2490, 2600, OpenChams::Name("ID"));
schematic->addInstance(OpenChams::Name("pmos1"), 2490, 2300, OpenChams::Name("ID"));
_vdd->addPort(OpenChams::Name("inV"), 0, 2490, 2100, OpenChams::Name("ID"));
OpenChams::Wire* wVdd = _vdd->addWire();
wVdd->setStartPoint(OpenChams::Name("pmos1"), OpenChams::Name("S"));
wVdd->setEndPoint (0);
_vss->addPort(OpenChams::Name("inV"), 0, 2490, 2800, OpenChams::Name("MY"));
OpenChams::Wire* wVss = _vss->addWire();
wVss->setStartPoint(OpenChams::Name("nmos1"), OpenChams::Name("S"));
wVss->setEndPoint (0);
_in->addPort(OpenChams::Name("inH"), 0, 2190, 2500, OpenChams::Name("ID"));
OpenChams::Wire* wIn = _in->addWire();
wIn->setStartPoint(OpenChams::Name("pmos1"), OpenChams::Name("G"));
wIn->setEndPoint (OpenChams::Name("nmos1"), OpenChams::Name("G"));
OpenChams::Wire* wIn1 = _in->addWire();
wIn1->setStartPoint(0);
wIn1->setEndPoint (OpenChams::Name("pmos1"), OpenChams::Name("G"));
_out->addPort(OpenChams::Name("outH"), 0, 2600, 2500, OpenChams::Name("ID"));
OpenChams::Wire* wOut = _out->addWire();
wOut->setStartPoint(OpenChams::Name("pmos1"), OpenChams::Name("D"));
wOut->setEndPoint (OpenChams::Name("nmos1"), OpenChams::Name("D"));
OpenChams::Wire* wOut1 = _out->addWire();
wOut1->setStartPoint(OpenChams::Name("nmos1"), OpenChams::Name("D"));
wOut1->setEndPoint (0);
// sizing
OpenChams::Sizing* sizing = circuit->createSizing();
OpenChams::Operator* op_pmos1 = sizing->addOperator(OpenChams::Name("pmos1"), OpenChams::Name("OPVG(Veg)"), OpenChams::Name("BSIM3V3"));
op_pmos1->addConstraint(OpenChams::Name("Temp"), OpenChams::Name("design"), OpenChams::Name("temp"));
op_pmos1->addConstraint(OpenChams::Name("Ids") , OpenChams::Name("design"), OpenChams::Name("Ids") );
op_pmos1->addConstraint(OpenChams::Name("L") , OpenChams::Name("design"), OpenChams::Name("L") );
op_pmos1->addConstraint(OpenChams::Name("Veg") , OpenChams::Name("design"), OpenChams::Name("Veg") );
op_pmos1->addConstraint(OpenChams::Name("Vd") , OpenChams::Name("design"), OpenChams::Name("Vdd") , 0.5);
op_pmos1->addConstraint(OpenChams::Name("Vs") , OpenChams::Name("design"), OpenChams::Name("Vdd") );
OpenChams::Operator* op_nmos1 = sizing->addOperator(OpenChams::Name("nmos1"), OpenChams::Name("OPW(Vg,Vs)"), OpenChams::Name("BSIM3V3"));
op_nmos1->addConstraint(OpenChams::Name("Temp"), OpenChams::Name("design"), OpenChams::Name("temp"));
op_nmos1->addConstraint(OpenChams::Name("Ids") , OpenChams::Name("design"), OpenChams::Name("Ids" ));
op_nmos1->addConstraint(OpenChams::Name("L") , OpenChams::Name("design"), OpenChams::Name("L" ));
op_nmos1->addConstraint(OpenChams::Name("Vs") , OpenChams::Name("design"), OpenChams::Name("Vdd" ));
op_nmos1->addConstraint(OpenChams::Name("Vg") , OpenChams::Name("pmos1") , OpenChams::Name("Vg" ));
op_nmos1->addConstraint(OpenChams::Name("Vd") , OpenChams::Name("pmos1") , OpenChams::Name("Vd" ));
op_nmos1->addConstraint(OpenChams::Name("another"), OpenChams::Name("myEq"), -2.5 );
// layout
OpenChams::Layout* layout = circuit->createLayout();
layout->addInstance(OpenChams::Name("pmos1"), OpenChams::Name("Common transistor"));
layout->addInstance(OpenChams::Name("nmos1"), OpenChams::Name("Rotate transistor"));
// create hbtree
OpenChams::Group* g1 = new OpenChams::Group("g1"); // default position is NONE and default parent is NULL
g1->setAlign(OpenChams::Group::VERTICAL);
OpenChams::Bloc* b1 = new OpenChams::Bloc("nmos1", OpenChams::Node::NONE, g1);
g1->setRootNode(b1); // b1 is root node of group g1
OpenChams::Bloc* b2 = new OpenChams::Bloc("pmos1", OpenChams::Node::TOP, b1);
b1->setTop(b2); // b2 is on top of b1
layout->setHBTreeRoot(g1); // g1 is the root of the tree
circuit->writeToFile("./myInverter.xml");
return 0;
}
Note
In order to compile these codes, a CMakeLists.txt file is provided. User must set the $VLSISAPD_TOP variable before running these commands in the directory containing the CMakeLists.txt file:
%> mkdir build; cd build
%> cmake ..
%> make

Python

Parser

The following python script (parseOpenChams.py) is an example of how to parse a OPENCHAMS file using python module.

1 import sys
2 
3 from OPENCHAMS import *
4 
5 def printHBTree(node, indent):
6  if node == None:
7  return
8  for i in range(indent):
9  print " |",
10  if isinstance(node, Bloc):
11  print " bloc:", node.getName(), "-", node.getPosition()
12  printHBTree(node.top , indent+1)
13  printHBTree(node.right, indent+1)
14  return
15  if isinstance(node, Group):
16  print " group:", node.getName(), "-", node.getPosition(), "-", node.align, "-", node.isolated, "-", node.paired
17  printHBTree(node.rootNode, indent+1)
18  printHBTree(node.top , indent+1)
19  printHBTree(node.right , indent+1)
20  return
21 
22 def printContents(circuit):
23  print circuit.name
24  # circuit parameters
25  print " + parameters"
26  for param in circuit.parameters.getValues():
27  print " | |", param.key, ":", param.value
28  for param in circuit.parameters.getEqValues():
29  print " | |", param.key, ":", param.value
30  # netlist
31  print " + netlist"
32  # instances
33  print " | + instances"
34  for instance in circuit.netlist.getInstances():
35  if isinstance(instance, Device):
36  print " | | +", instance.name, ":", instance.model, instance.order, instance.mosType, instance.sourceBulkConnected
37  else:
38  print " | | +", instance.name, ":", instance.model, instance.order
39  print " | | | + connectors"
40  for conn in instance.getConnectors():
41  print " | | | |", conn.key, ":", conn.value.name
42  if isinstance(instance, Device):
43  print " | | | + transistors"
44  for tr in instance.getTransistors():
45  print " | | | | name:", tr.name, "- gate:", tr.gate, "- source:", tr.source, "- drain:", tr.drain, "- bulk:", tr.bulk
46  # nets
47  print " | + nets"
48  schematicNet = False
49  for net in circuit.netlist.getNets():
50  print " | | +", net.name, ":", net.type, net.external
51  print " | | | + connections"
52  for conn in net.getConnections():
53  print " | | | | %s.%s"%(conn.instanceName, conn.connectorName)
54  if not net.hasNoPorts() or not net.hasNoWires():
55  schematicNet = True
56  # schematic
57  if (circuit.schematic):
58  print " + schematic"
59  for instance in circuit.schematic.getInstances():
60  print " | + instance name:", instance.key, "- x:", instance.value.x, "- y:", instance.value.y, "- orientation:", instance.value.orientation
61  if schematicNet:
62  for net in circuit.netlist.getNets():
63  if net.hasNoPorts() and net.hasNoWires():
64  continue
65  print " | + net name:", net.name
66  for port in net.getPorts():
67  print " | | + port type:", port.type, "- idx:", port.index, "- x:", port.x, "- y:", port.y, "- orientation:", port.orientation
68  for wire in net.getWires():
69  if isinstance(wire.startPoint, InstancePoint):
70  print " | | + wire <" + wire.startPoint.name.getString() + "," + wire.startPoint.plug.getString() +">"
71  elif isinstance(wire.startPoint, PortPoint):
72  print " | | + wire <" + str(wire.startPoint.index) + ">"
73  else:
74  print " - - UNKNOWN START POINT"
75  for point in wire.getIntermediatePoints():
76  print " | | <" + str(point.x) + "," + str(point.y) + ">"
77  if isinstance(wire.endPoint, InstancePoint):
78  print " | | <" + wire.endPoint.name.getString() + "," + wire.endPoint.plug.getString() +">"
79  elif isinstance(wire.endPoint, PortPoint):
80  print " | | <" + str(wire.endPoint.index) + ">"
81  else:
82  print " - - UNKNOWN END POINT"
83  # sizing
84  if (circuit.sizing):
85  print " + sizing"
86  for op in circuit.sizing.getOperators():
87  print " | + instance name:", op.key, "- operator:", op.value.name, "- simulModel:", op.value.simulModel
88  for constraint in op.value.getConstraints():
89  print " | | + param:", constraint.key, "- ref:", constraint.value.ref, "- refParam:", constraint.value.refParam, "- factor:", constraint.value.factor
90  print " | + equations"
91  for eq in circuit.sizing.getEquations():
92  print " | |", eq.key, ":", eq.value
93  # layout
94  if (circuit.layout):
95  print " + layout"
96  for inst in circuit.layout.getInstances():
97  print " | | instance name:", inst.key, "- style:", inst.value
98  if circuit.layout.hbTreeRoot != None:
99  print " | + hbtree"
100  printHBTree(circuit.layout.hbTreeRoot, 2)
101 
102 def usage():
103  print "usage:", sys.argv[0], "[filename]"
104  sys.exit(48)
105 
106 def main():
107  if len(sys.argv) == 1:
108  filename = "./inverter.xml"
109  elif len(sys.argv) == 2:
110  filename = sys.argv[1]
111  else:
112  usage()
113 
114  circuit = Circuit.readFromFile(filename)
115  printContents(circuit)
116 
117 
118 if __name__ == "__main__":
119  main()
120 

Driver

This python script (driveOpenChams.py) generates an inverter.xml file equivalent to the included one.

1 from OPENCHAMS import *
2 
3 circuit = Circuit(Name("design"), Name("myTech"))
4 # value parameters
5 circuit.addParameter(Name("temp"), 27.0 )
6 circuit.addParameter(Name("Vdd") , 1.2 )
7 circuit.addParameter(Name("Vss") , 0.0 )
8 circuit.addParameter(Name("L") , 0.1e-6)
9 circuit.addParameter(Name("Ids") , 30e-6 )
10 circuit.addParameter(Name("Veg") , 0.12 )
11 # equation parameters
12 circuit.addParameter(Name("complex"), "myEq")
13 
14 # netlist :
15 netlist = circuit.createNetlist()
16 # instances
17 # nmos1
18 inst_nmos1 = netlist.addDevice("nmos1", "Transistor", 1, "NMOS", True)
19 inst_nmos1.addConnector("G")
20 inst_nmos1.addConnector("S")
21 inst_nmos1.addConnector("D")
22 tr_nmos1 = inst_nmos1.addTransistor("m1")
23 tr_nmos1.gate = "G" # the name of the connector of inst_nmos1
24 tr_nmos1.source = "S"
25 tr_nmos1.drain = "D"
26 tr_nmos1.bulk = "S"
27 # pmos1
28 inst_pmos1 = netlist.addDevice("pmos1", "Transistor", 2, "PMOS", True)
29 inst_pmos1.addConnector("G")
30 inst_pmos1.addConnector("S")
31 inst_pmos1.addConnector("D")
32 tr_pmos1 = inst_pmos1.addTransistor("m1")
33 tr_pmos1.gate = "G" # the name of the connector of inst_pmos1
34 tr_pmos1.source = "S"
35 tr_pmos1.drain = "D"
36 tr_pmos1.bulk = "S"
37 # nets
38 _vdd = netlist.addNet("vdd", "power" , True)
39 _vss = netlist.addNet("vss", "ground" , True)
40 _in = netlist.addNet("in" , "logical", True)
41 _out = netlist.addNet("out", "logical", True)
42 _vdd.connectTo("pmos1", "S")
43 _vss.connectTo("nmos1", "S")
44 _in.connectTo ("nmos1", "G")
45 _in.connectTo ("pmos1", "G")
46 _out.connectTo("nmos1", "D")
47 _out.connectTo("pmos1", "D")
48 # schematic
49 schematic = circuit.createSchematic()
50 schematic.addInstance("nmos1", 2490, 2600, "ID")
51 schematic.addInstance("pmos1", 2490, 2300, "ID")
52 _vdd.addPort("inV" , 0, 2490, 2100, "ID")
53 _vss.addPort("inV" , 0, 2490, 2800, "MY")
54 _in.addPort ("inH" , 0, 2190, 2500, "ID")
55 _out.addPort("outH", 0, 2600, 2500, "ID")
56 wireVdd = _vdd.addWire()
57 wireVdd.setStartPoint("pmos1", "S")
58 wireVdd.setEndPoint(0)
59 wireVss = _vss.addWire()
60 wireVss.setStartPoint("nmos1", "S")
61 wireVss.setEndPoint(0)
62 wireIn0 = _in.addWire()
63 wireIn1 = _in.addWire()
64 wireIn0.setStartPoint("pmos1", "G")
65 wireIn0.setEndPoint ("nmos1", "G")
66 wireIn1.setStartPoint(0)
67 wireIn1.setEndPoint ("pmos1", "G")
68 wireOut0 = _out.addWire()
69 wireOut1 = _out.addWire()
70 wireOut0.setStartPoint("pmos1", "D")
71 wireOut0.setEndPoint ("nmos1", "D")
72 wireOut1.setStartPoint("nmos1", "D")
73 wireOut1.setEndPoint (0)
74 # sizing
75 sizing = circuit.createSizing()
76 op_pmos1 = sizing.addOperator("pmos1", "OPVG(Veg)" , "BSIM3V3")
77 op_pmos1.addConstraint("Temp", "design", "temp")
78 op_pmos1.addConstraint("Ids" , "design", "Ids" )
79 op_pmos1.addConstraint("L" , "design", "L" )
80 op_pmos1.addConstraint("Veg" , "design", "Veg" )
81 op_pmos1.addConstraint("Vd" , "design", "Vdd", 0.5)
82 op_pmos1.addConstraint("Vs" , "design", "Vdd" )
83 op_nmos1 = sizing.addOperator("nmos1", "OPW(Vg,Vs)", "BSIM3V3")
84 op_nmos1.addConstraint("Temp", "design", "temp")
85 op_nmos1.addConstraint("Ids" , "design", "Ids" )
86 op_nmos1.addConstraint("L" , "design", "L" )
87 op_nmos1.addConstraint("Vs" , "design", "Vdd" )
88 op_nmos1.addConstraint("Vg" , "pmos1" , "Vg" )
89 op_nmos1.addConstraint("Vd" , "pmos1" , "Vd" )
90 op_nmos1.addConstraint("another", "myEq", -2.5 )
91 # layout
92 layout = circuit.createLayout()
93 layout.addInstance("pmos1", "Common transistor")
94 layout.addInstance("nmos1", "Rotate transistor")
95 # create hbtree
96 g1 = Group("g1")
97 g1.align = Group.Align.VERTICAL
98 b1 = Bloc("nmos1", Node.Position.NONE, g1)
99 g1.rootNode = b1
100 b2 = Bloc("pmos1", Node.Position.TOP, b1)
101 b1.top = b2
102 layout.hbTreeRoot = g1
103 
104 circuit.writeToFile("./myInverter.xml")
Note
In order to run these two scripts (parseOpenChams.py & driveOpenChams.py), user must ensure that $PYTHONPATH variable points to the directory containing OPENCHAMS.so module.


Generated by doxygen 1.8.5 on Mon Oct 1 2018 Return to top of page
VLSI SAPD Documentation Copyright © 2010 - 2011 UPMC All rights reserved