RawExtractCell: Sinix.ExtractProc = {
flattenSomeChild: BOOL ← FALSE;
rct: CoreClasses.RecordCellType;
new, record: CellType;
newInternals: Wires ← NIL; -- used only if flatten of a child necessary
instances: LIST OF CoreClasses.CellInstance ← NIL; -- used only if flatten of a child necessary
[result, props] ← Sinix.ExtractCell[obj, mode, properties, userData];
record ← NARROW [result];
rct ← NARROW [record.data];
IF rct.size=0 THEN CoreProperties.PutCellTypeProp[record, $RawFlatten, $Keep];
IF CDProperties.GetObjectProp[obj, $RawFlatten]=$RawFlatten THEN CoreProperties.PutCellTypeProp[record, $RawFlatten, $Smash];
FOR i:
NAT
IN [0 .. rct.size)
DO
IF CoreProperties.GetCellTypeProp[rct[i].type, $RawFlatten]#NIL THEN flattenSomeChild ← TRUE;
ENDLOOP;
IF NOT flattenSomeChild THEN RETURN;
TerminalIO.PutF["In cell %g, flattening:", IO.rope[PW.Name[obj]]];
FOR i:
NAT
IN [0 .. rct.size)
DO
IF CoreProperties.GetCellTypeProp[rct[i].type, $RawFlatten]=
NIL
THEN instances ← CONS [rct[i], instances]
ELSE {
The following code does not deal properly with DAGS. Who cares?
CreateWire:
PROC [old: Wire]
RETURNS [wire: Wire] = {
geometry: CoreGeometry.Instances; ovg: BOOL;
[geometry, ovg] ← SpecialGetGeometry[old];
geometry ← CoreGeometry.TransformList[trans, geometry];
wire ← CoreOps.CreateWire[];
CoreGeometry.PutGeometry[mode.decoration, wire, geometry];
newInternals ← CONS [wire, newInternals];
};
AddInTable:
PROC [subInternal: Wire] = {
IF RefTab.Fetch[intToInt, subInternal].val#NIL THEN RETURN;
[] ← RefTab.Store[intToInt, subInternal, CreateWire[subInternal]];
};
CreateActual:
PROC [oldAct: Wire]
RETURNS [newAct: Wire] = {
newAct ← NARROW [RefTab.Fetch[intToInt, oldAct].val];
IF newAct#NIL THEN RETURN;
IF oldAct.size=0
THEN [] ← RefTab.Store[intToInt, oldAct, newAct ← CreateWire[oldAct]]
ELSE {
newAct ← CoreOps.CreateWires[size: oldAct.size];
FOR i: NAT IN [0 .. oldAct.size) DO newAct[i] ← CreateActual[oldAct[i]] ENDLOOP;
};
};
DecorateBinding: RefTab.EachPairAction = {
pub: Wire = NARROW [key];
act: Wire = NARROW [val];
CoreGeometry.AddGeometry[
mode.decoration, act,
CoreGeometry.TransformList[trans, SpecialGetGeometry[pub].geometry]
]; -- Hack to save some space for now!
};
name: ROPE = CoreOps.GetCellTypeName[rct[i].type];
trans: CoreGeometry.Transformation = CoreGeometry.GetTrans[mode.decoration, rct[i]];
subrct: CoreClasses.RecordCellType = NARROW [rct[i].type.data];
intToInt: RefTab.Ref ← CoreOps.CreateBindingTable[rct[i].type.public, rct[i].actual];
[] ← RefTab.Pairs[intToInt, DecorateBinding];
IF NOT Rope.Equal[PW.Name[CoreGeometry.GetObject[mode.decoration, rct[i].type]], name] THEN ERROR;
TerminalIO.PutF[" %g[%g]", IO.rope[name], IO.int[subrct.size]];
CoreOps.VisitRootAtomics[subrct.internal, AddInTable];
FOR j:
NAT
IN [0 .. subrct.size)
DO
instance: CoreClasses.CellInstance ← CoreClasses.CreateInstance[actual: CreateActual[subrct[j].actual], type: subrct[j].type, props: subrct[j].properties];
CoreGeometry.PutTrans[mode.decoration, instance, CDBasics.ComposeTransform[itemInCell: CoreGeometry.GetTrans[mode.decoration, subrct[j]], cellInWorld: trans]];
instances ← CONS [instance, instances]
ENDLOOP;
-- We flush the Sinix cache for name. When we flush, we do not need to explicit the pins because there is no circularity
IF CoreProperties.GetCellTypeProp[rct[i].type, $RawFlatten]=$Smash
THEN Sinix.FlushCache[CoreGeometry.GetObject[mode.decoration, rct[i].type]];
};
ENDLOOP;
IF instances=NIL AND newInternals=NIL AND record.public.size=1 AND rct.internal.size=1 THEN {result ← record.public[0]; RETURN}; -- optimization good for Big contacts!
new ← CoreClasses.CreateRecordCell[
record.public,
CoreOps.UnionWire[rct.internal, CoreOps.CreateWire[newInternals]],
instances, NIL, record.properties, TRUE
];
CoreGeometry.PutObject[mode.decoration, new, CoreGeometry.GetObject[mode.decoration, record]];
Commented for testing
If obj had already the $RawFlatten property, fine. If it did not have it and we have zero instance, let's make sure we'll flatten this cell. We do not flatten cell with only one instance, since wire decorations might kill us!
IF CDProperties.GetObjectProp[obj, $RawFlatten]#$RawFlatten AND instances=NIL THEN CoreProperties.PutCellTypeProp[new, $RawFlatten, $Keep];
TerminalIO.PutF[".\n"];
result ← new;
};