-- ChipExternalWiring.mesa -- A module to augment the geometric wiring with external wiring from -- a file, and to check the consistency of the two. -- Last Edited by: McCreight, October 25, 1984 1:45 PM -- written by McCreight, 11 Sept 83 DIRECTORY Ascii, ChipNetDefs, ChipUserInt, CWF, ppdefs, StreamDefs; ChipExternalWiring: PROGRAM IMPORTS ChipNetDefs, ChipUserInt, CWF, ppdefs, StreamDefs EXPORTS ChipNetDefs = BEGIN OPEN ppdefs, ChipNetDefs; ExternalNodePtr: TYPE = LONG POINTER TO ExternalNode _ NIL; ExternalNode: TYPE = RECORD [ next: ExternalNodePtr _ NIL, name: Atom, net: netPtr _ NIL]; TerminalSpecPtr: TYPE = LONG POINTER TO TerminalSpec _ NIL; TerminalSpec: TYPE = RECORD [ next: TerminalSpecPtr _ NIL, levelSpec: Atom]; AddExternalWiring: PUBLIC PROC [fileName: STRING, root: CellCallPtr] = BEGIN wirIn, wirOut: StreamDefs.DiskHandle _ NIL; s: STRING _ [200]; -- for error messages node: ExternalNodePtr _ NIL; nodeName: Atom _ NIL; token: Atom _ NIL; opens, shorts: NAT _ 0; Connect: PROC [cell: CellCallPtr, spec: TerminalSpecPtr] = BEGIN SELECT TRUE FROM spec=NIL => NULL; spec.next=NIL => -- ...z MatchTerminals[spec.levelSpec, cell.clusters]; spec.levelSpec = asterisk => BEGIN -- ...*.x.y.z FOR son: InstancePtr _ cell.offspring, son.sibling WHILE son#NIL DO WITH cs: son SELECT FROM cell => BEGIN Connect[@cs, spec]; -- son = ...*.x.y.z ? Connect[@cs, spec.next]; -- son = ...x.y.z ? END; ENDCASE => NULL; ENDLOOP; END; ENDCASE => -- ...x.y.z BEGIN FOR son: InstancePtr _ cell.offspring, son.sibling WHILE son#NIL DO WITH cs: son SELECT FROM cell => IF spec.levelSpec= FindPropValue[ItemRefToLp[cs.caller], instanceName] THEN Connect[@cs, spec.next]; ENDCASE => NULL; ENDLOOP; END; END; -- of Connect MatchTerminals: PROC [name: Atom, cl: ClusterPtr] = BEGIN WHILE cl#NIL DO IF cl.netName=name THEN FOR mc: MustConnectPtr _ @cl.first, mc.next WHILE mc#NIL DO SELECT TRUE FROM node.net=NIL => BEGIN node.net _ mc.net _ RefCanonNet[mc.net]; IF node.name#NIL THEN GetNormalNetId[@node.net].name _ named[name: node.name]; END; (mc.net _ CanonNet[mc.net])#node.net => BEGIN AppendLongString[s, "Had to join terminal "]; AppendTerminalName[s, mc.source]; AppendLongString[s, " to node "]; AppendAtom[s, node.name]; opens _ opens+1; Failure[]; mc.net _ node.net _ MergeNets[mc.net, node.net]; END; ENDCASE => NULL; ENDLOOP; -- mc cl _ cl.next; ENDLOOP; END; -- of MatchTerminals Failure: PROC = BEGIN IF wirOut=NIL THEN wirOut _ StreamDefs.NewByteStream[ (fileName _ ChipUserInt.FixExtension[fileName, ".werr"]), StreamDefs.WriteAppend]; FOR i: NAT IN [0..s.length) DO wirOut.put[wirOut, s[i]]; ENDLOOP; wirOut.put[wirOut, Ascii.CR]; s.length _ 0; END; -- of Failure s.length _ 0; BEGIN -- for EXITS wirIn _ StreamDefs.NewByteStream[ (fileName _ ChipUserInt.FixExtension[fileName, ".wspec"]), StreamDefs.Read ! StreamDefs.FileNameError => GOTO BadFileName]; FOR token _ ReadAtom[wirIn], ReadAtom[wirIn] WHILE token#endOfFile DO spec: TerminalSpecPtr _ NIL; IF token#colon THEN {nodeName _ token; token _ ReadAtom[wirIn]} ELSE nodeName _ NIL; IF token#colon THEN GOTO FormatError; node _ netZ.NEW[ExternalNode _ [ next: node, name: nodeName]]; token _ comma; WHILE token#semiColon AND token#endOfFile DO spec, tail: TerminalSpecPtr; IF token=comma THEN token _ ReadAtom[wirIn]; spec _ tail _ netZ.NEW[TerminalSpec _ [levelSpec: token]]; token _ ReadAtom[wirIn]; WHILE token=period DO nextSpec: TerminalSpecPtr = netZ.NEW[TerminalSpec _ [levelSpec: ReadAtom[wirIn]]]; tail.next _ nextSpec; tail _ nextSpec; token _ ReadAtom[wirIn]; ENDLOOP; Connect[root, spec]; WHILE spec#NIL DO t: TerminalSpecPtr _ spec; spec _ spec.next; netZ.FREE[@t]; ENDLOOP; ENDLOOP; -- reading terminal specs for a node IF token#semiColon THEN GOTO FormatError; ENDLOOP; -- reading nodes -- Make sure each node is unique FOR n1: ExternalNodePtr _ node, n1.next WHILE n1#NIL DO FOR n2: ExternalNodePtr _ n1.next, n2.next WHILE n2#NIL DO IF (n1.net _ CanonNet[n1.net])= (n2.net _ CanonNet[n2.net]) THEN BEGIN AppendLongString[s, "Shorted nodes: "]; AppendAtom[s, n1.name]; AppendLongString[s, " and "]; AppendAtom[s, n2.name]; shorts _ shorts+1; Failure[]; EXIT; END; ENDLOOP; ENDLOOP; EXITS BadFileName => BEGIN CWF.SWF1[s, "File %s doesn't exist.", fileName]; ChipUserInt.Explain[s, "(punting wiring spec)"]; END; FormatError => BEGIN pos: LONG CARDINAL _ StreamDefs.GetPosition[wirIn]; CWF.SWF1[s, "Wiring spec error just before character %ld.", @pos]; ChipUserInt.Explain[s, "(punting wiring spec)"]; END; END; wirIn.destroy[wirIn]; WHILE node#NIL DO t: ExternalNodePtr _ node; node _ node.next; netZ.FREE[@t]; ENDLOOP; IF wirOut#NIL THEN BEGIN wirOut.destroy[wirOut]; wirOut _ NIL; CWF.SWF2[s, "There are %d shorts and %d opens in the geometry according", @shorts, @opens]; ChipUserInt.Explain[s, "to the wiring specification. See", fileName]; END; END; -- of AddExternalWiring ReadAtom: PROC [file: StreamDefs.DiskHandle] RETURNS [atom: Atom] = BEGIN s: STRING _ [100]; c: CHARACTER _ ' ; s.length _ 0; DO ENABLE StreamDefs.StreamError => GOTO NoMore; SELECT c FROM Ascii.NUL, Ascii.LF => NULL; ':, '., ',, '; => IF s.length>0 THEN {StreamDefs.SetPosition[file, StreamDefs.GetPosition[file]-1]; EXIT} ELSE RETURN[SELECT c FROM ': => colon, '; => semiColon, '. => period, ', => comma, ENDCASE => NIL]; ' , Ascii.TAB, Ascii.CR => IF s.length>0 THEN EXIT; Ascii.ControlZ => -- get rid of Bravo formatting FOR c _ file.get[file], file.get[file] WHILE c#Ascii.CR DO ENDLOOP; '- => -- could be a comment BEGIN minusCount: [0..2] _ 0; s[s.length] _ '-; s.length _ s.length+1; c _ file.get[file]; IF c#'- THEN LOOP; -- It is a comment. Wait it out. s.length _ s.length-1; c _ file.get[file]; FOR c _ file.get[file], file.get[file] WHILE c#Ascii.CR AND minusCount<2 DO minusCount _ IF c='- THEN minusCount+1 ELSE 0; ENDLOOP; END; ENDCASE => BEGIN s[s.length] _ c; s.length _ s.length+1; END; c _ file.get[file]; REPEAT NoMore => IF s.length=0 THEN RETURN[endOfFile]; ENDLOOP; RETURN[MakeAtom[s]]; END; comma: Atom = MakeAtom[","]; semiColon: Atom = MakeAtom[";"]; colon: Atom = MakeAtom[":"]; period: Atom = MakeAtom["."]; endOfFile: Atom = MakeAtom["!!! End Of File !!!"]; asterisk: Atom = MakeAtom["*"]; END.