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.

import sys
from OPENCHAMS import *
def printHBTree(node, indent):
if node == None:
return
for i in range(indent):
print " |",
if isinstance(node, Bloc):
print " bloc:", node.getName(), "-", node.getPosition()
printHBTree(node.top , indent+1)
printHBTree(node.right, indent+1)
return
if isinstance(node, Group):
print " group:", node.getName(), "-", node.getPosition(), "-", node.align, "-", node.isolated, "-", node.paired
printHBTree(node.rootNode, indent+1)
printHBTree(node.top , indent+1)
printHBTree(node.right , indent+1)
return
def printContents(circuit):
print circuit.name
# circuit parameters
print " + parameters"
for param in circuit.parameters.getValues():
print " | |", param.key, ":", param.value
for param in circuit.parameters.getEqValues():
print " | |", param.key, ":", param.value
# netlist
print " + netlist"
# instances
print " | + instances"
for instance in circuit.netlist.getInstances():
if isinstance(instance, Device):
print " | | +", instance.name, ":", instance.model, instance.order, instance.mosType, instance.sourceBulkConnected
else:
print " | | +", instance.name, ":", instance.model, instance.order
print " | | | + connectors"
for conn in instance.getConnectors():
print " | | | |", conn.key, ":", conn.value.name
if isinstance(instance, Device):
print " | | | + transistors"
for tr in instance.getTransistors():
print " | | | | name:", tr.name, "- gate:", tr.gate, "- source:", tr.source, "- drain:", tr.drain, "- bulk:", tr.bulk
# nets
print " | + nets"
schematicNet = False
for net in circuit.netlist.getNets():
print " | | +", net.name, ":", net.type, net.external
print " | | | + connections"
for conn in net.getConnections():
print " | | | | %s.%s"%(conn.instanceName, conn.connectorName)
if not net.hasNoPorts() or not net.hasNoWires():
schematicNet = True
# schematic
if (circuit.schematic):
print " + schematic"
for instance in circuit.schematic.getInstances():
print " | + instance name:", instance.key, "- x:", instance.value.x, "- y:", instance.value.y, "- orientation:", instance.value.orientation
if schematicNet:
for net in circuit.netlist.getNets():
if net.hasNoPorts() and net.hasNoWires():
continue
print " | + net name:", net.name
for port in net.getPorts():
print " | | + port type:", port.type, "- idx:", port.index, "- x:", port.x, "- y:", port.y, "- orientation:", port.orientation
for wire in net.getWires():
if isinstance(wire.startPoint, InstancePoint):
print " | | + wire <" + wire.startPoint.name.getString() + "," + wire.startPoint.plug.getString() +">"
elif isinstance(wire.startPoint, PortPoint):
print " | | + wire <" + str(wire.startPoint.index) + ">"
else:
print " - - UNKNOWN START POINT"
for point in wire.getIntermediatePoints():
print " | | <" + str(point.x) + "," + str(point.y) + ">"
if isinstance(wire.endPoint, InstancePoint):
print " | | <" + wire.endPoint.name.getString() + "," + wire.endPoint.plug.getString() +">"
elif isinstance(wire.endPoint, PortPoint):
print " | | <" + str(wire.endPoint.index) + ">"
else:
print " - - UNKNOWN END POINT"
# sizing
if (circuit.sizing):
print " + sizing"
for op in circuit.sizing.getOperators():
print " | + instance name:", op.key, "- operator:", op.value.name, "- simulModel:", op.value.simulModel
for constraint in op.value.getConstraints():
print " | | + param:", constraint.key, "- ref:", constraint.value.ref, "- refParam:", constraint.value.refParam, "- factor:", constraint.value.factor
print " | + equations"
for eq in circuit.sizing.getEquations():
print " | |", eq.key, ":", eq.value
# layout
if (circuit.layout):
print " + layout"
for inst in circuit.layout.getInstances():
print " | | instance name:", inst.key, "- style:", inst.value
if circuit.layout.hbTreeRoot != None:
print " | + hbtree"
printHBTree(circuit.layout.hbTreeRoot, 2)
def usage():
print "usage:", sys.argv[0], "[filename]"
sys.exit(48)
def main():
if len(sys.argv) == 1:
filename = "./inverter.xml"
elif len(sys.argv) == 2:
filename = sys.argv[1]
else:
usage()
circuit = Circuit.readFromFile(filename)
printContents(circuit)
if __name__ == "__main__":
main()

Driver

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

from OPENCHAMS import *
circuit = Circuit(Name("design"), Name("myTech"))
# value parameters
circuit.addParameter(Name("temp"), 27.0 )
circuit.addParameter(Name("Vdd") , 1.2 )
circuit.addParameter(Name("Vss") , 0.0 )
circuit.addParameter(Name("L") , 0.1e-6)
circuit.addParameter(Name("Ids") , 30e-6 )
circuit.addParameter(Name("Veg") , 0.12 )
# equation parameters
circuit.addParameter(Name("complex"), "myEq")
# netlist :
netlist = circuit.createNetlist()
# instances
# nmos1
inst_nmos1 = netlist.addDevice("nmos1", "Transistor", 1, "NMOS", True)
inst_nmos1.addConnector("G")
inst_nmos1.addConnector("S")
inst_nmos1.addConnector("D")
tr_nmos1 = inst_nmos1.addTransistor("m1")
tr_nmos1.gate = "G" # the name of the connector of inst_nmos1
tr_nmos1.source = "S"
tr_nmos1.drain = "D"
tr_nmos1.bulk = "S"
# pmos1
inst_pmos1 = netlist.addDevice("pmos1", "Transistor", 2, "PMOS", True)
inst_pmos1.addConnector("G")
inst_pmos1.addConnector("S")
inst_pmos1.addConnector("D")
tr_pmos1 = inst_pmos1.addTransistor("m1")
tr_pmos1.gate = "G" # the name of the connector of inst_pmos1
tr_pmos1.source = "S"
tr_pmos1.drain = "D"
tr_pmos1.bulk = "S"
# nets
_vdd = netlist.addNet("vdd", "power" , True)
_vss = netlist.addNet("vss", "ground" , True)
_in = netlist.addNet("in" , "logical", True)
_out = netlist.addNet("out", "logical", True)
_vdd.connectTo("pmos1", "S")
_vss.connectTo("nmos1", "S")
_in.connectTo ("nmos1", "G")
_in.connectTo ("pmos1", "G")
_out.connectTo("nmos1", "D")
_out.connectTo("pmos1", "D")
# schematic
schematic = circuit.createSchematic()
schematic.addInstance("nmos1", 2490, 2600, "ID")
schematic.addInstance("pmos1", 2490, 2300, "ID")
_vdd.addPort("inV" , 0, 2490, 2100, "ID")
_vss.addPort("inV" , 0, 2490, 2800, "MY")
_in.addPort ("inH" , 0, 2190, 2500, "ID")
_out.addPort("outH", 0, 2600, 2500, "ID")
wireVdd = _vdd.addWire()
wireVdd.setStartPoint("pmos1", "S")
wireVdd.setEndPoint(0)
wireVss = _vss.addWire()
wireVss.setStartPoint("nmos1", "S")
wireVss.setEndPoint(0)
wireIn0 = _in.addWire()
wireIn1 = _in.addWire()
wireIn0.setStartPoint("pmos1", "G")
wireIn0.setEndPoint ("nmos1", "G")
wireIn1.setStartPoint(0)
wireIn1.setEndPoint ("pmos1", "G")
wireOut0 = _out.addWire()
wireOut1 = _out.addWire()
wireOut0.setStartPoint("pmos1", "D")
wireOut0.setEndPoint ("nmos1", "D")
wireOut1.setStartPoint("nmos1", "D")
wireOut1.setEndPoint (0)
# sizing
sizing = circuit.createSizing()
op_pmos1 = sizing.addOperator("pmos1", "OPVG(Veg)" , "BSIM3V3")
op_pmos1.addConstraint("Temp", "design", "temp")
op_pmos1.addConstraint("Ids" , "design", "Ids" )
op_pmos1.addConstraint("L" , "design", "L" )
op_pmos1.addConstraint("Veg" , "design", "Veg" )
op_pmos1.addConstraint("Vd" , "design", "Vdd", 0.5)
op_pmos1.addConstraint("Vs" , "design", "Vdd" )
op_nmos1 = sizing.addOperator("nmos1", "OPW(Vg,Vs)", "BSIM3V3")
op_nmos1.addConstraint("Temp", "design", "temp")
op_nmos1.addConstraint("Ids" , "design", "Ids" )
op_nmos1.addConstraint("L" , "design", "L" )
op_nmos1.addConstraint("Vs" , "design", "Vdd" )
op_nmos1.addConstraint("Vg" , "pmos1" , "Vg" )
op_nmos1.addConstraint("Vd" , "pmos1" , "Vd" )
op_nmos1.addConstraint("another", "myEq", -2.5 )
# layout
layout = circuit.createLayout()
layout.addInstance("pmos1", "Common transistor")
layout.addInstance("nmos1", "Rotate transistor")
# create hbtree
g1 = Group("g1")
g1.align = Group.Align.VERTICAL
b1 = Bloc("nmos1", Node.Position.NONE, g1)
g1.rootNode = b1
b2 = Bloc("pmos1", Node.Position.TOP, b1)
b1.top = b2
layout.hbTreeRoot = g1
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.14 on Thu Oct 18 2018 Return to top of page
VLSI SAPD Documentation Copyright © 2010 - 2011 UPMC All rights reserved