ModelLayout: PWCore.LayoutProc = {
AddRect:
PROC[wire: Wire, ir:
CD.Rect] = {
IF ir.x2=ir.x1
THEN {
rect: CD.Object ← CDRects.CreateRect[[L4, L4*(ir.y2-ir.y1)], verLayer];
isPin: BOOL ← ir.y1=0 OR ir.y2=max.y;
AddPositionedObject[wire, rect, [ir.x1*L4-L2, ir.y1*L4], isPin]};
IF ir.y2=ir.y1
THEN {
rect: CD.Object ← CDRects.CreateRect[[L4*(ir.x2-ir.x1), L4], horLayer];
isPin: BOOL ← ir.x1=0 OR ir.x2=max.x;
AddPositionedObject[wire, rect, [ir.x1*L4, ir.y1*L4-L2], isPin]}};
AddVia:
PROC[wire: Wire, row, col:
INT] = {
via: CD.Object ← CDSimpleRules.Contact[technologyKey, verLayer, horLayer];
AddPositionedObject[wire, via, [col*L4-L2, row*L4-L2]]};
AddPositionedObject:
PROC
[wire: Wire, obj: CD.Object, pos: CD.Position, isPin: BOOL ← FALSE] = {
cdInstances ← CONS [CDInstances.NewInst[obj, [pos]], cdInstances];
IF isPin
THEN {
inst: CoreGeometry.Instance ← [cdInstances.first.ob, cdInstances.first.trans];
CoreGeometry.AddPins[layDeco, wire, LIST[inst]]}};
cdInstances: CD.InstanceList ← NIL;
array: Array;
Array: TYPE = REF ArrayRec;
ArrayRec: TYPE = RECORD[SEQUENCE size: NAT OF Row];
Row: TYPE = REF RowRec;
RowRec: TYPE = RECORD[SEQUENCE size: NAT OF HorVerWire];
HorVerWire: TYPE = RECORD[hor, ver: Wire];
ir: CD.Rect ← CD.InterestRect[CoreGeometry.GetObject[schDeco, cellType]];
irSize: CD.Position ← CDBasics.SizeOfRect[ir];
max: CD.Position ← [(irSize.x + L1)/L2, (irSize.y + L1)/L2];
horLayer: CD.Layer;
verLayer: CD.Layer;
name: IO.ROPE ← CoreOps.GetCellTypeName[cellType];
eachAtomic:
PROC[wire: Wire] = {
eachInstance:
PROC [instance: CoreGeometry.Instance]
RETURNS [quit:
BOOL ←
FALSE] = {
bb: CD.Rect ← CoreGeometry.BBox[instance];
pos1: CD.Position ← [(bb.x1 - ir.x1 + L1)/L2, (bb.y1 - ir.y1 + L1)/L2];
pos2: CD.Position ← [(bb.x2 - ir.x1 + L1)/L2, (bb.y2 - ir.y1 + L1)/L2];
size: CD.Position ← [pos2.x - pos1.x, pos2.y - pos1.y];
IF (size.x=0) # (size.y=0)
THEN
FOR row: INT
IN [pos1.y .. pos2.y]
DO
FOR col: INT
IN [pos1.x .. pos2.x]
DO
IF size.x #0 THEN array[row][col].hor ← wire;
IF size.y #0 THEN array[row][col].ver ← wire;
ENDLOOP ENDLOOP};
[]𡤌oreGeometry.EnumerateGeometry[schDeco, wire, eachInstance]};
[verLayer, horLayer] ← CoreRoute.GetCellTypePropLayer[cellType, $VerticalMetal, $met2];
array ← NEW[ArrayRec[max.y+1]];
FOR row: INT
IN [0..array.size)
DO
array[row] ← NEW[RowRec[max.x+1]];
FOR col: INT
IN [0..array[row].size)
DO
array[row][col] ← [NIL, NIL] ENDLOOP ENDLOOP;
CoreOps.VisitRootAtomics[cellType.public, eachAtomic];
FOR row: INT
IN [0..array.size)
DO
begin: INT ← 0;
wire: Wire ← NIL;
FOR col: INT
IN [0..array[row].size)
DO
IF wire # array[row][col].hor
THEN {
IF wire#NIL THEN AddRect[wire, [begin, row, col-1, row]];
wire ← array[row][col].hor;
begin ← col;
LOOP};
IF col=(array[row].size-1) AND wire#NIL THEN AddRect[wire, [begin, row, col, row]];
ENDLOOP ENDLOOP;
FOR col: INT
IN [0..array[0].size)
DO
begin: INT ← 0;
wire: Wire ← NIL;
FOR row: INT
IN [0..array.size)
DO
IF wire # array[row][col].ver
THEN {
IF wire#NIL THEN AddRect[wire, [col, begin, col, row-1]];
wire ← array[row][col].ver;
begin ← row;
LOOP};
IF row=array.size-1 AND wire#NIL THEN AddRect[wire, [col, begin, col, row]];
ENDLOOP ENDLOOP;
FOR row: INT
IN [0..array.size)
DO
FOR col: INT
IN [0..array[row].size)
DO
IF array[row][col].hor = array[row][col].ver
AND
array[row][col].hor#
NIL
THEN AddVia[array[row][col].hor, row, col]
ENDLOOP ENDLOOP;
obj ←
PW.CreateCell
[instances: cdInstances, name: name.Cat[".mask"], ir: [0,0, max.x*L4, max.y*L4] ] };