<> <> <> <> <<>> <<>> DIRECTORY Core, CoreClasses, CoreFlat, CoreOps, CoreProperties, ElectricalCoreClasses, IO, Mint, MintList, MintPrivate, PWCore, RefTab, Rope, Schedule, WriteCapa; MintInputImpl: CEDAR PROGRAM IMPORTS CoreClasses, CoreFlat, CoreOps, CoreProperties, ElectricalCoreClasses, IO, Mint, MintList, MintPrivate, PWCore, RefTab, Schedule, WriteCapa EXPORTS Mint ~ BEGIN OPEN Mint, MintList; FlatCellProc: TYPE = PROC [cell: Core.CellType, target: CoreFlat.FlatCellTypeRec _ CoreFlat.allFlatCells, flatCell: CoreFlat.FlatCellTypeRec _ [], instance: CoreClasses.CellInstance _ NIL, parent: Core.CellType _ NIL, flatParent: CoreFlat.FlatCellTypeRec _ [], circuit: Circuit, wireName: RefTab.Ref, ignoreFlag, capaEvalFlag: BOOLEAN]; <> defaultIndex: NAT _ LAST[NAT]; kilo: REAL = 1000.0; ignoreMe: PUBLIC ATOM _ CoreProperties.RegisterProperty[ prop: $MintIgnoreMe, properties: CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]] ]; discardMe: PUBLIC ATOM _ CoreProperties.RegisterProperty[ prop: $MintDiscardMe, properties: CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]] ]; oneWay: PUBLIC ATOM _ CoreProperties.RegisterProperty[ prop: $MintOneWay, properties: CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]] ]; TypeTable: PUBLIC ARRAY CoreClasses.TransistorType OF TType _ [NEW[TTypeRec _ ["nE", 0.0012, 0.00025, 20000.0]], NEW[TTypeRec _ ["pE", 0.0012, 0.00025, 50000.0]], NEW[TTypeRec _ ["nD", 0.0012, 0.00025, 20000.0]]]; debug: BOOL _ FALSE; verbose: BOOL _ FALSE; debugCellType: Core.CellType _ NIL; debugCircuit: Circuit _ NIL; debugNode: Node _ NIL; debugNodeList: NodeList _ NIL; <> CreateCircuit: PUBLIC PROC [rootCell: Core.CellType, layout: BOOLEAN _ TRUE, eachPublicWireCapa: pF _ 0.0] RETURNS [circuit: Circuit] ~ { WireToNode: PROC[wire: Core.Wire] = { flatWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec _ [ flatCell: CoreFlat.rootCellType, wireRoot: public, wire: wire ]]; node: Node _ CreateNode[flatWire, circuit, IF layout THEN WriteCapa.GetRootCap[flatWire.wire] ELSE eachPublicWireCapa]; }; circuit _ NEW[CircuitRec _ [ rootCell: rootCell, info: NEW[MintPrivate.InfoRec], nodeTable: RefTab.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash], private: MintPrivate.CreatePrivate[] ]]; CoreOps.VisitRootAtomics[root: rootCell.public, eachWire: WireToNode]; }; CreateNode: PROC[flatWire: CoreFlat.FlatWire, circuit: Circuit, capa: pF] RETURNS [new: Node] = { <> val: RefTab.Val; found: BOOLEAN; [found: found, val: val] _ RefTab.Fetch[circuit.nodeTable, flatWire]; IF found THEN RETURN[NARROW[val]]; new _ NEW[NodeRec]; new.flatWire _ flatWire; IF debug THEN new.watched _ TRUE; -- keeps everything for ever if you debug the cell ... or the program. [] _ RefTab.Store[x: circuit.nodeTable, key: flatWire, val: new]; circuit.info.totalNodes _ circuit.info.totalNodes + 1; new.cap _ capa; new.ignoreMe _ CheckIgnoreProp[flatWire.wire]; new.fetSeq _ NEW[FetSeqRec[2]]; RETURN [new]; }; FetchNode: PROC[flatWire: CoreFlat.FlatWire, circuit: Circuit] RETURNS [node: Node] = { <> val: RefTab.Val; found: BOOLEAN; [found: found, val: val] _ RefTab.Fetch[circuit.nodeTable, flatWire]; IF found THEN RETURN[NARROW[val]] ELSE ERROR; --deep internal bug }; CheckIgnoreProp: PROC [wire: Core.Wire] RETURNS [ignored: BOOLEAN] ~ { ignored _ NARROW[CoreProperties.GetWireProp[from: wire, prop: ignoreMe], ATOM]=$TRUE; }; AddFetToNode: PROC [fet: Fet, node: Node, circuit: Circuit] ~ { fetSeq: FetSeq; nTotal: NAT _ node.fetSeq.size; nUsed: NAT _ node.fetSeq.nUsed; IF nUsed> <127 THEN fetSeq _ NEW[FetSeqRec[nFets+1]]>> <> <> <> <> <> <> <<};>> <0 THEN circuit.private.fetSeqPool[nFets] _ CONS[node.fetSeq, circuit.private.fetSeqPool[nFets]];>> <<};>> <> fetSeq _ NEW[FetSeqRec[2*nTotal]]; FOR i: NAT IN [0..nUsed) DO fetSeq.elements[i] _ node.fetSeq.elements[i]; ENDLOOP; fetSeq.elements[nUsed] _ fet; node.fetSeq _ fetSeq; node.fetSeq.nUsed _ nUsed+1; }; GetFetType: PROC [l, w: NAT, type: CoreClasses.TransistorType, circuit: Circuit] RETURNS [fType: FetType] ~ { FOR fTList: LIST OF FetType _ circuit.fetTypeList, fTList.rest UNTIL fTList=NIL DO IF fTList.first.l#l THEN LOOP; IF fTList.first.w#w THEN LOOP; IF fTList.first.type#type THEN LOOP; RETURN[fTList.first]; ENDLOOP; fType _ NEW[FetTypeRec _ [l, w, type, w/(l * TypeTable[type].rOn)]]; circuit.fetTypeList _ CONS[fType, circuit.fetTypeList]; }; BuildFet: PROC[gate, ch1, ch2: CoreFlat.FlatWire, type: CoreClasses.TransistorType, l, w: NAT, directional: BOOLEAN, circuit: Circuit] = { <> <> fet: Fet; fet _ NEW[FetRec _ [ gate: FetchNode[gate, circuit], ch1: FetchNode[ch1, circuit], ch2: FetchNode[ch2, circuit], switch: FALSE, directional: directional, type: GetFetType[l, w, type, circuit] ]]; fet.gate.cap _ fet.gate.cap+TypeTable[type].cPerArea*l*w; fet.ch1.cap _ fet.ch1.cap+TypeTable[type].cPerWidth*w; fet.ch2.cap _ fet.ch2.cap+TypeTable[type].cPerWidth*w; AddFetToNode[fet, fet.gate, circuit]; IF ~fet.ch1.fixedV THEN IF fet.ch1 # fet.gate THEN AddFetToNode[fet, fet.ch1, circuit]; IF ~fet.ch2.fixedV THEN IF (fet.ch2 # fet.gate) AND (fet.ch2 # fet.ch1) THEN AddFetToNode[fet, fet.ch2, circuit]; circuit.info.totalFets[fet.type.type] _ circuit.info.totalFets[fet.type.type]+1; }; <> NextCellType: PROC [cell: Core.CellType, target: CoreFlat.FlatCellTypeRec, flatCell: CoreFlat.FlatCellTypeRec, instance: CoreClasses.CellInstance, parent: Core.CellType, flatParent: CoreFlat.FlatCellTypeRec, circuit: Circuit, wireName: RefTab.Ref, ignoreFlag, capaEvalFlag: BOOLEAN, proc: FlatCellProc] = { BindCellType: CoreFlat.UnboundFlatCellProc = { BindPublicToActual: CoreOps.EachWirePairProc = { <> IF publicWire.size=0 THEN { flatWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[x: wireName, key: actualWire].val]; [] _ RefTab.Store[x: wireName, key: publicWire, val: flatWire]; IF CheckIgnoreProp[publicWire] THEN { node: Node _ NARROW[RefTab.Fetch[circuit.nodeTable, flatWire].val]; node.ignoreMe _ TRUE; }; }; }; IF CoreOps.VisitBinding[actual: IF instance=NIL OR instance.type#cell THEN previous.public ELSE instance.actual, public: cell.public, eachWirePair: BindPublicToActual] THEN ERROR; proc[cell, target, flatCell, instance, parent, flatParent, circuit, wireName, ignoreFlag, capaEvalFlag]; }; previous: Core.CellType _ cell; CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, defaultIndex, parent, flatParent, circuit, BindCellType]; }; Flatten: FlatCellProc = { discardFlag: BOOLEAN _ FALSE; cellIgnoreMe: ATOM _ NARROW[CoreProperties.GetCellTypeProp[cell, ignoreMe]]; cellDiscardMe: ATOM _ NARROW[CoreProperties.GetCellTypeProp[cell, discardMe]]; instanceIgnoreMe: ATOM _ IF instance#NIL THEN NARROW[CoreProperties.GetCellInstanceProp[instance, ignoreMe]] ELSE NIL; instanceDiscardMe: ATOM _ IF instance#NIL THEN NARROW[CoreProperties.GetCellInstanceProp[instance, discardMe]] ELSE NIL; layoutAtom: ATOM _ PWCore.GetLayoutAtom[cell]; IF cellIgnoreMe#NIL THEN ignoreFlag _ cellIgnoreMe=$TRUE; IF instanceIgnoreMe#NIL THEN ignoreFlag _ instanceIgnoreMe=$TRUE; IF cellDiscardMe#NIL THEN discardFlag _ cellDiscardMe=$TRUE; IF instanceDiscardMe#NIL THEN discardFlag _ instanceDiscardMe=$TRUE; IF discardFlag THEN RETURN; IF layoutAtom=$Get OR layoutAtom=$GetAndFlatten OR layoutAtom=$GetLibrary THEN capaEvalFlag _ FALSE; SELECT cell.class FROM CoreClasses.recordCellClass => { rct: CoreClasses.RecordCellType _ NARROW[cell.data]; InsertNonPublicWires[cell.public, rct.internal, flatCell, circuit, wireName, ignoreFlag, capaEvalFlag]; NextCellType[cell, target, flatCell, instance, parent, flatParent, circuit, wireName, ignoreFlag, capaEvalFlag, Flatten] }; CoreClasses.transistorCellClass => { directional: BOOLEAN _ CoreProperties.GetCellInstanceProp[instance, oneWay]#NIL OR CoreProperties.GetCellTypeProp[cell, oneWay]#NIL; transistorLength: INT _ NARROW[CoreProperties.GetCellTypeProp[cell, CoreClasses.lengthProp], REF INT]^; transistorWidth: INT _ NARROW[CoreProperties.GetCellTypeProp[cell, CoreClasses.widthProp], REF INT]^; gateWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[x:wireName, key: cell.public[ORD[CoreClasses.TransistorPort.gate]]].val]; ch1Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[x:wireName, key: cell.public[ORD[CoreClasses.TransistorPort.ch1]]].val]; ch2Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[x:wireName, key: cell.public[ORD[CoreClasses.TransistorPort.ch2]]].val]; tran: CoreClasses.Transistor _ NARROW[cell.data]; BuildFet[gateWire, ch1Wire, ch2Wire, tran.type, transistorLength, transistorWidth, directional, circuit]; }; ElectricalCoreClasses.capacitorCellClass => { gndNode: Node _ Mint.NodeFromRope["public.Gnd", circuit]; n0Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0]].val]; n0Node: Node _ NARROW[RefTab.Fetch[circuit.nodeTable, n0Wire].val]; n1Wire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[1]].val]; n1Node: Node _ NARROW[RefTab.Fetch[circuit.nodeTable, n1Wire].val]; capa: ElectricalCoreClasses.Capacitor _ NARROW[cell.data]; SELECT TRUE FROM n0Node=gndNode => n1Node.cap _ n1Node.cap+capa.value; n1Node=gndNode => n0Node.cap _ n0Node.cap+capa.value; ENDCASE => IO.PutF[StdOut, "Capacitor between %g and %g discarded\n", IO.rope[Mint.RopeFromNode[n0Node, circuit]], IO.rope[Mint.RopeFromNode[n0Node, circuit]]]; }; ElectricalCoreClasses.signalGeneratorCellClass => { nWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0]].val]; nNode: Node _ NARROW[RefTab.Fetch[circuit.nodeTable, nWire].val]; sig: ElectricalCoreClasses.SignalGenerator _ NARROW[cell.data]; nNode.input _ TRUE; SELECT sig.type FROM DC => nNode.history _ Schedule.CreateHistory[0.0, sig.onLevel*kilo]; RectWave => { delay: ps _ sig.tDelay*kilo; offLevel: mVolt _ sig.offLevel*kilo; onLevel: mVolt _ sig.onLevel*kilo; tRise: ps _ sig.tRise*kilo; tFall: ps _ sig.tFall*kilo; width: ps _ sig.width*kilo; period: ps _ sig.period*kilo; nNode.history _ Schedule.CreateHistory[0.0, offLevel]; THROUGH [0..3] DO nNode.history _ Schedule.AddToHistory[nNode.history, delay, offLevel]; nNode.history _ Schedule.AddToHistory[nNode.history, delay+tRise, onLevel]; nNode.history _ Schedule.AddToHistory[nNode.history, delay+width-tFall, onLevel]; nNode.history _ Schedule.AddToHistory[nNode.history, delay+width, offLevel]; delay _ delay+period; ENDLOOP; }; OneShot => { delay: ps _ sig.tDelay*kilo; offLevel: mVolt _ sig.offLevel*kilo; onLevel: mVolt _ sig.onLevel*kilo; tRise: ps _ sig.tRise*kilo; tFall: ps _ sig.tFall*kilo; width: ps _ sig.width*kilo; nNode.history _ Schedule.CreateHistory[0.0, offLevel]; nNode.history _ Schedule.AddToHistory[nNode.history, delay, offLevel]; nNode.history _ Schedule.AddToHistory[nNode.history, delay+tRise, onLevel]; nNode.history _ Schedule.AddToHistory[nNode.history, delay+width-tFall, onLevel]; nNode.history _ Schedule.AddToHistory[nNode.history, delay+width, offLevel]; }; Step => { delay: ps _ sig.tDelay*kilo; offLevel: mVolt _ sig.offLevel*kilo; onLevel: mVolt _ sig.onLevel*kilo; tRise: ps _ sig.tRise*kilo; nNode.history _ Schedule.CreateHistory[0.0, offLevel]; nNode.history _ Schedule.AddToHistory[nNode.history, delay, offLevel]; nNode.history _ Schedule.AddToHistory[nNode.history, delay+tRise, onLevel]; }; ENDCASE => ERROR; }; ElectricalCoreClasses.probeCellClass => { IF NARROW[cell.data, ElectricalCoreClasses.Probe].type=Voltage THEN { nWire: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[wireName, cell.public[0]].val]; nNode: Node _ NARROW[RefTab.Fetch[circuit.nodeTable, nWire].val]; nNode.watched _ TRUE; } ELSE IO.PutF[StdOut, "No current probes allowed\n"]; }; ElectricalCoreClasses.panelCellClass => { panel: ElectricalCoreClasses.Panel _ NARROW[cell.data]; circuit.info.tStart _ panel.tMin; circuit.info.tStop _ panel.tMax; }; ENDCASE => { IF cell.class.recast=NIL THEN IO.PutF[StdOut, "What is a %g ?\n", IO.rope[cell.class.name]] ELSE NextCellType[cell, target, flatCell, instance, parent, flatParent, circuit, wireName, ignoreFlag, capaEvalFlag, Flatten] }; }; InsertNonPublicWires: PROC [public, internal: Core.Wire, flatCell: CoreFlat.FlatCellTypeRec, circuit: Circuit, wireName: RefTab.Ref, ignoreFlag, capaEvalFlag: BOOLEAN] ~ { MarkAtomicPublic: PROC[wire: Core.Wire] = { [] _ RefTab.Store[x: publicsTable, key: wire, val: $Public]; }; InsertInternal: PROC[wire: Core.Wire] = { IF NOT RefTab.Fetch[x: publicsTable, key: wire].found THEN { <> flatWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec _ [ flatCell: flatCell, wireRoot: internal, wire: wire ]]; node: Node _ CreateNode[flatWire, circuit, IF capaEvalFlag THEN circuit.info.eachWireCapa ELSE WriteCapa.GetRootCap[wire]]; [] _ RefTab.Store[x: wireName, key: wire, val: flatWire]; IF NOT node.ignoreMe THEN node.ignoreMe _ ignoreFlag; }; }; publicsTable: RefTab.Ref _ RefTab.Create[public.size+1]; CoreOps.VisitRootAtomics[root: public, eachWire: MarkAtomicPublic]; CoreOps.VisitRootAtomics[root: internal, eachWire: InsertInternal]; }; NetFromCore: PROC[circuit: Circuit, layout: BOOLEAN _ TRUE] ~ { InsertPublic: PROC[wire: Core.Wire] = { flatWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec _ [ flatCell: CoreFlat.rootCellType, wireRoot: public, wire: wire ]]; node: Node _ FetchNode[flatWire, circuit]; [] _ RefTab.Store[x: wireName, key: wire, val: node.flatWire]; }; wireName: RefTab.Ref _ RefTab.Create[]; IO.PutF[Mint.StdOut, "\nConverting cell %g . . .", IO.rope[CoreOps.GetCellTypeName[circuit.rootCell]]]; CoreOps.VisitRootAtomics[root: circuit.rootCell.public, eachWire: InsertPublic]; Flatten[cell: circuit.rootCell, circuit: circuit, wireName: wireName, ignoreFlag: FALSE, capaEvalFlag: ~layout]; IO.PutRope[Mint.StdOut, "Finished\n"]; RefTab.Erase[wireName]; }; <> Stats: PUBLIC PROC[circuit: Circuit] = { total: INT _ 0; IO.PutF[Mint.StdOut, "Total number of nodes: %d.\n", IO.int[circuit.info.totalNodes]]; FOR i: CoreClasses.TransistorType IN CoreClasses.TransistorType DO IF circuit.info.totalFets[i] = 0 THEN LOOP; IO.PutF[Mint.StdOut, "Number of %s transistors: %d.\n", IO.rope[TypeTable[i].name], IO.int[circuit.info.totalFets[i]]]; total _ total + circuit.info.totalFets[i]; ENDLOOP; IO.PutF[Mint.StdOut, "Total number of transistors: %d.\n", IO.int[total]]; }; InputData: PUBLIC PROC [circuit: Circuit, fixedVList: NodeList, layout: BOOLEAN _ TRUE, eachWireCapa: pF _0.0] ~ { GuessInput: PROC[wire: Core.Wire] = { flatWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec _ [ flatCell: CoreFlat.rootCellType, wireRoot: public, wire: wire ]]; node: Node _ NARROW[RefTab.Fetch[circuit.nodeTable, flatWire].val]; IF ~node.fixedV THEN { node.input _ TRUE; FOR i: NAT IN [0..node.fetSeq.nUsed) DO fet: Fet _ node.fetSeq[i]; IF fet.ch1=node OR fet.ch2=node THEN { node.input _ FALSE; EXIT; }; ENDLOOP; }; node.watched _ TRUE; }; -- GuessInput circuit.info.eachWireCapa _ eachWireCapa; FOR iNodeList: NodeList _ fixedVList, iNodeList.rest UNTIL iNodeList = NIL DO iNodeList.first.fixedV _ TRUE; ENDLOOP; NetFromCore[circuit, layout]; CoreOps.VisitRootAtomics[root: circuit.rootCell.public, eachWire: GuessInput]; Stats[circuit]; PrepareSets[circuit, fixedVList]; }; NextNodeList: PROC [set: Set, fetList: FetList] RETURNS [nodeList: NodeList _ NIL] ~ { FOR iFetList: FetList _ fetList, iFetList.rest UNTIL iFetList = NIL DO IF NOT iFetList.first.ch1.done OR iFetList.first.ch1.tiedToDir THEN nodeList _ AddNode[set, iFetList.first.ch1, nodeList]; IF NOT iFetList.first.ch2.done OR iFetList.first.ch2.tiedToDir THEN nodeList _ AddNode[set, iFetList.first.ch2, nodeList]; ENDLOOP; set.lNodes _ AppendNodeLists[set.lNodes, nodeList]; }; --NextNodeList NextFetList: PROC [set: Set, nodeList: NodeList] RETURNS [fetList: FetList _ NIL] ~ { FOR iNodeList: NodeList _ nodeList, iNodeList.rest UNTIL iNodeList = NIL DO node: Node _ iNodeList.first; FOR i: NAT IN [0..node.fetSeq.nUsed) DO fet: Fet = node.fetSeq[i]; IF NOT fet.done THEN SELECT node FROM fet.gate => NULL; fet.ch1 => { fetList _ CONS[fet, fetList]; fet.done _ TRUE; set.type.nFets[fet.type.type] _ set.type.nFets[fet.type.type]+1; }; fet.ch2 => IF NOT fet.directional THEN { fetList _ CONS[fet, fetList]; fet.done _ TRUE; set.type.nFets[fet.type.type] _ set.type.nFets[fet.type.type]+1; } ELSE node.tiedToDir _ TRUE; ENDCASE => ERROR; --we don't care about fancy schematics ENDLOOP; ENDLOOP; set.lFets _ AppendFetLists[set.lFets, fetList]; }; --NextFetList AddNode: PROC [set: Set, node: Node, oldNodeList: NodeList] RETURNS [nodeList: NodeList] ~ { nodeList _ CONS[node, oldNodeList]; <> set.type.nNodes _ set.type.nNodes+1; node.done _ TRUE; }; PrepareSets: PUBLIC PROC [circuit: Circuit, fixedVList: NodeList] ~ { FindOneSet: RefTab.EachPairAction ~ { <> nodeList: NodeList; set: Set; node: Node _ NARROW[val]; IF node.done THEN RETURN; set _ NEW[SetRec _ [type: NEW[SetTypeRec]]]; nodeList _ AddNode[set, node, NIL]; set.lNodes _ nodeList; UNTIL nodeList = NIL DO fetList: FetList _ NextFetList[set, nodeList]; nodeList _ NextNodeList[set, fetList]; ENDLOOP; FindInputs[set]; FindFixedV[set, fixedVList, GndNode, VddNode]; FOR il: Library _ circuit.library, il.rest UNTIL il=NIL DO IF TypeEqual[set.type, il.first.type] THEN { il.first.nElem _ il.first.nElem+1; il.first.setList _ CONS[set, il.first.setList]; set.type _ il.first.type; RETURN; }; ENDLOOP; circuit.library _ CONS[NEW[LibraryElemRec _ [set.type, 1, LIST[set]]], circuit.library]; }; GndNode: Node _ Mint.NodeFromRope["public.Gnd", circuit]; VddNode: Node _ Mint.NodeFromRope["public.Vdd", circuit]; FOR inode: NodeList _ fixedVList, inode.rest UNTIL inode=NIL DO inode.first.done _ TRUE; inode.first.input _ TRUE; ENDLOOP; [] _ RefTab.Pairs[circuit.nodeTable, FindOneSet] }; -- PrepareSets FindInputs: PROC [set: Set] ~ { set.selfInputs _ FALSE; FOR ifet: FetList _ set.lFets, ifet.rest UNTIL ifet=NIL DO thisNode: Node _ ifet.first.gate; IF IsNodeInList[thisNode, set.lNodes] THEN set.selfInputs _ TRUE ELSE IF NOT IsNodeInList[thisNode, set.inList] THEN { set.type.nInput _ set.type.nInput+1; set.inList _ CONS[thisNode, set.inList]; thisNode.setList _ CONS[set, thisNode.setList] }; ENDLOOP; }; FindFixedV: PROC [set: Set, fixedVList: NodeList, GndNode, VddNode: Node] ~ { FOR ifet: FetList _ set.lFets, ifet.rest UNTIL ifet=NIL DO FOR fix: NodeList _ fixedVList, fix.rest UNTIL fix=NIL DO IF ifet.first.ch1=fix.first OR ifet.first.ch2=fix.first THEN { IF fix.first=VddNode THEN set.type.nVddTran _ set.type.nVddTran+1; IF fix.first=GndNode THEN set.type.nGndTran _ set.type.nGndTran+1; IF NOT IsNodeInList[fix.first, set.fixedV] THEN set.fixedV _ CONS[fix.first, set.fixedV]; }; ENDLOOP; ENDLOOP; }; TypeEqual: PROC [s1, s2: SetType] RETURNS [ok: BOOLEAN _ FALSE] ~ { FOR tt: CoreClasses.TransistorType IN CoreClasses.TransistorType DO IF s1.nFets[tt]#s2.nFets[tt] THEN RETURN; ENDLOOP; IF s1.nVddTran#s2.nVddTran THEN RETURN; IF s1.nGndTran#s2.nGndTran THEN RETURN; IF s1.nNodes#s2.nNodes THEN RETURN; IF s1.nInput#s2.nInput THEN RETURN; ok _ TRUE; }; <> <> <> <<};>> <<>> <> <> <> <<... to be finished.>> <<};>> <<>> ErrMsg: PROC [set: Set, circuit: Circuit] ~ { <> FOR iNodeList: NodeList _ set.inList, iNodeList.rest UNTIL iNodeList=NIL DO IF iNodeList.first.watched THEN RETURN; ENDLOOP; FOR iNodeList: NodeList _ set.lNodes, iNodeList.rest UNTIL iNodeList=NIL DO IF iNodeList.first.watched THEN RETURN; ENDLOOP; FOR iNodeList: NodeList _ set.lNodes, iNodeList.rest UNTIL iNodeList=NIL DO IO.PutF[Mint.StdOut, "%g\n", IO.rope[Mint.RopeFromNode[iNodeList.first, circuit]]]; ENDLOOP; }; CheckLibrary: PUBLIC PROC [circuit: Circuit] ~ { n: NAT _ 0; totalC: REAL _ 0.0; FOR il: Library _ circuit.library, il.rest UNTIL il=NIL DO thisSetType: SetType _ il.first.type; thisSetList: SetList _ il.first.setList; FOR iSetList: SetList _ thisSetList, iSetList.rest UNTIL iSetList=NIL DO thisNodeList: NodeList _ iSetList.first.lNodes; FOR iNodeList: NodeList _ thisNodeList, iNodeList.rest UNTIL iNodeList=NIL DO totalC _ totalC+iNodeList.first.cap; ENDLOOP; ENDLOOP; SELECT TRUE FROM thisSetType.nFets[nE]+thisSetType.nFets[pE]=0 => { FOR iSetList: SetList _ thisSetList, iSetList.rest UNTIL iSetList=NIL DO thisNode: Node _ iSetList.first.lNodes.first; IF iSetList.first.lNodes.rest#NIL THEN ERROR; IF thisNode.flatWire.wireRoot#public THEN { IF thisNode.setList=NIL THEN IO.PutF[Mint.StdOut, "%g is isolated \n", IO.rope[Mint.RopeFromNode[thisNode, circuit]]] ELSE IO.PutF[Mint.StdOut, "%g is not loaded by any fet \n", IO.rope[Mint.RopeFromNode[thisNode, circuit]]] } ENDLOOP; }; thisSetType.nVddTran=0 => { IO.PutF[Mint.StdOut, "These Nodes have no path to Vdd:\n"]; FOR iSetList: SetList _ thisSetList, iSetList.rest UNTIL iSetList=NIL DO ErrMsg[iSetList.first, circuit]; ENDLOOP; }; thisSetType.nGndTran=0 => { IO.PutF[Mint.StdOut, "These Nodes have no path to Gnd:\n"]; FOR iSetList: SetList _ thisSetList, iSetList.rest UNTIL iSetList=NIL DO ErrMsg[iSetList.first, circuit]; ENDLOOP; }; ENDCASE; ENDLOOP; IO.PutF[Mint.StdOut, "total capacitance : %g \n", IO.real[totalC]]; }; OutputResults: PUBLIC PROC [circuit: Circuit] ~ { n: NAT _ 0; IO.PutF[Mint.StdOut, " nE pE ^Vdd ^Gnd nodes inputs\n"]; FOR il: Library _ circuit.library, il.rest UNTIL il=NIL DO setType: SetType _ il.first.type; IO.PutF[Mint.StdOut, "%5d el: %5d Type: ", IO.int[n], IO.int[il.first.nElem]]; <> IO.PutF[Mint.StdOut, " %4d, %4d,", IO.int[setType.nFets[nE]], IO.int[setType.nFets[pE]]]; IO.PutF[Mint.StdOut, " %4d, %4d, %4d, %4d, \n", IO.int[setType.nVddTran], IO.int[setType.nGndTran], IO.int[setType.nNodes], IO.int[setType.nInput]]; n _ n+1; ENDLOOP; }; END.