<> <> <> <> 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; <> 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; <> 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: ROPE _ NIL] = CODE; <> 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; }; <> layoutAtomProp: PUBLIC ATOM _ CoreProperties.RegisterProperty[$Layout]; GetLayoutAtom: PUBLIC PROC [cellType: CellType] RETURNS [layoutAtom: ATOM _ NIL] = { layoutAtom _ NARROW [CoreProperties.InheritCellTypeProp[cellType, layoutAtomProp]]; }; <> 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]]; }; <> CoreOps.VisitAtomicPairs[to.public, from.public, CopyPins]; }; <> 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]; }; <> 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]; <> IF layoutAtomData.attributesProc#NIL THEN layoutAtomData.attributesProc[cellType]; <> obj _ layoutAtomData.layoutProc[cellType]; IF name#NIL THEN obj _ Pipal.CreateAnnotation[obj, Pipal.nameProp, name]; <> PipalCore.PutObject[PipalCore.layoutDecoration, cellType, obj]; <> IF layoutAtomData.decorateProc#NIL THEN layoutAtomData.decorateProc[cellType, obj]; <> CheckDecorations[cellType, obj]; <> 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]; }; <> <> 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]; }; <> 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]; <> 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]; <> [] _ 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]; }; <> 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]; }; <> SortInX: PUBLIC PROC [pos1, pos2: PipalInt.Position] RETURNS [BOOL] = {RETURN [pos1.xpos2.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> 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]; }; <> 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; <> TerminalIO.PutF["Saving the Core for cell %g ...\n", IO.rope[name]]; [] _ CoreIO.ReportSaveCellType[cellType]; <> 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]; <> 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]]; }; <> 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]; }; < 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]; }; <> [] _ 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. <<>>