-- File DisjointIO.mesa
-- Get input from Magic database and make direct calls on Disjoint
-- translates and rotates are removed on the fly
-- also has routines to output CIF
-- Written by Martin Newell/Dan Fitzpatrick, March 1981
-- Last updated (Pilot): August 27, 1981 3:34 PM
DIRECTORY
AuxIntDefs: FROM "AuxIntDefs" USING [IExpand, IGetRootID, IGetFirstSymbol,
IGetNextSymbol, IStop, ISymBB],
AuxOutputDefs: FROM "AuxOutputDefs",
DisjointIODefs: FROM "DisjointIODefs",
DisjointAllocDefs: FROM "DisjointAllocDefs" USING
[MakeSymbol, MakeInstance, MakeGeometry, AllocateRectangle, FreeRectangle, EnumerateSymbols],
DisjointPropDefs: FROM "DisjointPropDefs" USING [AllocPropID, PutProp, GetProp],
DisjointTypes: FROM "DisjointTypes" USING [DisCell, Symbol, Rectangle, Instance, Geometry, PIP, PropID],
Inline: FROM "Inline" USING [LowHalf, BITSHIFT, BITAND],
IntDefs: FROM "IntDefs" USING [IBoundBox],
IntStorageDefs: FROM "IntStorageDefs" USING [ObjectName, NilObjectName],
IntTransDefs: FROM "IntTransDefs" USING [Transform, TransformRecord],
IODefs: FROM "IODefs" USING [CR, WriteLine, WriteString, WriteDecimal,
WriteChar, GetOutputStream, SetOutputStream],
JaMFnsDefs: FROM "JaMFnsDefs" USING [GetJaMBreak, SetJaMBreak],
ParserTypeDefs: FROM "ParserTypeDefs" USING [Point, Path],
Real: FROM "Real" USING [Fix, WriteReal],
StreamDefs: FROM "StreamDefs" USING [StreamHandle, NewByteStream, Append, Write],
String: FROM "String" USING[AppendDecimal, AppendLongDecimal],
SystemDefs: FROM "SystemDefs" USING [AllocateHeapNode, FreeHeapNode];
DisjointIO: PROGRAM
IMPORTS AuxIntDefs, DisjointAllocDefs, DisjointPropDefs, Inline, IntDefs, IODefs, JaMFnsDefs, Real, StreamDefs, String, SystemDefs
EXPORTS DisjointIODefs, AuxOutputDefs =
BEGIN OPEN AuxIntDefs, AuxOutputDefs, DisjointAllocDefs, DisjointPropDefs, DisjointTypes, Inline, IntDefs, IntStorageDefs, IntTransDefs, IODefs, JaMFnsDefs, ParserTypeDefs, Real, StreamDefs, String, SystemDefs;
CIFInput: PUBLIC PROCEDURE[allSymbols: BOOLEAN, parent: Symbol] =
--Get layout from Magic database and make direct calls on Disjoint
--allSymbols is true for ALL symbols, false for REFERENCED only
--mainline will be hung on parent
BEGIN
symbol: ObjectName;
cifNum: CARDINAL;
orient: CARDINAL;
ParentSymbol ← parent;
Aborted ← FALSE;
InitDict[256];
IF allSymbols THEN --get handle on all symbols, even if not referenced
{FOR s:ObjectName ← IGetFirstSymbol[],IGetNextSymbol[]
UNTIL s=NilObjectName DO
[] ← Lookup[s, 0];
ENDLOOP;
};
--provoke initial entries in dictionary
ScanningTopLevel ← TRUE;
Rotation ← 0;
Mirror ← FALSE;
IExpand[IGetRootID[]];
IF Aborted THEN
{Abort[];
RETURN;
};
ScanningTopLevel ← FALSE;
--output symbols
DoHeader[];
[symbol,orient,cifNum] ← GetNonProcessedEntry[];
UNTIL cifNum=0 DO
DoSymbolHeader[symbol,orient];
IExpand[symbol];
IF Aborted THEN
{Abort[];
RETURN;
};
DoSymbolTrailer[symbol];
[symbol,orient,cifNum] ← GetNonProcessedEntry[];
ENDLOOP;
--output mainline
CurrentSymbol ← ParentSymbol;
Rotation ← 0;
Mirror ← FALSE;
IExpand[IGetRootID[]];
IF Aborted THEN
{Abort[];
RETURN;
};
DoTrailer[];
FreeDict[];
END;
Abort: PROCEDURE[] =
BEGIN
WriteLine["***Aborted***"];
DoTrailer[];
FreeDict[];
END;
DoHeader: PROCEDURE =
BEGIN
l,b,r,t: LONG INTEGER;
rec,next: Rectangle;
window: Rectangle ← AllocateRectangle[];
--set window of parent to be BB of whole layout
[l,r,b,t] ← IBoundBox[];
window↑ ← [
next: NIL,
l:l, b:b, r:r, t:t
];
FOR rec ← ParentSymbol.windows, next UNTIL rec=NIL DO
next ← rec.next;
FreeRectangle[rec];
ENDLOOP;
ParentSymbol.windows ← window;
CurrentLayer ← 32000; --i.e. not set
END;
DoTrailer: PROCEDURE =
BEGIN
END;
DoSymbolHeader: PROCEDURE [symbol: ObjectName, orient: CARDINAL] =
BEGIN
n: INTEGER;
name: STRING ← [20];
l,b,r,t: LONG INTEGER;
--set up current Rotation and Mirror from orient
Rotation ← BITSHIFT[orient,-1];
Mirror ← BITAND[orient,1]#0;
n ← Lookup[symbol,orient];
name.length ← 0;
AppendDecimal[name,n];
[l,r,b,t] ← ISymBB[symbol];
--Rotate and mirror bb
[l,b] ← RotMirXY[Rotation, Mirror, l,b];
[r,t] ← RotMirXY[Rotation, Mirror, r,t];
CurrentSymbol ← MakeSymbol[name, MIN[l,r],MIN[b,t],MAX[l,r],MAX[b,t]];
SaveLayer ← CurrentLayer;
CurrentLayer ← 32000;
END;
DoSymbolTrailer: PROCEDURE[symbol: ObjectName] =
BEGIN
CurrentLayer ← SaveLayer;
END;
--Orientation is packed as a 3 bit field, [0..3][0..1] representing ccw rotation in units of 90 degrees, and mirroring of the x coordinate. These are considered to be applied to the object in the order: mirror, rotation.
Rotation: CARDINAL; --current ccw rotation of symbol being expanded
Mirror: BOOLEAN; --current mirror status of symbol being expanded
--Procedures that export AuxOutputDefs--
AuxWire: PUBLIC PROCEDURE [layerName: CARDINAL, width: LONG CARDINAL, a: ParserTypeDefs.Path] =
BEGIN
WriteLine["Wire not implemented in CIFDJ"];
END;
AuxFlash: PUBLIC PROCEDURE [layerName: CARDINAL, diameter: LONG CARDINAL, center: ParserTypeDefs.Point] =
BEGIN
WriteLine["Flash not implemented in CIFDJ"];
END;
AuxPolygon: PUBLIC PROCEDURE [layerName: CARDINAL, a: ParserTypeDefs.Path] =
BEGIN
WriteLine["Polygon not implemented in CIFDJ"];
END;
AuxBox: PUBLIC PROCEDURE [layerName: CARDINAL, length, width: LONG CARDINAL,
center: ParserTypeDefs.Point, xRotation, yRotation: LONG INTEGER] =
BEGIN
len,wid,length2,width2: LONG CARDINAL;
xc,yc: LONG INTEGER;
rot: BOOLEAN;
IF GetJaMBreak[] THEN
{IStop[];
SetJaMBreak[FALSE];
Aborted ← TRUE;
RETURN;
};
IF ScanningTopLevel THEN RETURN;
IF yRotation#0 AND xRotation#0 THEN
{WriteLine["CIFDisjoint - oblique rectangles not implemented"];
RETURN;
};
SetLayer[layerName];
rot ← ((Rotation=0 OR Rotation=2) AND yRotation#0) OR
((Rotation=1 OR Rotation=3) AND yRotation=0); --xor
IF rot THEN {len ← width; wid ← length; }
ELSE {len ← length; wid ← width; };
[xc,yc] ← RotMirXY[Rotation, Mirror, center.x,center.y];
length2 ← len/2;
IF length2+length2<len THEN length2 ← length2 + 1;
width2 ← wid/2;
IF width2+width2<wid THEN width2 ← width2 + 1;
[] ← MakeGeometry[CurrentSymbol, CurrentLayer,
xc-length2,yc-width2,xc+length2,yc+width2];
END;
AuxUserObject: PUBLIC PROCEDURE [layerName: CARDINAL,
size: CARDINAL, data: POINTER TO UNSPECIFIED] =
BEGIN
END;
AuxCall: PUBLIC PROCEDURE [symbol: ObjectName, cifNumber: LONG CARDINAL, transform: Transform] =
BEGIN
save: StreamHandle ← GetOutputStream[];
t: TransformRecord;
mx: BOOLEAN ← FALSE;
rot: INTEGER ← 0;
tx: LONG INTEGER ← 0;
ty: LONG INTEGER ← 0;
orient: INTEGER;
c,s: REAL;
cifNum: INTEGER;
name: STRING ← [20];
--unpick transform in [tran][rot][mx]<object>
t ← transform↑;
--get local mirror
IF (t.a11*t.a22-t.a21*t.a12)<0 THEN --determinant negative - need mirror
{t.a11 ← -t.a11;
t.a12 ← -t.a12;
mx ← TRUE;
};
--get local rotate
c ← t.a11/t.a33;
s ← t.a12/t.a33;
IF s#0 OR c<0 THEN
{SELECT TRUE FROM
c=0=> rot ← IF s<0 THEN 3 ELSE 1;
s=0=> rot ← IF c<0 THEN 2 ELSE 4;
ENDCASE =>
WriteLine["CIFDJ can’t handle non-90 degree rotations"];
};
--get local translation
IF t.a31#0 OR t.a32#0 THEN {tx ← Fix[t.a31/t.a33]; ty ← Fix[t.a32/t.a33];};
--compose local transformation with current Rotation and Mirror
IF Mirror THEN
{rot ← (4-rot) MOD 4;
mx ← NOT mx;
};
IF Rotation#0 THEN rot ← (rot + Rotation) MOD 4;
[tx,ty] ← RotMirXY[Rotation, Mirror, tx,ty];
orient ← (rot + rot) + (IF mx THEN 1 ELSE 0);
--look up symbol, either to make initial entry or to use it
cifNum ← Lookup[symbol,orient]; --need to do this always
IF ScanningTopLevel THEN RETURN;
--output call with only translate
name.length ← 0;
AppendDecimal[name,cifNum];
[] ← MakeInstance[CurrentSymbol, name, tx,ty];
END;
two22: LONG INTEGER ← 20000000B;
SetLayer: PUBLIC PROCEDURE [layerName: CARDINAL] =
BEGIN
CurrentLayer ← layerName;
END;
RotMirXY: PROCEDURE [r: INTEGER, m: BOOLEAN, x,y: LONG UNSPECIFIED]
RETURNS[LONG UNSPECIFIED,LONG UNSPECIFIED] =
-- mirror x,y in x if m TRUE, then rotate result by r*90 degrees
--works for both REAL and LONG INTEGER for x and y
BEGIN
IF m THEN x ← -x;
SELECT r FROM
0 => RETURN[x,y];
1 => RETURN[-y,x];
2 => RETURN[-x,-y];
3 => RETURN[y,-x];
ENDCASE =>
{x1,y1: LONG UNSPECIFIED;
[x1,y1] ← RotMirXY[r MOD 4, FALSE, x,y];
RETURN[x1,y1];
};
END;
--Dictionary
--Each entry in the dictionary has an ObjectName for a key, and an array of CARDINALs for values. On Lookup, both the ObjectName and an index are provided, and the indexed entry in the corresponding entry is returned as the value
DictEntry: TYPE = POINTER TO DictEntryRecord;
DictEntryRecord: TYPE = RECORD [
next: DictEntry,--global list in order in which entries are made
ovflow: DictEntry,--overflow list from entry in hash table
key: ObjectName,--internal ID of symbol
value: ARRAY [0..7] OF INTEGER--generated CIF symbols # for output, one for each possible rotation and mirroring. -ve means not yet processed and symbol is -.value[i], 0 means unset
];
DictHead: DictEntry;
DictTail: DictEntry;
HTable: DESCRIPTOR FOR ARRAY OF DictEntry;
LastProcessedEntry: DictEntry; --points to last processed entry
Value: CARDINAL;
InitDict: PROCEDURE[hashlength: CARDINAL] =
BEGIN
i: CARDINAL;
DictHead ← NIL;
DictTail ← NIL;
HTable ←
DESCRIPTOR[AllocateHeapNode[hashlength*SIZE[DictEntry]],hashlength];
FOR i IN [0..hashlength) DO HTable[i] ← NIL; ENDLOOP;
LastProcessedEntry ← NIL;
Value ← 0;
END;
Lookup: PROCEDURE[key: ObjectName, index: CARDINAL] RETURNS[INTEGER] =
--Return value[index] associated with key. If key not found, or
-- value[index] not set, then generate a value, and return it.
BEGIN
de: DictEntry;
h: CARDINAL;
[de,h] ← Where[key];
IF de=NIL THEN
{de ← AllocateHeapNode[SIZE[DictEntryRecord]];
de↑ ← [
next: NIL,
ovflow: HTable[h],
key: key,
value: ALL[0]];
HTable[h] ← de;
IF DictTail=NIL THEN DictHead ← DictTail ← de
ELSE
{DictTail.next ← de;
DictTail ← de;
};
};
IF de.value[index]=0 THEN
{Value ← Value + 1;
de.value[index] ← -Value; --sign bit used to indicate not yet expanded
};
RETURN[ABS[de.value[index]]];
END;
GetNonProcessedEntry: PROCEDURE
RETURNS[key: ObjectName, index: CARDINAL, value: CARDINAL] =
--Search all entries, starting at LastProcessedEntry, and return its key, index, and value, if any, having marked it as processed
BEGIN
startEntry: DictEntry ← LastProcessedEntry;
DO
--check LastProcessedEntry to see if it contains any unprocessed element
IF LastProcessedEntry#NIL THEN
{FOR i:CARDINAL IN [0..7] DO
IF LastProcessedEntry.value[i]<0 THEN
{LastProcessedEntry.value[i] ← -LastProcessedEntry.value[i];
RETURN[LastProcessedEntry.key, i, LastProcessedEntry.value[i]];
};
ENDLOOP;
};
--step LastProcessedEntry by one
IF LastProcessedEntry=NIL THEN LastProcessedEntry ← DictHead
ELSE LastProcessedEntry ← LastProcessedEntry.next;
--
IF LastProcessedEntry=startEntry THEN
RETURN[NilObjectName,0,0]; --been all round
ENDLOOP;
END;
FreeDict: PROCEDURE =
BEGIN
de,nextde: DictEntry;
FOR de ← DictHead, nextde UNTIL de=NIL DO
nextde ← de.next;
FreeHeapNode[de];
ENDLOOP;
FreeHeapNode[BASE[HTable]];
END;
Where: PROCEDURE[key: ObjectName] RETURNS[de: DictEntry, h: CARDINAL] =
--h is result of hashing name
BEGIN
h ← Hash[key, LENGTH[HTable]];
FOR de ← HTable[h], de.ovflow UNTIL de=NIL OR key=de.key
DO --nothing-- ENDLOOP;
END;
Hash: PROCEDURE[key: ObjectName, range: CARDINAL] RETURNS[h: CARDINAL] =
--h is result of hashing name into [0..range)
BEGIN
i: CARDINAL ← LowHalf[LOOPHOLE[key,LONG UNSPECIFIED]];
RETURN[i MOD range];
END;
--Utilities
WriteLongDecimal: PUBLIC PROCEDURE[n: LONG INTEGER] =
BEGIN
s: STRING ← [50];
AppendLongDecimal[s,n];
WriteString[s];
END;
WriteFloat: PUBLIC PROCEDURE[r: REAL] =
BEGIN
WriteReal[WriteChar,r];
END;
-- parameters
ScanningTopLevel: BOOLEAN;
SaveLayer: CARDINAL;
CurrentLayer: CARDINAL;
CurrentSymbol: Symbol;
ParentSymbol: Symbol;
Aborted: BOOLEAN;
-- Output Procedures
CIFOutput: PUBLIC PROCEDURE [symbol: Symbol, callOnce: BOOLEAN,
fileName: STRING] =
BEGIN
countID: PropID ← AllocPropID[];
markID: PropID ← AllocPropID[];
Mark: PROC[s: Symbol] RETURNS[BOOLEAN] =
BEGIN
-- mark = 1 means symbol has not yet been output
-- count#0 means symbol can still be called
count ← count + 1;
PutProp[@s.prop,markID,1];
PutProp[@s.prop,countID,count];
RETURN[FALSE];
END;
WriteSymbolNumber: PROC[s: Symbol] =
BEGIN
--str: STRING ← [50];
--AppendLongNumber[str,s,8];
--WriteString[str];
WriteDecimal[GetProp[s.prop,countID]];
END;
WriteLongDecimal: PROC[n: LONG INTEGER] =
BEGIN
str: STRING ← [50];
AppendLongDecimal[str,n];
WriteString[str];
END;
Out: PROC[s: Symbol] RETURNS[BOOLEAN] =
BEGIN
PutProp[@s.prop,markID,0];
FOR in: Instance ← s.insts,in.next UNTIL in = NIL DO
IF GetProp[in.symbol.prop,markID] = 1 THEN [] ← Out[in.symbol];
ENDLOOP;
WriteLine[""]; WriteString["DS "]; WriteSymbolNumber[s];
WriteLine[";"];
-- write geometry
FOR g:Geometry ← s.geom,g.next UNTIL g = NIL DO
WriteString["L N"]; WriteChar[LayerChar[g.layer]];-- layer
WriteString["; B "];
WriteLongDecimal[Fix[g.r-g.l]]; WriteString[" "];-- length
WriteLongDecimal[Fix[g.t-g.b]]; WriteString[" "];--width
WriteLongDecimal[Fix[(g.r+g.l)/2]]; WriteString[" "];-- x Center
WriteLongDecimal[Fix[(g.t+g.b)/2]]; WriteLine[";"];-- y Center
ENDLOOP;
FOR in: Instance ← s.insts,in.next UNTIL in = NIL DO
IF GetProp[in.symbol.prop,countID]#0 THEN
{WriteString["C "]; WriteSymbolNumber[in.symbol];
WriteString[" T "]; WriteLongDecimal[Fix[in.xOffset]];
WriteString[" "]; WriteLongDecimal[Fix[in.yOffset]];
WriteLine[";"];
IF callOnce THEN PutProp[@in.symbol.prop,countID,0];
};
ENDLOOP;
WriteLine["DF;"];
RETURN[FALSE];
END;
count: CARDINAL ← 0;
IF symbol # NIL THEN {
cifFile: StreamHandle ← NewByteStream[fileName,Write+Append];
default: StreamHandle ← GetOutputStream[];
cifFile.reset[cifFile];
SetOutputStream[cifFile];
WriteString["(Generated by Disjoint from symbol "];
WriteString[symbol.name]; WriteLine[");"];
-- mark all the symbols
[] ← EnumerateSymbols[Mark];
[] ← Out[symbol];
WriteLine[""]; WriteString["C "]; WriteSymbolNumber[symbol];
WriteLine[";"];
cifFile.destroy[cifFile];
SetOutputStream[default];
WriteDecimal[count]; WriteString[" symbols from "];
WriteString[symbol.name]; WriteString[" in "]; WriteLine[fileName];
};
END;
PrintDisCells: PUBLIC PROCEDURE[disCellList: DisCell] =
BEGIN
FOR dc:DisCell ← disCellList, dc.next UNTIL dc=NIL DO
PrintDisCell[dc];
ENDLOOP;
END;
PrintDisCell: PUBLIC PROCEDURE[disCell: DisCell] =
BEGIN OPEN disCell;
w: DisjointTypes.Rectangle;
WriteLine["DisCell"];
WriteString[" geom: "];
FOR g:Geometry ← disCell.geom, g.next UNTIL g=NIL DO
WriteChar[’[]; WriteChar[’N]; WriteChar[LayerChar[g.layer]];
WriteChar[’,]; WriteReal[WriteChar, g.l];
WriteChar[’,]; WriteReal[WriteChar, g.b];
WriteChar[’,]; WriteReal[WriteChar, g.r];
WriteChar[’,]; WriteReal[WriteChar, g.t];
WriteChar[’]];
ENDLOOP;
WriteChar[CR];
WriteString[" instances: "];
FOR p:PIP ← disCell.insts, p.next UNTIL p=NIL DO
i: Instance ← p.inst;
WriteString["{"""]; WriteString[i.symbol.name]; WriteChar[’"];
WriteChar[’,]; WriteReal[WriteChar, i.xOffset];
WriteChar[’,]; WriteReal[WriteChar, i.yOffset];
WriteChar[’}];
ENDLOOP;
WriteChar[CR];
WriteString[" windows: "];
FOR w ← disCell.windows, w.next UNTIL w=NIL DO
WriteChar[’[]; WriteReal[WriteChar, w.l];
WriteChar[’,]; WriteReal[WriteChar, w.b];
WriteChar[’,]; WriteReal[WriteChar, w.r];
WriteChar[’,]; WriteReal[WriteChar, w.t];
WriteChar[’]];
ENDLOOP;
WriteChar[CR];
END;
PrintSymbols: PUBLIC PROCEDURE =
BEGIN
PS: PROC[s: Symbol] RETURNS[BOOLEAN] =
BEGIN
PrintSymbol[s];
RETURN[FALSE];
END;
[] ← EnumerateSymbols[PS];
END;
PrintSymbol: PUBLIC PROCEDURE[s: Symbol] =
BEGIN
w: DisjointTypes.Rectangle;
WriteString["Symbol: "]; WriteLine[s.name];
WriteString[" geom: "];
FOR g:Geometry ← s.geom, g.next UNTIL g=NIL DO
WriteChar[’[]; WriteChar[’N]; WriteChar[LayerChar[g.layer]];
WriteChar[’,]; WriteReal[WriteChar,g.l];
WriteChar[’,]; WriteReal[WriteChar,g.b];
WriteChar[’,]; WriteReal[WriteChar,g.r];
WriteChar[’,]; WriteReal[WriteChar,g.t];
WriteChar[’]];
ENDLOOP;
WriteChar[CR];
WriteString[" instances: "];
FOR i:Instance ← s.insts,i.next UNTIL i=NIL DO
WriteString["{"""]; WriteString[i.symbol.name]; WriteChar[’"];
WriteChar[’,]; WriteReal[WriteChar,i.xOffset];
WriteChar[’,]; WriteReal[WriteChar,i.yOffset];
WriteChar[’}];
ENDLOOP;
WriteChar[CR];
WriteString[" windows: "];
FOR w ← s.windows, w.next UNTIL w=NIL DO
WriteChar[’[]; WriteReal[WriteChar,w.l];
WriteChar[’,]; WriteReal[WriteChar,w.b];
WriteChar[’,]; WriteReal[WriteChar,w.r];
WriteChar[’,]; WriteReal[WriteChar,w.t];
WriteChar[’]];
ENDLOOP;
WriteChar[CR];
END;
LayerChar: ARRAY [0..15] OF CHARACTER ← ALL[’X];
--Set up CIF Layer names
LayerChar[0] ← ’I;--implant
LayerChar[1] ← ’D;--diffusion
LayerChar[2] ← ’P;--poly
LayerChar[3] ← ’C;--contact
LayerChar[4] ← ’M;--metal
LayerChar[5] ← ’B;--buried
LayerChar[6] ← ’G;--glass
LayerChar[7] ← ’X;--undef
END.