-- File: SimMOSRun.mesa -- Adapted by Martin Newell, January 1980, from MIT's MOSSIM -- Last Updated: December 4, 1980 12:47 PM -- For DStar compile using the /l switch DIRECTORY InlineDefs: FROM "InlineDefs" USING[BITSHIFT, BITAND, BITOR], IODefs: FROM "IODefs" USING[WriteString, WriteLine, WriteChar, CR, SP], SimMOSAccessDefs: FROM "SimMOSAccessDefs" USING[SetNodeFlags, SetNodeEquivClass, GetNodeFlags, GetNodeEquivClass, GetNodeName, GetNodeNext, SetTransNext, GetTransSource, GetTransDrain, GetTransNext], SimMOSDefs: FROM "SimMOSDefs" USING[Node, Transistor], SimMOSUtilitiesDefs: FROM "SimMOSUtilitiesDefs" USING[OnP, OffP, SimETrans, SimXTrans, SimDTrans, InputP, PullupP, StorageP, GateP, HasInputGnd, NewXFlag, NewGndFlag, OldGndFlag, NewVddFlag, OldVddFlag, NewVddGndFlags, OldVddGndFlags, NewToOldFlags, RootFlag, PermanentAndOldFlags, NewFlags1ToOldFlags2, SimAtomsLength, SimAtoms, HasInputVdd, HasPullup, HasGateVdd, HasGateGnd, DescriptorFlags, RootP, NewFlags, OldFlags, AllButRootFlag, CopyOldToNewFlags, PrintNode, SetDescriptor]; SimMOSRun: PROGRAM IMPORTS InlineDefs, IODefs, SimMOSAccessDefs, SimMOSUtilitiesDefs EXPORTS SimMOSDefs = BEGIN OPEN InlineDefs, IODefs, SimMOSAccessDefs, SimMOSDefs, SimMOSUtilitiesDefs; SimSolve: PUBLIC PROCEDURE[abort: PROCEDURE RETURNS[BOOLEAN]] = -- step - run simulation until no changes are detected, or abort returns TRUE BEGIN changed,shorts: CARDINAL; DO [changed, shorts] _ MicroStep[FALSE,FALSE]; IF changed=0 OR abort[] THEN EXIT; ENDLOOP; IF changed=0 AND shorts#0 THEN [,] _ MicroStep[FALSE,TRUE]; END; --An Equivalence Class, EC, is a set of nodes connected by ON enhancement mode transistors --The equivalence class is maintained as an inverted tree with all chains leading to --the Root, which has the RootFlag set. The Root is always the highest precedence --member of the class, where input>pullup>storage>other. --A SuperClass, SC, is a set of equivalence classes that are connected by X transistors. --This is also an inverted tree, in which the Root is identified by pointing to itself. --The Root of a superclass is not necessarily the highest precedence member, but it --contains a descriptor of the set of types and values of its members. These are --used to establish possible conflicts if any subset of the X transistors was on. MicroStep: PUBLIC PROCEDURE[reportChanges,reportShorts: BOOLEAN] RETURNS[changed,shorts: CARDINAL] = -- Execute one simulation iteration. -- Upon entry, it is assumed -- that the potential flags reflect the last simulation step and that -- each node has been made equivalent to itself. BEGIN nptr,next: Node; tptr,tnext,tprev: Transistor; i: CARDINAL; MakeEquiv: PROCEDURE [node1,node2: Node] RETURNS[BOOLEAN] = --Merge equivalence classes of node1 and node2. Merges which short -- two inputs having different values are not allowed BEGIN node1EC,node2EC: Node; Equiv: PROCEDURE [class1,class2: Node] = --make class1 point to class2, as well as node1 and node2 --remove RootFlag from class1 - beware side-effects! BEGIN class1Flags: WORD _ GetNodeFlags[class1]; class1Flags _ AllButRootFlag[class1Flags]; SetNodeFlags[class1,class1Flags]; SetNodeEquivClass[node1,class2]; SetNodeEquivClass[node2,class2]; SetNodeEquivClass[class1,class2]; END; --find classes of node1 and node2 FOR node1EC _ node1, GetNodeEquivClass[node1EC] UNTIL RootP[node1EC] DO ENDLOOP; FOR node2EC _ node2, GetNodeEquivClass[node2EC] UNTIL RootP[node2EC] DO ENDLOOP; --see if already in same class, and shorten chains if so IF node1EC=node2EC THEN BEGIN SetNodeEquivClass[node1,node1EC]; SetNodeEquivClass[node2,node1EC]; RETURN[TRUE]; END; --make classes equivalent, retaining higher precedence at root SELECT TRUE FROM InputP[node1EC] => BEGIN node1ECFlags: WORD _ GetNodeFlags[node1EC]; node2ECFlags: WORD _ GetNodeFlags[node2EC]; IF InputP[node2EC] AND OldFlags[node1ECFlags]#OldFlags[node2ECFlags] THEN BEGIN --short between two inputs having different values shorts _ shorts + 1; IF reportShorts THEN BEGIN WriteLine["Attempt to connect two inputs"]; WriteString["Nodes are: "]; PrintNode[node1]; IF node1#node1EC THEN BEGIN WriteString[" equivalent to input: "]; PrintNode[node1EC]; END; WriteChar[CR]; WriteString["and: "]; PrintNode[node2]; IF node2#node2EC THEN BEGIN WriteString[" equivalent to input: "]; PrintNode[node2EC]; END; WriteChar[CR]; END; RETURN[FALSE]; END ELSE Equiv[node2EC,node1EC]; END; PullupP[node1EC] => BEGIN IF InputP[node2EC] THEN Equiv[node1EC,node2EC] ELSE Equiv[node2EC,node1EC]; END; StorageP[node1EC] => BEGIN IF InputP[node2EC] OR PullupP[node2EC] THEN Equiv[node1EC,node2EC] ELSE Equiv[node2EC,node1EC]; END; ENDCASE => --node1EC is weakest possible Equiv[node1EC,node2EC]; RETURN[TRUE]; END; shorts _ 0; changed _ 0; -- for each enhancement mode transistor, if its gate is on -- make the source and drain nodes equivalent. -- If gate is x then move transistor to x list for subsequent scan tprev _ NIL; FOR tptr _ SimETrans, tnext UNTIL tptr=NIL DO tnext _ GetTransNext[tptr]; SELECT TRUE FROM OnP[tptr] => [] _ MakeEquiv[GetTransSource[tptr], GetTransDrain[tptr]]; ~OffP[tptr] => --i.e. x - move to SimXTrans BEGIN IF tprev=NIL THEN SimETrans _ tnext ELSE SetTransNext[tprev,tnext]; SetTransNext[tptr,SimXTrans]; SimXTrans _ tptr; LOOP; --i.e. leave tprev alone END; ENDCASE; --i.e. transistor is off tprev _ tptr; ENDLOOP; -- treat each depletion mode transistor as wire - i.e. join source and drain -- remember that only non-pullups are explicitly represented FOR tptr _ SimDTrans, GetTransNext[tptr] UNTIL tptr=NIL DO [] _ MakeEquiv[GetTransSource[tptr], GetTransDrain[tptr]]; ENDLOOP; --grow superclasses of classes joined by X transistors --propogate descriptor of members of superclass (types & values) --merge towards drain (arbitrary choice) tprev _ NIL; --will be left pointing to last member FOR tptr _ SimXTrans, GetTransNext[tptr] UNTIL tptr=NIL DO BEGIN source: Node _ GetTransSource[tptr]; drain: Node _ GetTransDrain[tptr]; sourceSC,drainSC: Node; sourceSCFlags,drainSCFlags: WORD; --get superclasses of source and drain (next=self) --Source: FOR sourceSC _ source, next DO next _ GetNodeEquivClass[sourceSC]; IF next=sourceSC THEN EXIT; ENDLOOP; sourceSCFlags _ GetNodeFlags[sourceSC]; --and Drain: FOR drainSC _ drain, next DO next _ GetNodeEquivClass[drainSC]; IF next=drainSC THEN EXIT; ENDLOOP; drainSCFlags _ GetNodeFlags[drainSC]; --merge classes --avoid merging if either SC is of type input, but always propogate -- descriptor to non-input class, if any IF InputP[sourceSC] THEN BEGIN --don't merge classes, investigate propogating descriptor to drainSC IF ~InputP[drainSC] THEN BEGIN drainSCFlags _ BITOR[drainSCFlags,DescriptorFlags[sourceSCFlags]]; SetNodeFlags[drainSC,drainSCFlags]; END; END ELSE BEGIN IF InputP[drainSC] THEN BEGIN --don't merge classes, but do propogate descriptor to source sourceSCFlags _ BITOR[sourceSCFlags,DescriptorFlags[drainSCFlags]]; SetNodeFlags[sourceSC,sourceSCFlags]; END ELSE BEGIN --neither is input - merge classes towards drain drainSCFlags _ BITOR[drainSCFlags,DescriptorFlags[sourceSCFlags]]; SetNodeFlags[drainSC,drainSCFlags]; --merge classes towards drainSC SetNodeEquivClass[sourceSC,drainSC]; END; END; tprev _ tptr; END; ENDLOOP; --Return X transistors to SimETrans: IF SimXTrans#NIL THEN BEGIN SetTransNext[tprev,SimETrans]; SimETrans _ SimXTrans; SimXTrans _ NIL; END; -- Run through all the nodes, and determine their values -- by chasing to the root of the equiv class. A second loop resets -- the NewFlags and equivalence classes for next iteration. FOR i IN [0..SimAtomsLength) DO FOR nptr _ SimAtoms[i], GetNodeNext[nptr] UNTIL nptr=NIL DO BEGIN nptrFlags: WORD _ GetNodeFlags[nptr]; nptrEC,nptrSC: Node; nptrECFlags,nptrSCFlags: WORD; --find root of equivalence class, nptrEC FOR nptrEC _ nptr,GetNodeEquivClass[nptrEC] UNTIL RootP[nptrEC] DO ENDLOOP; nptrECFlags _ GetNodeFlags[nptrEC]; --find root of superclass, nptrSC FOR nptrSC _ nptrEC, next DO next _ GetNodeEquivClass[nptrSC]; IF next=nptrSC THEN EXIT; ENDLOOP; nptrSCFlags _ GetNodeFlags[nptrSC]; --set nominal value of EC, if not already set, depending on type of the equiv class IF NewFlags[nptrECFlags]=0 THEN BEGIN SELECT TRUE FROM InputP[nptrEC] => --take its value regardless of superclass nptrECFlags _ CopyOldToNewFlags[nptrECFlags]; PullupP[nptrEC] => --check SC for HasInputGnd nptrECFlags _ IF BITAND[nptrSCFlags,HasInputGnd]#0 THEN BITOR[nptrECFlags, NewXFlag] ELSE BITOR[nptrECFlags, NewVddFlag]; StorageP[nptrEC] => nptrECFlags _ SELECT TRUE FROM BITAND[nptrECFlags,OldGndFlag]#0 => --check if InputVdd, Pullup or GateVdd in SC IF BITAND[nptrSCFlags,HasInputVdd+HasPullup+HasGateVdd]#0 THEN BITOR[nptrECFlags, NewXFlag] ELSE BITOR[nptrECFlags, NewGndFlag], BITAND[nptrECFlags,OldVddFlag]#0 => --check for InputGnd or GateGnd in SC IF BITAND[nptrSCFlags,HasInputGnd+HasGateGnd]#0 THEN BITOR[nptrECFlags, NewXFlag] ELSE BITOR[nptrECFlags, NewVddFlag], ENDCASE => BITOR[nptrECFlags, NewXFlag]; ENDCASE => nptrECFlags _ BITOR[nptrECFlags, NewXFlag]; SetNodeFlags[nptrEC,nptrECFlags]; END; --check for charge sharing between nptr and nptrEC IF StorageP[nptr] AND StorageP[nptrEC] AND OldFlags[nptrFlags]#OldFlags[nptrECFlags] THEN BEGIN -- charge sharing WriteLine["Charge sharing"]; WriteString["Nodes are: "]; PrintNode[nptr]; WriteString[" and "]; PrintNode[nptrEC]; WriteChar[CR]; --set EC to X --*should make another pass to set to X those nodes in -- this EC that have already been processed nptrECFlags _ BITOR[PermanentAndOldFlags[nptrECFlags], NewXFlag]; SetNodeFlags[nptrEC,nptrECFlags]; END; --copy value from EC into nptr nptrFlags _ NewFlags1ToOldFlags2[nptrECFlags,nptrFlags]; SetNodeFlags[nptr,nptrFlags]; END; ENDLOOP; ENDLOOP; --now visit all nodes again to move new values to old and reset equivalence classes IF reportChanges THEN WriteString["Nodes changing:"]; FOR i IN [0..SimAtomsLength) DO FOR nptr _ SimAtoms[i], GetNodeNext[nptr] UNTIL nptr=NIL DO BEGIN nptrFlags: WORD _ GetNodeFlags[nptr]; IF GateP[nptr] AND NewVddGndFlags[nptrFlags]#OldVddGndFlags[nptrFlags] THEN BEGIN changed _ changed + 1; IF reportChanges THEN BEGIN nodeName: STRING _ [50]; WriteChar[SP]; WriteString[GetNodeName[nptr,nodeName]]; END; END; nptrFlags _ NewToOldFlags[nptrFlags]; nptrFlags _ BITOR[nptrFlags, RootFlag]; nptrFlags _ SetDescriptor[nptrFlags]; SetNodeFlags[nptr, nptrFlags]; SetNodeEquivClass[nptr, nptr]; END; ENDLOOP; ENDLOOP; IF reportChanges THEN WriteChar[CR]; RETURN[changed, shorts] END; END. (635)\174b9B45f1 2f0 13f1 3f0 73f1 16f0 8f1 16f0 160f1 10f0 8f1 10f0 25f1 21f0 8f1 19f0 436f1 2f0 5b9B40f1 37f0 9f1 10f0 34f1 16f0 2f1 31f0 1087b9B350b9B209b5B