DIRECTORY CDBasics, CoreCreate, CD, CDOrient, Basics, Core, CoreBlock, CoreGeometry, CoreIOIFUProps, CoreOps, CoreClasses, CoreFrame, CoreInstCell, CoreName, CoreProperties, HashTable, IO, PWC, Rope; CoreBlockImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, 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 _ CDBasics.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, February 21, 1987 11:20:59 am PST Last Edited by: Louis Monier February 10, 1987 5:41:26 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™6Icode™=—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šœ˜—…—.„€n