<> <> <> <<>> <<>> DIRECTORY CoreFlat, CoreOps, IO, LinearSystem, Mint, MintList, MintPrivate, PlotGraph, Real, RefTab, Rope, Schedule; MintImpl: CEDAR MONITOR IMPORTS CoreFlat, CoreOps, IO, LinearSystem, PlotGraph, RefTab, Schedule EXPORTS Mint, MintList, MintPrivate SHARES Schedule ~ BEGIN OPEN Mint; plaDetect: INT = 8; freeNodeListCells: NodeList _ NIL; nFreeNodeListCells: CARD _ 0; freeFetListCells: FetList _ NIL; nFreeFetListCells: CARD _ 0; freeSetListCells: SetList _ NIL; nFreeSetListCells: CARD _ 0; Path: TYPE = REF PathRec; PathRec: TYPE = RECORD[node: Node, fet: Fet, refcnt: CARD _ 0, rest: Path]; PathList: TYPE = LIST OF Path; freePaths: Path _ NIL; --holds the first element of the chain of unused PathRec nFreePaths: CARD _ 0; --depth of freePaths (mostly debugging purposes) Delay: TYPE = REF DelayRec; DelayRec: TYPE = RECORD [tup, tdown: ps]; Try: TYPE = REF TryRec; TryRec: TYPE = RECORD [nodesUp, nodesDown: NodeChain _ NIL, rest: Try]; freeTries: Try _ NIL; --holds the first element of the chain of unused TryRec nFreeTries: CARD _ 0; --depth of freeTries (mostly debugging purposes) NodeChain: TYPE = REF NodeChainRec; -- Same as NodeList except for the reference count NodeChainRec: TYPE = RECORD[node: Node, refcnt: CARD _ 0, rest: NodeChain]; freeNodeChains: NodeChain _ NIL; nFreeNodeChains: CARD _ 0; ExtendedCircuit: TYPE = REF ExtendedCircuitRec; ExtendedCircuitRec: TYPE = RECORD [circuit: Circuit, data: REF ANY]; TimedPlot: TYPE = REF TimedPlotRec; TimedPlotRec: TYPE = RECORD [plot: PlotGraph.Plot _ NIL, oldt: ps _ 0.0]; <> gndName: Rope.ROPE = "public.Gnd"; vddName: Rope.ROPE = "public.Vdd"; VddVal: mVolt = 5000.0; GndVal: mVolt = 0.0; pVtVal: mVolt = -800.0; nVtVal: mVolt = 780.0; threshold: mVolt = 2500.0; gamma: REAL = 0.4*31.62277; -- 31.62277 = SqRt[1000.0] due to unit = mV phi: mVolt = 1000.0; sqrtPhi: REAL = 31.62277; timeSpecs: ps = 5.0; tInc: ps = 100.0; approx: REAL = 1.4; overlapFactor: REAL = 0.5; matrixCacheSize: CARDINAL = 100; totalSets: CARDINAL _ 0; separateView: BOOL _ FALSE; StdOut: PUBLIC IO.STREAM _ NIL; debug: PUBLIC BOOL _ FALSE; verbose: PUBLIC BOOL _ FALSE; <> <> <> <> statsNumberOfSimulations: CARDINAL _ 0; nSimInc: CARDINAL = 50; <> SimulateSet: PROC [ref: REF ANY, t: ps, data: REF ANY] ~ { circuit: Circuit ~ NARROW[data]; set: Set ~ NARROW[ref]; agenda: Schedule.Agenda ~ circuit.agenda; subsets: SetList; nodeList: NodeList; finished, firstTime: BOOLEAN _ FALSE; inputHistories: LIST OF Schedule.History; timeList: LIST OF ps; tmin, tmax, tmaxmin, tmaxmax: ps; IF set=NIL THEN RETURN; IF set.done THEN RETURN; set.done _ TRUE; IF debug THEN {IO.PutF[StdOut, "%5d ~~~>",IO.real[t]]; PrintSetType[set.type]; IO.PutF[StdOut, "\nInputs :"];}; nodeList _ ScanHistoriesOfNodeList[set.inList, t, agenda, FALSE]; IF verbose THEN FOR inode: NodeList _ nodeList, inode.rest UNTIL inode=NIL DO IO.PutF[StdOut," Unknown Input: %g \n", IO.rope[RopeFromNode[inode.first, circuit]]] ENDLOOP; FreeNodeList[nodeList]; nodeList _ ScanHistoriesOfNodeList[set.lNodes, t, agenda]; FOR inode: NodeList _ nodeList, inode.rest UNTIL inode=NIL DO inode.first.history _ Schedule.CreateHistory[t, GndVal+0.0314159]; --strange value to trace ENDLOOP; FreeNodeList[nodeList]; firstTime _ nodeList#NIL; FOR inode: NodeList _ set.inList, inode.rest UNTIL inode=NIL DO IF debug THEN PrintNode[inode.first, circuit]; inputHistories _ CONS[inode.first.history, inputHistories]; ENDLOOP; FOR inode: NodeList _ set.fixedV, inode.rest UNTIL inode=NIL DO IF ~inode.first.input THEN ResetInput[inode.first, set] ENDLOOP; FOR inode: NodeList _ set.lNodes, inode.rest UNTIL inode=NIL DO IF inode.first.input THEN SetInput[inode.first, set] ENDLOOP; IF debug THEN IO.PutF[StdOut, "\nOutputs:\n"]; timeList _ Schedule.Schedule[inputHistories]; IF timeList=NIL THEN timeList _ LIST[t]; tmin _ t; UNTIL timeList.first>=tmin OR timeList.rest=NIL DO timeList _ timeList.rest; ENDLOOP; tmaxmin _ timeList.first; IF set.type.solve#NIL THEN tmaxmin _ set.type.solve[set, tmin, circuit] ELSE UNTIL finished DO [finished , tmin] _ FlipSwitches[set.lFets, tmin, tmaxmin]; IF firstTime THEN finished _ FALSE; firstTime _ FALSE; IF ~finished THEN { tmaxmax _ tmaxmin; subsets _ ClipSet[set]; FOR isubset: SetList _ subsets, isubset.rest UNTIL isubset=NIL DO tmax _ RCSolve[isubset.first, tmin, circuit]; tmaxmin _ MIN[tmaxmin, tmax]; tmaxmax _ MAX[tmaxmax, tmax]; IF debug AND verbose THEN { IO.PutF[StdOut, "\nsubset between %g and %g", IO.real[tmin], IO.real[tmax]]; PrintNodeList[isubset.first.lNodes, circuit]; }; ENDLOOP; FreeSetList[subsets]; } ELSE { tmin _ tmaxmin; UNTIL timeList.first>tmin OR timeList.rest=NIL DO timeList _ timeList.rest; ENDLOOP; IF MAX[tmaxmax, timeList.first]> tmaxmin THEN finished _ FALSE; tmaxmin _ IF timeList.first>tmaxmin THEN timeList.first ELSE tmaxmax; }; ENDLOOP; WriteAgendaItems[set.lNodes, agenda, t]; circuit.info.nbOfSimulations _ circuit.info.nbOfSimulations+1; IF verbose THEN IF (circuit.info.nbOfSimulations MOD nSimInc) = 0 THEN IO.PutF[StdOut, "%5d t : %5d, No of events : %7d\n", IO.int[circuit.info.nbOfSimulations], IO.real[t], IO.int[agenda.nbOfEvents]]; }; WriteAgendaItems: PROC [nodeList: NodeList, agenda: Schedule.Agenda, t: ps] ~ { FOR inode: NodeList _ nodeList, inode.rest UNTIL inode=NIL DO nextNode: Node ~ inode.first; FOR setList: SetList _ nextNode.setList, setList.rest UNTIL setList=NIL DO nextSet: Set ~ setList.first; nextT: ps _ Schedule.NextTimeOfHistory[nextNode.history, t]; IF nextT>t THEN Schedule.InsertInAgenda[agenda, nextSet, nextT]; nextSet.done _ FALSE; ENDLOOP; ENDLOOP; }; ScanHistoriesOfNodeList: PROC [nodeList: NodeList, t: ps, agenda: Schedule.Agenda, cut: BOOLEAN _ TRUE] RETURNS [uninitialized: NodeList] ~ { CutHistory: PROC[node: Node] RETURNS [quit: BOOLEAN _ FALSE] ~ { IF node.history=NIL THEN RETURN; IF node.input THEN RETURN; t1 _ Schedule.NextTimeOfHistory[node.history, t+tInc]; IF t1>t AND Schedule.LastTimeOfHistory[node.history]>t1 THEN { node.history _ Schedule.AddToHistory[node.history, t1, Schedule.VFromHistory[node.history, t1]]; FOR iSetList: SetList _ node.setList, iSetList.rest UNTIL iSetList=NIL DO Schedule.InsertInAgenda[agenda, iSetList.first, t1]; iSetList.first.done _ FALSE; FOR inodeList: NodeList _ iSetList.first.lNodes, inodeList.rest UNTIL inodeList=NIL DO quit _ CutHistory[inodeList.first]; ENDLOOP; ENDLOOP; }; }; t1: ps _ t+tInc; FOR inode: NodeList _ nodeList, inode.rest UNTIL inode=NIL DO <> IF inode.first.history=NIL THEN { uninitialized _ NewNodeListCell[inode.first, uninitialized]; } ELSE { IF ~inode.first.watched THEN inode.first.history _ Schedule.ForgetBeginings[inode.first.history, t]; IF cut THEN [] _ CutHistory[inode.first]; }; ENDLOOP; }; <> NewSetListCell: ENTRY PROC [prevSetList: SetList _ NIL] RETURNS [newSetList: SetList] ~ { ENABLE UNWIND => NULL; IF freeSetListCells=NIL THEN newSetList _ CONS[NEW[SetRec], prevSetList] ELSE { newSetList _ freeSetListCells; freeSetListCells _ freeSetListCells.rest; newSetList.rest _ prevSetList; newSetList.first^ _ []; nFreeSetListCells _ nFreeSetListCells-1; }; }; FreeSetListCell: ENTRY PROC [setList: SetList] ~ { ENABLE UNWIND => NULL; setList.rest _ freeSetListCells; --we keep the set too freeSetListCells _ setList; nFreeSetListCells _ nFreeSetListCells+1; }; FreeSetList: PROC [setList: SetList] ~ { UNTIL setList=NIL DO sList: SetList _ setList; FreeFetList[setList.first.lFets]; FreeNodeList[setList.first.lNodes]; FreeNodeList[setList.first.inList]; FreeNodeList[setList.first.fixedV]; setList _ setList.rest; FreeSetListCell[sList]; ENDLOOP; }; <> NewNodeListCell: ENTRY PROC [node: Node _ NIL, prevNodeList: NodeList _ NIL] RETURNS [newNodeList: NodeList] ~ { ENABLE UNWIND => NULL; IF freeNodeListCells=NIL THEN newNodeList _ CONS[node, prevNodeList] ELSE { newNodeList _ freeNodeListCells; freeNodeListCells _ freeNodeListCells.rest; newNodeList^ _ [node, prevNodeList]; nFreeNodeListCells _ nFreeNodeListCells-1; }; }; FreeNodeListCell: ENTRY PROC [nodeList: NodeList] ~ { ENABLE UNWIND => NULL; nodeList^ _ [NIL, freeNodeListCells]; freeNodeListCells _ nodeList; nFreeNodeListCells _ nFreeNodeListCells+1; }; FreeNodeList: PROC [nodeList: NodeList] ~ { UNTIL nodeList=NIL DO nList: NodeList _ nodeList; nodeList _ nodeList.rest; FreeNodeListCell[nList]; ENDLOOP; }; NextNodeList2: PROC [fetList: FetList] RETURNS [nodeList: NodeList _ NIL] ~ { FOR iFetList: FetList _ fetList, iFetList.rest UNTIL iFetList = NIL DO IF NOT iFetList.first.ch1.done THEN { nodeList _ NewNodeListCell[iFetList.first.ch1, nodeList]; iFetList.first.ch1.done _ TRUE; }; IF NOT iFetList.first.ch2.done THEN { nodeList _ NewNodeListCell[iFetList.first.ch2, nodeList]; iFetList.first.ch2.done _ TRUE; }; ENDLOOP; }; --NextNodeList2 IsNodeInList: PUBLIC PROC [node: Node, nodeList: NodeList] RETURNS [found: BOOLEAN _ FALSE]~ { FOR inodeList: NodeList _ nodeList, inodeList.rest UNTIL inodeList=NIL DO IF inodeList.first=node THEN RETURN [TRUE]; ENDLOOP; }; AppendNodeLists: PUBLIC PROC [top, bottom: NodeList] RETURNS [nodeList: NodeList _ NIL] ~ { IF top=NIL THEN nodeList _ bottom ELSE FOR iNodeList: NodeList _ top, iNodeList.rest DO IF iNodeList.rest = NIL THEN { nodeList _ top; iNodeList.rest _ bottom; RETURN }; ENDLOOP; }; <> NewFetListCell: ENTRY PROC [fet: Fet _ NIL, prevFetList: FetList _ NIL] RETURNS [newFetList: FetList] ~ { ENABLE UNWIND => NULL; IF freeFetListCells=NIL THEN newFetList _ CONS[fet, prevFetList] ELSE { newFetList _ freeFetListCells; freeFetListCells _ freeFetListCells.rest; newFetList^ _ [fet, prevFetList]; nFreeFetListCells _ nFreeFetListCells-1; }; }; FreeFetListCell: ENTRY PROC [fetList: FetList] ~ { ENABLE UNWIND => NULL; fetList^ _ [NIL, freeFetListCells]; freeFetListCells _ fetList; nFreeFetListCells _ nFreeFetListCells+1; }; FreeFetList: PROC [fetList: FetList] ~ { UNTIL fetList=NIL DO fList: FetList _ fetList; fetList _ fetList.rest; FreeFetListCell[fList]; ENDLOOP; }; NextFetList2: PROC [nodeList: NodeList] RETURNS [fetList: FetList _ NIL] ~ { FOR iNodeList: NodeList _ nodeList, iNodeList.rest UNTIL iNodeList = NIL DO FOR i: NAT IN [0..iNodeList.first.fetSeq.nUsed) DO fet: Fet = iNodeList.first.fetSeq[i]; <> <> <> <> IF (NOT fet.done) AND (fet.gate#iNodeList.first) AND NOT (fet.directional AND fet.ch2=iNodeList.first) THEN { fetList _ NewFetListCell[fet, fetList]; fet.done _ TRUE; }; ENDLOOP; ENDLOOP; }; --NextFetList2 AppendFetLists: PUBLIC PROC [top, bottom: FetList] RETURNS [fetList: FetList _ NIL] ~ { IF top=NIL THEN fetList _ bottom ELSE FOR iFetList: FetList _ top, iFetList.rest DO IF iFetList.rest = NIL THEN { fetList _ top; iFetList.rest _ bottom; RETURN }; ENDLOOP; }; <> <> <> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <> <<};>> <> <> <<};>> <> <<};>> <<>> ClipSet: PROC [totalSet: Set] RETURNS [setList: SetList _ NIL] ~ { PrepareToClipSet[totalSet]; FOR inodeList: NodeList _ totalSet.lNodes, inodeList.rest UNTIL inodeList=NIL DO set: Set; IF inodeList.first.done THEN LOOP; setList _ NewSetListCell[setList]; set _ setList.first; FillSet[set, inodeList.first]; FindFixedV[set, totalSet.fixedV]; ENDLOOP; }; PrepareToClipSet: PROC [totalSet: Set] ~ { FOR iFetList: FetList _ totalSet.lFets, iFetList.rest UNTIL iFetList = NIL DO iFetList.first.done _ ~iFetList.first.switch; ENDLOOP; FOR iNodeList: NodeList _ totalSet.lNodes, iNodeList.rest UNTIL iNodeList=NIL DO iNodeList.first.done _ FALSE; ENDLOOP; FOR iNodeList: NodeList _ totalSet.fixedV, iNodeList.rest UNTIL iNodeList=NIL DO iNodeList.first.done _ TRUE; ENDLOOP; }; FillSet: PROC [set: Set, rootNode: Node] ~ { <> nodeList: NodeList; nodeList _ NewNodeListCell[rootNode]; set.lNodes _ nodeList; rootNode.done _ TRUE; UNTIL nodeList=NIL DO fetList: FetList _ NextFetList2[nodeList]; set.lFets _ AppendFetLists[set.lFets, fetList]; nodeList _ NextNodeList2[fetList]; set.lNodes _ AppendNodeLists[set.lNodes, nodeList]; ENDLOOP; }; FindFixedV: PROC [set: Set, fixedV: NodeList] ~ { FOR iNodeList: NodeList _ fixedV, iNodeList.rest UNTIL iNodeList=NIL DO iNodeList.first.done _ FALSE; ENDLOOP; FOR iFetList: FetList _ set.lFets, iFetList.rest UNTIL iFetList=NIL DO ch1: Node _ iFetList.first.ch1; ch2: Node _ iFetList.first.ch2; IF ch1.input THEN IF ~ch1.done AND iFetList.first.switch THEN { ch1.done _ TRUE; set.fixedV _ NewNodeListCell[ch1, set.fixedV]; }; IF ch2.input THEN IF ~ch2.done AND iFetList.first.switch THEN { ch2.done _ TRUE; set.fixedV _ NewNodeListCell[ch2, set.fixedV]; }; ENDLOOP; FOR iNodeList: NodeList _ fixedV, iNodeList.rest UNTIL iNodeList=NIL DO iNodeList.first.done _ TRUE; ENDLOOP; }; FLStats: PROC RETURNS [n, f, s, p, t, nc: CARD] ~ { <> n _ nFreeNodeListCells; f _ nFreeFetListCells; s _ nFreeSetListCells; p _ nFreePaths; t _ nFreeTries; nc _ nFreeNodeChains; }; <> <> <> <> <> <> <> <> <> <> <> < status _ FALSE;>> <=vDrain => status _ TRUE;>> < {>> <> < vTran);>> <<};>> <<};>> < {>> <> <> <> <> <> <