<> <> <> DIRECTORY Build, DPrint, FS, Globals, IO, Model, Parse, Printout, Rope, StagePool; DPrintImpl: CEDAR PROGRAM IMPORTS Build, FS, Globals, IO, Model, Parse, Printout, Rope, StagePool EXPORTS DPrint = BEGIN OPEN DPrint; <> NumPaths: PUBLIC ARRAY listType OF INT _ [5,5,5]; Threshold: PUBLIC ARRAY listType OF REAL _ [0.0, 0.0, 0.0]; Paths: ARRAY listType OF ARRAY[0..MaxPaths) OF Globals.Stage; <> numRecords: ARRAY listType OF INT _ [0,0,0]; numDups: INT _ 0; PrintEdgeSpeeds: PUBLIC BOOLEAN _ FALSE; CopyPath: PROC[src: Globals.Stage] RETURNS [copy: Globals.Stage] = <> BEGIN prev, cur: Globals.Stage; copy _ NIL; WHILE src # NIL DO prev _ StagePool.New[]; prev^ _ src^; IF copy = NIL THEN copy _ prev ELSE cur.prev _ prev; cur _ prev; src _ src.prev; ENDLOOP; RETURN [copy]; END; DeletePath: PROC[stage: Globals.Stage] = <> BEGIN next: Globals.Stage; WHILE stage # NIL DO next _ stage.prev; StagePool.Free[stage]; stage _ next; ENDLOOP; END; Record: PUBLIC PROC[stage: Globals.Stage, list: listType] = BEGIN i, max: INT; cur: Globals.Stage; bot, top: REAL; done: BOOLEAN _ FALSE; IF stage.time < Threshold[list] THEN RETURN; numRecords[list] _ numRecords[list] + 1; max _ NumPaths[list]; <> bot _ stage.time * .999; top _ stage.time * 1.001; FOR i IN [0..NumPaths[list]) DO cur _ Paths[list][i]; IF cur = NIL THEN LOOP; IF cur.time > top THEN EXIT; IF (cur.time >= bot) AND (cur.rise = stage.rise) THEN BEGIN numDups _ numDups + 1; RETURN; END; ENDLOOP; <> DeletePath[Paths[list][0]]; FOR i IN [1..max) DO cur _ Paths[list][i]; IF cur = NIL THEN LOOP; IF stage.time < cur.time THEN BEGIN Paths[list][i-1] _ CopyPath[stage]; done _ TRUE; EXIT; END; Paths[list][i-1] _ cur; ENDLOOP; IF NOT done THEN Paths[list][max-1] _ CopyPath[stage]; <> IF Paths[list][0] = NIL THEN Threshold[list] _ 0 ELSE Threshold[list] _ 1.001 * Paths[list][0].time; END; PrintStage: PUBLIC PROC[stream: IO.STREAM, stage: Globals.Stage, globalVars: Globals.GlobalVars] = BEGIN first: BOOLEAN _ TRUE; i: INT; direction, format: Rope.ROPE; IF stage = NIL THEN BEGIN IO.PutRope[stream, "No such critical path.\n"]; RETURN; END; WHILE stage # NIL DO IF stage.rise THEN direction _ "high" ELSE direction _ "low"; IF first THEN BEGIN format _ "Node %s is driven %s at %.2fns"; first _ FALSE; END ELSE format _ " after\n %s is driven %s at %.2fns"; IO.PutF[stream, format, IO.rope[Build.RopeFromNode[stage.piece2Node[stage.piece2Size-1], globalVars]], IO.rope[direction], IO.real[stage.time]]; IF PrintEdgeSpeeds THEN IO.PutF[stream, " with edge speed %.3f ns/volt", IO.real[stage.edgeSpeed]]; FOR i DECREASING IN [0..stage.piece2Size-2] DO IO.PutF[stream, "\n ...through fet at (%.1f, %.1f) to %s", IO.real[stage.piece2Fet[i].x/Printout.Units], IO.real[stage.piece2Fet[i].y/Printout.Units], IO.rope[Build.RopeFromNode[stage.piece2Node[i], globalVars]]]; ENDLOOP; FOR i IN [0..stage.piece1Size) DO IO.PutF[stream, "\n ...through fet at (%.1f, %.1f) to %s", IO.real[stage.piece1Fet[i].x/Printout.Units], IO.real[stage.piece1Fet[i].y/Printout.Units], IO.rope[Build.RopeFromNode[stage.piece1Node[i], globalVars]]]; ENDLOOP; stage _ stage.prev; ENDLOOP; IO.PutRope[stream, "\n"]; END; CriticalCmd: PUBLIC Globals.CmdProc = BEGIN list: listType _ any; ok: BOOLEAN; index: INT _ 1; fileName: Rope.ROPE _ NIL; stream: IO.STREAM; msg: Rope.ROPE _ NIL; <> WHILE args # NIL DO IF (Rope.Fetch[args.rope, 0] >= '0) AND (Rope.Fetch[args.rope, 0] <= '9) THEN BEGIN IF Rope.Fetch[args.rope, Rope.Length[args.rope] - 1] = 'm THEN BEGIN list _ memory; args.rope _ Rope.Substr[args.rope, 0, Rope.Length[args.rope] - 1]; END ELSE IF Rope.Fetch[args.rope, Rope.Length[args.rope] - 1] = 'w THEN BEGIN list _ watched; args.rope _ Rope.Substr[args.rope, 0, Rope.Length[args.rope] - 1]; END ELSE list _ any; [ok, index] _ Parse.Int[args]; IF index < 1 OR NOT ok THEN BEGIN IO.PutF[Globals.StdOut, "Bad critical path number: %s\n", IO.rope[args.rope]]; RETURN; END; END ELSE IF Rope.Fetch[args.rope, 0] # '- THEN fileName _ args.rope ELSE IO.PutF[Globals.StdOut, "Unknown %s switch ignored.\n", IO.rope[args.rope]]; args _ args.next; ENDLOOP; <> IF index > NumPaths[list] THEN BEGIN IO.PutF[Globals.StdOut, "Sorry, but there are only %d paths.", IO.int[NumPaths[list]]]; IO.PutF[Globals.StdOut, " Using index %d.\n", IO.int[NumPaths[list]]]; index _ 0; END ELSE index _ NumPaths[list] - index; <> IF fileName # NIL THEN BEGIN stream _ FS.StreamOpen[fileName, $create ! FS.Error => IF error.group # bug THEN {msg _ error.explanation; CONTINUE}]; IF msg # NIL THEN BEGIN IO.PutF[Globals.StdOut, "Couldn't open %s: %s\n", IO.rope[fileName], IO.rope[msg]]; RETURN; END; END ELSE stream _ Globals.StdOut; PrintStage[stream, Paths[list][index], globalVars]; IF fileName # NIL THEN IO.Close[stream]; END; Clear: PUBLIC PROC[] = BEGIN FOR i:INT IN [0..MaxPaths) DO Paths[memory][i] _ NIL; Paths[any][i] _ NIL; Paths[watched][i] _ NIL; ENDLOOP; Threshold[memory] _ 0.0; Threshold[any] _ 0.0; Threshold[watched] _ 0.0; END; Stats: PUBLIC PROC[] = BEGIN IO.PutF[Globals.StdOut, "Number of calls to record delays: %d.\n", IO.int[numRecords[any]]]; IO.PutF[Globals.StdOut, "Number of calls to record memory delays: %d.\n", IO.int[numRecords[memory]]]; IO.PutF[Globals.StdOut, "Number of calls to record watched delays: %d.\n", IO.int[numRecords[watched]]]; IO.PutF[Globals.StdOut, "Number of dups eliminated in recording: %d.\n", IO.int[numDups]]; END; RecomputeCmd: PUBLIC Globals.CmdProc = BEGIN FOR i:INT IN [0..NumPaths[any]) DO Recompute[Paths[any][i], globalVars]; ENDLOOP; FOR i:INT IN [0..NumPaths[memory]) DO Recompute[Paths[memory][i], globalVars]; ENDLOOP; FOR i:INT IN [0..NumPaths[watched]) DO Recompute[Paths[watched][i], globalVars]; ENDLOOP; END; Recompute: PROC[stage: Globals.Stage, globalVars: Globals.GlobalVars] = BEGIN IF (stage = NIL) OR (stage.prev = NIL) THEN RETURN; Recompute[stage.prev, globalVars]; Model.Delay[stage, globalVars]; END; DumpFet: PROC[stream: IO.STREAM, fet: Globals.Fet] = <> BEGIN IO.PutF[stream, " fet %d 0 %f %f %f %f\n", IO.int[fet.type], IO.real[fet.area], IO.real[fet.aspect]]; END; DumpNode: PROC[stream: IO.STREAM, node: Globals.Node, globalVars: Globals.GlobalVars] = <> BEGIN IO.PutF[stream, " node 0 %s %f %f %f %f\n", IO.rope[Build.RopeFromNode[node, globalVars]], IO.real[node.cap], IO.real[node.res], IO.real[node.hiTime], IO.real[node.loTime]]; END; DumpStage: PROC[stream: IO.STREAM, stage: Globals.Stage, globalVars: Globals.GlobalVars] = <> BEGIN IF stage.prev # NIL THEN DumpStage[stream, stage.prev, globalVars]; IO.PutF[stream, " stage %d %d ", IO.int[stage.piece1Size], IO.int[stage.piece2Size]]; IF stage.rise THEN IO.PutRope[stream, "1 "] ELSE IO.PutRope[stream, "0 "]; IO.PutF[stream, "%f %f\n", IO.real[stage.time], IO.real[stage.edgeSpeed]]; FOR i:INT IN [0..stage.piece1Size) DO DumpFet[stream, stage.piece1Fet[i]]; DumpNode[stream, stage.piece1Node[i], globalVars]; ENDLOOP; FOR i:INT IN [0..stage.piece2Size) DO IF i # stage.piece2Size-1 THEN DumpFet[stream, stage.piece2Fet[i]]; DumpNode[stream, stage.piece2Node[i], globalVars]; ENDLOOP; END; DumpCmd: PUBLIC Globals.CmdProc = BEGIN stream: IO.STREAM; msg: Rope.ROPE _ NIL; IF args = NIL THEN stream _ Globals.StdOut ELSE stream _ FS.StreamOpen[args.rope, $create ! FS.Error => IF error.group # bug THEN {msg _ error.explanation; CONTINUE}]; IF msg # NIL THEN BEGIN IO.PutF[Globals.StdOut, "Couldn't open %s for writing: %s.\n", IO.rope[args.rope], IO.rope[msg]]; RETURN; END; FOR i: INT IN [0..NumPaths[any]) DO IF Paths[any][i] = NIL THEN LOOP; IO.PutF[stream, "Any %d\n", IO.int[i]]; DumpStage[stream, Paths[any][i], globalVars]; ENDLOOP; FOR i: INT IN [0..NumPaths[memory]) DO IF Paths[memory][i] = NIL THEN LOOP; IO.PutF[stream, "Memory %d\n", IO.int[i]]; DumpStage[stream, Paths[memory][i], globalVars]; ENDLOOP; FOR i: INT IN [0..NumPaths[watched]) DO IF Paths[watched][i] = NIL THEN LOOP; IO.PutF[stream, "Watch %d\n", IO.int[i]]; DumpStage[stream, Paths[watched][i], globalVars]; ENDLOOP; IO.Close[stream]; END; <> <> <<>> <> <> <<[] _ IO.GetTokenRope[stream, Parse.WhiteSpace];>> <> <<[] _ IO.GetTokenRope[stream, Parse.WhiteSpace];>> <> <> <> <> <<>> <> <> <<>> <> <> <<[] _ IO.GetTokenRope[stream, Parse.WhiteSpace];>> <<[] _ IO.GetTokenRope[stream, Parse.WhiteSpace];>> <<[token: node.name] _ IO.GetTokenRope[stream, Parse.WhiteSpace];>> <> <> <> <> <> <> <<>> <> <> <<>> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <<>> <> <> <> <> <> <> <> <> <<>> <<{ENABLE ANY => CONTINUE;>> <<>> <> <> <> <> <> <<>> <> < IF error.group # bug>> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <<>> <<[token: rope] _ IO.GetTokenRope[stream, Parse.WhiteSpace];>> <<>> <> <> <> <> <> <> <> <<[token: rope] _ IO.GetTokenRope[stream, Parse.WhiteSpace];>> <> <> <> <> <> <> <> <<};>> <> <> <<>> END.