CoreBlockImpl.mesa
Created by Don Curry, February 1, 1986 2:43:22 pm PST
Edited by Don Curry, June 25, 1986 3:51:31 pm PDT
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];
CoreOps.PrintIndent[indent, to];
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: BOOLSELECT 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 ← GetWireLayoutSides[list.first.type, publicWire];
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.PANIL;
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];
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];
DelPAInternalOnlys[newPublicCtx, ais];
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: ROPENARROW[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: BOOLTRUE;
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]};
PWCore.FromLayoutWithoutPublic of PW.Abut
Rename by visiting bindings
AbutCellInstances: PUBLIC PROC[
name:   Core.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[PWCore.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 ← PWCore.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: Core.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[]; -- PWCore 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  => PWCore.SetAbutX[cellType];
bottom => PWCore.SetAbutY[cellType];
ENDCASE => Signal[] };
PWCore.FromLayoutWithoutPublic of PW.Abut
Rename by visiting bindings
AbutCellInstances: PUBLIC PROC[
name:   Core.ROPE,
first:   Sides,
instances:  CoreClasses.CellInstances]
RETURNS[cellType: CellType,
] = {
ApplySidesToPublic: PROC [wire: Wire] ~ {
name:  Core.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, sides]#NIL THEN Signal[];
CoreProperties.PutWireProp[wire, sides, 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[PWCore.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 ← PWCore.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: Core.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[]; -- PWCore should have cached
[ ] ← CoreOps.VisitBinding
[actual: data[index].actual, public: list.first.actual, eachWirePair: Visit];
list ← list.rest ENDLOOP;
CoreOps.VisitAtomicWires[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  => PWCore.SetAbutX[cellType];
bottom => PWCore.SetAbutY[cellType];
ENDCASE => Signal[] };
PWCore.CoreCreate.Cell
AbutCellList: PUBLIC PROC[
name: Core.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𡤋ottom};
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:  Core.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  => PWCore.SetAbutX[cellType];
bottom => PWCore.SetAbutY[cellType];
ENDCASE => Signal[] };
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 Signal[];
[] ← CoreOps.VisitAtomicWires[cell.public, eachWireProc];
PutCellSide[cell, all]};
GetWireLayoutSides: PUBLIC PROC[cell: CellType, wire: Wire]
RETURNS[sides: Sides ← none] = {
obj: CD.Object ← PWCore.Layout[cell];
eachPinProc: PWCore.EachPinProc =
{sides ← CoreBlock.AddSide[sides, GetInstSideLoc[obj, instance].side]};
[] ← PWCore.EnumeratePins[cell, wire, eachPinProc]};
GetInstSideLoc: PUBLIC PROC [ob: CD.Object, inst: CD.Instance] RETURNS [side: CoreBlock.Sides, loc: 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};
log: IO.STREAM ← CoreFrame.GetLog[];
END.