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"/>
<!--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"
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>
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[]) {
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.
3 from OPENCHAMS
import *
5 def printHBTree(node, indent):
8 for i
in range(indent):
10 if isinstance(node, Bloc):
11 print " bloc:", node.getName(),
"-", node.getPosition()
12 printHBTree(node.top , indent+1)
13 printHBTree(node.right, indent+1)
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)
22 def printContents(circuit):
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
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
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
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():
57 if (circuit.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
62 for net
in circuit.netlist.getNets():
63 if net.hasNoPorts()
and net.hasNoWires():
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) +
">"
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) +
">"
82 print " - - UNKNOWN END POINT"
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
96 for inst
in circuit.layout.getInstances():
97 print " | | instance name:", inst.key,
"- style:", inst.value
98 if circuit.layout.hbTreeRoot !=
None:
100 printHBTree(circuit.layout.hbTreeRoot, 2)
103 print "usage:", sys.argv[0],
"[filename]"
107 if len(sys.argv) == 1:
108 filename =
"./inverter.xml"
109 elif len(sys.argv) == 2:
110 filename = sys.argv[1]
114 circuit = Circuit.readFromFile(filename)
115 printContents(circuit)
118 if __name__ ==
"__main__":
Driver
This python script (driveOpenChams.py
) generates an inverter.xml file equivalent to the included one.
1 from OPENCHAMS
import *
3 circuit = Circuit(
Name(
"design"),
Name(
"myTech"))
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 )
12 circuit.addParameter(
Name(
"complex"),
"myEq")
15 netlist = circuit.createNetlist()
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")
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")
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")
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)
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 )
92 layout = circuit.createLayout()
93 layout.addInstance(
"pmos1",
"Common transistor")
94 layout.addInstance(
"nmos1",
"Rotate transistor")
97 g1.align = Group.Align.VERTICAL
98 b1 = Bloc(
"nmos1", Node.Position.NONE, g1)
100 b2 = Bloc(
"pmos1", Node.Position.TOP, b1)
102 layout.hbTreeRoot = g1
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.