Layout primitives
layoutAtomProp: PUBLIC ATOM ← CoreProperties.RegisterProperty[$Layout, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy]]];
SetLayout:
PUBLIC
PROC [cellType: CellType, layoutAtom:
ATOM, userDataProp:
ATOM ←
NIL, userData:
REF ←
NIL] = {
CoreProperties.PutCellTypeProp[cellType, layoutAtomProp, layoutAtom];
IF userDataProp#NIL THEN CoreProperties.PutCellTypeProp[cellType, userDataProp, userData];
};
layoutProp: PRIVATE ATOM ← CoreProperties.RegisterProperty[$PWCoreLayout]; -- cache on CellTypes
HasLayout:
PUBLIC
PROC [cellType: CellType]
RETURNS [
BOOL] = {
RETURN [CoreProperties.GetCellTypeProp[cellType, layoutProp]#NIL];
};
CancelLayout:
PUBLIC
PROC [cellType: CellType] = {
CoreProperties.PutCellTypeProp[cellType, layoutProp, NIL];
};
Layout:
PUBLIC
PROC [cellType: CellType]
RETURNS [obj: Object] = {
obj ← NARROW [CoreProperties.GetCellTypeProp[cellType, layoutProp]];
IF obj#NIL THEN RETURN;
BEGIN
CheckPinsNonNil:
PROC [public: Wire] = {
IF Sinix.GetPinsProp[extractMode, public]=NIL THEN Signal[];
};
layoutAtom: ATOM ← NARROW [CoreProperties.GetCellTypeProp[cellType, layoutAtomProp]];
layoutAtomData: LayoutAtomData;
IF layoutAtom=NIL THEN layoutAtom ← NARROW [CoreProperties.GetCellClassProp[cellType.class, layoutAtomProp]];
IF layoutAtom=
NIL
THEN {
PW.WriteF["*** Impossible to find a layoutAtom for this cellType\n"];
Signal[];
};
layoutAtomData ← NARROW [HashTable.Fetch[layoutAtomsTable, layoutAtom].value];
IF layoutAtomData=
NIL
THEN {
PW.WriteF["*** LayoutAtom %g has not been registered\n", IO.atom[layoutAtom]];
Signal[];
};
obj ← layoutAtomData.layoutProc[cellType];
Now we decorate the source cellType
layoutAtomData.decorateProc[cellType, obj];
We make a simple check to see if the public was correctly decorated
CoreOps.VisitAtomicWires[cellType.public, CheckPinsNonNil];
We make an indirect object to allow the same layout to be returned on 2 different calls of Layout
obj ← PWObjects.CreateIndirect[obj];
CDProperties.PutObjectProp[obj, extractMode.cacheProp, cellType];
CoreProperties.PutCellTypeProp[cellType, layoutProp, obj];
IF CoreOps.GetCellTypeName[cellType]#NIL AND CDDirectory.Name[obj]=NIL THEN NARROW [obj.class.directoryProcs, REF CDDirectory.DirectoryProcs].setName[obj, CoreOps.GetCellTypeName[cellType]];
Consistency check
IF Sinix.Extract[obj, extractMode].result#cellType THEN Signal[]; -- internal Bug of PWCore
END;
};
GetAndAddSuffix:
PROC [source:
CD.Design, name:
ROPE]
RETURNS [obj:
CD.Object] = {
obj ← PW.Get[source, IO.PutR[IO.rope[name], IO.rope[maskSuffix]]];
};
Checks that each sourcePublic corresponds to some extractedPublic, and decorates the sourcePublic.
DecorateCorrespondingPublic:
PROC [sourcePublic, extractedPublic: Wire]
RETURNS [extractedToSource: HashTable.Table] = {
FindInExtractedPublic: CoreOps.EachWireProc = {
xwire: Wire ← wire; -- to avoid name clash
names: LIST OF ROPE ← CoreOps.GetFullWireNames[sourcePublic, wire];
name: ROPE;
FindInExtractedPublicInternal: CoreOps.EachWireProc = {
source: Wire;
IF ~CoreOps.IsFullWireName[extractedPublic, wire, name] THEN RETURN;
source ← NARROW [HashTable.Fetch[extractedToSource, wire].value];
IF source=xwire THEN RETURN;
IF source#NIL THEN Signal[]; -- extracted wire corresponds to 2 source publics
[] ← HashTable.Store[extractedToSource, wire, xwire];
IF wire.size=0 THEN SourcePinsFromExtracted[xwire, wire, TRUE];
};
IF names=
NIL
OR names.rest#
NIL
THEN IF xwire.size#0 THEN RETURN ELSE Signal[]; -- more than one full name
name ← names.first;
[] ← CoreOps.VisitWire[extractedPublic, FindInExtractedPublicInternal];
IF xwire.size=0 AND Sinix.GetPinsProp[extractMode, xwire]=NIL THEN Signal[]; -- source public not found
};
extractedToSource ← HashTable.Create[extractedPublic.size];
[] ← CoreOps.VisitWire[sourcePublic, FindInExtractedPublic];
};
FromLayout:
PUBLIC
PROC [public: Wire, obj:
CD.Object]
RETURNS [cellType: CellType] = {
CreateActual:
PROC [extractedPublic: Wire]
RETURNS [actual: Wire] = {
sourceWire: Wire ← NARROW [HashTable.Fetch[extractedToSource, extractedPublic].value];
IF sourceWire#NIL THEN RETURN [sourceWire];
sourceWire ← CoreOps.CreateWires[size: extractedPublic.size];
[] ← HashTable.Store[extractedToSource, extractedPublic, sourceWire];
FOR i:
NAT
IN [0 .. extractedPublic.size)
DO
sourceWire[i] ← CreateActual[extractedPublic[i]];
ENDLOOP;
RETURN [sourceWire];
};
actual: Wire;
extractedToSource: HashTable.Table;
extractedCellType: CellType ← NARROW [Sinix.Extract[obj, extractMode].result];
extractedToSource ← DecorateCorrespondingPublic[public, extractedCellType.public];
actual ← CreateActual[extractedCellType.public];
cellType ← CoreClasses.CreateRecordCell[public, CoreOps.CreateWire[LIST[public, actual]], LIST [CoreClasses.CreateInstance[actual: CreateActual[extractedCellType.public], type: extractedCellType]]];
CDProperties.PutObjectProp[obj, extractMode.cacheProp, cellType];
CoreProperties.PutCellTypeProp[cellType, layoutProp, obj];
};
FromLayoutWithoutPublic:
PUBLIC
PROC [obj:
CD.Object]
RETURNS [cellType: CellType] = {
cellType ← NARROW [Sinix.Extract[obj, extractMode].result];
CoreProperties.PutCellTypeProp[cellType, layoutProp, obj];
};
Predefined layoutAtoms and their associated procs
Get:
PUBLIC LayoutProc = {
source: CD.Design ← NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreSourceDesign]];
obj ← GetAndAddSuffix[source, CoreOps.GetCellTypeName[cellType]];
};
GetAndFlatten:
PUBLIC LayoutProc = {
source: CD.Design ← NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreSourceDesign]];
obj ← PW.Flatten[GetAndAddSuffix[source, CoreOps.GetCellTypeName[cellType]]];
};
AbutX:
PUBLIC LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF CD.Object ← NIL;
FOR i:
NAT
DECREASING
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListX[subObjects];
};
AbutY:
PUBLIC LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF CD.Object ← NIL;
FOR i:
NAT
DECREASING
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListY[subObjects];
};
ReverseAbutX:
PUBLIC LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF CD.Object ← NIL;
FOR i:
NAT
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListX[subObjects];
};
ReverseAbutY:
PUBLIC LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF CD.Object ← NIL;
FOR i:
NAT
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListY[subObjects];
};
ArrayX:
PUBLIC LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $AbutX]; obj ← Layout[recasted];
};
ArrayY:
PUBLIC LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $AbutY]; obj ← Layout[recasted];
};
ReverseArrayX:
PUBLIC LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $ReverseAbutX]; obj ← Layout[recasted];
};
ReverseArrayY:
PUBLIC LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $ReverseAbutY]; obj ← Layout[recasted];
};
FlipX:
PUBLIC LayoutProc = {
IF cellType.class#CoreClasses.identityCellClass THEN Signal[];
obj ← PW.FlipX[Layout[NARROW [cellType.data]]];
};
FlipY:
PUBLIC LayoutProc = {
IF cellType.class#CoreClasses.identityCellClass THEN Signal[];
obj ← PW.FlipY[Layout[NARROW [cellType.data]]];
};
Rot90:
PUBLIC LayoutProc = {
IF cellType.class#CoreClasses.identityCellClass THEN Signal[];
obj ← PW.Rot90[Layout[NARROW [cellType.data]]];
};
Rot180:
PUBLIC LayoutProc = {
IF cellType.class#CoreClasses.identityCellClass THEN Signal[];
obj ← PW.Rot180[Layout[NARROW [cellType.data]]];
};
Rot270:
PUBLIC LayoutProc = {
IF cellType.class#CoreClasses.identityCellClass THEN Signal[];
obj ← PW.Rot270[Layout[NARROW [cellType.data]]];
};
Recast: LayoutProc = {
obj ← Layout[CoreOps.Recast[cellType]];
};
StructureWarnings:
TYPE =
RECORD [
kind: CoreStructuralComparison.WarningKind,
fromA, fromB: LIST OF REF];
FuseTransistors:
PROC [recordCell: CellType]
RETURNS [new: CellType] = {
oldData, newData, data: CoreClasses.RecordCellType;
nb, fused: NAT ← 0;
IF recordCell.class#CoreClasses.recordCellClass THEN RETURN [recordCell];
oldData ← NARROW [recordCell.data];
data ← NEW [CoreClasses.RecordCellTypeRec[oldData.size]];
data.internal ← oldData.internal;
FOR i: NAT IN [0 .. data.size) DO data[i] ← oldData[i] ENDLOOP;
FOR i:
NAT
IN [0 .. data.size)
DO
IF data[i]=NIL THEN LOOP;
data[i].type ← FuseTransistors[data[i].type];
IF data[i].type.class#CoreClasses.transistorCellClass THEN LOOP;
FOR j:
NAT
IN [0 .. i)
DO
IF data[j]=NIL THEN LOOP;
IF data[j].type.class#CoreClasses.transistorCellClass THEN LOOP;
IF data[i].actual[0]=data[j].actual[0]
AND ((data[i].actual[1]=data[j].actual[1]
AND data[i].actual[2]=data[j].actual[2])
OR (data[i].actual[2]=data[j].actual[1]
AND data[i].actual[1]=data[j].actual[2]))
THEN {
t1: CoreClasses.Transistor ← NARROW [data[i].type.data];
t2: CoreClasses.Transistor ← NARROW [data[j].type.data];
IF t1.type=t2.type
AND t1.length=t2.length
THEN {
data[i] ← CoreClasses.CreateInstance[
actual: data[i].actual,
type: CoreClasses.CreateTransistor[
args: [type: t1.type, length: t1.length, width: t1.width + t2.width],
props: data[i].type.properties
],
props: data[i].properties
];
data[j] ← NIL;
fused ← fused + 1;
};
};
ENDLOOP;
ENDLOOP;
IF fused=0 THEN RETURN [recordCell];
PW.WriteF["*** Lichen for PWCore.Get: fused %g transistors.\n", IO.int[fused]];
new ← CoreOps.CreateCellType[CoreClasses.recordCellClass, recordCell.public, NEW [CoreClasses.RecordCellTypeRec[data.size-fused]], NIL, recordCell.properties];
newData ← NARROW [new.data];
newData.internal ← data.internal;
FOR i:
NAT
IN [0 .. data.size)
DO
IF data[i]=NIL THEN LOOP;
newData[nb] ← data[i]; nb ← nb + 1;
ENDLOOP;
DecorateGet:
PUBLIC DecorateProc = {
extractedCT: CellType ← NARROW [Sinix.Extract[obj, extractMode].result];
InsertHint:
PROC [key, value:
REF
ANY]
RETURNS [quit:
BOOL ←
FALSE] = {
sourceWire: CoreFlat.FlatWire ← NEW [CoreFlat.FlatWireRec ← [path: CoreFlat.NullPath, wire: NARROW [value]]];
extractedWire: CoreFlat.FlatWire ← NEW [CoreFlat.FlatWireRec ← [path: CoreFlat.NullPath, wire: NARROW [key]]];
IF NOT HashTable.Insert[table: wireHints, key: sourceWire, value: extractedWire] THEN ERROR;
};
extractedToSource: HashTable.Table ← DecorateCorrespondingPublic[cellType.public, extractedCT.public];
wireHints: HashTable.Table ← HashTable.Create[];
warnings: LIST OF StructureWarnings ← NIL;
IF testLichen
THEN {
[] ← HashTable.Pairs[table: extractedToSource, action: InsertHint];
extractedCT ← FuseTransistors[extractedCT];
IF ~CoreStructuralComparison.FlattenAndCompare[ctA: cellType, ctB: extractedCT, wireHints: wireHints, instanceHints: HashTable.Create[] ! CoreStructuralComparison.Warning => {warnings ← CONS[[kind, fromA, fromB], warnings]; RESUME}] THEN {PrintWarnings[cellType, extractedCT, warnings, TerminalIO.TOS[]]; Signal[]};
};
};
PrintWarnings:
PROC [cellType: Core.CellType, extractedCT: Core.CellType, warnings:
LIST
OF StructureWarnings, out: Core.
STREAM ←
NIL] = {
PrintDescendants:
PROC [descendants:
LIST
OF
REF, root: Core.CellType] = {
FOR descendants ← descendants, descendants.rest
UNTIL descendants=
NIL
DO
WITH descendants.first
SELECT
FROM
in: CoreFlat.FlatInstance => {
IO.PutRope[out, CoreFlat.InstancePathRope[root, in^]];
IO.PutRope[out, "/"];
IO.PutRope[out, "?"];
};
wire: CoreFlat.FlatWire => {
IO.PutRope[out, CoreFlat.WirePathRope[root, wire^]];
};
ENDCASE => ERROR;
IO.PutRope[out, " "];
ENDLOOP;
};
IF out=NIL THEN out ← NARROW[ProcessProps.GetProp[$CommanderHandle], Commander.Handle].out;
FOR warns:
LIST
OF StructureWarnings ← warnings, warns.rest
UNTIL warns=
NIL
DO
warning: StructureWarnings ← warns.first;
IO.PutRope[out, IF warning.kind=stuck THEN "stuck " ELSE "difference "];
IO.PutRope[out, "\n fromA: "];
PrintDescendants[warning.fromA, cellType];
IO.PutRope[out, "\n fromB: "];
PrintDescendants[warning.fromB, extractedCT];
IO.PutRope[out, "\n"];
ENDLOOP;
};
EqualCellType:
PROC [cellType1, cellType2: CellType]
RETURNS [equal:
BOOL] = {
equal ←
SELECT
TRUE
FROM
cellType1=cellType2
=> TRUE,
cellType1.class=CoreClasses.identityCellClass
=> EqualCellType[NARROW [cellType1.data], cellType2],
cellType2.class=CoreClasses.identityCellClass
=> EqualCellType[cellType1, NARROW [cellType2.data]],
};
UncheckedDecorateAbut:
PROC [cellType: CellType, obj:
CD.Object, inOrder: OrderProc] = {
lazyPinsData: Sinix.LazyPinsData ← NEW [Sinix.LazyPinsDataRec ← [ir: CD.InterestRect[obj], getLazyPins: Sinix.RecordGetLazyPins, data: cellType]];
InsertInOrder:
PROC [element:
CD.Instance, sorted:
LIST
OF
CD.Instance]
RETURNS [new:
LIST
OF
CD.Instance] = {
IF sorted=NIL THEN RETURN [LIST [element]];
IF inOrder[CDBasics.BaseOfRect[CDInstances.InstRectO[element]], CDBasics.BaseOfRect[CDInstances.InstRectO[sorted.first]]] THEN RETURN [CONS [element, sorted]];
RETURN [CONS [sorted.first, InsertInOrder[element, sorted.rest]]];
};
SetLazyPins: PROC [wire: Wire] = {Sinix.PutLazyPinsProp[extractMode, wire, lazyPinsData]};
instances: LIST OF CD.Instance;
recordData: CoreClasses.RecordCellType ← NARROW [cellType.data];
WHILE obj.class#CDCells.cellClass DO obj ← CDDirectory.Expand[obj].new ENDLOOP;
FOR list:
LIST
OF
CD.Instance ←
NARROW [obj.specificRef,
CD.CellPtr].contents, list.rest
WHILE list#
NIL
DO
instances ← InsertInOrder[list.first, instances];
ENDLOOP;
FOR i:
NAT
IN [0 .. recordData.size)
DO
CoreProperties.PutCellInstanceProp[recordData[i], extractMode.instanceProp, instances.first];
instances ← instances.rest;
ENDLOOP;
IF instances#NIL THEN Signal[];
CoreOps.VisitAtomicWires[cellType.public, SetLazyPins];
};
InternalDecorateAbutX:
PUBLIC DecorateProc = {
IF checkAbuts
THEN DecorateAbutX[cellType, obj]
ELSE UncheckedDecorateAbut[cellType, obj, SortInX];
};
InternalDecorateAbutY:
PUBLIC DecorateProc = {
IF checkAbuts
THEN DecorateAbutY[cellType, obj]
ELSE UncheckedDecorateAbut[cellType, obj, SortInY];
};
InternalDecorateReverseAbutX:
PUBLIC DecorateProc = {
IF checkAbuts
THEN DecorateReverseAbutX[cellType, obj]
ELSE UncheckedDecorateAbut[cellType, obj, ReverseSortInX];
};
InternalDecorateReverseAbutY:
PUBLIC DecorateProc = {
IF checkAbuts
THEN DecorateReverseAbutY[cellType, obj]
ELSE UncheckedDecorateAbut[cellType, obj, ReverseSortInY];
};
DecorateAbutX:
PUBLIC DecorateProc = {
DecorateFlatten[cellType, obj, SortInX];
};
DecorateAbutY:
PUBLIC DecorateProc = {
DecorateFlatten[cellType, obj, SortInY];
};
DecorateReverseAbutX:
PUBLIC DecorateProc = {
DecorateFlatten[cellType, obj, ReverseSortInX];
};
DecorateReverseAbutY:
PUBLIC DecorateProc = {
DecorateFlatten[cellType, obj, ReverseSortInY];
};
SortInX: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.x<pos2.x]};
SortInY: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.y<pos2.y]};
ReverseSortInX: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.x>pos2.x]};
ReverseSortInY: PUBLIC PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = {RETURN [pos1.y>pos2.y]};
PositionnedInstance: TYPE = REF PositionnedInstanceRec;
PositionnedInstanceRec:
TYPE =
RECORD [
instance: CoreClasses.CellInstance,
bindings: HashTable.Table,
transf: CD.Instance
];
PositionnedWire: TYPE = REF PositionnedWireRec;
PositionnedWireRec:
TYPE =
RECORD [
wire: Wire,
bindings: HashTable.Table,
transf: CD.Instance
];
positionnedInstances is the sorted list of all instances that have associated layout.
positionnedWires is the list of all wires having their own geometry.
GetPositionnedInstances:
PROC [obj:
CD.Object, inOrder: OrderProc]
RETURNS [positionnedInstances:
LIST
OF PositionnedInstance ←
NIL, positionnedWires:
LIST
OF PositionnedWire ←
NIL] = {
transfs: LIST OF CD.Instance ← LIST [CDInstances.NewInst[obj]];
extractedCT: CellType ← NARROW [Sinix.Extract[obj, extractMode].result];
InsertInOrdered:
PROC [element: PositionnedInstance, sorted:
LIST
OF PositionnedInstance]
RETURNS [new:
LIST
OF PositionnedInstance] = {
IF sorted=NIL THEN RETURN [LIST [element]];
IF inOrder[CDBasics.BaseOfRect[CDInstances.InstRectO[element.transf]], CDBasics.BaseOfRect[CDInstances.InstRectO[sorted.first.transf]]] THEN RETURN [CONS [element, sorted]];
RETURN [CONS [sorted.first, InsertInOrdered[element, sorted.rest]]];
};
EachInstance: CoreFlat.EachInstanceProc = {
transf: CD.Instance ← Sinix.Transform[transfs.first, InstanceTransf[instance]];
flatten ← NOT HasLayout[instance.type];
IF flatten THEN {transfs ← CONS [transf, transfs]; RETURN};
positionnedInstances ← InsertInOrdered [
NEW [PositionnedInstanceRec ← [instance: instance, bindings: bindings, transf: transf]],
positionnedInstances];
};
RecordGeometry: CoreFlat.EachCellTypeProc = {
recordCellData: CoreClasses.RecordCellType ← NARROW [cellType.data];
RecordWireGeometry:
PROC [wire: Wire] = {
IF Sinix.GetWireGeometryProp[extractMode, wire]=NIL THEN RETURN;
positionnedWires ←
CONS [
NEW [PositionnedWireRec ← [wire: wire, bindings: bindings, transf: transfs.first]],
positionnedWires];
};
CoreOps.VisitAtomicWires[recordCellData.internal, RecordWireGeometry];
};
PopTransf: CoreFlat.EachCellTypeProc = {transfs ← transfs.rest};
CoreFlat.EnumerateLeaves[extractedCT, EachInstance, RecordGeometry, RecordGeometry, PopTransf];
};
DecorateFlatten:
PUBLIC
PROC [cellType: CellType, obj:
CD.Object, inOrder:
PROC [
CD.Position,
CD.Position]
RETURNS [
BOOL]] = {
ir: CD.Rect ← CD.InterestRect[obj];
extractedCT: CellType ← NARROW [Sinix.Extract[obj, extractMode].result];
extractedToSource: HashTable.Table ← HashTable.Create[CoreOps.WireBits[extractedCT.public]];
extractedCTData: CoreClasses.RecordCellType ← NARROW [extractedCT.data];
cellTypeData: CoreClasses.RecordCellType ← NARROW [cellType.data];
DecorateActual:
PROC [bindings: HashTable.Table, sourceActual, deepActual: Wire] = {
wireBind: CoreFlat.WireBind ← NARROW [HashTable.Fetch[bindings, deepActual].value];
extractedActual: Wire;
wire: Wire;
FOR i: NAT IN [0 .. sourceActual.size) DO DecorateActual[bindings, sourceActual[i], deepActual[i]] ENDLOOP;
IF deepActual.size#0 THEN RETURN;
IF wireBind=NIL THEN Signal[]; -- something is really wrong!
IF wireBind.path.length#0 THEN Signal[]; -- a deep internal wire
extractedActual ← wireBind.wire;
IF sourceActual.size#extractedActual.size THEN Signal[];
wire ← NARROW [HashTable.Fetch[extractedToSource, extractedActual].value];
IF wire=sourceActual THEN RETURN;
IF wire#
NIL
THEN {
PW.WriteF[
"*** Mismatch between extracted layout and source description: atomic extracted wire '%g' corresponds to 2 different atomic source wires '%g' and '%g'\n",
IO.rope[CoreOps.GetFullWireNames[extractedCTData.internal, extractedActual].first],
IO.rope[CoreOps.GetFullWireNames[cellType.public, wire].first],
IO.rope[CoreOps.GetFullWireNames[cellType.public, sourceActual].first]
];
Signal[];
};
SourcePinsFromExtracted[sourceActual, extractedActual, FALSE];
[] ← HashTable.Insert[extractedToSource, extractedActual, sourceActual];
};
positionnedInstances: LIST OF PositionnedInstance;
positionnedWires: LIST OF PositionnedWire;
length: INT ← 0;
[positionnedInstances, positionnedWires] ← GetPositionnedInstances[obj, inOrder];
FOR list: LIST OF PositionnedInstance ← positionnedInstances, list.rest WHILE list#NIL DO length ← length+1 ENDLOOP;
IF cellTypeData.size#length
THEN {
PW.WriteF["*** Mismatch between extracted layout (%g instances) and source description (%g instances)\n", IO.int[length], IO.int[cellTypeData.size]];
Signal[];
};
FOR i:
NAT
IN [0 .. cellTypeData.size)
DO
positionnedInstance: PositionnedInstance ← positionnedInstances.first;
positionnedInstances ← positionnedInstances.rest;
IF
NOT EqualCellType[cellTypeData[i].type, positionnedInstance.instance.type]
THEN {
PW.WriteF["*** Mismatch between the %gth instance of the extracted layout and the %gth instance of the source description: cellTypes are different\n", IO.int[i], IO.int[i]];
Signal[];
};
CoreProperties.PutCellInstanceProp[cellTypeData[i], extractMode.instanceProp, positionnedInstance.transf];
IF ~ CoreOps.Conform[cellTypeData[i].actual, positionnedInstance.instance.actual] THEN Signal[];
FOR j:
NAT
IN [0 .. positionnedInstance.instance.actual.size)
DO
DecorateActual[positionnedInstance.bindings, cellTypeData[i].actual[j], positionnedInstance.instance.actual[j]];
ENDLOOP;
ENDLOOP;
We copy the pinsProp and wireGeometryProp for all positionnedWires. For now, we only do it for wires which have the same name as some internal of cellType.
WHILE positionnedWires#
NIL
DO
positionnedWire: PositionnedWire ← positionnedWires.first;
wireBind: CoreFlat.WireBind;
name: ROPE ← CoreOps.GetShortWireName[positionnedWire.wire];
source: Wire;
geometry: LIST OF CD.Instance ← Sinix.GetWireGeometryProp[extractMode, positionnedWire.wire];
wireBind ← NARROW [HashTable.Fetch[positionnedWire.bindings, positionnedWire.wire].value];
IF wireBind=NIL THEN Signal[]; -- internal bug!
IF wireBind.path#CoreFlat.NullPath THEN Signal[]; -- not yet implemented if it is not part of the internal of extractedCT
source ← NARROW [HashTable.Fetch[extractedToSource, wireBind.wire].value];
All this code stinks ....
IF source=NIL THEN source ← CoreOps.FindWire[cellTypeData.internal, name];
IF source=NIL THEN Signal[];
geometry ← Sinix.TransformList[positionnedWire.transf, geometry];
Sinix.AppendWireGeometryProp[extractMode, source, geometry];
FOR pins:
LIST
OF
CD.Instance ← geometry, pins.rest
WHILE pins#
NIL
DO
pin: CD.Instance ← pins.first;
IF ~CDBasics.Inside[CDInstances.InstRectO[pin], CDBasics.Extend[ir, -1]]
THEN Sinix.AddPinsProp[extractMode, source, pin];
ENDLOOP;
positionnedWires ← positionnedWires.rest;
ENDLOOP;
};
DecorateRotated:
PUBLIC DecorateProc = {
extractedCT: CellType ← NARROW [Sinix.Extract[obj, extractMode].result];
extractedToSource: HashTable.Table ← HashTable.Create[CoreOps.WireBits[extractedCT.public]];
DecorateActual:
PROC [sourceActual, extractedActual: Wire] = {
wire: Wire ← NARROW [HashTable.Fetch[extractedToSource, extractedActual].value];
IF sourceActual.size#extractedActual.size THEN Signal[];
FOR i: NAT IN [0 .. sourceActual.size) DO DecorateActual[sourceActual[i], extractedActual[i]] ENDLOOP;
IF sourceActual.size#0 THEN RETURN;
IF wire=sourceActual THEN RETURN;
IF wire#
NIL
THEN {
PW.WriteF[
"*** Mismatch between extracted layout and source description: atomic extracted wire '%g' corresponds to 2 different atomic source wires '%g' and '%g'\n",
IO.rope[CoreOps.GetFullWireNames[extractedCTData.internal, extractedActual].first],
IO.rope[CoreOps.GetFullWireNames[cellType.public, wire].first],
IO.rope[CoreOps.GetFullWireNames[cellType.public, sourceActual].first]
];
Signal[];
};
SourcePinsFromExtracted[sourceActual, extractedActual, FALSE];
[] ← HashTable.Insert[extractedToSource, extractedActual, sourceActual];
};
extractedCTData: CoreClasses.RecordCellType ← NARROW [extractedCT.data];
IF cellType.class#CoreClasses.identityCellClass
OR extractedCTData.size#1
THEN {
PW.WriteF["*** Mismatch between extracted layout (%g instances) and source description (%g)\n", IO.int[extractedCTData.size], IO.rope[cellType.class.name]];
Signal[];
};
DecorateActual[cellType.public, extractedCTData[0].actual];
};
DecorateRecasted:
PUBLIC DecorateProc = {
extractedCT: CellType ← NARROW [Sinix.Extract[obj, extractMode].result];
CopyPinsFromExtractedToSourceProp: CoreOps.EachWirePairProc = {
IF publicWire.size#0 THEN RETURN;
SourcePinsFromExtracted[publicWire, actualWire, TRUE];
};
We check that the public of the source and the public of the extracted layout are similar, and we copy properties from one to the other
IF CoreOps.VisitBinding[extractedCT.public, cellType.public, CopyPinsFromExtractedToSourceProp] THEN Signal[];
};
InstanceTransf:
PROC [cellInst: CoreClasses.CellInstance]
RETURNS [transf:
CD.Instance] = {
transf ← NARROW [CoreProperties.GetCellInstanceProp[cellInst, extractMode.instanceProp]];
};
InstanceLocation:
PROC [cellInst: CoreClasses.CellInstance]
RETURNS [location:
CD.Position] = {
location ← CDBasics.BaseOfRect[CDInstances.InstRectO[InstanceTransf[cellInst]]];
};
SortInstances:
PUBLIC
PROC [cellType: CellType, inOrder:
PROC [
CD.Position,
CD.Position]
RETURNS [
BOOL]] = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
FOR i:
NAT
IN [0 .. data.size-1)
DO
FOR j:
NAT
IN (i .. data.size)
DO
IF ~inOrder[InstanceLocation[data[i]], InstanceLocation[data[j]]]
THEN {
w: CoreClasses.CellInstance ← data[i];
data[i] ← data[j]; data[j] ← w;
};
ENDLOOP;
ENDLOOP;
};
Registering layoutAtoms
[] ← RegisterLayoutAtom[$Get, Get, DecorateGet];
[] ← RegisterLayoutAtom[$GetAndFlatten, GetAndFlatten, DecorateGet];
[] ← RegisterLayoutAtom[$AbutX, AbutX, InternalDecorateAbutX];
[] ← RegisterLayoutAtom[$AbutY, AbutY, InternalDecorateAbutY];
[] ← RegisterLayoutAtom[$ReverseAbutX, ReverseAbutX, InternalDecorateReverseAbutX];
[] ← RegisterLayoutAtom[$ReverseAbutY, ReverseAbutY, InternalDecorateReverseAbutY];
[] ← RegisterLayoutAtom[$ArrayX, ArrayX, DecorateRecasted];
[] ← RegisterLayoutAtom[$ArrayY, ArrayY, DecorateRecasted];
[] ← RegisterLayoutAtom[$ReverseArrayX, ReverseArrayX, DecorateRecasted];
[] ← RegisterLayoutAtom[$ReverseArrayY, ReverseArrayY, DecorateRecasted];
[] ← RegisterLayoutAtom[$FlipX, FlipX, DecorateRotated];
[] ← RegisterLayoutAtom[$FlipY, FlipY, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot90, Rot90, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot180, Rot180, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot270, Rot270, DecorateRotated];
[] ← RegisterLayoutAtom[$Recast, Recast, DecorateRecasted];
CoreProperties.PutCellClassProp[CoreClasses.identityCellClass, layoutAtomProp, $Recast];