⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spice.java

📁 The ElectricTM VLSI Design System is an open-source Electronic Design Automation (EDA) system that c
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
			if (modelName != null) infstr.append(" " + modelName);			// compute length and width (or area for nonMOS transistors)			TransistorSize size = ni.getTransistorSize(context);            if (size == null)                System.out.println("Warning: transistor has null size " + ni.describe(false));            else            {            	// write the length            	Double foundLen = null;                Variable varLen = ni.getVar(Schematics.ATTR_LENGTH);                if (varLen != null && varLen.getCode() == CodeExpression.Code.SPICE &&                	!useCDL && Simulation.isSpiceUseCellParameters())                {                	// write as a parameter                    infstr.append(" L=" + evalParam(context, no, varLen, forceEval));                } else                {                	// write the value, start by getting gate length subtraction in lambda                    double lengthSubtraction = layoutTechnology.getGateLengthSubtraction() /                    	layoutTechnology.getScale() * 1000;	                if (size.getDoubleLength() > 0)	                {	                    double l = maskScale * size.getDoubleLength();	                    l -= lengthSubtraction;		                    // make into microns (convert to nanometers then divide by 1000)	                    if (!Simulation.isSpiceWriteTransSizeInLambda())	                        l *= layoutTechnology.getScale() / 1000.0;		                    if (fun == PrimitiveNode.Function.TRANMOS  || fun == PrimitiveNode.Function.TRA4NMOS ||	                        fun == PrimitiveNode.Function.TRAPMOS || fun == PrimitiveNode.Function.TRA4PMOS ||	                        fun == PrimitiveNode.Function.TRADMOS || fun == PrimitiveNode.Function.TRA4DMOS ||	                        ((fun == PrimitiveNode.Function.TRANJFET || fun == PrimitiveNode.Function.TRAPJFET ||	                          fun == PrimitiveNode.Function.TRADMES || fun == PrimitiveNode.Function.TRAEMES) &&	                          (spiceEngine == Simulation.SpiceEngine.SPICE_ENGINE_H || spiceEngine == Simulation.SpiceEngine.SPICE_ENGINE_H_ASSURA)))	                    {	                        // schematic transistors may be text	                        if (size.getDoubleLength() == 0 && size.getLength() instanceof String)	                        {                                infstr.append(" L=" + formatParam((String)size.getLength(), TextDescriptor.Unit.DISTANCE, false));	                            if (lengthSubtraction != 0) infstr.append(" - " + lengthSubtraction);	                        } else	                        {	                            infstr.append(" L=" + TextUtils.formatDouble(l));	                            if (!Simulation.isSpiceWriteTransSizeInLambda() && !st090laytrans) infstr.append("U");	                        }	                    }	                	foundLen = new Double(l);	                } else	                {	                    // get gate length subtraction in lambda	                    if (size.getDoubleLength() == 0 && size.getLength() instanceof String)	                    {                            infstr.append(" L=" + formatParam((String)size.getLength(), TextDescriptor.Unit.DISTANCE, false));	                        if (lengthSubtraction != 0) infstr.append(" - " + lengthSubtraction);	                    }	                }                }                // write the width            	Double foundWid = null;                Variable varWid = ni.getVar(Schematics.ATTR_WIDTH);                if (varWid != null && varWid.getCode() == CodeExpression.Code.SPICE &&                	!useCDL && Simulation.isSpiceUseCellParameters())                {                	// write as a parameter                    infstr.append(" W=" + evalParam(context, no, varWid, forceEval));                } else                {                	// write the value	                if (size.getDoubleWidth() > 0)	                {	                    double w = maskScale * size.getDoubleWidth();		                    // make into microns (convert to nanometers then divide by 1000)	                    if (!Simulation.isSpiceWriteTransSizeInLambda())	                        w *= layoutTechnology.getScale() / 1000.0;		                    if (fun == PrimitiveNode.Function.TRANMOS  || fun == PrimitiveNode.Function.TRA4NMOS ||	                        fun == PrimitiveNode.Function.TRAPMOS || fun == PrimitiveNode.Function.TRA4PMOS ||	                        fun == PrimitiveNode.Function.TRADMOS || fun == PrimitiveNode.Function.TRA4DMOS ||	                        ((fun == PrimitiveNode.Function.TRANJFET || fun == PrimitiveNode.Function.TRAPJFET ||	                          fun == PrimitiveNode.Function.TRADMES || fun == PrimitiveNode.Function.TRAEMES) &&	                          (spiceEngine == Simulation.SpiceEngine.SPICE_ENGINE_H || spiceEngine == Simulation.SpiceEngine.SPICE_ENGINE_H_ASSURA)))	                    {	                        if ((size.getDoubleWidth() == 0) && (size.getWidth() instanceof String)) {	                            infstr.append(" W="+formatParam((String)size.getWidth(), TextDescriptor.Unit.DISTANCE, false));	                        } else {	                            infstr.append(" W=" + TextUtils.formatDouble(w));	                            if (!Simulation.isSpiceWriteTransSizeInLambda() && !st090laytrans) infstr.append("U");	                        }	                    }	                	foundWid = new Double(w);	                } else	                {	                    // get gate length subtraction in lambda	                    if (size.getDoubleWidth() == 0 && size.getWidth() instanceof String)	                        infstr.append(" W="+formatParam((String)size.getWidth(), TextDescriptor.Unit.DISTANCE, false));	                }                }                // write area if appropriate                if (fun != PrimitiveNode.Function.TRANMOS && fun != PrimitiveNode.Function.TRA4NMOS &&                    fun != PrimitiveNode.Function.TRAPMOS && fun != PrimitiveNode.Function.TRA4PMOS &&                    fun != PrimitiveNode.Function.TRADMOS && fun != PrimitiveNode.Function.TRA4DMOS)                {                	if (foundLen != null && foundWid != null)                	{    	                infstr.append(" AREA=" + TextUtils.formatDouble(foundLen.doubleValue()*foundWid.doubleValue()));    	                if (!Simulation.isSpiceWriteTransSizeInLambda()) infstr.append("P");                	}                }            }			// make sure transistor is connected to nets			SpiceNet spNetGate = spiceNetMap.get(gateNet);			SpiceNet spNetSource = spiceNetMap.get(sourceNet);			SpiceNet spNetDrain = spiceNetMap.get(drainNet);			if (spNetGate == null || spNetSource == null || spNetDrain == null) continue;			// compute area of source and drain			if (!useCDL)			{				if (fun == PrimitiveNode.Function.TRANMOS || fun == PrimitiveNode.Function.TRA4NMOS ||					fun == PrimitiveNode.Function.TRAPMOS || fun == PrimitiveNode.Function.TRA4PMOS ||					fun == PrimitiveNode.Function.TRADMOS || fun == PrimitiveNode.Function.TRA4DMOS)				{					double as = 0, ad = 0, ps = 0, pd = 0;					if (spNetSource.transistorCount != 0)					{						as = spNetSource.diffArea / spNetSource.transistorCount;						ps = spNetSource.diffPerim / spNetSource.transistorCount;						if (!Simulation.isSpiceWriteTransSizeInLambda())						{							as *= layoutTechnology.getScale() * layoutTechnology.getScale() / 1000000.0;							ps *= layoutTechnology.getScale() / 1000.0;						}					}					if (spNetDrain.transistorCount != 0)					{						ad = spNetDrain.diffArea / spNetDrain.transistorCount;						pd = spNetDrain.diffPerim / spNetDrain.transistorCount;						if (!Simulation.isSpiceWriteTransSizeInLambda())						{							ad *= layoutTechnology.getScale() * layoutTechnology.getScale() / 1000000.0;							pd *= layoutTechnology.getScale() / 1000.0;						}					}					if (as > 0.0)					{						infstr.append(" AS=" + TextUtils.formatDouble(as));						if (!Simulation.isSpiceWriteTransSizeInLambda() && !st090laytrans) infstr.append("P");					}					if (ad > 0.0)					{						infstr.append(" AD=" + TextUtils.formatDouble(ad));						if (!Simulation.isSpiceWriteTransSizeInLambda() && !st090laytrans) infstr.append("P");					}					if (ps > 0.0)					{						infstr.append(" PS=" + TextUtils.formatDouble(ps));						if (!Simulation.isSpiceWriteTransSizeInLambda() && !st090laytrans) infstr.append("U");					}					if (pd > 0.0)					{						infstr.append(" PD=" + TextUtils.formatDouble(pd));						if (!Simulation.isSpiceWriteTransSizeInLambda() && !st090laytrans) infstr.append("U");					}				}			}			// Writing MFactor if available.            writeMFactor(context, ni, infstr);			infstr.append("\n");			multiLinePrint(false, infstr.toString());		}		// print resistances and capacitances		if (segmentedNets != null)		{			if (spLevel == Simulation.SpiceParasitics.RC_PROXIMITY)            {            	parasiticInfo.writeNewSpiceCode(cell, cni, layoutTechnology, this);            } else {	            // write caps	            int capCount = 0;	            multiLinePrint(true, "** Extracted Parasitic Capacitors ***\n");	            for (SpiceSegmentedNets.NetInfo netInfo : segmentedNets.getUniqueSegments()) {	                if (netInfo.getCap() > cell.getTechnology().getMinCapacitance()) {	                    if (netInfo.getName().equals("gnd")) continue;           // don't write out caps from gnd to gnd	                    multiLinePrint(false, "C" + capCount + " " + netInfo.getName() + " 0 " + TextUtils.formatDouble(netInfo.getCap()) + "fF\n");	                    capCount++;	                }	            }	            // write resistors	            int resCount = 0;	            multiLinePrint(true, "** Extracted Parasitic Resistors ***\n");	            for (Iterator<ArcInst> it = cell.getArcs(); it.hasNext(); ) {	                ArcInst ai = it.next();	                Double res = segmentedNets.getRes(ai);	                if (res == null) continue;	                String n0 = segmentedNets.getNetName(ai.getHeadPortInst());	                String n1 = segmentedNets.getNetName(ai.getTailPortInst());	                int arcPImodels = SpiceSegmentedNets.getNumPISegments(res.doubleValue(), layoutTechnology.getMaxSeriesResistance());	                if (arcPImodels > 1) {	                    // have to break it up into smaller pieces	                    double segCap = segmentedNets.getArcCap(ai)/(arcPImodels+1);	                    double segRes = res.doubleValue()/arcPImodels;	                    String segn0 = n0;	                    String segn1 = n0;	                    for (int i=0; i<arcPImodels; i++) {	                        segn1 = n0 + "##" + i;	                        // print cap on intermediate node	                        if (i == (arcPImodels-1))	                            segn1 = n1;	                        multiLinePrint(false, "R"+resCount+" "+segn0+" "+segn1+" "+TextUtils.formatDouble(segRes)+"\n");	                        resCount++;	                        if (i < (arcPImodels-1)) {	                            if (!segn1.equals("gnd") && segCap > layoutTechnology.getMinCapacitance()) {	                                String capVal = TextUtils.formatDouble(segCap);	                                if (!capVal.equals("0.00")) {	                                    multiLinePrint(false, "C"+capCount+" "+segn1+" 0 "+capVal+"fF\n");	                                    capCount++;	                                }	                            }	                        }	                        segn0 = segn1;	                    }	                } else {	                    multiLinePrint(false, "R" + resCount + " " + n0 + " " + n1 + " " + TextUtils.formatDouble(res.doubleValue()) + "\n");	                    resCount++;	                }	            }            }		}		// write out any directly-typed SPICE cards		if (!useCDL)		{			boolean firstDecl = true;			for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); )			{				NodeInst ni = it.next();				if (ni.getProto() != Generic.tech().invisiblePinNode) continue;				Variable cardVar = ni.getVar(SPICE_CARD_KEY);				if (cardVar == null) continue;				if (firstDecl)				{					firstDecl = false;					multiLinePrint(true, "\n* Spice Code nodes in cell " + cell + "\n");				}				emitEmbeddedSpice(cardVar, context, segmentedNets, info, false, forceEval);			}		}        // finally, if this is the top level,        // write out some very small resistors between any networks        // that are asserted will be connected by the NCC annotation "exportsConnectedByParent"        // this should really be done internally in the network tool with a switch, but        // this hack works here for now        NccCellAnnotations anna = NccCellAnnotations.getAnnotations(cell);        if (cell == topCell && anna != null) {            // each list contains all name patterns that are be shorted together            if (anna.getExportsConnected().hasNext()) {                multiLinePrint(true, "\n*** Exports shorted due to NCC annotation 'exportsConnectedByParent':\n");            }            for (Iterator<List<NamePattern>> it = anna.getExportsConnected(); it.hasNext(); ) {                List<NamePattern> list = it.next();                List<Network> netsToConnect = new ArrayList<Network>();                // each name pattern can match any number of exports in the cell                for (NccCellAnnotations.NamePattern pat : list) {                    for (Iterator<PortProto> it3 = cell.getPorts

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -