<> <> <> <> <> <> DIRECTORY Atom USING [GetPropFromList, PutPropOnList], CD USING [ApplicationPtr, combined, CreateDrawRef, DrawRectProc, DrawRef, Layer], CDApplications USING [NewApplicationI], CDBasics USING [Intersection, NonEmpty, ToRect], CDOps USING [LayerName], CDOrient USING [original, MapRect], CDPinObjects USING [AppEnumerator, EnumeratePins, GetLayer, GetName, GetOwner], IO USING [RIS, Close, EndOf, Error, SkipWhitespace, STREAM], Rope USING [Cat, Equal, ROPE], SX USING [AddRect, AdjustNode, Circuit, CircuitNode, IllegalLayer, LogicalCell, SignalName, SpinifexLayerIndex], SXAccess, SXAccessInternal, SXAtoms USING [SignalName, spinifexCircuitDescription], SXUserExtract, SymTab USING [Create, Fetch, Ref, Store]; SXUserExtractImpl: CEDAR PROGRAM IMPORTS Atom, Rope, IO, SymTab, CD, CDBasics, CDOrient, CDOps, CDPinObjects, CDApplications, SXAtoms, SX, SXAccess, SXAccessInternal EXPORTS SXUserExtract = BEGIN ConnectionPin: PROCEDURE [app: CD.ApplicationPtr] RETURNS [BOOLEAN] ~ { RETURN [CDPinObjects.GetOwner[app] = NIL AND CDPinObjects.GetLayer[app] # CD.combined] }; DataForRects: TYPE ~ RECORD [ pinLayer: CD.Layer, pinName: Rope.ROPE, cir: REF SX.Circuit, ports: SymTab.Ref ]; TranslateCell: PUBLIC PROCEDURE [cell: REF SX.LogicalCell, CircuitDescription: Rope.ROPE] ~ { AddPinRects: CDPinObjects.AppEnumerator ~ { IF ConnectionPin[app] THEN { dataRef: REF DataForRects _ NEW[DataForRects]; dr: CD.DrawRef ~ CD.CreateDrawRef[NIL]; fakeAppl: CD.ApplicationPtr = CDApplications.NewApplicationI[ob~ cell.cellObj]; fakeAppl.location _ [0, 0]; dr.drawRect _ CaptureGeomInPin; dr.saveRect _ CaptureGeomInPin; dr.devicePrivate _ dataRef; dr.stopFlag _ SXAccess.stopFlag; dr.interestClip _ CDOrient.MapRect[itemInCell~ CDBasics.ToRect[[0,0], app.ob.size], cellSize~ app.ob.size, cellInstOrient~ app.orientation, cellInstPos~ app.location]; dataRef.pinLayer _ CDPinObjects.GetLayer[app]; dataRef.pinName _ CDPinObjects.GetName[app]; dataRef.cir _ cell.circuit; dataRef.ports _ ports; cell.cellObj.p.drawMe[fakeAppl, [0, 0], CDOrient.original, dr ! SX.IllegalLayer => { SXAccessInternal.PutError[ob: cell.cellObj, r: dr.interestClip, message: Rope.Cat["Material on level ", CDOps.LayerName[dataRef.pinLayer], " may not appear as an isolated rectangle.\n"]]; GOTO BadRect } ]; EXITS BadRect => NULL }; quit _ FALSE }; -- end AddPinRects ports: SymTab.Ref ~ SymTab.Create[521]; <<-- Flag this cell for special output handling.>> cell.circuit.properties _ cell.circuit.properties.PutPropOnList[ SXAtoms.spinifexCircuitDescription, SXAtoms.spinifexCircuitDescription]; IF ~ Rope.Equal [CircuitDescription, "()"] THEN { [] _ CDPinObjects.EnumeratePins[cell.cellObj, AddPinRects]; ReadPortOrder[ cell, IO.RIS[CircuitDescription], ports]; <> }; <> <> <> <> }; CaptureGeomInPin: CD.DrawRectProc -- [r: DesignRect, l: Layer, pr: DrawRef] -- ~ { data: REF DataForRects ~ NARROW[pr.devicePrivate]; IF l = data.pinLayer THEN { r _ CDBasics.Intersection[r, pr.interestClip]; IF CDBasics.NonEmpty[r] THEN { <<-- value parameter may be NIL node has not been added yet>> node: REF SX.CircuitNode ~ SX.AddRect[ cir~ data.cir, lev~ l, dim~ r, value~ NARROW[data.ports.Fetch[data.pinName].val]]; IF node # NIL THEN { Layers: TYPE ~ SX.SpinifexLayerIndex; [] _ data.ports.Store[data.pinName, node]; FOR layer: Layers IN [Layers.FIRST .. SXAccess.sxTech.numSpinifexLayers) DO SX.AdjustNode[node, layer, 0, 0, absolute]; ENDLOOP; IF node.properties.GetPropFromList[SXAtoms.SignalName] = NIL THEN node.properties _ node.properties.PutPropOnList[SXAtoms.SignalName, NEW[ SX.SignalName _ [name~ data.pinName]]] }; } } }; ReadPortOrder: PROC [cell: REF SX.LogicalCell, from: IO.STREAM, ports: SymTab.Ref] ~ { <<-- Process SpinifexCircuitDescription property (a ROPE) to determine order of Thyme ports for cell.>> ENABLE IO.Error => { }; DO [] _ from.SkipWhitespace[]; IF from.EndOf[] THEN EXIT; EXIT; ENDLOOP; from.Close[]; }; END. <> <>