-- File: SimMOSCircuit.mesa -- Adapted by Martin Newell, January 1980, from MIT's MOSSIM -- Last Updated: December 4, 1980 12:40 PM -- For DStar compile using the /l switch DIRECTORY InlineDefs: FROM "InlineDefs" USING[BITAND, BITOR], IODefs: FROM "IODefs" USING[WriteLine], SimMOSAccessDefs: FROM "SimMOSAccessDefs" USING[AllocateTransistor, DestroyNodes, DestroyTransistors, SetNodeFlags, GetNodeFlags, GetNodeName, GetNodeNext, SetTrans, SetTransNext, GetTransGate, GetTransSource, GetTransDrain, GetTransNext], SimMOSDefs: FROM "SimMOSDefs" USING[Node, Transistor, TransistorRecord, L, H], SimMOSUtilitiesDefs: FROM "SimMOSUtilitiesDefs" USING[SimVddInputs, SimGndInputs, DestroyList, SimAtomsLength, SimAtoms, SimETrans, SimDTrans, sVDD, sGND, GateFlag, AllButGateFlag, SetDescriptor, AllButPullupFlag, GateStorage, SimIntern, PullupFlag, InputP, StorageP, OldGndFlag, OldVddFlag]; SimMOSCircuit: PROGRAM IMPORTS InlineDefs, IODefs, SimMOSAccessDefs, SimMOSDefs, SimMOSUtilitiesDefs EXPORTS SimMOSDefs = BEGIN OPEN InlineDefs, IODefs, SimMOSAccessDefs, SimMOSDefs, SimMOSUtilitiesDefs; --**Circuit Definition**-- SimReset: PUBLIC PROCEDURE = -- global simulator reset, zaps data base to initial state BEGIN i: CARDINAL; SimVddInputs _ DestroyList[SimVddInputs]; SimGndInputs _ DestroyList[SimGndInputs]; FOR i IN [0..SimAtomsLength) DO SimAtoms[i] _ DestroyNodes[SimAtoms[i]]; ENDLOOP; SimETrans _ DestroyTransistors[SimETrans]; SimDTrans _ DestroyTransistors[SimDTrans]; sGND _ SimNode["GND", FALSE]; L["GND"]; sVDD _ SimNode["VDD", FALSE]; H["VDD"]; END; ETrans: PUBLIC PROCEDURE[gate,source,drain: STRING] RETURNS[t: Transistor] = -- (ETrans 'gate 'source 'drain) makes an enhancement mode transistor -- with the specified connections BEGIN IF gate.length=0 OR source.length=0 OR drain.length=0 THEN BEGIN WriteLine["Null names not allowed in transistor definition"]; RETURN; END; RETURN[ETrans1[SimNode[gate,FALSE],SimNode[source,FALSE],SimNode[drain,FALSE]]]; END; ETrans1: PROCEDURE[gate,source,drain: Node] RETURNS[trans: Transistor] = BEGIN gateFlags: WORD _ GetNodeFlags[gate]; trans _ AllocateTransistor[]; SetTrans[trans: trans, transGate: gate, transSource: source, transDrain: drain, transNext: SimETrans]; gateFlags _ BITOR[gateFlags,GateFlag]; gateFlags _ SetDescriptor[gateFlags]; SetNodeFlags[gate,gateFlags]; SimETrans _ trans; END; DTrans: PUBLIC PROCEDURE[gate,source,drain: STRING] RETURNS[t: Transistor] = -- will either make an enhancement mode transistor with gate connected to VDD, -- or will mark the relevant node pulled up, and return NIL BEGIN IF gate.length=0 OR source.length=0 OR drain.length=0 THEN BEGIN WriteLine["Null names not allowed in transistor definition"]; RETURN; END; RETURN[DTrans1[SimNode[gate,FALSE],SimNode[source,FALSE],SimNode[drain,FALSE]]]; END; DTrans1: PROCEDURE[gate,source,drain: Node] RETURNS[trans: Transistor] = BEGIN IF source=sVDD OR drain=sVDD THEN BEGIN -- a pullup - these are not explicitly represented gateNodeFlags,sourceNodeFlags: WORD; IF source=sVDD THEN BEGIN --switch it around temp: Node = source; source _ drain; drain _ temp; END; sourceNodeFlags _ GetNodeFlags[source]; sourceNodeFlags _ BITOR[sourceNodeFlags,PullupFlag]; sourceNodeFlags _ SetDescriptor[sourceNodeFlags]; SetNodeFlags[source,sourceNodeFlags]; gateNodeFlags _ GetNodeFlags[gate]; gateNodeFlags _ BITOR[gateNodeFlags,GateFlag]; gateNodeFlags _ SetDescriptor[gateNodeFlags]; SetNodeFlags[gate,gateNodeFlags]; RETURN[NIL]; END ELSE -- a "yellow" transistor - put it on SimDTrans BEGIN gateFlags: WORD _ GetNodeFlags[gate]; trans _ AllocateTransistor[]; SetTrans[trans: trans, transGate: gate, transSource: source, transDrain: drain, transNext: SimDTrans]; gateFlags _ BITOR[gateFlags,GateFlag]; gateFlags _ SetDescriptor[gateFlags]; SetNodeFlags[gate,gateFlags]; SimDTrans _ trans; END; END; SetStorage: PUBLIC PROCEDURE[gatesOnly: BOOLEAN] = -- set mode of charge storage BEGIN GateStorage _ gatesOnly; END; SimNode: PUBLIC PROCEDURE[name: STRING, noCreate: BOOLEAN] RETURNS[n: Node] = -- (SimNode name) makes a node with the appropriate name. if node -- already exists, nothing is done (but it is returned). if node does -- not exist and no-create=t then NIL is returned. BEGIN n _ SimIntern[name,noCreate]; END; --**Circuit Interrogation**-- EnumerateNodes: PUBLIC PROCEDURE[apply: PROCEDURE[Node]RETURNS[abort: BOOLEAN]] RETURNS[aborted: BOOLEAN] = --Invoke apply for each node BEGIN i: CARDINAL; nptr: Node; FOR i IN [0..SimAtomsLength) DO FOR nptr _ SimAtoms[i], GetNodeNext[nptr] UNTIL nptr=NIL DO IF apply[nptr] THEN RETURN[TRUE]; ENDLOOP; ENDLOOP; RETURN[FALSE]; END; EnumerateETrans: PUBLIC PROCEDURE[apply: PROCEDURE[Transistor]RETURNS[BOOLEAN]] RETURNS[aborted: BOOLEAN] = --Invoke apply for each enhancement mode transistor --If apply returns TRUE then enumeration is aborted BEGIN tptr: Transistor; FOR tptr _ SimETrans, GetTransNext[tptr] UNTIL tptr=NIL DO IF apply[tptr] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; END; EnumerateDTrans: PUBLIC PROCEDURE[apply: PROCEDURE[Transistor]RETURNS[BOOLEAN]] RETURNS[aborted: BOOLEAN] = --Invoke apply for each depletion mode transistor -- However, pullup nodes are not explicitly sored --If apply returns TRUE then enumeration is aborted BEGIN tptr: Transistor; MakeDTrans: PROCEDURE[node: Node] RETURNS[BOOLEAN] = BEGIN nodeFlags: WORD _ GetNodeFlags[node]; --don't use PullupP[node] in next line since gives FALSE if also InputP IF BITAND[nodeFlags,PullupFlag]#0 THEN BEGIN trans: Transistor; TransRec.transGate _ node; TransRec.transSource _ node; TransRec.transDrain _ sVDD; TransRec.transNext _ NIL; trans _ LONG[@TransRec]; RETURN[apply[trans]]; END ELSE RETURN[FALSE]; END; --enumerate yellow transistors FOR tptr _ SimDTrans, GetTransNext[tptr] UNTIL tptr=NIL DO IF apply[tptr] THEN RETURN[TRUE]; ENDLOOP; --enumerate reconstituted transistors RETURN[EnumerateNodes[MakeDTrans]]; END; RedefineETrans: PUBLIC PROCEDURE[trans: Transistor, gate,source,drain: STRING] = --Redefine terminals of given enhancement mode transistor BEGIN IF gate.length=0 OR source.length=0 OR drain.length=0 THEN BEGIN WriteLine["Null names not allowed in redefined transistor"]; RETURN; END; RedefineETrans1[trans, SimNode[gate,FALSE],SimNode[source,FALSE],SimNode[drain,FALSE]]; END; RedefineETrans1: PROCEDURE[trans: Transistor, gate,source,drain: Node] = --Redefine terminals of given transistor BEGIN oldGate: Node _ GetTransGate[trans]; oldGateFlags: WORD _ GetNodeFlags[oldGate]; oldTransNext: Transistor _ GetTransNext[trans]; gateFlags: WORD _ GetNodeFlags[gate]; FindGate: PROCEDURE[t: Transistor] RETURNS[BOOLEAN] = BEGIN RETURN[GetTransGate[t]=oldGate]; END; SetTrans[trans: trans, transGate: gate, transSource: source, transDrain: drain, transNext: oldTransNext]; IF gate#oldGate THEN BEGIN gateFlags _ BITOR[gateFlags,GateFlag]; gateFlags _ SetDescriptor[gateFlags]; SetNodeFlags[gate,gateFlags]; IF ~EnumerateETrans[FindGate] THEN BEGIN --not found - remove GateFlag oldGateFlags _ AllButGateFlag[oldGateFlags]; oldGateFlags _ SetDescriptor[oldGateFlags]; SetNodeFlags[oldGate,oldGateFlags]; END; END; END; RedefineDTrans: PUBLIC PROCEDURE[trans: Transistor, gate,source,drain: STRING] = --Redefine terminals of given depletion mode transistor BEGIN IF gate.length=0 OR source.length=0 OR drain.length=0 THEN BEGIN WriteLine["Null names not allowed in redefined transistor"]; RETURN; END; RedefineDTrans1[trans, SimNode[gate,FALSE],SimNode[source,FALSE],SimNode[drain,FALSE]]; END; RedefineDTrans1: PROCEDURE[trans: Transistor, gate,source,drain: Node] = BEGIN oldSource: Node _ GetTransSource[trans]; oldGate: Node _ GetTransGate[trans]; oldPullup: BOOLEAN _ TRUE; tptr: Transistor; prevD: Transistor; FindGate: PROCEDURE[t: Transistor] RETURNS[BOOLEAN] = BEGIN RETURN[GetTransGate[t]=oldGate]; END; --see if transistor is non-pullup, and establish pointer to previous --cannot use EnumerateDTrans since do not want pullups prevD _ NIL; --means head of SimDTrans FOR tptr _ SimDTrans, GetTransNext[tptr] UNTIL tptr=NIL DO IF tptr=trans THEN BEGIN oldPullup _ FALSE; EXIT; END; prevD _ tptr; ENDLOOP; IF oldPullup THEN --remove PullupFlag from oldSource - no way of checking if valid! BEGIN --will get reset if new is pullup oldSourceFlags: WORD _ GetNodeFlags[oldSource]; oldSourceFlags _ AllButPullupFlag[oldSourceFlags]; oldSourceFlags _ SetDescriptor[oldSourceFlags]; SetNodeFlags[oldSource,oldSourceFlags]; END; --establish type of new version IF source=sVDD OR drain=sVDD THEN BEGIN -- a pullup IF source=sVDD THEN BEGIN --switch it around temp: Node = source; source _ drain; drain _ temp; END; IF ~oldPullup THEN --yellow becoming pullup - remove it from SimDTrans BEGIN --previous transistor is prevD (notice lack of releasing space! - boo) next: Transistor _ GetTransNext[trans]; IF prevD=NIL THEN SimDTrans _ next ELSE SetTransNext[prevD,next]; END; --reconnect new pullup [] _ DTrans1[gate,source,drain]; END ELSE --new transistor is yellow BEGIN IF oldPullup THEN BEGIN --pullup becoming yellow [] _ DTrans1[gate,source,drain]; END ELSE BEGIN --old and new are yellow oldTransNext: Transistor _ GetTransNext[trans]; SetTrans[trans: trans, transGate: gate, transSource: source, transDrain: drain, transNext: oldTransNext]; END; END; --adjust gate bit if necessary IF gate#oldGate THEN BEGIN gateFlags: WORD _ GetNodeFlags[gate]; gateFlags _ BITOR[gateFlags,GateFlag]; gateFlags _ SetDescriptor[gateFlags]; SetNodeFlags[gate,gateFlags]; IF ~EnumerateETrans[FindGate] AND ~EnumerateDTrans[FindGate] THEN BEGIN --not found - remove GateFlag oldGateFlags: WORD _ GetNodeFlags[oldGate]; oldGateFlags _ AllButGateFlag[oldGateFlags]; oldGateFlags _ SetDescriptor[oldGateFlags]; SetNodeFlags[oldGate,oldGateFlags]; END; END; END; NodeNames: PUBLIC PROCEDURE[trans: Transistor, gate,source,drain: STRING] = --Copy existing names of terminals of given transistor into strings provided BEGIN transGate: Node _ GetTransGate[trans]; transSource: Node _ GetTransSource[trans]; transDrain: Node _ GetTransDrain[trans]; [] _ GetNodeName[transGate,gate]; [] _ GetNodeName[transSource,source]; [] _ GetNodeName[transDrain,drain]; END; NodeAttributes: PUBLIC PROCEDURE[node: Node, name: STRING] RETURNS[value: CHARACTER, input,storage: BOOLEAN] = --Copy existing name of node into string provided, and return other state BEGIN [] _ GetNodeName[node,name]; value _ SELECT TRUE FROM BITAND[GetNodeFlags[node],OldGndFlag]#0 => '0, BITAND[GetNodeFlags[node],OldVddFlag]#0 => '1, ENDCASE => 'X; input _ InputP[node]; storage _ StorageP[node]; END; TransRec: PUBLIC TransistorRecord; -- used as permanent storage in EnumerateDTrans END. (635)\178b9B50f1 3f0 40f1 16f0 8f1 16f0 200f1 10f0 8f1 10f0 49f1 21f0 8f1 19f0 245f1 2f0 5b13B40f1 49f0 9f1 10f0 34f1 16f0 2f1 31f0