JasmineImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights resolutionerved.
Created by Neil Gunther April 24, 1986 1:16:18 pm PST
Last Edited by: Neil Gunther October 8, 1986 12:26:25 pm PDT
DIRECTORY
AMBridge USING [TVForATOM, TVForROPE, TVForReferent],
AMTypes USING [TV],
Basics USING [CompareINT],
CD USING [Instance, InstanceList, Layer, LayerKey, Number, Position, Rect, Technology],
CDBasics USING [Extend, SizeOfRect --, Surround--],
CDSequencer USING [Command, ImplementCommand],
CDMenus USING [CreateEntry],
CoreGeometry,
CDOps USING [InstList],
CMosB USING [cmosB, lambda],
Core,
CoreClasses USING [Transistor, transistorCellClass],
CoreFlat USING [EachInternalWireProc, EachWireInstanceProc, EnumerateAtomicWireLeaves],
CoreOps USING [GetWireIndex, PrintCellType, ToBasic],
CDOrient USING [MapRect],
CoreProperties USING [GetCellInstanceProp, GetWireProp, PutWireProp, RegisterProperty],
CStitching,
GList USING [CompareProc, Sort],
IO USING [int, PutFR, real, rope, STREAM],
Jasmine,
PrintTV USING [Print],
Process USING [priorityBackground, SetPriority],
Real USING [Float, Round],
Rope,
Sinix,
SinixOps,
SymTab USING [Create, Fetch, Ref, Store],
TerminalIO USING [RequestRope, TOS, WriteF, WriteRope];
JasmineImpl: CEDAR PROGRAM
IMPORTS AMBridge, Basics, CD, CDBasics, CDSequencer, CDMenus, CDOps, CMosB, CoreClasses, CoreFlat, CoreGeometry, CoreOps, CDOrient, CoreProperties, CStitching, GList, IO, PrintTV, Process, Real, Rope, Sinix, SinixOps, SymTab, TerminalIO
EXPORTS Jasmine
= BEGIN
OPEN Jasmine;
Jasmine keys for decorating Core
resolutionistorProp: ATOM = CoreProperties.RegisterProperty[$JasmineResistor];
capacitorProp: ATOM = CoreProperties.RegisterProperty[$JasmineCapacitor];
inductorProp: ATOM = CoreProperties.RegisterProperty[$JasmineInductor];
transistorProp: ATOM = CoreProperties.RegisterProperty[$JasmineTransistor];
modelProp: ATOM = CoreProperties.RegisterProperty[$JasmineModel];
ChipnDale keys
CDTechnology: CD.Technology = CMosB.cmosB;
lambda: CD.Number = CMosB.lambda;
CD Layers:
CDCut: ATOM = $cut;
CDMetal1: ATOM = $met;
CDMetal2: ATOM = $met2;
CDNDif: ATOM = $ndif;
CDOGlass: ATOM = $ovg;
CDPDif: ATOM = $pdif;
CDPoly: ATOM = $pol;
CDVia: ATOM = $cut2;
CD Objects:
CDRect:  ATOM = $Rect;
CDCell:  ATOM = $Cell;
CDNXtor:  ATOM = $C2Trans;
CDPXtor:  ATOM = $C2WellTrans;
CDNXtorL: ATOM = $C2LTrans;
CDPXtorL: ATOM = $CLWellTrans;
NOTE: Ordering of LayerObject matches Chipndale keys
LayerObject: TYPE = {cut, met1, met2, ndif, oglass, pdif, poly, via, nXtor, pXtor, nXtorL, pXtorL};
LayersInTile: TYPE = REF LayersInTileRec;
LayersInTileRec: TYPE = RECORD[
primary: PACKED ARRAY LayerObject OF BOOL ALL[FALSE],
secondary: PACKED ARRAY LayerObject OF BOOL ALL[FALSE],
coreWire: Core.Wire ← NIL,
coreTrans: CoreClasses.Transistor ← NIL
];
MergeRect: TYPE = REF MergeRectRec;
MergeRectRec: TYPE = RECORD [r: CD.Rect ← [0,0,0,0]];
ContactArea: CD.Rect = [0, 0, 32, 32];
TransArea: CD.Rect = [0, 0, 64, 64];
LTransArea: CD.Rect = [0, 0, 112, 144];
RelArea: TYPE = {smallerThan, largerThan, equalTo};
Error: SIGNAL [msg: Core.ROPE] = CODE;
none: REF INT = NEW[INT];
spaceTile: REF = NIL;
tranCount: NAT;
md: PUBLIC MapDimension ← NIL;
locations: PUBLIC LIST OF MacroLocation ← NIL;
Volts: TYPE = REAL;
kOhm: TYPE = REAL;
pF: TYPE = REAL;
mA: TYPE = REAL;
nH: TYPE = REAL;
--diagnostics
db: BOOLFALSE;
resolution: PUBLIC Resolution ← high;
Operations
CornerStitchWire: PUBLIC PROC [root: Core.CellType, wire: Core.Wire] RETURNS [tesselation: CStitching.Tesselation] = {
AddWireGeometry: CoreFlat.EachInternalWireProc = {
AccumulateLayer: PROC [wireLayer: CD.Layer] = {
data ← NEW[LayersInTileRec];
layer ← SELECT CD.LayerKey[wireLayer] FROM
CDCut => cut,
CDMetal1  => met1,
CDMetal2  => met2,
CDNDif  => ndif,
CDOGlass => oglass,
CDPDif => pdif,
CDPoly => poly,
ENDCASE => via;
data.primary[layer] ← TRUE;
data.coreWire ← wire; 
};
InsertWireRectangle: CStitching.RectProc
-- [plane: Tesselation, rect: Rect, oldValue: REF, data: REF] -- = {
WITH oldValue SELECT FROM
tileLayer: LayersInTile =>
IF NOT tileLayer.primary[layer] THEN tileLayer.secondary[layer] ← TRUE;
ENDCASE --tile=NIL-- =>
CStitching.ChangeRect[plane: tesselation, rect: rect, new: data];
};
geometry: LIST OF CD.Instance ← NARROW[CoreProperties.GetWireProp[wire, wireGeometryProp]];
inst: CD.Instance ← NIL;
wireRect: CD.Rect;
FOR geom: LIST OF CD.Instance ← geometry, geom.rest UNTIL geom=NIL DO
inst ← geom.first;
IF inst.ob.class.objectType = CDRect THEN {
AccumulateLayer[inst.ob.layer];
Change from relative to absolute ("world") coordinates ... sigh!!
wireRect ← CDOrient.MapRect[
itemInCell: IF layer=cut OR layer=via THEN
Avoid tesselation of contact tile by expanding cut rect to match surround dimensions.
CDBasics.Extend[[0,0,inst.ob.size.x,inst.ob.size.y], inst.ob.size.x/2]
ELSE [0,0,inst.ob.size.x,inst.ob.size.y],
cellSize: inst.ob.size,
cellInstOrient: inst.orientation,
cellInstPos: inst.location
];
CStitching.ChangeEnumerateArea[plane: tesselation, rect: wireRect, eachRect: InsertWireRectangle, data: data, skip: none];
};
ENDLOOP;
}; --AddWireGeometry
AddTransistorGeometry: CoreFlat.EachWireInstanceProc
--[bindings: HashTable.Table, path: PackedPath, instance: CoreClasses.CellInstance, wire: Core.Wire] RETURNS [flatten: BOOLTRUE]-- = {
AccumulateTransistor: PROC [tranInst: CD.Instance, tranData: CoreClasses.Transistor] = {
data ← NEW[LayersInTileRec];
layer ← SELECT tranInst.ob.class.objectType FROM
CDNXtor => nXtor,
CDPXtor => pXtor,
CDNXtorL => nXtorL,
ENDCASE => pXtorL;
data.primary[layer] ← TRUE;
data.coreTrans ← tranData; 
};
InsertTransistor: CStitching.RectProc
-- [plane: Tesselation, rect: Rect, oldValue: REF, data: REF] -- = {
WITH oldValue SELECT FROM
tileLayer: LayersInTile =>
IF NOT tileLayer.primary[layer] THEN tileLayer.secondary[layer] ← TRUE;
ENDCASE --tile=NIL-- =>
CStitching.ChangeRect[plane: tesselation, rect: rect, new: data];
};
basic: Core.CellType ← CoreOps.ToBasic[instance.type];
IF basic.class=CoreClasses.transistorCellClass THEN {
trans: CoreClasses.Transistor ← NARROW[instance.type.data];
inst: CD.Instance ← NARROW[CoreProperties.GetCellInstanceProp[instance, instanceProp]];
xtor: CD.Rect ← CDOrient.MapRect[
itemInCell: [0, 0, inst.ob.size.x, inst.ob.size.y],
cellSize: inst.ob.size,
cellInstOrient: inst.orientation,
cellInstPos: inst.location
];
flatten ← FALSE;
AccumulateTransistor[inst, trans];
CStitching.ChangeEnumerateArea[plane: tesselation, rect: xtor, eachRect: InsertTransistor, data: data, skip: none];
};
}; --AddTransistorGeometry
data: LayersInTile;
layer: LayerObject;
wireGeometryProp: ATOM = CoreGeometry.Decoration.geometryProp;
instanceProp: ATOM = CoreGeometry.Decoration.transfProp;
tesselation ← CStitching.NewTesselation[];
CoreFlat.EnumerateAtomicWireLeaves[root: root, rootWire: wire, eachInternalWire: AddWireGeometry, eachWireInstance: AddTransistorGeometry];
}; --CornerStitchWire
EstablishTopography: PUBLIC PROC [tesselation: CStitching.Tesselation] = {
DefineJasmineObjects: CStitching.TileProc
--PROC [tile: Tile, data: REF]-- = {
ElectJasmineObject: PROC [nomination, elected: JasmineObject] = {
tileValue.object ← SELECT CompareRelativeArea[CDBasics.SizeOfRect[CStitching.Area[tile]], CDBasics.SizeOfRect[CDStandardArea[elected]]] FROM
smallerThan, equalTo => elected,
ENDCASE => tileValue.object ← nomination;
}; --ElectJasmineObject
Discriminate: PROC [primLayer: LayerObject] = {
SELECT primLayer FROM
cut => {
SELECT TRUE FROM
tLayer.secondary[met1] => {
SELECT TRUE FROM
tLayer.secondary[ndif] => ElectJasmineObject[m1Wire, nDifCont];
tLayer.secondary[pdif] => ElectJasmineObject[m1Wire, pDifCont];
tLayer.secondary[poly] => ElectJasmineObject[m1Wire, polyCont];
tLayer.secondary[met1] => ElectJasmineObject[m1Wire, Via];
tLayer.secondary[met2] => ElectJasmineObject[m2Wire, Via];
ENDCASE => tileValue.object ← m1Wire;
};
tLayer.secondary[met2] => {
SELECT TRUE FROM
tLayer.secondary[ndif] => ElectJasmineObject[m2Wire, nDifCont];
tLayer.secondary[poly]  => ElectJasmineObject[m2Wire, polyCont];
ENDCASE => tileValue.object ← m2Wire;
};
ENDCASE => Error["Isolated Cut layer."];
};
met1 => {
SELECT TRUE FROM
tLayer.secondary[cut] => {
SELECT TRUE FROM
tLayer.secondary[met2] => ElectJasmineObject[m1Wire, Via];
tLayer.secondary[ndif] => ElectJasmineObject[m1Wire, nDifCont];
tLayer.secondary[pdif] => ElectJasmineObject[m1Wire, pDifCont];
tLayer.secondary[poly] => ElectJasmineObject[m1Wire, polyCont];
ENDCASE => tileValue.object ← m1Wire;
};
tLayer.secondary[met2] => ElectJasmineObject[m1Wire, Via];
ENDCASE => tileValue.object ← m1Wire;
};
met2 => {
SELECT TRUE FROM
tLayer.secondary[cut]  => {
SELECT TRUE FROM
tLayer.secondary[met1] => ElectJasmineObject[m2Wire, Via];
tLayer.secondary[ndif] => ElectJasmineObject[m2Wire, nDifCont];
tLayer.secondary[pdif] => ElectJasmineObject[m2Wire, pDifCont];
tLayer.secondary[poly] => ElectJasmineObject[m2Wire, polyCont];
ENDCASE => tileValue.object ← m2Wire;
};
tLayer.secondary[met1] => ElectJasmineObject[m2Wire, Via];
ENDCASE => tileValue.object ← m2Wire;
};
ndif => {
SELECT TRUE FROM
tLayer.secondary[cut] => {
SELECT TRUE FROM
tLayer.secondary[met1] => ElectJasmineObject[nDifWire, nDifCont];
tLayer.secondary[met2] => ElectJasmineObject[nDifWire, nDifCont];
ENDCASE => tileValue.object ← nDifWire;
};
ENDCASE => tileValue.object ← nDifWire;
};
oglass => { --do we care ???-- };
pdif => {
SELECT TRUE FROM
tLayer.secondary[cut] => {
SELECT TRUE FROM
tLayer.secondary[met1] => ElectJasmineObject[pDifWire, pDifCont];
tLayer.secondary[met2] => ElectJasmineObject[pDifWire, pDifCont];
ENDCASE => tileValue.object ← pDifWire;
};
ENDCASE => tileValue.object ← pDifWire;
};
poly => {
SELECT TRUE FROM
tLayer.secondary[cut] => {
SELECT TRUE FROM
tLayer.secondary[met1] => ElectJasmineObject[polyWire, polyCont];
tLayer.secondary[met2] => ElectJasmineObject[polyWire, polyCont];
ENDCASE => tileValue.object ← polyWire;
};
ENDCASE => tileValue.object ← polyWire;
};
via => tileValue.object ← Via;
nXtor => {tileValue.object ← nTran; tileValue.data ← tLayer.coreTrans};
nXtorL => {tileValue.object ← nTranL; tileValue.data ← tLayer.coreTrans};
pXtor => {tileValue.object ← pTran; tileValue.data ← tLayer.coreTrans};
pXtorL => {tileValue.object ← pTranL; tileValue.data ← tLayer.coreTrans};
ENDCASE => NULL;
}; --Discriminate
tLayer: LayersInTile = NARROW[tile.value];
tileValue: JasmineObjectInLayer ← NEW[JasmineObjectRec];
FOR layer: LayerObject IN LayerObject DO
wire: Core.Wire = tLayer.coreWire;
IF tLayer.primary[layer] THEN {
Discriminate[layer];
IF wire#NIL AND CoreProperties.GetWireProp[from: wire, prop: modelProp]=NIL THEN CoreProperties.PutWireProp[on: wire, prop: modelProp, value: tileValue];
CStitching.ChangeTile[plane: tesselation, tile: tile, new: tileValue];
PrintJasmineObjectData[tile, db];
EXIT;
};
ENDLOOP;
}; --DefineJasmineObjects
CStitching.EnumerateArea[plane: tesselation, rect: CStitching.all, eachTile: DefineJasmineObjects, skip: spaceTile];
MergeJasmineTiles[tesselation];
}; --EstablishTopography
MergeJasmineTiles: PROC [tesselation: CStitching.Tesselation] = {
MergeTiles: CStitching.TileProc
--PROC [tile: Tile, data: REF]-- = {
MergeTransistorTiles: PROC [keyTile: CStitching.Tile] = {
MarkTile: CStitching.TileProc = {
td: JasmineObjectInLayer ← NARROW[tile.value];
SELECT td.object FROM
nTran, pTran, nTranL, pTranL =>
IF td.private=NIL THEN {
td.private ← $Merge;
CStitching.ChangeTile[plane: tesselation, tile: tile, new: td];
};
ENDCASE => NULL;
};
tdata: JasmineObjectInLayer ← NARROW[keyTile.value];
CStitching.EnumerateArea[plane: tesselation, rect: CDBasics.Extend[CStitching.Area[keyTile], lambda/4], eachTile: MarkTile, skip: spaceTile];
IF tdata.private=$Merge AND tdata.object#Ignore THEN {
tdata.object ← Ignore;
tdata.data ← NIL;
CStitching.ChangeTile[plane: tesselation, tile: keyTile, new: tdata];
};
}; --MergeTransistorTiles
MergeWireTiles: PROC [keyTile: CStitching.Tile] = {
--*** Bug: Causes Poly & Diff wires to get merged
MarkTile: CStitching.TileProc = {
td: JasmineObjectInLayer ← NARROW[tile.value];
SELECT td.object FROM
m1Wire, m2Wire, nDifWire, pDifWire, polyWire =>
IF td.private=NIL THEN {
td.private ← $Merge;
CStitching.ChangeTile[plane: tesselation, tile: tile, new: td];
};
ENDCASE => NULL;
};
tdata: JasmineObjectInLayer ← NARROW[keyTile.value];
CStitching.EnumerateArea[plane: tesselation, rect: CDBasics.Extend[CStitching.Area[keyTile], lambda/4], eachTile: MarkTile, skip: spaceTile];
IF tdata.private=$Merge AND tdata.object#Ignore THEN {
tdata.object ← Ignore;
tdata.data ← NIL;
CStitching.ChangeTile[plane: tesselation, tile: keyTile, new: tdata];
mergedWires ← CONS[CStitching.Area[keyTile], mergedWires];
};
}; --MergeWireTiles
tileValue: JasmineObjectInLayer ← NARROW[tile.value];
mergedRect: MergeRect ← NEW[MergeRectRec];
mergedWires: LIST OF CD.Rect;
SELECT tileValue.object FROM
m1Wire, m2Wire, nDifWire, pDifWire, polyWire => {
IF tileValue.private=NIL THEN tileValue.private ← $Keep;
CStitching.ChangeTile[plane: tesselation, tile: tile, new: tileValue];
mergedWires ← CONS[CStitching.Area[tile], mergedWires];
MergeWireTiles[tile];
FOR mw: LIST OF CStitching.Rect ← mergedWires, mw.rest UNTIL mw=NIL DO
mergedRect.r ← CDBasics.Surround[mergedRect.r, mw.first];
ENDLOOP;
tileValue.data ← mergedRect;
CStitching.ChangeTile[plane: tesselation, tile: tile, new: tileValue];
mergedRect.r ← CStitching.Area[tile];
tileValue.data ← mergedRect;
CStitching.ChangeTile[plane: tesselation, tile: tile, new: tileValue];
};
nTran, pTran, nTranL, pTranL => {
IF tileValue.private=NIL THEN tileValue.private ← $Keep;
CStitching.ChangeTile[plane: tesselation, tile: tile, new: tileValue];
MergeTransistorTiles[tile];
};
ENDCASE => NULL;
}; --MergeTiles
CStitching.EnumerateArea[plane: tesselation, rect: CStitching.all, eachTile: MergeTiles, skip: spaceTile];
}; --MergeJasmineTiles
CreateModel: PUBLIC PROC [tesselation: CStitching.Tesselation] RETURNS [model: SymTab.Ref] = {
InsertMacro: CStitching.TileProc
--PROC [tile: Tile, data: REF]-- = {
WireAspect: PROC [r: CD.Rect] RETURNS [ar: AspectType] = {
ar ← SELECT TRUE FROM
(r.x2-r.x1)>(r.y2-r.y1) => horiz,
(r.x2-r.x1)<(r.y2-r.y1) => vert,
ENDCASE => square;
};
Branching: PROC [r: CD.Rect] RETURNS [branch: BranchType] = {
N, E, W, S: INT ← 0; --score--
[N, E, W, S] ← ScoreAdjacentTiles[tile];
SELECT (N+S+E+W) FROM
4 => branch ← fourWay;
3 => SELECT TRUE FROM
N+(E+W)=3 => branch ← inverseT;
N+(E+S)=3 => branch ← rightT;
N+(W+S)=3 => branch ← leftT;
S+(E+W)=3 => branch ← T;
ENDCASE => ERROR;
2 => SELECT TRUE FROM
N+S =2 => branch ← straight;
N+E =2 => branch ← L;
N+W=2 => branch ← reverseL;
S+E =2 => branch ← inverseL;
S+W=2 => branch ← inverseRevL;
ENDCASE => ERROR;
1 => branch ← straight;
0 => Error["Adjacent tile score = 0 => isolated tile!"];
ENDCASE => Error["Adjacent tile score > 4."];
};
ContactResistance: PROC [r: CD.Rect] RETURNS [R: kOhm] = {
R ← SELECT tileValue.object FROM
nDifCont => 30,
pDifCont => 120,
polyCont => 25,
Via => 1,
ENDCASE => ERROR;
RR*1E-3;
};
WireResistance: PROC [r: CD.Rect] RETURNS [R: kOhm] = {
Squares: PROC [CStitching.Rect] RETURNS [sqrs: REAL] = {
normLength ← (r.x2-r.x1)/lambda;
normWidth ← (r.y2-r.y1)/lambda;
IF normLength > normWidth THEN sqrs ← Real.Float[normLength]/normWidth
ELSE sqrs ← Real.Float[normWidth]/normLength;
};
QuickAndDirty. (Should come from common process parameter source).
m1Resistivity: REAL ← 0.065;
m2Resistivity: REAL ← 0.042;
polyResistivity: REAL ← 3.5;
nDifResistivity: REAL ← 35;
pDifResistivity: REAL ← 120;
R ← SELECT tileValue.object FROM
m1Wire => Squares[r]*m1Resistivity,
m2Wire => Squares[r]*m2Resistivity,
polyWire => Squares[r]*polyResistivity,
nDifWire => Squares[r]*nDifResistivity,
pDifWire => Squares[r]*pDifResistivity
ENDCASE => ERROR;
RR*1E-3;
};
WireInductance: PROC [r: CD.Rect] RETURNS [L: nH] = {
Self-inductance
pi: REAL = 3.14159276;
L ← (1.25663706*1E-6*normLength*1E+9)/(8*pi);
};
WireCapacitance: PROC [r: CD.Rect] RETURNS [C: pF ← 0.1] = {
Represent each segment as Thyme Stray
jasmineMacro.wireArea ← normLength*normWidth;
jasmineMacro.wirePerimeter ← (2*normLength)+(2*normWidth);
};
TransistorParameters: PROC [r: CD.Rect] = {
tranData: CoreClasses.Transistor ←NARROW[tileValue.data];
GateAspect: PROC RETURNS [aspect: TranAspect ← chanTied] = {
FOR regions: LIST OF REF CStitching.Region ← CStitching.ListArea[tesselation, CDBasics.Extend[CStitching.Area[tile], lambda]], regions.rest UNTIL regions=NIL DO
rd: JasmineObjectInLayer ← NARROW[regions.first.value];
IF rd.object = polyWire THEN {
aspect ← gateTied;
EXIT;
};
ENDLOOP;
};
jasmineMacro.xtorType ← SELECT tileValue.object FROM
nTran, nTranL => nE,
pTran, pTranL => pE,
ENDCASE => ERROR;
jasmineMacro.xtorAspect ← GateAspect[];
jasmineMacro.xtorLength ← tranData.length;
jasmineMacro.xtorWidth ← tranData.width;
tranCount ← tranCount.SUCC;
}; --TransistorParameters
tileValue: JasmineObjectInLayer ← NARROW[tile.value];
normLength, normWidth: INT;
jasmineMacro: JasmineMacro ← NEW[JasmineMacroRec];
macroLocation:MacroLocation ← NEW[MacroLocationRec ← [0, 0]];
jasmineMacro.macroType ← tileValue.object;
SELECT jasmineMacro.macroType FROM
m1Wire, m2Wire, nDifWire, pDifWire, polyWire => {
mergedRect: MergeRect ← NARROW[tileValue.data];
jasmineMacro.wireAspect ← WireAspect[mergedRect.r];
jasmineMacro.resistance ← WireResistance[mergedRect.r];
jasmineMacro.inductance ← WireInductance[mergedRect.r];
jasmineMacro.capacitance ← WireCapacitance[mergedRect.r];
--jasmineMacro.branch ← Branching[mergedRect.r];
};
nDifCont, pDifCont, polyCont, Via => {
jasmineMacro.resistance ← ContactResistance[CStitching.Area[tile]];
jasmineMacro.branch ← Branching[CStitching.Area[tile]];
};
nTran, nTranL, pTran, pTranL => {
TransistorParameters[CStitching.Area[tile]];
};
ENDCASE => NULL;
Map[macroLocation, tile];
locations ← CONS[macroLocation, locations];
IF jasmineMacro.macroType#Ignore THEN [] ← SymTab.Store[x: model, key: MapConvert[macroLocation], val: jasmineMacro];
}; --InsertMacro
md ← NEW[MapDimensionRec ← [mapXMax: 1, mapXMin: 100, mapYMax: 1, mapYMin: 100]];
model ← SymTab.Create[];
tranCount ← 0;
locations ← NIL; --reset the cache
CStitching.EnumerateArea[plane: tesselation, rect: CStitching.all, eachTile: InsertMacro];
locations ← OrderMapLocations[locations];
}; --CreateModel
CompareRelativeArea: PROC [p1, p2: CD.Position] RETURNS [rs: RelArea] = {
IF (p1.x*p1.y) = (p2.x*p2.y) THEN rs ← equalTo;
IF (p1.x*p1.y) < (p2.x*p2.y) THEN rs ← smallerThan;
IF (p1.x*p1.y) > (p2.x*p2.y) THEN rs ← largerThan;
};
CDStandardArea: PROC [jObj: JasmineObject] RETURNS [area: CD.Rect] = {
Used fixed values for now
area ← SELECT jObj FROM
nDifCont,
pDifCont,
polyCont,
Via => ContactArea,
nTran,
pTran => TransArea,
nTranL,
pTranL => LTransArea,
ENDCASE => [0, 0, INT.FIRST, INT.FIRST];
};
ScoreAdjacentTiles: PROC [startingTile: CStitching.Tile] RETURNS [N, E, W, S: INT ← 0] = {
tWest, tEast, tSouth, tNorth: CStitching.Tile;
n: CStitching.Number = CStitching.NEdge[startingTile];
e: CStitching.Number = CStitching.EEdge[startingTile];
s: CStitching.Number = CStitching.SEdge[startingTile];
w: CStitching.Number = CStitching.WEdge[startingTile];
--trace down Eastern edge
tEast ← CStitching.NE[startingTile];
WHILE CStitching.SEdge[tEast]>=s DO
IF tEast.value#spaceTile THEN {E ← 1; EXIT};
TRUSTED {tEast ← LOOPHOLE[tEast.wS]};
ENDLOOP;
Check for overhangs: Is there a tile whose Southern border is more Southerly than that of the starting tile which also abuts its Eastern edge? (i.e. an Eastern overhang).
IF tEast.value#spaceTile THEN E ← 1;
--trace left, along Southern edge
TRUSTED {tSouth ← LOOPHOLE[startingTile.wS]};
WHILE CStitching.WEdge[tSouth]>=w DO
IF tSouth.value#spaceTile THEN {S ← 1; EXIT};
tSouth ← tSouth.sW;
ENDLOOP;
IF tSouth.value#spaceTile THEN S ← 1;
--trace up Western edge
tWest ← CStitching.SW[startingTile];
WHILE CStitching.NEdge[tWest]<=n DO
IF tWest.value#spaceTile THEN {W ← 1; EXIT};
tWest ← tWest.eN;
ENDLOOP;
IF tWest.value#spaceTile THEN W ← 1;
--trace right, along Northern edge to starting point
TRUSTED {tNorth ← LOOPHOLE[startingTile.eN]};
WHILE CStitching.EEdge[tNorth]<=e DO
IF tNorth.value#spaceTile THEN {N ← 1; EXIT};
TRUSTED {tNorth ← LOOPHOLE[tNorth.nE]};
ENDLOOP;
IF tNorth.value#spaceTile THEN N ← 1;
}; --ScoreAdjacentTiles
MapConvert: PUBLIC PROC [ml: MacroLocation] RETURNS [sym: Core.ROPE] = {
sym ← IO.PutFR["[%g, %g]", IO.int[ml.mapX], IO.int[ml.mapY]];
};
OrderMapLocations: PROC [unordered: LIST OF MacroLocation] RETURNS [ordered: LIST OF MacroLocation] = {
Compare: GList.CompareProc --[ref1, ref2: REF ANY] RETURNS [Basics.Comparison]-- = {
location1: MacroLocation ← NARROW[ref1];
location2: MacroLocation ← NARROW[ref2];
RETURN [Basics.CompareINT[location1.mapX, location2.mapX]];
};
ordered ← NARROW[GList.Sort[unordered, Compare]];
};
Map: PROC [modLoc: MacroLocation, tile: CStitching.Tile] = {
x, y, scale: INT ← 0;
r: CStitching.Rect ← CStitching.Area[tile];
SELECT resolution FROM
high => scale ← 1;
medium => {--see individual transistors+contacts & some wires--};
low => {--see only accumulated transistor+contacts-- };
ENDCASE => NULL;
x ← Real.Round[Real.Float[r.x1+(r.x2-r.x1)/2]/(scale*lambda)];
y ← Real.Round[Real.Float[r.y1+(r.y2-r.y1)/2]/(scale*lambda)];
IF x < md.mapXMin THEN md.mapXMin ← x;
IF y < md.mapYMin THEN md.mapYMin ← y;
IF x > md.mapXMax THEN md.mapXMax ← x;
IF y > md.mapYMax THEN md.mapYMax ← y;
IF x < 1 THEN x ← 1; IF y < 1 THEN y ← 1;
modLoc.mapX← x; modLoc.mapY← y;
};
Interactive User Utilities
InteractiveExtract: PROC [comm: CDSequencer.Command] = {
FOR all: CD.InstanceList ← CDOps.InstList[comm.design], all.rest UNTIL all=NIL DO
IF all.first.selected THEN {
indx: NAT;
coreCell: Core.CellType;
coreWire: Core.Wire;
wireName: Core.ROPE;
tesselation: CStitching.Tesselation;
TRUSTED {Process.SetPriority[Process.priorityBackground]};
coreCell ← NARROW[Sinix.ExtractCell[obj: all.first.ob, mode: SinixOps.GetExtractMode[comm.design.technology]].result];
wireName ← TerminalIO.RequestRope["\nEnter wire name: "];
indx ← CoreOps.GetWireIndex[coreCell.public, wireName];
coreWire ← coreCell.public[indx];
tesselation ← CornerStitchWire[coreCell, coreWire];
EstablishTopography[tesselation];
IF db THEN {
out: IO.STREAM ← TerminalIO.TOS[];
CoreOps.PrintCellType[coreCell, out];
TerminalIO.WriteRope["\n\n"];
};
};
ENDLOOP;
TerminalIO.WriteRope["\nJasmine extraction complete.\n"];
}; --InteractiveExtract
Debugging Utilities
PrintRect: PROC [tag: Core.ROPE, r: CD.Rect, debug: BOOL] = {
Simple diagnostics. Use CSMonitor for WYSIWYG tesselations
IF debug THEN TerminalIO.WriteF["%g: [x1: %g, y1: %g, x2: %g, y2: %g]\n", IO.rope[tag], IO.int[r.x1],IO.int[r.y1],IO.int[r.x2],IO.int[r.y2]];
};
PrintJasmineObjectData: PROC [tile: CStitching.Tile, debug: BOOL] = {
GetTypedVar: PROC [ra: REF ANY] RETURNS [tv: AMTypes.TV] = TRUSTED {
WITH ra SELECT FROM
a: ATOM  => tv ← AMBridge.TVForATOM[a];
r: Rope.ROPE => tv ← AMBridge.TVForROPE[r];
ENDCASE => tv ← AMBridge.TVForReferent[ra];
};
tos: IO.STREAM ← TerminalIO.TOS[];
IF debug THEN {
TerminalIO.WriteRope["\nJasmine Object: "];
IF tile=NIL THEN TerminalIO.WriteRope[" not found."]
ELSE PrintTV.Print[tv: GetTypedVar[tile.value], put: tos];
};
};
PrintModel: PROC [model: SymTab.Ref] = {
PrintMacro: PROC = {
FOR indices: LIST OF MacroLocation ← locations, indices.rest UNTIL indices=NIL DO
[thereIs, val] ← SymTab.Fetch[model, MapConvert[indices.first]];
IF thereIs THEN {
macro: JasmineMacro ← NARROW[val];
TerminalIO.WriteRope["\nMap: "];
TerminalIO.WriteRope[MapConvert[indices.first]];
SELECT macro.macroType FROM
m1Wire, m2Wire, nDifWire, pDifWire, polyWire => {
IF macro.wireAspect=vert THEN TerminalIO.WriteRope[" | "]
ELSE TerminalIO.WriteRope[" -- "];
TerminalIO.WriteF[" \t%gK ", IO.real[macro.resistance]];
};
nDifCont, pDifCont, polyCont, Via => {
SELECT macro.branch FROM
leftT => TerminalIO.WriteRope[" --| "];
rightT=> TerminalIO.WriteRope[" |-- "];
inverseT=> TerminalIO.WriteRope[" —L "];
T=> TerminalIO.WriteRope[" T "];
L => TerminalIO.WriteRope[" L "];
reverseL => TerminalIO.WriteRope[" ←L "];
inverseL => TerminalIO.WriteRope[" F "];
inverseRevL => TerminalIO.WriteRope[" 𡤏 "];
straight => TerminalIO.WriteRope[" * "];
fourWay=> TerminalIO.WriteRope[" + "];
ENDCASE => NULL;
TerminalIO.WriteF[" \t%gK ", IO.real[macro.resistance]];
};
nTran, nTranL => {
IF macro.xtorAspect=gateTied THEN TerminalIO.WriteRope[" =|= n "]
ELSE TerminalIO.WriteRope[" -[n "];
};
pTran, pTranL => {
IF macro.xtorAspect=gateTied THEN TerminalIO.WriteRope[" =|= p"]
ELSE TerminalIO.WriteRope[" -[p "];
};
ENDCASE => NULL;
macroCount ← macroCount.SUCC;
}; 
ENDLOOP;
};
val: REF ANY;
thereIs: BOOL;
macroCount: NAT ← 0;
PrintMacro[];
TerminalIO.WriteF["\nMacros: %g, Transistors: %g, Resolution: %g\n\n", IO.int[macroCount], IO.int[tranCount], IO.rope[SELECT resolution FROM low=> "low", medium=>"medium", ENDCASE=>"high"], ];
}; --PrintModel
Thus item appears in Additional Programs Menu
CDSequencer.ImplementCommand[key: $InterJas, proc: InteractiveExtract, queue: doQueue];
CDMenus.CreateEntry[menu: $ProgramMenu, entry: "Extract Jasmine Network", key: $InterJas];
TerminalIO.WriteRope["Interactive Jasmine loaded.\n"];
END... of JasmineImpl