DIRECTORY CoreCreate, CD, CDOrient, Basics, Core, CoreBlock, CoreGeometry, CoreIOIFUProps, CoreOps, CoreClasses, CoreFrame, CoreInstCell, CoreName, CoreProperties, HashTable, IO, PWC, Rope; CoreBlockImpl: CEDAR PROGRAM IMPORTS CD, CDOrient, Basics, CoreBlock, CoreOps, CoreFrame, CoreGeometry, CoreInstCell, CoreIOIFUProps, CoreName, CoreProperties, HashTable, IO, PWC, Rope EXPORTS CoreBlock = BEGIN OPEN CoreBlock; Wire: TYPE = Core.Wire; CellType: TYPE = Core.CellType; ROPE: TYPE = Core.ROPE; SidesProp: PROC RETURNS[ATOM] = {RETURN[CoreIOIFUProps.sides]}; Signal: SIGNAL[] = CODE; AddSide: PUBLIC PROC[new, old: Sides] RETURNS[Sides] = {RETURN[SidesFmWord[Basics.BITOR[SidesToWord[new], SidesToWord[old]]]]}; DelSide: PUBLIC PROC[new, old: Sides] RETURNS[Sides] = {RETURN[SidesFmWord[Basics.BITAND[Basics.BITNOT[SidesToWord[new]], SidesToWord[old]]]]}; OnSide: PUBLIC PROC[new, old: Sides] RETURNS[BOOL] = {RETURN[(Basics.BITAND[SidesToWord[new], SidesToWord[old]])#0]}; OtherSide: PUBLIC PROC[side: Sides] RETURNS[Sides] = {RETURN[SELECT side FROM bottom=>top, top=>bottom, left=>right, right=>left,ENDCASE=>none]}; SidesToWord: PUBLIC PROC[side: Sides] RETURNS[word: WORD] = {RETURN[LOOPHOLE[side]]}; SidesFmWord: PUBLIC PROC[word: WORD] RETURNS[side: Sides] = {RETURN[LOOPHOLE[Basics.BITAND[word, SidesToWord[all] ] ] ] }; GetCellSide: PUBLIC PROC[cell: CellType] RETURNS[side: Sides] = { refSides: REF Sides; IF cell=NIL THEN RETURN[none]; refSides _ NARROW[CoreProperties.GetCellTypeProp[cell, SidesProp[]]]; RETURN[IF refSides=NIL THEN none ELSE refSides^] }; PutCellSide: PUBLIC PROC[cell: CellType, side: Sides] = {CoreProperties.PutCellTypeProp[cell, SidesProp[], 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, SidesProp[]]]; 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, SidesProp[]]]; IF refSides=NIL THEN CoreProperties.PutWireProp[wire, SidesProp[], 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, SidesProp[]]]; IF refSides=NIL THEN refSides _ NEW[Sides _ none]; refSides^ _ AddSide[side, refSides^]; CoreProperties.PutWireProp[wire, SidesProp[], 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, SidesProp[]]]; IF refSides=NIL THEN refSides _ NEW[Sides _ none]; refSides^ _ DelSide[side, refSides^]; CoreProperties.PutWireProp[wire, SidesProp[], 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; DeletePseudoPublics[cell]}; DeletePseudoPublics: PUBLIC PROC [cell: Core.CellType] = { publics: Core.Wires _ NIL; FOR i: INT DECREASING IN [0..cell.public.size) DO IF GetWireSide[ cell.public[i] ]#none THEN publics _ CONS[ cell.public[i], publics] ELSE log.PutF["\nRemoving pseudo public: %g", IO.rope[ CoreName.WireNm[cell.public[i]].n] ]; ENDLOOP; cell.public _ CoreOps.CreateWire[publics]}; 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: ROPE, first: Sides, cellTypes: LIST OF CellType] RETURNS[cellType: CellType] = { temp: LIST OF CellType _ NIL; cts: LIST OF CellType _ NIL; data: CoreClasses.RecordCellType; FOR temp: LIST OF CellType _ cellTypes, temp.rest WHILE temp#NIL DO cts _ CONS[(IF temp.first.class=CoreInstCell.specificGenericCellClass THEN NARROW[ temp.first.data, CellType] ELSE temp.first ), cts]; ENDLOOP; IF first=left OR first=bottom THEN { temp: LIST OF CellType _ cts; cts _ NIL; FOR temp _ temp, temp.rest WHILE temp#NIL DO cts _ CONS[temp.first, cts] ENDLOOP}; cellType _ PWC.AbutList[ cts, (first=left OR first=right)]; [ ] _ CoreName.CellNm[cellType, name]; CoreBlock.PutCellSide[cellType, (SELECT first FROM left, right => left, ENDCASE => bottom)]; CoreBlock.MergeSides[cellType]; IF first=top OR first=right THEN { temp: LIST OF CellType _ cellTypes; cellTypes _ NIL; FOR temp _ temp, temp.rest WHILE temp#NIL DO cellTypes _ CONS[temp.first, cellTypes] ENDLOOP}; data _ NARROW[cellType.data]; FOR index: NAT IN [0..data.size) DO Visit: CoreOps.EachWirePairProc ~ { new: ROPE _ CoreName.WireNm[publicWire].n; IF publicWire.size#actualWire.size THEN Signal[]; IF publicWire.size#0 THEN RETURN[TRUE, FALSE]; [ ] _ CoreName.WireNm[actualWire, new]}; IF cellTypes.first.public.size#0 THEN [ ] _ CoreOps.VisitBinding [actual: data[index].actual, public: cellTypes.first.public, eachWirePair: Visit]; cellTypes _ cellTypes.rest ENDLOOP; EnsureUniqueNames[cellType]}; MergeCell: PUBLIC PROC[cellType: CellType] = { data: CoreClasses.RecordCellType _ NARROW[cellType.data]; FOR index: NAT IN [0..data.size) DO Visit: CoreOps.EachWirePairProc ~ { new: ROPE _ CoreName.WireNm[publicWire].n; IF publicWire.size#0 OR new.Length[]=0 THEN RETURN[TRUE, FALSE]; [ ] _ CoreName.WireNm[actualWire, new]}; IF data[index].type.public.size#0 THEN [ ] _ CoreOps.VisitBinding [actual: data[index].actual, public: data[index].type.public, eachWirePair: Visit] ENDLOOP; EnsureUniqueNames[cellType]}; phA: ROPE _ CoreName.RopeNm["PhA"]; phB: ROPE _ CoreName.RopeNm["PhB"]; GND: ROPE _ CoreName.RopeNm["GND"]; VDD: ROPE _ CoreName.RopeNm["VDD"]; VBB: ROPE _ CoreName.RopeNm["VBB"]; EnsureUniqueNames: PROC[cellType: CellType] = { publics: CoreName.Context _ CoreName.NewContext[]; -- public name to wire deletedPublics: HashTable.Table _ HashTable.Create[]; -- wires internal: CoreName.Context _ CoreName.NewContext[]; -- internal name to wire iVersion: HashTable.Table _ HashTable.Create[]; -- internal name to version data: CoreClasses.RecordCellType _ NARROW[cellType.data]; ResolveNameConflicts: PROC[root: Wire, mergeConflicts: BOOL _ FALSE] = { CoreOps.FlushNameCaches[root]; FOR i: INT IN [0..root.size) DO IF root[i].size # 0 THEN ResolveNameConflicts[root[i], mergeConflicts] ELSE { old: Wire _ root[i]; wNm: ROPE _ CoreName.WireNm[old].n; regPublic: Wire _ CoreName.CtxNameToWire[publics, wNm]; regInternal: Wire _ CoreName.CtxNameToWire[internal, wNm]; alreadyMerged: BOOL _ HashTable.Fetch[deletedPublics, old].found; IF wNm.Length[]=0 THEN LOOP; -- no conflicts possible IF regInternal=old THEN LOOP; IF regPublic#NIL AND mergeConflicts OR alreadyMerged THEN { root[i] _ regPublic; IF alreadyMerged THEN LOOP; [ ] _ HashTable.Store[deletedPublics, old, old]; [ ] _ AddWireSide[root[i], GetWireSide[old]]; CoreGeometry.AddIndirectLazyPins[PWC.extractMode.decoration, root[i], old]; LOOP}; SELECT wNm FROM phA, phB, GND, VDD, VBB => Signal[]; ENDCASE; IF regInternal=NIL THEN {[ ] _ CoreName.CtxRegisterWire[internal, old]} ELSE { last: REF INT _ NARROW[HashTable.Fetch[iVersion, wNm].value]; IF last=NIL THEN {[ ] _ HashTable.Store[iVersion, wNm, NEW[INT _ 0]]; LOOP}; last^ _ last^ +1; []_CoreName.WireNm[old, wNm.Cat[IO.PutFR["!%g",IO.int[last^]]]]}} ENDLOOP}; Visitor: PROC [wire: Wire] = { [ ] _ CoreName.CtxRegisterWire[publics, wire]; [ ] _ CoreName.CtxRegisterWire[internal, wire]}; log.PutF["\nEnsure unique wire names for: %g ", IO.rope[CoreName.CellNm[cellType].n]]; [ ] _ CoreOps.VisitRootAtomics[cellType.public, Visitor]; ResolveNameConflicts[root: cellType.public, mergeConflicts: TRUE]; FOR i: INT IN [0..data.size) DO ResolveNameConflicts[root: data[i].actual, mergeConflicts: FALSE] ENDLOOP; ResolveNameConflicts[root: data.internal, mergeConflicts: FALSE]; cellType.public _ CoreName.WireFromCtx[publics]; -- flatten and reorder HashTable.Erase[iVersion]; HashTable.Erase[deletedPublics]; publics _ CoreName.KillContext[publics]; publics _ CoreName.KillContext[internal]}; DelPAInternalOnlys: PROC[context: CoreName.Context, ais: LIST OF PWC.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]}; MarkSides: PUBLIC PROC[cell: CellType, cap: Sides _ none] = { eachWireProc: PROC [wire: Wire] = {[ ] _ CoreBlock.PutWireSide[wire, DelSide[cap, GetWireLayoutSides[cell, wire] ] ]}; IF GetCellSide[cell]#none THEN RETURN; -- already done (ie. cached blank) [] _ CoreOps.VisitRootAtomics[cell.public, eachWireProc]; PutCellSide[cell, all]}; MySides: PROC[hisSides: CoreGeometry.Sides] RETURNS[mySides: Sides _ none] = { IF hisSides[left] THEN mySides _ CoreBlock.AddSide[mySides, left]; IF hisSides[right] THEN mySides _ CoreBlock.AddSide[mySides, right]; IF hisSides[top] THEN mySides _ CoreBlock.AddSide[mySides, top]; IF hisSides[bottom] THEN mySides _ CoreBlock.AddSide[mySides, bottom]}; GetWireLayoutSides: PUBLIC PROC[cell: CellType, wire: Wire] RETURNS[sides: Sides _ none] = { ir: CD.Rect _ PWC.InterestRect[cell]; eachPinProc: CoreGeometry.EachInstanceProc = {sides _ CoreBlock.AddSide[sides, MySides[CoreGeometry.GetSides[ir, instance]]]}; [] _ CoreGeometry.EnumeratePins[PWC.extractMode.decoration, wire, eachPinProc]}; GetInstSideLocSize: PUBLIC PROC [ob: CD.Object, inst: CD.Instance] RETURNS [side: CoreBlock.Sides, loc, size: INT] = { base: CD.Rect _ CD.InterestRect[ob]; rect: CD.Rect _ CDOrient.RectAt[inst.location, inst.ob.size, inst.orientation]; side _ none; IF base.y1 = rect.y1 THEN side _ AddSide[bottom, side]; IF base.x2 = rect.x2 THEN side _ AddSide[right, side]; IF base.y2 = rect.y2 THEN side _ AddSide[top, side]; IF base.x1 = rect.x1 THEN side _ AddSide[left, side]; loc _ SELECT side FROM left, right => rect.y1 - base.y1, top, bottom => rect.x1 - base.x1, ENDCASE => 0; size _ SELECT side FROM left, right => rect.y2 - rect.y1, top, bottom => rect.x2 - rect.x1, ENDCASE => 0}; log: IO.STREAM _ CoreFrame.GetLog[]; END. 5’CoreBlockImpl.mesa Created by Don Curry, February 1, 1986 2:43:22 pm PST Edited by Don Curry, October 27, 1986 12:47:39 pm PST specificGeneric, other: BOOL _ FALSE; FOR temp: LIST OF CellType _ cellTypes, temp.rest WHILE temp#NIL DO SELECT temp.first.class FROM CoreInstCell.specificGenericCellClass => specificGeneric _ TRUE; ENDCASE => other _ TRUE ENDLOOP; IF specificGeneric=other THEN Signal[]; Rename wires. Names are wrong either because cells were specificGeneric's or because extraction does not propagate names if nodes are split. IF new.Length[]=0 THEN {IF CoreName.WireNm[actualWire].n.Length[]#0 THEN Signal[]}; refCell: CellType _ IF specificGeneric THEN NARROW[cellTypes.first.data, CellType] ELSE cellTypes.first; Imports don't understand this prop until recasted IF GetCellSide[data[index].type]=none THEN Signal[]; IF data[index].type#refCell THEN Signal[]; MergeCell renames children actuals based on children publics then does EnsureUniqueNames. MergeCell can't be used in AbutCellList because AbutCellList must deal with specificGeneric's. MergeCell is useful for extracting pads by getting Gnd and Vdd to connect. Public wires with the same name are merged. InternalOnlys are given versions (ie !1) data.internal _ CoreName.WireFromCtx[internal]; -- flatten and reorder MergeSplitPublicsRenameInternalConflicts: PROC[cellType: CellType] = { index: INT; publics: CoreName.Context _ CoreName.NewContext[]; deletedPublics: HashTable.Table; -- removed public wires iOnlys: HashTable.Table; -- int onlys version # name: ROPE _ CoreName.CellNm[cellType].n; data: CoreClasses.RecordCellType _ NARROW[cellType.data]; SubstituteContextWires: PROC[root: Wire, trap: BOOL] = { FOR i: INT IN [0..root.size) DO IF root[i].size # 0 THEN SubstituteContextWires[root[i], trap] ELSE { old: Wire _ root[i]; wNm: ROPE _ CoreName.WireNm[old].n; new: Wire _ CoreName.CtxNameToWire[publics, wNm]; IF new=NIL OR new=old THEN LOOP; IF HashTable.Fetch[deletedPublics, old].found THEN {root[i] _ new; LOOP}; IF trap THEN { IF HashTable.Fetch[iOnlys, wNm].found THEN { last: REF INT _ NARROW[HashTable.Fetch[deletedPublics, old].value]; []_CoreName.WireNm[old, wNm.Cat[IO.PutFR["!%g",IO.int[last^]]]]; last^ _ last^ +1; LOOP}; -- add version # to additional iOnlys IF index=-1 THEN Signal[] -- why was this not found in actuals ELSE { log.PutF["\nSIGNAL - Internal-Only with public name %g", IO.rope[wNm] ]; log.PutF["\n Parent: %g Index: %g Child: %g", IO.rope[name], IO.int[index], IO.rope[CoreName.CellNm[data[index].type].n] ]; []_CoreName.WireNm[old, wNm.Cat["!0"]]; [ ] _ HashTable.Store[iOnlys, wNm, NEW[INT _ 1]]; LOOP} }; root[i] _ new; [ ] _ HashTable.Store[deletedPublics, old, old]; log.PutF["\n Joining split public %g", IO.rope[wNm]]; [ ] _ AddWireSide[root[i], GetWireSide[old]]; CoreGeometry.AddIndirectLazyPins[PWC.extractMode.decoration, root[i], old]}; ENDLOOP}; VisitPublics: PROC [wire: Wire] = {[ ] _ CoreName.CtxRegisterWire[publics, wire]}; log.PutF["\nCheck new public and internal of: %g ", IO.rope[name]]; [ ] _ CoreOps.VisitRootAtomics[cellType.public, VisitPublics]; deletedPublics _ HashTable.Create[]; -- removed public wires iOnlys _ HashTable.Create[]; -- next version SubstituteContextWires[cellType.public, FALSE]; cellType.public _ CoreName.WireFromCtx[publics]; FOR index IN [0..data.size) DO SubstituteContextWires[data[index].actual, TRUE] ENDLOOP; index _ -1; SubstituteContextWires[data.internal, TRUE]; HashTable.Erase[iOnlys]; HashTable.Erase[deletedPublics]; publics _ CoreName.KillContext[publics]}; 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 PWC.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; pName: ROPE _ CoreName.WireNm[publicWire].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 { Signal[]; parentPublic _ CoreOps.CreateWires[0]; -- Should Be Dead End Wire noNamePublics _ CONS[parentPublic, noNamePublics]}; Must use rope here since Identity sub cell publics get copied when making the CellType to Layout to CellType round trip pas _ CONS[ [pName, parentPublic], pas]; [ ] _ AddWireSide[parentPublic, DelSide[inSides, sides]] } }; pas: LIST OF CoreCreate.PA _ NIL; outSides: Sides _ OutSides[index, size, first]; inSides: Sides _ DelSide[outSides, all]; IF checking AND GetCellSide[list.first.type]=none THEN Signal[]; [ ] _ CoreOps.VisitBinding [actual: list.first.actual, public: list.first.type.public, eachWirePair: eachWirePair]; THEN Signal[]; ais _ CONS[[PWC.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]; DelPAInternalOnlys[newPublicCtx, ais]; SELECT first FROM right, top => { }; ENDCASE => { list: LIST OF PWC.AbutInstance _ ais; ais _ NIL; FOR list _ list, list.rest WHILE list#NIL DO ais _ CONS[list.first, ais] ENDLOOP}; cellType _ PWC.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]}; PWC.FromLayoutWithoutPublic of PW.Abut Rename by visiting bindings AbutCellInstances: PUBLIC PROC[ name: ROPE, first: Sides, instances: CoreClasses.CellInstances] RETURNS[cellType: CellType, ] = { RevObjs: PROC = { temp: PW.ListOb _ objs; objs _ NIL; FOR temp _ temp, temp.rest WHILE temp#NIL DO objs _ CONS[temp.first, objs] ENDLOOP}; publicSides: HashTable.Table _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; newFirst: Sides; objs: PW.ListOb _ NIL; obj: CD.Object _ NIL; data: CoreClasses.RecordCellType; list: CoreClasses.CellInstances _ SELECT first FROM left, bottom => RevInstances[instances], ENDCASE => instances; FOR list _ list, list.rest WHILE list#NIL DO objs _ CONS[PWC.Layout[list.first.type], objs] ENDLOOP; SELECT first FROM left, right => {obj _ PW.AbutListX[objs]; newFirst _ left}; bottom, top => {obj _ PW.AbutListY[objs]; newFirst _ bottom}; ENDCASE => ERROR; cellType _ PWC.FromLayoutWithoutPublic[obj]; [ ] _ CoreName.CellNm[cellType, name]; data _ NARROW[cellType.data]; IF data.size>1 AND first=none THEN Signal[]; list _ SELECT first FROM right, top => RevInstances[instances], ENDCASE => instances; FOR index: NAT IN [0..data.size) DO Visit: CoreOps.EachWirePairProc ~ { name: ROPE _ CoreName.WireNm[publicWire].n; [ ] _ CoreName.WireNm[actualWire, name]}; IF GetCellSide[data[index].type]=none THEN Signal[]; IF list.first.type#data[index].type THEN Signal[]; -- PWC should have cached [ ] _ CoreOps.VisitBinding [actual: data[index].actual, public: list.first.actual, eachWirePair: Visit]; list _ list.rest ENDLOOP; CoreOps.FlushNameCaches[cellType.public]; CoreOps.FlushNameCaches[data.internal]; CoreBlock.PutCellSide [cellType, newFirst]; CoreBlock.MergeSides [cellType]; SELECT newFirst FROM left => PWC.SetAbutX[cellType]; bottom => PWC.SetAbutY[cellType]; ENDCASE => Signal[] }; PWC.FromLayoutWithoutPublic of PW.Abut Rename by visiting bindings AbutCellInstances: PUBLIC PROC[ name: ROPE, first: Sides, instances: CoreClasses.CellInstances] RETURNS[cellType: CellType, ] = { ApplySidesToPublic: PROC [wire: Wire] ~ { name: ROPE _ CoreName.WireNm[wire].n; refSides: REF Sides _ NARROW[HashTable.Fetch[publicSides, name].value]; IF refSides=NIL THEN Signal[]; IF refSides^=none THEN Signal[]; IF CoreProperties.GetWireProp[wire, SidesProp[]]#NIL THEN Signal[]; CoreProperties.PutWireProp[wire, SidesProp[], refSides]}; RevObjs: PROC = { temp: PW.ListOb _ objs; objs _ NIL; FOR temp _ temp, temp.rest WHILE temp#NIL DO objs _ CONS[temp.first, objs] ENDLOOP}; publicSides: HashTable.Table _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; hidden: Sides; newFirst: Sides; newLast: Sides; objs: PW.ListOb _ NIL; obj: CD.Object _ NIL; data: CoreClasses.RecordCellType; list: CoreClasses.CellInstances _ SELECT first FROM left, bottom => RevInstances[instances], ENDCASE => instances; FOR list _ list, list.rest WHILE list#NIL DO objs _ CONS[PWC.Layout[list.first.type], objs] ENDLOOP; SELECT first FROM left, right => {obj _ PW.AbutListX[objs]; newFirst _ left}; bottom, top => {obj _ PW.AbutListY[objs]; newFirst _ bottom}; ENDCASE => ERROR; newLast _ OtherSide[newFirst]; cellType _ PWC.FromLayoutWithoutPublic[obj]; [ ] _ CoreName.CellNm[cellType, name]; data _ NARROW[cellType.data]; IF data.size>1 AND first=none THEN Signal[]; list _ SELECT first FROM right, top => RevInstances[instances], ENDCASE => instances; FOR index: NAT IN [0..data.size) DO Visit: CoreOps.EachWirePairProc ~ { name: ROPE _ CoreName.WireNm[publicWire].n; side: Sides _ GetWireSide[actualWire]; pubs: REF Sides _ NARROW[HashTable.Fetch[publicSides, name].value]; side _ DelSide[hidden, side]; IF pubs=NIL THEN pubs _ NEW[Sides _ none]; pubs^ _ AddSide[pubs^, side]; [ ] _ HashTable.Store[publicSides, name, pubs]; [ ] _ CoreName.WireNm[actualWire, name]}; IF GetCellSide[data[index].type]=none THEN Signal[]; hidden _ IF index # 0 THEN newFirst ELSE none; hidden _ AddSide[ IF (index+1) < data.size THEN newLast ELSE none, hidden]; IF list.first.type#data[index].type THEN Signal[]; -- PWC should have cached [ ] _ CoreOps.VisitBinding [actual: data[index].actual, public: list.first.actual, eachWirePair: Visit]; list _ list.rest ENDLOOP; CoreOps.VisitRootAtomics[wire: cellType.public, eachWire: ApplySidesToPublic]; CoreOps.FlushNameCaches[cellType.public]; CoreOps.FlushNameCaches[data.internal]; CoreBlock.PutCellSide [cellType, newFirst]; CoreBlock.MergeSides [cellType]; -- replaced by ApplySidesToPublic SELECT newFirst FROM left => PWC.SetAbutX[cellType]; bottom => PWC.SetAbutY[cellType]; ENDCASE => Signal[] }; PWC.CoreCreate.Cell AbutCellList: PUBLIC PROC[ name: ROPE, first: Sides, cellTypes: LIST OF CellType, ] RETURNS[cellType: CellType, ] = { oIside, nIside, oOsides, nOsides: Sides; public: CoreName.Context _ CoreName.NewContext[]; internal: CoreName.Context _ CoreName.NewContext[]; intOnly: CoreName.Context _ CoreName.NewContext[]; intances: CoreClasses.CellInstances; tempInsts: CoreClasses.CellInstances; IF first=right OR first=top THEN { temp: LIST OF CellType, _ cellTypes; cellTypes _ NIL; FOR temp _ temp, temp.rest WHILE temp#NIL DO cellTypes _ CONS[temp.first, cellTypes] ENDLOOP; IF first=right THEN first_left ELSE first_bottom}; IF first=left THEN {oIside _ right; nIside _ left} ELSE {oIside _ top; nIside _ bottom}; oOsides _ DelSide[ oIside, all]; nOsides _ DelSide[ nIside, all]; FOR kids: LIST OF CellType, _ cellTypes, kids.rest WHILE kids#NIL DO nPubSides: Sides _ all; IF kids#cellTypes THEN nPubSides _ DelSide[nIside, nPubSides]; IF kids.rest#NIL THEN nPubSides _ DelSide[oIside, nPubSides]; FOR index: INT IN [0..kids.first.public.size) DO newWire: Wire _ kids.first.public[index]; aName: ROPE _ CoreName.WireNm[newWire ].n; oldWire: Wire _ CoreName.CtxWire[internal, aName]; -- adds if not present check: Wire _ CoreName.CtxNameToWire[intOnly, aName]; oldSides: Sides _ CoreBlock.GetWireSide[oldWire]; newSides: Sides _ CoreBlock.GetWireSide[newWire]; oldExternal: BOOL _ CoreBlock.OnSide[oldSides, oOsides]; oldConn: BOOL _ CoreBlock.OnSide[oldSides, oIside]; newExternal: BOOL _ CoreBlock.OnSide[newSides, nOsides]; newConn: BOOL _ CoreBlock.OnSide[newSides, nIside]; newPublic: BOOL _ CoreBlock.OnSide[newSides, nPubSides]; IF check#NIL THEN Signal[]; IF kids#cellTypes THEN { IF oldConn # newConn THEN { log.PutF["\n Wire ending at cell boundry."]; log.PutF[" Parent: %g; Neglected child: %g; Wire: %g", IO.rope[name], IO.rope[CoreName.CellNm[kids.first].n], IO.rope[aName]]}; IF ~(oldExternal OR newExternal) THEN [] _ CoreName.CtxWire[intOnly, aName]}; IF oldExternal OR newPublic THEN [ ] _ CoreName.CtxRegisterWire[public, oldWire]; PutWireSide[oldWire, AddSide[DelSide[ oIside, oldSides], DelSide[ nIside, newSides]]]; ENDLOOP; intances _ CONS[CoreCreate.Instance[ kids.first ], intances]; ENDLOOP; tempInsts _ intances; intances _ NIL; FOR tempInsts _ tempInsts, tempInsts.rest WHILE tempInsts#NIL DO intances _ CONS[tempInsts.first, intances] ENDLOOP; IF HashTable.GetSize[internal] # (HashTable.GetSize[public] + HashTable.GetSize[intOnly]) THEN log.PutF["\n CoreBlockImpl.AbutCellList internal#public+intOnly anomaly"]; THEN Signal; cellType _ CoreCreate.Cell[ public: CoreName.WireFromCtx[public], internal: CoreName.WireFromCtx[internal], instances: intances, name: name ]; public _ CoreName.KillContext[public]; internal _ CoreName.KillContext[internal]; intOnly _ CoreName.KillContext[intOnly]; CoreBlock.PutCellSide [cellType, first]; CoreBlock.MergeSides [cellType]; SELECT first FROM left => PWC.SetAbutX[cellType]; bottom => PWC.SetAbutY[cellType]; ENDCASE => Signal[] }; ʘšœ™J™5J™5—J˜JšÏk œ œ—œœ˜½J•StartOfExpansion[]˜šÏn œœ˜Jšœœ„œœ˜›Jšœ ˜Jšœœ ˜—J˜Jšœœ ˜Jšœ œ˜ Jšœœœ˜J˜Jš œ œœœœ˜?J˜Jšžœœœ˜J˜šžœœœœ ˜6Jšœœœ(˜H—šžœœœœ ˜6Jšœœœœ)˜X—š žœœœœœ˜4Jšœœ œ*˜@—šž œœœœ ˜4Jš œœœœ4œ ˜\—š ž œœœœœ˜;Jšœœœ ˜—š ž œœœœœ˜;Jšœœœœ ˜>—J˜šž œœœœ˜BJšœ œ˜Jšœœœœ˜Jšœ œ4˜EJš œœ œœœ˜3—J˜šž œœœ˜7Jšœ3œ˜Q—J˜šž œœœ œ˜>Jšœ œ˜Jšœœœœ˜Jšœ œ0˜AJš œœ œœœ ˜2—J˜šž œœœ˜5Jšœ œ˜Jšœœœœ˜Jšœ œ0˜Ašœ ˜Jšœ/œ˜OJšœ˜—Jš œœœœœ˜D—J˜šž œœœœ˜NJšœ œ˜Jš œœœœœ˜Jšœ œ0˜AJšœ œœ œ˜2Jšœ%˜%Jšœ8˜8Jš œœœœ&œ˜MJšœ˜—J˜šž œœœœ˜NJšœ œ˜Jš œœœœœ˜Jšœ œ0˜AJšœ œœ œ˜2Jšœ%˜%Jšœ8˜8Jš œœœœ&œ˜MJšœ˜—J˜šž œœœ˜,Jšœ"˜"Jšœ ˜ Jšœ˜Jšœ#œ ˜5šœ#˜#Jšœ&˜&Jšœ˜Jšœ%˜%—Jšœ œ œ ˜,šœœœ˜Jšœ œ œœ˜-Jšœœœœ˜DJšœG˜O—Jšœ˜—J˜šžœœœ˜:Jšœœ˜š œœ œœ˜1šœ#˜%Jšœ œ˜-šœ)˜-Jšœ-œ˜7———Jšœ+˜+J˜—šž œœ"œ$˜_Jš œœœœœœ˜R—J˜šž œœœ˜Jšœœ˜ Jšœ ˜ šœ œœ ˜Jšœ˜—Jšœœœ œ˜Jšœœœ œ˜Jšœ!˜!Jšœœœ™%š œœœ!œœ™Cšœ™Jšœ;œ™@Jšœœœ™+——Jšœœ ™'š œœœ!œœ˜Cšœœœ7˜EJšœœ˜'Jšœ˜"—Jšœ˜—šœ œœ˜$Jšœœœœ˜(Jš œœœœœœ˜R—Jšœ œœ˜;Jšœ&˜&Jšœ!œœœ ˜\Jšœ˜šœ œ œ˜"Jšœœœ#œ˜4šœœ˜)Jšœ œœ˜4——Jšœ™Jšœœ˜šœœœ˜#šžœ˜#Jšœœ!˜*Jšœ!œ ˜1Jš œœœœœ˜.šœ™Jšœœ*œ ™<—Jšœ(˜(—šœ™Jšœœœ!œ™T—šœ1™1Jšœ$œ ™4—Jšœœ ™*šœœ˜@JšœR˜R—Jšœœ˜#—JšÏbœ ˜—J˜JšœGŸœ™YJšœ^™^JšœJ™Jšž œ œ˜.Jšœ#œ˜9šœœœ˜#šžœ˜#Jšœœ!˜*Jš œœœœœœ˜@Jšœ(˜(—šœ œ˜AJšœSœ˜[——JšŸœ ˜—J˜Jšœœ˜#Jšœœ˜#Jšœœ˜#Jšœœ˜#Jšœœ˜#J™Jšœ+™+Jšœ(™(šŸœœ˜/Jšœ5Ïc˜KJšœ8 ˜@Jšœ6 ˜NJšœ4 ˜OJšœ&œ˜<šžœœœœ˜HJšœ˜šœœœ˜šœ˜Jšœžœ˜2šœ˜Jšœ˜Jšœœ˜&Jšœ8˜8Jšœ;˜;Jšœœ.˜AJšœœœ˜5Jšœœœ˜šœ œœœ˜4šœ˜Jšœ˜Jšœœœ˜Jšœ1˜1Jšœ.˜.Jšœ!œ'˜KJšÐbkœ˜——Jš œœ œœœ œ˜=šœ ˜Jšœ0˜4šœ˜Jšœœœœ'˜=šœœ˜Jšœ&œœœ˜;—J˜Jšœ œ œœ˜K——————šÐbnŸœœ˜Jšœ.˜.Jšœ0˜0—Jšœ0œ$˜VJšœžœ¢Ÿœ˜9JšŸœ(œ˜Bšœœœ˜JšŸœ'œœ˜J—JšŸœ&œ˜AJšœ1 ˜GJšœ1 ™GJšœ˜Jšœ ˜ Jšœ(˜(Jšœ*˜*—J˜šŸ(œœ™FJšœ œ™Jšœ4™4Jšœ! ™8Jšœ ™1Jšœ œ™,Jšœ&œ™<šžœœœ™8šœœœ™šœ™Jšœ&™*šœ™Jšœ™Jšœœ™$Jšœ2™2Jš œœœ œœ™ Jšœ,œœ™Išœœ™šœ$œ™,Jšœœœœ-™CJšœ œ œ™@J™Jšœ %™,—šœ ™ Jšœ  $™2šœ™Jšœ9œ ™HJšœ5œ œ œ-™ƒJšœ'™'Jšœ1œ™:———Jšœ™Jšœ0™0Jšœ(œ ™6Jšœ.™.JšœL™L——Jšœ™ ——Jšž œœ@™RJšœ4œ ™CJšœžœž œ™>Jšœ% ™—šœœœ™,Jšœœ$œ™7—šœ™Jšœœ#™;Jšœœ%™=Jšœœ™—Jšœ,™,Jšœ&™&Jšœœ™Jšœ œ œ ™,šœ œ™Jšœ' œ ™<—šœœœ™#šžœ™#Jšœœ!™+Jšœ.™.—Jšœ$œ ™4Jšœ"œ  ™Lšœ™JšœŸœŸœ*™M—Jšœœ™—Jšœ)™)Jšœ'™'Jšœ+™+Jšœ ™ šœ ™Jšœ ™ Jšœ!™!Jšœ™——J˜šœœ™&Jšœ™—šžœœœ™Jšœœ™ Jšœ™šœ&™&Jšœ™!—šžœœ™)Jšœœ™&Jšœ œ œ+™HJšœ œœ ™Jšœœ ™ Jšœ/œœ ™CJšœ9™9—šžœœ™Jšœœœ™#Jš œœœœœœ™T—šœ™JšœG™G—Jšœ™Jšœ™Jšœ™Jšœœ œ™Jšœœ œ™Jšœ!™!šœ œ™3Jšœ) œ ™>—šœœœ™,Jšœœ$œ™7—šœ™Jšœœ#™;Jšœœ%™=Jšœœ™—Jšœ™Jšœ,™,Jšœ&™&Jšœœ™Jšœ œ œ ™,šœ œ™Jšœ' œ ™<—šœœœ™#šžœ™#Jšœœ!™+Jšœ(™(Jšœœ œ+™DJšœ!™!Jšœœœœ™*Jšœ!™!Jšœ4™4Jšœ.™.—Jšœ$œ ™4Jšœ œœ œ™5Jšœœœ œ™KJšœ"œ  ™Lšœ™JšœŸœŸœ*™M—Jšœœ™—Jšœžœ6™NJšœ)™)Jšœ'™'Jšœ+™+JšœB™Bšœ ™Jšœ ™ Jšœ!™!Jšœ™——J˜Jšœ™šž œœœ™Jšœœ™ Jšœ ™ šœ œœ ™Jšœ™!—Jšœ(™(Jšœ1™1Jšœ3™3Jšœ2™2Jšœ%™%Jšœ%™%šœ œ ™šœ™Jšœœœ%œ™6šœœœ™,Jšœ œ™0—Jšœ œ œ™2——šœ ™ Jšœ ™$Jšœ!™%—Jšœ ™ Jšœ ™ š œœœ#œœ™EJšœ™Jšœœ(™>Jšœ œ(™>šœœœ™0Jšœ*™*Jšœœ™+JšœJ™JJšœ6™6Jšœ3™3Jšœ3™3Jšœ œ(™9Jšœ œ'™5Jšœ œ(™9Jšœ œ'™4Jšœ œ*™9Jšœœœ ™šœ™šœ™Jšœ,™,šœ9™9Jšœ œ&œ™H——Jšœœ œ œ(™M—Jšœ œ œ1™QJšœV™VJšœ™—Jšœ œ.™=Jšœ™—Jšœ!œ™%šœ'œ œ™@Jšœ œ™3—šœW™YJšœK™OJšœ™ —šœ™Jšœ&™&Jšœ*™*Jšœ™Jšœ™—Jšœ&™&Jšœ*™*Jšœ(™(Jšœ(™(Jšœ ™ šœ™Jšœ ™ Jšœ!™!Jšœ™——J˜šž œœœ'˜=šœœ˜"JšœT˜T—Jšœœœ "˜IJšœ žœ˜9Jšœ˜J˜—šžœœœ˜NJšœœ,˜CJšœœ-˜DJšœœ+˜AJšœœ/˜G—J˜šžœœœ˜;Jšœ˜ Jšœœœ˜%šœ-˜-JšœQ˜Q—Jšœ œ?˜PJ˜—šžœœ˜Jš œœœ œ$œ˜VJšœœœ˜%JšœœG˜OJšœ ˜ Jšœœ˜7Jšœœ˜7Jšœœ˜5Jšœœ˜7šœœ˜Jšœ!˜!Jšœ!˜!Jšœ˜—šœœ˜Jšœ!˜!Jšœ!˜!Jšœ˜——J˜Jšœœœ˜$J™Jšœ˜—…—.p€