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 { 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; }; 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. θMintInputImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Bertrand Serlet October 18, 1986 8:12:25 pm PDT Christian Le Cocq October 16, 1987 10:02:45 am PDT some usefull definitions Basic data stuctures builders Creates a new node after checking that it has not been already inserted if the table. Fetch an existing Node or fails ooops! sounds like we've exceded our available space... IF nFets>127 THEN fetSeq _ NEW[FetSeqRec[nFets+1]] ELSE { poolIndex: NAT _ IF circuit.private.fetSeqPool[nFets+1]=NIL THEN fetSeq _ NEW[FetSeqRec[nFets+1]] ELSE { fetSeq _ circuit.private.fetSeqPool[nFets+1].first; circuit.private.fetSeqPool[nFets+1] _ circuit.private.fetSeqPool[nFets+1].rest; }; IF nFets>0 THEN circuit.private.fetSeqPool[nFets] _ CONS[node.fetSeq, circuit.private.fetSeqPool[nFets]]; }; IF fetSeq.size#nFets+1 THEN ERROR; --temporary while debug (hopefully..) This procedure builds a transistor data structure and links it into the network under construction. cap: REAL; Input From Core PROC [actualWire, publicWire: Wire] node: Node _ InsertWire[wire, flatCell, circuit, wireName]; Circuit Preparation node.set _ set; PROC [key: Key, val: Val] RETURNS [quit: BOOLEAN _ FALSE]; PrintSetType: PROC [out: IO.STREAM, setType: SetType] ~ { IO.PutF[out, " %4d, %4d,", IO.int[setType.nFets[nE]], IO.int[setType.nFets[pE]]]; IO.PutF[out, " %4d, %4d, %4d, %4d", IO.int[setType.nVddTran], IO.int[setType.nGndTran], IO.int[setType.nNodes], IO.int[setType.nInput]]; }; SolveInverter: PROC [set: Set, t: ps] RETURNS [tlast: ps] ~ { out: Node ~ set.lNodes.first; in: Node ~ set.inList.first; ... to be finished. }; no error messages for sets dealing with I/O of the chip PrintSetType[Mint.StdOut, il.first.type];-- merged in to save one gfi ΚW˜šœ™Icodešœ Οmœ1™žœžœ˜eKšœžœ+žœ)˜{Kšœžœ+žœ(˜yKšœžœ+žœ(˜yKšœžœ ˜1Kšœi˜iK˜—šœ-˜-Kšœ9˜9Kšœžœ-˜OKšœžœ.˜CKšœžœ-˜OKšœžœ.˜CKšœ(žœ ˜:šžœžœž˜Kšœ5˜5Kšœ5˜5Kšžœžœ9žœ+žœ+˜ —K˜—šœ3˜3Kšœžœ-˜NKšœžœ-˜AKšœ-žœ ˜?Kšœžœ˜šžœ ž˜KšžœB˜Dšœ ˜ Kšœ˜Kšœ$˜$Kšœ"˜"Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ6˜6šžœž˜KšœF˜FKšœK˜KKšœQ˜QKšœL˜LKšœ˜Kšžœ˜Kšœ˜——šœ ˜ Kšœ˜Kšœ$˜$Kšœ"˜"Kšœ˜Kšœ˜Kšœ˜Kšœ6˜6KšœF˜FKšœK˜KKšœQ˜QKšœL˜LKšœ˜—šœ ˜ Kšœ˜Kšœ$˜$Kšœ"˜"Kšœ˜Kšœ6˜6KšœF˜FKšœK˜KK˜—Kšžœžœ˜—K˜—šœ)˜)šžœžœ6žœ˜EKšœžœ-˜NKšœžœ-˜AKšœžœ˜K˜—Kšžœžœ-˜4K˜—šœ)˜)Kšœ%žœ ˜7K˜!K˜ K˜—šžœ˜ Kš žœžœžœžœ"žœ˜[Kšžœy˜}Kšœ˜——Kšœ˜K˜—š œžœ…žœ˜«K˜š œžœ˜+Kšœ<˜˜>Kšœ˜K˜—K˜'Kšžœ1žœ2˜gKšœP˜PKšœRžœ˜pKšžœ$˜&K–$[x: RefTab.Ref, key: RefTab.Key]šœ˜K˜K˜——™š œžœžœ˜(Kšœžœ˜Kšžœ3žœ˜Všžœžœž˜BKšžœžœžœ˜+Kšžœ6žœžœ!˜wKšœ*˜*Kšžœ˜—Kšžœ9žœ ˜JK˜K˜—š   œžœžœ2žœžœ˜rš  œžœ˜%šœžœ˜:Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜—Kšœ žœ0˜Cšžœžœ˜Kšœ žœ˜šžœžœžœž˜'Kšœ˜š žœžœžœžœžœ˜&Kšœ žœ˜Kšžœ˜K˜—Kšžœ˜—K˜—Kšœžœ˜Kšœ‘˜K˜—Kšœ)˜)šžœ2žœ žœž˜MKšœžœ˜Kšžœ˜—Kšœ˜KšœN˜NK˜Kšœ!˜!˜K˜——š  œžœžœžœ˜Všžœ,žœ žœž˜FKšžœžœžœžœ7˜zKšžœžœžœžœ7˜zKšžœ˜—Kšœ3˜3Kšœ‘˜K˜—š  œžœ žœžœ˜Ušžœ0žœ žœž˜KKšœ˜šžœžœžœž˜'Kšœ˜šžœžœ žœ˜šžœž˜Kšœ žœ˜šœ ˜ Kšœ žœ˜Kšœ žœ˜Kšœ@˜@K˜—šœ ˜ šžœžœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœ@˜@K˜—Kšžœžœ˜—Kšžœžœ‘&˜8——Kšžœ˜—Kšžœ˜—Kšœ/˜/Kšœ‘ ˜K˜—š œžœ/žœ˜\Kšœ žœ˜#Kšœ™Kšœ$˜$Kšœ ž˜˜K˜——š  œž œ-˜EK˜š  œ˜%Kšžœžœžœžœ™:Kšœ˜K˜ Kšœ žœ˜Kšžœ žœžœ˜Kšœžœžœ˜,Kšœžœ˜#Kšœ˜šžœ žœž˜Kšœ.˜.Kšœ&˜&Kšžœ˜—Kšœ˜Kšœ.˜.šžœ(žœžœž˜:šžœ#žœ˜,K˜"Kšœžœ˜/Kšœ˜Kšžœ˜K˜—Kšžœ˜—Kšœžœžœ žœ˜XK˜K˜—Kšœ9˜9Kšœ9˜9šžœ*žœžœž˜?Kšœžœ˜Kšœžœ˜Kšžœ˜—Kšœ0˜0Kšœ‘˜K˜—š  œžœ˜Kšœžœ˜šžœ&žœžœž˜:Kšœ!˜!Kšžœ$žœž˜@šžœžœ$žœ˜5Kšœ$˜$Kšœ žœ˜(Kšœžœ˜.K˜—Kšžœ˜—K˜—K˜š  œžœ=˜Mšžœ&žœžœž˜:šžœ&žœžœž˜9šžœžœžœ˜>Kšžœžœ)˜BKšžœžœ)˜BKšžœžœ%žœžœ˜YK˜—Kšžœ˜—Kšžœ˜—K˜K˜—š ’ œžœžœžœžœ˜Cšžœ žœž˜CKšžœžœžœ˜)Kšžœ˜—Kšžœžœžœ˜'Kšžœžœžœ˜'Kšžœžœžœ˜#Kšžœžœžœ˜#Kšœžœ˜ K˜K˜—š  œžœžœžœ™:Kšžœžœžœ™QKš žœ"žœžœžœžœ™ˆK™K™—š  œžœžœ™=K™Kšœ™K™K™K™—š œžœ!˜-K™7šžœ2žœ žœž˜KKšžœžœžœ˜'Kšžœ˜—šžœ2žœ žœž˜KKšžœžœžœ˜'Kšžœ˜—šžœ2žœ žœž˜KKšžœžœ4˜SKšžœ˜—K˜K˜—š  œž œ˜0Kšœžœ˜ Kšœžœ˜šžœ(žœžœž˜:Kšœ%˜%Kšœ(˜(šžœ0žœ žœž˜HJšœ/˜/šžœ4žœ žœž˜MKšœ$˜$Kšžœ˜—Kšžœ˜—šžœžœž˜šœ2˜2šžœ0žœ žœž˜HKšœ-˜-Kšžœžœžœžœ˜-šžœ#žœ˜+šžœžœ˜Kšžœžœ(žœ-˜^Kšžœžœ5žœ,˜j—K˜—Kšžœ˜—K˜—šœ˜Kšžœ9˜;šžœ0žœ žœž˜HKšœ ˜ Kšžœ˜—K˜—šœ˜Kšžœ9˜;šžœ0žœ žœž˜HKšœ ˜ Kšžœ˜—K˜—Kšžœ˜—Kšžœ˜—Kšžœ0žœ˜CK˜K˜—š  œž œ˜1Kšœžœ˜ KšžœT˜Všžœ(žœžœž˜:Kšœ!˜!Kšžœ,žœ žœ˜QKšœE™EKšžœ!žœžœ˜YKš žœ.žœžœžœžœ˜”K˜Kšžœ˜—K˜K˜——Jšžœ˜—…—S^r