File: Pga257.mesa
Christophe Cuenod January 15, 1988 2:49:54 pm PST

Enables to generate easily 257 pins PGA parts for EXPERT (Sparc or FPU).
Requires one input file: Filename.pins and generates two files Filename.A.part and Filename.B.part (to be transformed by the NewPart program).
The file has to be 256 lines long exactly. Each line has to content either NC, VCC, GND or PinName PinType (I, O, D, ...) and SwapNumber. (i.e. K5 D 5)
The pads stacks are:
- pin 1       stack 8
- corners       stack 10
- power or gnd       stack 12
- nul pin       stack 11
- remaining      stack 9
DIRECTORY
Commander USING [CommandProc, Register],
Rope USING [Cat, Equal, ROPE],
FS USING [StreamOpen],
IO USING [ BreakProc, card, Close, EndOfStream, GetCard, GetTokenRope, PutF, RIS, rope, STREAM];
Pga257: CEDAR PROGRAM
IMPORTS IO, Commander, Rope, FS =
BEGIN
ROPE: TYPE = Rope.ROPE;
PGAPinsRep: TYPE = ARRAY[1..19] OF ARRAY[1..19] OF ROPE;
PGAPins: TYPE = REF PGAPinsRep;
Pos: TYPE = RECORD [
x: CARD,
y: CARD
];
Line: TYPE = RECORD [
name: ROPE,
type: CARD,
swap: CARD
];
BadFile: SIGNAL [];
Position: PROC [i: CARD] RETURNS [position: Pos] ~ {
SELECT i FROM
IN [1..19] => {
position.x ← 0;
position.y ← 100*(i-1);
};
IN [20..37] => {
position.x ← 100*(i-19);
position.y ← 1800;
};
IN [38..55] => {
position.x ← 1800;
position.y ← 100*(55-i);
};
IN [56..72] => {
position.x ← 100*(73-i);
position.y ← 0;
};
IN [73..89] => {
position.x ← 100;
position.y ← 100*(i-72);
};
IN [90..105] => {
position.x ← 100*(i-88);
position.y ← 1700;
};
IN [106..121] => {
position.x ← 1700;
position.y ← 100*(122-i);
};
IN [122..136] => {
position.x ← 100*(138-i);
position.y ← 100;
};
IN [137..151] => {
position.x ← 200;
position.y ← 100*(i-135);
};
IN [152..165] => {
position.x ← 100*(i-149);
position.y ← 1600;
};
IN [166..179] => {
position.x ← 1600;
position.y ← 100*(181-i);
};
IN [180..192] => {
position.x ← 100*(195-i);
position.y ← 200;
};
IN [193..205] => {
position.x ← 300;
position.y ← 100*(i-190);
};
IN [206..217] => {
position.x ← 100*(i-202);
position.y ← 1500;
};
IN [218..229] => {
position.x ← 1500;
position.y ← 100*(232-i);
};
IN [230..240] => {
position.x ← 100*(244-i);
position.y ← 300;
};
Last raw
IN [241..244] => {
position.x ← 400;
position.y ← 600 +200*(i-241);
};
IN [245..248] => {
position.x ← 600+200*(i-245);
position.y ← 1400;
};
IN [249..252] => {
position.x ← 1400;
position.y ← 1200-200*(i-249);
};
IN [253..256] => {
position.x ← 1200-200*(i-253);
position.y ← 400;
};
ENDCASE => ERROR;
};
TokenBreak: IO.BreakProc ~ {
IF char = ' OR char = '\t OR char = '\n THEN RETURN [sepr];
RETURN [other];
};
GetLine: PROC [in: IO.STREAM, display: IO.STREAM, i: CARD, file: ROPE] RETURNS [line: Line] ~ {
type: ROPE;
line.name ← IO.GetTokenRope[in, TokenBreak ! IO.EndOfStream => CONTINUE].token;
IF line.name = NIL THEN {
IO.PutF[display, "File %g is too short: line %g is missing.\n",
IO.rope[file], IO.card[i]];
SIGNAL BadFile[];
};
SELECT TRUE FROM
Rope.Equal[line.name, "nc", FALSE] =>{
line.name ← "NC";
line.type ← 0; --Unspecified
line.swap ← 1;
};
Rope.Equal[line.name, "vcc", FALSE] OR Rope.Equal[line.name, "vdd", FALSE] =>{
line.name ← "VCC";
line.type ← 4; --Power
line.swap ← 1;
};
Rope.Equal[line.name, "gnd", FALSE] OR Rope.Equal[line.name, "vss", FALSE] =>{
line.name ← "GND";
line.type ← 5; --Ground
line.swap ← 1;
};
ENDCASE => {
type ← IO.GetTokenRope[in ! IO.EndOfStream => CONTINUE].token;
SELECT TRUE FROM
Rope.Equal[type, "i", FALSE] => line.type ← 1; --input
Rope.Equal[type, "o", FALSE] => line.type ← 2; --output
Rope.Equal[type, "d", FALSE] => line.type ← 3; --duplex
ENDCASE => {
IO.PutF[display, "The Second word on line %g has to be I,O or D instead of %g\n",
IO.card[i], IO.rope[type]];
SIGNAL BadFile[];
};
line.swap ← IO.GetCard[in ! IO.Error[SyntaxError] => CONTINUE];
line.swap ← IO.GetCard[in];
};
};
InsertPin: PROC [out: IO.STREAM, position: Pos, i: CARD, line: Line] ~ {
IO.PutF[out, "%g %g %g %g 19 ", IO.card[position.x], IO.card[position.y], IO.rope[line.name], IO.card[line.swap]];
IF line.type = 1 OR line.type = 2 OR line.type = 3 THEN IO.PutF[out, "1 %g", IO.card[line.type]]
ELSE IO.PutF[out, "256 %g", IO.card[line.type]];
IF i = 1 THEN IO.PutF[out, " 8\n"] --Pad stack for pin 1
ELSE IF i = 19 OR i = 37 OR i = 55 THEN IO.PutF[out, " 10\n"] --Corner Pad stack
ELSE IF line.type = 4 OR line.type = 5 THEN IO.PutF[out, " 12\n"] --Power Pad stack
ELSE IO.PutF[out, " 9\n"]; --Pad stack for standard pin
};
Pga257Proc: Commander.CommandProc = BEGIN
fault: BOOLEANFALSE;
i: CARD ← 1;
in: IO.STREAM;
out: IO.STREAM;
stream: IO.STREAMIO.RIS[cmd.commandLine];
fileName: ROPEIO.GetTokenRope[stream].token;
in ← FS.StreamOpen[Rope.Cat[fileName,".pin"]];
out ← FS.StreamOpen[Rope.Cat[fileName,".A.part"],$create];
IO.PutF[out, "4096 2048 -550 -300 2050 2200 700 -150 %g-A PARC-%g-A U\n",
IO.rope[fileName], IO.rope[fileName]];
WHILE i IN [1..255] DO
InsertPin[out, Position[i], i, GetLine[in, cmd.out, i, Rope.Cat[fileName,".pin"] ! BadFile => {
i ← 256;
fault ← TRUE;
CONTINUE;
}]];
i ← i+1;
ENDLOOP;
IO.Close[out];
IF ~ fault THEN {
out ← FS.StreamOpen[Rope.Cat[fileName,".B.part"],$create];
IO.PutF[out, "4096 2048 -550 -300 2050 2200 1100 -150 %g-B PARC-%g-B U\n",
IO.rope[fileName], IO.rope[fileName]];
IO.PutF[out, "0 0 DUMMY 1 0 256 0 11\n"];
InsertPin[out, Position[256], 256, GetLine[in, cmd.out, 256, Rope.Cat[fileName,".pin"] ! BadFile => {
fault ← TRUE;
CONTINUE;
}]];
IO.PutF[out, "400 400 INDEX 1 0 256 0 9\n"];
IO.Close[out];
};
IF ~ fault THEN {
IO.PutF[cmd.out, "Files %g.A.part and %g.B.part Written\n", IO.rope[fileName], IO.rope[fileName]];
};
END;
Commander.Register[
key: "Pga257", proc: Pga257Proc, doc: "Transform the input file: Filename.pins into Filename.A.part and Filename.B.part (to be used by the NewPart program)."];
END.