PWCImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Louis Monier May 17, 1986 1:35:25 pm PDT
Bertrand Serlet August 11, 1986 8:06:03 pm PDT
Barth, April 22, 1986 7:30:28 pm PST
Spreitzer, April 11, 1986 10:52:25 am PST
Curry, October 8, 1986 7:46:14 am PDT
Don Curry November 3, 1986 4:18:37 pm PST
DIRECTORY
Atom, Basics, CD, CDBasics, CDCells, CDDirectory, CDInstances, CDOrient, CDProperties, CDRects,
Commander,
Core, CoreClasses, CoreGeometry, CoreIO, CoreOps, CoreProperties,
CMosB,
HashTable, IO,
PW, PWObjects, PWC, PWPins,
Rope, Sinix, SinixOps;
PWCImpl:
CEDAR
PROGRAM
IMPORTS Atom, Basics, CD, CDBasics, CDCells, CDDirectory, CDInstances, CDProperties, CDRects, CoreClasses, CoreGeometry, CoreIO, CoreOps, CoreProperties, HashTable, IO, PW, PWObjects, Rope, Sinix, SinixOps
EXPORTS PWC
SHARES CDCells, CDDirectory =
BEGIN OPEN PWC;
VisitAtomicPairs:
PROC [wire1, wire2: Wire, eachPair:
PROC [Wire, Wire]] = {
VisitInternal:
PROC [wire1, wire2: Wire] = {
IF wire1.size#wire2.size THEN ERROR;
IF wire1.size=0
THEN eachPair[wire1, wire2]
ELSE FOR i: NAT IN [0 .. wire1.size) DO VisitInternal[wire1[i], wire2[i]] ENDLOOP};
IF wire1.size#wire2.size THEN ERROR;
FOR i: NAT IN [0 .. wire1.size) DO VisitInternal[wire1[i], wire2[i]] ENDLOOP};
Exceptions
Error:
PUBLIC
ERROR [type:
ATOM, message:
ROPE, cellType: CellType] =
CODE;
GeometryCorrespondingToSeveralPublics:
PUBLIC
SIGNAL [cellType: CellType, obj: Object, publics: Wires, geometry:
LIST
OF
CD.Instance] =
CODE;
NoGeometryOnAtomicPublics: PUBLIC SIGNAL [cellType: CellType, obj: Object, publics: Wires, message: ROPE ← NIL] = CODE;
LayoutAtomsTable
layoutAtomsTable: HashTable.Table ← HashTable.Create[];
LayoutAtomData: TYPE = REF LayoutAtomDataRec;
LayoutAtomDataRec: TYPE = RECORD [layoutProc: LayoutProc, decorateProc: DecorateProc];
RegisterLayoutAtom:
PUBLIC
PROC [layoutAtom:
ATOM, layoutProc: LayoutProc, decorateProc: DecorateProc]
RETURNS [sameAtom:
ATOM] = {
sameAtom ← layoutAtom;
IF ~HashTable.Store[layoutAtomsTable, layoutAtom,
NEW [LayoutAtomDataRec ← [layoutProc: layoutProc, decorateProc: decorateProc]]]
THEN PW.WriteF["LayoutProc and DecorateProc for %g overwritten\n", IO.atom[layoutAtom]]};
Layout primitives
layoutAtomProp:
PUBLIC
ATOM ← CoreProperties.RegisterProperty[$Layout];
GetLayoutAtom:
PUBLIC
PROC [cellType: CellType]
RETURNS [layoutAtom:
ATOM ←
NIL] = {
layoutAtom ← NARROW [CoreProperties.GetCellTypeProp[cellType, layoutAtomProp]];
IF layoutAtom#NIL THEN RETURN;
layoutAtom ← NARROW [CoreProperties.GetCellClassProp[cellType.class, layoutAtomProp]]};
Cache on CellTypes and Objects
layoutProp: PRIVATE ATOM ← CoreProperties.RegisterProperty[$PWCLayout];
FakeExtract: Sinix.ExtractProc = {result ← CDProperties.GetObjectProp[obj, $PWCCellType]};
SetExtractCell:
PUBLIC PROC [obj: CD.Object, cellType: CellType] = {
CDProperties.PutObjectProp[obj, $PWCCellType, cellType];
CDProperties.PutObjectProp[obj, extractMode.extractProcProp, $FakeExtract]};
SetLayoutObj:
PUBLIC
PROC [cellType: CellType, obj:
CD.Object] =
{CoreProperties.PutCellTypeProp[cellType, layoutProp, obj]};
{SetLayout[cellType, $ValueNoDecorate, $PWCValue, obj]};
Layout:
PUBLIC
PROC [cellType: CellType]
RETURNS [obj: Object] = {
obj ← NARROW [CoreProperties.GetCellTypeProp[cellType, layoutProp]];
IF obj#NIL THEN RETURN;
BEGIN
CopyDecorations:
PROC [wire1, wire2: Wire] = {
SourcePinsFromExtracted[cellType, obj, wire2, wire1]};
publicsWithoutPin: Wires;
layoutAtom: ATOM ← GetLayoutAtom[cellType];
layoutAtomData: LayoutAtomData;
layoutData: LayoutData;
layoutCellType: CellType;
IF layoutAtom=
NIL
THEN Error[$NoLayoutAtom,
"Impossible to find a layoutAtom for this cellType", cellType];
layoutAtomData ← NARROW [HashTable.Fetch[layoutAtomsTable, layoutAtom].value];
IF layoutAtomData=
NIL
THEN Error[$NoRegistration,
IO.PutFR["LayoutAtom %g has not been registered", IO.atom[layoutAtom]], cellType];
obj ← layoutAtomData.layoutProc[cellType];
layoutData ← NEW [LayoutDataRec ← [cellType: cellType, obj: obj, mode: extractMode]];
layoutCellType ← CoreOps.CreateCellType[class: layoutClass, public: CoreOps.CopyWire[cellType.public], data: layoutData];
Now we decorate the source cellType
IF layoutAtomData.decorateProc#NIL THEN layoutAtomData.decorateProc[cellType, obj];
IF
NOT CoreGeometry.HasIR[extractMode.decoration, cellType]
THEN ERROR;
We make a simple check to see if the public was correctly decorated
publicsWithoutPin ← AtomicWithoutPin[cellType.public];
IF publicsWithoutPin#
NIL
THEN NoGeometryOnAtomicPublics[cellType, obj, publicsWithoutPin];
We decorate layoutCellType with the same decorations
VisitAtomicPairs[cellType.public, layoutCellType.public, CopyDecorations];
Indirect object to allow the same layout to be returned on 2 different calls of Layout
obj ← PWObjects.CreateIndirect[obj];
SetExtractCell[obj, cellType];
SetLayoutObj[cellType, obj];
IF CoreOps.GetCellTypeName[cellType]#NIL AND CDDirectory.Name[obj]=NIL THEN SetObjName[obj, CoreOps.GetCellTypeName[cellType]];
Consistency check
IF Sinix.Extract[obj, extractMode].result#cellType
THEN Error[$InternalBug, "Internal invariant failed", cellType];
IF CorrespondingCellType[obj]#cellType
THEN Error[$InternalBug, "Internal invariant failed", cellType];
END };
SetObjName:
PUBLIC
PROC [obj:
CD.Object, name:
ROPE] = {
NARROW[obj.class.directoryProcs, REF CDDirectory.DirectoryProcs].setName[obj, name]};
CountTransistors:
PUBLIC
PROC[cell: CellType]
RETURNS[count:
INT ← 0] = {
refInt: REF INT;
IF cell=NIL THEN RETURN[0];
refInt ← NARROW[CoreProperties.GetCellTypeProp[cell, transistorCount].value];
IF refInt#NIL THEN RETURN[refInt^];
SELECT cell.class
FROM
CoreClasses.sequenceCellClass => {
data: CoreClasses.SequenceCellType ← NARROW[cell.data];
count ← data.count*CountTransistors[data.base]};
CoreClasses.recordCellClass => {
data: CoreClasses.RecordCellType ← NARROW[cell.data];
FOR child:
NAT
IN [0..data.size)
DO
count ← count + CountTransistors[ data.instances[child].type ] ENDLOOP };
CoreClasses.transistorCellClass => RETURN[1];
rotatedCellClass => count ← CountTransistors[NARROW[cell.data]];
CoreIO.importCellClass => {
PW.WriteF["\nSkipping Imported Transistors: %g\n",
IO.rope[CoreOps.GetCellTypeName[cell] ] ]};
ENDCASE =>
IF
ISTYPE[cell.data, CellType]
THEN count ← CountTransistors[NARROW[cell.data]]
ELSE PW.WriteF["\nSkipping transistor count: %g\n",
IO.rope[CoreOps.GetCellTypeName[cell] ] ];
CoreProperties.PutCellTypeProp[cell, transistorCount, NEW[INT ← count]] };
transistorCount:
PUBLIC ATOM ← CoreIO.RegisterProperty[
CoreProperties.RegisterProperty[
$TransistorCount,
CoreProperties.Props[
[CoreProperties.propPrint, NEW[CoreProperties.PropPrintProc ← PrintTCnt ]] ] ],
WriteTCnt,
ReadTCnt ];
WriteTCnt: CoreIO.PropWriteProc = {CoreIO.WriteInt[h, NARROW[value, REF INT]^]};
ReadTCnt: CoreIO.PropReadProc = {RETURN[ NEW[INT ← CoreIO.ReadInt[h] ] ]};
PrintTCnt: CoreProperties.PropPrintProc =
{to.PutF[" Transistor Count: %g", IO.int[NARROW[val, REF INT]^]]};
InterestRect:
PUBLIC
PROC [cellType: CellType]
RETURNS [ir:
CD.Rect] = {
IF NOT CoreGeometry.HasIR[extractMode.decoration, cellType] THEN [] ← Layout[cellType];
ir ← CoreGeometry.GetIR[extractMode.decoration, cellType]};
InterestSize:
PUBLIC
PROC [cellType: CellType]
RETURNS [size:
CD.Position] =
{RETURN[ CDBasics.SizeOfRect[ InterestRect[ cellType]]]};
Extract:
PUBLIC
PROC [obj: Object]
RETURNS [cellType: CellType] = {
cellType ← NARROW [Sinix.Extract[obj, extractMode].result];
SetLayoutObj[cellType, obj]};
Global Variable
extractMode: PUBLIC Sinix.Mode ← SinixOps.GetExtractMode[$cmosB];
StoringPins
AtomicWithoutPin:
PROC [public: Wire]
RETURNS [publicsWithoutPin: Wires ←
NIL] = {
CheckPinsNonNil:
PROC [wire: Wire] = {
IF CoreGeometry.GetPins[extractMode.decoration, wire]=
NIL
THEN publicsWithoutPin ← CONS [wire, publicsWithoutPin]};
FOR i:
NAT
IN [0 .. public.size)
DO CoreOps.VisitRootAtomics[public[i], CheckPinsNonNil] ENDLOOP};
IndirectGetPins: PROC [mode: Sinix.Mode, wire: Wire, ir: CD.Rect, data: REF]
RETURNS [pins: LIST OF CD.Instance ← NIL] = {
Check for simple loops that should never occur
IF data=wire THEN Error[$InternalBug, "Internal invariant failed", NIL];
pins ← Sinix.GetPinsProp[mode, NARROW [data]]};
Should be called only when source.size=extracted.size=0
SourcePinsFromExtracted:
PROC
[cellType: CellType, obj: Object, source, extracted: Wire] = {
IF NOT CoreGeometry.HasPins[extractMode.decoration, extracted] THEN NoGeometryOnAtomicPublics[cellType, obj, LIST [source]];
CoreGeometry.AddIndirectLazyPins[extractMode.decoration, source, extracted]};
$Get, $GetAndFlatten, $Value and $ValueNoDecorate
maskSuffix:
PUBLIC
ROPE ← ".mask";
GetAndAddSuffix:
PROC [source:
CD.Design, name:
ROPE]
RETURNS [obj: Object] = {
obj ← PW.Get[source, IO.PutR[IO.rope[name], IO.rope[maskSuffix]]]};
Get: LayoutProc = {
source: CD.Design ← NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCSourceDesign]];
obj ← GetAndAddSuffix[source, CoreOps.GetCellTypeName[cellType]]};
GetAndFlatten: LayoutProc = {
source: CD.Design ← NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCSourceDesign]];
obj ← PW.Flatten[GetAndAddSuffix[source, CoreOps.GetCellTypeName[cellType]]]};
Value: LayoutProc = {
obj ← NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCValue]]};
NoDecorate: DecorateProc = {};
DecorateValue:
PUBLIC DecorateProc = {
extractedCT: CellType ← NARROW [Sinix.Extract[obj, extractMode].result];
extractedToSource: HashTable.Table ← HashTable.Create[extractedCT.public.size];
FindInExtractedPublic: CoreOps.EachWireProc = {
FOR names:
LIST
OF
ROPE ← CoreOps.GetFullWireNames[cellType.public, wire], names.rest
WHILE names#
NIL
DO
name: ROPE ← names.first;
extractedWire: Wire ← CoreOps.FindWire[extractedCT.public, name];
previousSourceWire: Wire ← NARROW [HashTable.Fetch[extractedToSource, extractedWire].value];
IF extractedWire=NIL OR extractedWire.size#0 THEN LOOP;
IF previousSourceWire#NIL AND previousSourceWire#wire THEN GeometryCorrespondingToSeveralPublics[cellType, obj, LIST [previousSourceWire, wire], CoreGeometry.GetPins[extractMode.decoration, extractedWire]];
SourcePinsFromExtracted[cellType, obj, wire, extractedWire];
[] ← HashTable.Store[extractedToSource, extractedWire, wire];
ENDLOOP };
CoreGeometry.PutIR[extractMode.decoration, cellType, CD.InterestRect[obj]];
[] ← CoreOps.VisitWire[cellType.public, FindInExtractedPublic] };
Abuts, Arrays and Recast
AbutX: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i:
NAT
DECREASING
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListX[subObjects]};
AbutY: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i:
NAT
DECREASING
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListY[subObjects]};
ReverseAbutX: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i:
NAT
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListX[subObjects]};
ReverseAbutY: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i:
NAT
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListY[subObjects]};
ArrayX: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $AbutX]; obj ← Layout[recasted]};
ArrayY: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $AbutY]; obj ← Layout[recasted]};
ReverseArrayX: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $ReverseAbutX]; obj ← Layout[recasted]};
ReverseArrayY: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $ReverseAbutY]; obj ← Layout[recasted]};
Recast: LayoutProc = {
obj ← PWObjects.CreateIndirect[Layout[CoreOps.Recast[cellType]]]};
DecorateAbut:
PUBLIC
PROC [cellType: CellType, obj: Object, sort: SortProc] = {
InsertInOrder:
PROC [element:
CD.Instance, sorted:
LIST
OF
CD.Instance]
RETURNS [new:
LIST
OF
CD.Instance] = {
IF element.orientation#0 THEN Error[$CallerBug, "DecorateAbut is only applicable for CD Cells without rotations", cellType];
IF sorted=NIL THEN RETURN [LIST [element]];
IF sort[CDBasics.BaseOfRect[CDInstances.InstRectO[element]], CDBasics.BaseOfRect[CDInstances.InstRectO[sorted.first]]] THEN RETURN [CONS [element, sorted]];
RETURN [CONS [sorted.first, InsertInOrder[element, sorted.rest]]]};
SetLazyPins: PROC [wire: Wire] = {CoreGeometry.PutRecordLazyPins[extractMode.decoration, wire, cellType]};
instances: LIST OF CD.Instance;
recordData: CoreClasses.RecordCellType ← NARROW [cellType.data];
WHILE obj.class#CDCells.cellClass DO obj ← CDDirectory.Expand[obj].new ENDLOOP;
CoreGeometry.PutIR[extractMode.decoration, cellType, CD.InterestRect[obj]];
FOR list:
LIST
OF
CD.Instance ←
NARROW [obj.specificRef,
CD.CellPtr].contents, list.rest
WHILE list#
NIL
DO
instances ← InsertInOrder[list.first, instances];
ENDLOOP;
We decorate each instance with the appropriate extractMode.instanceProp, so that the Lazy GetPins can find the location
FOR i:
NAT
IN [0 .. recordData.size)
DO
CoreGeometry.PutTransf[extractMode.decoration, recordData[i], instances.first];
instances ← instances.rest;
ENDLOOP;
IF instances#NIL THEN Error[$CallerBug, "DecorateAbut assumption not valid: CD cell has more instances than record CellType", cellType];
FOR i: NAT IN [0 .. cellType.public.size) DO CoreOps.VisitRootAtomics[cellType.public[i], SetLazyPins] ENDLOOP };
DecorateAbutX:
PUBLIC DecorateProc =
{DecorateAbut[cellType, obj, SortInX] };
DecorateAbutY:
PUBLIC DecorateProc =
{DecorateAbut[cellType, obj, SortInY] };
DecorateReverseAbutX:
PUBLIC DecorateProc =
{DecorateAbut[cellType, obj, ReverseSortInX] };
DecorateReverseAbutY:
PUBLIC DecorateProc =
{DecorateAbut[cellType, obj, ReverseSortInY]};
SmashPins:
PROC [wire: Wire] = {CoreGeometry.PutPins[extractMode.decoration, wire,
NIL]};
DecorateRecasted:
PUBLIC DecorateProc = {
recastedCT: CellType ← CoreOps.Recast[cellType];
CopySourcePinsFromRecasted:
PROC [wire1, wire2: Wire] = {
SourcePinsFromExtracted[cellType, obj, wire1, wire2]};
We check that the public of the source and the public of the recasted layout are similar, and we copy properties from one to the other
CoreOps.VisitRootAtomics[cellType.public, SmashPins];
CoreGeometry.PutIR[extractMode.decoration, cellType, CD.InterestRect[obj]];
VisitAtomicPairs[cellType.public, recastedCT.public, CopySourcePinsFromRecasted]};
Rotations
rotatedCellClass:
PUBLIC Core.CellClass ← CoreOps.SetClassPrintProc
[NEW [Core.CellClassRec ← [name: "Rotated", recast: RecastRotated, layersProps: FALSE]], PrintRotated];
RecastRotated: Core.RecastProc = {RETURN[ NARROW[me.data, CellType] ]};
PrintRotated: CoreOps.PrintClassProc = {
CoreOps.PrintIndent[indent, out];
out.PutF["Rotation of: %g", IO.rope[CoreOps.GetCellTypeName[NARROW [data, CellType]]]]};
RotateCellType:
PUBLIC PROC[cellType: CellType, orientation:
ATOM]
RETURNS [rotatedCellType: CellType] = {
name:
ROPE ← Rope.Cat
[Atom.GetPName[orientation], "-", CoreOps.GetCellTypeName[cellType]];
rotatedCellType ← CoreOps.CreateCellType[
class: rotatedCellClass,
public: CoreOps.CopyWire[cellType.public],
data: cellType,
name: name];
SetLayout[rotatedCellType, orientation]};
AtomOrientation:
PROC[atom:
ATOM]
RETURNS[orientation: CDOrient.Orientation] = {
RETURN[
SELECT atom
FROM
$Rot0 => CDOrient.original,
$Rot0X => CDOrient.mirrorX,
$Rot90 => CDOrient.rotate90,
$Rot90X => CDOrient.rotate90X,
$Rot180 => CDOrient.rotate180,
$Rot180X => CDOrient.rotate180X,
$Rot270 => CDOrient.rotate270,
$Rot270X => CDOrient.rotate270X,
$FlipX => CDOrient.mirrorX,
$FlipY => CDOrient.mirrorY,
ENDCASE => ERROR]};
Rotate: LayoutProc = {
layoutAtom: ATOM ← GetLayoutAtom[cellType];
orientation: CDOrient.Orientation ← AtomOrientation[layoutAtom];
IF cellType.class#rotatedCellClass
THEN
Error[$CallerBug, "Rotated CellType expected", cellType];
obj ← PW.ChangeOrientation[Layout[NARROW [cellType.data]], orientation]};
DecorateRotated:
PUBLIC DecorateProc = {
recastedCT: CellType ← CoreOps.Recast[cellType];
transf: CD.Instance;
CopyPinsFromRotated:
PROC [wire1, wire2: Wire] = {
CoreGeometry.PutTransfWireIRLazyPins[
decoration: extractMode.decoration, public: wire1, indirect: wire2, transf: transf, ir: ir]};
instances: LIST OF CD.Instance;
ir: CD.Rect = CD.InterestRect[obj];
WHILE obj.class#CDCells.cellClass DO obj ← CDDirectory.Expand[obj].new ENDLOOP;
CoreGeometry.PutIR[extractMode.decoration, cellType, ir];
instances ← NARROW [obj.specificRef, CD.CellPtr].contents;
IF instances=NIL OR instances.rest#NIL THEN ERROR Error[$CallerBug, "DecorateRotated is not supposed to be called with an obj that does not expand into a one instance cell", cellType];
transf ← instances.first;
We check that the public of the source and the public of the recasted layout are similar, and we copy pins from one to the other
VisitAtomicPairs[cellType.public, recastedCT.public, CopyPinsFromRotated];
};
Help for writing DecorateProcs
SortInX: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.x<pos2.x]};
SortInY: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.y<pos2.y]};
ReverseSortInX: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.x>pos2.x]};
ReverseSortInY:
PUBLIC
PROC [pos1, pos2:
CD.Position]
RETURNS [
BOOL] = {
RETURN [pos1.y>pos2.y]};
Short cut
SetLayout:
PUBLIC
PROC [cellType: CellType, layoutAtom:
ATOM, userDataProp:
ATOM ←
NIL, userData:
REF ←
NIL] = {
CoreProperties.PutCellTypeProp[cellType, layoutAtomProp, layoutAtom];
IF userDataProp#
NIL
THEN
CoreProperties.PutCellTypeProp[cellType, userDataProp, userData]};
Tentative help for regular structures
AbutList:
PUBLIC
PROC [cellTypes:
LIST
OF CellType, inX:
BOOL]
RETURNS [recordCell: CellType] = {
lobj: LIST OF CD.Object ← NIL;
WHILE cellTypes#
NIL
DO
ct: CellType ← cellTypes.first;
obj: CD.Object ← CDCells.CreateEmptyCell[];
CDCells.SetInterestRect[obj, InterestRect[ct]];
CDProperties.PutObjectProp[obj, $PWCCellType, ct];
CDProperties.PutObjectProp[obj, extractMode.extractProcProp, $FakeExtract];
lobj ← CONS [obj, lobj];
cellTypes ← cellTypes.rest;
ENDLOOP;
recordCell ← NARROW [Sinix.Extract[(IF inX THEN PW.AbutListX ELSE PW.AbutListY)[PW.Reverse[lobj]], extractMode].result];
SetLayout[recordCell, IF inX THEN $AbutListXNoDecorate ELSE $AbutListYNoDecorate]};
CellShell:
PUBLIC
PROC[cell: CellType]
RETURNS[shell:
CD.Object] = {
iSize: CD.Position ← InterestSize[cell];
list: LIST OF NWMML;
minW: INT = CMosB.lambda;
shell ← CDCells.CreateEmptyCell[];
FOR side: Side
IN Side
DO
FOR list ← SidePinList[cell, side], list.rest
WHILE list#
NIL
DO
wireName: ROPE ← CoreOps.GetFullWireName[cell.public, list.first.wire];
pos:
CD.Position ←
SELECT side
FROM
left => [0, list.first.min],
right => [iSize.x-minW, list.first.min],
top => [list.first.min, iSize.y-minW],
bottom => [list.first.min, 0],
ENDCASE => ERROR;
size:
CD.Position ←
SELECT side
FROM
top, bottom => [list.first.max - list.first.min, minW]
ENDCASE => [minW, list.first.max - list.first.min];
inst: CD.Instance ← PW.IncludeInCell[shell, CDRects.CreateRect[size, list.first.layer], pos];
IF wireName.Length[]=0 THEN ERROR;
CDProperties.PutInstanceProp[inst, $InstanceName, wireName];
ENDLOOP;
ENDLOOP;
PW.SetInterestRect[shell, iSize];
PW.RepositionCell[shell]};
SidePinList:
PUBLIC
PROC [cellType: CellType, side: Side]
RETURNS [list: LIST OF NWMML ← NIL] = {
thisSide: Side ← side;
EachWirePin: CoreGeometry.EachWirePinProc = {
name: ROPE ← CoreOps.GetShortWireName[wire];
IF side#thisSide THEN RETURN;
IF name=NIL THEN RETURN;
list ← AddMergeNWMMLs[[name, wire, min, max, layer], list]};
[] ← CoreGeometry.EnumerateWireSides[extractMode.decoration, cellType, EachWirePin];
PosSortNWMMLs[list]};
Add sorted by name, wire, layer, min, max - - - merge overlaps
AddMergeNWMMLs:
PUBLIC PROC[item:
NWMML, lst:
LIST
OF
NWMML]
RETURNS[LIST OF NWMML] = {
NameCompare:
PROC[item1, item2:
NWMML]
RETURNS[comp: Basics.Comparison] = {
IV: PROC[w: Core.Wire] RETURNS[int: INT] = {int ← LOOPHOLE[w]};
comp ←
IF item1.name=
NIL
AND item2.name =
NIL
THEN Basics.CompareINT[IV[ item1.wire], IV[ item2.wire]]
ELSE Rope.Compare[ item1.name, item2.name]};
dummy: NWMML ← [];
head: LIST OF NWMML ← CONS[dummy, lst];
l: LIST OF NWMML ← head;
IF lst=NIL THEN RETURN[CONS[item, NIL]];
WHILE l.rest#
NIL
DO
SELECT NameCompare[l.rest.first, item]
FROM
greater => EXIT;
equal =>
IF
l.rest.first.layer = item.layer AND
l.rest.first.max >= item.min AND
l.rest.first.min <= item.max
THEN {
item.max ← MAX[ l.rest.first.max, item.max];
item.min ← MIN[ l.rest.first.min, item.min];
l.rest ← l.rest.rest; LOOP};
ENDCASE;
l ← l.rest;
ENDLOOP;
l ← head;
FOR l ← l, l.rest
WHILE l.rest#
NIL
DO
cpr: Basics.Comparison ← NameCompare[l.rest.first, item];
IF cpr = greater
OR
cpr = equal
AND (
l.rest.first.layer > item.layer OR
l.rest.first.layer = item.layer AND
l.rest.first.min > item.max) THEN {l.rest ← CONS[item, l.rest]; EXIT};
REPEAT FINISHED => l.rest ← CONS[item, NIL] ENDLOOP;
RETURN[head.rest]};
PosSortNWMMLs:
PUBLIC
PROC[lst:
LIST
OF
NWMML] = {
DO
ok: BOOL ← TRUE;
FOR l:
LIST
OF
NWMML ← lst, l.rest
WHILE l#
NIL
AND l.rest#
NIL
DO
IF l.first.min > l.rest.first.min
OR
l.first.min = l.rest.first.min
AND l.first.max > l.rest.first.max
THEN
{temp: NWMML ← l.first; l.first ← l.rest.first; l.rest.first ← temp; ok ← FALSE}
ENDLOOP;
IF ok THEN EXIT;
ENDLOOP};
Registering layoutAtoms
Sinix.RegisterExtractProc[$FakeExtract, FakeExtract];
[] ← RegisterLayoutAtom[$Get, Get, DecorateValue];
[] ← RegisterLayoutAtom[$GetAndFlatten, GetAndFlatten, DecorateValue];
[] ← RegisterLayoutAtom[$Value, Value, DecorateValue];
[] ← RegisterLayoutAtom[$ValueNoDecorate, Value, NoDecorate];
[] ← RegisterLayoutAtom[$AbutListXNoDecorate, AbutX, NoDecorate];
[] ← RegisterLayoutAtom[$AbutListYNoDecorate, AbutY, NoDecorate];
[] ← RegisterLayoutAtom[$AbutX, AbutX, DecorateAbutX];
[] ← RegisterLayoutAtom[$AbutY, AbutY, DecorateAbutY];
[] ← RegisterLayoutAtom[$ReverseAbutX, ReverseAbutX, DecorateReverseAbutX];
[] ← RegisterLayoutAtom[$ReverseAbutY, ReverseAbutY, DecorateReverseAbutY];
[] ← RegisterLayoutAtom[$ArrayX, ArrayX, DecorateRecasted];
[] ← RegisterLayoutAtom[$ArrayY, ArrayY, DecorateRecasted];
[] ← RegisterLayoutAtom[$ReverseArrayX, ReverseArrayX, DecorateRecasted];
[] ← RegisterLayoutAtom[$ReverseArrayY, ReverseArrayY, DecorateRecasted];
[] ← RegisterLayoutAtom[$Recast, Recast, DecorateRecasted];
[] ← RegisterLayoutAtom[$FlipX, Rotate, DecorateRotated];
[] ← RegisterLayoutAtom[$FlipY, Rotate, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot0, Rotate, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot0X, Rotate, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot90, Rotate, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot90X, Rotate, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot180, Rotate, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot180X, Rotate, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot270, Rotate, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot270X, Rotate, DecorateRotated];
CoreProperties.PutCellClassProp[CoreClasses.identityCellClass, layoutAtomProp, $Recast];
END.