--File: SimMOSUtilitiesDefs.mesa
-- Martin Newell, January 1980
--Last Updated: December 4, 1980 1:30 PM
DIRECTORY
InlineDefs: FROM "InlineDefs" USING [BITAND, BITOR, BITSHIFT],
SimMOSAccessDefs: FROM "SimMOSAccessDefs" USING[GetNodeFlags, GetTransGate],
SimMOSDefs: FROM "SimMOSDefs" USING[Transistor, Node
];

SimMOSUtilitiesDefs: DEFINITIONS
IMPORTS
InlineDefs, SimMOSAccessDefs =

BEGIN OPEN InlineDefs,
SimMOSAccessDefs, SimMOSDefs;

SimMOSUtilities: PROGRAM;

OldVddFlag: CARDINAL = 1;
OldGndFlag: CARDINAL = 2;
OldXFlag: CARDINAL = 4;
NewVddFlag: CARDINAL = 10B;
NewGndFlag: CARDINAL = 20B;
NewXFlag: CARDINAL = 40B;
InputFlag: CARDINAL = 100B;
-- node is an input
GateFlag: CARDINAL = 200B;
-- node is hooked to the gate of some transistor
PullupFlag: CARDINAL = 400B;
-- node is pulled up

RootFlag: CARDINAL = 100000B;
-- node is current root of Equiv class
--flags for accumulating members of superclasses
HasInputVdd: CARDINAL = 40000B;
HasInputGnd: CARDINAL = 20000B;
HasPullup: CARDINAL = 10000B;
HasGateVdd: CARDINAL = 4000B;
HasGateGnd: CARDINAL = 2000B;


-- macros for accessing flags
DescriptorFlags: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
RETURN[BITAND[HasInputVdd+HasInputGnd+HasPullup+HasGateVdd+HasGateGnd, flags]];
END;
PermanentFlags: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
RETURN[BITAND[RootFlag+PullupFlag+GateFlag+InputFlag, flags]];
END;
PermanentAndOldFlags: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
RETURN[
BITAND[RootFlag+PullupFlag+GateFlag+InputFlag+OldXFlag+OldGndFlag+OldVddFlag,flags]];
END;
NewFlags: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
RETURN[BITSHIFT[BITAND[flags, NewVddFlag+NewGndFlag+NewXFlag], -3]];
END;
OldFlags: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
RETURN[BITAND[flags, OldVddFlag+OldGndFlag+OldXFlag]];
END;
NewVddGndFlags: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
RETURN[BITSHIFT[BITAND[flags, NewVddFlag+NewGndFlag], -3]];
END;
OldVddGndFlags: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
RETURN[BITAND[flags, OldVddFlag+OldGndFlag]];
END;
AllButInputFlag: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
RETURN[BITAND[177777B-InputFlag, flags]];
END;
AllButPullupFlag: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
RETURN[BITAND[177777B-PullupFlag, flags]];
END;
AllButGateFlag: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
RETURN[BITAND[177777B-GateFlag, flags]];
END;
AllButRootFlag: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
RETURN[BITAND[177777B-RootFlag, flags]];
END;
AllButDescriptorFlags: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
RETURN[BITAND[177777B-(HasInputVdd+HasInputGnd+HasPullup+HasGateVdd+HasGateGnd),flags]];
END;

-- predicates based on nodeFlags
OffP: PROCEDURE[trans: Transistor] RETURNS[BOOLEAN] = INLINE
BEGIN
transGate: Node ← GetTransGate[trans];
RETURN[BITAND[OldGndFlag,GetNodeFlags[transGate]]#0];
END;
OnP: PROCEDURE[trans: Transistor] RETURNS[BOOLEAN] = INLINE
BEGIN
transGate: Node ← GetTransGate[trans];
RETURN[BITAND[OldVddFlag,GetNodeFlags[transGate]]#0];
END;
InputP: PROCEDURE[n: Node] RETURNS[BOOLEAN] = INLINE
BEGIN
RETURN[BITAND[InputFlag,GetNodeFlags[n]]#0];
END;
PullupP: PROCEDURE[n: Node] RETURNS[BOOLEAN] = INLINE
BEGIN --Pullup AT MOST
RETURN[BITAND[InputFlag+PullupFlag,GetNodeFlags[n]]=PullupFlag];
END;
StorageP: PROCEDURE[n: Node] RETURNS[BOOLEAN] = INLINE
BEGIN --Gate AT MOST
RETURN[(GateStorage AND BITAND[InputFlag+PullupFlag+GateFlag,GetNodeFlags[n]]=GateFlag)
OR (~GateStorage AND BITAND[InputFlag+PullupFlag,GetNodeFlags[n]]=0)];
END;
GateP: PROCEDURE[n: Node] RETURNS[BOOLEAN] = INLINE
BEGIN --Connected to a gate (i.e. can switch a transistor)
RETURN[BITAND[GateFlag,GetNodeFlags[n]]#0];
END;
NewXP: PROCEDURE[n: Node] RETURNS[BOOLEAN] = INLINE
BEGIN
RETURN[BITAND[NewXFlag,GetNodeFlags[n]]#0];
END;
RootP: PROCEDURE[n: Node] RETURNS[BOOLEAN] = INLINE
BEGIN
RETURN[BITAND[RootFlag,GetNodeFlags[n]]#0];
END;

-- given flag word returns with new flags MOVED to old flags
NewToOldFlags: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
perm: WORD ← PermanentFlags[flags];
new: WORD ← NewFlags[flags]; --(returned as old flags)
RETURN[BITOR [perm, new]];
END;

-- given flag word returns with old flags COPIED to new flags
CopyOldToNewFlags: PROCEDURE [flags: WORD] RETURNS [WORD] = INLINE
BEGIN
permAndOld: WORD ← PermanentAndOldFlags[flags];
old: WORD ← OldFlags[flags];
RETURN[BITOR [permAndOld, BITSHIFT[old,3]]];
END;

NewFlags1ToOldFlags2: PROCEDURE [flags1,flags2: WORD] RETURNS [WORD] = INLINE
BEGIN
allButNewFlags2: WORD ← BITAND[flags2, 177777B-(NewXFlag+NewGndFlag+NewVddFlag)];
RETURN[BITOR[BITAND[flags1, NewXFlag+NewGndFlag+NewVddFlag], allButNewFlags2]];
END;

SetDescriptor: PROCEDURE[flags: WORD] RETURNS[WORD];
--return flags with descriptor bits set according to type and old value

--Named-structure handler for Node structure, to make it print nicer
PrintNode: PROCEDURE[n: Node];

--Print VGX from node bits
PrintNodeBits: PROCEDURE[bits: WORD];

SimIntern: PROCEDURE[str: STRING, noCreate: BOOLEAN] RETURNS[n: Node];
--names are hashed and matched by EquivalentString

--List processing support

List: TYPE = POINTER TO ConsCell;
ConsCell: TYPE = RECORD [
value: LONG POINTER,
next: List];

AddToList: PROCEDURE[element: LONG POINTER, list: List] RETURNS[l: List];

RemoveFromList: PROCEDURE[element: LONG POINTER, list: List] RETURNS[l: List];

InList: PROCEDURE[element: LONG POINTER, list: List] RETURNS[BOOLEAN];

DestroyList: PROCEDURE[list: List] RETURNS[List];

-- Global variables

SimVddInputs: List;
-- list of nodes to be forced to vdd
SimGndInputs: List;
-- list of nodes to be forced to gnd
SimETrans: Transistor;
-- list of enhancement mode transistors
SimDTrans: Transistor;
-- list of non-pullup depletion mode transistors
SimXTrans: Transistor;
-- list of transistors with gate=X
sGND: Node;
-- ground node
sVDD: Node;
-- vdd node
SimAtoms: ARRAY [0..SimAtomsLength) OF Node;
--obarray for simulator nodes
SimAtomsLength: CARDINAL = 512;
--length of obarray
GateStorage: BOOLEAN;
-- mode of charge storage

END.