<> <> <> DIRECTORY Build, Flow, Globals, HashTable, IO, Mark, Model, Parse, Printout, Rope; MarkImpl: CEDAR PROGRAM IMPORTS Build, Flow, Globals, IO, HashTable, Model, Parse, Printout EXPORTS Mark = BEGIN OPEN Mark; <> flag: {input, output, bus, precharged, watched}; value: REAL; ivalue: INT; <> nodes0: INT _ 0; -- number of nodes forced to zero. nodes1: INT _ 0; -- number of nodes forced to one. dynamic: INT _ 0; -- number of nodes marked dynamic. simCount: INT _ 0; -- counts calls to checkNode and findStrength. <> SeeSettings: PUBLIC BOOLEAN _ FALSE; SeeAllSettings: PUBLIC BOOLEAN _ FALSE; SeeDynamic: PUBLIC BOOLEAN _ FALSE; <> FSLimit: PUBLIC INT _ 1000; fSCount: INT; InputCmd: PUBLIC Globals.CmdProc = BEGIN node: Globals.Node; <> WHILE args # NIL DO <> node _ Build.NodeFromRope[args.rope, globalVars]; node.input _ TRUE; args _ args.next; ENDLOOP; END; OutputCmd: PUBLIC Globals.CmdProc = BEGIN node: Globals.Node; <> WHILE args # NIL DO <> node _ Build.NodeFromRope[args.rope, globalVars]; node.output _ TRUE; args _ args.next; ENDLOOP; END; BusCmd: PUBLIC Globals.CmdProc = BEGIN node: Globals.Node; <> WHILE args # NIL DO <> node _ Build.NodeFromRope[args.rope, globalVars]; node.bus _ TRUE; args _ args.next; ENDLOOP; END; PrechargedCmd: PUBLIC Globals.CmdProc = BEGIN node: Globals.Node; flag _ precharged; WHILE args # NIL DO <> node _ Build.NodeFromRope[args.rope, globalVars]; node.precharged _ TRUE; node.bus _ TRUE; args _ args.next; ENDLOOP; END; WatchCmd: PUBLIC Globals.CmdProc = BEGIN node: Globals.Node; flag _ watched; WHILE args # NIL DO <> node _ Build.NodeFromRope[args.rope, globalVars]; node.watched _ TRUE; args _ args.next; ENDLOOP; END; <> <> <> < node.input _ TRUE;>> < node.output _ TRUE;>> < node.bus _ TRUE;>> < node.watched _ TRUE;>> < >> <> <> <> <> <> <> ResCmd: PUBLIC Globals.CmdProc = BEGIN ok: BOOLEAN; node: Globals.Node; IF args = NIL THEN BEGIN IO.PutRope[Globals.StdOut, "No resistance value given.\n"]; RETURN; END; [ok, value] _ Parse.Real[args]; IF (NOT ok) OR (value < 0) THEN BEGIN IO.PutRope[Globals.StdOut, "Bad resistance value.\n"]; RETURN; END; args _ args.next; WHILE args # NIL DO <> node _ Build.NodeFromRope[args.rope, globalVars]; node.res _ value; args _ args.next; ENDLOOP; END; <> <> <> <> <> CapCmd: PUBLIC Globals.CmdProc = BEGIN ok: BOOLEAN; node: Globals.Node; IF args = NIL THEN BEGIN IO.PutRope[Globals.StdOut, "No capacitance value given.\n"]; RETURN; END; [ok, value] _ Parse.Real[args]; IF (NOT ok) OR (value < 0) THEN BEGIN IO.PutRope[Globals.StdOut, "Bad capacitance value.\n"]; RETURN; END; args _ args.next; WHILE args # NIL DO <> node _ Build.NodeFromRope[args.rope, globalVars]; node.cap _ value; args _ args.next; ENDLOOP; END; <> <> <> <> <> SetNodeValue: PUBLIC PROC[node: Globals.Node, value: INT, propAnyway: BOOLEAN _ FALSE, globalVars: Globals.GlobalVars] = BEGIN p: Globals.Pointer; f: Globals.Fet; <> IF value = 0 THEN BEGIN IF node.always1 THEN IO.PutF[Globals.StdOut, "Node forced to 1, then to 0 (0 wins): %s.\n", IO.rope[Printout.NodeRope[node, globalVars]]]; node.always1 _ FALSE; IF node.always0 AND NOT propAnyway THEN RETURN; node.always0 _ TRUE; nodes0 _ nodes0 + 1; END ELSE BEGIN IF node.always0 THEN IO.PutF[Globals.StdOut, "Node forced to 0, then to 1 (1 wins): %s.\n", IO.rope[Printout.NodeRope[node, globalVars]]]; node.always0 _ FALSE; IF node.always1 AND NOT propAnyway THEN RETURN; node.always1 _ TRUE; nodes1 _ nodes1 + 1; END; <> <<((Rope.Fetch[node.name, 0] < '0) OR (Rope.Fetch[node.name, 0] > '9))) THEN>> <> IF SeeAllSettings OR SeeSettings THEN IO.PutF[Globals.StdOut, "Node %s forced to %d.\n", IO.rope[Printout.NodeRope[node, globalVars]], IO.int[value]]; <> FOR p _ node.firstPointer, p.next UNTIL p = NIL DO f _ p.fet; <> IF (f.source = node) AND f.flowFromSource AND (f.onAlways OR f.forcedOn) THEN CheckNode[f.drain, globalVars]; IF (f.drain = node) AND f.flowFromDrain AND (f.onAlways OR f.forcedOn) THEN CheckNode[f.source, globalVars]; <> IF f.gate = node THEN BEGIN IF ((value=1) AND f.on1) OR ((value=0) AND f.on0) THEN f.forcedOn _ TRUE ELSE IF f.on1 OR f.on0 THEN f.forcedOff _ TRUE ELSE LOOP; IF f.flowFromDrain THEN CheckNode[f.source, globalVars]; IF f.flowFromSource THEN CheckNode[f.drain, globalVars]; END; ENDLOOP; END; CheckNode: PROC[node: Globals.Node, globalVars: Globals.GlobalVars] = <> BEGIN p: Globals.Pointer; f: Globals.Fet; other: Globals.Node; strength, strength2, value: INT; simCount _ simCount+1; <> strength _ 0; FOR p _ node.firstPointer, p.next UNTIL p = NIL DO f _ p.fet; IF NOT (f.onAlways OR f.forcedOn) THEN LOOP; IF f.source = node THEN BEGIN other _ f.drain; IF NOT f.flowFromDrain THEN LOOP; END ELSE IF f.drain = node THEN BEGIN other _ f.source; IF NOT f.flowFromSource THEN LOOP; END ELSE LOOP; IF other.always0 THEN BEGIN IF Model.TypeTable[f.type].strengthLo > strength THEN BEGIN value _ 0; strength _ Model.TypeTable[f.type].strengthLo; END; END ELSE BEGIN IF Model.TypeTable[f.type].strengthHi > strength THEN BEGIN value _ 1; strength _ Model.TypeTable[f.type].strengthHi; END; END; ENDLOOP; <> fSCount _ 0; IF strength > 0 THEN BEGIN strength2 _ FindStrength[node: node, value: 1-value, beatThis: strength-1, globalVars: globalVars]; IF strength > strength2 THEN SetNodeValue[node, value, FALSE, globalVars]; END ELSE <> IF (FindStrength[node: node, value: 1, beatThis: 0, globalVars: globalVars] = 0) AND (FindStrength[node: node, value: 0, beatThis: 0, globalVars: globalVars] = 0) THEN BEGIN FOR p _ node.firstPointer, p.next UNTIL p=NIL DO f _ p.fet; IF f.source = node THEN BEGIN IF NOT f.flowFromSource THEN LOOP; f.flowFromSource _ FALSE; CheckNode[f.drain, globalVars]; END ELSE IF f.drain = node THEN BEGIN IF NOT f.flowFromDrain THEN LOOP; f.flowFromDrain _ FALSE; CheckNode[f.source, globalVars]; END ; ENDLOOP; END; END; FindStrength: PROC[node: Globals.Node, value: INT, beatThis: INT, globalVars: Globals.GlobalVars] RETURNS [INT] = <> BEGIN p: Globals.Pointer; f: Globals.Fet; other: Globals.Node; strength, strength2: INT; simCount _ simCount+1; <> fSCount _ fSCount + 1; IF fSCount >= FSLimit THEN BEGIN IO.PutF[Globals.StdOut, "Aborting simulation at %s:\n", IO.rope[Printout.NodeRope[node, globalVars]]]; IO.PutRope[Globals.StdOut, " It's taking too long to find all the potential signal sources.\n"]; IO.PutRope[Globals.StdOut, " You probably need to add more flow control info. \n"]; IO.PutRope[Globals.StdOut, " A list of nodes in the area follows:\n"]; RETURN [-1]; END; <> node.inPath _ TRUE; <> FOR p _ node.firstPointer, p.next UNTIL p=NIL DO f _ p.fet; IF f.forcedOff THEN LOOP; IF value = 0 THEN strength _ Model.TypeTable[f.type].strengthLo ELSE strength _ Model.TypeTable[f.type].strengthHi; IF strength <= beatThis THEN LOOP; IF f.source = node THEN BEGIN other _ f.drain; IF NOT f.flowFromDrain THEN LOOP; END ELSE IF f.drain = node THEN BEGIN other _ f.source; IF NOT f.flowFromSource THEN LOOP; END ELSE LOOP; IF f.firstFlow # NIL THEN IF NOT Flow.Lock[fet: f, input: other] THEN LOOP; <> IF other.always1 OR other.always0 OR other.input THEN BEGIN IF value = 0 THEN BEGIN IF other.always1 THEN BEGIN IF f.firstFlow # NIL THEN Flow.Unlock[fet: f, input: other]; LOOP; END; END ELSE IF other.always0 THEN BEGIN IF f.firstFlow # NIL THEN Flow.Unlock[fet: f, input: other]; LOOP; END; END ELSE BEGIN IF other.inPath THEN BEGIN IF f.firstFlow # NIL THEN Flow.Unlock[fet: f, input: other]; LOOP; END; strength2 _ FindStrength[node: other, value: value, beatThis: beatThis, globalVars: globalVars]; IF strength2 < 0 THEN BEGIN IO.PutF[Globals.StdOut, " %s\n", IO.rope[Printout.NodeRope[node, globalVars]]]; node.inPath _ FALSE; IF f.firstFlow # NIL THEN Flow.Unlock[fet: f, input: other]; RETURN [-1]; END; IF strength2 < strength THEN strength _ strength2; IF f.firstFlow # NIL THEN Flow.Unlock[fet: f, input: other]; END; IF strength > beatThis THEN beatThis _ strength; ENDLOOP; node.inPath _ FALSE; RETURN [beatThis]; END; SetCmd: PUBLIC Globals.CmdProc = BEGIN ok: BOOLEAN; IF args = NIL THEN BEGIN IO.PutRope[Globals.StdOut, "\"Set\" needs a 0/1 value and node names.\n"]; RETURN; END; [ok, ivalue] _ Parse.Int[args]; IF (NOT ok) OR (ivalue < 0) OR (ivalue > 1) THEN BEGIN IO.PutRope[Globals.StdOut, "Value must be 0 or 1.\n"]; RETURN; END; args _ args.next; WHILE args # NIL DO <> SetNodeValue[Build.NodeFromRope[args.rope, globalVars], ivalue, TRUE, globalVars]; args _ args.next; ENDLOOP; END; <> <> <> <> <> Stats: PUBLIC PROC[] = BEGIN IO.PutF[Globals.StdOut, "Total nodes set to 0: %d.\n", IO.int[nodes0]]; IO.PutF[Globals.StdOut, "Total nodes set to 1: %d.\n", IO.int[nodes1]]; IO.PutF[Globals.StdOut, "Total nodes marked dynamic: %d.\n", IO.int[dynamic]]; IO.PutF[Globals.StdOut, "Total number of recursive simulation calls: %d.\n", IO.int[simCount]]; END; MarkDynamic: PUBLIC PROC[globalVars: Globals.GlobalVars] = { MarkDynamicProc: HashTable.EachPairAction = BEGIN p: Globals.Pointer; f: Globals.Fet; node: Globals.Node _ NARROW[value]; node.dynamic _ FALSE; IF node.input OR node.always0 OR node.always1 THEN RETURN; FOR p _ node.firstPointer, p.next UNTIL p = NIL DO f _ p.fet; IF f.source = node THEN BEGIN IF NOT f.flowFromDrain THEN LOOP; END ELSE IF f.drain = node THEN BEGIN IF NOT f.flowFromSource THEN LOOP; END ELSE LOOP; IF NOT f.forcedOff THEN RETURN; ENDLOOP; node.dynamic _ TRUE; dynamic _ dynamic + 1; IF SeeDynamic THEN IO.PutF[Globals.StdOut, "%s is dynamic.\n", IO.rope[Printout.NodeRope[node, globalVars]]]; END; <> [] _ HashTable.Pairs[globalVars.nodeTable, MarkDynamicProc] }; END.