CoreConnectImpl.mesa
Copyright c 1986 by Xerox Corporation. All rights resersed.
Last Edited by: Curry, August 20, 1986 5:40:38 pm PDT
DIRECTORY Core, CoreClasses, CoreConnect, CoreGlue, CoreName, CoreOps, CoreFrame, HashTable, IO, Rope;
CoreConnectImpl: CEDAR PROGRAM
IMPORTS CoreFrame, CoreName, CoreOps, HashTable, IO, Rope
EXPORTS CoreConnect
ROPE: TYPE = Core.ROPE;
Path: TYPE = LIST OF INT; -- [bottom .. top]
Addr: TYPE = LIST OF INT; -- [top .. bottom]
CtxRec: TYPE = RECORD[addr: Addr, cnt: INT];
NodeContext: TYPE = REF NodeContextRec;
NodeContextRec:
TYPE =
RECORD[
root: Core.CellType,
table: HashTable.Table];
Signal: SIGNAL = CODE;
log: IO.STREAM ← CoreFrame.GetLog[];
Connect:
PUBLIC
PROC [frameCT: Core.CellType]
RETURNS[success:
BOOL ←
TRUE] = {
ctx: NodeContext ←
NEW[ NodeContextRec ← [
root: frameCT,
table: HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope ] ] ];
ConnectNodes[ctx];
CheckPublic[ctx];
success ← CheckConnects[frameCT];
success ← CheckForSingles[ctx];
LogFrame[frameCT, wireLogger];
LogFrame[frameCT, frameLogger];
};
ConnectNodes:
PROC [
ctx: NodeContext,
frameCT: Core.CellType ← NIL,
path: Path ← NIL ] = {
frame: CoreFrame.Frame ← FCT[IF frameCT=NIL THEN ctx.root ELSE frameCT];
hereRef: Addr ← PathToAddr[path];
eachWire: CoreOps.EachWireProc = {
name: ROPE ← CoreName.WireNm[wire].n;
IF wire=NIL THEN Signal[];
IF wire.size#0 THEN RETURN;
IF name.Length[]=0 THEN RETURN;
eachWireRp[name]};
eachWireRp:
PROC[name:
ROPE] = {
probe: Core.CellType;
start: Core.CellType ← ctx.root;
oldRef: REF CtxRec ← NARROW[HashTable.Fetch[ctx.table, name].value];
old: Addr ← NIL;
here: Addr ← hereRef;
new: Path ← NIL;
IF oldRef=NIL THEN {
frame.intOnly ← AddItem[name, frame.intOnly];
[]←HashTable.Store[ctx.table, name, NEW[CtxRec ← [here, 1]]];
RETURN };
old ← oldRef.addr;
DO
IF here=NIL OR old=NIL THEN EXIT;
IF here.first # old.first THEN EXIT;
new ← CONS[here.first, new];
start ← FCT[start].seq[here.first];
here ← here.rest;
old ← old.rest;
ENDLOOP;
oldRef.addr ← PathToAddr[new];
oldRef.cnt ← oldRef.cnt+1;
FCT[start].intOnly ← AddItem[name, FCT[start].intOnly];
probe ← start;
IF old#
NIL
THEN {
FOR old ← old, old.rest
WHILE old#
NIL
DO
probe ← FCT[probe].seq[old.first];
FCT[probe].public ← AddItem[name, FCT[probe].public];
ENDLOOP;
FCT[probe].intOnly ← RemoveItem[name, FCT[probe].intOnly] };
probe ← start;
FOR here ← here, here.rest
WHILE here#
NIL
DO
probe ← FCT[probe].seq[here.first];
FCT[probe].public ← AddItem[name, FCT[probe].public];
ENDLOOP };
IF frame.cell#
NIL
THEN [ ] ← CoreOps.VisitWire[frame.cell.public, eachWire]
ELSE IF frame.seq.size#0
THEN
FOR i:
INT
IN [0..frame.seq.size)
DO ConnectNodes[ctx, frame.seq[i], CONS[i, path]] ENDLOOP
ELSE
IF frame.data=
NIL OR NOT
ISTYPE[frame.data, CoreGlue.Glue]
THEN Signal[]
ELSE
FOR pubs:
LIST
OF
ROPE ← frame.public, pubs.rest
WHILE pubs#
NIL
DO [ ] ← eachWireRp[pubs.first] ENDLOOP};
CheckPublic:
PROC [ctx: NodeContext] = {
FOR public:
LIST
OF
ROPE ←
FCT[ctx.root].public, public.rest
WHILE public#
NIL
DO
oldRef: REF CtxRec ← NARROW[HashTable.Fetch[ctx.table, public.first].value];
probe: Core.CellType;
old: Addr ← oldRef.addr;
probe ← ctx.root;
IF oldRef=
NIL
THEN log.PutF["\n WARNING, %g's public: %g not exported by children",
IO.rope[CoreName.CellNm[ctx.root].n],
IO.rope[public.first] ]
ELSE
{
FOR old: Addr ← oldRef.addr, old.rest
WHILE old#
NIL
DO
probe ← FCT[probe].seq[old.first];
FCT[probe].public ← AddItem[public.first, FCT[probe].public];
ENDLOOP;
oldRef.cnt ← oldRef.cnt+1;
oldRef.addr ← NIL};
FCT[probe].intOnly ← RemoveItem[public.first, FCT[probe].intOnly];
ENDLOOP};
This picks up on unnamed publics generated by extractor
CheckConnects: PROC [frameCT: Core.CellType] RETURNS[ok: BOOL ← TRUE] = {
frame: CoreFrame.Frame ← FCT[frameCT];
IF frame.seq.size=0
THEN { -- expect no intOnlys and publics match
count: INT ← 0;
compare: INT ← 0;
data: CoreClasses.RecordCellType ← NARROW[frame.cell.data];
FOR lst: LIST OF ROPE ← frame.intOnly, lst.rest WHILE lst#NIL DO
ok ← FALSE;
count ← count+1;
log.PutF["\n WARNING, %g is NOT connected", IO.rope[lst.first]]; ENDLOOP;
FOR lst: LIST OF ROPE ← frame.public, lst.rest WHILE lst#NIL
DO count ← count+1 ENDLOOP;
compare ← IF frame.cell.public.size=0 THEN 0 ELSE CoreOps.WireBits[frame.cell.public];
IF compare#count THEN {ok ← FALSE; Signal[]} }
ELSE FOR i: INT DECREASING IN [0..frame.seq.size) DO
ok ← CheckConnects[frame.seq[i]] AND ok ENDLOOP };
CheckForSingles:
PROC [ctx: NodeContext]
RETURNS[ok:
BOOL ←
TRUE] = {
singleChk: HashTable.EachPairAction = {
oldRef: REF CtxRec ← NARROW[value];
IF oldRef.cnt < 2
THEN {
name: ROPE ← NARROW[key];
ok ← FALSE;
log.PutF["\n WARNING, %g is not connected", IO.rope[name]]} };
[ ] ← HashTable.Pairs[ctx.table, singleChk]};
LogFrame:
PROC[frameCT: Core.CellType, logger: FrameLogger] = {
LogIt:
PROC[fCT: Core.CellType, pathName:
ROPE ←
NIL, depth:
INT ← 0] = {
frame: CoreFrame.Frame ← FCT[fCT];
CoreOps.PrintIndent[depth, log];
log.PutF["Frame: %g", IO.rope[pathName]];
logger[fCT, depth];
FOR field:
INT
IN [0..frame.seq.size)
DO
name ← CoreName.CellNm[frame.seq[field]].n;
IF name=NIL THEN name ← IO.PutFR["%g", IO.int[field]];
LogIt[frame.seq[field], Rope.Cat[pathName, ".", name], depth+1]; ENDLOOP};
name: ROPE ← CoreName.CellNm[frameCT].n;
IF name=NIL THEN name ← "top";
LogIt[frameCT, name]};
FrameLogger: TYPE = PROC[fCT: Core.CellType, depth: INT];
wireLogger: FrameLogger = {
frame: CoreFrame.Frame ← FCT[fCT];
IF frame.seq.size=0 THEN CoreOps.PrintWire[frame.cell.public, log, depth]};
frameLogger: FrameLogger = {
frame: CoreFrame.Frame ← FCT[fCT];
CoreOps.PrintIndent[depth, log];
log.PutRope[" Public:"];
FOR list:
LIST
OF
ROPE ← frame.public, list.rest
WHILE list#
NIL
DO
log.PutRope[" "]; log.PutRope[list.first]; ENDLOOP;
CoreOps.PrintIndent[depth, log];
log.PutRope[" IntOnly:"];
FOR list:
LIST
OF
ROPE ← frame.intOnly, list.rest
WHILE list#
NIL
DO
log.PutRope[" "]; log.PutRope[list.first]; ENDLOOP;
IF frame.seq.size=0 THEN CoreOps.PrintWire[frame.cell.public, log, depth];
};
FCT:
PROC[frameCT: Core.CellType]
RETURNS[frame: CoreFrame.Frame] =
INLINE
{RETURN[CoreFrame.FCT[frameCT]]};
PathToAddr:
PROC [path: Path]
RETURNS[addr: Addr ←
NIL] =
{FOR path ← path, path.rest WHILE path#NIL DO addr ← CONS[path.first, addr] ENDLOOP};
LogAddr:
PROC [addr: Addr] =
{FOR addr ← addr, addr.rest WHILE addr#NIL DO log.PutF[" %g", IO.int[addr.first]] ENDLOOP};
RemoveItem:
PROC[item:
ROPE, list:
LIST
OF
ROPE]
RETURNS[new: LIST OF ROPE ← NIL] = {
FOR list ← list, list.rest
WHILE list#
NIL
DO
IF NOT Rope.Equal[item, list.first] THEN new ← CONS[list.first, new] ENDLOOP};
AddItem:
PROC[item:
ROPE, list:
LIST
OF
ROPE]
RETURNS[new:
LIST
OF
ROPE ←
NIL] = {
FOR lst:
LIST
OF
ROPE ← list, lst.rest
WHILE lst#
NIL
DO
IF Rope.Equal[item, lst.first] THEN RETURN[list] ENDLOOP;
RETURN[CONS[item, list]]};
END.