<> <> <> DIRECTORY CoreCreate, CoreIO, CD, CDOrient, Basics, Core, CoreBlock, CoreOps, CoreClasses, CoreFrame, CoreName, CoreProperties, IO, PWCore; CoreBlockImpl: CEDAR PROGRAM IMPORTS CoreIO, CD, CDOrient, Basics, CoreBlock, CoreOps, CoreFrame, CoreName, CoreProperties, IO, PWCore EXPORTS CoreBlock = BEGIN OPEN CoreBlock; Wire: TYPE = Core.Wire; CellType: TYPE = Core.CellType; ROPE: TYPE = Core.ROPE; Signal: SIGNAL = CODE; sides: PUBLIC ATOM _ CoreIO.RegisterProperty[ CoreProperties.RegisterProperty[ $CoreBlockSides, CoreProperties.Props[ [CoreProperties.propCompare, NEW[CoreProperties.PropCompareProc _ CompareSides]], [CoreProperties.propCopy, NEW[CoreProperties.PropCopyProc _ CopySides ]], [CoreProperties.propPrint, NEW[CoreProperties.PropPrintProc _ PrintSides ]] ] ], WriteSides, ReadSides ]; WriteSides: CoreIO.PropWriteProc = { refSides: REF Sides _ NARROW[value]; card: CARDINAL _ ToWord[refSides^]; IO.PutF[h.stream, "%g ", IO.card[card]]}; ReadSides: CoreIO.PropReadProc = { card: CARDINAL _ IO.GetCard[h.stream]; max: CARDINAL _ ToWord[all]; IF card > max THEN Signal[]; RETURN[ NEW[Sides _ FmWord[card]] ]}; CopySides: CoreProperties.PropCopyProc = {refSides: REF Sides _ NARROW[value]; RETURN[NEW[Sides _ refSides^]]}; CompareSides: CoreProperties.PropCompareProc = { refSides1: REF Sides _ NARROW[value1]; refSides2: REF Sides _ NARROW[value2]; RETURN[refSides1^=refSides2^]}; PrintSides: CoreProperties.PropPrintProc = { refSides: REF Sides _ NARROW[val]; <> to.PutRope[" Sides: "]; IF refSides^=all THEN {to.PutRope[" All"]; RETURN}; IF refSides^=none THEN {to.PutRope[" None"]; RETURN}; IF OnSide[bottom, refSides^] THEN to.PutRope[" Bottom"]; IF OnSide[right, refSides^] THEN to.PutRope[" Right"]; IF OnSide[top, refSides^] THEN to.PutRope[" Top"]; IF OnSide[left, refSides^] THEN to.PutRope[" Left"]}; AddSide: PUBLIC PROC[new, old: Sides] RETURNS[Sides] = {RETURN[FmWord[Basics.BITOR[ToWord[new], ToWord[old]]]]}; DelSide: PUBLIC PROC[new, old: Sides] RETURNS[Sides] = {RETURN[FmWord[Basics.BITAND[Basics.BITNOT[ToWord[new]], ToWord[old]]]]}; OnSide: PUBLIC PROC[new, old: Sides] RETURNS[BOOL] = {RETURN[(Basics.BITAND[ToWord[new], ToWord[old]])#0]}; OtherSide: PUBLIC PROC[side: Sides] RETURNS[Sides] = {RETURN[SELECT side FROM bottom=>top, top=>bottom, left=>right, right=>left,ENDCASE=>none]}; ToWord: PROC[side: Sides] RETURNS[word: WORD] = {RETURN[LOOPHOLE[side]]}; FmWord: PUBLIC PROC[word: WORD] RETURNS[side: Sides] = {RETURN[LOOPHOLE[Basics.BITAND[word, ToWord[all] ] ] ] }; GetCellSide: PUBLIC PROC[cell: CellType] RETURNS[side: Sides] = { refSides: REF Sides; IF cell=NIL THEN RETURN[none]; refSides _ NARROW[CoreProperties.GetCellTypeProp[cell, sides]]; RETURN[IF refSides=NIL THEN none ELSE refSides^] }; PutCellSide: PUBLIC PROC[cell: CellType, side: Sides] = {CoreProperties.PutCellTypeProp[cell, sides, NEW[CoreBlock.Sides _ side]]}; GetWireSide: PUBLIC PROC[wire: Wire] RETURNS[side: Sides] = { refSides: REF Sides; IF wire=NIL THEN RETURN[none]; refSides _ NARROW[CoreProperties.GetWireProp[wire, sides]]; RETURN[IF refSides=NIL THEN none ELSE refSides^]}; PutWireSide: PUBLIC PROC[wire: Wire, side: Sides] = { refSides: REF Sides; IF wire=NIL THEN RETURN; refSides _ NARROW[CoreProperties.GetWireProp[wire, sides]]; IF refSides=NIL THEN CoreProperties.PutWireProp[wire, sides, NEW[CoreBlock.Sides _ side]] ELSE refSides^ _ side; FOR i: NAT IN [0..wire.size) DO PutWireSide[wire[i], side] ENDLOOP}; AddWireSide: PUBLIC PROC[wire: Wire, side: Sides] RETURNS[sameWire: Wire] = { refSides: REF Sides; IF wire=NIL THEN RETURN[NIL]; refSides _ NARROW[CoreProperties.GetWireProp[wire, sides]]; IF refSides=NIL THEN refSides _ NEW[Sides _ none]; refSides^ _ AddSide[side, refSides^]; CoreProperties.PutWireProp[wire, sides, refSides]; FOR i: NAT IN [0..wire.size) DO wire[i] _ AddWireSide[wire[i], side] ENDLOOP; RETURN[wire]}; DelWireSide: PUBLIC PROC[wire: Wire, side: Sides] RETURNS[sameWire: Wire] = { refSides: REF Sides; IF wire=NIL THEN RETURN[NIL]; refSides _ NARROW[CoreProperties.GetWireProp[wire, sides]]; IF refSides=NIL THEN refSides _ NEW[Sides _ none]; refSides^ _ DelSide[side, refSides^]; CoreProperties.PutWireProp[wire, sides, refSides]; FOR i: NAT IN [0..wire.size) DO wire[i] _ DelWireSide[wire[i], side] ENDLOOP; RETURN[wire]}; MergeSides: PUBLIC PROC[cell: CellType] = { first: Sides _ GetCellSide[cell]; last: Sides _ OtherSide[first]; hidden: Sides; data: CoreClasses.RecordCellType _ NARROW[cell.data]; visit: CoreOps.EachWirePairProc ~ { side: Sides _ GetWireSide[publicWire]; side _ DelSide[hidden, side]; [ ] _ AddWireSide[actualWire, side]}; IF data.size>1 AND first=none THEN Signal[]; FOR i: NAT IN [0..data.size) DO hidden _ IF i # 0 THEN first ELSE none; hidden _ AddSide[ IF (i+1) < data.size THEN last ELSE none, hidden]; [ ] _ CoreOps.VisitBinding[data[i].actual, data[i].type.public, visit] ENDLOOP}; RevInstances: PROC[list: CoreClasses.CellInstances] RETURNS[rev: CoreClasses.CellInstances] = { FOR list _ list, list.rest WHILE list#NIL DO rev _ CONS[list.first, rev] ENDLOOP}; AbutCellList: PUBLIC PROC[ name: Core.ROPE, first: Sides, cellTypes: LIST OF CellType] RETURNS[cellType: CellType] = { instances: CoreClasses.CellInstances _ NIL; FOR cellTypes _ cellTypes, cellTypes.rest WHILE cellTypes#NIL DO instances _ CONS[NEW[CoreClasses.CellInstanceRec _ [ actual: CoreOps.CopyWire[cellTypes.first.public], type: cellTypes.first]], instances] ENDLOOP; instances _ RevInstances[instances]; cellType _ AbutCellInstances[ name, first, instances]}; <<>> AbutCellInstances: PUBLIC PROC[ name: ROPE, first: Sides, instances: CoreClasses.CellInstances] RETURNS[cellType: CellType] = { size: INT _ 0; index: INT _ 0; newPublicCtx: CoreName.Context _ CoreName.NewContext[]; newPublicWire: Wire; newPublicWires: Core.Wires _ NIL; noNamePublics: Core.Wires _ NIL; ais: LIST OF PWCore.AbutInstance _ NIL; inX: BOOL _ SELECT first FROM left, right => TRUE, bottom, top => FALSE, ENDCASE => ERROR; FOR list: CoreClasses.CellInstances _ instances, list.rest WHILE list#NIL DO size _ size+1 ENDLOOP; index _ 0; FOR list: CoreClasses.CellInstances _ instances, list.rest WHILE list#NIL DO eachWirePair: CoreOps.EachWirePairProc ~ { aName: ROPE _ CoreName.WireNm[actualWire].n; <> sides: Sides _ GetWireSide[publicWire]; IF actualWire.size#0 THEN RETURN; IF OnSide[sides, outSides] THEN { parentPublic: Wire; IF aName#NIL THEN parentPublic _ CoreName.CtxWire[newPublicCtx, aName] -- adds if new ELSE { parentPublic _ CoreOps.CreateWires[0]; -- Should Be Dead End Wire noNamePublics _ CONS[parentPublic, noNamePublics]}; pas _ CONS[ [publicWire, parentPublic], pas]; [ ] _ AddWireSide[parentPublic, DelSide[inSides, sides]] } }; pas: LIST OF CoreCreate.PA _ NIL; outSides: Sides _ OutSides[index, size, first]; inSides: Sides _ DelSide[outSides, all]; <> [ ] _ CoreOps.VisitBinding [actual: list.first.actual, public: list.first.type.public, eachWirePair: eachWirePair]; ais _ CONS[[PWCore.Layout[list.first.type], pas], ais]; index _ index+1; ENDLOOP; newPublicWires _ CoreName.WiresFromCtx[newPublicCtx]; FOR list: Core.Wires _ noNamePublics, list.rest WHILE list#NIL DO newPublicWires _ CONS[ list.first, newPublicWires] ENDLOOP; newPublicWire _ CoreOps.CreateWire[newPublicWires]; <> SELECT first FROM right, top => { }; ENDCASE => { list: LIST OF PWCore.AbutInstance _ ais; ais _ NIL; FOR list _ list, list.rest WHILE list#NIL DO ais _ CONS[list.first, ais] ENDLOOP}; cellType _ PWCore.AbutCell[ public: newPublicWire, abutInstances: ais, inX: inX, shared: FALSE, name: name, props: NIL]; newPublicCtx _ CoreName.KillContext[newPublicCtx]; CoreBlock.PutCellSide [cellType, IF inX THEN left ELSE bottom]; IF PWCore.FromLayoutWithoutPublic[PWCore.Layout[cellType]] # cellType THEN Signal[]}; DelPAInternalOnlys: PROC[context: CoreName.Context, ais: LIST OF PWCore.AbutInstance] = { IsPublic: PROC[wr: CoreCreate.WR] RETURNS[BOOL] = {name: ROPE _ NARROW[wr]; RETURN[CoreName.CtxNameToWire[context, name]#NIL]}; FOR ais _ ais, ais.rest WHILE ais#NIL DO -- two LOOPs to avoid CONSing pas: LIST OF CoreCreate.PA; DO -- remove internal onlys from first of list IF ais.first.pas=NIL THEN GOTO Exit; IF IsPublic[ais.first.pas.first.actual] THEN EXIT; ais.first.pas _ ais.first.pas.rest; REPEAT Exit => LOOP; ENDLOOP; pas _ ais.first.pas; WHILE pas.rest#NIL DO -- remove internal onlys from rest of list IF IsPublic[pas.rest.first.actual] THEN pas _ pas.rest ELSE pas.rest _ pas.rest.rest ENDLOOP; ENDLOOP}; checking: BOOL _ TRUE; OutSides: PROC[index, size: INT, first: Sides] RETURNS[ outSides: Sides _ all] = { nextInSide, lastInSide: Sides; SELECT first FROM left => {nextInSide _ right; lastInSide _ left}; bottom => {nextInSide _ top; lastInSide _ bottom}; right => {nextInSide _ left; lastInSide _ right}; top => {nextInSide _ bottom; lastInSide _ top}; ENDCASE => Signal[]; IF index#0 THEN outSides _ DelSide[lastInSide, outSides]; IF index+1#size THEN outSides _ DelSide[nextInSide, outSides]}; <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> < RevInstances[instances], ENDCASE => instances;>> <> <> <> < PWCore.SetAbutX[cellType];>> < PWCore.SetAbutY[cellType];>> < Signal[] };>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> < RevInstances[instances], ENDCASE => instances;>> <> <> <> < PWCore.SetAbutX[cellType];>> < PWCore.SetAbutY[cellType];>> < Signal[] };>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <