Instance:
PROC [ct: Core.CellType, bindings: CoreFlat.Bindings, intTable: RefTab.Ref]
RETURNS [CoreClasses.CellInstance] = {
MakeActual:
PROC [public: Core.Wire]
RETURNS [actual: Core.Wire] = {
flatWire: CoreFlat.FlatWire = NARROW [RefTab.Fetch[bindings, public].val];
actual ← NARROW [RefTab.Fetch[table, public].val];
IF actual#NIL THEN RETURN;
IF flatWire=NIL THEN ERROR;
actual ← NARROW [RefTab.Fetch[intTable, flatWire].val];
IF actual#NIL THEN RETURN;
actual ← CoreOps.CreateWires[size: public.size];
[] ← RefTab.Store[intTable, flatWire, actual];
[] ← RefTab.Store[table, public, actual];
FOR i: NAT IN [0 .. public.size) DO actual[i] ← MakeActual[public[i]] ENDLOOP;
};
table: RefTab.Ref = RefTab.Create[]; -- maps publics of ct to new internals of record
actual: Core.WireSeq ← CoreOps.CreateWires[size: ct.public.size];
FOR i: NAT IN [0 .. actual.size) DO actual[i] ← MakeActual[ct.public[i]] ENDLOOP;
RETURN [CoreClasses.CreateInstance[actual, ct]];
};
AddIntType:
PROC [intType: RefTab.Ref, int: Core.Wire, type: WireUse] = {
wireUses: REF WireUses ← NARROW [RefTab.Fetch[intType, int].val];
IF wireUses=NIL THEN wireUses ← NEW [WireUses];
wireUses[type] ← TRUE;
[] ← RefTab.Store[intType, int, wireUses];
FOR i: NAT IN [0 .. int.size) DO AddIntType[intType, int[i], type] ENDLOOP;
};
SplitCombinatorial:
PUBLIC
PROC [cell: Core.CellType, flatten:
PROC [ct: Core.CellType]
RETURNS [
BOOL]]
RETURNS [record: Core.CellType ←
NIL] = {
public: Core.WireSeq = CoreOps.CopyWire[cell.public];
intTable: RefTab.Ref = RefTab.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash]; -- maps flat wires of cell to internals of record
intType: RefTab.Ref = RefTab.Create[]; -- maps internals of record to WireUses
combs: LIST OF CoreClasses.CellInstance ← NIL; -- new combinatorial instances
nonCombs: LIST OF CoreClasses.CellInstance ← NIL; -- new non-combinatorial instances
bindings: CoreFlat.Bindings ← CoreFlat.InitialBindingTable[cell];
combInt, combPub, combAct: Core.Wires ← NIL;
combCT: Core.CellType;
combInstance: CoreClasses.CellInstance;
combNewInt: RefTab.Ref = RefTab.Create[]; -- maps internals of record to internals of combCT
internals: Core.Wires ← NIL;
EachBound: CoreFlat.BoundFlatCellProc = {
SELECT
TRUE
FROM
InternalIsCombinatorial[cell] => combs ← CONS [Instance[cell, bindings, intTable], combs];
flatten[cell] => CoreFlat.NextBoundCellType[cell: cell, target: target, flatCell: flatCell, instance: instance, index: index, parent: parent, flatParent: flatParent, data: data, bindings: bindings, proc: EachBound];
ENDCASE => nonCombs ← CONS [Instance[cell, bindings, intTable], nonCombs];
};
CreateNew:
PROC [int: Core.Wire]
RETURNS [new: Core.Wire] = {
new ← NARROW [RefTab.Fetch[combNewInt, int].val];
IF new#NIL THEN RETURN;
new ← CoreOps.CreateWires[int.size];
[] ← RefTab.Store[combNewInt, int, new];
FOR i: NAT IN [0 .. int.size) DO new[i] ← CreateNew[int[i]] ENDLOOP;
};
EachIntTypeCreateNew: RefTab.EachPairAction = {
wireUses: REF WireUses = NARROW [val];
IF wireUses[CombUse] THEN [] ← CreateNew[NARROW [key]];
};
EachIntType: RefTab.EachPairAction = {
int: Core.Wire = NARROW [key];
wireUses: REF WireUses = NARROW [val];
IF wireUses[CombUse]
THEN {
new: Core.Wire ← NARROW [RefTab.Fetch[combNewInt, int].val];
combInt ← ConsIfNotMember[new, combInt];
IF NOT wireUses[NonCombUse] AND NOT wireUses[PublicUse] THEN RETURN;
internals ← ConsIfNotMember[int, internals];
combInt ← ConsIfNotMember[new, combInt];
IF
NOT CoreOps.Member[combPub, new]
THEN {
combAct ← CONS [int, combAct];
combPub ← CONS [new, combPub];
};
}
ELSE internals ← ConsIfNotMember[int, internals];
};
BEGIN
EachBind: RefTab.EachPairAction = {
cellPub: Core.Wire = NARROW [key];
flatWire: CoreFlat.FlatWire = NARROW [val];
pub: Core.Wire = NARROW [RefTab.Fetch[pubTable, cellPub].val];
IF pub=NIL THEN ERROR;
[] ← RefTab.Store[intTable, flatWire, pub];
};
pubTable: RefTab.Ref = CoreOps.CreateBindingTable[cell.public, public]; -- maps publics of cell to public of record
[] ← RefTab.Pairs[bindings, EachBind];
END;
EachBound[cell: cell, bindings: bindings];
FOR i: NAT IN [0 .. public.size) DO AddIntType[intType, public[i], PublicUse] ENDLOOP;
FOR list:
LIST
OF CoreClasses.CellInstance ← combs, list.rest
WHILE list#
NIL
DO
FOR i: NAT IN [0 .. list.first.actual.size) DO AddIntType[intType, list.first.actual[i], CombUse] ENDLOOP;
ENDLOOP;
FOR list:
LIST
OF CoreClasses.CellInstance ← nonCombs, list.rest
WHILE list#
NIL
DO
FOR i: NAT IN [0 .. list.first.actual.size) DO AddIntType[intType, list.first.actual[i], NonCombUse] ENDLOOP;
ENDLOOP;
[] ← RefTab.Pairs[intType, EachIntTypeCreateNew];
[] ← RefTab.Pairs[intType, EachIntType];
FOR list:
LIST
OF CoreClasses.CellInstance ← combs, list.rest
WHILE list#
NIL
DO
actual: Core.WireSeq ← CoreOps.CreateWires[list.first.actual.size];
FOR i:
NAT
IN [0 .. actual.size)
DO
actual[i] ← NARROW [RefTab.Fetch[combNewInt, list.first.actual[i]].val];
IF actual[i]=NIL THEN ERROR;
ENDLOOP;
list.first.actual ← actual;
ENDLOOP;
combCT ← CoreClasses.CreateRecordCell[
public: CoreOps.CreateWire[combPub], internal: CoreOps.CreateWire[combInt],
instances: combs, giveNames: TRUE
];
MakeCombinatorial[combCT ! InputOutputProblem => {
wire: Core.Wire ← flatWire.wire;
int: Core.Wire ← NARROW [SearchRefTab[combNewInt, wire].key];
intFlat: CoreFlat.FlatWire ← NARROW [SearchRefTab[intTable, int].key];
IF root#combCT OR intFlat=NIL THEN ERROR;
InputOutputWarning[type, cell, intFlat];
RESUME;
}];
combInstance ← CoreClasses.CreateInstance[actual: CoreOps.CreateWire[combAct], type: combCT];
record ← CoreClasses.CreateRecordCell[
public: public,
internal: CoreOps.CreateWire[internals],
instances: CONS [combInstance, nonCombs],
props: CoreProperties.Props[[$FlattenForCombinatorial, $FALSE]],
giveNames: TRUE
];
};