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; END. pFILE: DprintImpl.mesa Last edited by Ousterhout, January 24, 1984 1:59 pm Christian LeCocq December 30, 1986 1:56:42 pm PST The following arrays and values are used to record delay paths. In the arrays, lower indices correspond to shorter delays. The following values are used to record statistical information. This local procedure simply makes a copy of a path (a chain of stages) and returns a pointer to the copy. Returns to the stage pool all of the stages linked to stage. See if this path's delay duplicates a delay already in the array. Find the slot in which to store the new path. Find the new smallest times in the arrays for use as a threshold. Scan off all of the arguments. Make sure the index is within the range of what we've recorded. Open the file, if neccessary, then call the procedure to print out stuff. This is a local utility procedure that prints information about a transistor in ASCII form. This is a local utility procedure that prints information about a node in ASCII form. This is a recursive local utility procedure that prints information about a path consisting of a chain of stages. The stages are printed in increasing order of delay time. UndumpFet: PROC[stream: IO.STREAM] RETURNS [fet: Globals.Fet] = This is a local utility procedure that reads in the description of a transistor from an ASCII file, as dumped by dumpFet. BEGIN fet _ NEW[Globals.FetRec _ [NIL, NIL, NIL, 0.0, 0.0, 0.0, 0.0, 0, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NIL]]; [] _ IO.GetTokenRope[stream, Parse.WhiteSpace]; fet.type _ IO.GetInt[stream]; [] _ IO.GetTokenRope[stream, Parse.WhiteSpace]; fet.area _ IO.GetReal[stream]; fet.aspect _ IO.GetReal[stream]; RETURN [fet]; END; UndumpNode: PROC[stream: IO.STREAM] RETURNS [node: Globals.Node] = This is a local routine that reads in the description of a node, as dumped by dumpNode, and returns a new node. BEGIN node _ NEW[Globals.NodeRec _ [NIL, 0, 0, 0, 0, NIL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE]]; [] _ IO.GetTokenRope[stream, Parse.WhiteSpace]; [] _ IO.GetTokenRope[stream, Parse.WhiteSpace]; [token: node.name] _ IO.GetTokenRope[stream, Parse.WhiteSpace]; node.cap _ IO.GetReal[stream]; node.res _ IO.GetReal[stream]; node.hiTime _ IO.GetReal[stream]; node.loTime _ IO.GetReal[stream]; RETURN [node]; END; UndumpStage: PROC[stream: IO.STREAM] RETURNS [stage: Globals.Stage] = Local procedure to read in ASCII description of stage. BEGIN i: INT; stage _ NEW[Globals.StageRec]; stage.piece1Size _ IO.GetInt[stream]; stage.piece2Size _ IO.GetInt[stream]; i _ IO.GetInt[stream]; IF i # 0 THEN stage.rise _ TRUE ELSE stage.rise _ FALSE; stage.time _ IO.GetReal[stream]; stage.edgeSpeed _ IO.GetReal[stream]; stage.prev _ NIL; FOR i IN [0..stage.piece1Size) DO stage.piece1Fet[i] _ UndumpFet[stream]; stage.piece1Node[i] _ UndumpNode[stream]; ENDLOOP; FOR i IN [0..stage.piece2Size) DO IF i = stage.piece2Size-1 THEN stage.piece2Fet[i] _ NIL ELSE stage.piece2Fet[i] _ UndumpFet[stream]; stage.piece2Node[i] _ UndumpNode[stream]; ENDLOOP; RETURN [stage]; END; UndumpCmd: PUBLIC Globals.CmdProc = BEGIN rope: Rope.ROPE; index: INT; prev, next: Globals.Stage; stream: IO.STREAM; msg: Rope.ROPE _ NIL; list: listType; {ENABLE ANY => CONTINUE; IF args = NIL THEN BEGIN IO.PutRope[Globals.StdOut, "No file name given.\n"]; RETURN; END; stream _ FS.StreamOpen[args.rope ! 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 reading: %s.\n", IO.rope[args.rope], IO.rope[msg]]; RETURN; END; FOR i: INT IN [0..MaxPaths) DO Paths[any][i] _ NIL; Paths[memory][i] _ NIL; Paths[watched][i] _ NIL; ENDLOOP; [token: rope] _ IO.GetTokenRope[stream, Parse.WhiteSpace]; WHILE TRUE DO index _ IO.GetInt[stream]; IF Rope.Equal[rope, "Memory"] THEN list _ memory ELSE IF Rope.Equal[rope, "Watch"] THEN list _ watched ELSE list _ any; prev _ NIL; WHILE TRUE DO [token: rope] _ IO.GetTokenRope[stream, Parse.WhiteSpace]; IF NOT Rope.Equal[rope, "stage"] THEN EXIT; next _ UndumpStage[stream]; next.prev _ prev; Paths[list][index] _ next; prev _ next; ENDLOOP; ENDLOOP; }; IO.Close[stream]; END; Κ)˜Icodešœ™šœ3™3K™1—K˜šΟk ˜ K˜K˜Kšœ˜K˜Kšœ˜K˜K˜K˜ K˜K˜ —K˜KšΟn œœ˜š˜Kšœ˜Kšœ˜K˜Kšœ˜K˜K˜K˜ K˜K˜ —Kšœ ˜Kš˜Kšœ˜ K˜Kšœz™zK˜Kš žœœœ œœ ˜1Kš ž œœœ œœ˜;Kš žœœ œœœ˜=K˜Kšœ@™@K˜Kšœ œ œœ ˜,Kšœ œ˜K˜Kšžœœœœ˜(K˜K˜šžœœœ˜BKšœi™iK˜Kš˜K˜K˜Kšœœ˜ šœœ˜K˜K˜ Kšœœœ ˜Kšœ˜K˜ K˜Kšœ˜—Kšœ˜Kšœ˜—K˜šž œœ˜(Kšœ<™Kš˜K˜K˜BKš˜—šœœ8˜CKš˜K˜K˜BKš˜—Kšœ ˜K˜šœ œœ˜Kš˜Kšœ8œ˜NKšœ˜Kšœ˜—Kš˜—Kšœœœ˜?Kšœœ6œ˜QK˜Kšœ˜K˜—Kšœ?™?K˜šœ˜Kš˜Kšœ<œ˜WKšœ-œ˜GK˜ Kš˜—Kšœ ˜$K˜šœI™IK˜—šœ œ˜Kš˜šœ œ˜(Kšœœ œ˜"Kšœœ˜+—šœœ˜Kš˜Kšœ0œœ ˜SKšœ˜Kšœ˜—Kš˜—Kšœ˜K˜3Kšœ œœœ˜(Kšœ˜K˜—K˜šžœœœ˜Kš˜šœœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœ˜—K˜K˜K˜Kšœ˜—K˜K˜šžœœœ˜Kš˜KšœAœ˜\KšœHœ˜fKšœIœ˜hKšœGœ˜ZKšœ˜—K˜K˜šž œœ˜&Kš˜šœœœ˜"Kšœ%˜%Kšœ˜—šœœœ˜%Kšœ(˜(Kšœ˜—šœœœ˜&Kšœ)˜)Kšœ˜—Kšœ˜—K˜šž œœ8˜GKš˜Kš œ œœœœœ˜3K˜"K˜Kšœ˜—K˜K˜šžœœ œœ˜4KšœPœ™[K˜Kš˜Kšœ0œœœ˜lKšœ˜—K˜šžœœ œœ7˜WKšœJœ™UK˜Kš˜Kš œ1œ-œœœœ˜΄Kšœ˜—K˜šž œœ œœ9˜ZKšœ«™«K˜Kš˜Kšœœœ+˜CKšœ"œœ˜XKšœ œœ˜+Kšœœ˜Kšœœœ˜Jšœœœ˜%K˜$Kšœ2˜2Kšœ˜—šœœœ˜%Kšœ˜Kšœ$˜$Kšœ2˜2Kšœ˜—Kšœ˜—K˜K˜šžœœ˜!Kš˜Kšœœœ˜Kšœ œœ˜K˜Kšœœœ˜*šœ œ˜.Kšœœ œ˜"Kšœœ˜*—šœœ˜Kš˜Kšœ=œœ ˜aKšœ˜Kšœ˜—K˜šœœœ˜#Kšœœœœ˜!Kšœœ ˜'Kšœ-˜-Kšœ˜—šœœœ˜&Kšœœœœ˜$Kšœœ ˜*K˜0Kšœ˜—šœœœ˜'Kšœœœœ˜%Kšœœ ˜)K˜1Kšœ˜—Kšœ˜Kšœ˜—K˜K˜š ž œœ œœœ™?KšœXœ™yK™Kš™Kšœœœœœœœœœœœœœœœ™‡Kšœœ(™/Kšœ œ™Kšœœ(™/Kšœ œ™Kšœ œ™!Kšœ™ Kšœ™—K™š ž œœ œœœ™BKšœo™oK™Kš™Kšœœœœœœœœœœœœœœ™{Kšœœ(™/Kšœœ(™/Kšœœ(™?Kšœ œ™Kšœ œ™Kšœœ™!Kšœœ™!Kšœ™Kšœ™—K™š ž œœ œœœ™EKšœœ™6K™Kš™Kšœœ™K™Kšœœ™Kšœœ™%Kšœœ™%Kšœœ™Kšœœ™Kšœœ™Kšœ œ™ Kšœœ™%Kšœ œ™šœœ™!K™'K™)Kšœ™—šœœ™!Kšœœ™7Kšœ(™,K™)Kšœ™—Kšœ ™Kšœ™—K™K™šž œœ™#Kš™Kšœ œ™Kšœœ™ Kšœ™Kšœœœ™Kšœ œœ™K™K™Kšœœœœ™K™šœœ™Kš™Kšœ2™4Kšœ™Kšœ™K™—šœ œ™ Kšœœ œ™"Kšœœ™*—šœœ™Kš™šœ<™>Kšœœ ™"—Kšœ™Kšœ™—K™šœœœ™Kšœœ™Kšœœ™Kšœœ™Kšœ™—K™Kšœœ(™:K™šœœ™ Kšœœ™Kšœœ™0Kšœœœ™5Kšœ ™Kšœœ™ šœœ™ Kšœœ(™:Kšœœœœ™+K™K™K™K™ Kšœ™—Kšœ™—K™Kšœ™Kšœ™K™—Kšœ˜—…—hA