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:
ROPE ←
NIL]
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:
ROPE ←
NIL]
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;
{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: BOOLEAN ← TRUE;
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.