/* CoreFlat.c */
#include "CoreBasics.h"
#include "Core.h"
#include "CoreFlat.h"
/* Types */
FlatCellTypeRec rootCellType;
FlatCellTypeRec allFlatCells;
WirePathRec rootWirePath;
/* Flat Instance */
Bool InstancePathEqualRec(one, other)
InstancePathRec one;
InstancePathRec other;
{
Nat i;
if (one.length!=other.length) return(false);
for (i=0; i<CellTypePathSize; i++) if (one.bits[i]!=other.bits[i]) return(false);
return(true);
};
Nat InstancePathHashRec(path)
InstancePathRec path;
{
Nat hash=0;
Nat i;
for (i=0; i<=path.length; i++) hash=hash↑(path.bits[i]<<(i%16));
return(hash);
};
void ExtendPath(newPath, currentPath, index, rct)
InstancePath newPath;
InstancePathRec currentPath;
Nat index;
RecordCellType rct;
{
Nat bit;
Nat pathBits=NBits(rct->size);
*newPath=currentPath;
for (bit=0; bit<pathBits; bit++) newPath->bits[newPath->length+bit]=EBFN(index, bit, pathBits);
newPath->length+=pathBits;
};
typedef struct BindPublicToActualContextRec {
HashTable bindings;
HashTable newBindings;
FlatCellTypeRec parent;
} BindPublicToActualContextRec;
typedef BindPublicToActualContextRec *BindPublicToActualContext;
Bool BindPublicToActual(actualWire, publicWire, context, subWires)
Wire actualWire;
Wire publicWire;
Ref context;
Bool *subWires;
{
BindPublicToActualContext c=(BindPublicToActualContext)context;
FlatWire bind=nil;
*subWires=true;
if (c->bindings!=nil) bind=(FlatWire)HashTableGet(c->bindings, actualWire);
if (bind==nil) bind=CreateFlatWire(c->parent, 0, internal, false, rootWirePath, actualWire);
HashTablePut(c->newBindings, publicWire, bind);
return(false);
};
HashTable BindInstance(parent, actual, public, bindings)
FlatCellTypeRec parent;
WireSeq actual;
WireSeq public;
HashTable bindings;
{
BindPublicToActualContextRec context;
context.bindings=bindings;
context.newBindings=HashTableCreate(17, nil, nil);
context.parent=parent;
if (VisitBindingSeq(actual, public, BindPublicToActual, &context)) Die;
return(context.newBindings);
};
/* Flat Cell Type */
Bool FlatCellTypeEqualRec(one, other)
FlatCellTypeRec one;
FlatCellTypeRec other;
{
return(InstancePathEqualRec(one.path, other.path) && one.recastCount==other.recastCount);
};
Nat FlatCellTypeHashRec(flatCell)
FlatCellTypeRec flatCell;
{
Nat hash=InstancePathHashRec(flatCell.path);
hash=hash↑flatCell.recastCount;
return(hash);
};
/* Flat Wire */
FlatWire CreateFlatWire(flatCell, instanceIndex, wireRoot, validPath, path, wire)
FlatCellTypeRec flatCell;
Nat instanceIndex;
WireRoot wireRoot;
Bool validPath;
WirePathRec path;
Wire wire;
{
FlatWire flatWire=New(FlatWire, FlatWireRec);
flatWire->flatCell=flatCell;
flatWire->instanceIndex=instanceIndex;
flatWire->wireRoot=wireRoot;
flatWire->validPath=validPath;
flatWire->path=path;
flatWire->wire=wire;
return(flatWire);
};
Bool FlatWireEqual(key1, key2)
Ref key1;
Ref key2;
{
FlatWire wire1=(FlatWire)key1;
FlatWire wire2=(FlatWire)key2;
return(wire1->wire==wire2->wire && FlatCellTypeEqualRec(wire1->flatCell, wire2->flatCell));
};
Nat FlatWireHash(key)
Ref key;
{
FlatWire flatWire=(FlatWire)key;
Nat hash=FlatCellTypeHashRec(flatWire->flatCell);
hash=hash↑(((Nat)flatWire->wire)&0x0FFFFL)↑(((Nat)flatWire->wire)>>16);
return(hash);
};
/* Enumeration */
void NextUnboundCellType(cell, target, flatCell, instance, index, parent, flatParent, data, proc)
CellType cell;
FlatCellTypeRec target;
FlatCellTypeRec flatCell;
CellInstance instance;
Nat index;
CellType parent;
FlatCellTypeRec flatParent;
Ref data;
UnboundFlatCellProc proc;
{
if (FlatCellTypeEqualRec(target, flatCell)) return;
if (cell->class==recordCellClass) {
RecordCellType rct=(RecordCellType)cell->data;
Nat pathBits=NBits(rct->size);
CellInstance instance;
FlatCellTypeRec childFlatCell;
childFlatCell.path=flatCell.path;
childFlatCell.recastCount=0;
if (FlatCellTypeEqualRec(target, allFlatCells)) {
Nat inst;
for (inst=0; inst<rct->size; inst++) {
instance=rct->cellInstances[inst];
ExtendPath(&childFlatCell.path, flatCell.path, inst, rct);
proc(instance->type, target, childFlatCell, instance, inst, cell, flatCell, data);
};
}
else Die;
}
else Die;
};
typedef struct BindCellTypeContextRec {
CellType previousCell;
CellInstance previousInstance;
Ref data;
HashTable bindings;
BoundFlatCellProc proc;
} BindCellTypeContextRec;
typedef BindCellTypeContextRec *BindCellTypeContext;
void BindCellType(cell, target, flatCell, instance, index, parent, flatParent, data)
CellType cell;
FlatCellTypeRec target;
FlatCellTypeRec flatCell;
CellInstance instance;
Nat index;
CellType parent;
FlatCellTypeRec flatParent;
Ref data;
{
BindCellTypeContext context=(BindCellTypeContext)data;
HashTable newBindings;
if (instance==context->previousInstance && cell==context->previousCell) context->proc(cell, target, flatCell, instance, index, parent, flatParent, context->data, context->bindings);
else {
Wire actual;
if (instance==nil || instance->type!=cell) actual=context->previousCell->public;
else actual=instance->actual;
newBindings=BindInstance(flatParent, actual, cell->public, context->bindings);
context->proc(cell, target, flatCell, instance, index, parent, flatParent, context->data, newBindings);
/* really should delete the flat wires which are no longer needed */
HashTableFree(newBindings);
};
};
void NextBoundCellType(cell, target, flatCell, instance, index, parent, flatParent, data, bindings, proc)
CellType cell;
FlatCellTypeRec target;
FlatCellTypeRec flatCell;
CellInstance instance;
Nat index;
CellType parent;
FlatCellTypeRec flatParent;
Ref data;
HashTable bindings;
UnboundFlatCellProc proc;
{
BindCellTypeContextRec context;
context.previousCell=cell;
context.previousInstance=instance;
context.data=data;
context.bindings=bindings;
context.proc=proc;
NextUnboundCellType(cell, target, flatCell, instance, index, parent, flatParent, &context, BindCellType);
};
HashTable InitialBindingTable(root)
CellType root;
{
HashTable bindings;
Die;
return(bindings);
};
/* Initialization */
void CoreFlatInitialize()
{
Nat i;
rootCellType.path.length=0;
for (i=0; i<CellTypePathSize; i++) rootCellType.path.bits[i]=false;
rootCellType.recastCount=0;
allFlatCells.path.length=0;
for (i=0; i<CellTypePathSize; i++) allFlatCells.path.bits[i]=false;
allFlatCells.recastCount=NatLast;
rootWirePath.length=0;
for (i=0; i<WirePathSize; i++) rootWirePath.bits[i]=false;
};