DIRECTORY
Core, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties,
IO,
Pipal, PipalCore, PipalInstanceTable, PipalInt, PipalIO, PipalMos, PipalSinix, PipalUI,
PatchWork,
RefTab, Rope, TerminalIO;
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:
ATOM ←
NIL] = {
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: INT ← LOOPHOLE [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:
BOOL ←
FALSE]
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: BOOL ← FALSE; -- 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:
BOOL ←
FALSE] = {
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: BOOL ← FALSE;
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;
};
Saving "Checkpoints"
Store:
PUBLIC
PROC [cellType: CellType, withCuteFonts:
BOOL ←
FALSE] = {
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];