Commands
SimpleExpand:
PUBLIC
PROC [from, to:
CD.Design, stCell: Object]
RETURNS [mosOb: Object] = {
cellType: CellType ← StixParser.InputStix[stCell, from];
stickCell: StickPtr ← GetStickPtr[cellType];
dr: CDDesignRules.DesignRules ← CDDesignRules.FindRules[from.technology.key];
Stix.ConvertToDR[cellType, dr];
mosOb ← Stix.Layout[stickPtr: stickCell, cell: NIL, dr: dr].ob;
PW.IncludeInDirectory[to, mosOb, "Brand-New"];
};
CompactXYCmd: PUBLIC PROC [from, to: CD.Design, stCell: Object] RETURNS [mosOb: Object] = {
cellType: CellType ← StixParser.InputStix[stCell, from];
stickCell: StickPtr ← NARROW[CoreProperties.GetCellTypeProp[cellType, layoutProp]];
dr: CDDesignRules.DesignRules ← CDDesignRules.FindRules[from.technology.key];
Stix.ConvertToDR[stickCell, dr];
CompactXY[stickCell, dr];
mosOb ← Stix.Layout[stickPtr: stickCell, cell: NIL, dr: dr].ob;
PW.IncludeInDirectory[to, mosOb, "Brand-New"];
};
Compaction
CompactXCmd:
PUBLIC
PROC [from, to:
CD.Design, stCell: Object]
RETURNS [mosOb: Object] = {
cellType: CellType ← StixParser.InputStix[stCell, from];
stickCell: StickPtr ← GetStickPtr[cellType];
dr: CDDesignRules.DesignRules ← CDDesignRules.FindRules[from.technology.key];
Stix.ConvertToDR[cellType, dr];
CompactX[cellType, dr];
mosOb ← Stix.Layout[stickPtr: stickCell, cell: NIL, dr: dr].ob;
PW.IncludeInDirectory[to, mosOb, "Compacted-X"];
};
CompactX:
PUBLIC CompactProc = {
[cellType: CellType, dr: DRules]
xFirst: BOOL ← TRUE;
graph: Graph ← MakeGraph[cellType, x];
Stix.Explode[GetStickPtr[cellType], dr];
CompactStickCell[dr, graph, cellType, x, xFirst];
};
CompactXY: PUBLIC CompactProc = {
groups: Groups;
xFirst: BOOL ← TRUE;
groups ← FormGroups[cell, x];
Stix.Explode[cell, dr];
CompactStickCell[dr, groups, cell, x, xFirst];
groups ← FormGroups[cell, y];
Stix.Explode[cell, dr];
CompactStickCell[dr, groups, cell, y, xFirst];
};
-- From left to right, compute the minimum separation between groups and update the nodes
CompactStickCell:
PROC [dr: DRules, graph: Graph ←
NIL, cellType: CellType, inX, xFirst:
BOOL] = {
-- Compute the coordinate of each group
tab: Tab ← NARROW[GetStickPtr[cellType].data, StickCell].tab;
FOR i:
NAT
IN [0..graph.size)
DO
dist, formerCoord, max: INT;
group: Group ← graph[i];
IF group=NIL THEN LOOP;
dist ← 0;
formerCoord ← group.coord;
max ← 0;
-- coord[i] = max of coord[j]+minDist[i, j] over all pred. j
FOR pred:
NAT
DECREASING
IN [0..i)
DO
IF graph[pred]=NIL THEN LOOP;
IF graph[pred].coord>=group.coord THEN EXIT;
dist ← MinSepGroup[dr, graph[pred], group, tab, inX, xFirst];
max ← MAX[max, IF dist=0 AND ~l.first.hasPinOnexternalEdge THEN 0 ELSE preds.first.newCoord+dist];
max ← MAX[max, graph[pred].newCoord+dist];
ENDLOOP;
group.newCoord ← max;
ENDLOOP;
-- and update the nodes which have to be updated!
FOR i:
NAT
IN [0..graph.size)
DO
group: Group ← graph[i];
IF group=NIL THEN LOOP;
FOR l: Nodes ← group.nodes, l.rest
WHILE l#
NIL
DO
Update[l.first, group.coord, group.newCoord, inX];
ENDLOOP;
ENDLOOP;
-- special hack for the transistors
FOR stickPtrs: StickPtrs ← stickCell.insts, stickPtrs.rest WHILE stickPtrs#NIL DO
stickPtr: StickPtr ← stickPtrs.first;
IF stickPtr.type#transistor THEN LOOP;
IF stickPtr.isVertical THEN {
stickPtr.node2.pos ← CDBasics.SubPoints[stickPtr.node1.pos, [0, gateSDNodeSpacing]];
stickPtr.node3.pos ← CDBasics.AddPoints[stickPtr.node1.pos, [0, gateSDNodeSpacing]];}
ELSE {
stickPtr.node2.pos ← CDBasics.SubPoints[stickPtr.node1.pos, [gateSDNodeSpacing, 0]];
stickPtr.node3.pos ← CDBasics.AddPoints[stickPtr.node1.pos, [gateSDNodeSpacing, 0]];};
ENDLOOP;
};
Update:
PROC [n: Node, former, new:
INT, inX:
BOOL] = {
IF n=NIL THEN RETURN;
IF inX THEN {IF n.pos.x=former THEN n.pos.x ← new} ELSE {IF n.pos.y=former THEN n.pos.y ← new}};
-- The distance between the two centerlines
MinSepGroup:
PROC [dr: DRules, group1, group2: Group, tab: Tab, inX, xFirst:
BOOL]
RETURNS [d:
INT ← 0] = {
FOR l1: StickPtrs ← group1.insts, l1.rest
WHILE l1#
NIL
DO
FOR l2: StickPtrs ← group2.insts, l2.rest
WHILE l2#
NIL
DO
IF l1.first#l2.first THEN d ← MAX[d, MinSepPlates[dr, l1.first.plates, l2.first.plates, group1.coord, group2.coord, tab, inX, xFirst]];
ENDLOOP;
ENDLOOP;
};
MinSepPlates:
PROC [dr: DRules, plates1, plates2: Plates, g1Coord, g2Coord:
INT, tab: Tab, inX, xFirst:
BOOL]
RETURNS [dist:
INT ← 0] = {
FOR l1: Plates ← plates1, l1.rest
WHILE l1#
NIL
DO
FOR l2: Plates ← plates2, l2.rest
WHILE l2#
NIL
DO
dist ← MAX[dist, MinSepPlate[dr, l1.first, l2.first, g1Coord, g2Coord, tab, inX, xFirst]];
ENDLOOP;
ENDLOOP;
};
-- Rules: sep is distance between layers; 0 means they can overlap
sep=0 OR (sep#0, same layer, connected) => 0
sep#0, different layers OR (same layer, not connected) => sep+1/2 size
MinSepPlate:
PROC [dr: DRules, plate1, plate2: Plate, g1Coord, g2Coord:
INT, tab: Tab, inX, xFirst:
BOOL]
RETURNS [dist:
INT ← 0] = {
connected: BOOL ← PlatesAreConnected[plate1, plate2, tab];
r1: CD.Rect ← plate1.dr.r;
r2: CD.Rect ← plate2.dr.r;
lay1: Layer ← plate1.dr.lev;
lay2: Layer ← plate2.dr.lev;
sep, thickness: INT;
sep ←
IF connected
THEN CDDesignRules.MinConnectedDist[dr, lay1, lay2]
ELSE CDDesignRules.MinDist[dr, lay1, lay2];
IF ~Facing[r1, r2, sep, inX, xFirst] THEN RETURN; -- not facing each other
thickness ← IF inX THEN (r1.x2-g1Coord+g2Coord-r2.x1) ELSE (r1.y2-g1Coord+g2Coord-r2.y1);
dist ← IF sep=0 THEN 0 ELSE sep+thickness;
IF sep=0 OR (connected AND lay1=lay2) THEN dist ← 0
ELSE dist ← sep+thickness;
};
-- X compaction: Just facing from left to right
-- Y compaction: Facing from top to bottom, but corner checking as well by extending r1 by "diagonal" on both sides.
Facing:
PROC [r1, r2:
CD.Rect, diagSep:
INT, inX, xFirst:
BOOL]
RETURNS [
BOOL] ~ {
delta: INT ← IF inX#xFirst THEN diagSep ELSE 0;
IF inX THEN RETURN [r1.y2+delta>r2.y1 AND r2.y2>r1.y1-delta]
ELSE RETURN [r1.x2+delta>r2.x1 AND r2.x2>r1.x1-delta];
};
CompactYX: PUBLIC CompactProc = {
groups: Groups;
stickCell: StickCell ← InputStix[stCell, to];
xFirst: BOOL ← FALSE;
Extract[stickCell];
groups ← FormGroups[stickCell, y];
CompactStickCell[groups, stickCell, y, xFirst];
Extract[stickCell];
groups ← FormGroups[stickCell, x];
CompactStickCell[groups, stickCell, x, xFirst];
mosCell ← LayoutStickCell[stickCell, to];
Brag[mosCell];
};