DIRECTORY
CD, CDBasics, CDDirectory, CDInstances, CDSimpleRules, CDSymbolicObjects, CMosB, Core, CoreClasses, CoreOps, CoreProperties, HashTable,
IO, OnionCore, OnionCoreArc,
PW, PWCore, PWPins, Rope, Sinix;
CRPadFrame:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDDirectory, CDInstances, CDSimpleRules, CDSymbolicObjects, CMosB, CoreOps, CoreProperties, HashTable, IO, OnionCore, PW, PWCore, PWPins, Rope, Sinix =
BEGIN
LayoutCRPadFrame: PWCore.LayoutProc = {
AddInnerPinsToNets:
PROC [wire: Wire] = {
EachPin: PWCore.EachPinProc = {
seg: Seg;
IF layer#CMosB.met
THEN {
PW.WriteF["*** Inner pin %g not made of met but of %g discarded\n", IO.rope[name], IO.atom[CD.LayerKey[layer]]];
RETURN;
};
SELECT side
FROM
top, bottom => {min ← min + innerPos.x; max ← max + innerPos.x};
left, right => {min ← min + innerPos.y; max ← max + innerPos.y};
ENDCASE => ERROR;
seg ←
SELECT side
FROM
top, left => NEW [OnionCoreArc.SegRec ← [max, min, side, side]],
bottom, right => NEW [OnionCoreArc.SegRec ← [min, max, side, side]],
ENDCASE => ERROR;
net.innerSegs ← CONS [seg, net.innerSegs];
};
name: ROPE ← CoreOps.GetFullWireName[innerCT.public, wire];
net: Net ← NARROW [HashTable.Fetch[nets, name].value];
IF net=NIL THEN net ← NEW [OnionCore.NetRec ← [name: name]];
IF Rope.Equal[name, "Vdd"] THEN net.width ← 200*CMosB.lambda;
IF Rope.Equal[name, "Gnd"] THEN net.width ← 96*CMosB.lambda;
IF Rope.Equal[name, "Net3"] THEN {net.routeEveryOuterSeg ← FALSE};
[] ← PWCore.EnumeratePins[innerCT, wire, EachPin];
[] ← HashTable.Store[nets, name, net];
};
EachOuterPin: PWPins.InstanceEnumerator = {
seg: Seg;
name: ROPE ← CDSymbolicObjects.GetName[inst];
layer: CD.Layer ← CDSymbolicObjects.GetLayer[inst];
side: PWPins.Side ← PWPins.GetSide[outer, inst];
pos: CD.Position ← CDBasics.BaseOfRect[CDInstances.InstRectO[inst]];
min, max: INT;
net: Net ← NARROW [HashTable.Fetch[nets, name].value];
IF layer#CMosB.met
THEN {
PW.WriteF["*** Outer pin %g not made of met but of %g discarded\n", IO.rope[name], IO.atom[CD.LayerKey[layer]]];
RETURN;
};
IF net=
NIL
THEN {
PW.WriteF["*** Outer pin %g discarded (no corresponding inner pin)\n", IO.rope[name]];
RETURN;
};
SELECT side
FROM
top, bottom => {min ← pos.x-outerBase.x; max ← min + inst.ob.size.x};
left, right => {min ← pos.y-outerBase.x; max ← min + inst.ob.size.y};
ENDCASE => ERROR;
seg ←
SELECT side
FROM
top, left => NEW [OnionCoreArc.SegRec ← [max, min, side, side]],
bottom, right => NEW [OnionCoreArc.SegRec ← [min, max, side, side]],
ENDCASE => ERROR;
net.outerSegs ← CONS [seg, net.outerSegs];
};
PutDummyPins: PROC [wire: Wire] = {Sinix.PutPinsProp[PWCore.extractMode, wire, LIST [PWPins.NewInstance[CDSimpleRules.Rect[[16, 16], CMosB.met]]]]};
design: CD.Design ← NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreSourceDesign]];
recordData: CoreClasses.RecordCellType = NARROW [cellType.data];
innerCT, outerCT: CellType;
inner, outer: CD.Object;
nets: HashTable.Table ← HashTable.Create[5, HashTable.RopeEqual, HashTable.HashRope];
innerPos, outerBase: CD.Position;
IF Rope.Equal[CoreOps.GetCellTypeName[recordData[0].type], "CrossRAMInner"]
THEN {innerCT ← recordData[0].type; outerCT ← recordData[1].type}
ELSE {outerCT ← recordData[0].type; innerCT ← recordData[1].type};
inner ← PWCore.Layout[innerCT];
outer ← CDDirectory.Fetch[design, "CrossRAMPadFrame.mask"].object;
innerPos ← OnionCore.Center[inner, outer];
outerBase ← CDBasics.BaseOfRect[CD.InterestRect[outer]];
innerPos ← [107*CMosB.lambda, 27*CMosB.lambda];
innerPos ← [107*CMosB.lambda, 2722*CMosB.lambda];
obj ← PW.CreateEmptyCell[];
CoreOps.VisitAtomicWires[innerCT.public, AddInnerPinsToNets];
[] ← PWPins.EnumerateDeepPins[outer, EachOuterPin];
[] ← PW.IncludeInCell[obj, inner, innerPos];
[] ← PW.IncludeInCell[obj, outer];
IF NOT OnionCore.IncludeInOuter[obj, nets, innerPos, CD.InterestSize[inner], CD.InterestSize[outer]] THEN PW.WriteF["*** Did not finish properly!\n"];
PW.RepositionCell[obj];
CoreOps.VisitAtomicWires[cellType.public, PutDummyPins];
};
[] ← PWCore.RegisterLayoutAtom[$CRPadFrame, LayoutCRPadFrame, DecorateCRPadFrame];