ExtractObj:
PUBLIC ExtractObjProc = {
refProc: REF ExtractObjProc;
name: ROPE ← CDDirectory.Name[obj];
IF name#NIL THEN cellType ← CoreOps.FetchCellType[coreDesign, name];
IF cellType#NIL THEN RETURN;
refProc ← NARROW [CDProperties.GetPropFromObject[obj, extractObjProcProp]];
IF refProc=NIL THEN refProc ← NARROW [CDObjectProcs.FetchFurther[obj.class, extractObjProcProp]];
[cellType, nbErrors] ← (IF refProc=NIL THEN DefaultExtractObj ELSE refProc^)[coreDesign, cdDesign, obj];
IF cellType=NIL THEN RETURN;
cellType.name ← name;
cellType.properties ← CoreProperties.PutProp[cellType.properties, sinixObjectProp, obj];
IF name#NIL AND CDDirectory.Fetch[cdDesign, name].found THEN CoreOps.InsertCellType[coreDesign, cellType];
};
DefaultExtractObj:
PUBLIC ExtractObjProc = {
obj ← CDDirectory.ExpandHard[obj, NIL, NIL];
IF obj=NIL THEN ERROR;
RETURN ExtractObj[coreDesign, cdDesign, obj];
};
AtomicExtractObj:
PUBLIC ExtractObjProc = {
subWire: Core.Wire ← NEW [Core.WireRec];
wire: Core.Wire ← NEW [Core.WireRec ← [structure: record, elements: NEW [Core.WireSequenceRec[1]]]];
AddWireGeometryPropOnWire[subWire, NEW [CD.InstanceRep ← [ob: obj]]];
wire.elements[0] ← subWire;
cellType ← NEW[Core.CellTypeRec ← [class: CoreRecord.recordCellClass, publicWire: wire, data: NEW[CoreRecord.RecordCellTypeRec ← [internalWire: wire]]]];
};
CellExtractObj: ExtractObjProc = {
cellPtr: CD.CellPtr ← NARROW [obj.specificRef];
currentWires: RefTab.Ref ← RefTab.Create[];
realPublicWire: RefTab.Ref ← RefTab.Create[];
realInternalWires: RefTab.Ref ← RefTab.Create[];
currentInstances: LIST OF CoreRecord.CellInstance ← NIL;
cellTypeData: CoreRecord.RecordCellType;
FOR instances:
LIST
OF
CD.Instance ← cellPtr.contents, instances.rest
WHILE instances#
NIL
DO
cdInstance: CD.Instance ← instances.first;
subCellType: Core.CellType;
subErrors: INT;
subPublics: Core.WireSequence;
size: NAT;
actualWire: Core.Wire;
instance: CoreRecord.CellInstance;
[subCellType, subErrors] ← ExtractObj[coreDesign, cdDesign, cdInstance.ob];
nbErrors ← nbErrors + subErrors;
IF subCellType=NIL THEN LOOP; -- Symbolic object such as a pin
subPublics ← subCellType.publicWire.elements;
size ← subPublics.size;
actualWire ← NEW [Core.WireRec ← [name: "Bidon", structure: record, elements: NEW [Core.WireSequenceRec[size]]]];
instance ← NEW [CoreRecord.CellInstanceRec ← [actualWire: actualWire, type: subCellType]];
instance.properties ← CoreProperties.PutProp[instance.properties, sinixInstanceProp, cdInstance];
currentInstances ← CONS [instance, currentInstances];
we fill the actual
FOR i:
NAT
IN [0 .. size)
DO
subPublic: Core.Wire ← subPublics[i];
newActual: Core.Wire ← NEW [Core.WireRec];
IF GetWireGeometryPropFromWire[subPublic]=
NIL
THEN {} -- that means a non-connected subPublic
ELSE AddWireGeometryPropOnWire[newActual, NEW [CD.InstanceRep ← [ob: SinixBridge.WireToObjectBridge[cdInstance.ob, subPublic], location: cdInstance.location, orientation: cdInstance.orientation]]];
Fusion[currentWires, newActual];
actualWire.elements[i] ← newActual;
ENDLOOP;
ENDLOOP;
compute now the realInternalWires
BEGIN
ComputeRealWire: RefTab.EachPairAction = {
[key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]
rootWire: Core.Wire ← Root[currentWires, NARROW[key]];
quit ← FALSE;
[] ← RefTab.Store[realInternalWires, rootWire, NIL];
};
[] ← RefTab.Pairs[currentWires, ComputeRealWire];
END;
compute now the realPublicWire by enumerating the pins
BEGIN
EachPin: PWPins.InstanceEnumerator = {
[inst: CD.Instance] RETURNS [quit: BOOL ← FALSE]
pinName: ROPE ← CDPinObjects.GetName[inst];
geometry: LIST OF CD.Instance ← LIST [inst];
lastRootWire: Core.Wire ← NIL;
EachWire: RefTab.EachPairAction = {
[key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]
wire: Core.Wire ← NARROW[key];
quit ← FALSE;
IF ~TouchInstances[GetWireGeometryPropFromWire[wire], geometry] THEN RETURN;
IF lastRootWire#NIL THEN ERROR; -- 2 different nets touched by the same pin
lastRootWire ← wire;
IF wire.name=
NIL
OR Rope.Equal[wire.name, pinName]
THEN wire.name ← pinName
ELSE {
[] ← CDErrors.IncludeMessage[cdDesign, obj, RectAt[inst], Rope.Cat["Different names on the same net (probably 2 pins of different nets connected together): ", wire.name, pinName]];
nbErrors ← nbErrors+1;
};
};
[] ← RefTab.Pairs[realInternalWires, EachWire];
IF lastRootWire=NIL THEN ERROR; -- pin touches no net
[] ← RefTab.Store[realPublicWire, lastRootWire, NIL];
};
[] ← PWPins.EnumerateEdgePins[obj, EachPin];
END;
we build the CellType
cellTypeData ← NEW [CoreRecord.RecordCellTypeRec ← [internalWire: TableToWire[realInternalWires]]];
cellType ←
NEW [Core.CellTypeRec ← [
class: CoreRecord.recordCellClass,
publicWire: TableToWire[realPublicWire],
data: cellTypeData]];
WHILE currentInstances#
NIL
DO
instance: CoreRecord.CellInstance ← currentInstances.first;
actualWire: Core.Wire ← instance.actualWire;
FOR i:
NAT
IN [0 .. actualWire.elements.size)
DO
wire: Core.Wire ← Root[currentWires, actualWire.elements[i]];
IF GetWireGeometryPropFromWire[wire]=NIL THEN ERROR; -- non connected actualWire (that is a problem for transistors)
IF ~RefTab.Fetch[realInternalWires, wire].found THEN ERROR; -- BUG!
actualWire.elements[i] ← wire;
ENDLOOP;
cellTypeData.instances ← CONS [instance, cellTypeData.instances];
currentInstances ← currentInstances.rest;
ENDLOOP;
};