{from Jason at uiuc April 29, 1988}
{ ptest - test the Preas/Roberts placement language parser
Copyright (C) 1987 by Jonathan Rose. All rights reserved.
}
program TestParser(input,output);
{ 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 }
const MAXNAMESIZE = 100;
KEYWORDSIZE = 15;
{Module Type Constants}
STANDARD = 1;
PAD = 2;
GENERAL = 3;
PARENT = 4;
FEEDTHROUGH = 5;
ENDFILE = 6;
{ Unspecified Position and width on terminal constants }
NOPOSITION = -1.0;
NOWIDTH = -1.0;
{IO Pin type constants}
I = 1;
O = 2;
B = 3;
PI = 4;
PO = 5;
PB = 6;
F = 7;
{Pin side constants}
BOTTOM = 1;
RIGHT = 2;
TOP = 3;
LEFT = 4;
NOSIDE = 5;
{Layer type constants}
PDIFF = 1;
NDIFF = 2;
POLY = 3;
METAL1 = 4;
METAL2 = 5;
NOLAYER = 6;
{Reflection Type Constants}
RFLNONE = 1;
RFLY = 2;
{Rotation Type Constants}
ROT0 = 1;
ROT90 = 2;
ROT180 = 3;
ROT270 = 4;
{ Character strings that define the key words and comments }
{ Comment Delimiters }
STARTCOMMENT = '/* ';
ENDCOMMENT = '*/ ';
{ End of entry delimeter }
LineTerminator = ';';
{ Module Parameters }
ModuleKeyword = 'MODULE ';
EndModuleKeyword = 'ENDMODULE ';
TypeKeyword = 'TYPE ';
WidthKeyword = 'WIDTH ';
HeightKeyword = 'HEIGHT ';
{ IOList Delimiters }
IOListKeyword = 'IOLIST ';
EndIOListKeyword = 'ENDIOLIST ';
{ Network Delimiters }
NetworkKeyword = 'NETWORK ';
EndNetworkKeyword = 'ENDNETWORK ';
{ Placement Delimiters }
PlacementKeyword = 'PLACEMENT ';
EndPlacementKeyword = 'ENDPLACEMENT ';
{ Module Types }
StandardKeyword = 'STANDARD ';
PadKeyword = 'PAD ';
GeneralKeyword = 'GENERAL ';
ParentKeyword = 'PARENT ';
FeedthroughKeyword = 'FEEDTHROUGH ';
{ IOList Terminal Types }
InputTerminal = 'I ';
OutputTerminal = 'O ';
BiDirectionTerminal = 'B ';
PadInputTerminal = 'PI ';
PadOutputTerminal = 'PO ';
PadBiTerminal = 'PB ';
FeedThroughTerminal = 'F ';
{ Side Types }
BottomSide = 'BOTTOM ';
RightSide = 'RIGHT ';
TopSide = 'TOP ';
LeftSide = 'LEFT ';
{ Layer Types }
PDiffLayer = 'PDIFF ';
NDiffLayer = 'NDIFF ';
PolyLayer = 'POLY ';
Metal1Layer = 'METAL1 ';
Metal2Layer = 'METAL2 ';
{ Reflections }
NoReflection = 'RFLNONE ';
YReflection = 'RFLY ';
{ Rotations }
Rot0String = 'ROT0 ';
Rot90String = 'ROT90 ';
Rot180String = 'ROT180 ';
Rot270String = 'ROT270 ';
{Types Definitions}
type NameType = packed array [1..MAXNAMESIZE] of char;
{ Keyword Type is a smaller size due to the need in Pascal to pad blanks}
KeywordType = packed array [1..KEYWORDSIZE] of char;
ModuleType = STANDARD .. ENDFILE;
Number = real;
TerminalType = I .. F;
SideType = BOTTOM .. NOSIDE;
LayerType = PDIFF .. NOLAYER;
IOListPointer = ^IOList;
IOList = record
SignalName: NameType;
Terminal: TerminalType;
Side:SideType;
Position: Number;
Width: Number;
Layer: LayerType;
Link: IOListPointer;
end;
SignalListPointer = ^SignalList;
SignalList = record
SignalName: NameType;
Link:SignalListPointer;
end;
NetworkListPointer = ^NetworkList;
NetworkList = record
InstanceName: NameType;
ModuleName: NameType;
SignalListHead: SignalListPointer;
Link: NetworkListPointer;
end;
ReflectionType = RFLNONE .. RFLY;
RotationType = ROT0 .. ROT270 ;
PlacementListPointer = ^PlacementList;
PlacementList = record
InstanceName: NameType;
XLocation: Number;
YLocation: Number;
Reflection: ReflectionType;
Rotation: RotationType;
Link: PlacementListPointer;
end;
type FileNameType = packed array [1..100] of char;
var InputFile : text;
OutputFile: text;
Name: NameType;
ModType: ModuleType;
Width: Number;
Height: Number;
IOListHead: IOListPointer;
NetworkListHead: NetworkListPointer;
PlacementListHead: PlacementListPointer;
Done: boolean;
ModuleNumber: integer;
LineNumber: integer;
InputFileName : FileNameType;
OutputFileName: FileNameType;
procedure GetModule(var TInputFile: text;
var TName: NameType;
var TModType: ModuleType;
var TWidth: Number;
var THeight: Number;
var TIOListHead: IOListPointer;
var TNetworkListHead: NetworkListPointer;
var TPlacementListHead: PlacementListPointer;
var TLineNumber: integer);
{ Getmodule - routines for parsing the standard placement input form
specified by Preas and Roberts.
Copyright (C) 1987 by Jonathan Rose. All rights reserved.
}
{ Constants }
const FATAL = 1;
WARNING = 2;
BLANK = ' ';
TAB = ' ';
EOFConst = -1;
{ Global Variables }
var
InputField: NameType;
EOFDetected: boolean;
ExpectingEOF: boolean;
LineTerminated: boolean;
LLineNumber: integer;
{ Support Routines }
{ Error is called when an exception occurs - FATAL ones cause
an halt, while WARNINGS are just printed and execution continues }
procedure Error(EString: NameType; ErrorType: integer);
begin
if ErrorType = WARNING then write('Warning: ')
else write('Fatal Error: ');
writeln(EString,' on line ',LLineNumber,' of input file');
if ErrorType = FATAL then halt;
end;
{ kstrequal returns true if the two strings are the same, false otherwise }
function kstrequal(s1: KeywordType;s2: NameType): boolean;
var j: integer;
begin
j := 1;
kstrequal := true;
while (s1[j] = s2[j]) and (s1[j] <> BLANK) and (s2[j] <> BLANK)
do j := j + 1;
if s1[j] <> s2[j] then kstrequal := false;
end;
{ nstrcpy copies one name type into another }
procedure nstrcpy(var s1: NameType; s2: NameType);
var j: integer;
begin
j := 1;
while j <= MAXNAMESIZE do begin
s1[j] := s2[j];
j := j + 1;
end;
end;
{ nstrlen returns the length of the first string on nonblank characters
in the NameType string }
function nstrlen(s1: NameType): integer;
var j: integer;
begin
j := 1;
while not ((s1[j] = BLANK) or (s1[j] = chr(0))) do j := j + 1;
nstrlen := j - 1;
end;
{ ScanField picks up the next field, whilst counting the number of
lines that go by }
function ScanField (var InputFile: text; var SText:NameType): integer;
var NextChar: char;
TextP: integer;
{ Skip over blanks, tabs and newlines, counting newlines }
begin
if eof(InputFile) then
ScanField := EOFConst
else begin
read(InputFile,NextChar);
if not eof(InputFile) then
if eoln(InputFile) then LLineNumber := LLineNumber + 1;
while ((NextChar = BLANK) or (NextChar = TAB)) and (not eof(InputFile))
do begin
read(InputFile,NextChar);
if not eof(InputFile) then
if eoln(InputFile) then LLineNumber := LLineNumber + 1;
end;
if eof(InputFile) then
ScanField := EOFConst
else begin
TextP := 1;
SText[TextP] := NextChar;
TextP := TextP + 1;
{ Collect Characters until a white space or end of file }
read(InputFile,NextChar);
if not eof(InputFile) then
if eoln(InputFile) then LLineNumber := LLineNumber + 1;
while (NextChar <> BLANK) and (NextChar <> TAB) and
not eof(InputFile) do begin
SText[TextP] := NextChar;
TextP := TextP + 1;
read(InputFile,NextChar);
if not eof(InputFile) then
if eoln(InputFile) then LLineNumber := LLineNumber + 1;
end;
SText[TextP] := BLANK;
ScanField := 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. }
procedure GetField(var IFile: text; var GText: NameType);
var ErrFlag: integer;
begin
ErrFlag := ScanField(IFile,GText);
if (ErrFlag = EOFConst) and (not ExpectingEOF) then
Error('Unexpected End of File',FATAL)
else if (ErrFlag = EOFConst) and ExpectingEOF then
EOFDetected := true;
end;
{ ReadField reads a field from the input stream, ignoring comments }
procedure ReadField (var IFile: text; var RText: NameType);
var FieldLength: integer;
begin
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('Non-terminated Comment',FATAL);
GetField(IFile,RText);
end;
GetField(IFile,RText);
end;
{ Strip off the line terminator if it is attached to the field,
and set end of logical line indicator }
FieldLength := nstrlen(RText);
if RText[FieldLength] = LineTerminator then begin
LineTerminated := true;
RText[FieldLength] := BLANK;
end;
end;
{ ConvertToNumber does the conversion from ascii to a floating point
number }
function ConvertToNumber(CText: NameType): Number;
var CharPosition: integer;
SubTotal: Number;
ch: char;
NewDigit: Number;
DivFactor: Number;
begin
SubTotal := 0.0;
CharPosition := 1;
ch := CText[CharPosition];
while (ch <> BLANK) and (ch <> '.') do begin
if (ord(ch) < ord('0')) or (ord(ch) > ord('9')) then
Error('Illegal Number specified',FATAL)
else begin
NewDigit := ord(ch) - ord('0');
SubTotal := (SubTotal * 10.0) + NewDigit;
end;
CharPosition := CharPosition + 1;
ch := CText[CharPosition];
end;
DivFactor := 10.0;
if ch = '.' then begin
CharPosition := CharPosition + 1;
ch := CText[CharPosition];
while ch <> BLANK do begin
if (ord(ch) < ord('0')) or (ord(ch) > ord('9')) then
Error('Illegal Number specified',FATAL)
else begin
NewDigit := ord(ch) - ord('0');
SubTotal := SubTotal + NewDigit / DivFactor;
DivFactor := DivFactor * 10;
end;
CharPosition := CharPosition + 1;
ch := CText[CharPosition];
end;
end;
ConvertToNumber := SubTotal;
end;
{ Get Line Terminator looks for the line terminator as the next
field if it wasn't already encountered }
procedure GetLineTerminator(var IFile: text);
var TermField: NameType;
begin
if LineTerminated then
LineTerminated := false
else begin
ReadField(IFile,TermField);
if LineTerminated then LineTerminated := false
else Error('Missing Line Terminator (;)',FATAL);
end;
end;
{ GetIOList reads in the IO List }
procedure GetIOList(var IFile: text; var IOListHead: IOListPointer);
var IOField: NameType;
EndDetected: boolean;
NewIOPin: IOListPointer;
IOListTail: IOListPointer;
begin
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 }
new(NewIOPin);
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('Unknown Terminal Type Specification',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('Unknown Side Type Specification',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('Unknown Layer Specification', 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;
end;
procedure GetNetworkList(var IFile: text; var NetworkListHead: NetworkListPointer);
var NetworkField: NameType;
EndDetected: boolean;
SignalListEnd: boolean;
NewNetworkEntry, NetworkListTail: NetworkListPointer;
NewSignal, SignalListTail: SignalListPointer;
begin
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 }
new(NewNetworkEntry);
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 }
new(NewSignal);
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;
{ Link the new NetworkEntry }
if NetworkListHead = nil then
NetworkListHead := NewNetworkEntry
else
NetworkListTail^.Link := NewNetworkEntry;
NetworkListTail := NewNetworkEntry;
LineTerminated := false;
end;
end;
end;
procedure GetPlacementList(var IFile: text; var PlacementListHead: PlacementListPointer);
var PlacementField: NameType;
EndDetected: boolean;
NewPlacementEntry, PlacementListTail: PlacementListPointer;
begin
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 }
new(NewPlacementEntry);
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('Unknown Rotation or Reflection type',FATAL);
end;
end;
LineTerminated := false;
{ Link the new placement entry }
if PlacementListHead = nil then
PlacementListHead := NewPlacementEntry
else
PlacementListTail^.Link := NewPlacementEntry;
PlacementListTail := NewPlacementEntry;
end;
end;
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. }
begin { 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('Missing Module Declaration', FATAL)
else begin
ExpectingEOF := false;
ReadField(TInputFile,TName);
GetLineTerminator(TInputFile);
{ Get Type }
ReadField(TInputFile,InputField);
if not kstrequal(TypeKeyword,InputField) then
Error('Missing Type Declaration - Must be after MODULE', 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('Unknown Module Type Specification',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('Unknown Keyword',FATAL);
ReadField(TInputFile,InputField);
end;
GetLineTerminator(TInputFile);
end;
{ Update LineNumber }
TLineNumber := LLineNumber;
end; { GetModule }
procedure WriteModule(var WOutputFile: text;
WName: NameType;
WModType: ModuleType;
WWidth: Number;
WHeight: Number;
WIOListHead: IOListPointer;
WNetworkListHead: NetworkListPointer;
WPlacementListHead: PlacementListPointer);
{ Writemodule - routines for printing out a module in the format
specified by Preas and Roberts.
Copyright (C) 1987 by Jonathan Rose. All rights reserved.
}
var IOListPin: IOListPointer;
CurrentNetworkEntry: NetworkListPointer;
CurrentSignal: SignalListPointer;
CurrentPlacementEntry: PlacementListPointer;
procedure PrintKeyword(var OFile: text; Keyword: KeywordType);
const BLANK = ' ';
var CharPosition: integer;
begin
CharPosition := 1;
while not ((Keyword[CharPosition] = BLANK) or
(Keyword[CharPosition] = chr(0))) do begin
write(OFile,Keyword[CharPosition]);
CharPosition := CharPosition + 1;
end;
end;
procedure PrintName(var OFile: text; Name: NameType);
const BLANK = ' ';
var CharPosition: integer;
begin
CharPosition := 1;
while not ((Name[CharPosition] = BLANK) or
(Name[CharPosition] = chr(0))) do begin
write(OFile,Name[CharPosition]);
CharPosition := CharPosition + 1;
end;
end;
begin { WriteModule }
writeln(WOutputFile);
PrintKeyword (WOutputFile, ModuleKeyword);
write(WOutputFile,' ');
PrintName (WOutputFile, WName);
writeln(WOutputFile,';');
write(WOutputFile,' ');
PrintKeyword(WOutputFile,TypeKeyword);
write(WOutputFile,' ');
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
writeln(WOutputFile,'UNKNOWN!!!');
writeln(WOutputFile,';');
if (WWidth <> 0.0) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,WidthKeyword);
writeln(WOutputFile,' ',WWidth:1:1,';');
end;
if (WHeight <> 0.0) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,HeightKeyword);
writeln(WOutputFile,' ',WHeight:1:1,';');
end;
IOListPin := WIOListHead;
if (WIOListHead <> nil) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,IOListKeyword);
writeln(WOutputFile,';');
end;
while (IOListPin <> nil) do begin
write(WOutputFile,' ');
PrintName(WOutputFile,IOListPin^.SignalName);
write(WOutputFile,' ');
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
write(WOutputFile,'UNKNOWN!!! ');
if (IOListPin^.Side <> NOSIDE) then begin
if (IOListPin^.Side = BOTTOM) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,BottomSide);
end
else if (IOListPin^.Side = RIGHT) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,RightSide);
end
else if (IOListPin^.Side = TOP) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,TopSide);
end
else if (IOListPin^.Side = LEFT) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,LeftSide);
end
else
write(WOutputFile,'UNKNOWN!!!');
if (IOListPin^.Position <> NOPOSITION) then begin
write(WOutputFile,' ',IOListPin^.Position:1:1);
if (IOListPin^.Width <> NOWIDTH) then begin
write(WOutputFile,' ',IOListPin^.Width:1:1);
if (IOListPin^.Layer <> NOLAYER) then begin
write(WOutputFile,' ');
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,'UNKNOWN LAYER!!');
end;
end;
end;
end;
writeln(WOutputFile,';');
IOListPin := IOListPin^.Link;
end;
if (WIOListHead <> nil) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,EndIOListKeyword);
writeln(WOutputFile,';');
end;
if (WNetworkListHead <> nil) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,NetworkKeyword);
writeln(WOutputFile,';');
CurrentNetworkEntry := WNetworkListHead;
while (CurrentNetworkEntry <> nil) do begin
write(WOutputFile,' ');
PrintName(WOutputFile,CurrentNetworkEntry^.InstanceName);
write(WOutputFile,' ');
PrintName(WOutputFile,CurrentNetworkEntry^.ModuleName);
CurrentSignal := CurrentNetworkEntry^.SignalListHead;
while (CurrentSignal <> nil) do begin
write(WOutputFile,' ');
PrintName(WOutputFile,CurrentSignal^.SignalName);
CurrentSignal := CurrentSignal^.Link;
end;
writeln(WOutputFile,';');
CurrentNetworkEntry := CurrentNetworkEntry^.Link;
end;
write(WOutputFile,' ');
PrintKeyword(WOutputFile,EndNetworkKeyword);
writeln(WOutputFile,';');
end;
if (WPlacementListHead <> nil) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,PlacementKeyword);
writeln(WOutputFile,';');
CurrentPlacementEntry := WPlacementListHead;
while (CurrentPlacementEntry <> nil) do begin
write(WOutputFile,' ');
PrintName(WOutputFile,CurrentPlacementEntry^.InstanceName);
write(WOutputFile,' ',CurrentPlacementEntry^.XLocation:1:1,' ',
CurrentPlacementEntry^.YLocation:1:1);
if (CurrentPlacementEntry^.Reflection = RFLNONE) then
write(WOutputFile,' ')
else if (CurrentPlacementEntry^.Reflection = RFLY) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,YReflection);
end
else
write(WOutputFile,' UNKNOWN REFLECTION');
if (CurrentPlacementEntry^.Rotation = ROT0) then
write(WOutputFile,' ')
else if (CurrentPlacementEntry^.Rotation = ROT90) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,Rot90String);
end
else if (CurrentPlacementEntry^.Rotation = ROT180) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,Rot180String);
end
else if (CurrentPlacementEntry^.Rotation = ROT270) then begin
write(WOutputFile,' ');
PrintKeyword(WOutputFile,Rot270String);
end
else
write(WOutputFile,' UNKNOWN ROTATION');
writeln(WOutputFile,';');
CurrentPlacementEntry := CurrentPlacementEntry^.Link;
end;
{ writeln(WOutputFile,' ',EndPlacementKeyword,';'); BTP April 29, 1988 12:59:08 pm PDT }
write(WOutputFile,' ');
PrintKeyword(WOutputFile,EndPlacementKeyword);
writeln(WOutputFile,';');
end;
write(WOutputFile,' ');
PrintKeyword(WOutputFile,EndModuleKeyword);
writeln(WOutputFile,';');
end; { WriteModule }
begin { main body of pptest }
{ if argc < 2 then
writeln('Usage: ptest inputfile outputfile'); }
LineNumber := 1;
{ Open input and output files }
{ argv(1,InputFileName); }
{ argv(2,OutputFileName); }
reset(InputFile, InputFileName);
rewrite(OutputFile, OutputFileName);
Done := false;
ModuleNumber := 1;
while not Done do begin
GetModule(InputFile, Name, ModType, Width, Height, IOListHead,
NetworkListHead, PlacementListHead, LineNumber);
if ModType = ENDFILE then Done := true
else begin
writeln('Got Module ',ModuleNumber);
WriteModule(OutputFile, Name, ModType, Width, Height, IOListHead,
NetworkListHead, PlacementListHead);
end;
ModuleNumber := ModuleNumber + 1;
end;
end.