file: ParseImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Pascal-to-Mesa translator output, translated at April 29, 1988 5:57:26 pm PDT
DIRECTORY
FS,
IO,
PascalBasic,
PascalNoviceFiles,
ParsePrivate,
Rope,
TerminalIO;
ParseImpl: PROGRAM
IMPORTS FS, IO, PascalBasic, PascalNoviceFiles, Rope, TerminalIO
EXPORTS ParsePrivate = PUBLIC
BEGIN OPEN PascalBasic, PascalNoviceFiles, ParsePrivate;
from Jason at uiuc April 29, 1988
ptest - test the Preas/Roberts placement language parser
Copyright (C) 1987 by Jonathan Rose. All rights reserved.
pbenchtypes.h contains the data types, structures, and constants
for the Pascal-language parser of the standard placement program input
format specified by Preas and Roberts.
Copyright (C) 1987 by Jonathan Rose. All rights reserved.
Constants Section - all grouped together in accordance with Pascal's wishes
Inputfile: Text;
Outputfile: Text;
Name: LONG POINTER TO Nametype ← PascalStaticZone.NEW[Nametype];
Modtype: Moduletype;
Width: Number;
Height: Number;
Iolisthead: Iolistpointer;
Networklisthead: Networklistpointer;
Placementlisthead: Placementlistpointer;
Blank : PascalChar = ' ;
Tab : PascalChar = ' ;
Return : PascalChar = '\n;
CircuitName : Rope.ROPE;
ReadChar: PROCEDURE [file: PascalTextFilePtr]
RETURNS [PascalChar] = {
RETURN[IO.GetChar[file.baseFile.in]]};
TextEOF: PROCEDURE [file: PascalTextFilePtr]
RETURNS [BOOLEAN] = {
RETURN[IO.EndOf[file.baseFile.in]]};
InventInFileName: PROCEDURE [name: ROPENIL] RETURNS [PascalFile] =
BEGIN
openFiles: MesaFilePtr ← z.NEW[MesaFile ← [name: name, in: FS.StreamOpen[fileName: name, accessOptions: read]]];
RETURN[LOOPHOLE[openFiles]];
END; -- end of InventFileName
InventOutFileName: PROCEDURE [name: ROPENIL] RETURNS [PascalFile] =
BEGIN
openFiles: MesaFilePtr ← z.NEW[MesaFile ← [name: name, out: FS.StreamOpen[fileName: name, accessOptions: create]]];
RETURN[LOOPHOLE[openFiles]];
END; -- end of InventFileName
TextRESET: PROCEDURE [name: Rope.ROPE]
RETURNS [file: PascalTextFilePtr] = {
pf: PascalFile ← InventInFileName[name];
file ← LOOPHOLE[z.NEW[PascalTextFile ← [baseFile: pf]]]};
TextREWRITE: PROCEDURE [name: Rope.ROPE]
RETURNS [file: PascalTextFilePtr] = {
pf: PascalFile ← InventOutFileName[name];
file ← LOOPHOLE[z.NEW[PascalTextFile ← [baseFile: pf]]]};
WriteChar: PROCEDURE [
file: PascalTextFilePtr, item: PascalChar,
fieldMinLength: PascalInteger ← -1] =
TRUSTED BEGIN
i: PascalInteger;
FOR i IN [1..fieldMinLength) DO
file.baseFile.out.PutChar[' ] ENDLOOP;
IF fieldMinLength#0 THEN
BEGIN
IF file.baseFile.in = NIL THEN file.baseFile.out.PutChar[item];
file.element ← item;
END;
END;
CleanupFile: PUBLIC PROCEDURE [file: PascalTextFilePtr] = BEGIN
f: PascalFile ← file.baseFile;
IF f.in # NIL THEN {f.in.Flush[]; f.in.Close[]};
IF f.out # NIL THEN {f.out.Flush[]; f.out.Close[]};
IF f.inSource # NIL THEN {f.inSource.Flush[]; f.inSource.Close[]};
IF f.inSource2 # NIL THEN {f.inSource2.Flush[]; f.inSource2.Close[]};
IF f.outDest # NIL THEN {f.outDest.Flush[]; f.outDest.Close[]};
IF f.outDest2 # NIL THEN {f.outDest2.Flush[]; f.outDest2.Close[]};
END;
Printkeyword: PROCEDURE[ Ofile : LONG POINTER TO Text, Keyword : Keywordtype] = BEGIN
Charposition: PascalInteger ← 1;
WHILE NOT ((Keyword[Charposition] = Blank) OR (Keyword[Charposition] = PascalCHR[0])) DO BEGIN
-- Pascal -- WriteChar[file: @Ofile^, item: Keyword[Charposition]];
Charposition ← Charposition +1;
END ENDLOOP ;
END;
Printname: PROCEDURE[ Ofile : LONG POINTER TO Text, Name : Nametype] = BEGIN
Charposition: PascalInteger ← 1;
WHILE NOT ((Name[Charposition] = Blank) OR (Name[Charposition] = PascalCHR[0])) DO BEGIN
-- Pascal -- WriteChar[file: @Ofile^, item: Name[Charposition]];
Charposition ← Charposition +1;
END ENDLOOP ;
END;
Nameequal returns true if the two strings are the same, false otherwise
Nameequal: PROCEDURE[S1 : Nametype, S2 : Nametype] RETURNS[ NameequalResult: PascalBoolean] = BEGIN
J: PascalInteger ← 1;
NameequalResult ← TRUE;
WHILE (S1[J] = S2[J]) AND (S1[J] # Blank) AND (S2[J] # Blank) DO J ← J +1 ENDLOOP ;
IF S1[J] #S2[J] THEN NameequalResult ← FALSE;
END;
kstrequal returns true if the two strings are the same, false otherwise
Kstrequal: PROCEDURE[S1 : Keywordtype, S2 : Nametype] RETURNS[ KstrequalResult: PascalBoolean] = BEGIN
J: PascalInteger ← 1;
KstrequalResult ← TRUE;
WHILE (S1[J] = S2[J]) AND (S1[J] # Blank) AND (S2[J] # Blank) DO J ← J +1 ENDLOOP ;
IF S1[J] #S2[J] THEN KstrequalResult ← FALSE;
END;
nstrcpy copies one name type into another
Nstrcpy: PROCEDURE[ S1 : LONG POINTER TO Nametype, S2 : Nametype] = BEGIN
J: PascalInteger ← 1;
WHILE J <= Maxnamesize DO BEGIN
S1^[J] ← S2[J];
J ← J +1;
END ENDLOOP ;
END;
nstrlen returns the length of the first string on nonblank characters in the NameType string
Nstrlen: PROCEDURE[S1 : Nametype] RETURNS[ NstrlenResult: PascalInteger] = BEGIN
J: PascalInteger ← 1;
WHILE NOT ((S1[J] = Blank) OR (S1[J] = PascalCHR[0])) DO J ← J +1 ENDLOOP ;
NstrlenResult ← J -1;
END;
NameOnList: PROC [Name: Nametype, NameList: LIST OF Nametype] RETURNS [found: PascalBoolean ← FALSE] ~ BEGIN
FOR sl: LIST OF Nametype ← NameList, sl.rest WHILE sl # NIL AND ~found DO
IF Nameequal[sl.first, Name] THEN found ← TRUE;
ENDLOOP;
END;
RopeToName: PROC [rope: Rope.ROPE] RETURNS [name: Nametype] ~ {
length: INT ← Rope.Length[rope];
FOR index: INT ← 1, index + 1 WHILE index <= length DO
name[index] ← Rope.Fetch[rope, index -1];
ENDLOOP;
FOR index: INT ← length + 1, index + 1 WHILE index <= Maxnamesize DO
name[index] ← ' ;
ENDLOOP;
};
RopesToNames: PROC [ropes: LIST OF Rope.ROPE] RETURNS [names: LIST OF Nametype ← NIL] ~ {
FOR rl: LIST OF Rope.ROPE ← ropes, rl.rest WHILE rl # NIL DO
names ← CONS[RopeToName[rl.first], names];
ENDLOOP;
};
Reverse: PROC [list: LIST OF Nametype] RETURNS[val: LIST OF Nametype] = {
val ← NIL;
UNTIL list = NIL DO
val ← CONS[list.first, val];
list ← list.rest;
ENDLOOP;
RETURN[val];
}; -- of Reverse
Getmodule - routines for parsing the standard placement input form
specified by Preas and Roberts.
Copyright (C) 1987 by Jonathan Rose. All rights reserved.
Constants
Getmodule: PROCEDURE[ Tinputfile : LONG POINTER TO Text,
Tname : LONG POINTER TO Nametype,
Tmodtype : LONG POINTER TO Moduletype,
Twidth : LONG POINTER TO Number,
Theight : LONG POINTER TO Number,
Tiolisthead : LONG POINTER TO Iolistpointer,
Tnetworklisthead : LONG POINTER TO Networklistpointer,
Tplacementlisthead : LONG POINTER TO Placementlistpointer,
Tlinenumber : LONG POINTER TO PascalInteger] = BEGIN
Fatal : PascalInteger = 1;
Warning : PascalInteger = 2;
Eofconst : PascalInteger = -1;
Global Variables
Inputfield: LONG POINTER TO Nametype ← PascalZone.NEW[Nametype];
Eofdetected: PascalBoolean;
Expectingeof: PascalBoolean;
Lineterminated: PascalBoolean;
Llinenumber: PascalInteger;
Support Routines
Error is called when an exception occurs - FATAL ones cause an halt, while WARNINGS are just printed and execution continues --
Error: PROCEDURE[Estring : Nametype, Errortype : PascalInteger] = BEGIN
IF Errortype = Warning THEN PascalWriteLongString[file: @Output, item: "Warning: "]
ELSE PascalWriteLongString[file: @Output, item: "Fatal Error: "];
{PascalWriteLongArrayOfChar[file: @Output, item: @Estring, arrayBound: 100]; PascalWriteLongString[file: @Output, item: " on line "]; PascalWriteInteger[file: @Output, item: Llinenumber]; PascalWriteLongString[file: @Output, item: " of input file"]; PascalWriteLn[file: @Output]};
IF Errortype = Fatal THEN PascalHALT--?--;
END;
ScanField picks up the next field, whilst counting the number of lines that go by
Scanfield: PROCEDURE[ Inputfile : LONG POINTER TO Text, Stext: LONG POINTER TO Nametype] RETURNS[ ScanfieldResult: PascalInteger] = BEGIN
Nextchar: PascalChar;
Textp: PascalInteger;
Skip over blanks, tabs and newlines, counting newlines
IF -- Pascal-- TextEOF[file: @Inputfile^] THEN ScanfieldResult ← Eofconst
ELSE BEGIN
Nextchar← --Pascal-- ReadChar[file: @Inputfile^];
IF Nextchar = Return THEN Llinenumber ← Llinenumber +1;
WHILE ((Nextchar = Blank) OR (Nextchar = Tab) OR (Nextchar = Return)) AND (NOT -- Pascal-- TextEOF[file: @Inputfile^]) DO BEGIN
Nextchar← --Pascal-- ReadChar[file: @Inputfile^];
IF Nextchar = Return THEN Llinenumber ← Llinenumber +1;
END ENDLOOP ;
IF -- Pascal-- TextEOF[file: @Inputfile^] THEN ScanfieldResult ← Eofconst
ELSE BEGIN
Textp ← 1;
Stext^[Textp] ← Nextchar;
Textp ← Textp +1;
Characters until a white space or end of file
Nextchar← --Pascal-- ReadChar[file: @Inputfile^];
IF Nextchar = Return THEN Llinenumber ← Llinenumber +1;
WHILE Nextchar # Blank AND Nextchar # Tab AND NOT -- Pascal-- TextEOF[file: @Inputfile^] AND Nextchar # Return DO BEGIN
Stext^[Textp] ← Nextchar;
Textp ← Textp +1;
Nextchar← --Pascal-- ReadChar[file: @Inputfile^];
IF Nextchar = Return THEN Llinenumber ← Llinenumber +1;
END ENDLOOP ;
Stext^[Textp] ← Blank;
ScanfieldResult ← 1;
END;
END;
END;
GetField reads a field from the input stream. A field is any set of characters delimited by blanks, tabs or newlines.
Getfield: PROCEDURE[ Ifile : LONG POINTER TO Text, Gtext : LONG POINTER TO Nametype] = BEGIN
Errflag: PascalInteger;
Errflag ← Scanfield[@Ifile^, @Gtext^];
IF (Errflag = Eofconst) AND (NOT Expectingeof) THEN
Error[Nametype['U, 'n, 'e, 'x, 'p, 'e, 'c, 't, 'e, 'd, ' , 'E, 'n, 'd, ' , 'o, 'f, ' , 'F, 'i, 'l, 'e, ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal]
ELSE IF (Errflag = Eofconst) AND Expectingeof THEN Eofdetected ← TRUE;
END;
ReadField reads a field from the input stream, ignoring comments
Readfield: PROCEDURE[ Ifile : LONG POINTER TO Text, Rtext : LONG POINTER TO Nametype] = BEGIN
Fieldlength: PascalInteger;
Getfield[@Ifile^, @Rtext^];
WHILE Kstrequal[Startcomment, Rtext^] DO BEGIN
get fields until end of comment
Getfield[@Ifile^, @Rtext^];
WHILE NOT Kstrequal[Endcomment, Rtext^] DO BEGIN
IF Eofdetected THEN Error[Nametype['N, 'o, 'n, '-, 't, 'e, 'r, 'm, 'i, 'n, 'a, 't, 'e, 'd, ' , 'C, 'o, 'm, 'm, 'e, 'n, 't, ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal];
Getfield[@Ifile^, @Rtext^];
END ENDLOOP ;
Getfield[@Ifile^, @Rtext^];
END ENDLOOP ;
Strip off the line terminator if it is attached to the field,
and set end of logical line indicator
Fieldlength ← Nstrlen[Rtext^];
IF ~Eofdetected THEN
IF Rtext^[Fieldlength] = Lineterminator THEN BEGIN
Lineterminated ← TRUE;
Rtext^[Fieldlength] ← Blank;
END;
END;
ConvertToNumber does the conversion from ascii to a floating point number
Converttonumber: PROCEDURE[Ctext : Nametype] RETURNS[ ConverttonumberResult: Number] = BEGIN
Charposition: PascalInteger;
Subtotal: Number;
Ch: PascalChar;
Newdigit: Number;
Divfactor: Number;
Subtotal ← 0.0;
Charposition ← 1;
Ch ← Ctext[Charposition];
WHILE (Ch #Blank) AND (Ch #'.) DO BEGIN
IF (PascalORD[Ch] <PascalORD['0]) OR (PascalORD[Ch] >PascalORD['9]) THEN
Error[Nametype['I, 'l, 'l, 'e, 'g, 'a, 'l, ' , 'N, 'u, 'm, 'b, 'e, 'r, ' , 's, 'p, 'e, 'c, 'i, 'f, 'i, 'e, 'd, ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal]
ELSE BEGIN
Newdigit ← PascalORD[Ch] -PascalORD['0];
Subtotal ← (Subtotal *10.0) +Newdigit;
END;
Charposition ← Charposition +1;
Ch ← Ctext[Charposition];
END ENDLOOP ;
Divfactor ← 10.0;
IF Ch = '. THEN BEGIN
Charposition ← Charposition +1;
Ch ← Ctext[Charposition];
WHILE Ch #Blank DO BEGIN
IF (PascalORD[Ch] <PascalORD['0]) OR (PascalORD[Ch] >PascalORD['9]) THEN
Error[Nametype['I, 'l, 'l, 'e, 'g, 'a, 'l, ' , 'N, 'u, 'm, 'b, 'e, 'r, ' , 's, 'p, 'e, 'c, 'i, 'f, 'i, 'e, 'd, ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal]
ELSE BEGIN
Newdigit ← PascalORD[Ch] -PascalORD['0];
Subtotal ← Subtotal +Newdigit /Divfactor;
Divfactor ← Divfactor *PascalFLOAT[10];
END;
Charposition ← Charposition +1;
Ch ← Ctext[Charposition];
END ENDLOOP ;
END;
ConverttonumberResult ← Subtotal;
END;
Get Line Terminator looks for the line terminator as the next field if it wasn't already encountered
Getlineterminator: PROCEDURE[ Ifile : LONG POINTER TO Text] = BEGIN
Termfield: LONG POINTER TO Nametype ← PascalZone.NEW[Nametype];
IF Lineterminated THEN Lineterminated ← FALSE
ELSE BEGIN
Readfield[@Ifile^, @Termfield^];
IF Lineterminated THEN Lineterminated ← FALSE
ELSE Error[Nametype['M, 'i, 's, 's, 'i, 'n, 'g, ' , 'L, 'i, 'n, 'e, ' , 'T, 'e, 'r, 'm, 'i, 'n, 'a, 't, 'o, 'r, ' , '(, ';, '), ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal];
END;
PascalZone.FREE[@Termfield];
END;
GetIOList reads in the IO List
Getiolist: PROCEDURE[ Ifile : LONG POINTER TO Text, Iolisthead : LONG POINTER TO Iolistpointer]
=
BEGIN Iofield: LONG POINTER TO Nametype ← PascalZone.NEW[Nametype];
Enddetected: PascalBoolean;
Newiopin: Iolistpointer;
Iolisttail: Iolistpointer;
Iolisthead^ ← NIL;
Getlineterminator[@Ifile^];
Main loop to read each pin
Enddetected ← FALSE;
WHILE NOT Enddetected DO BEGIN
Read Signal Name or end of IO List
 Readfield[@Ifile^, @Iofield^];
IF Kstrequal[Endiolistkeyword, Iofield^] THEN BEGIN
  Enddetected ← TRUE;
  Getlineterminator[@Ifile^];
END
ELSE BEGIN -- Create a New IO Pin
  Newiopin ← PascalZone.NEW[Iolist];
  Newiopin^.Side ← Noside;
  Newiopin^.Position ← Noposition;
  Newiopin^.Layer ← Nolayer;
  Newiopin^.Width ← Nowidth;
  Newiopin^.Link ← NIL;
  Nstrcpy[@Newiopin^.Signalname, Iofield^];
Read Terminal Type
  Readfield[@Ifile^, @Iofield^];
IF Kstrequal[Inputterminal, Iofield^] THEN
  Newiopin^.Terminal ← I
ELSE IF Kstrequal[Outputterminal, Iofield^] THEN
  Newiopin^.Terminal ← O
ELSE IF Kstrequal[Bidirectionterminal, Iofield^] THEN
  Newiopin^.Terminal ← B
ELSE IF Kstrequal[Padinputterminal, Iofield^] THEN
  Newiopin^.Terminal ← Pi
ELSE IF Kstrequal[Padoutputterminal, Iofield^] THEN
  Newiopin^.Terminal ← Po
ELSE IF Kstrequal[Padbiterminal, Iofield^] THEN
  Newiopin^.Terminal ← Pb
ELSE IF Kstrequal[Feedthroughterminal, Iofield^] THEN
  Newiopin^.Terminal ← F
ELSE Error[Nametype['U, 'n, 'k, 'n, 'o, 'w, 'n, ' , 'T, 'e, 'r, 'm, 'i, 'n, 'a, 'l, ' , 'T, 'y, 'p, 'e, ' , 'S, 'p, 'e, 'c, 'i, 'f, 'i, 'c, 'a, 't, 'i, 'o, 'n, ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal];
IF NOT Lineterminated THEN BEGIN
  Readfield[@Ifile^, @Iofield^];
  IF (NOT Lineterminated) OR (
   Lineterminated AND (Nstrlen[Iofield^] #0)) THEN BEGIN
   IF Kstrequal[Bottomside, Iofield^] THEN
   Newiopin^.Side ← Bottom
   ELSE IF Kstrequal[Rightside, Iofield^] THEN
   Newiopin^.Side ← Right
   ELSE IF Kstrequal[Topside, Iofield^] THEN
   Newiopin^.Side ← Top
   ELSE IF Kstrequal[Leftside, Iofield^] THEN
   Newiopin^.Side ← Left
  
   ELSE Error[Nametype['U, 'n, 'k, 'n, 'o, 'w, 'n, ' , 'S, 'i, 'd, 'e, ' , 'T, 'y, 'p, 'e, ' , 'S, 'p, 'e, 'c, 'i, 'f, 'i, 'c, 'a, 't, 'i, 'o, 'n, ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal];
   IF NOT Lineterminated THEN BEGIN
   Readfield[@Ifile^, @Iofield^];
   IF
    (NOT Lineterminated) OR (Lineterminated AND (Nstrlen[Iofield^] #0)) THEN
    BEGIN
    Newiopin^.Position ← Converttonumber[Iofield^];
    IF NOT Lineterminated THEN BEGIN
    Readfield[@Ifile^, @Iofield^];
    IF
     (NOT Lineterminated) OR (Lineterminated AND (Nstrlen[Iofield^] #0))
     THEN BEGIN
     Newiopin^.Width ← Converttonumber[Iofield^];
     IF NOT Lineterminated THEN BEGIN
     Readfield[@Ifile^, @Iofield^];
     IF
      (NOT Lineterminated) OR (
      Lineterminated AND (Nstrlen[Iofield^] #0)) THEN BEGIN
      IF Kstrequal[Pdifflayer, Iofield^] THEN
      Newiopin^.Layer ← Pdiff
      ELSE IF Kstrequal[Ndifflayer, Iofield^]
       THEN
      Newiopin^.Layer ← Ndiff
      ELSE IF Kstrequal[Polylayer, Iofield^]
      THEN
      Newiopin^.Layer ← Poly
      ELSE IF Kstrequal[Metal1layer, Iofield^]
      THEN
      Newiopin^.Layer ← Metal1
      ELSE IF Kstrequal[Metal2layer, Iofield^]
       THEN
      Newiopin^.Layer ← Metal2
     
      ELSE Error[Nametype['U, 'n, 'k, 'n, 'o, 'w, 'n, ' , 'L, 'a, 'y, 'e, 'r, ' , 'S, 'p, 'e, 'c, 'i, 'f, 'i, 'c, 'a, 't, 'i, 'o, 'n, ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal];
      Getlineterminator[@Ifile^];
      END;
     END;
     END;
    END;
    END;
   END;
   END;
END;
Link the new IO Pin
IF Iolisthead^ = NIL THEN
  Iolisthead^ ← Newiopin
ELSE
  Iolisttail^.Link ← Newiopin;
  Iolisttail ← Newiopin;
  Lineterminated ← FALSE;
END;
END ENDLOOP ;
PascalZone.FREE[@Iofield]; END;
Getnetworklist: PROCEDURE[ Ifile : LONG POINTER TO Text, Networklisthead : LONG POINTER TO Networklistpointer] = BEGIN
Networkfield: LONG POINTER TO Nametype ← PascalZone.NEW[Nametype];
Enddetected: PascalBoolean;
Signallistend: PascalBoolean;
Newnetworkentry, Networklisttail: Networklistpointer;
Newsignal, Signallisttail: Signallistpointer;
Networklisthead^ ← NIL;
Getlineterminator[@Ifile^];
Main loop to read each Network Entry
Enddetected ← FALSE;
WHILE NOT Enddetected DO BEGIN
Read Instance Name or end of Network List
Readfield[@Ifile^, @Networkfield^];
IF Kstrequal[Endnetworkkeyword, Networkfield^] THEN BEGIN
Enddetected ← TRUE;
Getlineterminator[@Ifile^];
END
ELSE BEGIN -- Create a New Network Entry
Newnetworkentry ← PascalZone.NEW[Networklist];
Newnetworkentry^.Signallisthead ← NIL;
Newnetworkentry^.Link ← NIL;
Nstrcpy[@Newnetworkentry^.Instancename, Networkfield^];
Read Module Name
Readfield[@Ifile^, @Newnetworkentry^.Modulename];
Get the signal names and link onto this entry's list
Signallistend ← FALSE;
WHILE NOT Signallistend DO BEGIN
IF Lineterminated THEN
Signallistend ← TRUE
ELSE BEGIN
Readfield[@Ifile^, @Networkfield^];
IF Lineterminated AND (Nstrlen[Networkfield^] = 0) THEN
Signallistend ← TRUE
ELSE BEGIN
Create a New Signal
Newsignal ← PascalZone.NEW[Signallist];
Newsignal^.Link ← NIL;
Nstrcpy[@Newsignal^.Signalname, Networkfield^];
Link onto this entry's list
IF Newnetworkentry^.Signallisthead = NIL THEN
Newnetworkentry^.Signallisthead ← Newsignal
ELSE
Signallisttail^.Link ← Newsignal;
Signallisttail ← Newsignal;
END;
END;
END ENDLOOP ;
Link the new NetworkEntry
IF Networklisthead^ = NIL THEN
Networklisthead^ ← Newnetworkentry
ELSE
Networklisttail^.Link ← Newnetworkentry;
Networklisttail ← Newnetworkentry;
Lineterminated ← FALSE;
END;
END ENDLOOP ;
PascalZone.FREE[@Networkfield]; END;
Getplacementlist: PROCEDURE[ Ifile : LONG POINTER TO Text, Placementlisthead : LONG POINTER TO Placementlistpointer]
=
BEGIN Placementfield: LONG POINTER TO Nametype ← PascalZone.NEW[Nametype];
Enddetected: PascalBoolean;
  Newplacemententry, Placementlisttail: Placementlistpointer;
Placementlisthead^ ← NIL;
Getlineterminator[@Ifile^];
Main loop to read each Placement Entry
Enddetected ← FALSE;
WHILE NOT Enddetected DO BEGIN
Read Instance Name or end of Placement List
 Readfield[@Ifile^, @Placementfield^];
IF Kstrequal[Endplacementkeyword, Placementfield^] THEN BEGIN
  Enddetected ← TRUE;
  Getlineterminator[@Ifile^];
END
ELSE BEGIN -- Create a New Placement Entry
  Newplacemententry ← PascalZone.NEW[Placementlist];
Newplacemententry^.Reflection ← Rflnone;
Newplacemententry^.Rotation ← Rot0;
Newplacemententry^.Link ← NIL;
  Nstrcpy[@Newplacemententry^.Instancename, Placementfield^];
Read X Location
  Readfield[@Ifile^, @Placementfield^];
Newplacemententry^.Xlocation ← Converttonumber[Placementfield^];
Read Y Location
  Readfield[@Ifile^, @Placementfield^];
Newplacemententry^.Ylocation ← Converttonumber[Placementfield^];
Check for End of Line or reflections, rotations
WHILE NOT Lineterminated DO BEGIN
  Readfield[@Ifile^, @Placementfield^];
  IF NOT (Lineterminated AND (Nstrlen[Placementfield^] = 0))
    THEN BEGIN
   IF Kstrequal[Noreflection, Placementfield^] THEN
   Newplacemententry^.Reflection ← Rflnone
   ELSE IF Kstrequal[Yreflection, Placementfield^] THEN
   Newplacemententry^.Reflection ← Rfly
   ELSE IF Kstrequal[Rot0string, Placementfield^] THEN
   Newplacemententry^.Rotation ← Rot0
   ELSE IF Kstrequal[Rot90string, Placementfield^] THEN
   Newplacemententry^.Rotation ← Rot90
   ELSE IF Kstrequal[Rot180string, Placementfield^] THEN
   Newplacemententry^.Rotation ← Rot180
   ELSE IF Kstrequal[Rot270string, Placementfield^] THEN
   Newplacemententry^.Rotation ← Rot270
   ELSE Error[Nametype['U, 'n, 'k, 'n, 'o, 'w, 'n, ' , 'R, 'o, 't, 'a, 't, 'i, 'o, 'n, ' , 'o, 'r, ' , 'R, 'e, 'f, 'l, 'e, 'c, 't, 'i, 'o, 'n, ' , 't, 'y, 'p, 'e, ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal];
   END;
END ENDLOOP ;
  Lineterminated ← FALSE;
Link the new placement entry
IF Placementlisthead^ = NIL THEN
  Placementlisthead^ ← Newplacemententry
ELSE
  Placementlisttail^.Link ← Newplacemententry;
  Placementlisttail ← Newplacemententry;
END;
END ENDLOOP ;
PascalZone.FREE[@Placementfield]; END;
This is the main routine, called to get the next module. Depending on the
type of module, the Network List and the Placement List may or may not
be empty.
GetModule
Lineterminated ← FALSE;
Eofdetected ← FALSE;
Llinenumber ← Tlinenumber^;
Set all the optional return arguments to Null at start
Twidth^ ← 0.0;
Theight^ ← 0.0;
Tiolisthead^ ← NIL;
Tnetworklisthead^ ← NIL;
Tplacementlisthead^ ← NIL;
Get Module Declaration, return with ENDFILE type if end of file
Expectingeof ← TRUE;
Readfield[@Tinputfile^, @Inputfield^];
IF Eofdetected THEN
 Tmodtype^ ← Endfile
ELSE IF NOT Kstrequal[Modulekeyword, Inputfield^] THEN
 Error[Nametype['M, 'i, 's, 's, 'i, 'n, 'g, ' , 'M, 'o, 'd, 'u, 'l, 'e, ' , 'D, 'e, 'c, 'l, 'a, 'r, 'a, 't, 'i, 'o, 'n, ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal]
ELSE BEGIN
Expectingeof ← FALSE;
Readfield[@Tinputfile^, @Tname^];
Getlineterminator[@Tinputfile^];
Get Type
Readfield[@Tinputfile^, @Inputfield^];
IF NOT Kstrequal[Typekeyword, Inputfield^] THEN
 Error[Nametype['M, 'i, 's, 's, 'i, 'n, 'g, ' , 'T, 'y, 'p, 'e, ' , 'D, 'e, 'c, 'l, 'a, 'r, 'a, 't, 'i, 'o, 'n, ' , '-, ' , 'M, 'u, 's, 't, ' , 'b, 'e, ' , 'a, 'f, 't, 'e, 'r, ' , 'M, 'O, 'D, 'U, 'L, 'E, ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal]
ELSE
Readfield[@Tinputfile^, @Inputfield^];
IF Kstrequal[Standardkeyword, Inputfield^] THEN Tmodtype^ ← Standard
ELSE IF Kstrequal[Padkeyword, Inputfield^] THEN Tmodtype^ ← Pad
ELSE IF Kstrequal[Generalkeyword, Inputfield^] THEN Tmodtype^ ← General
ELSE IF Kstrequal[Parentkeyword, Inputfield^] THEN Tmodtype^ ← Parent
ELSE IF Kstrequal[Feedthroughkeyword, Inputfield^] THEN Tmodtype^ ← Feedthrough
ELSE Error[Nametype['U, 'n, 'k, 'n, 'o, 'w, 'n, ' , 'M, 'o, 'd, 'u, 'l, 'e, ' , 'T, 'y, 'p, 'e, ' , 'S, 'p, 'e, 'c, 'i, 'f, 'i, 'c, 'a, 't, 'i, 'o, 'n, ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal];
Getlineterminator[@Tinputfile^];
Loop to pick up the next field and process it - either
width, height, IOList, NetworkList or PlacementList
Readfield[@Tinputfile^, @Inputfield^];
WHILE NOT (Kstrequal[Endmodulekeyword, Inputfield^]) DO BEGIN
IF Kstrequal[Widthkeyword, Inputfield^] THEN BEGIN
  Readfield[@Tinputfile^, @Inputfield^];
  Twidth^ ← Converttonumber[Inputfield^];
  Getlineterminator[@Tinputfile^];
END
ELSE IF Kstrequal[Heightkeyword, Inputfield^] THEN BEGIN
  Readfield[@Tinputfile^, @Inputfield^];
  Theight^ ← Converttonumber[Inputfield^];
  Getlineterminator[@Tinputfile^];
END
ELSE IF Kstrequal[Iolistkeyword, Inputfield^] THEN
  Getiolist[@Tinputfile^, @Tiolisthead^]
ELSE IF Kstrequal[Networkkeyword, Inputfield^] THEN
  Getnetworklist[@Tinputfile^, @Tnetworklisthead^]
ELSE IF Kstrequal[Placementkeyword, Inputfield^] THEN
  Getplacementlist[@Tinputfile^, @Tplacementlisthead^]
ELSE Error[Nametype['U, 'n, 'k, 'n, 'o, 'w, 'n, ' , 'K, 'e, 'y, 'w, 'o, 'r, 'd, ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' , ' ], Fatal];
 Readfield[@Tinputfile^, @Inputfield^];
END ENDLOOP ;
Getlineterminator[@Tinputfile^];
END;
Update LineNumber
Tlinenumber^ ← Llinenumber;
PascalZone.FREE[@Inputfield]; END; -- GetModule
Writemodule - routines for printing out a module in the format
specified by Preas and Roberts.
Copyright (C) 1987 by Jonathan Rose. All rights reserved.
Writemodule: PROCEDURE[ Woutputfile : LONG POINTER TO Text,
Wname : Nametype,
Wmodtype : Moduletype,
Wwidth : Number,
Wheight : Number,
Wiolisthead : Iolistpointer,
Wnetworklisthead : Networklistpointer,
Wplacementlisthead : Placementlistpointer] = BEGIN
Iolistpin: Iolistpointer;
Currentnetworkentry: Networklistpointer;
Currentsignal: Signallistpointer;
Currentplacemententry: Placementlistpointer;
WriteModule
PascalWriteLn[file: @Woutputfile^];
Printkeyword [@Woutputfile^, Modulekeyword];
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printname [@Woutputfile^, Wname];
{PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Typekeyword];
PascalWriteLongString[file: @Woutputfile^, item: " "];
IF Wmodtype = Standard THEN
Printkeyword[@Woutputfile^, Standardkeyword]
ELSE IF Wmodtype = Pad THEN
Printkeyword[@Woutputfile^, Padkeyword]
ELSE IF Wmodtype = General THEN
Printkeyword[@Woutputfile^, Generalkeyword]
ELSE IF Wmodtype = Parent THEN
Printkeyword[@Woutputfile^, Parentkeyword]
ELSE IF Wmodtype = Feedthrough THEN
Printkeyword[@Woutputfile^, Feedthroughkeyword]
ELSE
{PascalWriteLongString[file: @Woutputfile^, item: "UNKNOWN!!!"]; PascalWriteLn[file: @Woutputfile^]};
{PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
IF (Wwidth #0.0) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Widthkeyword];
{PascalWriteLongString[file: @Woutputfile^, item: " "]; PascalWriteReal[file: @Woutputfile^, item: Wwidth, fieldMinLength: 9, fracLength: 6]; PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
END;
IF (Wheight #0.0) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Heightkeyword];
{PascalWriteLongString[file: @Woutputfile^, item: " "]; PascalWriteReal[file: @Woutputfile^, item: Wheight, fieldMinLength: 9, fracLength: 6]; PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
END;
Iolistpin ← Wiolisthead;
IF (Wiolisthead #NIL) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Iolistkeyword];
{PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
END;
WHILE (Iolistpin #NIL) DO BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printname[@Woutputfile^, Iolistpin^.Signalname];
PascalWriteLongString[file: @Woutputfile^, item: " "];
IF (Iolistpin^.Terminal = I) THEN
Printkeyword[@Woutputfile^, Inputterminal]
ELSE IF (Iolistpin^.Terminal = O) THEN
Printkeyword[@Woutputfile^, Outputterminal]
ELSE IF (Iolistpin^.Terminal = B) THEN
Printkeyword[@Woutputfile^, Bidirectionterminal]
ELSE IF (Iolistpin^.Terminal = Pi) THEN
Printkeyword[@Woutputfile^, Padinputterminal]
ELSE IF (Iolistpin^.Terminal = Po) THEN
Printkeyword[@Woutputfile^, Padoutputterminal]
ELSE IF (Iolistpin^.Terminal = Pb) THEN
Printkeyword[@Woutputfile^, Padbiterminal]
ELSE IF (Iolistpin^.Terminal = F) THEN
Printkeyword[@Woutputfile^, Feedthroughterminal]
ELSE
PascalWriteLongString[file: @Woutputfile^, item: "UNKNOWN!!! "];
IF (Iolistpin^.Side #Noside) THEN BEGIN
IF (Iolistpin^.Side = Bottom) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Bottomside];
END
ELSE IF (Iolistpin^.Side = Right) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Rightside];
END
ELSE IF (Iolistpin^.Side = Top) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Topside];
END
ELSE IF (Iolistpin^.Side = Left) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Leftside];
END
ELSE
PascalWriteLongString[file: @Woutputfile^, item: "UNKNOWN!!!"];
IF (Iolistpin^.Position #Noposition) THEN BEGIN
{PascalWriteLongString[file: @Woutputfile^, item: " "]; PascalWriteReal[file: @Woutputfile^, item: Iolistpin^.Position, fieldMinLength: 9, fracLength: 6]};
IF (Iolistpin^.Width #Nowidth) THEN BEGIN
{PascalWriteLongString[file: @Woutputfile^, item: " "]; PascalWriteReal[file: @Woutputfile^, item: Iolistpin^.Width, fieldMinLength: 9, fracLength: 6]};
IF (Iolistpin^.Layer #Nolayer) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
IF (Iolistpin^.Layer = Pdiff) THEN
Printkeyword[@Woutputfile^, Pdifflayer]
ELSE IF (Iolistpin^.Layer = Ndiff) THEN
Printkeyword[@Woutputfile^, Ndifflayer]
ELSE IF (Iolistpin^.Layer = Poly) THEN
Printkeyword[@Woutputfile^, Polylayer]
ELSE IF (Iolistpin^.Layer = Metal1) THEN
Printkeyword[@Woutputfile^, Metal1layer]
ELSE IF (Iolistpin^.Layer = Metal2) THEN
Printkeyword[@Woutputfile^, Metal2layer]
ELSE
Printkeyword[@Woutputfile^, Keywordtype['U, 'N, 'K, 'N, 'O, 'W, 'N, ' , 'L, 'A, 'Y, 'E, 'R, '!, '!]];
END;
END;
END;
END;
{PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
Iolistpin ← Iolistpin^.Link;
END ENDLOOP ;
IF (Wiolisthead #NIL) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Endiolistkeyword];
{PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
END;
IF (Wnetworklisthead #NIL) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Networkkeyword];
{PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
Currentnetworkentry ← Wnetworklisthead;
WHILE (Currentnetworkentry #NIL) DO BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printname[@Woutputfile^, Currentnetworkentry^.Instancename];
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printname[@Woutputfile^, Currentnetworkentry^.Modulename];
Currentsignal ← Currentnetworkentry^.Signallisthead;
WHILE (Currentsignal #NIL) DO BEGIN
  
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printname[@Woutputfile^, Currentsignal^.Signalname];
Currentsignal ← Currentsignal^.Link;
END ENDLOOP ;
{PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
Currentnetworkentry ← Currentnetworkentry^.Link;
END ENDLOOP ;
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Endnetworkkeyword];
{PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
END;
IF (Wplacementlisthead #NIL) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Placementkeyword];
{PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
Currentplacemententry ← Wplacementlisthead;
WHILE (Currentplacemententry #NIL) DO BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printname[@Woutputfile^, Currentplacemententry^.Instancename];
{PascalWriteLongString[file: @Woutputfile^, item: " "]; PascalWriteReal[file: @Woutputfile^, item: Currentplacemententry^.Xlocation, fieldMinLength: 9, fracLength: 2]; PascalWriteLongString[file: @Woutputfile^, item: " "]; PascalWriteReal[file: @Woutputfile^, item: Currentplacemententry^.Ylocation, fieldMinLength: 9, fracLength: 6]};
IF (Currentplacemententry^.Reflection = Rflnone) THEN
PascalWriteLongString[file: @Woutputfile^, item: " "]
ELSE IF (Currentplacemententry^.Reflection = Rfly) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Yreflection];
END
ELSE
PascalWriteLongString[file: @Woutputfile^, item: " UNKNOWN REFLECTION"];
IF (Currentplacemententry^.Rotation = Rot0) THEN
PascalWriteLongString[file: @Woutputfile^, item: " "]
ELSE IF (Currentplacemententry^.Rotation = Rot90) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Rot90string];
END
ELSE IF (Currentplacemententry^.Rotation = Rot180) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Rot180string];
END
ELSE IF (Currentplacemententry^.Rotation = Rot270) THEN BEGIN
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Rot270string];
END
ELSE
PascalWriteLongString[file: @Woutputfile^, item: " UNKNOWN ROTATION"];
{PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
Currentplacemententry ← Currentplacemententry^.Link;
END ENDLOOP ;
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Endplacementkeyword];
{PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
END;
PascalWriteLongString[file: @Woutputfile^, item: " "];
Printkeyword[@Woutputfile^, Endmodulekeyword];
{PascalWriteLongString[file: @Woutputfile^, item: ";"]; PascalWriteLn[file: @Woutputfile^]};
END; -- WriteModule
WriteMesa: PROCEDURE[
Woutputfile : LONG POINTER TO Text,
Wname : Nametype,
Wmodtype : Moduletype,
Wwidth : Number,
Wheight : Number,
Wiolisthead : Iolistpointer,
Wnetworklisthead : Networklistpointer,
Wplacementlisthead : Placementlistpointer] = BEGIN
Pads: LIST OF Nametype ← NIL;
InstanceList: LIST OF Nametype ← NIL;
WriteWires: PROC [file: LONG POINTER TO Text, iolisthead: Iolistpointer, networklisthead: Networklistpointer] ~ BEGIN
Iolistpin: Iolistpointer ← Wiolisthead;
Networklistentry: Networklistpointer ← networklisthead;
SignalList: LIST OF Nametype ← NIL;
PublicList: LIST OF Nametype ← NIL;
PadSignals: LIST OF Nametype ← NIL;
PublicsForThisCell: LIST OF Nametype ← NIL;
collect the public wires
WHILE (Iolistpin #NIL) DO BEGIN
IF ~NameOnList[Iolistpin^.Signalname, PublicList] THEN BEGIN
PublicList ← CONS[Iolistpin^.Signalname, PublicList];
END;
Iolistpin ← Iolistpin^.Link;
END ENDLOOP ;
collect the wires connected to the pads
WHILE (Networklistentry #NIL) DO BEGIN
IF NameOnList[Networklistentry^.Modulename, Pads] THEN BEGIN
Instancelistpin: Signallistpointer ← Networklistentry.Signallisthead;
WHILE (Instancelistpin #NIL) DO BEGIN
IF ~NameOnList[Instancelistpin^.Signalname, PadSignals] AND ~NameOnList[Instancelistpin^.Signalname, PublicList] THEN BEGIN
PadSignals ← CONS[Instancelistpin^.Signalname, PadSignals];
END;
Instancelistpin ← Instancelistpin^.Link;
END ENDLOOP;
END;
Networklistentry ← Networklistentry^.Link;
END ENDLOOP ;
write the public wires
PublicsForThisCell ← IF Wmodtype = Parent THEN PadSignals
ELSE PublicList;
PascalWriteLongString[file: @file^, item: "\tpubWires: Wire ← "];
IF (PublicsForThisCell = NIL) THEN
PascalWriteLongString[file: @file^, item: "NIL;\n"]
ELSE BEGIN
PascalWriteLongString[file: @file^, item: "CreateWire[LIST["];
FOR sl: LIST OF Nametype ← Reverse[PublicsForThisCell], sl.rest WHILE sl # NIL DO
PascalWriteLongString[file: @file^, item: "\""];
Printname[@file^, sl.first];
PascalWriteLongString[file: @file^, item: "\", "];
ENDLOOP;
PascalWriteLongString[file: @file^, item: "\"Vdd\", \"Gnd\"]];\n"];
END;
private wires
Networklistentry ← networklisthead;
PascalWriteLongString[file: @file^, item: "\tprivateWires: Wire ← "];
IF (Networklistentry = NIL) THEN
PascalWriteLongString[file: @file^, item: "NIL;\n"]
ELSE BEGIN
first: BOOLEANTRUE;
PascalWriteLongString[file: @file^, item: "CreateWire[LIST["];
WHILE (Networklistentry #NIL) DO BEGIN
IF ~NameOnList[Networklistentry^.Modulename, Pads] THEN BEGIN
Instancelistpin: Signallistpointer ← Networklistentry.Signallisthead;
WHILE (Instancelistpin #NIL) DO BEGIN
IF ~NameOnList[Instancelistpin^.Signalname, PublicsForThisCell] AND ~NameOnList[Instancelistpin^.Signalname, SignalList] THEN BEGIN
IF ~first THEN PascalWriteLongString[file: @file^, item: ", "];
first ← FALSE;
PascalWriteLongString[file: @file^, item: "\""];
Printname[@file^, Instancelistpin^.Signalname];
PascalWriteLongString[file: @file^, item: "\""];
SignalList ← CONS[Instancelistpin^.Signalname, SignalList];
END;
Instancelistpin ← Instancelistpin^.Link;
END; ENDLOOP;
END;
Networklistentry ← Networklistentry^.Link;
END ENDLOOP ;
PascalWriteLongString[file: @file^, item: "]];\n"];
END;
PascalWriteLongString[file: @file^, item: "\tinternWires: Wire ← UnionWire[pubWires, privateWires];\n"];
END;
WriteInstance: PROC [file: LONG POINTER TO Text, Currentnetworkentry: Networklistpointer] ~ BEGIN
Currentsignal: Signallistpointer;
PascalWriteLongString[file: @file^, item: "\t"];
Printname[@Woutputfile^, Currentnetworkentry.Instancename];
PascalWriteLongString[file: @file^, item: ": CellInstance ← CreateInstance[LIST["];
Currentsignal ← Currentnetworkentry^.Signallisthead;
WHILE (Currentsignal #NIL) DO BEGIN
PascalWriteLongString[file: @file^, item: "\""];
Printname[@Woutputfile^, Currentsignal^.Signalname];
PascalWriteLongString[file: @file^, item: "\", "];
Currentsignal ← Currentsignal^.Link;
END ENDLOOP ;
PascalWriteLongString[file: @file^, item: "\"Vdd\", \"Gnd\"], "];
Printname[@Woutputfile^, Currentnetworkentry^.Modulename];
PascalWriteLongString[file: @file^, item: "CellType, \""];
Printname[@Woutputfile^, Currentnetworkentry^.Instancename];
PascalWriteLongString[file: @file^, item: "\", internWires];\n"];
END;
WriteCell: PROC [file: LONG POINTER TO Text, CellName: Nametype] ~ BEGIN
PascalWriteLongString[file: @file^, item: "\t"];
Printname[@Woutputfile^, CellName];
PascalWriteLongString[file: @file^, item: "CellType: CellType ← CreateCoreFor"];
Printname[@Woutputfile^, CellName];
PascalWriteLongString[file: @file^, item: "[libDesign, coreLibrary];\n"];
END;
WriteInstances: PROC [file: LONG POINTER TO Text, networklisthead: Networklistpointer] RETURNS[Instances: LIST OF Nametype ← NIL] ~ BEGIN
Currentnetworkentry: Networklistpointer;
Cells: LIST OF Nametype ← NIL;
IF (networklisthead #NIL) THEN BEGIN
first gather the celltypes
Currentnetworkentry ← networklisthead;
WHILE (Currentnetworkentry #NIL) DO BEGIN
IF ~NameOnList[Currentnetworkentry^.Modulename, Cells] AND ~NameOnList[Currentnetworkentry^.Modulename, Pads] THEN
Cells ← CONS[Currentnetworkentry^.Modulename, Cells];
Currentnetworkentry ← Currentnetworkentry^.Link;
END ENDLOOP ;
next, write the instances and the cells
FOR cl: LIST OF Nametype ← Cells, cl.rest WHILE cl # NIL DO
WriteCell[@file^, cl.first];
Currentnetworkentry ← networklisthead;
WHILE (Currentnetworkentry #NIL) DO BEGIN
IF Nameequal[Currentnetworkentry^.Modulename, cl.first] THEN BEGIN
Instances ← CONS[Currentnetworkentry^.Instancename, Instances];
WriteInstance[@file^, Currentnetworkentry];
END;
Currentnetworkentry ← Currentnetworkentry^.Link;
END ENDLOOP ;
ENDLOOP;
END;
END;
WriteProcHeader: PROC [file: LONG POINTER TO Text, name: Nametype, modtype: Moduletype] ~ BEGIN
PascalWriteLongString[file: @file^, item: "\nCreateCoreFor"];
Printname [@file^, name];
PascalWriteLongString[file: @file^, item: ": PUBLIC PROC [libDesign: CD.Design, coreLibrary: Library] RETURNS [CellType] = BEGIN\n\t-- Create a Core CellType\n\t\n"];
IF modtype = Parent THEN
PascalWriteLongString[file: @file^, item: "\tgnd: CellType ← CreateCoreForGnd[libDesign, coreLibrary];\n\tvdd: CellType ← CreateCoreForVdd[libDesign, coreLibrary];\n"];
END;
WriteMesa
Pads ← RopesToNames[LIST["I1", "I2", "O1", "O2", "B21", "OUTPUTPAD", "INPUTPAD"]];
WriteProcHeader[@Woutputfile^, Wname, Wmodtype];
public and private wires
WriteWires[file: @Woutputfile^, iolisthead: Wiolisthead, networklisthead: Wnetworklisthead];
instances
InstanceList ← WriteInstances[file: @Woutputfile^, networklisthead: Wnetworklisthead];
PascalWriteLongString[file: @Woutputfile^, item: "\t"];
Printname[@Woutputfile^, Wname];
PascalWriteLongString[file: @Woutputfile^, item: "CellType: CellType ← CreateRecordCell[\""];
Printname[@Woutputfile^, Wname];
PascalWriteLongString[file: @Woutputfile^, item: "\", pubWires, internWires, "];
IF Wmodtype # Parent THEN
PascalWriteLongString[file: @Woutputfile^, item: "NIL];\n"]
ELSE BEGIN
PascalWriteLongString[file: @Woutputfile^, item: "LIST["];
Printname[@Woutputfile^, InstanceList.first];
FOR list: LIST OF Nametype ← InstanceList.rest, list.rest WHILE list # NIL DO
PascalWriteLongString[file: @Woutputfile^, item: ", "];
Printname[@Woutputfile^, list.first];
ENDLOOP;
PascalWriteLongString[file: @Woutputfile^, item: "]];\n"]
END;
PascalWriteLongString[file: @Woutputfile^, item: "\t[] ← Insert[coreLibrary, \""];
Printname[@Woutputfile^, Wname];
PascalWriteLongString[file: @Woutputfile^, item: "\", "];
Printname[@Woutputfile^, Wname];
PascalWriteLongString[file: @Woutputfile^, item: "CellType, TRUE];\n\tSetGet["];
Printname[@Woutputfile^, Wname];
PascalWriteLongString[file: @Woutputfile^, item: "CellType, libDesign];\n\tRETURN ["];
Printname[@Woutputfile^, Wname];
PascalWriteLongString[file: @Woutputfile^, item: "CellType];\n\tEND;\n"];
END; -- WriteMesa
WriteMesaHeader: PROCEDURE[
Woutputfile : LONG POINTER TO Text]
= BEGIN
program header
PascalWriteLongString[file: @Woutputfile^, item: "\n-- CreateCoreFor"];
PascalWriteLongString[file: @Woutputfile^, item: CircuitName];
PascalWriteLongString[file: @Woutputfile^, item: "Impl.mesa\n\t-- Copyright Ó 1988 by Xerox Corporation. All rights reserved.\n\t-- Bryan Preas May 4, 1988 3:33:03 pm PDT\n\nDIRECTORY\n\tCD, Core, CoreClasses, CoreDirectory, PWCore, RTTestUtil;\nCreateCoreFor"];
PascalWriteLongString[file: @Woutputfile^, item: CircuitName];
PascalWriteLongString[file: @Woutputfile^, item: "Impl: CEDAR PROGRAM\n\tIMPORTS CoreDirectory, PWCore, RTTestUtil\n\tEXPORTS RTTestUtil = BEGIN\n\tOPEN Core, CoreClasses, CoreDirectory, PWCore, RTTestUtil;\n\n"];
END; -- WriteMesaHeader
WriteMesaFooter: PROCEDURE[
Woutputfile : LONG POINTER TO Text]
= BEGIN
program footer
PascalWriteLongString[file: @Woutputfile^, item: "\n\t\n\tEND.\n"];
END; -- WriteMesaFooter
main body of pptest
ParseRun: UnsafeCommandProc = BEGIN
Linenumber: PascalInteger ← 1;
Done: PascalBoolean ← FALSE;
Modulenumber: PascalInteger ← 1;
CircuitName ← TerminalIO.RequestRope["Yal file to convert? "];
Open input and output files
Inputfile ← -- Pascal -- TextRESET[name: Rope.Cat[CircuitName, ".yal"]]^;
Outputfile ← -- Pascal -- TextREWRITE[name: Rope.Cat[CircuitName, ".mesa"]]^;
WriteMesaHeader[@Outputfile];
WHILE NOT Done DO BEGIN
Getmodule[@Inputfile, @Name^, @Modtype, @Width, @Height, @Iolisthead, @Networklisthead, @Placementlisthead, @Linenumber];
IF Modtype = Endfile THEN Done ← TRUE
ELSE BEGIN
-- Writemodule[@Outputfile, Name^, Modtype, Width, Height, Iolisthead, Networklisthead, Placementlisthead];
WriteMesa[@Outputfile, Name^, Modtype, Width, Height, Iolisthead, Networklisthead, Placementlisthead];
END;
Modulenumber ← Modulenumber +1;
END ENDLOOP ;
WriteMesaFooter[@Outputfile];
--Pascal -- CleanupFile[@Inputfile];
--Pascal -- CleanupFile[@Outputfile];
END;
PascalRegister["Parse", ParseRun];
END.