diff --git a/vlsisapd/examples/spice/CMakeLists.txt b/vlsisapd/examples/spice/CMakeLists.txt index bef453bb..2950214b 100644 --- a/vlsisapd/examples/spice/CMakeLists.txt +++ b/vlsisapd/examples/spice/CMakeLists.txt @@ -1,5 +1,5 @@ ADD_SUBDIRECTORY(cplusplus) -#ADD_SUBDIRECTORY(python) +ADD_SUBDIRECTORY(python) SET ( SP_FILES OTA_miller.spi ) diff --git a/vlsisapd/examples/spice/cplusplus/driveSpice.cpp b/vlsisapd/examples/spice/cplusplus/driveSpice.cpp new file mode 100644 index 00000000..e0b4e507 --- /dev/null +++ b/vlsisapd/examples/spice/cplusplus/driveSpice.cpp @@ -0,0 +1,127 @@ +#include +using namespace std; + +#include "vlsisapd/spice/Circuit.h" +#include "vlsisapd/spice/Subckt.h" +#include "vlsisapd/spice/Instances.h" + +int main(int argc, char * argv[]) { + SPICE::Circuit* circuit = new SPICE::Circuit(); + circuit->setTitle("* Single-ended two-stage amplifier"); + + // PARAMS + circuit->addParameter("CC_VALUE", "2.8794pF"); + circuit->addParameter("L_VALUE" , "0.340e-6"); + + // SUBCKTS + // CurrentMirror + SPICE::Subckt* CM = circuit->addSubckt("currentMirrorPMOS"); + CM->addInterface("d1"); + CM->addInterface("d2"); + CM->addInterface("s1"); + CM->addInterface("s2"); + CM->addParameter("l_val" , "0.0" ); + CM->addParameter("w_val" , "0.0" ); + CM->addParameter("nf_val" , "1" ); + CM->addParameter("aeq_val" , "100e-6"); + CM->addParameter("temp_val", "27" ); + + SPICE::Instance* cmP3 = new SPICE::Mosfet("P3", "d1", "d1", "s1", "s1", "psvt"); + cmP3->addParameter("l" , "l_val" ); + cmP3->addParameter("wf" , "{w_val/nf_val}"); + cmP3->addParameter("nf" , "nf_val" ); + cmP3->addParameter("aeq" , "aeq_val" ); + cmP3->addParameter("tempsimu", "temp_val" ); + CM->addInstance(cmP3); + + SPICE::Instance* cmP4 = new SPICE::Mosfet("P4", "d2", "d1", "s2", "s2", "psvt"); + cmP4->addParameter("l" , "l_val" ); + cmP4->addParameter("wf" , "{w_val/nf_val}"); + cmP4->addParameter("nf" , "nf_val" ); + cmP4->addParameter("aeq" , "aeq_val" ); + cmP4->addParameter("tempsimu", "temp_val" ); + CM->addInstance(cmP4); + + // DifferentialPair + SPICE::Subckt* DP = circuit->addSubckt("diffPairNMOS"); + DP->addInterface("d1"); + DP->addInterface("d2"); + DP->addInterface("g1"); + DP->addInterface("g2"); + DP->addInterface("s"); + DP->addInterface("b"); + DP->addParameter("l_val" , "0.0" ); + DP->addParameter("w_val" , "0.0" ); + DP->addParameter("nf_val" , "1" ); + DP->addParameter("aeq_val" , "100e-6"); + DP->addParameter("temp_val", "27" ); + + SPICE::Instance* dpN1 = new SPICE::Mosfet("N1", "d1", "g1", "s", "b", "nsvt"); + dpN1->addParameter("l" , "l_val" ); + dpN1->addParameter("wf" , "{w_val/nf_val}"); + dpN1->addParameter("nf" , "nf_val" ); + dpN1->addParameter("aeq" , "aeq_val" ); + dpN1->addParameter("tempsimu", "temp_val" ); + DP->addInstance(dpN1); + + SPICE::Instance* dpN2 = new SPICE::Mosfet("N2", "d2", "g2", "s", "b", "nsvt"); + dpN2->addParameter("l" , "l_val" ); + dpN2->addParameter("wf" , "{w_val/nf_val}"); + dpN2->addParameter("nf" , "nf_val" ); + dpN2->addParameter("aeq" , "aeq_val" ); + dpN2->addParameter("tempsimu", "temp_val" ); + DP->addInstance(dpN2); + + //INSTANCES + SPICE::Instance* iCM = new SPICE::Instance("CM", "currentMirrorPMOS"); + iCM->addConnector("1"); + iCM->addConnector("2"); + iCM->addConnector("vdd"); + iCM->addConnector("vdd"); + iCM->addParameter("l_val" , "L_VALUE" ); + iCM->addParameter("w_val" , "3.889618e-06"); + iCM->addParameter("nf_val", "2" ); + circuit->addInstance(iCM); + + SPICE::Instance* iDP = new SPICE::Instance("DP", "diffPairNMOS"); + iDP->addConnector("1"); + iDP->addConnector("2"); + iDP->addConnector("vim"); + iDP->addConnector("vip"); + iDP->addConnector("3"); + iDP->addConnector("vss"); + iDP->addParameter("l_val" , "L_VALUE" ); + iDP->addParameter("w_val" , "7.683346e-07"); + iDP->addParameter("nf_val", "4" ); + circuit->addInstance(iDP); + + SPICE::Instance* iP6 = new SPICE::Mosfet("P6", "vout", "2", "vdd", "vdd", "psvt"); + iP6->addParameter("l_val" , "L_VALUE" ); + iP6->addParameter("w_val" , "3.558995e-05"); + iP6->addParameter("nf_val", "20" ); + circuit->addInstance(iP6); + + SPICE::Instance* iN5 = new SPICE::Mosfet("N5", "3", "4", "vss", "vss", "nsvt"); + iN5->addParameter("l_val" , "L_VALUE" ); + iN5->addParameter("w_val" , "2.536703e-06"); + iN5->addParameter("nf_val", "4" ); + circuit->addInstance(iN5); + + SPICE::Instance* iN7 = new SPICE::Mosfet("N7", "vout", "4", "vss", "vss", "nsvt"); + iN7->addParameter("l_val" , "L_VALUE" ); + iN7->addParameter("w_val" , "1.069083e-05"); + iN7->addParameter("nf_val", "16" ); + circuit->addInstance(iN7); + + SPICE::Instance* iN8 = new SPICE::Mosfet("N8", "4", "4", "vss", "vss", "nsvt"); + iN8->addParameter("l_val" , "L_VALUE" ); + iN8->addParameter("w_val" , "2.536703e-06"); + iN8->addParameter("nf_val", "4" ); + circuit->addInstance(iN8); + + circuit->addInstance(new SPICE::Capacitor("C1", "vout", "2", "CC_VALUE")); + + circuit->writeToFile("./myOTA.spi"); + return 0; +} + diff --git a/vlsisapd/examples/spice/python/CMakeLists.txt b/vlsisapd/examples/spice/python/CMakeLists.txt new file mode 100644 index 00000000..8599fd0f --- /dev/null +++ b/vlsisapd/examples/spice/python/CMakeLists.txt @@ -0,0 +1 @@ +INSTALL ( FILES driveSpice.py parseSpice.py DESTINATION share/doc/coriolis2/examples/vlsisapd/spice ) diff --git a/vlsisapd/examples/spice/python/driveSpice.py b/vlsisapd/examples/spice/python/driveSpice.py new file mode 100644 index 00000000..2c3ba828 --- /dev/null +++ b/vlsisapd/examples/spice/python/driveSpice.py @@ -0,0 +1,120 @@ +from SPICE import * + +circuit = Circuit() + +circuit.title = '* Single-ended two-stage amplifier' + +# PARAMS +circuit.addParameter("CC_VALUE", "2.8794pF"); +circuit.addParameter("L_VALUE" , "0.340e-6"); + +# SUBCKTS +# CurrentMirror +CM = circuit.addSubckt("currentMirrorPMOS"); +CM.addInterface("d1"); +CM.addInterface("d2"); +CM.addInterface("s1"); +CM.addInterface("s2"); +CM.addParameter("l_val" , "0.0" ); +CM.addParameter("w_val" , "0.0" ); +CM.addParameter("nf_val" , "1" ); +CM.addParameter("aeq_val" , "100e-6"); +CM.addParameter("temp_val", "27" ); + +cmP3 = Mosfet("P3", "d1", "d1", "s1", "s1", "psvt"); +cmP3.addParameter("l" , "l_val" ); +cmP3.addParameter("wf" , "{w_val/nf_val}"); +cmP3.addParameter("nf" , "nf_val" ); +cmP3.addParameter("aeq" , "aeq_val" ); +cmP3.addParameter("tempsimu", "temp_val" ); +CM.addInstance(cmP3); + +cmP4 = Mosfet("P4", "d2", "d1", "s2", "s2", "psvt"); +cmP4.addParameter("l" , "l_val" ); +cmP4.addParameter("wf" , "{w_val/nf_val}"); +cmP4.addParameter("nf" , "nf_val" ); +cmP4.addParameter("aeq" , "aeq_val" ); +cmP4.addParameter("tempsimu", "temp_val" ); +CM.addInstance(cmP4); + +# DifferentialPair +DP = circuit.addSubckt("diffPairNMOS"); +DP.addInterface("d1"); +DP.addInterface("d2"); +DP.addInterface("g1"); +DP.addInterface("g2"); +DP.addInterface("s"); +DP.addInterface("b"); +DP.addParameter("l_val" , "0.0" ); +DP.addParameter("w_val" , "0.0" ); +DP.addParameter("nf_val" , "1" ); +DP.addParameter("aeq_val" , "100e-6"); +DP.addParameter("temp_val", "27" ); + +dpN1 = Mosfet("N1", "d1", "g1", "s", "b", "nsvt"); +dpN1.addParameter("l" , "l_val" ); +dpN1.addParameter("wf" , "{w_val/nf_val}"); +dpN1.addParameter("nf" , "nf_val" ); +dpN1.addParameter("aeq" , "aeq_val" ); +dpN1.addParameter("tempsimu", "temp_val" ); +DP.addInstance(dpN1); + +dpN2 = Mosfet("N2", "d2", "g2", "s", "b", "nsvt"); +dpN2.addParameter("l" , "l_val" ); +dpN2.addParameter("wf" , "{w_val/nf_val}"); +dpN2.addParameter("nf" , "nf_val" ); +dpN2.addParameter("aeq" , "aeq_val" ); +dpN2.addParameter("tempsimu", "temp_val" ); +DP.addInstance(dpN2); + +# INSTANCES +iCM = Instance("CM", "currentMirrorPMOS"); +iCM.addConnector("1"); +iCM.addConnector("2"); +iCM.addConnector("vdd"); +iCM.addConnector("vdd"); +iCM.addParameter("l_val" , "L_VALUE" ); +iCM.addParameter("w_val" , "3.889618e-06"); +iCM.addParameter("nf_val", "2" ); +circuit.addInstance(iCM); + +iDP = Instance("DP", "diffPairNMOS"); +iDP.addConnector("1"); +iDP.addConnector("2"); +iDP.addConnector("vim"); +iDP.addConnector("vip"); +iDP.addConnector("3"); +iDP.addConnector("vss"); +iDP.addParameter("l_val" , "L_VALUE" ); +iDP.addParameter("w_val" , "7.683346e-07"); +iDP.addParameter("nf_val", "4" ); +circuit.addInstance(iDP); + +iP6 = Mosfet("P6", "vout", "2", "vdd", "vdd", "psvt"); +iP6.addParameter("l_val" , "L_VALUE" ); +iP6.addParameter("w_val" , "3.558995e-05"); +iP6.addParameter("nf_val", "20" ); +circuit.addInstance(iP6); + +iN5 = Mosfet("N5", "3", "4", "vss", "vss", "nsvt"); +iN5.addParameter("l_val" , "L_VALUE" ); +iN5.addParameter("w_val" , "2.536703e-06"); +iN5.addParameter("nf_val", "4" ); +circuit.addInstance(iN5); + +iN7 = Mosfet("N7", "vout", "4", "vss", "vss", "nsvt"); +iN7.addParameter("l_val" , "L_VALUE" ); +iN7.addParameter("w_val" , "1.069083e-05"); +iN7.addParameter("nf_val", "16" ); +circuit.addInstance(iN7); + +iN8 = Mosfet("N8", "4", "4", "vss", "vss", "nsvt"); +iN8.addParameter("l_val" , "L_VALUE" ); +iN8.addParameter("w_val" , "2.536703e-06"); +iN8.addParameter("nf_val", "4" ); +circuit.addInstance(iN8); + +capa = Capacitor("C1", "vout", "2", "CC_VALUE") +circuit.addInstance(capa); + +circuit.writeToFile("./myOTA.spi"); diff --git a/vlsisapd/examples/spice/python/parseSpice.py b/vlsisapd/examples/spice/python/parseSpice.py new file mode 100644 index 00000000..6eb56df0 --- /dev/null +++ b/vlsisapd/examples/spice/python/parseSpice.py @@ -0,0 +1,120 @@ +import sys + +from SPICE import * + +def printContents(circuit): + print "+", circuit.title + + if len(circuit.getIncludes()): + print "| + includes" + for include in circuit.getIncludes(): + print "| |", include + + if len(circuit.getLibraries()): + print "| + libraries" + for (lib, typ) in circuit.getLibraries(): + print "| |", lib, typ + + if len(circuit.getParameters()): + print "| + parameters" + for (name, value) in circuit.getParameters().items(): + print "| | %s=%s"%(name, value) + + if len(circuit.getOptions()): + print "| + options" + for (name, value) in circuit.getOptions().items(): + print "| | %s=%s"%(name, value) + + if len(circuit.getSources()): + print "| + sources" + for source in circuit.getSources(): + print "| |", source.getName(), source.getPositive(), source.getNegative(), source.getValue() + + if len(circuit.getSubckts()): + print "| + subckts" + for sub in circuit.getSubckts(): + print "| | +", sub.getName(), + for interf in sub.getInterfaces(): + print interf, + if len(sub.getParameters()): + print "param:", + for (name, value) in sub.getParameters().items(): + print "%s=%s"%(name,value), + print + for inst in sub.getInstances(): + print "| | | +", inst.getName(), + if isinstance(inst, Mosfet): + print inst.getDrain(), inst.getGrid(), inst.getSource(), inst.getBulk(), inst.getModel(), + i = 0 + for (name, value) in inst.getParameters().items(): + if i%6 == 0: + print + print "| | | | +", + print "%s=%s"%(name, value), + i += 1 + elif isinstance(inst, Resistor): + print inst.getFirst(), inst.getSecond(), inst.getValue(), + elif isinstance(inst, Capacitor): + print inst.getPositive(), inst.getNegative(), inst.getValue(), + else: + for conn in inst.getConnectors(): + print conn, + print inst.getModel(), + i = 0 + for (name, value) in inst.getParameters().items(): + if i%6 == 0: + print + print "| | | | +", + print "%s=%s"%(name, value), + i += 1 + print + + if len(circuit.getInstances()): + print "| + instances" + for inst in circuit.getInstances(): + print "| | | +", inst.getName(), + if isinstance(inst, Mosfet): + print inst.getDrain(), inst.getGrid(), inst.getSource(), inst.getBulk(), inst.getModel(), + i = 0 + for (name, value) in inst.getParameters().items(): + if i%6 == 0: + print + print "| | | | +", + print "%s=%s"%(name, value), + i += 1 + elif isinstance(inst, Resistor): + print inst.getFirst(), inst.getSecond(), inst.getValue(), + elif isinstance(inst, Capacitor): + print inst.getPositive(), inst.getNegative(), inst.getValue(), + else: + for conn in inst.getConnectors(): + print conn, + print inst.getModel(), + i = 0 + for (name, value) in inst.getParameters().items(): + if i%6 == 0: + print + print "| | | | +", + print "%s=%s"%(name, value), + i += 1 + print + +def usage(): + print "usage:", sys.argv[0], "[filename]" + sys.exit(48) + +def main(): + if len(sys.argv) == 1: + filename = "./OTA_miller.spi" + elif len(sys.argv) == 2: + filename = sys.argv[1] + else: + usage() + + circuit = Circuit.readFromFile(filename) + printContents(circuit) + + +if __name__ == "__main__": + main() +