PatchWorkImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Created by Bertrand Serlet, May 8, 1988 2:18:10 am PDT
Bertrand Serlet May 13, 1988 4:08:11 pm PDT
DIRECTORY
Core, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties,
IO,
Pipal, PipalCore, PipalInstanceTable, PipalInt, PipalIO, PipalMos, PipalSinix, PipalUI,
PatchWork,
RefTab, Rope, TerminalIO;
PatchWorkImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreIO, CoreOps, CoreProperties, IO, PatchWork, Pipal, PipalCore, PipalInstanceTable, PipalInt, PipalIO, PipalMos, PipalSinix, PipalUI, RefTab, Rope, TerminalIO
EXPORTS PatchWork =
BEGIN OPEN PatchWork;
Basics
CellType: TYPE = Core.CellType;
Object: TYPE = Pipal.Object;
Objects: TYPE = Pipal.Objects;
Wire: TYPE = Core.Wire;
WireSeq: TYPE = Core.WireSeq;
ROPE: TYPE = Core.ROPE;
Properties: TYPE = Core.Properties;
Wires: TYPE = Core.Wires;
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: Object] = CODE;
NoPinsOnAtomicPublic: PUBLIC SIGNAL [cellType: CellType, obj: Object, public: Wire, message: ROPENIL] = CODE;
LayoutAtomsTable
layoutAtomsTable: RefTab.Ref ← RefTab.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 ~RefTab.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] = {
entry: ROPE;
layoutAtomData ← NARROW [RefTab.Fetch[layoutAtomsTable, layoutAtom].val];
IF layoutAtomData#NIL THEN RETURN;
entry ← PipalUI.FetchKeyLine["PatchWork.LoadList", IO.PutR1[IO.atom[layoutAtom]]];
IF entry=NIL THEN RETURN [NIL];
PipalUI.ExecuteInTerminal[entry];
layoutAtomData ← NARROW [RefTab.Fetch[layoutAtomsTable, layoutAtom].val];
};
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: ATOMNIL] = {
layoutAtom ← NARROW [CoreProperties.InheritCellTypeProp[cellType, layoutAtomProp]];
};
Copies decorations from from to to
CopyDecorations: PROC [to, from: CellType, obj: Object] = {
CopyPins: PROC [toWire, fromWire: Wire] = {
IF NOT PipalCore.HasPort[PipalCore.layoutDecoration, fromWire]
THEN SIGNAL NoPinsOnAtomicPublic[from, obj, fromWire, CoreOps.GetFullWireName[from.public, fromWire]];
PipalCore.AddPort[PipalCore.layoutDecoration, toWire, PipalCore.GetPort[PipalCore.layoutDecoration, 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.VisitAtomicPairs[to.public, from.public, CopyPins];
};
Checks that's ct is properly decorated.
CheckDecorations: PROC [ct: CellType, obj: Object] = {
CheckPins: PROC [wire: Wire] = {
IF NOT PipalCore.HasPort[PipalCore.layoutDecoration, wire] THEN
SIGNAL NoPinsOnAtomicPublic[ct, obj, wire, CoreOps.GetFullWireName[ct.public, wire]];
};
CoreOps.VisitRootAtomics[ct.public, CheckPins];
};
You don't really want to know why!
FromPatchWorkRecord: PRIVATE TYPE = RECORD [int: INT];
fromPatchWorkTable: PRIVATE RefTab.Ref ← RefTab.Create[];
SetFromPatchWork: PRIVATE PROC [cellType: CellType] = {
obj: Object ← PipalCore.GetObject[PipalCore.layoutDecoration, cellType];
int: INTLOOPHOLE [cellType];
IF RefTab.Fetch[fromPatchWorkTable, obj].val#NIL THEN Signal[cellType]; -- same object is stuffed on two different cells! That breaks the invariants, and Lichen will not work!
[] ← RefTab.Store[fromPatchWorkTable, obj, NEW [FromPatchWorkRecord ← [int]]];
};
Layout: PUBLIC PROC [cellType: CellType] RETURNS [obj: Object] = {
layoutAtom: ATOM;
layoutAtomData: LayoutAtomData;
name: ROPE ← CoreOps.GetCellTypeName[cellType];
obj ← PipalCore.GetObject[PipalCore.layoutDecoration, cellType];
IF obj#NIL THEN RETURN;
layoutAtom ← NARROW [CoreProperties.GetCellTypeProp[cellType, layoutAtomProp]];
IF layoutAtom=NIL THEN
layoutAtom ← NARROW [CoreProperties.GetCellClassProp[cellType.class, layoutAtomProp]];
IF layoutAtom=NIL AND cellType.class.recast=NIL THEN
ERROR Error[$NoLayoutAtom, "Impossible to find a layoutAtom for this cellType", cellType];
layoutAtomData ← GetLayoutAtomData[IF layoutAtom=NIL THEN $Recast ELSE 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];
IF name#NIL THEN obj ← Pipal.CreateAnnotation[obj, Pipal.nameProp, name];
We decorate for lazy decorations
PipalCore.PutObject[PipalCore.layoutDecoration, cellType, obj];
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.
CheckDecorations[cellType, obj];
We mark obj as coming from Layout
SetFromPatchWork[cellType];
};
GetPatchWorkExtractedCTKey: PUBLIC PROC [extractedCT: CellType] RETURNS [key: INT ← 0] = {
obj: Object ← PipalCore.GetObject[PipalCore.layoutDecoration, extractedCT];
ref: REF FromPatchWorkRecord ← NARROW [RefTab.Fetch[fromPatchWorkTable, obj].val];
IF ref#NIL THEN key ← ref.int;
};
IsPatchWorkGenerated: PUBLIC PROC [obj: Object] RETURNS [BOOL] = {
RETURN [RefTab.Fetch[fromPatchWorkTable, obj].val#NIL];
};
FromLayoutWithoutPublic: PUBLIC PROC [obj: Object] RETURNS [cellType: CellType] = {
cellType ← NARROW [PipalSinix.Extract[obj, PipalSinix.layoutMode].result];
IF IsPatchWorkGenerated[obj] THEN RETURN; -- done twice!
SetLayoutAndDecoration[cellType, obj];
CheckDecorations[cellType, obj];
SetFromPatchWork[cellType];
};
$Get, $GetAndFlatten, $Value and $ValueNoDecorate
maskSuffix: PUBLIC ROPE ← ".mask";
GetAndAddSuffix: PROC [cellType: CellType] RETURNS [obj: Object] = {
ctName: ROPE ← CoreOps.GetCellTypeName[cellType];
maskName: ROPE ← Rope.Cat[ctName, maskSuffix];
obj ← PipalIO.Fetch[maskName];
};
Question for the reader: Why are we making an indirect here???
Answer: because two different cellTypes can have the exact same name and Layout: $Get. For example two icons extracted in different Sisyph contexts will yield two different (but identical!) cellTypes.
Get: LayoutProc = {
obj ← Pipal.CreateAnnotation[GetAndAddSuffix[cellType], PipalMos.indirectProp, NIL];
};
Flatten: PUBLIC PROC [object: Object] RETURNS [flat: Object] = {
instances: Objects ← NIL;
EachChild: PipalInt.EachChildProc = {
instances ← CONS [PipalInt.TransformObject[transformation, Flatten[child]], instances];
};
IF Pipal.ObjectClass[object]=Pipal.annotationClass THEN {
annotation: Pipal.Annotation ← NARROW [object];
IF annotation.key=$DontFlatten AND annotation.value#NIL THEN RETURN [object];
RETURN [Pipal.CreateAnnotation[Flatten[annotation.child], annotation.key, annotation.value]];
};
IF PipalMos.IsAtomic[object] THEN RETURN [object];
[] ← PipalInt.Enumerate[object, EachChild];
flat ← Pipal.CreateOverlay[instances];
};
GetAndFlatten: LayoutProc = {
obj ← Flatten[GetAndAddSuffix[cellType]];
};
Value: LayoutProc = {
obj ← NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreValue]];
};
DecorateValue: PUBLIC DecorateProc = {
extractedCT: CellType ← NARROW [PipalSinix.Extract[obj, PipalSinix.layoutMode].result];
extractedToSource: RefTab.Ref ← RefTab.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 [RefTab.Fetch[extractedToSource, extractedWire].val];
IF extractedWire=NIL OR extractedWire.size#0 THEN LOOP;
IF previousSourceWire#NIL AND previousSourceWire#wire THEN SIGNAL PinsCorrespondingToSeveralPublics[cellType, obj, LIST [previousSourceWire, wire], PipalCore.GetPort[PipalCore.layoutDecoration, extractedWire]];
IF NOT PipalCore.HasPort[PipalCore.layoutDecoration, extractedWire]
THEN SIGNAL NoPinsOnAtomicPublic[cellType, obj, extractedWire, name];
PipalCore.AddPort[PipalCore.layoutDecoration, wire, PipalCore.GetPort[PipalCore.layoutDecoration, extractedWire]];
[] ← RefTab.Store[extractedToSource, extractedWire, wire];
ENDLOOP;
};
[] ← CoreOps.VisitWire[cellType.public, FindInExtractedPublic];
};
Abuts, Arrays and Recast
AttributeAbutXorY: AttributesProc = {
ambiguous, inX: BOOL;
[ambiguous, inX] ← InstancesInXOrY[PipalCore.schematicsDecoration, cellType, PipalUI.schematicFudge];
IF ambiguous THEN ERROR Error[$CallerBug, "*** Ambiguity for deciding between AbutX and AbutY.\n", cellType];
SortInstances[PipalCore.schematicsDecoration, cellType, IF inX THEN SortInX ELSE SortInY];
};
LayoutAbutXorY: LayoutProc = {
obj ← (IF InstancesInXOrY[PipalCore.schematicsDecoration, cellType, PipalUI.schematicFudge].inX THEN AbutX ELSE AbutY)[cellType];
};
AttributeX: AttributesProc = {SortInstances[PipalCore.schematicsDecoration, cellType, SortInX]};
AttributeY: AttributesProc = {SortInstances[PipalCore.schematicsDecoration, cellType, SortInY]};
AbutX: LayoutProc = {obj ← Abut[TRUE, cellType]};
AbutY: LayoutProc = {obj ← Abut[FALSE, cellType]};
ReverseAbutX: LayoutProc = {obj ← Abut[TRUE, cellType, TRUE]};
ReverseAbutY: LayoutProc = {obj ← Abut[FALSE, cellType, TRUE]};
Abut: PROC [inX: BOOL, cellType: CellType, reverse: BOOLFALSE] RETURNS [obj: Object] = {
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 ← PipalInt.CreateAbut[inX, IF reverse THEN Pipal.Reverse[subObjects] ELSE subObjects];
};
AbutFlipXAndDecorate: LayoutProc = {obj ← AbutFlipAndDecorate[cellType, TRUE]};
AbutFlipYAndDecorate: LayoutProc = {obj ← AbutFlipAndDecorate[cellType, FALSE]};
AbutFlipAndDecorate: PROC [cellType: CellType, inX: BOOL] RETURNS [obj: Object] = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
flip: BOOLFALSE; -- indicates polarity of the coming flip
instances: Objects ← NIL; -- instances for constructing the cell
layout0: Object ← Layout[data[0].type];
isize0: PipalInt.Size ← PipalInt.AbutBox[layout0].size;
pos: PipalInt.Position ← [0, 0]; -- position (in ir coordonnates) of the coming cell
FOR i: NAT IN [0 .. data.size) DO
orientation: PipalInt.Orientation ← IF flip THEN IF inX THEN mirrorX ELSE rotate180X ELSE identity;
layout: Object ← Layout[data[i].type];
ir: PipalInt.Rectangle = PipalInt.TransformRectangle[[PipalInt.zeroVector, orientation], PipalInt.AbutBox[layout]];
trans: PipalInt.Transformation = [PipalInt.Sub[pos, ir.base], orientation]; -- translation, in the cell coordonnate system
IF NOT (IF inX THEN ir.size.y=isize0.y ELSE ir.size.x=isize0.x) THEN ERROR; -- incompatible y dimension for an abutX
instances ← CONS [PipalInt.TransformObject[trans, layout], instances];
We decorate each instance with the appropriate trans, so that the Lazy GetPins can find the location
PipalCore.PutTrans[PipalCore.layoutDecoration, data[i], trans];
IF inX THEN pos.x ← pos.x + ir.size.x ELSE pos.y ← pos.y + ir.size.y;
flip ← NOT flip;
ENDLOOP;
obj ← Pipal.CreateOverlay[instances];
PipalCore.PutRecordPorts[PipalCore.layoutDecoration, cellType, PipalInt.AbutBox[obj]];
};
ArrayX: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawAbutX];
obj ← Pipal.CreateAnnotation[Layout[recasted], PipalMos.indirectProp, NIL];
};
ArrayY: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawAbutY];
obj ← Pipal.CreateAnnotation[Layout[recasted], PipalMos.indirectProp, NIL];
};
ArrayFlipX: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawAbutFlipX];
obj ← Pipal.CreateAnnotation[Layout[recasted], PipalMos.indirectProp, NIL];
};
ArrayFlipY: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawAbutFlipY];
obj ← Pipal.CreateAnnotation[Layout[recasted], PipalMos.indirectProp, NIL];
};
ReverseArrayX: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawReverseAbutX];
obj ← Pipal.CreateAnnotation[Layout[recasted], PipalMos.indirectProp, NIL];
};
ReverseArrayY: LayoutProc = {
recasted: CellType ← CoreOps.Recast[cellType];
SetLayout[recasted, $RawReverseAbutY];
obj ← Pipal.CreateAnnotation[Layout[recasted], PipalMos.indirectProp, NIL];
};
Recast: LayoutProc = {
obj ← Pipal.CreateAnnotation[Layout[CoreOps.Recast[cellType]], PipalMos.indirectProp, NIL];
};
DecorateEnumeration: PUBLIC PROC [cellType: CellType, obj: Object, reverse: BOOLFALSE] = {
rank: NAT ← 0;
Each: PipalInt.EachChildProc = {
instance: CoreClasses.CellInstance ← recordData[IF reverse THEN recordData.size-rank-1 ELSE rank];
IF Layout[instance.type]#child THEN ERROR Error[$CallerBug, "DecorateEnumeration assumptions not valid", cellType];
PipalCore.PutTrans[PipalCore.layoutDecoration, instance, transformation];
rank ← rank + 1;
};
recordData: CoreClasses.RecordCellType ← NARROW [cellType.data];
abutBox: PipalInt.Rectangle ← PipalInt.AbutBox[obj];
WHILE Pipal.ObjectClass[obj]=Pipal.annotationClass DO
obj ← PipalInt.NthChild[obj].nthChild;
ENDLOOP;
IF PipalInt.CountChildren[obj]#recordData.size THEN ERROR Error[$CallerBug, "DecorateEnumeration assumption not valid: layout has a different number of instances than record CellType", cellType];
We decorate each instance with the appropriate trans, so that the Lazy GetPins can find the location
[] ← PipalInt.Enumerate[obj, Each];
PipalCore.PutRecordPorts[PipalCore.layoutDecoration, cellType, abutBox];
};
DecorateAbutXY: DecorateProc = {DecorateEnumeration[cellType, obj, FALSE]};
DecorateReverseAbut: DecorateProc = {DecorateEnumeration[cellType, obj, TRUE]};
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 ← PipalInt.CreateOrient[mirrorX, Layout[Rotated[cellType]]];
};
FlipY: LayoutProc = {
obj ← PipalInt.CreateOrient[rotate180X, Layout[Rotated[cellType]]];
};
Rot90: LayoutProc = {
obj ← PipalInt.CreateOrient[rotate90, Layout[Rotated[cellType]]];
};
Rot180: LayoutProc = {
obj ← PipalInt.CreateOrient[rotate180, Layout[Rotated[cellType]]];
};
Rot270: LayoutProc = {
obj ← PipalInt.CreateOrient[rotate270, Layout[Rotated[cellType]]];
};
DecorateTransformed: PUBLIC DecorateProc = {
rotatedCT: CellType = Rotated[cellType];
trans: PipalInt.Transformation; child: Object;
abutBox: PipalInt.Rectangle ← PipalInt.AbutBox[obj];
WHILE Pipal.ObjectClass[obj]=Pipal.annotationClass DO
obj ← PipalInt.NthChild[obj].nthChild;
ENDLOOP;
IF PipalInt.CountChildren[obj]#1 THEN ERROR Error[$CallerBug, "DecorateTransformed is not supposed to be called with an obj that does not expand into a one instance cell", cellType];
[trans, child] ← PipalInt.NthChild[obj];
IF Layout[rotatedCT]#child THEN ERROR Error[$CallerBug, "DecorateTransformed: some invariant broken", cellType];
PipalCore.PutTrans[PipalCore.layoutDecoration, NARROW [cellType.data, CoreClasses.RecordCellType][0], trans];
PipalCore.PutRecordPorts[PipalCore.layoutDecoration, cellType, abutBox];
};
Help for writing DecorateProcs
SortInX: PUBLIC PROC [pos1, pos2: PipalInt.Position] RETURNS [BOOL] = {RETURN [pos1.x<pos2.x]};
SortInY: PUBLIC PROC [pos1, pos2: PipalInt.Position] RETURNS [BOOL] = {RETURN [pos1.y<pos2.y]};
ReverseSortInX: PUBLIC PROC [pos1, pos2: PipalInt.Position] RETURNS [BOOL] = {RETURN [pos1.x>pos2.x]};
ReverseSortInY: PUBLIC PROC [pos1, pos2: PipalInt.Position] RETURNS [BOOL] = {RETURN [pos1.y>pos2.y]};
InstanceAbutBox: PROC [decoration: PipalCore.Decoration, instance: CoreClasses.CellInstance] RETURNS [abutBox: PipalInt.Rectangle] = {
trans: PipalInt.Transformation ← PipalCore.GetTrans[decoration, instance];
object: Object ← PipalCore.GetObject[decoration, instance.type];
abutBox ← PipalInt.TransformRectangle[trans, PipalInt.AbutBox[object]];
};
InstancesInXOrY: PUBLIC PROC [decoration: PipalCore.Decoration, record: CellType, fudge: INT ← 0] RETURNS [ambiguous, inX: BOOL] = {
data: CoreClasses.RecordCellType ← NARROW [record.data];
overlappingInX, overlappingInY: BOOLFALSE;
FOR i: NAT IN [0 .. data.size-1) DO
rect1: PipalInt.Rectangle ← InstanceAbutBox[decoration, data[i]];
FOR j: NAT IN (i .. data.size) DO
rect2: PipalInt.Rectangle ← InstanceAbutBox[decoration, data[j]];
IF rect1.base.x+fudge<rect2.base.x+rect2.size.x AND rect2.base.x+fudge<rect1.base.x+rect1.size.x THEN overlappingInX ← TRUE;
IF rect1.base.y+fudge<rect2.base.y+rect2.size.y AND rect2.base.y+fudge<rect1.base.y+rect1.size.y THEN overlappingInY ← TRUE;
ENDLOOP;
ENDLOOP;
ambiguous ← overlappingInX=overlappingInY;
inX ← overlappingInY;
};
SortInstances: PUBLIC PROC [decoration: PipalCore.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[InstanceAbutBox[decoration, data[i]].base, InstanceAbutBox[decoration, data[j]].base] THEN {
w: CoreClasses.CellInstance ← data[i];
data[i] ← data[j]; data[j] ← w;
};
ENDLOOP;
ENDLOOP;
};
Short cut
SetLayout: PUBLIC PROC [cellType: CellType, layoutAtom: ATOM, userDataProp: ATOMNIL, userData: REFNIL] = {
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];
};
Saving "Checkpoints"
Store: PUBLIC PROC [cellType: CellType, withCuteFonts: BOOLFALSE] = {
name: ROPE ← CoreOps.GetCellTypeName[cellType];
layout: Object ← Layout[cellType];
layoutFileName: ROPE ← Rope.Cat[name, "Layout"];
shellFileName: ROPE ← Rope.Cat[name, "Shell"];
shell: 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 ← PipalCore.CreateShell[PipalCore.layoutDecoration, cellType, withCuteFonts];
TerminalIO.PutF["Storing Shell for cell %g ...\n", IO.rope[name]];
[] ← PipalIO.SaveObject[shellFileName, shell];
Layout
TerminalIO.PutF["Storing Layout for cell %g ...\n", IO.rope[name]];
[] ← PipalIO.SaveObject[layoutFileName, layout];
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] = {
obj: Object;
TerminalIO.PutF["Retrieving the Core for cell %g ...\n", IO.rope[name]];
cellType ← CoreIO.RestoreCellType[name];
obj ← PipalCore.GetObject[PipalCore.layoutDecoration, cellType];
SetFromPatchWork[cellType];
TerminalIO.PutF["... core retrieved in %g.core ...\n", IO.rope[name]];
};
Backdoor for clients such as PWCoreLichen
LayoutInfo: PUBLIC PROC [sourceCT: CellType] RETURNS [layout: Object, extractedCT: CellType, extractedToSource: RefTab.Ref, key: INT] = {
FillTable: PROC [sourcePublic: Wire] = {
Action: PROC [extractedTrans: PipalInt.Transformation, extractedPort: Object, value: PipalInstanceTable.Value] = {
extractedWire: Wire = NARROW [value];
prevSource: Wire ← NARROW [RefTab.Fetch[extractedToSource, extractedWire].val];
IF prevSource=sourcePublic THEN RETURN; -- already considered
IF NOT PipalMos.LayoutTouch[PipalMos.LayoutTouch, [], sourcePort, extractedTrans, extractedPort]
THEN RETURN;
IF prevSource#NIL THEN SIGNAL PinsCorrespondingToSeveralPublics[sourceCT, layout, LIST [prevSource, sourcePublic], Pipal.CreateOv[LIST [sourcePort, PipalInt.TransformObject[extractedTrans, extractedPort]]]];
[] ← RefTab.Store[extractedToSource, extractedWire, sourcePublic];
};
sourcePort: Object ← PipalCore.GetPort[PipalCore.layoutDecoration, sourcePublic];
PipalInstanceTable.Enumerate[extractedInstances, Action, PipalInt.BBox[sourcePort, []]];
};
extractedInstances: PipalInstanceTable.Table; -- table instance -> extractedPublic
layout ← Layout[sourceCT];
extractedCT ← NARROW [PipalSinix.Extract[layout, PipalSinix.layoutMode].result];
extractedToSource ← RefTab.Create[]; -- maps extractedWire to source
extractedInstances ← InstanceTableFromPublic[PipalCore.layoutDecoration, PipalInt.BBox[layout, []], extractedCT.public];
key ← GetPatchWorkExtractedCTKey[extractedCT];
CoreOps.VisitRootAtomics[sourceCT.public, FillTable];
};
Creates a table instance -> public
InstanceTableFromPublic: PROC [decoration: PipalCore.Decoration, bbox: PipalInt.Rectangle, public: WireSeq] RETURNS [table: PipalInstanceTable.Table] = {
FillInstanceTable: PROC [wire: Wire] = {
PipalInstanceTable.Insert[table, [], PipalCore.GetPort[decoration, wire], wire];
};
table ← PipalInstanceTable.Create[bbox];
CoreOps.VisitRootAtomics[public, FillInstanceTable];
};
Initialization and various registrations
[] ← RegisterLayoutAtom[$Get, Get, DecorateValue];
[] ← RegisterLayoutAtom[$GetAndFlatten, GetAndFlatten, DecorateValue];
[] ← RegisterLayoutAtom[$Value, Value, DecorateValue];
[] ← RegisterLayoutAtom[$ValueNoDecorate, Value];
[] ← RegisterLayoutAtom[$AbutListXNoDecorate, AbutX];
[] ← RegisterLayoutAtom[$AbutListYNoDecorate, AbutY];
[] ← RegisterLayoutAtom[$RawAbutX, AbutX, DecorateAbutXY];
[] ← RegisterLayoutAtom[$RawAbutY, AbutY, DecorateAbutXY];
[] ← RegisterLayoutAtom[$RawAbutFlipX, AbutFlipXAndDecorate];
[] ← RegisterLayoutAtom[$RawAbutFlipY, AbutFlipYAndDecorate];
[] ← RegisterLayoutAtom[$RawReverseAbutX, ReverseAbutX, DecorateReverseAbut];
[] ← RegisterLayoutAtom[$RawReverseAbutY, ReverseAbutY, DecorateReverseAbut];
[] ← RegisterLayoutAtom[$AbutX, AbutX, DecorateAbutXY, AttributeX];
[] ← RegisterLayoutAtom[$AbutY, AbutY, DecorateAbutXY, AttributeY];
[] ← RegisterLayoutAtom[$Abut, LayoutAbutXorY, DecorateAbutXY, AttributeAbutXorY];
[] ← RegisterLayoutAtom[$ReverseAbutX, ReverseAbutX, DecorateReverseAbut, AttributeX];
[] ← RegisterLayoutAtom[$ReverseAbutY, ReverseAbutY, DecorateReverseAbut, AttributeY];
[] ← RegisterLayoutAtom[$ArrayX, ArrayX, DecorateRecasted];
[] ← RegisterLayoutAtom[$ArrayY, ArrayY, DecorateRecasted];
[] ← RegisterLayoutAtom[$ArrayFlipX, ArrayFlipX, DecorateRecasted];
[] ← RegisterLayoutAtom[$ArrayFlipY, ArrayFlipY, DecorateRecasted];
[] ← RegisterLayoutAtom[$ReverseArrayX, ReverseArrayX, DecorateRecasted];
[] ← RegisterLayoutAtom[$ReverseArrayY, ReverseArrayY, DecorateRecasted];
[] ← RegisterLayoutAtom[$Recast, Recast, DecorateRecasted];
[] ← RegisterLayoutAtom[$FlipX, FlipX, DecorateTransformed];
[] ← RegisterLayoutAtom[$FlipY, FlipY, DecorateTransformed];
[] ← RegisterLayoutAtom[$Rot90, Rot90, DecorateTransformed];
[] ← RegisterLayoutAtom[$Rot180, Rot180, DecorateTransformed];
[] ← RegisterLayoutAtom[$Rot270, Rot270, DecorateTransformed];
END.