<> <> <> <<>> DIRECTORY BasicTime, CCDUtils, CD, CDOrient, CDBasics, Core, CoreBlock, CoreClasses, CoreCreate, CoreFrame, CoreGlue, CoreInstCell, CoreIO, CoreName, CoreOps, CoreProperties, IO, LayoutCheckpoint, PW, PWCore, Rope, ViewerIO, WatchStats, WriteCapa; CoreFrameImpl: CEDAR PROGRAM IMPORTS BasicTime, CCDUtils, CDOrient, CDBasics, CoreBlock, CoreClasses, CoreCreate, CoreFrame, CoreGlue, CoreInstCell, CoreIO, CoreName, CoreOps, CoreProperties, IO, LayoutCheckpoint, PW, PWCore, Rope, ViewerIO, WatchStats, WriteCapa EXPORTS CoreFrame = BEGIN OPEN CoreFrame; Signal: SIGNAL = CODE; frameCellClass: PUBLIC Core.CellClass _ CoreOps.SetClassPrintProc[ class: NEW[ Core.CellClassRec _ [name: "Frame", recast: RecastFrameSoft]], proc: ClassPrintProc]; ClassPrintProc: CoreOps.PrintClassProc = { frame: Frame _ NARROW [data]; LogFrameData[frame, 0, TRUE, out]; FOR ii: INT IN [0..frame.seq.size) DO LogFCT[frame.seq[ii], 1, 21, out] ENDLOOP}; FreeRope: ARRAY Freedom OF ROPE _ ["fixed", "tame", "wild"]; SideRope: PUBLIC ARRAY Side OF ROPE _ ["BOTTOM", "RIGHT", "TOP", "LEFT"]; <<>> LogFCT: PUBLIC PROC[frameCT: CT, indent: INT, lim: INT, out: IO.STREAM _ NIL] = { frame: Frame; IF out=NIL THEN out _ GetLog[]; IF frameCT.class#frameCellClass THEN {CoreOps.PrintCellType[frameCT]; RETURN}; frame _ FCT[frameCT]; CoreOps.PrintIndent[indent, out]; out.PutRope[CoreName.CellNm[frameCT].n]; LogFrameData[frame, 2, FALSE, out]; IF indent> <> <> <> <> <> <> ReadFrameCache: PUBLIC PROC[name: ROPE] RETURNS[frameCT: CT] = { count: INT _ 0; Period: TYPE = {begin, mid, end}; time: ARRAY Period OF BasicTime.GMT; vm: ARRAY Period OF INT; cell: CT; design: CD.Design; time[begin] _ BasicTime.Now[]; vm[begin] _ WatchStats.GetWatchStats[].vmFree; design _ PW.OpenDesign[name.Cat["Shell"]]; IF design=NIL THEN RETURN[NIL]; cell _ LayoutCheckpoint.Retrieve[name]; frameCT _ NewFrameCell[size: 0, name: name, rec: [cell: cell] ]; frameCT.properties _ AddPropCopyIfNotPresent[frameCT.properties, cell.properties]; time[mid] _ BasicTime.Now[]; vm[mid] _ WatchStats.GetWatchStats[].vmFree; <<[] _ PWCore.Layout[cell];>> <> time[end] _ BasicTime.Now[]; vm[end] _ WatchStats.GetWatchStats[].vmFree; log.PutF["\nReadFrameCache: %g %g", IO.rope[name], IO.time[]]; log.PutF["\n Begin: vm: %6g %g", IO.int[vm[begin]], IO.time[time[begin]]]; log.PutF["\n Core: vm: %6g %g", IO.int[vm[mid]], IO.time[time[mid]]]; log.PutF["\n Dale: vm: %6g %g", IO.int[vm[end]], IO.time[time[end]]]; log.PutF["\n Cost: vm: %6g", IO.int[ vm[begin]-vm[end] ] ]; log.PutF["\n Xstrs: %g", IO.int[ count ] ]}; WriteCapaProc: PROC[cell: Core.CellType] = {WriteCapa.WriteWireCapa[cell]}; WriteFrameCache: PUBLIC PROC[frameCT: CT] = { Period: TYPE = {begin, mid, end}; time: ARRAY Period OF BasicTime.GMT; vm: ARRAY Period OF INT; count: INT; name: ROPE _ CoreName.CellNm[frameCT].n; IF name.Length[]=0 THEN Signal[]; time[begin] _ BasicTime.Now[]; vm[begin] _ WatchStats.GetWatchStats[].vmFree; [ ] _ Expand[hard, frameCT]; [ ] _ CoreGlue.RouteHard[frameCT]; [ ] _ CoreName.CellNm[FCT[frameCT].cell, name]; FCT[frameCT].cell.properties _ AddPropCopyIfNotPresent[FCT[frameCT].cell.properties, frameCT.properties]; count _ CountTransistors[FCT[frameCT].cell]; <> LayoutCheckpoint.Store[FCT[frameCT].cell]; FCT[frameCT].cell _ LayoutCheckpoint.Retrieve[name]; FCT[frameCT].seq _ NEW[FrameSeq[0]]; time[mid] _ BasicTime.Now[]; vm[mid] _ WatchStats.GetWatchStats[].vmFree; <> time[end] _ BasicTime.Now[]; vm[end] _ WatchStats.GetWatchStats[].vmFree; log.PutF["\nWriteFrameCache: %g %g", IO.rope[name], IO.time[]]; log.PutF["\n Start: vm: %6g %g", IO.int[vm[begin]], IO.time[time[begin]]]; log.PutF["\n Built: vm: %6g %g", IO.int[vm[mid]], IO.time[time[mid]]]; log.PutF["\n Cached: vm: %6g %g", IO.int[vm[end]], IO.time[time[end]]]; log.PutF["\n Cost: vm: %6g", IO.int[ vm[begin]-vm[end] ] ]; log.PutF["\n Xstrs: %g", IO.int[ count ] ]}; AddPropCopyIfNotPresent: PROC [old, addends: Core.Properties] RETURNS [Core.Properties] = { consume: PROC [prop: ATOM, val: REF ANY _ NIL] = { IF CoreProperties.GetProp[old, prop]#NIL THEN RETURN; old _ CoreProperties.PutProp[old, prop, val]}; CoreProperties.Enumerate[CoreProperties.CopyProps[addends], consume]; RETURN[old]}; SetFrameExpandProc: PUBLIC PROC[type: ExpandType, on: REF, proc: REF ExpandProc] = { expandProc: ATOM _ IF type=soft THEN frameExpandSoftProc ELSE frameExpandHardProc; WITH on SELECT FROM cell: Core.CellType => {cell.properties _ CoreProperties.PutProp[cell.properties, expandProc, proc]}; class: Core.CellClass => {class.properties _ CoreProperties.PutProp[class.properties, expandProc, proc]}; ENDCASE => Signal[]}; GetFrameExpandProc: PUBLIC PROC[type: ExpandType, on: REF] RETURNS[proc: REF ExpandProc] = { expandProc: ATOM _ IF type=soft THEN frameExpandSoftProc ELSE frameExpandHardProc; WITH on SELECT FROM cell: Core.CellType => {proc _ NARROW[ CoreProperties.GetCellTypeProp[cell, expandProc].value]}; class: Core.CellClass => {proc _ NARROW[ CoreProperties.GetCellClassProp[class, expandProc].value]}; ENDCASE => Signal[]}; RecastFrameSoft: PUBLIC Core.RecastProc = { frame: Frame _ FCT[me]; public: Core.Wires; intOnly: Core.Wires; instances: CoreCreate.CellInstances; ReOrderFrame[me]; new _ frame.cell; IF new#NIL THEN RETURN[new]; IF frame.seq.size=0 THEN { IF frame.intOnly=NIL THEN RETURN[frame.cell]; log.PutF["\n WARNING: %g has partially disconnected public.", IO.rope[CoreName.CellNm[frame.cell].n] ]; log.PutRope["\n I will bury the loose ends inside for now."]; instances _ LIST[ CoreCreate.Instance[frame.cell] ]} ELSE FOR i: INT DECREASING IN [0..frame.seq.size) DO new _ RecastFrameSoft[frame.seq[i]]; instances _ CONS[CoreCreate.Instance[new], instances] ENDLOOP; FOR ropes: LIST OF ROPE _ frame.public, ropes.rest WHILE ropes#NIL DO public _ CONS[CoreOps.CreateWires[0, ropes.first], public] ENDLOOP; FOR ropes: LIST OF ROPE _ frame.intOnly, ropes.rest WHILE ropes#NIL DO intOnly _ CONS[CoreOps.CreateWires[0, ropes.first], intOnly] ENDLOOP; new _ frame.cell _ CoreCreate.Cell[ public: CoreOps.CreateWire[public], onlyInternal: CoreOps.CreateWire[intOnly], instances: instances, name: CoreName.CellNm[me].n ]; CoreBlock.PutCellSide[new, SideSides[frame.first]]; CoreBlock.MergeSides[new]; SELECT frame.first FROM left => PWCore.SetAbutX[new]; bottom => PWCore.SetAbutY[new]; ENDCASE => Signal[] }; RecastWithLayout: PUBLIC Core.RecastProc = { Signal[] }; <> <> <> <> <> <> <> <> <> RecastFrameHard: PUBLIC Core.RecastProc = { frame: Frame _ FCT[me]; IF frame.cell#NIL THEN RETURN[CoreOps.Recast[frame.cell]] ELSE RETURN[FrameInst[me].type]}; FrameInst: PUBLIC PROC[frameCT: CT] RETURNS [instance: CoreClasses.CellInstance_NIL] = { frame: Frame _ FCT[frameCT]; name: ROPE _ CoreName.CellNm[frameCT].n; instances: CoreClasses.CellInstances; ReOrderFrame[frameCT]; IF frame.cell=NIL THEN { IF frame.seq.size=0 THEN {Signal[]; RETURN[instance]}; -- NIL FOR i: INT DECREASING IN [0..frame.seq.size) DO instances _ CONS[FrameInst[frame.seq[i]], instances] ENDLOOP; frame.cell _ CoreBlock.AbutCellInstances [name: name, first: SideSides[frame.first], instances: instances]}; SELECT frame.cell.class FROM CoreInstCell.specificGenericCellClass => { instance _ CoreClasses.SetCellInstanceName[ NEW[CoreClasses.CellInstanceRec _ [actual: frame.cell.public, type: NARROW[frame.cell.data]] ], name]}; ENDCASE => { <> instance _ CoreClasses.SetCellInstanceName[ NEW[CoreClasses.CellInstanceRec _ [actual: frame.cell.public, type: frame.cell] ], name]}; RETURN[instance]}; <<>> <> <> <> <> <> <> <> <> <> <> <> <> CountTransistors: PUBLIC PROC[cell: CT] RETURNS[count: INT _ 0] = { IF cell=NIL THEN RETURN[0]; SELECT cell.class FROM CoreInstCell.specificGenericCellClass => RETURN[CountTransistors[NARROW[cell.data]]]; frameCellClass => { frame: Frame _ FCT[cell]; IF frame.seq.size=0 THEN RETURN[CountTransistors[frame.cell]]; FOR child: INT IN [0..frame.seq.size) DO count _ count + CountTransistors[ frame.seq[child] ] ENDLOOP }; CoreClasses.sequenceCellClass => { data: CoreClasses.SequenceCellType _ NARROW[cell.data]; RETURN[data.count*CountTransistors[data.base]]}; CoreClasses.recordCellClass => { data: CoreClasses.RecordCellType _ NARROW[cell.data]; FOR child: NAT IN [0..data.size) DO count _ count + CountTransistors[ data.instances[child].type ] ENDLOOP }; CoreClasses.transistorCellClass => RETURN[1]; CoreClasses.identityCellClass => RETURN[CountTransistors[NARROW[cell.data]]]; CoreIO.importCellClass => {log.PutRope["\nSkipping Imported Transistors\n"]; RETURN[0]}; ENDCASE => {Signal[]; RETURN[0]}}; ReOrderFrame: PROC[cell: Core.CellType] = { DualCell: TYPE = RECORD[cell0, cell1: Core.CellType]; frame: Frame; IF cell.class # frameCellClass THEN RETURN; frame _ FCT[cell]; SELECT frame.first FROM right => frame.first _ left; top => frame.first _ bottom; ENDCASE => RETURN; FOR i: INT IN [0..frame.seq.size/2) DO j: INT _ frame.seq.size-1-i; [frame.seq[j], frame.seq[i]] _ DualCell[frame.seq[i], frame.seq[j]] ENDLOOP}; Expand: PUBLIC PROC[type: ExpandType, frameCT: CT] = { expandNodeProc: EnumProc = { expand: REF ExpandProc _ NIL; IF expand=NIL THEN expand _ GetFrameExpandProc[type, fCT]; IF expand=NIL THEN expand _ GetFrameExpandProc[type, fCT.class]; IF expand#NIL THEN expand^[type, fCT]; IF fCT.class # frameCellClass THEN Signal[]; RETURN[kids: TRUE, continue: TRUE] }; checkNodeProc: EnumProc = { IF fCT.class # frameCellClass THEN Signal[]}; <> []_EnumFrame[frameCT, expandNodeProc]; []_EnumFrame[frameCT, checkNodeProc]}; NameFrame: PUBLIC PROC[cell: CT, root: ROPE _ NIL] = { name: ROPE _ CoreName.CellNm[cell].n; IF name=NIL THEN {name _ root; []_CoreName.CellNm[cell, name]}; IF name=NIL THEN RETURN; SELECT cell.class FROM frameCellClass => { frame: Frame _ FCT[cell]; IF frame.cell#NIL THEN NameFrame[frame.cell, name.Cat[".RC"]]; FOR field: INT IN [0..frame.seq.size) DO subName: ROPE _ IO.PutFR["%g[%g]", IO.rope[name], IO.int[field]]; NameFrame[frame.seq[field], subName]; ENDLOOP}; < {>> <> <> <> ENDCASE}; Fetch: PUBLIC PROC[cell: CT, subCellName: ROPE] RETURNS[subCell: CT _ NIL] = { fetchNodeProc: EnumProc = { IF CoreName.CellNm[fCT].n=subCellName THEN {subCell _ fCT; RETURN[FALSE, FALSE]} }; subCellName _ CoreName.RopeNm[subCellName]; []_EnumFrame[cell, fetchNodeProc] }; Log2: PROC [n: INT] RETURNS [INT] = {RETURN [IF n<=1 THEN 0 ELSE 1 + Log2[n / 2]]}; Exp2: PROC [n: INT] RETURNS [INT] = {RETURN [IF n<=0 THEN 1 ELSE 2 * Exp2[n-1]]}; <<>> RotateFrame: PUBLIC PROC[frameCT: CT, orient: CD.Orientation _ CD.original] = { ReSeq: PROC = { TwoFrames: TYPE = RECORD[f0, f1: CT]; FOR i: INT IN [0..frame.seq.size/2) DO [frame.seq[frame.seq.size-i-1], frame.seq[i]] _ TwoFrames[frame.seq[i], frame.seq[frame.seq.size-i-1]]; ENDLOOP}; frame: Frame _ FCT[frameCT]; orient _ CDOrient.ComposeOrient[frame.orient, orient]; frame.orient _ CDOrient.original; IF frame.cell#NIL THEN { -- In this case, child frames are ignored IF orient=CDOrient.original THEN RETURN; frame.cell _ RotateCellType[frame.cell, orient]; frame.size _ FixedSize[CCDUtils.CellSize[frame.cell]]; RETURN}; IF frame.seq.size = 0 THEN { -- Data must be glue IF orient=CDOrient.original THEN RETURN; IF frame.data=NIL THEN ERROR; WITH frame.data SELECT FROM glue: CoreGlue.Glue => { OPEN glue; srcs: ARRAY Side OF Side _ OrientSideSide[CDOrient.InverseOrient[orient]]; glue.type _ [type[srcs[bottom]], type[srcs[right]], type[srcs[top]], type[srcs[left]] ]; glue.cell _ [cell[srcs[bottom]], cell[srcs[right]], cell[srcs[top]], cell[srcs[left]] ]; FOR side: Side IN Side DO IF cell[side]#NIL AND type[side]=chan THEN cell[side] _ RotateCellType[cell[side], orient]; -- for chan cells ENDLOOP; SELECT orient FROM CDOrient.rotate90, CDOrient.rotate90X, CDOrient.rotate270, CDOrient.rotate270X => { RopePair: TYPE = RECORD[r0, r1: ROPE]; [params.branchLayer, params.trunkLayer] _ RopePair[ params.trunkLayer, params.branchLayer]; frame.size _ FlipSize[frame.size]; tDir _ IF tDir=horizontal THEN vertical ELSE horizontal}; ENDCASE }; ENDCASE => ERROR; RETURN}; frame.first _ OrientSideSide[orient][frame.first]; ReOrderFrame[frameCT]; -- first _ left or bottom FOR i: INT IN [0..frame.seq.size) DO RotateFrame[frame.seq[i], orient] ENDLOOP}; OrientSideSide: ARRAY CD.Orientation OF ARRAY Side OF Side = [ [bottom, right, top, left], [bottom, left, top, right], [right, top, left, bottom], [left, top, right, bottom], [top, left, bottom, right], [top, right, bottom, left], [left, bottom, right, top], [right, bottom, left, top] ]; <> <> <> <> <> <> <> <> <> <<>> RotateCellType: PUBLIC PROC[cell: CT, orient: CD.Orientation] RETURNS[new: CT] = { RotateSides: PROC[wire: Core.Wire] = { oldSides: CoreBlock.Sides _ CoreBlock.GetWireSide[wire]; newSides: CoreBlock.Sides _ none; FOR side: Side IN Side DO IF CoreBlock.OnSide[SideSides[side], oldSides] THEN newSides _ CoreBlock.AddSide[SideSides[OrientSideSide[orient][side]], newSides] ENDLOOP; CoreBlock.PutWireSide[wire, newSides]}; new _ cell; SELECT orient FROM CDOrient.rotate90, CDOrient.rotate90X => {new _ PWCore.RotateCellType[new, $Rot90]}; CDOrient.rotate180, CDOrient.rotate180X => {new _ PWCore.RotateCellType[new, $Rot180]}; CDOrient.rotate270, CDOrient.rotate270X => {new _ PWCore.RotateCellType[new, $Rot270]}; ENDCASE; SELECT orient FROM CDOrient.mirrorX, CDOrient.rotate90X, CDOrient.rotate180X, CDOrient.rotate270X => {new _ PWCore.RotateCellType[new, $FlipX]}; ENDCASE; IF new=cell THEN RETURN[new]; CoreOps.VisitAtomicWires[new.public, RotateSides]; CoreBlock.PutCellSide[new, all]}; -- For this identity cellType <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> < {new _ PWCore.RotateCellType[new, $FlipX]}; ENDCASE;>> <> <> <> <> <<>> GetSize: PUBLIC PROC[frameCT: CT] = { variable: BOOL _ FALSE; dad, son: Size; frame: Frame _ FCT[frameCT]; horizontal: BOOL _ frame.first=left OR frame.first=right; glue: CoreGlue.Glue _ NARROW[frame.data]; IF frame.cell#NIL THEN { frame.size _ FixedSize[CCDUtils.CellSize[frame.cell]]; IF glue#NIL THEN IF glue.tDir=vertical THEN frame.size.xfree _ tame ELSE frame.size.yfree _ tame; RETURN}; IF frame.seq.size = 0 THEN { IF glue=NIL THEN {Signal[]; RETURN}; frame.size _ TameSize[]; IF glue.class=chan OR glue.class=pwr THEN IF glue.tDir=vertical THEN frame.size.xfree _ wild ELSE frame.size.yfree _ wild; IF frame.size.x < 1 OR frame.size.y < 1 THEN {Signal[]; frame.data _ NIL}; RETURN}; dad _ [0, 0, fixed, tame]; FOR i: INT IN [0..frame.seq.size) DO -- Normalize sons to x sequences for computations GetSize[frame.seq[i]]; son _ IF horizontal THEN FCT[frame.seq[i]].size ELSE FlipSize[FCT[frame.seq[i]].size]; CheckXSeqForExpansionError[dad, son, frame.seq[i]]; dad.xfree _ MAX[dad.xfree, son.xfree]; -- fixed, tame, wild dad.x _ dad.x + son.x; dad.yfree _ IF MIN[dad.yfree,son.yfree]=fixed THEN fixed ELSE MAX[dad.yfree,son.yfree]; dad.y _ MAX[dad.y, son.y]; ENDLOOP; FOR i: INT IN [0..frame.seq.size) DO son _ IF ~horizontal THEN FlipSize[FCT[frame.seq[i]].size] ELSE FCT[frame.seq[i]].size; IF dad.yfree=fixed AND son.yfree=wild THEN { log.PutF["\n WARNING: Limited wild %g width", IO.rope[ IF horizontal THEN "Y" ELSE "X" ]]; LogFCT[frameCT, 0, 2, log]; log.PutRope["\n"]; EXIT}; ENDLOOP; frame.size _ IF horizontal THEN dad ELSE FlipSize[dad]}; <<>> CheckXSeqForExpansionError: PROC[size1, size2: Size, frameCT: CT] = { IF (size1.y > size2.y AND size2.yfree=fixed) OR (size2.y > size1.y AND size1.yfree=fixed) THEN { log.PutF["\n ERROR: Size of %g not expandable", IO.rope[CoreName.CellNm[frameCT].n]]; LogFCT[FCT[frameCT].father, 0, 2, log]; log.Flush[]; Signal[]} }; <<>> ReSize: PUBLIC PROC[frameCT: CT] = { dad, son: Size; freedom: Freedom; oneVariable: BOOL; cnt: ARRAY Freedom OF INT _ ALL[0]; length, diff: INT _ 0; frame: Frame _ FCT[frameCT]; horizontal: BOOL _ frame.first=left OR frame.first=right; IF frame.seq.size = 0 THEN RETURN; dad _ IF horizontal THEN frame.size ELSE FlipSize[frame.size]; -- norm FOR ii: INT IN [0..frame.seq.size) DO son _ FCT[frame.seq[ii]].size; son _ IF horizontal THEN son ELSE FlipSize[son]; -- norm CheckXSeqForExpansionError[dad, son, frame.seq[ii]]; length _ length + son.x; cnt[son.xfree] _ cnt[son.xfree] + 1; SELECT dad.yfree FROM wild => IF son.yfree=fixed THEN Signal[]; -- how can this happen? tame => IF son.yfree#tame THEN Signal[]; -- how can this happen? ENDCASE; IF (dad.yfree >= son.yfree) AND (dad.y=son.y) THEN LOOP; log.PutF["\n %g width changed from %6g %6g", IO.rope [IF horizontal THEN "Y" ELSE "X"], IO.int[son.y], IO.rope[FreeRope[son.yfree]] ]; son.yfree _ MIN[dad.yfree, son.yfree]; son.y _ MAX[dad.y, son.y]; log.PutF[" to %6g %6g in: %g", IO.int[son.y], IO.rope[FreeRope[son.yfree]], IO.rope [CoreName.CellNm[frame.seq[ii]].n] ]; FCT[frame.seq[ii]].size _ IF horizontal THEN son ELSE FlipSize[son]; -- denorm ENDLOOP; diff _ dad.x - length; FOR freedom DECREASING IN Freedom DO IF cnt[freedom]>0 THEN EXIT ENDLOOP; oneVariable _ (cnt[tame]=1 AND cnt[wild]=0) OR (cnt[tame]=0 AND cnt[wild]=1); IF diff<0 THEN Signal[]; IF diff>0 OR diff=0 AND dad.xfree = fixed AND oneVariable THEN { SELECT dad.xfree FROM wild, tame => IF freedom#dad.xfree THEN Signal[]; ENDCASE; FOR ii: INT IN [0..frame.seq.size) WHILE cnt[freedom] > 0 DO incr: INT _ diff/cnt[freedom]; son _ FCT[frame.seq[ii]].size; son _ IF horizontal THEN son ELSE FlipSize[son]; -- norm; IF son.xfree#freedom THEN LOOP; log.PutF["\n %g length changed from %6g %6g", IO.rope[IF horizontal THEN "X" ELSE "Y"], IO.int[son.x], IO.rope[FreeRope[son.xfree]] ]; IF oneVariable THEN son.xfree _ dad.xfree; son.x _ son.x + incr; log.PutF[" to %6g %6g in: %g", IO.int[son.x], IO.rope[FreeRope[son.xfree]], IO.rope [CoreName.CellNm[frame.seq[ii]].n] ]; diff _ diff - incr; cnt[freedom] _ cnt[freedom] - 1; FCT[frame.seq[ii]].size _ IF horizontal THEN son ELSE FlipSize[son]; -- denorm ENDLOOP; IF diff#0 THEN ERROR}; FOR i: INT IN [0..frame.seq.size) DO ReSize[frame.seq[i]] ENDLOOP }; <<>> RePos: PUBLIC PROC[frameCT: CT, new: CD.Position] = { cng, pos: CD.Position; frame: Frame _ FCT[frameCT]; cng _ [new.x-frame.pos.x, new.y-frame.pos.y]; pos _ frame.pos _ new; IF frame.seq.size=0 THEN RETURN; <> <> <> <> <> <> <> <> FOR i: INT IN [0..frame.seq.size) DO RePos[frame.seq[i], pos]; SELECT frame.first FROM left, right => pos.x _ pos.x + FCT[frame.seq[i]].size.x; top, bottom => pos.y _ pos.y + FCT[frame.seq[i]].size.y; ENDCASE ENDLOOP }; <<>> FixOneSize: PUBLIC PROC [frameCT: CT] RETURNS[fixed1: BOOL _ FALSE] = { FixOneSizeRecursive: PUBLIC PROC [fframeCT: CT] RETURNS[ffixed1: BOOL _ FALSE] = { fframe: Frame _ FCT[fframeCT]; lastTame: INT _ -1; wildOrMultTamesFound: BOOL _ FALSE; horizontal: BOOL _ fframe.first=left OR fframe.first=right; FOR kid: INT IN [0..fframe.seq.size) DO SELECT (IF horizontal THEN FCT[fframe.seq[kid]].size.xfree ELSE FCT[fframe.seq[kid]].size.yfree) FROM fixed => LOOP; wild => wildOrMultTamesFound _ TRUE; ENDCASE => {IF lastTame#-1 THEN wildOrMultTamesFound _ TRUE; lastTame_kid}; ENDLOOP; IF lastTame#-1 AND wildOrMultTamesFound THEN { selectedFrame: Frame _ FCT[fframe.seq[lastTame]]; IF horizontal THEN {selectedFrame.size.xfree _ fixed; log.PutRope["\n X length"]} ELSE {selectedFrame.size.yfree _ fixed; log.PutRope["\n Y length"]}; log.PutF[" FIXED in %g", IO.rope[CoreName.CellNm[fframe.seq[lastTame]].n]]; IF selectedFrame.cell#NIL AND selectedFrame.data#NIL THEN { -- Extendable glue glue: CoreGlue.Glue _ NARROW[selectedFrame.data]; size: CD.Position _ CCDUtils.CellSize[selectedFrame.cell]; extend: BOOL _ IF glue.tDir=vertical THEN selectedFrame.size.x#size.x ELSE selectedFrame.size.y#size.y; IF extend THEN { extFrame: Frame; AddExtention[fframe.seq[lastTame]]; extFrame _ FCT[FCT[fframe.seq[lastTame]].seq[0]]; extFrame.size.xfree _ extFrame.size.yfree _ fixed} }; ReSize[fframeCT]; RETURN[TRUE]}; FOR kid: INT IN [0..fframe.seq.size) WHILE NOT ffixed1 DO ffixed1 _ FixOneSizeRecursive[fframe.seq[kid]] ENDLOOP}; frame: Frame _ FCT[frameCT]; IF FixOneSizeRecursive[frameCT] THEN RETURN[TRUE]; IF frame.size.xfree=tame THEN {frame.size.xfree_fixed; ReSize[frameCT]; RETURN[TRUE]}; IF frame.size.yfree=tame THEN {frame.size.yfree_fixed; ReSize[frameCT]; RETURN[TRUE]}; RETURN[FALSE]}; <<>> AddExtention: PROC[frameCT: Core.CellType] = { name: ROPE _ CoreName.CellNm[frameCT].n; origFrm: Frame _ FCT[frameCT]; newFrm: Frame; glue: CoreGlue.Glue _ NARROW[origFrm.data]; extSide: Side _ (IF glue.tDir=vertical THEN IF glue.type[left] = conn THEN left ELSE right ELSE IF glue.type[bottom] = conn THEN bottom ELSE top); origFrm.size.xfree _ origFrm.size.yfree _ fixed; newFrm _ NEW[CoreFrame.FrameRec _ [first: extSide]]; frameCT.data _ newFrm; newFrm.seq _ NEW[CoreFrame.FrameSeq[2]]; newFrm.seq[0] _ SELECT extSide FROM left => CoreGlue.CellProc[name: name.Cat["Ext"], l: ext, r: conn], right => CoreGlue.CellProc[name: name.Cat["Ext"], r: ext, l: conn], top => CoreGlue.CellProc[name: name.Cat["Ext"], t: ext, b: conn], bottom => CoreGlue.CellProc[name: name.Cat["Ext"], b: ext, t: conn], ENDCASE => ERROR; Expand[hard, newFrm.seq[0]]; newFrm.seq[1] _ CoreOps.SetCellTypeName[ NEW [Core.CellTypeRec _ [frameCT.class, NIL, origFrm]], name.Cat["Orig"]]; newFrm.father _ origFrm.father; origFrm.father _ FCT[newFrm.seq[0]].father _ frameCT; origFrm.data _ NIL}; TellKidsAboutDad: PUBLIC PROC [frameCT: CT] = { dad: Frame _ FCT[frameCT]; FOR kid: INT IN [0..dad.seq.size) DO FCT[dad.seq[kid]].father _ frameCT; TellKidsAboutDad[dad.seq[kid]] ENDLOOP}; <<>> Neighbor: PUBLIC PROC [frameCT: CT, side: Side] RETURNS[neighborCT: CT, ok: BOOL] = { NeighborCheck: PROC[fCT: CT] RETURNS[type: {eq, ok, out}] = { frame: Frame _ FCT[fCT]; negh: CD.Rect _ CDBasics.RectAt[frame.pos, [frame.size.x,frame.size.y]]; SELECT neighborSide FROM right => { IF seg.x2=negh.x2 AND seg.y1=negh.y1 AND seg.y2=negh.y2 THEN RETURN[eq]; IF seg.x2 NOT IN (negh.x1 .. negh.x2] THEN RETURN[out]}; left => { IF seg.x1=negh.x1 AND seg.y1=negh.y1 AND seg.y2=negh.y2 THEN RETURN[eq]; IF seg.x1 NOT IN [negh.x1 .. negh.x2) THEN RETURN[out]}; top => { IF seg.y2=negh.y2 AND seg.x1=negh.x1 AND seg.x2=negh.x2 THEN RETURN[eq]; IF seg.y2 NOT IN (negh.y1 .. negh.y2] THEN RETURN[out]}; bottom => { IF seg.y1=negh.y1 AND seg.x1=negh.x1 AND seg.x2=negh.x2 THEN RETURN[eq]; IF seg.y1 NOT IN [negh.y1 .. negh.y2) THEN RETURN[out]}; ENDCASE; SELECT neighborSide FROM right, left => { IF seg.y1 NOT IN [negh.y1 .. negh.y2) THEN RETURN[out]; IF seg.y2 NOT IN (negh.y1 .. negh.y2] THEN RETURN[out]; RETURN[ok]}; top, bottom => { IF seg.x1 NOT IN [negh.x1 .. negh.x2) THEN RETURN[out]; IF seg.x2 NOT IN (negh.x1 .. negh.x2] THEN RETURN[out]; RETURN[ok]}; ENDCASE }; leaf: Frame _ FCT[frameCT]; leafNm: ROPE _ CoreName.CellNm[frameCT].n; neighborSide: Side _ OppSide[side]; seg: CD.Rect _ CDBasics.RectAt[leaf.pos, [leaf.size.x,leaf.size.y]]; SELECT side FROM top => seg.y1 _ seg.y2; bottom => seg.y2 _ seg.y1; right => seg.x1 _ seg.x2; left => seg.x2 _ seg.x1; ENDCASE; FOR neighborCT _ leaf.father, FCT[neighborCT].father WHILE neighborCT#NIL DO SELECT NeighborCheck[neighborCT] FROM ok => EXIT; out => LOOP; ENDCASE => ERROR REPEAT FINISHED => { log.PutF["\n ERROR: %g side neighbor of %g is external to frame", IO.rope[SideRope[side]], IO.rope[leafNm]]; RETURN[NIL, FALSE]} ENDLOOP; DO neighbor: Frame _ FCT[neighborCT]; IF neighbor.seq.size=0 THEN RETURN[neighborCT, FALSE]; FOR i: INT IN [0..neighbor.seq.size) DO SELECT NeighborCheck[neighbor.seq[i]] FROM out => LOOP; eq => {neighborCT _ neighbor.seq[i]; GOTO Found}; ENDCASE => {neighborCT _ neighbor.seq[i]; EXIT}; REPEAT Found=> EXIT; FINISHED => { log.PutF["\n ERROR: %g side neighbor of %g can't be identified", IO.rope[SideRope[side]], IO.rope[leafNm]]; RETURN[NIL, FALSE]} ENDLOOP; ENDLOOP; RETURN[neighborCT, TRUE]}; <<>> <<>> <> <<{new _ TestMergeNodes[frame]};>> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> < IF elist#NIL THEN nlist _ CONS[elist, nlist] ENDLOOP;>> <> <> <> <> <> < {>> <> <> <> <> <> <> < {new[node] _ plaFrame};>> < ERROR;>> <> <<>> EnumFrame: PUBLIC PROC[fCT: CT, proc: EnumProc] RETURNS[kids, continue: BOOL _ TRUE] = { frame: Frame; [kids, continue] _ proc[fCT]; IF NOT continue THEN RETURN[FALSE, FALSE]; IF NOT kids THEN RETURN[FALSE, TRUE]; frame _ FCT[fCT]; FOR field: INT IN [0..frame.seq.size) DO IF NOT EnumFrame[frame.seq[field], proc].continue THEN RETURN[FALSE, FALSE]; ENDLOOP; RETURN[TRUE, TRUE]}; <<>> NextSide: PUBLIC PROC [side: Side] RETURNS [next: Side] = {RETURN[SELECT side FROM bottom=>right, right=>top, top=>left, left=>bottom, ENDCASE=>ERROR]}; PrevSide: PUBLIC PROC [side: Side] RETURNS [prev: Side] = {RETURN[SELECT side FROM bottom=>left, left=>top, top=>right, right=>bottom, ENDCASE=>ERROR]}; OppSide: PUBLIC PROC [side: Side] RETURNS [opp: Side] = {RETURN[SELECT side FROM left=>right, right=>left, top=>bottom, bottom=>top, ENDCASE=>ERROR]}; log: IO.STREAM _ NIL; GetLog: PUBLIC PROC RETURNS[IO.STREAM] = { logName: ROPE _ "CoreFrame.log"; IF log=NIL THEN { log _ ViewerIO.CreateViewerStreams[logName, NIL, logName].out; log.PutF["%g %g\n\n", IO.rope[logName], IO.time[]]}; RETURN[log]}; [ ] _ GetLog[]; END.