-- 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.