-- File: DisjointGather.mesa -- Finds similar cells -- Written by Martin Newell/Dan Fitzpatrick February 1981 -- Last edited (Pilot): 16-Jul-81 10:53:27 DIRECTORY DisjointGatherDefs: FROM "DisjointGatherDefs", DisjointSplitDefs: FROM "DisjointSplitDefs" USING [Split], DisjointTypes: FROM "DisjointTypes" USING [DisCell, Instance, Rectangle, Symbol, PIP, Geometry], DisjointAllocDefs: FROM "DisjointAllocDefs" USING [AllocateInstance, AllocateSymbol, FreeInstance, FreeSymbol, FreeRectangle, FreeDisCell, FreePIP, AllocateGeometry, FreeGeometry], Inline: FROM "Inline" USING [LowHalf], Real: FROM "Real" USING [Fix], XFSPDefs: FROM "XFSPDefs" USING [XAllocateHeapNode]; DisjointGather: PROGRAM IMPORTS DisjointSplitDefs, DisjointAllocDefs, Inline, Real, XFSPDefs EXPORTS DisjointGatherDefs = BEGIN OPEN DisjointTypes, DisjointSplitDefs, DisjointAllocDefs, Inline, Real, XFSPDefs; Gather: PUBLIC PROCEDURE[symbol: Symbol, DisCellList: DisCell] = BEGIN -- for each cell in the discell list, see if a Instance has been defined, -- if not create a new Instance and hash it into the InstanceTable. -- then create Instance pointing to the Instance with the correct offset next: DisCell; tmp,ptr: SCell; -- hold instances previously attached to symbol so DisCells can point to them HoldInstList[symbol.insts]; symbol.insts _ NIL; FOR a: DisCell _ DisCellList, next UNTIL a = NIL DO x: REAL; y: REAL; usymb: Symbol; next _ a.next; x _ a.windows.l; -- find offset y _ a.windows.b; usymb _ FindSymbol[a,x,y]; MakeInstance[usymb,x,y,symbol]; ENDLOOP; ptr _ SCellList; SCellList _ NIL; FOR ptr _ ptr,tmp UNTIL ptr = NIL DO tmp _ ptr.next; Expand[ptr.symbol]; FreeSCell[ptr]; ENDLOOP; END; FindSymbol: PROCEDURE[dc:DisCell, x,y: REAL] RETURNS[usymb: Symbol] = -- Returns a pointer to a Instance in the symbol table, -- creating one if necessary, which corresponds with the DisCell 'dc' -- relative to x & y BEGIN found: BOOLEAN; hash: INTEGER _ 0; SortDisCell[dc]; usymb _ AllocateSymbol[]; usymb.insts _ NIL; -- create list of instances with their relative offset FOR b:PIP _ dc.insts,b.next UNTIL b = NIL DO desc: Instance _ AllocateInstance[]; desc^ _ [ next: NIL, symbol: b.inst.symbol, xOffset: b.inst.xOffset - x, yOffset: b.inst.yOffset - y ]; -- add desc into usymb's desc list desc.next _ usymb.insts; usymb.insts _ desc; -- make hash function hash _ hash + (LowHalf[desc.symbol] + LowHalf[Fix[3*(desc.xOffset)]+Fix[13*(desc.yOffset)]]); ENDLOOP; -- can let new symbol point to window list since neither DisCells or window will -- change the contents of the window list. (Free window list if found dc already -- in DisCell table and freeing new symbol.) usymb.windows _ dc.windows; FOR b:Rectangle _ usymb.windows,b.next UNTIL b = NIL DO -- make windows relative to symbol origin b.l _ b.l - x; b.b _ b.b - y; b.r _ b.r - x; b.t _ b.t - y; -- make hash function hash _ hash + LowHalf[Fix[b.l + 5*b.b + 11*b.r + b.t]]; ENDLOOP; -- Add geometry of symbol from DisCell usymb.geom _ NIL; FOR gptr: Geometry _ dc.geom,gptr.next UNTIL gptr = NIL DO g: Geometry _ AllocateGeometry[]; -- make geometry relative to symbol origin gptr.l _ gptr.l - x; gptr.b _ gptr.b - y; gptr.r _ gptr.r - x; gptr.t _ gptr.t - y; g^ _ [ next: usymb.geom, layer: gptr.layer, l: gptr.l, b: gptr.b, r: gptr.r, t: gptr.t ]; usymb.geom _ g; -- make hash function hash _ hash + LowHalf[Fix[g.l + g.b + g.r + 7*g.t + 17*g.layer]]; ENDLOOP; found _ FALSE; hash _ ABS[hash MOD TblSize]; FOR ptr:DisCell _ DisCellTable[hash],ptr.next UNTIL ptr = NIL DO IF SameDisCell[dc,ptr] THEN { next: Rectangle; -- Free windows attached to usymb & dc FOR w:Rectangle _ usymb.windows, next UNTIL w = NIL DO next _ w.next; FreeRectangle[w]; ENDLOOP; -- release usymb ReleaseSymbol[usymb]; -- release dc ReleaseDisCell[dc]; -- make usymb point to ptr usymb _ ptr.symbol; found _ TRUE; EXIT; --this loop } ENDLOOP; IF NOT found THEN { -- add usymb to Symbol Table sCell: SCell; dc.symbol _ usymb; dc.next _ DisCellTable[hash]; DisCellTable[hash] _ dc; -- also mark this symbol to be expanded later sCell _ AllocSCell[]; sCell.next _ SCellList; SCellList _ sCell; sCell.symbol _ usymb; } END; SameDisCell: PROCEDURE[dc1,dc2: DisCell] RETURNS[BOOLEAN] = BEGIN --Returns true if us1 and us2 represent same comibnation of primInstances -- and window boxes are the same pip1: PIP _ dc1.insts; pip2: PIP _ dc2.insts; xOffset: REAL _ pip2.inst.xOffset - pip1.inst.xOffset; yOffset: REAL _ pip2.inst.yOffset - pip1.inst.yOffset; IF pip1.inst.symbol # pip2.inst.symbol THEN RETURN[FALSE]; -- first symbols are the same, check the rest of the symbols and their -- relative offsets. pip1 _ pip1.next; pip2 _ pip2.next; UNTIL pip1 = NIL DO IF pip2 = NIL THEN RETURN[FALSE]; IF pip1.inst.symbol # pip2.inst.symbol THEN RETURN[FALSE]; IF pip1.inst.xOffset # pip2.inst.xOffset - xOffset THEN RETURN[FALSE]; IF pip1.inst.yOffset # pip2.inst.yOffset - yOffset THEN RETURN[FALSE]; pip1 _ pip1.next; pip2 _ pip2.next; ENDLOOP; IF pip2 # NIL THEN RETURN[FALSE]; -- Now check geometry IF NOT SameGeometry[dc1.geom,dc2.geom,xOffset,yOffset] THEN RETURN[FALSE]; -- Now check window list IF NOT SameWindow[dc1.windows,dc2.windows] THEN RETURN[FALSE]; RETURN[TRUE]; END; SameGeometry: PROCEDURE[g1,g2:Geometry, xOffset,yOffset:REAL] RETURNS[BOOLEAN] = -- Returns true if r1 and r2 are the same list of rectangles BEGIN UNTIL g1 = NIL DO IF g2 = NIL THEN RETURN[FALSE]; IF g1.layer # g2.layer THEN RETURN[FALSE]; IF g1.r # g2.r - xOffset THEN RETURN[FALSE]; IF g1.l # g2.l - xOffset THEN RETURN[FALSE]; IF g1.t # g2.t - yOffset THEN RETURN[FALSE]; IF g1.b # g2.b - yOffset THEN RETURN[FALSE]; g1 _ g1.next; g2 _ g2.next; ENDLOOP; IF g2 # NIL THEN RETURN[FALSE]; RETURN[TRUE]; END; SameWindow: PROCEDURE[r1,r2:Rectangle] RETURNS[BOOLEAN] = -- Returns true if r1 and r2 are the same list of rectangles BEGIN UNTIL r1 = NIL DO IF r2 = NIL THEN RETURN[FALSE]; IF r1.r # r2.r THEN RETURN[FALSE]; IF r1.l # r2.l THEN RETURN[FALSE]; IF r1.t # r2.t THEN RETURN[FALSE]; IF r1.b # r2.b THEN RETURN[FALSE]; r1 _ r1.next; r2 _ r2.next; ENDLOOP; IF r2 # NIL THEN RETURN[FALSE]; RETURN[TRUE]; END; SortDisCell: PROCEDURE[dc:DisCell] = BEGIN list: PIP _ NIL; next: PIP; -- first sort all the instances of dc onto list FOR pip: PIP _ dc.insts,next UNTIL pip = NIL DO next _ pip.next; IF list=NIL OR InstanceLessThan[pip.inst,list.inst] THEN { pip.next _ list; list _ pip; } ELSE { a:PIP; FOR a _ list,a.next UNTIL a.next = NIL DO IF InstanceLessThan[pip.inst,a.next.inst] THEN EXIT; ENDLOOP; pip.next _ a.next; a.next _ pip; } ENDLOOP; -- list is now sorted, make dc point to this list dc.insts _ list; -- now sort the geometry of the discell SortDisCellGeometry[dc]; END; SortDisCellGeometry: PROCEDURE[dc:DisCell] = BEGIN list: Geometry _ NIL; next: Geometry; -- first sort all the geometry of dc onto list FOR rec: Geometry _ dc.geom,next UNTIL rec = NIL DO next _ rec.next; IF list=NIL OR GeometryLessThan[rec,list] THEN { rec.next _ list; list _ rec; } ELSE { a:Geometry; FOR a _ list,a.next UNTIL a.next = NIL DO IF GeometryLessThan[rec,a.next] THEN EXIT; ENDLOOP; rec.next _ a.next; a.next _ rec; } ENDLOOP; -- list is now sorted, make dc point to this list dc.geom _ list; END; InstanceLessThan: PROCEDURE[p1,p2:Instance] RETURNS[BOOLEAN] = BEGIN c1: LONG CARDINAL _ LOOPHOLE[p1.symbol]; c2: LONG CARDINAL _ LOOPHOLE[p2.symbol]; RETURN[c1