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:
- General
- Netlist
- Sizing
- Schematic
- Layout
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"/>
<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>
#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"
if (!node) return;
for (unsigned i = 0 ; i < indent ; i++) {
cerr << " |";
}
string pos = "";
case OpenChams::Node::TOP:
pos = "top";
break;
case OpenChams::Node::RIGHT:
pos = "right";
break;
default:
break;
}
if (bloc) {
cerr <<
" bloc: " << bloc->
getName().getString() <<
" - " << pos << endl;
printHBTree(bloc->
getTop() , indent+1);
printHBTree(bloc->
getRight(), indent+1);
return;
}
if (group) {
string align = "none";
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);
}
try {
cerr << e.what() << endl;
exit(48);
}
cerr << circuit->
getName().getString() << endl;
cerr << " + parameters" << endl;
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;
for (
size_t i = 0 ; i < netlist->
getInstances().size() ; i++) {
if (dynamic_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;
}
if (dev) {
cerr << " | | | + transistors" << endl;
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;
for (
size_t i = 0 ; i < netlist->
getNets().size() ; i++) {
cerr <<
" | | + " << net->
getName().getString() <<
" : " << net->
getType().getString() <<
" - " << (net->
isExternal()?
"true":
"false") << endl;
cerr << " | | | + connections" << endl;
}
schematicNet = true;
}
}
cerr << " + schematic" << endl;
for (map<OpenChams::Name, OpenChams::Schematic::Infos*>::const_iterator sit = schematic->
getInstances().begin() ; sit != schematic->
getInstances().end() ; ++sit) {
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++) {
cerr <<
" | + net name: " << net->
getName().getString() << endl;
for (
size_t j = 0 ; j < net->
getPorts().size() ; j++) {
cerr <<
" | | + port type: " << port->
getType().getString() <<
" - idx: " << port->
getIndex() <<
" - x: " << port->
getX() <<
" - y: " << port->
getY() <<
" - orientation: " << port->
getOrientation().getString() << endl;
}
}
for (
size_t j = 0 ; j < net->
getWires().size() ; j++) {
cerr << " | | + wire ";
if (dynamic_cast<OpenChams::InstancePoint*>(start)) {
cerr <<
"<" << iP->
getName().getString() <<
"," << iP->
getPlug().getString() <<
"> ";
} else if (dynamic_cast<OpenChams::PortPoint*>(start)) {
}
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)) {
}
cerr << endl;
}
}
}
}
}
if (sizing) {
cerr << " + sizing" << endl;
for (map<OpenChams::Name, OpenChams::Operator*>::const_iterator oit = sizing->
getOperators().begin() ; oit != sizing->
getOperators().end() ; ++oit) {
cerr <<
" | + instance name: " << ((*oit).first).getString() <<
" - operator: " << op->
getName().getString() <<
" - simulModel: " << op->
getSimulModel().getString() << endl;
for (map<OpenChams::Name, OpenChams::Operator::Constraint*>::const_iterator cit = op->
getConstraints().begin() ; cit != op->
getConstraints().end() ; ++cit) {
cerr <<
" | | + param: " << ((*cit).first).getString() <<
" - ref: " << cstr->
getRef().getString() <<
" - refParam: " << cstr->
getRefParam().getString() <<
" - factor: " << cstr->
getFactor() << endl;
}
}
}
}
}
if (layout) {
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;
}
}
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>
#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[]) {
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" );
circuit->addParameter(OpenChams::Name("complex"), "myEq");
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"));
tr_nmos1->
setGate (OpenChams::Name(
"G"));
tr_nmos1->
setDrain (OpenChams::Name(
"D"));
tr_nmos1->
setBulk (OpenChams::Name(
"S"));
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"));
tr_pmos1->
setGate (OpenChams::Name(
"G"));
tr_pmos1->
setDrain (OpenChams::Name(
"D"));
tr_pmos1->
setBulk (OpenChams::Name(
"S"));
_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->
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"));
wVdd->setStartPoint(OpenChams::Name("pmos1"), OpenChams::Name("S"));
wVdd->setEndPoint (0);
_vss->
addPort(OpenChams::Name(
"inV"), 0, 2490, 2800, OpenChams::Name(
"MY"));
wVss->setStartPoint(OpenChams::Name("nmos1"), OpenChams::Name("S"));
wVss->setEndPoint (0);
_in->
addPort(OpenChams::Name(
"inH"), 0, 2190, 2500, OpenChams::Name(
"ID"));
wIn->setStartPoint(OpenChams::Name("pmos1"), OpenChams::Name("G"));
wIn->setEndPoint (OpenChams::Name("nmos1"), OpenChams::Name("G"));
wIn1->setStartPoint(0);
wIn1->setEndPoint (OpenChams::Name("pmos1"), OpenChams::Name("G"));
_out->
addPort(OpenChams::Name(
"outH"), 0, 2600, 2500, OpenChams::Name(
"ID"));
wOut->setStartPoint(OpenChams::Name("pmos1"), OpenChams::Name("D"));
wOut->setEndPoint (OpenChams::Name("nmos1"), OpenChams::Name("D"));
wOut1->setStartPoint(OpenChams::Name("nmos1"), OpenChams::Name("D"));
wOut1->setEndPoint (0);
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") );
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->
addInstance(OpenChams::Name(
"pmos1"), OpenChams::Name(
"Common transistor"));
layout->
addInstance(OpenChams::Name(
"nmos1"), OpenChams::Name(
"Rotate transistor"));
g1->
setAlign(OpenChams::Group::VERTICAL);
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
print " + parameters"
for param in circuit.parameters.getValues():
print " | |", param.key, ":", param.value
for param in circuit.parameters.getEqValues():
print " | |", param.key, ":", param.value
print " + netlist"
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
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
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"
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
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"))
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 )
circuit.addParameter(
Name(
"complex"),
"myEq")
netlist = circuit.createNetlist()
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"
tr_nmos1.source = "S"
tr_nmos1.drain = "D"
tr_nmos1.bulk = "S"
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"
tr_pmos1.source = "S"
tr_pmos1.drain = "D"
tr_pmos1.bulk = "S"
_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 = 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 = 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 = circuit.createLayout()
layout.addInstance("pmos1", "Common transistor")
layout.addInstance("nmos1", "Rotate transistor")
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.