-- File: SimMOSState.mesa
-- Adapted by Martin Newell, January 1980, from MIT’s MOSSIM
-- Last Updated: December 4, 1980 12:49 PM
-- For DStar compile using the /l switch
DIRECTORY
InlineDefs: FROM "InlineDefs" USING[BITAND, BITOR],
IODefs: FROM "IODefs" USING[WriteString, WriteLine, WriteChar, CR],
SimMOSAccessDefs: FROM "SimMOSAccessDefs" USING[SetNodeFlags, GetNodeFlags],
SimMOSDefs: FROM "SimMOSDefs" USING[Node, EnumerateNodes, SimNode],
SimMOSUtilitiesDefs: FROM "SimMOSUtilitiesDefs" USING[SimVddInputs, SimGndInputs, sVDD, sGND, GateFlag, SetDescriptor, PullupFlag, PermanentFlags, PermanentAndOldFlags, InputFlag, AllButInputFlag, OldVddFlag, OldGndFlag, GateStorage, InputP, StorageP, InList, AddToList, RemoveFromList];
SimMOSState: PROGRAM
IMPORTS InlineDefs, IODefs, SimMOSAccessDefs, SimMOSDefs, SimMOSUtilitiesDefs
EXPORTS SimMOSDefs =
BEGIN OPEN InlineDefs, IODefs, SimMOSAccessDefs, SimMOSDefs, SimMOSUtilitiesDefs;
--**State Definition**--
CircuitReset: PUBLIC PROCEDURE[value: CHARACTER] =
-- Apply (SH,SL,X) to all nodes for value = (1, 0, X)
BEGIN
NodeReset: PROCEDURE [n: Node] RETURNS[BOOLEAN] =
BEGIN
IF n#sVDD AND n#sGND THEN
SELECT value FROM
’1=> IF ~InputP[n] THEN MakeHi[n,FALSE];
’0=> IF ~InputP[n] THEN MakeLo[n,FALSE];
’X,’x=> X1[n];
ENDCASE=>
BEGIN
WriteString["Invalid node value in CircuitReset: "]; WriteChar[value];
WriteChar[CR];
RETURN[TRUE];
END;
RETURN[FALSE];
END;
[] ← EnumerateNodes[NodeReset];
END;
H: PUBLIC PROCEDURE[name: STRING] =
-- make node an input tied to VDD
BEGIN
n: Node ← SimNode[name, TRUE];
nFlags: WORD;
SELECT n FROM
NIL =>
BEGIN
WriteString[name];
WriteLine[" is not a node (in hi)"];
RETURN;
END;
sGND =>
BEGIN
WriteLine["Attempt to connect GND to VDD (in hi)"];
RETURN;
END;
ENDCASE;
IF ~InList[n,SimVddInputs] THEN SimVddInputs ← AddToList[n,SimVddInputs];
SimGndInputs ← RemoveFromList[n,SimGndInputs];
nFlags ← GetNodeFlags[n];
nFlags ← BITOR[PermanentFlags[nFlags],InputFlag+OldVddFlag];
nFlags ← SetDescriptor[nFlags];
SetNodeFlags[n, nFlags];
END;
L: PUBLIC PROCEDURE[name: STRING] =
-- make node an input tied to GND
BEGIN
n: Node ← SimNode[name, TRUE];
nFlags: WORD;
SELECT n FROM
NIL =>
BEGIN
WriteString[name];
WriteLine[" is not a node (in lo)"];
RETURN;
END;
sVDD =>
BEGIN
WriteLine["Attempt to connect VDD to GND (in lo)"];
RETURN;
END;
ENDCASE;
IF ~InList[n,SimGndInputs] THEN SimGndInputs ← AddToList[n,SimGndInputs];
SimVddInputs ← RemoveFromList[n,SimVddInputs];
nFlags ← GetNodeFlags[n];
nFlags ← BITOR[PermanentFlags[nFlags],InputFlag+OldGndFlag];
nFlags ← SetDescriptor[nFlags];
SetNodeFlags[n, nFlags];
END;
X: PUBLIC PROCEDURE[name: STRING] =
-- remove node as an input, back to normal status
BEGIN
n: Node ← SimNode[name, TRUE];
SELECT n FROM
NIL =>
BEGIN
WriteString[name];
WriteLine[" is not a node (in x)"];
RETURN;
END;
sGND,sVDD =>
BEGIN
WriteLine["Attempt to disconnect GND or VDD (in x)"];
RETURN;
END;
ENDCASE;
X1[n];
END;
X1: PROCEDURE[n: Node] =
-- internal - remove node as an input, back to normal status
BEGIN
nFlags: WORD;
SimVddInputs ← RemoveFromList[n,SimVddInputs];
SimGndInputs ← RemoveFromList[n,SimGndInputs];
nFlags ← GetNodeFlags[n];
nFlags ← PermanentAndOldFlags[nFlags];
nFlags ← AllButInputFlag[nFlags];
nFlags ← SetDescriptor[nFlags];
SetNodeFlags[n, nFlags];
END;
SH: PUBLIC PROCEDURE[name: STRING] =
-- Store High on node, if connected to a gate
BEGIN
n: Node ← SimNode[name, TRUE];
SELECT n FROM
NIL =>
BEGIN
WriteString[name];
WriteLine[" is not a node"];
RETURN;
END;
sGND =>
BEGIN
WriteLine["Attempt to store 1 on GND"];
RETURN;
END;
ENDCASE;
MakeHi[n, TRUE];
END;
InitHi: PUBLIC PROCEDURE[name: STRING] =
-- Initialize High on node
BEGIN
n: Node ← SimNode[name, TRUE];
SELECT n FROM
NIL =>
BEGIN
WriteString[name];
WriteLine[" is not a node"];
RETURN;
END;
sGND =>
BEGIN
WriteLine["Attempt to initialize GND to 1"];
RETURN;
END;
ENDCASE;
MakeHi[n, FALSE];
END;
MakeHi: PROCEDURE[n: Node, checkStorage: BOOLEAN] =
-- Initialize High on node
BEGIN
SELECT TRUE FROM
InputP[n] =>WriteLine["Attempt to store high on an input node"];
checkStorage AND ~StorageP[n] =>WriteLine["Attempt to store high on non-storage node"];
ENDCASE =>
BEGIN
nFlags: WORD ← GetNodeFlags[n];
nFlags ← PermanentFlags[nFlags];
nFlags ← BITOR[nFlags,OldVddFlag];
nFlags ← SetDescriptor[nFlags];
SetNodeFlags[n, nFlags];
END;
END;
SL: PUBLIC PROCEDURE[name: STRING] =
-- Store Low on node, if connected to a gate
BEGIN
n: Node ← SimNode[name, TRUE];
SELECT n FROM
NIL =>
BEGIN
WriteString[name];
WriteLine[" is not a node"];
RETURN;
END;
sVDD =>
BEGIN
WriteLine["Attempt to store 0 on VDD"];
RETURN;
END;
ENDCASE;
MakeLo[n, TRUE];
END;
InitLo: PUBLIC PROCEDURE[name: STRING] =
-- Initialize High on node
BEGIN
n: Node ← SimNode[name, TRUE];
SELECT n FROM
NIL =>
BEGIN
WriteString[name];
WriteLine[" is not a node"];
RETURN;
END;
sVDD =>
BEGIN
WriteLine["Attempt to initialize VDD to 0"];
RETURN;
END;
ENDCASE;
MakeLo[n, FALSE];
END;
MakeLo: PROCEDURE[n: Node, checkStorage: BOOLEAN] =
-- Store Low on node, if connected to a gate
BEGIN
SELECT TRUE FROM
InputP[n] =>WriteLine["Attempt to store low on an input node"];
checkStorage AND ~StorageP[n] =>WriteLine["Attempt to store low on non-storage node"];
ENDCASE =>
BEGIN
nFlags: WORD ← GetNodeFlags[n];
nFlags ← PermanentFlags[nFlags];
nFlags ← BITOR[nFlags,OldGndFlag];
nFlags ← SetDescriptor[nFlags];
SetNodeFlags[n, nFlags];
END;
END;
--**State Interrogation**--
GetNodeValue: PUBLIC PROCEDURE[name: STRING] RETURNS[CHARACTER] =
-- get value of node. returns 1,0,-1 for high,low,x
BEGIN
n: Node;
IF (n ← SimNode[name, TRUE])=NIL THEN
BEGIN
WriteString[name];
WriteLine[" is not a node (in GetNodeValue)"];
RETURN[’X];
END;
RETURN[SELECT TRUE FROM
BITAND[GetNodeFlags[n],OldGndFlag]#0 => ’0,
BITAND[GetNodeFlags[n],OldVddFlag]#0 => ’1,
ENDCASE => ’X];
END;
END.