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