DIRECTORY
Basics, CCDUtils, CD, CDCells, CDCleanUp, CDCreateLabels, CDDirectory, CDOps, CDOrient, CDProperties, CDRects, CDSimpleOps, CDSimpleRules, CDSymbolicObjects, CDViewer, CMosB, CMosBObjects, Convert, Core, CoreBlock, CoreClasses, CoreFrame, CoreInstCell, CoreName, CoreOps, FS, HashTable, Imager, ImagerFont, IO, PW, PWCore, PWPins, Real, Rope, Sinix, SinixCMos, VFonts;

CCDUtilsImpl: CEDAR PROGRAM
IMPORTS Basics, CD, CDCells, CDCleanUp, CDCreateLabels, CDDirectory, CDOps, CDProperties, CDRects, CDSimpleOps, CDSimpleRules, CDSymbolicObjects, CDViewer, CMosB, CMosBObjects, Convert, CoreBlock, CoreClasses, CoreFrame, CoreInstCell, CoreName, CoreOps, FS, HashTable, ImagerFont, IO, PW, PWCore, PWPins, Real, Rope, Sinix, SinixCMos, VFonts
EXPORTS CCDUtils =
BEGIN

Signal:	SIGNAL	= CODE;
ROPE:		TYPE		= CCDUtils.ROPE;
GND:		ROPE		= CoreName.RopeNm["GND"];
VDD:		ROPE		= CoreName.RopeNm["VDD"];
plus:		ROPE		= CoreName.RopeNm["+"];
minus:	ROPE		= CoreName.RopeNm["-"];
NWMML:	TYPE		= CCDUtils.NWMML;
CellType:	TYPE		= Core.CellType;
Side:		TYPE		= CoreFrame.Side;

cache:		HashTable.Table _
HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
Store:		PROC[name: ROPE, obj: CD.Object] = {[]_HashTable.Store[cache, name, obj]};
Fetch:	PROC[name: ROPE] RETURNS[obj: CD.Object] =
{RETURN[NARROW[HashTable.Fetch[cache, name].value, CD.Object]]};

BlankObj: PUBLIC PROC[size: CD.Position] RETURNS[cell: CD.Object] ~ {
name:			ROPE _ IO.PutFR["Dummy-%g-%g", IO.int[size.x], IO.int[size.y]];
minLineW:		INT = 2 ;
IF size.x=0 OR size.y=0 THEN RETURN[NIL];
cell	_ Fetch[name];
IF cell#NIL THEN RETURN[cell];
cell	_ CDCells.CreateEmptyCell[];
IF size.x IN (0..4*minLineW) OR size.y IN (0..4*minLineW)
THEN [ ] _ PW.IncludeInCell[cell, CDRects.CreateRect[size, CD.commentLayer],	[0, 0] ]
ELSE {
lwidth:	INT		_ MAX[minLineW, MIN[size.x/100, size.y/100]];
hor:		CD.Object	_ CDRects.CreateRect[[size.x, lwidth], CD.commentLayer];
ver:		CD.Object	_ CDRects.CreateRect[[lwidth, size.y], CD.commentLayer];
[ ] _ PW.IncludeInCell[cell, hor,	[0,					0] ];
[ ] _ PW.IncludeInCell[cell, hor,	[0,		size.y-lwidth] ];
[ ] _ PW.IncludeInCell[cell, ver,	[0,					0] ];
[ ] _ PW.IncludeInCell[cell, ver,	[size.x-lwidth,	0] ]};
PW.RepositionCell[cell];
Store[name, cell]};

BlankCell: PUBLIC PROC[size: CD.Position] RETURNS[cell: CellType] ~ {
obj:	CD.Object	_ BlankObj[size];
CDProperties.PutProp [obj, SinixCMos.extractBMode.extractProcProp, $CCDUtilsBlankCell];
cell _ PWCore.FromLayoutWithoutPublic[obj];
CoreBlock.PutCellSide[cell, all];
cell _ CoreFrame.NewFrameCell[0, ObjName[obj], [cell: cell]]};

NewBlankCellType: PUBLIC PROC RETURNS[cell: CellType] ~ {
rec:	CoreClasses.RecordCellType _ NEW [CoreClasses.RecordCellTypeRec[0]];
rec.internal		_ CoreOps.CreateWires[0];
cell				_ NEW[Core.CellTypeRec _ [
class:	CoreClasses.recordCellClass, 
public:	CoreOps.CreateWires[0],
data:	rec,	
properties:	NIL]]};

BlankExtractProc: Sinix.ExtractProc ~ {
name:		ROPE				_ ObjName[obj];
cellType:	Core.CellType	_ NewBlankCellType[];
result _ CoreOps.SetCellTypeName[cellType, name]};

ObjName: PUBLIC PROC[obj: CD.Object] RETURNS[name: ROPE] = {
IF obj=NIL				THEN RETURN[NIL];
IF obj.specificRef=NIL	THEN RETURN[NIL];
IF NOT ISTYPE[obj.specificRef, CD.CellPtr] THEN RETURN[NIL];
RETURN[NARROW[obj.specificRef, CD.CellPtr].name]};

ObjSize: PUBLIC PROC[obj: CD.Object] RETURNS[size: CD.Position] =
{RETURN[CD.InterestSize[obj]]};
font1: Imager.Font _ VFonts.EstablishFont
[family:"Helvetica", size: 7, bold: TRUE, italic: FALSE, defaultOnFailure: FALSE];
font2: Imager.Font _ VFonts.EstablishFont
[family:"Helvetica", size: 14, bold: TRUE, italic: FALSE, defaultOnFailure: FALSE];

OrnateFrame: PUBLIC PROC [cell: CellType, design: CD.Design_NIL]
RETURNS[picture: CD.Object] = {
recCell:		CellType _ cell;
rSize:			CD.Position;
loc:			CD.Position;
sidesObj:		ARRAY Side OF CD.Object;
refObj:		CD.Object;
IF cell.class = CoreFrame.frameCellClass
THEN	recCell _ CoreFrame.FCT[cell].cell
ELSE	recCell _ cell;
refObj		_ CoreFrame.Layout[recCell];
picture		_ CDCells.CreateEmptyCell[];
rSize			_ CD.InterestSize[refObj];
[ ]				_ PW.IncludeInCell[picture, refObj, [0, 0]];
FOR side: Side IN Side DO
nwmmls:	LIST OF NWMML _ SidePinList[recCell, side];
bias:		INT	= lambda;
orient:	CD.Orientation;
size:		CD.Position _ [0, 0];
IF nwmmls=NIL THEN LOOP;
sidesObj[side] _ CDCells.CreateEmptyCell[];
FOR nwmmls _ nwmmls, nwmmls.rest WHILE nwmmls#NIL DO
textOb: CD.Object _ ScaledText
[nwmmls.first.name, [400*lambda,10*lambda],CD.commentLayer, design];
pos:		CD.Position ;
size.x		_ MAX[size.x, ((textOb.size.x+2*bias+lambda-1)/lambda)*lambda];
pos.x		_ bias;
pos.y		_ SELECT side FROM
left, right	=> nwmmls.first.min,
bottom, top	=> rSize.x - nwmmls.first.max,
ENDCASE		=> ERROR;
[ ] _ PW.IncludeInCell[sidesObj[side], textOb, pos];
ENDLOOP;
SELECT side FROM
left, right	=>	{size.y	_ rSize.y};
top, bottom	=>	{size.y	_ rSize.x};
ENDCASE	=> ERROR;
SELECT side FROM
left		=>	{loc _ [-size.x,		0		];	orient _ CDOrient.original};
right		=>	{loc _ [ rSize.x,		0		];	orient _ CDOrient.original};
top		=>	{loc _ [	0,		 rSize.y	];	orient _ CDOrient.rotate90};
bottom	=>	{loc _ [	0,		-size.x	];	orient _ CDOrient.rotate90};
ENDCASE	=> ERROR;
CDCells.SetInterestRect[sidesObj[side], [0, 0, size.x, size.y]];
[ ] _ CDCells.RepositionCell[sidesObj[side], NIL];
[ ] _ PW.IncludeInCell[picture, sidesObj[side], loc, orient];
ENDLOOP;
[ ] _ CDCells.RepositionCell[picture, NIL]};


AddRet: PUBLIC PROC [cell: CD.Object, size: CD.Position, loc: CD.Position, level: CD.Layer] = {
IF  size.x<0 OR size.y<0
THEN {
PW.WriteF["Strange rectangle size [%g, %g]", IO.int[size.x], IO.int[size.y] ];
Signal[]};
IF size.x=0 OR size.y=0 THEN RETURN;
[] _ PW.IncludeInCell[cell, CDRects.CreateRect[size, level], loc]};

SidePinList: PUBLIC PROC [cellType: CellType, side: PWPins.Side]
RETURNS [list: LIST OF NWMML _ NIL] = {
refCell:	CellType;
thisSide:	Side _ side;
EachWirePin: PWCore.EachWirePinProc = {
SubstituteWireName: CoreOps.EachWirePairProc ~ {
IF actualWire#wire THEN RETURN;
wire_publicWire; name_CoreName.WireNm[wire].n; RETURN[FALSE, TRUE]};
name:		ROPE _ CoreName.WireNm[wire].n;
IF side#thisSide THEN RETURN;
IF NOT CoreBlock.OnSide[CoreFrame.SideSides[side], CoreBlock.GetWireSide[wire]]
THEN RETURN;
IF layer#cmosMet AND layer#cmosMet2 THEN
SELECT name FROM GND, VDD, plus, minus => RETURN ENDCASE;
IF cellType.class=CoreInstCell.specificGenericCellClass THEN 
[ ] _ CoreOps.VisitBinding[refCell.public, cellType.public, SubstituteWireName];
IF name=NIL THEN RETURN;
list _ AddMergeNWMMLs[[name, wire, min, max, layer], list]};
IF cellType.class=CoreInstCell.specificGenericCellClass
THEN {refCell _ NARROW[cellType.data]} ELSE refCell _ cellType;
[] _ PWCore.EnumerateWirePins[refCell, EachWirePin];
PosSortNWMMLs[list]};

AddMergeNWMMLs: PUBLIC PROC[item: NWMML, lst: LIST OF NWMML]
RETURNS[LIST OF NWMML] = {
IV: PROC[w: Core.Wire] RETURNS[int: INT] = {int _ LOOPHOLE[w]};
IF lst=NIL THEN RETURN[CONS[item, NIL]];
FOR l: LIST OF NWMML _ lst, l.rest DO
nameCompare: Basics.Comparison _ IF l.first.name=NIL AND item.name = NIL
THEN	Basics.CompareINT[IV[l.first.wire], IV[item.wire]]
ELSE	Rope.Compare[l.first.name, item.name];
IF nameCompare	=	equal AND
l.first.layer	 =	 item.layer AND
l.first.max		>=	 item.min  AND
l.first.min		<=	 item.max THEN {
l.first.max _ MAX[ l.first.max, item.max];
l.first.min _ MIN[ l.first.min, item.min];
RETURN[lst]};
IF nameCompare	   =  greater			OR
nameCompare    =  equal			AND (
l.first.layer		>  item.layer		OR
l.first.layer		=  item.layer		AND
l.first.min			>  item.min)		THEN {
temp: NWMML	_ l.first;
l.rest				_ CONS[item, l.rest];
l.first				_ l.rest.first;
l.rest.first			_ temp;
RETURN[lst]};
IF l.rest = NIL THEN {l.rest _ CONS[item, l.rest]; RETURN[lst]};
ENDLOOP};

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};

ListNWMMLs: PUBLIC PROC[lst: LIST OF NWMML, log: IO.STREAM] = {
list:		LIST OF NWMML;
list _ lst; lst _ NIL;
FOR list _ list, list.rest WHILE list#NIL DO
lst _ CONS[list.first, lst] ENDLOOP;
list _ lst;
FOR list _ list, list.rest WHILE list#NIL DO ListNWMML[list.first, log] ENDLOOP;
log.PutChar[IO.CR] };

ListNWMML: PUBLIC PROC[nwmml: NWMML, log: IO.STREAM] = {
layerCard: CARDINAL _ LOOPHOLE[nwmml.layer];
log.PutF["\n%g\tpos: %5g\tsize: %5g\tlayer: %g",
IO.rope[nwmml.name],
IO.int[nwmml.min],
IO.int[nwmml.max-nwmml.min],
IO.rope[ SELECT nwmml.layer FROM
cmosMet2	=> "metal2",
cmosMet	=> "metal",
cmosPoly	=> "poly",
ENDCASE	=> Convert.RopeFromCard[layerCard] ] ]};
ListUniqueSignals: PUBLIC PROC[first: PWPins.Side, cell0, cell1: CellType, log: REF _ NIL] = {
Incrment: PROC[table: HashTable.Table, id: REF] = {
val: REF INT _ NARROW[HashTable.Fetch[table, id].value];
IF val=NIL THEN {val _ NEW[INT _ 0]; [] _ HashTable.Store[table, id, val]};
val^ _ val^ + 1};
nwmmls0:	LIST OF NWMML _ SidePinList[cell0, CoreFrame.OppSide[first]];
nwmmls1:	LIST OF NWMML _ SidePinList[cell1, first];
side0Nm:		ROPE _ CoreFrame.SideRope[CoreFrame.OppSide[first]];
side1Nm:		ROPE _ CoreFrame.SideRope[first];
out:			IO.STREAM;
count:			INT _ 0;
mark:			REF _ NEW[INT _ 0];
table0:		HashTable.Table _ HashTable.Create[ ];
table1:		HashTable.Table _ HashTable.Create[ ];
IF log=NIL
THEN	out _ FS.StreamOpen["UniqueSignals.txt", $create]
ELSE	WITH log SELECT FROM
rope:	ROPE			=>	{out _ FS.StreamOpen[rope, $create]};
text:	REF TEXT	=>	{out _ FS.StreamOpen[Rope.FromRefText[text], $create]};
stm:	IO.STREAM	=>	{out _ stm};
ENDCASE				=>	{Signal[]};
FOR temp: LIST OF NWMML _ nwmmls0, temp.rest WHILE temp#NIL DO
Incrment[table0, temp.first.name] ENDLOOP;
FOR temp: LIST OF NWMML _ nwmmls1, temp.rest WHILE temp#NIL DO
Incrment[table1, temp.first.name] ENDLOOP;
out.PutF["\nUnique signal log		%g\n%10g side of %g\n%10g side of %g\n",
IO.time[],
IO.rope[side0Nm],	IO.rope[CoreName.CellNm[cell0].n],
IO.rope[side1Nm],	IO.rope[CoreName.CellNm[cell1].n] ];
FOR temp: LIST OF NWMML _ nwmmls0, temp.rest WHILE temp#NIL DO
val: REF INT _ NARROW[HashTable.Fetch[table0, temp.first.name].value];
IF val^<2 AND NOT HashTable.Fetch[table1, temp.first.name].found THEN
out.PutF["\n%g\tpos: %5g", IO.rope[temp.first.name], IO.int[temp.first.min]] ENDLOOP;
FOR temp: LIST OF NWMML _ nwmmls1, temp.rest WHILE temp#NIL DO
val: REF INT _ NARROW[HashTable.Fetch[table1, temp.first.name].value];
IF val^<2 AND NOT HashTable.Fetch[table0, temp.first.name].found THEN
out.PutF["\n%g\tpos: %5g", IO.rope[temp.first.name], IO.int[temp.first.min]] ENDLOOP;
out.PutRope["\n"]; out.Close[]};

PutPin: PUBLIC PROC[cell: CD.Object, size, loc: CD.Position, level: CD.Layer, name: ROPE]  = {
pinApl: CD.Instance
_ PW.IncludeInCell[cell, CDSymbolicObjects.CreatePin[size], loc];
CDSymbolicObjects.SetName[pinApl, name];
CDSymbolicObjects.SetLayer[pinApl, level]};

RenamePins: PUBLIC PROC[
object:			CD.Object,
pinNameProc:	CCDUtils.PinNameProc]
RETURNS[newObject: CD.Object] = {
KeepPinOnEdge: CDSymbolicObjects.InstEnumerator ~ {
newRope: ROPE;
newInst: CD.Instance;
side: PWPins.Side;
side _ PWPins.GetSide[object, inst];
IF side=none THEN RETURN;
newRope _ pinNameProc[inst, side];
IF Rope.IsEmpty[newRope] THEN RETURN;
newInst _ NEW[CD.InstanceRep _ [
ob:			CDSymbolicObjects.CreatePin[inst.ob.size], 
location:		inst.location,
orientation:	inst.orientation ]];
CDProperties.CopyProps[inst.properties, newInst];
CDSymbolicObjects.SetName[newInst, newRope];
newCellPtr.contents _ CONS[newInst, newCellPtr.contents] };
newCellPtr:	CD.CellPtr;
inst:			CD.Instance _ NEW[CD.InstanceRep _ [ob: object]];
CDProperties.PutInstanceProp[inst, $StopEnumerateDeepPins, $StopEnumerateDeepPins];
newObject	_ CDCells.CreateEmptyCell[];
newCellPtr	_ NARROW[newObject.specificRef];
[] _ PWPins.EnumerateDeepPins[object, KeepPinOnEdge];
newCellPtr.contents _ CONS[inst, newCellPtr.contents];
CDCells.SetInterestRect[newObject, CD.InterestRect[object]];
RETURN[newObject] };

cmos: 				PUBLIC CD.Technology	= CMosB.cmosB;

cmosNDif:		PUBLIC CD.Layer _ CMosB.ndif;
cmosPDif:			PUBLIC CD.Layer	_ CMosB.pdif;
cmosWPDif:		PUBLIC CD.Layer	_ CMosB.wpdif;
cmosWNDif:		PUBLIC CD.Layer	_ CMosB.wndif;
cmosPoly:			PUBLIC CD.Layer	_ CMosB.pol;
cmosMet:			PUBLIC CD.Layer	_ CMosB.met;
cmosMet2:		PUBLIC CD.Layer	_ CMosB.met2;
cmosPWCont:		PUBLIC CD.Layer	_ CMosB.pwellCont;
cmosNWCont:	PUBLIC CD.Layer	_ CMosB.nwellCont;
cmosNWell:		PUBLIC CD.Layer	_ CMosB.nwell;

lambda:			PUBLIC INT	_	CMosB.lambda;

pwrW:			PUBLIC INT	_	5*lambda;
metW:				PUBLIC INT	_	3*lambda;
met2W:			PUBLIC INT	_	4*lambda;
polW:				PUBLIC INT	_	2*lambda;
difW:				PUBLIC INT	_	2*lambda;

topTail:			PUBLIC INT	_	2*lambda;
leftTail:			PUBLIC INT	_	6*lambda;	-- to center of 0th channel
rightTail:			PUBLIC INT	_	2*lambda;	-- metPitch-leftTail
botTail:			PUBLIC INT	_	1*lambda;

cnctSize: 			PUBLIC INT	_  4*lambda;
metPitch: 		PUBLIC INT	_  8*lambda;
met2Pitch: 		PUBLIC INT	_  8*lambda;
polMuxPitch: 	PUBLIC INT	_  8*lambda;
polPitch: 			PUBLIC INT	_  6*lambda;	-- without adjacent contacts

Contact: PUBLIC PROC[layer: CD.Layer] RETURNS[cntc: CD.Object] = {
RETURN[SELECT layer FROM
cmosMet2, cmosPoly, cmosNDif, cmosPDif, cmosWPDif, cmosWNDif	=>
CDSimpleRules.Contact[cmosMet, layer],
cmosPWCont, cmosNWCont	=>
CMosBObjects.CreateDifCon[layer],
ENDCASE	=> ERROR]};

TransistorObject: PUBLIC PROC[size: CD.Position, difLayer: CD.Layer]
RETURNS[trans: CD.Object]=
{trans _ CMosBObjects.CreateTransistor[size: size, difLayer: difLayer]};

textCache: CD.Design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];

ScaledText: PUBLIC PROC[text: ROPE, box: CD.Position, layer: CD.Layer, design: CD.Design_NIL]
RETURNS[cell: CD.Object _ NIL] = {
MakeName: PROC[fontIndex: INT] RETURNS[name: ROPE] = {
name _ IO.PutFR["Label%g-%g[%g]", IO.int[fontIndex], IO.int[scaleFactor], IO.rope[text]]};
Scale: PROC[font: Imager.Font] RETURNS[scale:		INT] = {
extents:	ImagerFont.Extents _ ImagerFont.RopeBoundingBox[font, text];
strSize:	CD.Position;
IF box.x<4 OR box.y<4 THEN RETURN[0];
strSize.x	_ Real.RoundI[extents.rightExtent+extents.leftExtent];
strSize.y	_ Real.RoundI[extents.ascent+extents.descent];
scale		_ MIN[box.x/strSize.x, box.y/strSize.y]};
scaleFactor: INT;
IF design=NIL THEN design _ textCache;
IF text.Length[]=0 THEN text _ "<no name>";
scaleFactor _ Scale[font2];
IF scaleFactor>0 THEN {
cell _ CDDirectory.Fetch[design, MakeName[2]].object;
IF cell=NIL THEN {
cell _ CDCreateLabels.CreateTextCell[design, text, font2, scaleFactor, layer];
[] _ CDDirectory.Include[design, cell, MakeName[2]];
RETURN[cell]} };
scaleFactor _ Scale[font1];
IF scaleFactor>0 THEN {
cell _ CDDirectory.Fetch[design, MakeName[1]].object;
IF cell=NIL THEN {
cell _ CDCreateLabels.CreateTextCell[design, text, font1, scaleFactor, layer];
[] _ CDDirectory.Include[design, cell, MakeName[2]];
RETURN[cell]} };
RETURN[NIL] };

ShowModule:	PUBLIC PROC[name: ROPE, design: CD.Design _ NIL] = {
frameCT: CellType;
new: BOOL _ design=NIL;
mainObj, decoratedObj: CD.Object;
IF new THEN {
design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
CDSimpleOps.RenameDesign[design, name]};
frameCT _ CoreFrame.ReadFrameCache[name];
IF frameCT=NIL THEN Signal[];
IF frameCT=NIL THEN RETURN;
mainObj _ CoreFrame.Layout[frameCT];
[] _ CDDirectory.Include[design, mainObj, name];
decoratedObj	_ OrnateFrame[frameCT, design];
[] _ CDDirectory.Include[design, decoratedObj, Rope.Cat["Ornate", name]];
IF new THEN CDOps.IncludeObjectI[design, decoratedObj,	[0, 0]];
CDCleanUp.CleanUp[ design, NIL];
[ ] _ CDViewer.CreateViewer[design]};


IF metW	#	CDSimpleRules.MinWidth[cmosMet]	THEN ERROR;
IF met2W	#	CDSimpleRules.MinWidth[cmosMet2]	THEN ERROR;
IF polW	#	CDSimpleRules.MinWidth[cmosPoly]	THEN ERROR;
IF difW	#	CDSimpleRules.MinWidth[cmosNDif]	THEN ERROR;

Sinix.RegisterExtractProc[$CCDUtilsBlankCell, BlankExtractProc];

END.




��„��CCDUtilsImpl.mesa
Copyright c 1985 by Xerox Corporation.  All rights reserved.
Last Edited by Curry, June 11, 1986 11:28:30 pm PDT

Side:		TYPE		= PWPins.Side;

BlankObj: PUBLIC PROC[size: CD.Position] RETURNS[cell: CD.Object] ~ {
cellPtr:	CD.CellPtr;
found:	BOOL _ FALSE;
name:		ROPE _ IO.PutFR["Dummy-%g-%g", IO.int[size.x], IO.int[size.y]];
IF size.x=0 OR size.y=0 THEN RETURN[NIL];
cell _ Fetch[name];
IF cell#NIL THEN RETURN[cell];
cell		_ CDCells.CreateEmptyCell[];
cellPtr	_ NARROW[cell.specificRef];
cellPtr.contents _ CONS[NEW[CD.InstanceRep _
[ob: CDRects.CreateRect[size, CD.backgroundLayer]] ], cellPtr.contents];
Store[name, cell]};

textOb	_ CDTexts.CreateText[pins[i].name, font, layer];
IF (size.x MOD 2)=1 OR (size.y MOD 2)=1 OR size.x<0 OR size.y<0
Only metal2 left/right or metal1 top/bottom power is included
Add sorted by name, wire, layer, min, max - - - merge overlaps


InsertModule: PUBLIC PROC
[cell: CellType, name: ROPE _ NIL, design: CD.Design] = {
new: BOOL _ design=NIL;
mainObj, decoratedObj: CD.Object;
name _ CoreName.CellNm[cell, name].n;
IF new THEN {
design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
CDSimpleOps.RenameDesign[design, name]};
CoreFrame.Expand[hard, cell];
CoreFrame.NameFrame[cell, name];
[ ] _ CoreGlue.RouteHard[cell];
mainObj _ CoreFrame.Layout[cell];
[] _ CDDirectory.Include[design, mainObj, name];
decoratedObj	_ OrnateFrame[cell, design];
[] _ CDDirectory.Include[design, decoratedObj, Rope.Cat["Ornate", name]];
IF new THEN CDOps.IncludeObjectI[design, decoratedObj,	[0, 0]];
CDCleanUp.CleanUp[ design, NIL];
[ ] _ CDViewer.CreateViewer[design];
[ ] _ CDIO.WriteDesign[design, design.name] };
InsertModule: PUBLIC PROC[cell:CellType, name: ROPE _ NIL, design: CD.Design _NIL]={
name _ CoreName.CellNm[cell, name].n;
CoreFrame.Expand[hard, cell];
CoreFrame.NameFrame[cell, name];
[ ] _ CoreGlue.RouteHard[cell];
CoreFrame.WriteFrameCheckPoint[cell]};
Ê)��˜�šœ™Jšœ<™<J™3J™�—šÏk	˜	JšœœŸœœ7˜ð—J˜�šÏnœœ˜Jšœ	œ‡œœ6˜ÕJšœ˜Jš˜J˜�Jšžœœœ˜Jšœœ
œ˜Jšœœ˜%Jšœœ˜%Jšœœ˜$Jšœœ˜$Jšœœ
œ˜Jšœ
œ˜ Jšœœ™Jšœœ˜J˜�šœ˜JšœG˜G—Jšžœœœœ2˜Rš
žœœœœœ
˜1Jšœœœ%œ˜@—J˜�šžœœœœœœ˜EJš	œœœœœ˜GJšœœ˜Jš
œ
œ
œœœ˜)Jšœ˜Jšœœœœ˜Jšœ!˜!šœœœœ˜9JšœœH˜Ušœ˜Jšœœœœ˜:Jšœœ@˜HJšœœ@˜HJšœœ'˜/Jšœœ0˜8Jšœœ'˜/Jšœœ0˜8——Jšœžœ˜Jšœ˜J™�—šžœœœœœœ™EJšœ	œ	™Jšœœœ™Jš	œœœœœ™FJš
œ
œ
œœœ™)Jšœ™Jšœœœœ™Jšœ"™"Jšœ
œ™#šœœœœ™,Jšœœ(™H—Jšœ™—J˜�š
ž	œœœœœ˜EJšœœ˜ JšœW˜WJšœ+˜+Jšœ!˜!Jšœ>˜>—J˜�šžœœœ˜9Jšœ"œ$˜IJšœ'˜'šœ
œ˜"Jšœ$˜$Jšœ˜Jšœ˜Jšœœ˜——J˜�šžœ˜'Jšœœ˜Jšœ-˜-Jšœ2˜2—J˜�šžœœœœ	œœ˜<Jš
œœœœœ˜Jš
œœœœœ˜(Jšœœœœ
œœœ˜<Jšœœœ˜2—J˜�šžœœœœ	œœ˜AJšœœœ˜—J™�šœ)˜)Jšœ$œ
œœ˜R—šœ)˜)Jšœ%œ
œœ˜S—J˜�šžœœ(˜@Jšœ
œ˜Jšœ˜Jšœ	œ
˜Jšœœ
˜Jšœœœœ˜#Jšœ	œ˜šœ&˜(Jšœœ˜'Jšœ˜—Jšœ$˜$Jšœ%˜%Jšœ
œ˜"Jšœ	œ(˜3šœœ˜Jšœœœœ˜3Jšœœ
˜Jšœœ
˜Jšœœ˜Jšœœœœ˜Jšœ+˜+šœœœ˜4šœ˜Jšœ+œ˜D—Jšœ7™7Jšœœ˜Jšœ
œ:˜GJšœ˜šœ	œ˜Jšœ ˜ Jšœ*˜*Jšœœ˜—Jšœœ,˜4Jš˜—šœ˜Jšœ"˜"Jšœ"˜"Jšœœ˜—šœ˜Jšœ=˜=Jšœ?˜?Jšœ=˜=Jšœ>˜>Jšœœ˜—Jšœ@˜@Jšœ2˜2Jšœœ5˜=Jšœ˜—Jšœ,˜,—J˜�J˜�šžœœœœœœœ˜_Jšœ	œœ	œœ
œ	™?šœœ	˜šœ˜Jšœ+œœ˜NJšœ
˜
——Jšœ
œ
œœ˜$Jšœœ<˜C—J˜�J™=šžœœœ(˜@Jš
œœœœœ˜'Jšœ˜Jšœ˜šžœ˜'šžœ˜0Jšœœœ˜Jšœ/œœœ˜D—Jšœœ˜&Jšœœœ˜šœœI˜OJšœœ˜—šœœ˜(Jš
œœœœœ˜9—šœ5œ˜=JšœP˜P—Jšœœœœ˜Jšœ<˜<—šœ5˜7Jšœœœ˜?—Jšœ4˜4Jšž
œ˜—J˜�Jšœ>™>šžœœœœœœœ˜<Jšœœœœ˜Jš
œœœœœ˜?Jšœœœœœœ˜(š	œœœœ˜%šœ!œœœ
˜HJšœœœ˜7Jšœ'˜+—šœ˜Jšœ˜ Jšœ˜šœœ˜ Jšœœ˜*Jšœœ˜*Jšœ˜
——šœ˜!Jšœ˜Jšœ˜ Jšœ˜!šœœ˜"Jšœœ˜Jšœœ˜Jšœ˜Jšœ˜Jšœ˜
——Jš
œ
œœœœ˜@Jšœ˜	——J˜�šž
œœœœœœ˜2š˜Jšœœœ˜šœœœœœœœœ˜@šœ ˜$šœœ ˜FJšœœ>œ˜PJšœ˜———Jšœœœ˜Jšœ˜	——J˜�šž
œœœœœœœœ˜?Jšœœœœ˜Jšœœ˜šœœœ˜,Jšœœœ˜$—Jšœ˜Jš
œœœœœ˜PJšœœœ˜—J˜�šž	œœœœœœ˜8Jšœœœ˜,šœ0˜0Jšœ˜Jšœ˜Jšœ˜šœœ
˜ Jšœ˜Jšœ˜Jšœ˜Jšœ)˜0———J™�šžœœ2œœ˜^šžœœœ˜3Jšœœœœ#˜8Jš
œœœœœ-˜KJšœ˜—Jšœ	œœœ0˜FJšœ	œœœ˜3Jšœ
œ0˜>Jšœ
œ˜+Jšœœœ˜Jšœ	œ˜Jšœœœœ˜Jšœ/˜/Jšœ/˜/šœ˜
Jšœœ)˜6šœœœ˜Jšœœ
œ˜5Jšœœœœ.˜IJšœœœ˜Jšœ˜——š
œœœœœœ˜>Jšœ"œ˜*—š
œœœœœœ˜>Jšœ"œ˜*—šœG˜GJšœ˜
Jšœœ ˜4Jšœœ!˜6—š
œœœœœœ˜>Jšœœœœ1˜Fšœœœ0˜EJšœœœœ˜U——š
œœœœœœ˜>Jšœœœœ1˜Fšœœœ0˜EJšœœœ˜U——Jšœœ˜ J˜�—šžœœœœœœœ˜^šœœ	˜Jšœœ=˜A—Jšœ(˜(Jšœ+˜+—J˜�šž
œœœ˜Jšœ
œ˜šœ"˜"Jšœœ˜!—•StartOfExpansion= -- [app: CD.ApplicationPtr] RETURNS [quit: BOOL _ FALSE] -- šž
œ&˜3Jšœ	œ˜Jšœ	œ
˜Jšœ˜Jšœ$˜$Jšœœœ˜Jšœ"˜"Jšœœœ˜%šœ
œœ˜ Jšœ1˜1Jšœ˜Jšœ!˜!—Jšœ1˜1Jšœ,˜,Jšœœ!˜;—Jšœœ	˜Jšœœœœ˜9JšœS˜SJšœ&˜&Jšœ
œ˜+Jšœ5˜5Jšœœ˜6Jšœ#œ˜<Jšœ˜—J˜�Jšœ
œœ˜-J˜�Jšœœœ˜(Jšœœœ˜)Jšœœœ˜*Jšœœœ˜*Jšœœœ˜(Jšœœœ˜'Jšœœœ˜(Jšœ
œœ˜/Jšœœœ˜.Jšœœœ˜*J˜�Jšœ
œœ˜$J˜�Jšœœœ˜Jšœ	œœ˜Jšœ	œœ˜Jšœ	œœ˜Jšœ	œœ˜J˜�Jšœœœ˜!Jšœœœ
Ïc˜>Jšœ
œœ
Ÿ˜8Jšœœœ˜!J˜�Jšœ
œœ
˜$Jšœœœ
˜#Jšœ
œœ
˜$Jšœœœ
˜%Jšœ
œœŸ˜AJ˜�šžœœœœœœ˜Bšœœ˜šœ?˜?Jšœ&˜&—šœ˜Jšœ!˜!—Jšœœ˜J˜�——š
žœœœœœ˜Dšœœ	˜JšœH˜H——J˜�Jšœœ9˜FJ˜�šž
œœœœœœ˜]Jšœœ˜"š
žœœœœœ˜6Jš	œœœœœ˜Z—šžœœœ	œ˜7JšœE˜EJšœ	œ
˜Jšœ	œ	œœ˜%Jšœ@˜@Jšœ8˜8Jšœ	œ$˜0—Jšœ
œ˜Jšœœœ˜&Jšœ+˜+Jšœ˜šœœ˜Jšœ5˜5šœœ˜JšœN˜NJšœžœ˜4Jšœ
˜——Jšœ˜šœœ˜Jšœ5˜5šœœ˜JšœN˜NJšœžœ˜4Jšœ
˜——Jšœœ˜J˜�—šž
œœœœ
œ
œ˜@Jšœ˜Jšœœ
œ˜Jšœœ˜!šœœ˜
Jšœœ˜8Jšœ(˜(—Jšœ)˜)Jšœ	œœ
˜Jšœ	œœœ˜Jšœ$˜$Jšœ0˜0Jšœ,˜,JšœI˜IJšœœ4˜?Jšœœ˜ Jšœ%˜%—J™�šžœœ™Jšœœœ
œ™9Jšœœ
œ™Jšœœ™!Jšœ%™%šœœ™
Jšœœ™8Jšœ(™(—Jšœ™Jšœ ™ Jšœ™Jšœ!™!Jšœ0™0Jšœ)™)JšœI™IJšœœ4™?Jšœœ™ Jšœ$™$Jšœœ$™.—J˜�šžœœœœœ
œ	œ™TJšœ%™%Jšœ™Jšœ ™ Jšœ™Jšœ&™&—J˜�Jšœ(œœ˜5Jšœ*œœ˜7Jšœ)œœ˜6Jšœ)œœ˜6J˜�Jšœ@˜@J˜�Jšœ˜—J˜�J˜�J˜�J˜�—�…—����>¾��\k��