FILE: PrintoutImpl.mesa
Last edited by Ousterhout, August 30, 1983 1:40 pm
Christian LeCocq December 19, 1986 2:02:15 pm PST
DIRECTORY
Build,
Globals,
IO,
Model,
Parse,
Printout,
Rope;
PrintoutImpl: CEDAR PROGRAM
IMPORTS
Build,
Globals,
IO,
Model,
Rope,
Parse
EXPORTS Printout =
BEGIN
OPEN Printout;
Units: PUBLIC REAL ← 2.0;
The following variables are used to communicate between command-level routines and enumeration action routines.
dupTable: Hash.Table;
threshold: REAL;
nDups: INT;
FetRope: PUBLIC PROC[fet: Globals.Fet, globalVars: Globals.GlobalVars] RETURNS [rope: Rope.ROPE] =
BEGIN
rope ← IO.PutFR["g=%s, s=%s, d=%s",
IO.rope[Build.RopeFromNode[fet.gate, globalVars]],
IO.rope[Build.RopeFromNode[fet.source, globalVars]],
IO.rope[Build.RopeFromNode[fet.drain, globalVars]]];
RETURN [rope];
END;
NodeRope: PUBLIC PROC[node: Globals.Node, globalVars: Globals.GlobalVars] RETURNS [rope: Rope.ROPE] =
BEGIN
x,y: REAL;
p: Globals.Pointer;
terminal: Rope.ROPE;
f: Globals.Fet;
The only tricky thing about this routine is that nodes don't contain (x,y) locations. I've found that the best way to identify a node is with a transistor gate. So, this procedure checks the first few transistors attached to the node to see if there's a gate available for use as a reference point.
p ← node.firstPointer;
IF p = NIL THEN
BEGIN
RETURN [Build.RopeFromNode[node, globalVars]];
END
ELSE
BEGIN
FOR i:INT IN [0..10) DO
f ← p.fet;
IF node = f.gate THEN EXIT;
IF p.next = NIL THEN EXIT;
p ← p.next;
ENDLOOP;
x ← f.x/Units;
y ← f.y/Units;
IF node = f.gate THEN terminal ← "gate"
ELSE IF node = f.drain THEN terminal ← "drain"
ELSE IF node = f.source THEN terminal ← "source"
ELSE
BEGIN
IO.PutF[Globals.StdOut, "Crystal bug: node %s doesn't connect right!\n", IO.rope[Build.RopeFromNode[node, globalVars]]];
RETURN ["??"];
END;
rope ← IO.PutFR["%s (see %s at %f,%f)",
IO.rope[Build.RopeFromNode[node, globalVars]],
IO.rope[terminal],
IO.real[x],
IO.real[y]];
RETURN [rope];
END;
END;
PrintCap: PUBLIC Globals.CmdProc =
BEGIN
ParseOK: BOOLEAN;
dupTable ← Hash.NewTable[];
node: Globals.Node;
nDups ← 0;
threshold ← 0.0;
Read off switches, if there are any.
WHILE args # NIL DO
IF Rope.Fetch[args.rope, 0] # '- THEN EXIT;
IF Rope.Length[args.rope] # 2 THEN
BEGIN
IO.PutF[Globals.StdOut, "Bad switch: %s\n", IO.rope[args.rope]];
args ← args.next;
LOOP;
END;
SELECT Rope.Fetch[args.rope, 1] FROM
't =>
BEGIN
[ParseOK, threshold] ← Parse.Real[args.next];
IF ParseOK THEN args ← args.next
ELSE IO.PutF[Globals.StdOut, "No threshold value given, using 0.\n"];
END;
ENDCASE => IO.PutF[Globals.StdOut, "Bad switch: %s\n", IO.rope[args.rope]];
args ← args.next;
ENDLOOP;
Read off nodes. For each node, look it up in the node table and print out its capacitance if it's greater than threshold.
nDups ← 0;
IF args = NIL THEN
Hash.Enumerate[table: globalVars.nodeTable, pattern: "*", proc: capProc, errorStream: Globals.StdOut]
ELSE
WHILE args # NIL DO
Hash.Enumerate[table: globalVars.nodeTable, pattern: args.rope, proc: capProc, errorStream: Globals.StdOut];
node ← Build.NodeFromRope[args.rope, globalVars];
IO.PutF[Globals.StdOut, "%.3f pf capacitance at %s.\n", IO.real[node.cap], IO.rope[NodeRope[node, globalVars]]];
args ← args.next;
ENDLOOP;
IF nDups > 0 THEN
IO.PutF[Globals.StdOut, "%d duplicates not printed.\n", IO.int[nDups]];
END;
CapProc: PROC[node: Globals.Node] =
BEGIN
valRope: Rope.ROPE;
IF node = NIL THEN RETURN;
IF node.cap >= threshold THEN BEGIN
valRope ← IO.PutFR["%.3f", IO.real[node.cap]];
entry ← Hash.Find[dupTable, valRope];
IF (entry.clientData # $Duplicate) OR Globals.DupsOK THEN BEGIN
entry.clientData ← $Duplicate;
IO.PutF[Globals.StdOut, "%s pf capacitance at %s.\n",
IO.rope[valRope],
IO.rope[NodeRope[node]]];
END
ELSE nDups ← nDups + 1;
END;
END;
PrintRes: PUBLIC Globals.CmdProc =
BEGIN
ParseOK: BOOLEAN;
dupTable ← Hash.NewTable[];
node: Globals.Node;
nDups ← 0;
threshold ← 0.0;
Read off switches, if there are any.
WHILE args # NIL DO
IF Rope.Fetch[args.rope, 0] # '- THEN EXIT;
IF Rope.Length[args.rope] # 2 THEN
BEGIN
IO.PutF[Globals.StdOut, "Bad switch: %s\n", IO.rope[args.rope]];
args ← args.next;
LOOP;
END;
SELECT Rope.Fetch[args.rope, 1] FROM
't =>
BEGIN
[ParseOK, threshold] ← Parse.Real[args.next];
IF ParseOK THEN args ← args.next
ELSE IO.PutF[Globals.StdOut, "No threshold value given, using 0.\n"];
END;
ENDCASE => IO.PutF[Globals.StdOut, "Bad switch: %s\n", IO.rope[args.rope]];
args ← args.next;
ENDLOOP;
Read off nodes. For each node, look it up in the node table and print
out its resistance if it's greater than threshold.
nDups ← 0;
IF args = NIL THEN
Hash.Enumerate[table: globalVars.nodeTable, pattern: "*", proc: resProc, errorStream: Globals.StdOut]
ELSE
WHILE args # NIL DO
node ← Build.NodeFromRope[args.rope, globalVars];
IO.PutF[Globals.StdOut, "%.3f ohms resistance at %s.\n", IO.real[node.res], IO.rope[NodeRope[node, globalVars]]];
Hash.Enumerate[table: globalVars.nodeTable, pattern: args.rope, proc: resProc, errorStream: Globals.StdOut];
args ← args.next;
ENDLOOP;
IF nDups > 0 THEN
IO.PutF[Globals.StdOut, "%d duplicates not printed.\n", IO.int[nDups]];
END;
ResProc: PROC[node: Globals.Node] =
BEGIN
valRope: Rope.ROPE;
IF node = NIL THEN RETURN;
IF node.res >= threshold THEN
BEGIN
valRope ← IO.PutFR["%.1f", IO.real[node.res]];
entry ← Hash.Find[dupTable, valRope];
IF (entry.clientData # $Duplicate) OR Globals.DupsOK THEN
BEGIN
entry.clientData ← $Duplicate;
IO.PutF[Globals.StdOut, "%s ohms resistance at %s.\n", IO.rope[valRope], IO.rope[NodeRope[node]]];
END
ELSE nDups ← nDups + 1;
END;
END;
PrintFets: PUBLIC Globals.CmdProc =
BEGIN
IF args = NIL THEN Hash.Enumerate[table: globalVars.nodeTable, pattern: "*", proc: fetProc,
errorStream: Globals.StdOut]
ELSE
WHILE args # NIL DO
Hash.Enumerate[table: globalVars.nodeTable, pattern: args.rope, proc: fetProc, errorStream: Globals.StdOut];
FetProc[Build.NodeFromRope[args.rope, globalVars], globalVars];
args ← args.next;
ENDLOOP;
END;
FetProc: PROC[node: Globals.Node, globalVars: Globals.GlobalVars] =
BEGIN
pointer: Globals.Pointer;
fet: Globals.Fet;
fp: Globals.FlowPtr;
FOR pointer ← node.firstPointer, pointer.next UNTIL pointer = NIL DO
fet ← pointer.fet;
IF fet.gate = node THEN
BEGIN
IO.PutF[Globals.StdOut, "%s, type=%s, aspect=%.3f, area=%.3f\n",
IO.rope[FetRope[fet, globalVars]],
IO.rope[Model.TypeTable[fet.type].name],
IO.real[fet.aspect],
IO.real[fet.area/(Units*Units)]];
IO.PutRope[Globals.StdOut, " Flags:"];
IF fet.flowFromSource THEN IO.PutRope[Globals.StdOut, " fromSource"];
IF fet.flowFromDrain THEN IO.PutRope[Globals.StdOut, " fromDrain"];
IF fet.forcedOn THEN IO.PutRope[Globals.StdOut, " forcedOn"];
IF fet.forcedOff THEN IO.PutRope[Globals.StdOut, " forcedOff"];
IF fet.on0 THEN IO.PutRope[Globals.StdOut, " on0"];
IF fet.on1 THEN IO.PutRope[Globals.StdOut, " on1"];
IF fet.onAlways THEN IO.PutRope[Globals.StdOut, " onAlways"];
IF fet.noSourceInfo THEN IO.PutRope[Globals.StdOut, " noSourceInfo"];
IF fet.noDrainInfo THEN IO.PutRope[Globals.StdOut, " noDrainInfo"];
IF fet.firstFlow # NIL THEN IO.PutRope[Globals.StdOut, " Flow:"];
FOR fp ← fet.firstFlow, fp.next UNTIL fp = NIL DO
IF fp.source THEN IO.PutF[Globals.StdOut, " s=%s", IO.rope[fp.flow.name]];
IF fp.drain THEN IO.PutF[Globals.StdOut, " d=%s", IO.rope[fp.flow.name]];
ENDLOOP;
IO.PutRope[Globals.StdOut, "\n"];
END;
ENDLOOP;
END;
PrintNodes: PUBLIC Globals.CmdProc =
BEGIN
IF args = NIL THEN Hash.Enumerate[table: globalVars.nodeTable, pattern: "*", proc: nodeProc, errorStream: Globals.StdOut]
ELSE
WHILE args # NIL DO
Hash.Enumerate[table: globalVars.nodeTable, pattern: args.rope, proc: nodeProc, errorStream: Globals.StdOut];
NodeProc[Build.NodeFromRope[args.rope, globalVars], globalVars];
args ← args.next;
ENDLOOP;
END;
NodeProc: PROC[node: Globals.Node, globalVars: Globals.GlobalVars] =
BEGIN
IO.PutF[Globals.StdOut, "%s:", IO.rope[Build.RopeFromNode[node, globalVars]]];
IF node.always0 THEN IO.PutRope[Globals.StdOut, " always 0"];
IF node.always1 THEN IO.PutRope[Globals.StdOut, " always 1"];
IF node.input THEN IO.PutRope[Globals.StdOut, " input"];
IF node.output THEN IO.PutRope[Globals.StdOut, " output"];
IF node.precharged THEN IO.PutRope[Globals.StdOut, " precharged"];
IF node.bus THEN IO.PutRope[Globals.StdOut, " bus"];
IF node.dynamic THEN IO.PutRope[Globals.StdOut, " dynamic"];
IF node.inPath THEN IO.PutRope[Globals.StdOut, " inPath"];
IF node.ratioError THEN IO.PutRope[Globals.StdOut, " ratioError"];
IF node.watched THEN IO.PutRope[Globals.StdOut, " watched"];
IO.PutF[Globals.StdOut, " capacitance = %.5f, resistance = %.1f,", IO.real[node.cap], IO.real[node.res]];
IO.PutF[Globals.StdOut, " rise time = %.1f, fall time = %.1f\n", IO.real[node.hiTime], IO.real[node.loTime]];
END;
END.