DIRECTORY BasicTime USING [Now], CD USING [Layer, Number], CedarProcess USING [Fork], Commander USING [CommandProc], ComputeClientExtras USING [StartServiceExtra], ComputeServerClient USING [RemoteSuccess, StartService], ComputeServerServer USING [Register], DABasics USING [Number, Rect], FS USING [StreamOpen, Delete, Rename], IO USING [Close, STREAM, PutFR, card, char], RefIO USING [WriteRef, ReadRef], Rope USING [ROPE, Cat, Index, Substr, Equal, Fetch], Route USING [DesignRules, Optimization, ResultData, ResultDataRec], RouteChannel USING [ChannelData, Method, MethodRec, TrackSequence, DirectionSequence, WriteResult], RouteChannelTopol USING [RouteOneChan], RoutePrivate USING [RoutingAreaParms], RouteUtil USING [CompareResult], SymTab USING [Create, Delete, Update, Fetch, Store, Ref, UpdateAction]; RouteChannelRemoteImpl: CEDAR MONITOR IMPORTS BasicTime, CedarProcess, ComputeClientExtras, ComputeServerClient, ComputeServerServer, FS, IO, RefIO, Rope, RouteChannel, RouteChannelTopol, RouteUtil, SymTab --, Convert, Rope, TerminalIO EXPORTS RouteChannel = { ResultSummary: TYPE ~ REF ResultSummaryRec; ResultSummaryRec: TYPE ~ RECORD[ nOut: NAT _ 0, servers: LIST OF Rope.ROPE _ NIL, bestResult: Route.ResultData, bestMethod: RouteChannel.Method ]; oneFinished: CONDITION; nForked: NAT _ 0; maxForkedPossible: NAT _ 8; idTable: SymTab.Ref _ SymTab.Create[]; csCommandName: Rope.ROPE _ "ChannelRoute"; debug: BOOLEAN _ FALSE; okToFlush: BOOLEAN _ FALSE; okToRemoteSubmit: BOOLEAN _ FALSE; cachedChanData: RouteChannel.ChannelData; cachedParms: RoutePrivate.RoutingAreaParms; cachedRules: Route.DesignRules; cachedId: Rope.ROPE _ "invalid"; TopoWiring: PUBLIC PROC [chanData: RouteChannel.ChannelData, parms: RoutePrivate.RoutingAreaParms, rules: Route.DesignRules, opt: Route.Optimization] RETURNS [bestResult: Route.ResultData] = { bestResult _ IF okToRemoteSubmit THEN RemoteTopoWiring[chanData, parms, rules, opt] ELSE LocalTopoWiring[chanData, parms, rules, opt]; }; LocalTopoWiring: PROC [chanData: RouteChannel.ChannelData, parms: RoutePrivate.RoutingAreaParms, rules: Route.DesignRules, opt: Route.Optimization] RETURNS [bestResult: Route.ResultData] = { lastMethod: RouteChannel.Method _ NEW[RouteChannel.MethodRec]; bestMethod: RouteChannel.Method; result: Route.ResultData; maxL: NAT = LAST[NAT]; bestResult _ NEW[Route.ResultDataRec _ [maxL, maxL, maxL, maxL, maxL, maxL, maxL, DABasics.Rect[maxL, maxL, maxL, maxL]]]; FOR method: RouteChannel.Method _ GetNextMethod[lastMethod], GetNextMethod[lastMethod] WHILE method # NIL DO result _ RouteChannelTopol.RouteOneChan[chanData, parms, rules, method]; lastMethod _ method; IF RouteUtil.CompareResult[result, bestResult] = less THEN {bestResult _ result; bestMethod _ method}; IF opt = noIncompletes AND bestResult.numIncompletes = 0 THEN EXIT; ENDLOOP; IF bestMethod # lastMethod THEN bestResult _ RouteChannelTopol.RouteOneChan[chanData, parms, rules, bestMethod]; RouteChannel.WriteResult[bestResult, parms, rules, bestMethod]; }; RemoteTopoWiring: PROC [chanData: RouteChannel.ChannelData, parms: RoutePrivate.RoutingAreaParms, rules: Route.DesignRules, opt: Route.Optimization] RETURNS [bestResult: Route.ResultData] = { bestMethod: RouteChannel.Method; id: Rope.ROPE _ GetUniqueId[]; WriteRefOnFile[chanData, "ChannelDataSource", id]; WriteRefOnFile[parms, "RoutingAreaParms", id]; WriteRefOnFile[rules, "DesignRules", id]; CacheInputArgs[chanData, parms, rules, id]; FOR method: RouteChannel.Method _ GetNextMethod[NEW[RouteChannel.MethodRec]], GetNextMethod[method] WHILE method # NIL DO ForkOneMethod[id, method]; ENDLOOP; [bestResult, bestMethod] _ WaitForEveryOne[id]; chanData _ NARROW[ReadRefFromFile[Rope.Cat["ChannelDataRes", MethodName[bestMethod]], id]]; RouteChannel.WriteResult[bestResult, parms, rules, bestMethod]; }; GetNextMethod: PROC [currentMethod: RouteChannel.Method] RETURNS [nextMethod: RouteChannel.Method] = { SELECT currentMethod.directionSequence FROM start => nextMethod _ NEW[RouteChannel.MethodRec _ [outsideInTop, leftToRight]]; leftToRight => nextMethod _ NEW[RouteChannel.MethodRec _ [currentMethod.trackSequence, rightToLeft]]; rightToLeft => nextMethod _ NEW[RouteChannel.MethodRec _ [currentMethod.trackSequence, alternateLeft]]; alternateLeft => nextMethod _ NEW[RouteChannel.MethodRec _ [currentMethod.trackSequence, alternateRight]]; alternateRight => { nextMethod _ NEW[RouteChannel.MethodRec _ [currentMethod.trackSequence, leftToRight]]; SELECT currentMethod.trackSequence FROM start => nextMethod.trackSequence _ outsideInTop; outsideInTop => nextMethod.trackSequence _ outsideInBottom; outsideInBottom => nextMethod.trackSequence _ botToTop; botToTop => nextMethod.trackSequence _ topToBot; topToBot => nextMethod _ NIL; ENDCASE; }; ENDCASE; }; CacheInputArgs: ENTRY PROC [chanData: RouteChannel.ChannelData, parms: RoutePrivate.RoutingAreaParms, rules: Route.DesignRules, id: Rope.ROPE] ~ { ENABLE UNWIND => NULL; cachedId _ id; cachedChanData _ chanData; cachedParms _ parms; cachedRules _ rules; }; GetCachedArgs: ENTRY PROC [id: Rope.ROPE] RETURNS [chanData: RouteChannel.ChannelData, parms: RoutePrivate.RoutingAreaParms, rules: Route.DesignRules, notValid: BOOLEAN] ~ { ENABLE UNWIND => NULL; IF Rope.Equal[id, cachedId] THEN RETURN[cachedChanData, cachedParms, cachedRules, FALSE] ELSE RETURN [NIL, NIL, NIL, TRUE]; }; GetUniqueId: PROC RETURNS [id: Rope.ROPE] ~ { maxL: NAT = LAST[NAT]; rs: ResultSummary _ NEW[ResultSummaryRec _ [bestResult: NEW[Route.ResultDataRec _ [maxL, maxL, maxL, maxL, maxL, maxL, maxL, DABasics.Rect[maxL, maxL, maxL, maxL]]]]]; id _ IO.PutFR["%d", IO.card[LOOPHOLE[BasicTime.Now[], CARD]]]; [] _ SymTab.Store[x: idTable, key: id, val: rs]; WriteRefOnFile[rs.bestResult, "BestResult", id]; }; ForkData: TYPE ~ REF ForkDataRec; ForkDataRec: TYPE ~ RECORD [id: Rope.ROPE, method: RouteChannel.Method]; ForkOneMethod: ENTRY PROC [id: Rope.ROPE, method: RouteChannel.Method] ~ { ENABLE UNWIND => NULL; forkData: ForkData _ NEW[ForkDataRec _ [id, method]]; rs: ResultSummary _ NARROW[SymTab.Fetch[x: idTable, key: id].val]; UNTIL nForked NULL; nForked _ nForked-1; BROADCAST oneFinished; }; SubmitOneChan: PROC [data: REF] RETURNS [results: REF _ NIL] ~ { Open: SymTab.UpdateAction ~ { rs: ResultSummary _ NARROW[val]; IF rs.servers#NIL THEN { serverInstance _ rs.servers.first; rs.servers _ rs.servers.rest; }; }; Close: SymTab.UpdateAction ~ { rs: ResultSummary _ NARROW[val]; IF RouteUtil.CompareResult[result, rs.bestResult]=less THEN { rs.bestResult _ result; rs.bestMethod _ forkData.method; RenameBestResult[methodName, forkData.id]; } ELSE IF okToFlush THEN { FlushFile[Rope.Cat["ResultData", methodName], forkData.id]; FlushFile[Rope.Cat["ChannelDataRes", methodName], forkData.id]; }; rs.nOut _ rs.nOut-1; rs.servers _ CONS[serverInstance, rs.servers]; }; ntries: NAT _ 10; result: Route.ResultData; forkData: ForkData _ NARROW[data]; methodName: Rope.ROPE _ MethodName[forkData.method]; cmdLine: Rope.ROPE _ Rope.Cat[forkData.id, methodName]; msg: Rope.ROPE; serverInstance: Rope.ROPE; found: BOOL; success: ComputeServerClient.RemoteSuccess _ false; UNTIL success=true DO SymTab.Update[x: idTable, key: forkData.id, action: Open]; IF serverInstance=NIL THEN [found, success, msg, serverInstance] _ ComputeServerClient.StartService[ service: csCommandName, cmdLine: cmdLine, in: NIL, out: NIL, queueService: TRUE] ELSE [found, success, msg, serverInstance] _ ComputeClientExtras.StartServiceExtra[ service: csCommandName, cmdLine: cmdLine, in: NIL, out: NIL, queueService: FALSE, serverName: serverInstance]; ntries _ ntries-1; IF ntries=0 THEN Error[explanation: Rope.Cat["Summoner error, ", msg]]; ENDLOOP; result _ NARROW[ReadRefFromFile[Rope.Cat["ResultData", methodName], forkData.id]]; SymTab.Update[x: idTable, key: forkData.id, action: Close]; OneFinished[]; }; Error: ERROR[explanation: Rope.ROPE _ NIL] = CODE; WaitForEveryOne: ENTRY PROC [id: Rope.ROPE] RETURNS [bestResult: Route.ResultData, bestMethod: RouteChannel.Method] ~ { ENABLE UNWIND => NULL; rs: ResultSummary _ NARROW[SymTab.Fetch[x: idTable, key: id].val]; UNTIL rs.nOut=0 DO WAIT oneFinished ENDLOOP; bestResult _ rs.bestResult; bestMethod _ rs.bestMethod; [] _ SymTab.Delete[x: idTable, key: id]; }; MethodName: PROC [method: RouteChannel.Method] RETURNS [name: Rope.ROPE] ~ { c1, c2: CHAR; SELECT method.trackSequence FROM start => c1 _ 's; outsideInTop => c1 _ 'o; outsideInBottom => c1 _ 'O; botToTop => c1 _ 'b; topToBot => c1 _ 't; ENDCASE => ERROR; SELECT method.directionSequence FROM start => c2 _ 's; leftToRight => c2 _ 'l; rightToLeft => c2 _ 'r; alternateLeft => c2 _ 'a; alternateRight => c2 _ 'A; ENDCASE => ERROR; name _ IO.PutFR["-%g%g", IO.char[c1], IO.char[c2]]; }; MethodFromName: PROC [name: Rope.ROPE] RETURNS [method: RouteChannel.Method] ~ { c1, c2: CHAR; ts: RouteChannel.TrackSequence; ds: RouteChannel.DirectionSequence; IF Rope.Fetch[name, 0]#'- THEN ERROR; c1 _ Rope.Fetch[name, 1]; c2 _ Rope.Fetch[name, 2]; SELECT c1 FROM 's => ts _ start; 'o => ts _ outsideInTop; 'O => ts _ outsideInBottom; 'b => ts _ botToTop; 't => ts _ topToBot; ENDCASE => ERROR; SELECT c2 FROM 's => ds _ start; 'l => ds _ leftToRight; 'r => ds _ rightToLeft; 'a => ds _ alternateLeft; 'A => ds _ alternateRight; ENDCASE => ERROR; method _ NEW[RouteChannel.MethodRec _ [ts, ds]]; }; RemoteRouteOne: Commander.CommandProc ~ { sepIndex: INT _ Rope.Index[s1: cmd.commandLine, s2: "-"]; id: Rope.ROPE _ Rope.Substr[base: cmd.commandLine, len: sepIndex]; methodName: Rope.ROPE _ Rope.Substr[base: cmd.commandLine, start: sepIndex, len: 3]; method: RouteChannel.Method _ MethodFromName[methodName]; chanData: RouteChannel.ChannelData; parms: RoutePrivate.RoutingAreaParms; rules: Route.DesignRules; notValid: BOOLEAN; routeResult, bestResult: Route.ResultData; [chanData, parms, rules, notValid] _ GetCachedArgs[id]; IF notValid THEN { chanData _ NARROW[ReadRefFromFile["ChannelDataSource", id]]; parms _ NARROW[ReadRefFromFile["RoutingAreaParms", id]]; rules _ NARROW[ReadRefFromFile["DesignRules", id]]; CacheInputArgs[chanData, parms, rules, id]; }; routeResult _ RouteChannelTopol.RouteOneChan[chanData, parms, rules, method]; bestResult _ NARROW[ReadRefFromFile["BestResult", id]]; WriteRefOnFile[routeResult, Rope.Cat["ResultData", methodName], id]; IF RouteUtil.CompareResult[routeResult, bestResult]=less THEN WriteRefOnFile[chanData, Rope.Cat["ChannelDataRes", methodName], id]; }; WriteRefOnFile: PROC [ref: REF, name, id: Rope.ROPE] ~ { fileName: Rope.ROPE _ Rope.Cat[name, ".", id]; s: IO.STREAM _ FS.StreamOpen[fileName: fileName, accessOptions: create]; RefIO.WriteRef[s, ref]; IO.Close[s]; }; ReadRefFromFile: PROC [name, id: Rope.ROPE] RETURNS [ref: REF] ~ { fileName: Rope.ROPE _ Rope.Cat[name, ".", id]; s: IO.STREAM _ FS.StreamOpen[fileName: fileName]; ref _ RefIO.ReadRef[s]; IO.Close[s]; }; FlushFile: PROC [name, id: Rope.ROPE] ~ { fileName: Rope.ROPE _ Rope.Cat[name, ".", id]; FS.Delete[name: fileName]; }; RenameBestResult: PROC [methodName, id: Rope.ROPE] ~ { from: Rope.ROPE _ Rope.Cat["ResultData", methodName, ".", id]; to: Rope.ROPE _ Rope.Cat["BestResult", ".", id]; FS.Rename[from: from, to: to]; }; ComputeServerServer.Register[ key: csCommandName, proc: RemoteRouteOne ]; }. ζRouteChannelRemoteImpl.mesa Copyright Σ 1985, 1987, 1988 by Xerox Corporation. All rights reserved. by Bryan Preas July 10, 1985 6:57:00 pm PDT last edited by Bryan Preas July 20, 1987 7:47:21 pm PDT Christian Le Cocq March 21, 1988 2:15:52 pm PST channel route the routing area channel route the routing area start with a bad result loop through the options IF debug THEN RouteChannel.WriteResult[result, parms, rules, method]; restore results of the best method channel route the routing area loop through the options read results of the best method IF debug AND nextMethod # NIL THEN { TerminalIO.PutRope[Rope.Cat["\nNew method: ", RouteChannel.directionSequenceName[nextMethod.directionSequence], ", ", RouteChannel.trackSequenceName[nextMethod.trackSequence]]]}; CedarProcess.ForkableProc InitMaps: PROC ~ { daMapFile: Rope.ROPE _ "/DATools/DATools7.0/DAToolsVersionMaps/DAToolsSymbols.VersionMap"; daPrefix: Rope.ROPE _ "[DATools]"; mapList: VersionMap.MapList _ VersionMapDefaults.GetMapList[$Symbols]; UNTIL mapList=NIL DO IF Rope.Equal[VersionMap.GetPrefix[mapList.first], daPrefix] THEN RETURN; mapList _ mapList.rest; ENDLOOP; VersionMapDefaults.AddToMapList[$Symbols, VersionMap.RestoreMapFromFile[daMapFile]]; }; Κ‡˜codešœ™KšœH™HKšœ*Οkœ™.Kšœ6™9K™/K™—š ˜ Kšœ œ˜Kšœœ˜Kšœ œ˜Kšœ œ˜Kšœœ˜.Kšœœ˜8Kšœœ ˜%Kšœ œ˜Kšœœ˜&Kšœœ œ˜,Kšœœ˜ Kšœœœ$˜4Kšœœ8˜CKšœ œQ˜cKšœœ˜'Kšœ œ˜&Kšœ œ˜ Kšœœ;˜GK˜—šΠlnœœ˜%Kšœ‘Οc˜ΕKšœ˜K˜šœœœ˜+šœœœ˜ Kšœœ˜Kš œ œœœœ˜!Kšœ˜Kšœ˜K˜——K˜Kšœ  œ˜Kšœ œ˜Kšœœ˜K˜&Kšœœ˜*Kšœœœ˜Kšœ œœ˜Kšœœœ˜"Kšœ)˜)Kšœ+˜+Kšœ˜Kšœœ ˜ K˜šΟn œ œ%˜=Kšœ%˜%Kšœ˜Kšœ˜Kšœ#˜*K™šœ œ˜!Kšœ.˜2Kšœ.˜2—Kšœ˜K˜—š œœ%˜;Kšœ%˜%Kšœ˜Kšœ˜Kšœ#˜*K™K™Kšœ"œ˜>Kšœ ˜ Kšœ˜Kšœ™Kšœœœœ˜Kšœ œj˜zK˜Kšœ™šœTœ œ˜lKšœH˜HKšœ˜Kšœœ8™EK˜šœ4˜:Kšœ+˜+—Kšœœœœ˜CKšœ˜K˜—Kšœ"™"šœ˜KšœP˜P—K˜Kšœ?˜?Kšœ˜K˜—š œœ%˜Kšœ0˜0Kšœ0˜0K˜K˜—šœ œœ ˜!Kšœ œœ œ˜HK˜—š  œœœ œ"˜JKšœœœ˜Kšœœ˜5K•StartOfExpansion[x: SymTab.Ref, key: ROPE]šœœ(˜BKšœœœ œ˜Kšœ œ#˜0Kšœ˜K˜K˜—š œœ™KšœœF™ZKšœœ™.KšœF™Fšœ œ™Kšœ;œœ™IKšœ™Kšœ™—KšœT™TK™—K˜šœ˜Kšœ˜Kšœ˜K˜K˜—K˜Kšœ˜——…—-@‡