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 [record: Core.CellType]
RETURNS [split: Core.CellType ←
NIL] = {
rct: CoreClasses.RecordCellType = NARROW [record.data];
intTable: RefTab.Ref = RefTab.Create[]; -- maps internals of record to internals of split
public: Core.WireSeq = MakeNewSeq[record.public, intTable];
intType: RefTab.Ref = RefTab.Create[]; -- maps internals of split to WireUses
combs: LIST OF CoreClasses.CellInstance ← NIL; -- new combinatorial instances
nonCombs: LIST OF CoreClasses.CellInstance ← NIL; -- new non-combinatorial instances
combInt, combPub, combAct: Core.Wires ← NIL;
combCT: Core.CellType;
combInstance: CoreClasses.CellInstance;
combNewInt: RefTab.Ref = RefTab.Create[]; -- maps internals of split to internals of combCT
internals: Core.Wires ← NIL;
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];
};
FOR i:
NAT
IN [0 .. rct.size)
DO
ct: Core.CellType = rct[i].type;
actual: Core.WireSeq = MakeNewSeq[rct[i].actual, intTable];
instance: CoreClasses.CellInstance = CoreClasses.CreateInstance[actual, ct];
IF InternalIsCombinatorial[ct]
THEN combs ← CONS [instance, combs]
ELSE nonCombs ← CONS [instance, nonCombs];
ENDLOOP;
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;
newInt: Core.Wire ← NARROW [SearchRefTab[combNewInt, wire].key];
oldInt: Core.Wire ← NARROW [SearchRefTab[intTable, newInt].key];
IF root#combCT OR oldInt=NIL THEN ERROR;
InputOutputWarning[type, record, NEW [CoreFlat.FlatWireRec ← [wire: oldInt]]];
RESUME;
}];
combInstance ← CoreClasses.CreateInstance[actual: CoreOps.CreateWire[combAct], type: combCT];
split ← CoreClasses.CreateRecordCell[
public: public,
internal: CoreOps.CreateWire[internals],
instances: CONS [combInstance, nonCombs],
giveNames: TRUE
];
TerminalIO.PutF[
"Splitting done for %g: combinatorial cell with %g outputs and %g non combinatorial cells.\n",
IO.rope[CoreOps.GetCellTypeName[record]],
IO.int[GList.Length[GetTypedWires[combCT, output]]],
IO.int[GList.Length[nonCombs]]
];
};