• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Custom IC SKILL
  3. Find photonics port angle and location in hierarchy

Stats

  • Locked Locked
  • Replies 7
  • Subscribers 143
  • Views 8315
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Find photonics port angle and location in hierarchy

MSchuldt
MSchuldt over 2 years ago

Hi,

I'm in ICADVM20 doing photonics work, and I'm trying to find the angle and location of one of the ports in a child instance.

I can find the approximate location and angle of a child instance's pin by name (code mostly provided by my awesome AE, Momchil Milev):

procedure( MEPSfindPin( inst pinName )

    let( ( pin pinCoord )

        pin = car( caar( setof( p inst->master->terminals~>pins car( p )->net->name == pinName ) )~>figs )

        pinCoord = centerBox( pin->bBox )

        pinCoord = dbTransformPoint( pinCoord inst->transform )

        pinCoord ) ; end let

    ) ; end findPin

procedure( MEPSfindPinAngle( inst pinName )

    let( ( pin pinAngle )

        pin = car( caar( setof( p inst->master->terminals~>pins car( p )->net->name == pinName ) )~>figs )
        pinAngle  = dbGetPhotonicPinFigAngle( pin )

        ; some magic to transform the angle, based on nth( 1 inst->transform )

        pinAngle ) ; end let

    ) ; end findPinAngle

Some problems with this code:
1) it's returning the location/angle of the polygon pin/port shape, which is snapped to the manufacturing grid.  I'm looking for the centerpoint of the math shape 'under' the drawn shape.  It's a subtle difference, but those fractions of a nm all add up.  And angle the pin angle is rounded to two decimal points (this is done in phoAddWaveguidePorts, apparently).  That's not a close enough approximation of angle for my application.  Is there a way to grab information from down in the math-ier parts of the phoConnectors and the pins they generate?  I've already bugged Momchil about the location part of this, but he's traveling and I'm stuck.
2) Transforming the pin angle if the child instance is added rotated/mirrored - I could write a case statement for every rotation/mirror possibility in inst->transform, but that seems like something an API should do for me (maybe dbTransformAngle to match dbTransformPoint?).

case( nth( 1 inst->transform )

    ( "R90"

        pinAngle += 90.0 )

    ( "R180"

        pinAngle +=180.0 )

    ( etc ... )

    ) ; end case

  • Cancel
  • p94todorov
    p94todorov over 2 years ago

    Hello,

    as far as I know the angle of the photonic pins is being set with the dbSetPhotonicPinFigAngle API and the value returned by the dbGetPhotonicPinFigAngle is simply what has already been specified. This means that you will get whatever has been already set for that pin with the exact same resolution. The same goes for the location of the pin itself - some geometry has been defined as the pin shape and it doesn't have to be a CurvyCore mathematical object at all. It might be a regular db object like a rectangle, ellipse or polygon. This means that unless the pin shape is explicitly attached to a CurvyCore object (generated via ccGenFigs API) you will not be able to retrieve such information. Your best shot is to try the ccGetFromFig API on top of the pin figs already found by the code above. 

    To put what I've said above into some context, the pseudo-code below is absolutely valid example for creating an optical terminal:

    net = dbMakeNet(cv netName)

    pinFig = dbCreateEllipse(cv lpp ellipseBBox)

    ;;; a dbCreateRect / dbCreatePolygon might also work but ellipse can be defined using center and radius, which is an easy to transform geometry and remains the same when transformed - a circle will be the best option since it is equivalent to a geometrical dot. This means that ellipseBBox might be easily defined as:

    ellipseBBox  = list(rodAddPoints(refPt -r:-r) rodAddPoints(refPt r:r))

    So the optical pin can be created by linking everything together:

    pin = dbCreatePin(net pinFig portName)

    and specifying the pin angle direction afterwards:

    dbSetPhotonicPinFigAngle(pinFig pinAngle)

    The same goes for the width of the pin, but in case you are interested in aligning CC objects appropriately in the first place, you definitely will need to use facets. Only they can ensure proper grid snapping for arbitrary device/port orientations. So a full example pseudo-code  for a pin creation would look like this:

    facet = ccCreateFacet(pt ?angle angle ?radius radius ?offsets off1:off2 ?name facetName)

    net = dbMakeNet(cv netName)

    refPt = facet->xy

    ellipseBBox  = list(rodAddPoints(refPt -r:-r) rodAddPoints(refPt r:r))

    pinFig = dbCreateEllipse(cv lpp ellipseBBox)

    dbSetPhotonicPinFigAngle(pinFig facet->angle)

    dbSetPhotonicPinFigWidth(pinFig facet->width)

    I know that this doesn't exactly answer your question, but I wanted to highlight that it really depends on how the optical pins were created in the first place, since it might simply be impossible to retrieve such information. If your optical pins are attached to a facet, all you need for the second part of your question is the ccTransformFacet API. Even if you get the pin angle with the code above, but the facet is not directly attached (as my example above) you can create a dummy facet with the same angle, transform it leveraging the API, return your information of interest and then delete it. As you said, the other way around is to write your own angle transformation function.

    I hope that you will find some of this information helpful.

    Regards,

    Petar

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • MSchuldt
    MSchuldt over 2 years ago in reply to p94todorov

    Ok, a bit more specific, then.  I'm almost entirely using phoStraightConnector and phoBendConnector, with a few phoDeltaConnectors thrown in.  The pins are created by using ?startPortName or ?endPortName in the pho connectors.  There's clearly a facet being created by the connectors, I can see it.  I just can't figure out where it is, or how to query it, or how to query the math under it.

    My problem instance is a very complicated ring.  It's got some number of bend segments, and I'm finding that my start point is not always my end point - I can illustrate this in a piece of code:

    pcDefinePCell(
         list(ddGetObj("test") "badCircle" "layout")
         ( ( segments 10 ) )
         let( ( cv startCoord rotation bigW smallW segAng seg bend1 straight )

            cv = pcCellView

            startCoord = 0.0:0.0
            rotation = 135.0
            bigW = 10.0
            smallW = 1.0
            segAng = 360.0 / float( segments )

            seg = 1
            while( seg <= segments
               bend1 = phoBendConnector( cv "wg1"   
                        ?rotation rotation
                        ?offset startCoord
                        ?startPortName nil
                        ?endPortName nil
                        ?angle segAng
                        ?radius 1000.0

                        ?taperStyle 'linear
                        ?taperStartClamp 1.0
                        ?taperEndClamp 1.0
                        ?startWidth smallW
                        ?endWidth bigW )
                straight = phoStraightConnector( cv "wg2"
                        ?rotation bend1->endPort->facet->angle + 180.0
                        ?offset bend1->endPort->xy
                        ?startPortName nil
                        ?endPortName nil
                        ?length 100.0
                        ?taperStyle 'linear
                        ?taperStartClamp 1.0
                        ?taperEndClamp 1.0
                        ?startWidth bigW
                        ?endWidth smallW )
                startCoord = straight->endPort->xy
                rotation = straight->endPort->facet->angle + 180.0
                seg += 1
                ) ; end while
             ) ; end let
        ) ; end pcell

    If you place the instance and start increasing the number of segments, you can see that the native rounding from facet->angle and endPort->xy are not quite good enough in this application.  14 was particularly bad.  And then I want to throw in some hierarchy as well.  So imagine a ring that is a combination of phoBendConnector, phoStraightConnector, and an assortment of pcell wrappers around phoBend and phoStraight connectors.

    I have a partial fix, but only if I want to switch over to the cc connectors (which I don't).  I haven't tried this through hierarchy, but it does fix badCircle if I swap over to cc connectors.  Helpful code provided by Momchil and Cadence R&D.

    (defun getConnectorEndPoint (connector)
       (let ((segment (car (last (get (get connector 'connector) 'segments)))))
         (ccGetCurvePoint segment (cadr (get (car segment) 'range)))))

    (defun getConnectorEndAngle (connector)
       (let ((segment (car (last (get (get connector 'connector) 'segments)))))
         (let ((tangent (ccGetCurveDerivative segment (cadr (get (car segment) 'range)))))
           (atan2 (cadr tangent) (car tangent)) * 45.0 / atan(1))))

    What I'm looking for is a way to do something like this, but for the pho conenctors.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • p94todorov
    p94todorov over 2 years ago in reply to MSchuldt

    Well,

    my knowledge is a bit limited, but it looks like only a Cadence representative might be able to help you with that.

    You want to use the connector functions with already existing Waveguide tempaltes defined in the techfile. The only way to ensure proper closed curve is within the ccCreatePolyCurve API when specifying the close attribute , but this is much lower-level approach.

    I think that I can only confirm the observations that you already had or Momchil has provided to you.

    I might play around though, since I am curious as well how this can be addressed and will get back to you in case I find a more elegant way.

    Regards,

    Petar 

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • p94todorov
    p94todorov over 2 years ago in reply to p94todorov

    Hello,

    as it usually happens, it turns out that there is a trivial solution to the problem.
    There is no need to think about the facets, ports and trying to get the information from previous segments. It will be good if Cadence can update their infrastructure so we can access this information without it being rounded and losing accuracy, but for your particular example you can bypass this by explicitly incrementing the segment start angles as follows:

    pcDefinePCell(
         list(ddGetObj("test") "badCircle" "layout")
         ( ( segments 10 ) )
         let( ( cv startCoord rotation bigW smallW segAng seg bend1 straight )

            cv = pcCellView

            startCoord = 0.0:0.0
            rotation = 135.0
            bigW = 10.0
            smallW = 1.0
            segAng = 360.0 / float( segments )

            seg = 1
            while( seg <= segments
               bend1 = phoBendConnector( cv "wg1"   
                        ?rotation rotation
                        ?offset startCoord
                        ?startPortName nil
                        ?endPortName nil
                        ?angle segAng
                        ?radius 1000.0

                        ?taperStyle 'linear
                        ?taperStartClamp 1.0
                        ?taperEndClamp 1.0
                        ?startWidth smallW
                        ?endWidth bigW )
                straight = phoStraightConnector( cv "wg2"
                        ?rotation rotation+segAng
                        ?offset bend1->endPort->xy
                        ?startPortName nil
                        ?endPortName nil
                        ?length 100.0
                        ?taperStyle 'linear
                        ?taperStartClamp 1.0
                        ?taperEndClamp 1.0
                        ?startWidth bigW
                        ?endWidth smallW )
                startCoord = straight->endPort->xy
                rotation += segAng
                seg += 1
                ) ; end while
             ) ; end let
        ) ; end pcell

    This seems to address the observed issue on my side and I hope it will be suitable for you as well.

    Regards,

    Petar

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • MSchuldt
    MSchuldt over 2 years ago in reply to p94todorov

    Ah, that is the trouble with submitting a simple version of a complicated problem... trivial solutions abound.  But the complicated problems have IP in them, so I can't share.

    You might have solved the real problem, though.  Maybe I can calculate angle.  I should be able to figure out what my arc length is in this situation, and I know my bendRad.  I'll just cross my fingers that that arc length stays standard, no one has asked to customize it yet.

    But I'd still love to be able to dig out the facet/math.

    Thank you!

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
  • p94todorov
    p94todorov over 2 years ago in reply to MSchuldt

    I am glad to hear that this might be working. I don't know what types of bends your IP has, but at least for what I've been working on I realized that decoupling the math from the facets/ccObjects sometimes works better. For example if I could integrate the length of a parametric curve, I do so instead of relying on an API to do the job. It's definitely faster and less prone to rounding errors as long as I keep enough significant digits in all coefficients. For Circular and Bezier bends this is trivial, but there might not be an easy way around for Clothoids or some hybrid approaches.

    I've also observed that most of the differences are purely mathematical and I don't expect anything measurable when it snaps to the design grid. I would say that tweaking a Bezier polynomial to some "parameterized topology" can represent closely any bend curve, which you can subsequently relatively easy integrate. 

    Regards,

    Petar

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • MSchuldt
    MSchuldt over 2 years ago in reply to p94todorov

    It's actually not a complicated curve right now, which is what saves me in this application.  I'm using a taper from my ring coupling region to my non-coupling region for... reasons.  That taper happens once the ring waveguide is a defined distance from the bus waveguide.  But with different taper lengths, bend radii, and waveguide widths, I don't necessarily know what angle I'm at when I hit the end of my taper, so I was trying to pull the angle and location from the prior segment.  But in this application I can find my arclength, which will give me angle since I know bendRad and what location/angle the taper starts.
    But of course, the moment that we want a complex coupling region all of this goes in the bin and I need a better approach.  It's also probably one of those 'wow, you've got a lot of wavelengths' problems that are not quite applicable to most users right now.  Different wavelengths have different taper lengths, bend radii, waveguide widths, so my pcells take wavelength as a parameter and pull a bunch of wavelength-specific information from the techfile for bend radius, taper length, waveguide width, etc.  It's the best I've come up with so far, but writing the perfect pcell for 350nm-8mm is... interesting.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information