PWCoreImpl.mesa
Copyright © 1985, 1987 by Xerox Corporation. All rights reserved.
Louis Monier May 17, 1986 1:35:25 pm PDT
Bertrand Serlet March 16, 1987 11:05:11 pm PST
Barth, April 22, 1986 7:30:28 pm PST
Spreitzer, April 11, 1986 10:52:25 am PST
Last Edited by: Louis Monier April 19, 1987 7:59:37 pm PDT
Last edited by: Christian Jacobi, January 9, 1987 12:16:44 pm PST
DIRECTORY
Atom,
CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDIO, CDOps, CDProperties,
Commander,
Core, CoreClasses, CoreCreate, CoreFlat, CoreIO, CoreOps, CoreProperties,
CoreGeometry, CoreGeometryBackdoor,
GList, HashTable, IO,
PW, PWCore, PWObjects,
Rope,
Sinix, SinixOps, Sisyph, TerminalIO;
PWCoreImpl:
CEDAR
PROGRAM
IMPORTS Atom, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDIO, CDOps, CDProperties, CoreClasses, CoreCreate, CoreIO, CoreOps, CoreProperties, CoreGeometry, CoreGeometryBackdoor, GList, HashTable, IO, PW, PWCore, PWObjects, Rope, Sinix, SinixOps, Sisyph, TerminalIO
EXPORTS PWCore
SHARES CDCells, CDDirectory =
BEGIN OPEN PWCore;
Soon in Core ?
VisitAtomicPairs:
PROC [wire1, wire2: Wire, eachPair:
PROC [Wire, Wire]] = {
VisitInternal:
PROC [wire1, wire2: Wire] = {
IF wire1.size#wire2.size THEN ERROR;
IF wire1.size=0
THEN eachPair[wire1, wire2]
ELSE FOR i: NAT IN [0 .. wire1.size) DO VisitInternal[wire1[i], wire2[i]] ENDLOOP;
};
IF wire1.size#wire2.size THEN ERROR;
FOR i: NAT IN [0 .. wire1.size) DO VisitInternal[wire1[i], wire2[i]] ENDLOOP;
};
Exceptions
Signal:
PUBLIC
SIGNAL [cellType: CellType] =
CODE;
Error:
PUBLIC
ERROR [type:
ATOM, message:
ROPE, cellType: CellType] =
CODE;
PinsCorrespondingToSeveralPublics:
PUBLIC
SIGNAL [cellType: CellType, obj: Object, publics: Wires, geometry: CoreGeometry.Instances] =
CODE;
NoPinsOnAtomicPublic: PUBLIC SIGNAL [cellType: CellType, obj: Object, public: Wire, message: ROPE ← NIL] = CODE;
LayoutAtomsTable
layoutAtomsTable: HashTable.Table ← HashTable.Create[];
LayoutAtomData: TYPE = REF LayoutAtomDataRec;
LayoutAtomDataRec: TYPE = RECORD [layoutProc: LayoutProc, decorateProc: DecorateProc, attributesProc: AttributesProc ← NIL];
RegisterLayoutAtom:
PUBLIC
PROC [layoutAtom:
ATOM, layoutProc: LayoutProc, decorateProc: DecorateProc ←
NIL, attributesProc: AttributesProc ←
NIL]
RETURNS [sameAtom:
ATOM] = {
sameAtom ← layoutAtom;
IF ~HashTable.Store[layoutAtomsTable, layoutAtom,
NEW [LayoutAtomDataRec ← [layoutProc: layoutProc, decorateProc: decorateProc, attributesProc: attributesProc]]]
THEN TerminalIO.PutF["LayoutProc and DecorateProc for %g overwritten\n", IO.atom[layoutAtom]];
};
GetLayoutAtomData:
PROC [layoutAtom:
ATOM]
RETURNS [layoutAtomData: LayoutAtomData] = {
layoutAtomData ← NARROW [HashTable.Fetch[layoutAtomsTable, layoutAtom].value];
IF layoutAtomData#NIL THEN RETURN;
CDEnvironment.ExecFileEntry[Atom.GetPName[layoutAtom], NIL, "PWCore"];
layoutAtomData ← NARROW [HashTable.Fetch[layoutAtomsTable, layoutAtom].value];
};
GetLayoutAtomRegistration:
PUBLIC
PROC [layoutAtom:
ATOM]
RETURNS [layoutProc: LayoutProc ←
NIL, decorateProc: DecorateProc ←
NIL, attributesProc: AttributesProc ←
NIL] = {
layoutAtomData: LayoutAtomData ← GetLayoutAtomData[layoutAtom];
IF layoutAtomData=NIL THEN RETURN;
layoutProc ← layoutAtomData.layoutProc;
decorateProc ← layoutAtomData.decorateProc;
attributesProc ← layoutAtomData.attributesProc;
};
Primitives
layoutAtomProp:
PUBLIC
ATOM ← CoreProperties.RegisterProperty[$Layout];
GetLayoutAtom:
PUBLIC
PROC [cellType: CellType]
RETURNS [layoutAtom:
ATOM ←
NIL] = {
layoutAtom ← NARROW [CoreProperties.GetCellTypeProp[cellType, layoutAtomProp]];
IF layoutAtom#NIL THEN RETURN;
layoutAtom ← NARROW [CoreProperties.GetCellClassProp[cellType.class, layoutAtomProp]];
};
FakeExtract: Sinix.ExtractProc = {result ← CDProperties.GetObjectProp[obj, $PWCoreCellType]};
SmashPins:
PROC [wire: Wire] = {CoreGeometry.PutPins[extractMode.decoration, wire,
NIL]};
copies decorations from from to to
CopyDecorations:
PROC [to, from: CellType, obj: Object] = {
CopyPins:
PROC [toWire, fromWire: Wire] = {
IF
NOT CoreGeometry.HasPins[extractMode.decoration, fromWire]
THEN SIGNAL NoPinsOnAtomicPublic[from, obj, fromWire, CoreOps.GetFullWireName[from.public, fromWire]];
CoreGeometry.AddIndirectLazyPins[extractMode.decoration, toWire, fromWire];
};
We check that the public of the source and the public of the recasted layout are similar, and we copy properties from one to the other
CoreOps.VisitRootAtomics[to.public, SmashPins];
VisitAtomicPairs[to.public, from.public, CopyPins];
};
layoutProp:
PRIVATE
ATOM ← CoreProperties.RegisterProperty[$PWCoreLayout];
cache on CellTypes
Layout:
PUBLIC
PROC [cellType: CellType]
RETURNS [obj: Object] = {
obj ← NARROW [CoreProperties.GetCellTypeProp[cellType, layoutProp]];
IF obj#NIL THEN RETURN;
BEGIN
layoutAtom: ATOM ← GetLayoutAtom[cellType];
layoutAtomData: LayoutAtomData;
layoutData: LayoutData;
layoutCellType: CellType;
IF layoutAtom=
NIL
THEN
IF cellType.class.recast=
NIL
THEN ERROR Error[$NoLayoutAtom, "Impossible to find a layoutAtom for this cellType", cellType]
ELSE {
recasted: CellType = CoreOps.Recast[cellType];
obj ← Layout[recasted];
CopyDecorations[cellType, recasted, obj];
CoreGeometry.PutObject[extractMode.decoration, cellType, obj];
RETURN;
};
layoutAtomData ← GetLayoutAtomData[layoutAtom];
IF layoutAtomData=NIL THEN ERROR Error[$NoRegistration, IO.PutFR["LayoutAtom %g has not been registered", IO.atom[layoutAtom]], cellType];
We compute the attributes (if any)
IF layoutAtomData.attributesProc#NIL THEN layoutAtomData.attributesProc[cellType];
Now the layout
obj ← layoutAtomData.layoutProc[cellType];
We decorate temporarily for lazy decorations
CoreGeometry.PutObject[extractMode.decoration, cellType, obj];
layoutData ← NEW [LayoutDataRec ← [cellType: cellType, obj: obj, mode: extractMode]];
layoutCellType ← CoreOps.CreateCellType[class: layoutClass, public: CoreOps.CopyWire[cellType.public], data: layoutData];
Now we decorate the source cellType
IF layoutAtomData.decorateProc#NIL THEN layoutAtomData.decorateProc[cellType, obj];
We check those decorations, and we decorate layoutCellType. We need to do that in order to be able to return layoutCellType as the result of the extraction.
CopyDecorations[layoutCellType, cellType, obj];
CoreGeometry.PutObject[extractMode.decoration, layoutCellType, obj];
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, $PWCoreCellType, layoutCellType];
CDProperties.PutObjectProp[obj, extractMode.extractProcProp, $FakeExtract];
CoreGeometry.PutObject[extractMode.decoration, cellType, obj];
CoreProperties.PutCellTypeProp[cellType, layoutProp, obj];
Consistency check
IF Sinix.Extract[obj, extractMode].result#layoutCellType THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType];
IF CorrespondingCellType[obj]#layoutCellType THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType];
END;
};
FromLayoutWithoutPublic:
PUBLIC
PROC [obj: Object]
RETURNS [cellType: CellType] = {
cellType ← NARROW [Sinix.Extract[obj, extractMode].result];
SetLayoutAndDecoration[cellType, obj];
};
Global Variable
extractMode: PUBLIC Sinix.Mode ← SinixOps.GetExtractMode[$cmosB];
$Get, $GetAndFlatten, $Value and $ValueNoDecorate
maskSuffix:
PUBLIC
ROPE ← ".mask";
GetAndAddSuffix:
PROC [source:
CD.Design, name:
ROPE]
RETURNS [obj: Object] = {
obj ← PW.Get[source, IO.PutR[IO.rope[name], IO.rope[maskSuffix]]];
};
Get: LayoutProc = {
source: CD.Design ← NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreSourceDesign]];
obj ← GetAndAddSuffix[source, CoreOps.GetCellTypeName[cellType]];
};
GetAndFlatten: LayoutProc = {
source: CD.Design ← NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreSourceDesign]];
obj ← PW.Flatten[GetAndAddSuffix[source, CoreOps.GetCellTypeName[cellType]]];
};
Value: LayoutProc = {
obj ← NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreValue]];
};
DecorateValue:
PUBLIC DecorateProc = {
extractedCT: CellType ← NARROW [Sinix.Extract[obj, extractMode].result];
extractedToSource: HashTable.Table ← HashTable.Create[extractedCT.public.size];
FindInExtractedPublic: CoreOps.EachWireProc = {
FOR names:
LIST
OF
ROPE ← CoreOps.GetFullWireNames[cellType.public, wire], names.rest
WHILE names#
NIL
DO
name: ROPE ← names.first;
extractedWire: Wire ← CoreOps.FindWire[extractedCT.public, name];
previousSourceWire: Wire ← NARROW [HashTable.Fetch[extractedToSource, extractedWire].value];
IF extractedWire=NIL OR extractedWire.size#0 THEN LOOP;
IF previousSourceWire#NIL AND previousSourceWire#wire THEN SIGNAL PinsCorrespondingToSeveralPublics[cellType, obj, LIST [previousSourceWire, wire], CoreGeometry.GetPins[extractMode.decoration, extractedWire]];
IF
NOT CoreGeometry.HasPins[extractMode.decoration, extractedWire]
THEN SIGNAL NoPinsOnAtomicPublic[cellType, obj, extractedWire, name];
CoreGeometry.AddIndirectLazyPins[extractMode.decoration, wire, extractedWire];
[] ← HashTable.Store[extractedToSource, extractedWire, wire];
ENDLOOP;
};
CoreOps.VisitRootAtomics[cellType.public, SmashPins];
[] ← CoreOps.VisitWire[cellType.public, FindInExtractedPublic];
};
Abuts, Arrays and Recast
AttributeX: AttributesProc = {SortInstances[Sisyph.mode.decoration, cellType, SortInX]};
AttributeY: AttributesProc = {SortInstances[Sisyph.mode.decoration, cellType, SortInY]};
AbutX: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i:
NAT
DECREASING
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListX[subObjects];
};
AbutY: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i:
NAT
DECREASING
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListY[subObjects];
};
ReverseAbutX: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i:
NAT
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListX[subObjects];
};
ReverseAbutY: LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
subObjects: LIST OF Object ← NIL;
FOR i:
NAT
IN [0 .. data.size)
DO
subObjects ← CONS [Layout[data[i].type], subObjects];
ENDLOOP;
obj ← PW.AbutListY[subObjects];
};
ArrayX: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawAbutX]; obj ← Layout[recasted];
};
ArrayY: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawAbutY]; obj ← Layout[recasted];
};
ReverseArrayX: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawReverseAbutX]; obj ← Layout[recasted];
};
ReverseArrayY: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawReverseAbutY]; obj ← Layout[recasted];
};
Recast: LayoutProc = {
obj ← Layout[CoreOps.Recast[cellType]];
};
DecorateAbut:
PUBLIC
PROC [cellType: CellType, obj: Object, sort: SortProc] = {
InsertInst: CDCells.InstEnumerator = {
IF inst.trans.orient#original THEN ERROR Error[$CallerBug, "DecorateAbut is only applicable to objects expanding into cells without rotation", cellType];
sorted ← CONS [inst, sorted];
};
CompareInst: GList.CompareProc = {
inst1: CD.Instance = NARROW [ref1];
inst2: CD.Instance = NARROW [ref2];
RETURN [
IF sort[ObjectBase[inst1.ob, inst1.trans], ObjectBase[inst2.ob, inst2.trans]]
THEN less ELSE greater];
};
sorted: LIST OF CD.Instance;
recordData: CoreClasses.RecordCellType ← NARROW [cellType.data];
WHILE obj.class#CDCells.pCellClass DO obj ← CDDirectory.Expand[obj].new ENDLOOP;
[] ← CDCells.EnumerateInstances[obj, InsertInst];
sorted ← NARROW [GList.Sort[sorted, CompareInst]];
We decorate each instance with the appropriate trans, so that the Lazy GetPins can find the location
FOR i:
NAT
IN [0 .. recordData.size)
DO
CoreGeometry.PutTrans[extractMode.decoration, recordData[i], sorted.first.trans];
sorted ← sorted.rest;
ENDLOOP;
IF sorted#NIL THEN ERROR Error[$CallerBug, "DecorateAbut assumption not valid: CD cell has more instances than record CellType", cellType];
CoreGeometry.PutRecordLazyPins[extractMode.decoration, cellType, CD.InterestRect[obj]];
};
DecorateAbutX:
PUBLIC DecorateProc = {
DecorateAbut[cellType, obj, SortInX];
};
DecorateAbutY:
PUBLIC DecorateProc = {
DecorateAbut[cellType, obj, SortInY];
};
DecorateReverseAbutX:
PUBLIC DecorateProc = {
DecorateAbut[cellType, obj, ReverseSortInX];
};
DecorateReverseAbutY:
PUBLIC DecorateProc = {
DecorateAbut[cellType, obj, ReverseSortInY];
};
DecorateRecasted:
PUBLIC DecorateProc = {
CopyDecorations[cellType, CoreOps.Recast[cellType], obj];
};
Rotations
Rotated:
PROC [cellType: CellType]
RETURNS [rotatedCT: CellType] = {
rct: CoreClasses.RecordCellType;
IF cellType.class#CoreClasses.recordCellClass THEN ERROR Error[$CallerBug, "Rotation CellType expected [RecordCell with one instance]", cellType];
rct ← NARROW [cellType.data];
IF rct.size#1 THEN ERROR Error[$CallerBug, "Rotation CellType expected [RecordCell with one instance]", cellType];
rotatedCT ← rct[0].type;
};
FlipX: LayoutProc = {obj ←
PW.FlipX[Layout[Rotated[cellType]]]};
FlipY: LayoutProc = {obj ←
PW.FlipY[Layout[Rotated[cellType]]]};
Rot90: LayoutProc = {obj ←
PW.Rot90[Layout[Rotated[cellType]]]};
Rot180: LayoutProc = {obj ←
PW.Rot180[Layout[Rotated[cellType]]]};
Rot270: LayoutProc = {obj ←
PW.Rot270[Layout[Rotated[cellType]]]};
DecorateRotated:
PUBLIC DecorateProc = {
rotatedCT: CellType = Rotated[cellType];
trans: CoreGeometry.Transformation;
DecorateUniqueInst: CDCells.InstEnumerator = {trans ← inst.trans};
WHILE obj.class#CDCells.pCellClass DO obj ← CDDirectory.Expand[obj].new ENDLOOP;
IF CDCells.CountInstances[obj]#1 THEN ERROR Error[$CallerBug, "DecorateRotated is not supposed to be called with an obj that does not expand into a one instance cell", cellType];
[] ← CDCells.EnumerateInstances[obj, DecorateUniqueInst];
CoreGeometry.PutTrans[extractMode.decoration, NARROW [cellType.data, CoreClasses.RecordCellType][0], trans];
CoreGeometry.PutRecordLazyPins[extractMode.decoration, cellType, CD.InterestRect[obj]];
};
Help for writing DecorateProcs
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]};
ObjectBase:
PROC [obj:
CD.Object, trans: CoreGeometry.Transformation]
RETURNS [pos:
CD.Position] = {
pos ← CDBasics.BaseOfRect[CDBasics.MapRect[CD.InterestRect[obj], trans]];
};
InstanceBase:
PROC [decoration: CoreGeometry.Decoration, cellType: CellType, trans: CoreGeometry.Transformation]
RETURNS [pos:
CD.Position] = {
pos ← ObjectBase[CoreGeometry.GetObject[decoration, cellType], trans];
};
SortInstances:
PUBLIC
PROC [decoration: CoreGeometry.Decoration, cellType: CellType, sort: SortProc] = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
FOR i:
NAT
IN [0 .. data.size-1)
DO
FOR j:
NAT
IN (i .. data.size)
DO
IF ~sort[
InstanceBase[decoration, data[i].type, CoreGeometry.GetTrans[decoration, data[i]]],
InstanceBase[decoration, data[j].type, CoreGeometry.GetTrans[decoration, data[j]]]
] THEN {
w: CoreClasses.CellInstance ← data[i];
data[i] ← data[j]; data[j] ← w;
};
ENDLOOP;
ENDLOOP;
};
DecorateFlatten:
PUBLIC
PROC [cellType: CellType, obj: Object, sort:
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]]; -- table of publics of extracted to publics of source
extractedCTData: CoreClasses.RecordCellType ← NARROW [extractedCT.data];
cellTypeData: CoreClasses.RecordCellType ← NARROW [cellType.data];
positionnedInstances: LIST OF PositionnedInstance;
positionnedWires: LIST OF PositionnedWire;
DecorateActual:
PROC [bindings: HashTable.Table, sourceActual, deepPublic: Wire] = {
wireBind: CoreFlat.FlatWire ← NARROW [HashTable.Fetch[bindings, deepPublic].value]; -- bindings=NIL would mean that extractedCT is a leaf, which is impossible
extractedActual: Wire;
wire: Wire;
FOR i: NAT IN [0 .. sourceActual.size) DO DecorateActual[bindings, sourceActual[i], deepPublic[i]] ENDLOOP;
IF deepPublic.size#0 THEN RETURN;
IF wireBind=NIL THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType]; -- something is really wrong!
IF wireBind.flatCell#[] THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType]; -- a deep internal wire
extractedActual ← wireBind.wire;
IF sourceActual.size#extractedActual.size THEN ERROR Error[$InternalBug, "Internal invariant failed", cellType];
wire ← NARROW [HashTable.Fetch[extractedToSource, extractedActual].value];
IF wire=sourceActual THEN RETURN;
IF wire#NIL THEN SIGNAL PinsCorrespondingToSeveralPublics[cellType, obj, LIST [wire, sourceActual], CoreGeometry.GetPins[extractMode.decoration, extractedActual]];
CoreGeometry.AddIndirectLazyPins[extractMode.decoration, sourceActual, extractedActual];
[] ← HashTable.Insert[extractedToSource, extractedActual, sourceActual];
};
[positionnedInstances, positionnedWires] ← GetPositionnedInstances[extractedCT, sort];
IF cellTypeData.size#GList.Length[positionnedInstances] THEN ERROR Error[$CallerBug, IO.PutFR["Mismatch between extracted layout (%g instances) and source description (%g instances)", IO.int[GList.Length[positionnedInstances]], IO.int[cellTypeData.size]], cellType];
CoreOps.VisitRootAtomics[cellType.public, SmashPins];
FOR i:
NAT
IN [0 .. cellTypeData.size)
DO
positionnedInstance: PositionnedInstance = positionnedInstances.first;
cell: CellType = positionnedInstance.cell;
sourceCellType: CellType = NARROW [cell.data, LayoutData].cellType;
IF Layout[cellTypeData[i].type]#Layout[sourceCellType] THEN ERROR Error[$CallerBug, IO.PutFR["Mismatch between the %gth instance of the extracted layout and the %gth instance of the source description: cellTypes are different", IO.int[i], IO.int[i]], cellType];
CoreGeometry.PutTrans[extractMode.decoration, cellTypeData[i], positionnedInstance.trans];
IF ~ CoreOps.CorrectConform[cellTypeData[i].actual, cell.public] THEN ERROR Error[$InternalBug, "Call Implementor!", cellType];
FOR j:
NAT
IN [0 .. cell.public.size)
DO
DecorateActual[positionnedInstance.bindings, cellTypeData[i].actual[j], cell.public[j]];
ENDLOOP;
positionnedInstances ← positionnedInstances.rest;
ENDLOOP;
We copy the pins for all publics. For now, we only do it for wires which have the same name as some internal of cellType.
All this code stinks ....
WHILE positionnedWires#
NIL
DO
AddExtraPins: CoreGeometry.EachInstanceProc = {
IF CoreGeometry.TransfedNotAtEdge[positionnedWire.trans, ir, instance] THEN RETURN;
CoreGeometry.PutPins[
extractMode.decoration, source,
CONS [CoreGeometry.Transform[positionnedWire.trans, instance], CoreGeometry.GetPins[extractMode.decoration, source]]
];
};
positionnedWire: PositionnedWire = positionnedWires.first;
wire: Wire = positionnedWire.wire;
flatWire: CoreFlat.FlatWireRec = positionnedWire.flatWire;
name: ROPE = CoreOps.GetShortWireName[wire];
source: Wire ← NARROW [HashTable.Fetch[extractedToSource, flatWire.wire].value];
IF flatWire.flatCell#[] THEN ERROR Error[$InternalBug, "Call implementor!", cellType]; -- not yet implemented if it is not part of the internal of extractedCT
The following lines are to pass PWCoreRoute test
All this code stinks ....
IF source=NIL THEN source ← CoreOps.FindWire[cellTypeData.internal, name];
If source is NIL, crash!
IF source=NIL THEN SIGNAL Signal[cellType];
If it is an internal only, let's forget it!
IF source#NIL AND CoreOps.RecursiveMember[cellType.public, source] THEN [] ← CoreGeometry.EnumerateGeometry[extractMode.decoration, wire, AddExtraPins];
positionnedWires ← positionnedWires.rest;
ENDLOOP;
};
PositionnedInstance: TYPE = REF PositionnedInstanceRec;
PositionnedInstanceRec:
TYPE =
RECORD [
cell: CellType, -- flat CT (of class layoutClass)
flatCell: CoreFlat.FlatCellTypeRec,
bindings: CoreFlat.Bindings, -- [public of cellType -> CoreFlat.WireBind]
trans: CoreGeometry.Transformation
];
PositionnedWire: TYPE = REF PositionnedWireRec;
PositionnedWireRec:
TYPE =
RECORD [
wire: Wire,
flatWire: CoreFlat.FlatWireRec,
trans: CoreGeometry.Transformation
];
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 [extractedCT: CellType, sort: SortProc]
RETURNS [positionnedInstances:
LIST
OF PositionnedInstance ←
NIL, positionnedWires:
LIST
OF PositionnedWire ←
NIL] = {
Leaf: CoreGeometry.LeafProc = {RETURN [cellType.class=layoutClass]};
EachFlatWire: CoreGeometry.EachFlatWireProc = {
positionnedWires ←
CONS [
NEW [PositionnedWireRec ← [wire: wire, flatWire: flatWire, trans: trans]],
positionnedWires];
};
EachFlatCell: CoreGeometry.EachFlatCellProc = {
positionnedInstances ←
CONS [
NEW [PositionnedInstanceRec ← [
cell: cell, flatCell: flatCell, bindings: bindings, trans: trans
]],
positionnedInstances];
};
Compare: GList.CompareProc = {
pi1: PositionnedInstance = NARROW [ref1];
pi2: PositionnedInstance = NARROW [ref2];
RETURN [
IF sort[InstanceBase[extractMode.decoration, pi1.cell, pi1.trans], InstanceBase[extractMode.decoration, pi2.cell, pi2.trans]]
THEN less ELSE greater];
};
CoreGeometry.EnumerateFlatGeometry[decoration: extractMode.decoration, root: extractedCT, leafProc: Leaf, eachFlatWire: EachFlatWire, eachFlatCell: EachFlatCell];
positionnedInstances ← NARROW [GList.Sort[positionnedInstances, Compare]];
};
Short cut
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];
};
RotateCellType:
PUBLIC
PROC [rotatedCellType: CellType, orientation:
ATOM]
RETURNS [cellType: CellType] = {
public: Wire = CoreOps.CreateWires[size: rotatedCellType.public.size];
internal: Wire = CoreOps.CreateWires[size: rotatedCellType.public.size];
FOR i:
NAT
IN [0 .. rotatedCellType.public.size)
DO
new: Wire = CoreOps.CopyWire[rotatedCellType.public[i]];
public[i] ← internal[i] ← new;
ENDLOOP;
cellType ← CoreClasses.CreateRecordCell[public: public, internal: internal, instances: LIST [CoreClasses.CreateInstance[actual: internal, type: rotatedCellType]]];
SetLayout[cellType, orientation];
};
Tentative help for regular structures
AbutCell:
PUBLIC
PROC [public: Wire, abutInstances:
LIST
OF AbutInstance, inX:
BOOL, name:
ROPE ←
NIL, props: Properties ←
NIL]
RETURNS [recordCell: CellType] = {
positionnedInstances: LIST OF PositionnedInstance ← NIL;
ObjectsFromAbutInstances:
PROC [abutInstances:
LIST
OF AbutInstance]
RETURNS [
LIST
OF Object] = {
IF abutInstances=NIL THEN RETURN [NIL];
BEGIN
obj: Object ← abutInstances.first.object; -- to allow 2 instances of the same object to have different bindings
ct: CellType ← FromLayoutWithoutPublic[obj];
RETURN [CONS [Layout[ct], ObjectsFromAbutInstances[abutInstances.rest]]];
END;
};
RegisterExtractedToSource:
PROC [extracted, source: Wire, checkPins:
BOOL] = {
prevAct: Wire ← NARROW [HashTable.Fetch[extractedToSource, extracted].value];
IF extracted.size#source.size THEN ERROR Error[$CallerBug, "Extracted wire and truth public do not have same structure. You may call implementor for help!", extractedCT];
FOR i: NAT IN [0 .. extracted.size) DO RegisterExtractedToSource[extracted[i], source[i], checkPins] ENDLOOP;
IF prevAct=source THEN RETURN;
IF prevAct#NIL THEN SIGNAL PinsCorrespondingToSeveralPublics[extractedCT, obj, LIST [prevAct, source], CoreGeometry.GetPins[extractMode.decoration, extracted]];
[] ← HashTable.Store[extractedToSource, extracted, source];
IF source.size#0 THEN RETURN;
IF checkPins
AND
NOT CoreGeometry.HasPins[extractMode.decoration, extracted]
THEN IF checkPins THEN SIGNAL NoPinsOnAtomicPublic[extractedCT, obj, extracted] ELSE RETURN; -- sub-public should have pins!
CoreGeometry.AddIndirectLazyPins[extractMode.decoration, source, extracted];
};
Replace:
PROC [extractedWire: Wire]
RETURNS [wire: Wire] = {
wire ← NARROW [HashTable.Fetch[extractedToSource, extractedWire].value];
IF wire#NIL THEN RETURN;
wire ← CoreOps.CreateWires[size: extractedWire.size];
internals ← CONS [wire, internals];
FOR i:
NAT
IN [0 .. extractedWire.size)
DO
wire[i] ← Replace[extractedWire[i]];
ENDLOOP;
RegisterExtractedToSource[extractedWire, wire, FALSE];
};
CheckPinsNonNil:
PROC [wire: Wire] = {
IF
NOT CoreGeometry.HasPins[extractMode.decoration, wire]
THEN SIGNAL NoPinsOnAtomicPublic[extractedCT, obj, wire, "Some atomic publics have no associated geometry, probably because you forgot to specify in each abutInstance the sub-public bound to it."];
};
internals: Wires ← LIST [public];
instances: LIST OF CoreClasses.CellInstance;
obj: Object ← (IF inX THEN PW.AbutListX ELSE PW.AbutListY)[ObjectsFromAbutInstances[abutInstances]];
extractedCT: CellType ← NARROW [Sinix.Extract[obj, extractMode].result];
extractedData: CoreClasses.RecordCellType ← NARROW [extractedCT.data];
extractedToSource: HashTable.Table ← HashTable.Create[CoreOps.WireBits[public]];
i: NAT ← 0;
CoreOps.VisitRootAtomics[public, SmashPins];
SortInstances[extractMode.decoration, extractedCT, IF inX THEN SortInX ELSE SortInY];
FOR list:
LIST
OF AbutInstance ← abutInstances, list.rest
WHILE list#
NIL
DO
instance: CoreClasses.CellInstance = extractedData[i];
FOR pas:
LIST
OF CoreCreate.
PA ← list.first.pas, pas.rest
WHILE pas#
NIL
DO
pub: Wire = CoreCreate.FindWire[instance.type.public, pas.first.public];
act: Wire = CoreCreate.FindWire[public, pas.first.actual];
IF pub=NIL THEN ERROR Error[$CallerBug, "Some public specified in some PA in your call to AbutCell is not really a public of the cellTYpe. You may call the maintainor of this package for help!", extractedCT];
IF act=NIL THEN ERROR Error[$CallerBug, "Call implementor for help!", extractedCT];
RegisterExtractedToSource[CoreClasses.CorrespondingActual[instance, pub], act, TRUE];
ENDLOOP;
i ← i + 1;
ENDLOOP;
IF i#extractedData.size THEN Error[$CallerBug, "Call implementor for help!", extractedCT];
We check now that every atomic public has pins
CoreOps.VisitRootAtomics[public, CheckPinsNonNil];
We replace the actuals
FOR i:
NAT
DECREASING
IN [0 .. extractedData.size)
DO
actual: Wire ← CoreOps.CreateWires[size: extractedData[i].actual.size];
FOR j:
NAT
IN [0 .. extractedData[i].actual.size)
DO
actual[j] ← Replace[extractedData[i].actual[j]];
ENDLOOP;
instances ← CONS [CoreClasses.CreateInstance[actual: actual, type: extractedData[i].type, props: extractedData[i].properties], instances];
ENDLOOP;
recordCell ← CoreClasses.CreateRecordCell[public, CoreOps.CreateWire[internals], instances, name, props];
SetLayoutAndDecoration[recordCell, obj];
};
Saving "Checkpoints"
Store:
PUBLIC
PROC [cellType: CellType, withCuteFonts:
BOOL ←
FALSE] = {
name: ROPE ← CoreOps.GetCellTypeName[cellType];
layout: CD.Object ← Layout[cellType];
layoutFileName: ROPE ← Rope.Cat[name, "Layout"];
shellFileName: ROPE ← Rope.Cat[name, "Shell"];
layoutDesign: CD.Design ← CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
shellDesign: CD.Design ← CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
shell: CD.Object;
Core
TerminalIO.PutF["Saving the Core for cell %g ...\n", IO.rope[name]];
[] ← CoreIO.ReportSaveCellType[cellType];
Shell
TerminalIO.PutF["Making shell for cell %g ...\n", IO.rope[name]];
shell ← CoreGeometry.CreateShell[extractMode.decoration, cellType, withCuteFonts];
shellDesign.name ← shellFileName;
[] ← CDDirectory.Include[shellDesign, shell, name];
CDOps.IncludeObjectI[shellDesign, shell];
TerminalIO.PutF["Storing Shell for cell %g ...\n", IO.rope[name]];
[] ← CDIO.WriteDesign[shellDesign, shellFileName];
Layout
layoutDesign.name ← layoutFileName;
layout ← PWObjects.CreateCell[LIST [CDInstances.NewInst[layout]], CD.InterestRect[layout], name];
[] ← CDDirectory.Include[layoutDesign, layout, name];
CDOps.IncludeObjectI[layoutDesign, layout];
TerminalIO.PutF["Storing Layout for cell %g ...\n", IO.rope[name]];
[] ← CDIO.WriteDesign[layoutDesign, layoutFileName];
TerminalIO.PutF["... layout checkpoint stored in %g.core, %gLayout.dale and %gShell.dale\n", IO.rope[name], IO.rope[name], IO.rope[name]];
};
Retrieve:
PUBLIC
PROC [name:
ROPE]
RETURNS [cellType: CellType] = {
TerminalIO.PutF["Retrieving the Core for cell %g ...\n", IO.rope[name]];
cellType ← CoreIO.RestoreCellType[name];
TerminalIO.PutF["... core retrieved in %g.core ...\n", IO.rope[name]];
};
Backdoor for clients such as PWCoreLichen
layoutClass:
PUBLIC Core.CellClass ←
NEW [Core.CellClassRec ← [name: "Layout", recast: RecastLayout]];
RecastLayout: Core.RecastProc = {
FillTable:
PROC [extractedWire: Wire] = {
FillTableInternal:
PROC [sourcePublic, newPublic: Wire] = {
prevSource: Wire;
sourcePins: CoreGeometry.Instances ← CoreGeometry.GetPins[data.mode.decoration, sourcePublic];
CoreGeometry.PutPins[data.mode.decoration, sourcePublic, sourcePins]; -- to avoid all that lazyness
IF NOT CoreGeometry.TouchListList[sourcePins, extractedPins] THEN RETURN;
prevSource ← NARROW [HashTable.Fetch[table, extractedWire].value];
IF prevSource#NIL AND prevSource#newPublic THEN SIGNAL PinsCorrespondingToSeveralPublics[data.cellType, data.obj, LIST [prevSource, sourcePublic], extractedPins];
[] ← HashTable.Store[table, extractedWire, newPublic];
[] ← HashTable.Store[extractedToSource, extractedWire, sourcePublic];
};
extractedPins: CoreGeometry.Instances ← CoreGeometry.GetPins[data.mode.decoration, extractedWire];
VisitAtomicPairs[data.cellType.public, public, FillTableInternal];
};
recordData: CoreClasses.RecordCellType;
data: LayoutData ← NARROW [me.data];
extractedCT: CellType ← NARROW [Sinix.Extract[data.obj, data.mode].result];
public: Wire = CoreOps.CopyWire[me.public];
table: HashTable.Table ← HashTable.Create[];
extractedToSource: HashTable.Table ← HashTable.Create[];
CoreOps.VisitRootAtomics[extractedCT.public, FillTable];
new ← CoreClasses.CreatePermutedRecordCell[iconPublic: public, schCell: extractedCT, table: table, name: Rope.Cat["LayoutRecastOf", CoreOps.GetCellTypeName[data.cellType]]];
recordData ← NARROW [new.data];
IF recordData.size#1 THEN ERROR Error[$InternalBug, "Internal invariant failed", data.cellType];
CoreProperties.PutCellTypeProp[extractedCT, $ExtractedToSource, extractedToSource];
CoreGeometry.PutTrans[data.mode.decoration, recordData[0], []];
};
LayoutCellTypeInfo:
PUBLIC
PROC [layoutCellType: CellType]
RETURNS [obj: Object, sourceCellType, extractedCellType: CellType, extractedToSource: HashTable.Table] = {
data: LayoutData ← NARROW [layoutCellType.data];
obj ← data.obj;
sourceCellType ← data.cellType;
extractedCellType ← NARROW [CoreOps.Recast[layoutCellType].data, CoreClasses.RecordCellType][0].type;
extractedToSource ← NARROW [CoreProperties.GetCellTypeProp[extractedCellType, $ExtractedToSource]];
};
CorrespondingCellType:
PUBLIC
PROC [obj: Object]
RETURNS [layoutCellType: CellType ←
NIL] = {
IF CDProperties.GetObjectProp[obj, extractMode.extractProcProp]=$FakeExtract
THEN layoutCellType ← NARROW [CDProperties.GetObjectProp[obj, $PWCoreCellType]];
};
Registering layoutAtoms
WriteLayoutCache: CoreIO.PropWriteProc = {CoreGeometryBackdoor.WriteObject[h, NARROW [value]]};
ReadLayoutCache: CoreIO.PropReadProc = {value ← CoreGeometryBackdoor.ReadObject[h]};
[] ← CoreIO.RegisterProperty[layoutProp, WriteLayoutCache, ReadLayoutCache];
Sinix.RegisterExtractProc[$FakeExtract, FakeExtract];
[] ← RegisterLayoutAtom[$Get, Get, DecorateValue];
[] ← RegisterLayoutAtom[$GetAndFlatten, GetAndFlatten, DecorateValue];
[] ← RegisterLayoutAtom[$Value, Value, DecorateValue];
[] ← RegisterLayoutAtom[$ValueNoDecorate, Value];
[] ← RegisterLayoutAtom[$AbutListXNoDecorate, AbutX];
[] ← RegisterLayoutAtom[$AbutListYNoDecorate, AbutY];
[] ← RegisterLayoutAtom[$RawAbutX, AbutX, DecorateAbutX];
[] ← RegisterLayoutAtom[$RawAbutY, AbutY, DecorateAbutY];
[] ← RegisterLayoutAtom[$RawReverseAbutX, ReverseAbutX, DecorateReverseAbutX];
[] ← RegisterLayoutAtom[$RawReverseAbutY, ReverseAbutY, DecorateReverseAbutY];
[] ← RegisterLayoutAtom[$AbutX, AbutX, DecorateAbutX, AttributeX];
[] ← RegisterLayoutAtom[$AbutY, AbutY, DecorateAbutY, AttributeY];
[] ← RegisterLayoutAtom[$ReverseAbutX, ReverseAbutX, DecorateReverseAbutX, AttributeX];
[] ← RegisterLayoutAtom[$ReverseAbutY, ReverseAbutY, DecorateReverseAbutY, AttributeY];
[] ← RegisterLayoutAtom[$ArrayX, ArrayX, DecorateRecasted];
[] ← RegisterLayoutAtom[$ArrayY, ArrayY, DecorateRecasted];
[] ← RegisterLayoutAtom[$ReverseArrayX, ReverseArrayX, DecorateRecasted];
[] ← RegisterLayoutAtom[$ReverseArrayY, ReverseArrayY, DecorateRecasted];
[] ← RegisterLayoutAtom[$Recast, Recast, DecorateRecasted];
[] ← RegisterLayoutAtom[$FlipX, FlipX, DecorateRotated];
[] ← RegisterLayoutAtom[$FlipY, FlipY, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot90, Rot90, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot180, Rot180, DecorateRotated];
[] ← RegisterLayoutAtom[$Rot270, Rot270, DecorateRotated];
END.