DIRECTORY CD, CDBasics, CDDesignRules, PW, Stix, StixCompact, StixParser, TerminalIO; StixCompactImpl: CEDAR PROGRAM IMPORTS CDDesignRules, PW, Stix, StixParser EXPORTS StixCompact = BEGIN OPEN Stix, StixCompact; x: BOOL = TRUE; y: BOOL = ~x; GetCoord: PROC [pos: Position, inX: BOOL] RETURNS [INT] ~ { RETURN [IF inX THEN pos.x ELSE pos.y]}; 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"]; }; MakeGraph: PROC [cellType: CellType, inX: BOOL] RETURNS [graph: Graph] = { InsertInGroup: EachStickPtrProc = { SELECT stickPtr.class FROM contactClass, transistorClass => { c: INT _ GetCoord[Origin[stickPtr].pos, inX]; graph[c].insts _ CONS[stickPtr, graph[c].insts]; }; wireClass => { c: INT _ GetCoord[Origin[stickPtr].pos, inX]; graph[c].insts _ CONS[stickPtr, graph[c].insts]; c _ GetCoord[OtherEnd[stickPtr].pos, inX]; graph[c].insts _ CONS[stickPtr, graph[c].insts]; }; ENDCASE => ERROR; }; graph _ NEW[GraphRec[1000]]; -- adjust with IRect FOR l: Nodes _ AllNodes[GetStickPtr[cellType]], l.rest WHILE l#NIL DO node: Node _ l.first; coord: INT _ GetCoord[node.pos, inX]; IF graph[coord]=NIL THEN graph[coord] _ NEW [GroupRec _ [coord: coord]]; graph[coord].nodes _ CONS[node, graph[coord].nodes]; ENDLOOP; [] _ EnumerateInsts[cellType, InsertInGroup]; }; 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 = { xFirst: BOOL _ TRUE; graph: Graph _ MakeGraph[cellType, x]; Stix.Explode[GetStickPtr[cellType], dr]; CompactStickCell[dr, graph, cellType, x, xFirst]; }; CompactStickCell: PROC [dr: DRules, graph: Graph _ NIL, cellType: CellType, inX, xFirst: BOOL] = { 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; 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, graph[pred].newCoord+dist]; ENDLOOP; group.newCoord _ max; ENDLOOP; 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; }; 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}}; 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; }; 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; }; 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]; }; END. Brag: PROC [newCell: Object] ~ { size: CD.Position _ CD.InterestSize[newCell]; TerminalIO.WriteRope["The new cell: dx="]; TerminalIO.WriteInt[size.x/lambda]; TerminalIO.WriteRope[" lambda, dy="]; TerminalIO.WriteInt[size.y/lambda]; TerminalIO.WriteRope[" lambda, area="]; TerminalIO.WriteInt[size.x*size.y/(lambda*lambda)]; TerminalIO.WriteLn[]; }; bStixCompactImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Louis Monier December 6, 1985 2:08:45 pm PST Convenient for axis-independance Commands 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"]; }; Group formation -- First cut: the virtual grid! All nodes with the same coordinate make a group Compaction [cellType: CellType, dr: DRules] 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 -- Compute the coordinate of each group -- coord[i] = max of coord[j]+minDist[i, j] over all pred. j max _ MAX[max, IF dist=0 AND ~l.first.hasPinOnexternalEdge THEN 0 ELSE preds.first.newCoord+dist]; -- and update the nodes which have to be updated! -- 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; -- The distance between the two centerlines -- 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 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. 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]; }; Utilities -- Bragging about the new-born cell Κ ˜šœ™Icodešœ Οmœ1™