ExpertLibReadImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Christophe Cuenod, April 1, 1989 6:42:34 pm PST
Reads an Expert .lib file and retrieve from this file for each part entry the relative position of each pin.
DIRECTORY
Basics USING [BITAND, Int16FromH],
FS USING [StreamOpen],
IntHashTable USING [Create, Fetch, Insert, Table],
IO USING [EndOf, GetByte, GetHWord, GetRope, STREAM],
Rope USING [Cat, FromChar, ROPE],
ExpertLibRead;
ExpertLibReadImpl: CEDAR PROGRAM
IMPORTS Basics, FS, IntHashTable, IO, Rope
EXPORTS ExpertLibRead
~ BEGIN
ROPE: TYPE = Rope.ROPE;
PinPos: TYPE = ExpertLibRead.PinPos;
PartPinInfo: TYPE = ExpertLibRead.PartPinInfo;
LibTable: TYPE = ExpertLibRead.LibTable;
LibEntry: TYPE = ExpertLibRead.LibEntry;
LibEntryRep: TYPE = ExpertLibRead.LibEntryRep;
bufferSize: NAT = 20;
BufferRep: TYPE = RECORD[
size: NAT ← bufferSize,
lastentryindex: NAT,
table: ARRAY[0..bufferSize) OF BYTE
];
Buffer: TYPE = REF BufferRep;
Private procedures
CircularBufferPut: PROC [buffer: Buffer, i: BYTE] ~ {
buffer.lastentryindex ← buffer.lastentryindex + 1;
IF buffer.lastentryindex = bufferSize THEN buffer.lastentryindex ← 0;
buffer.table[buffer.lastentryindex] ← i;
};
CircularBufferGet: PROC [buffer: Buffer, offset: INT] RETURNS [i: BYTE] ~ {
index: INT;
index ← buffer.lastentryindex + offset;
IF index < 0 THEN index ← index + bufferSize;
IF index - bufferSize >= 0 THEN index ← index - bufferSize;
i ← buffer.table[index];
};
Skip: PROC [in: IO.STREAM, number: CARD] ~ {
WHILE number # 0 DO
[] ← IO.GetByte[in];
number ← number - 1;
ENDLOOP;
};
IsChar: PROC [i: BYTE] RETURNS [yes: BOOLEANFALSE] ~ {
IF i IN [ORD['A]..ORD['Z]] OR i IN [ORD['a]..ORD['z]] THEN yes ← TRUE;
};
IsNum: PROC [i: BYTE] RETURNS [yes: BOOLEANFALSE] ~ {
IF i IN [ORD['0]..ORD['9]] THEN yes ← TRUE;
};
IsAscii: PROC [i: BYTE] RETURNS [yes: BOOLEANFALSE] ~ {
IF i IN [020H..07FH] THEN yes ← TRUE;
};
GetFullPinsPosition: PROC [in: IO.STREAM] RETURNS [libEntry: LibEntry] ~ {
numberOfPins: NAT;
numberOfPins ← IO.GetByte[in];
Skip[in, 7];  -- Align with first pin entry
libEntry ← NEW[LibEntryRep[numberOfPins]];
FOR i: NAT IN [0..numberOfPins) DO
libEntry.partPinInfo[i].pinPos.x ← Basics.Int16FromH[IO.GetHWord[in]];
libEntry.partPinInfo[i].pinPos.y ← - Basics.Int16FromH[IO.GetHWord[in]];
Skip[in, 1];
libEntry.partPinInfo[i].diameter ← IO.GetByte[in];
FillRemainingOfPartPinInfo[libEntry, i, in];
ENDLOOP;
};
GetAbreviatedPinsPosition: PROC [in: IO.STREAM] RETURNS [libEntry: LibEntry] ~ {
numberOfPins, diameter: NAT;
deltax, deltay: CARD;
numberOfPins ← IO.GetByte[in];
Skip[in, 11];  -- Align with deltas
deltay ← Basics.Int16FromH[IO.GetHWord[in]];  -- Find delta y
deltax ← Basics.Int16FromH[IO.GetHWord[in]];  -- Find delta x
Skip[in, 1];
diameter ← IO.GetByte[in];
libEntry ← NEW[LibEntryRep[numberOfPins]];
IF (numberOfPins MOD 2) # 0 THEN ERROR;
FOR i: NAT IN [0..numberOfPins/2) DO
libEntry.partPinInfo[i].pinPos.x ← 0;
libEntry.partPinInfo[i].pinPos.y ← -(deltay * i);
libEntry.partPinInfo[i].diameter ← diameter;
FillRemainingOfPartPinInfo[libEntry, i, in];
ENDLOOP;
FOR i: NAT IN [numberOfPins/2..numberOfPins) DO
libEntry.partPinInfo[i].pinPos.x ← deltax;
libEntry.partPinInfo[i].pinPos.y ← deltay * (1+i-numberOfPins);
libEntry.partPinInfo[i].diameter ← diameter;
FillRemainingOfPartPinInfo[libEntry, i, in];
ENDLOOP;
};
FillRemainingOfPartPinInfo: PROC [libEntry: LibEntry, pin: NAT, in: IO.STREAM] ~ {
temp, pinNameLength: NAT;
libEntry.partPinInfo[pin].site ← IO.GetByte[in] + 1;
libEntry.partPinInfo[pin].padStack ← IO.GetByte[in];
libEntry.partPinInfo[pin].swap ← IO.GetByte[in];
temp ← IO.GetByte[in];
libEntry.partPinInfo[pin].type ← temp/16;
pinNameLength ← Basics.BITAND[temp, 00FH]; --Low digit is significant
IF pinNameLength = 0 THEN pinNameLength ← 16;
libEntry.partPinInfo[pin].name ← IO.GetRope[in, pinNameLength];
};
TryMatch: PROC [buffer: Buffer, libTable: IntHashTable.Table, in: IO.STREAM] ~ {
c: BYTE;
partName: ROPE ← NIL;
partNumberLength: CARD;
pinNumberingType: INT;
libEntry: LibEntry;
entryLength, entryNumber: CARD;
nameLength: BYTE ← CircularBufferGet[buffer, 0];
entryLength ← CircularBufferGet[buffer, -5];
entryLength ← entryLength * 256 + CircularBufferGet[buffer, -4];
IF entryLength < 20 THEN RETURN;  -- Impossible to have a so short entry
entryNumber ← CircularBufferGet[buffer, -7];
entryNumber ← entryNumber * 256 + CircularBufferGet[buffer, -6];
entryNumber ← entryNumber * 256 + CircularBufferGet[buffer, -9];
entryNumber ← entryNumber * 256 + CircularBufferGet[buffer, -8];
IF nameLength = 0 THEN RETURN;
WHILE nameLength # 0 DO
c ← IO.GetByte[in];
IF NOT IsAscii[c] THEN RETURN;
partName ← Rope.Cat[partName, Rope.FromChar[LOOPHOLE[c]]];
nameLength ← nameLength-1;
ENDLOOP;
pinNumberingType ← Basics.Int16FromH[IO.GetHWord[in]];
Skip[in, 38];  -- Align with pin number
SELECT pinNumberingType FROM
= 0 => { -- Implied position of the pins
libEntry ← GetAbreviatedPinsPosition[in];
};
= 1 => { -- Full x and y position for each pin
libEntry ← GetFullPinsPosition[in];
};
ENDCASE => RETURN;
Skip[in, 1]; -- Align with "Part number"
partNumberLength ← IO.GetByte[in];
libEntry.partNumber ← IO.GetRope[in, partNumberLength];
libEntry.partName ← partName;
[] ← IntHashTable.Insert[libTable, entryNumber, libEntry];
};
Public Procedures
ReadLibFile: PUBLIC PROC [file: Rope.ROPE] RETURNS [libTable: LibTable] ~ {
Creates libTable from the input file
buffer: Buffer ← NEW[BufferRep];
in: IO.STREAMFS.StreamOpen[file];
libTable ← IntHashTable.Create[];
WHILE NOT IO.EndOf[in] DO
CircularBufferPut[buffer, IO.GetByte[in]];
A caracteristic pattern of a part is 00 07 00 followed by the lenght of the name (#0)
IF CircularBufferGet[buffer, -2] = 7 AND
CircularBufferGet[buffer, -3] = 0 AND
CircularBufferGet[buffer, -1] = 0 AND
CircularBufferGet[buffer, 0] # 0 THEN TryMatch[buffer, libTable, in];
ENDLOOP;
};
PartName: PUBLIC PROC [libTable: LibTable, entryNumber: CARD] RETURNS [partName: Rope.ROPE] ~{
libEntry: LibEntry;
libEntry ← NARROW[IntHashTable.Fetch[libTable, entryNumber].value];
partName ← libEntry.partName;
};
PartNumber: PUBLIC PROC [libTable: LibTable, entryNumber: CARD] RETURNS [partNumber: Rope.ROPE] ~{
libEntry: LibEntry;
libEntry ← NARROW[IntHashTable.Fetch[libTable, entryNumber].value];
partNumber ← libEntry.partNumber;
};
PinNumber: PUBLIC PROC [libTable: LibTable, entryNumber: CARD] RETURNS [pinNumber: NAT] ~{
gives the number of pins of an entry
libEntry: LibEntry;
libEntry ← NARROW[IntHashTable.Fetch[libTable, entryNumber].value];
pinNumber ← libEntry.size;
};
RelativePinPosition: PUBLIC PROC [libTable: LibTable, entryNumber: CARD, pin: NAT] RETURNS [pinPos: PinPos] ~{
gives the relative position of any pin for an unrotated entry
libEntry: LibEntry;
libEntry ← NARROW[IntHashTable.Fetch[libTable, entryNumber].value];
pinPos ← libEntry.partPinInfo[pin-1].pinPos;
};
FirstPinOfThisType: PUBLIC PROC [libTable: LibTable, entryNumber: CARD, type: NAT, swap: NAT] RETURNS [pinNumber: NAT ← 0] ~{
index: NAT ← 0;
libEntry: LibEntry;
libEntry ← NARROW[IntHashTable.Fetch[libTable, entryNumber].value];
WHILE index < libEntry.size DO
IF libEntry.partPinInfo[index].type = type AND libEntry.partPinInfo[index].swap = swap THEN {
pinNumber ← index + 1;
EXIT;
};
index ← index + 1;
ENDLOOP;
};
IsPinOfThisType: PUBLIC PROC [libTable: LibTable, entryNumber: CARD, pinNumber: CARD, type: NAT, swap: NAT] RETURNS [yes: BOOLEANFALSE] ~{
libEntry: LibEntry ← NARROW[IntHashTable.Fetch[libTable, entryNumber].value];
IF libEntry.partPinInfo[pinNumber - 1].type = type
AND libEntry.partPinInfo[pinNumber - 1].swap = swap THEN yes ← TRUE;
};
END.