• 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. updating code to include pathSeg width for formula calculation...

Stats

  • Locked Locked
  • Replies 7
  • Subscribers 143
  • Views 16235
  • 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

updating code to include pathSeg width for formula calculation.

Carona
Carona over 5 years ago

I have an old code I used to calculate the current capacity and resistance of a path or rectangle in virtuoso.

However now we predominantly use wires (pathSeg) and I tried to just replace path with pathSeg in my code, but it doesn't appear to be as straight forward as that.

I was wondering if someone could help, I figure it should be pretty straight forward to grab and pass along the width of a pathSeg, but I guess I missing something. Thanks in advance.

Here is a sample of the code I am using....  I enlarged the sections where I previously grabbed the width of a path, ideally it would be great to grab the width from either a path or pathSeg

procedure(AFigCurDens(figList)
prog((techVal m0JMax m1JMax m2JMax m3JMax m4JMax m5JMax m6JMax m7JMax m8JMax m9JMax m10JMax layerName
figWidth ll ur jMax figCurrent)
techVal = "foundarytech"
case(techVal
("foundarytech" || "foundarytech2"
;mA/um (width)
m0JMax = 1 ;
m1JMax = 2 ;
m2JMax = 3
m3JMax = 4
m4JMax = 5
m5JMax = 6
m6JMax = 7
m8JMax = 8
m9JMax = 9
m10JMax = 10
)
); case

foreach(fig figList
layerName = fig->layerName

if(fig->objType == "path" then
figWidth = fig->width
else
ll = car(fig~>bBox)
ur = cadr(fig~>bBox)
figWidth = abs(yCoord(ll) - yCoord(ur))
)

case(layerName
("M0"
jMax = m0JMax
)
("M1"
jMax = m1JMax
)
("M2"
jMax = m2JMax
)
("M3"
jMax = m3JMax
)
("M4"
jMax = m4JMax
)
("M5"
jMax = m5JMax
)
("M6"
jMax = m6JMax
)
("M7"
jMax = m7JMax
)
("M8"
jMax = m8JMax
)
("M9"
jMax = m9JMax
)
("M10"
jMax = m10JMax
)
); case


figCurrent = jMax*figWidth*1 


if(fig->objType == "path" then
printf("Max Current of %s path is: %gmA\n" layerName figCurrent)
else
printf("Max Current of %s rectangle is: %gmA\n" layerName figCurrent)
)

); foreach

); prog
); proc

  • Cancel
Parents
  • Andrew Beckett
    Andrew Beckett over 5 years ago

    Given that pathSegs also have a width attribute, you should be able to just change the if lines to:

    if(fig->objType == "path" || fig~>objType == "pathSeg" then

    Regards,

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Carona
    Carona over 5 years ago in reply to Andrew Beckett

    Thank you Andrew, that was pretty straight forward, however further along in my code, I am getting stuck with the area calculation portion.

    I added in BOLD my new portion of the code that should cover the pathSeg option, however every time I have a pathSeg selected I get the following warning, "Object must be a Wire, polygon or rectangle" which I also highlighted in BOLD, so it seems to not being recognized as intended. I get (nil)/width in my calculations.  Appreciate any help in resolving this, it would be great to get this working with wires and I feel I am only a few steps away from getting it up and running. You guys are always so excellent at pinpointing exactly what the issue is. Thanks. Let me know if you need more info, or the complete code to see the whole picture.

    Its just very long with lots of pieces, so I figured it was easier to break it down by sections.

    ;Area calculation (for fig calcs)
    procedure(AGeomArea(@key (figLength nil) (printLine t) (fig nil))
    prog((sSet lyr_name sum crd lastPt firstPt crdList area
    corners ll ur dx dy shape width endShp diax diay
    diay radx rady pLength)
    when(!ALayoutWindowCheck(t)
    return(nil)
    )

    if(fig == nil then
    sSet = geGetSelSet( hiGetCurrentWindow())
    else
    sSet = fig
    )

    if( sSet == nil then
    ADialogs( "error"
    "A single object must be pre-selected"
    )
    return( nil)
    )

    if( car(sSet)~>type != "geomInst" then
    ADialogs( "error"
    "Object must be a Wire, polygon or rectangle"
    )
    return( nil)
    )

    shape = car(sSet)~>shape

    if(figLength && shape != "path" && shape != "pathSeg" && shape != "rectangle" then
    ADialogs("error"
    "Object must be a path or rectangle"
    )
    return(nil)
    )

    lyr_name = techGetLayerName(
    techGetTechFile(geGetEditCellView()) car(sSet)~>layer)

    case( shape
    ("polygon"
    crdList = car(sSet)~>path
    sum = 0
    firstPt = lastPt = car(crdList)
    crdList = cdr(crdList)
    foreach(crd crdList
    sum = sum + ((xCoord(crd) - xCoord(lastPt))
    * (yCoord(crd) + yCoord(lastPt)))
    lastPt = crd
    )
    sum = sum + ((xCoord(firstPt) - xCoord(lastPt))
    * (yCoord(firstPt) + yCoord(lastPt)))
    area = 0.5 * abs(sum)
    printf("The area for this %s polygon is: %f\n" lyr_name area)
    )
    ("rectangle"
    corners = car(sSet)~>bBox
    ll = car(corners)
    ur = cadr(corners)
    dx = xCoord(ll) - xCoord(ur)
    dy = yCoord(ll) - yCoord(ur)
    fLength = abs(dx)
    area = abs( dx * dy )
    when(printLine
    printf("The area for this %s rectangle is: %f\n" lyr_name area)
    printf("Length: %n\n" abs(dx))
    printf("Width: %n\n" abs(dy))
    ); when

    when(figLength
    return(fLength)
    )
    )
    ("path"
    crdList = car(sSet)~>path
    width = car(sSet)~>width
    endShp = car(sSet)~>pathShape
    if(endShp == "bothArrowEnded" ||
    endShp == "singleArrowEnded" then
    ADialogs("warning"
    "Path must have square or octagon ends."
    )
    return(nil)
    );if
    if(figLength then
    if(printLine then
    printf( "The length for this %s path is: %f\n " lyr_name
    car(APathArea( crdList width endShp )))
    )
    pLength = car(APathArea( crdList width endShp ))
    return(pLength)
    else
    area = cadr(APathArea( crdList width endShp ))
    printf( "The area for this %s path is: %f\n" lyr_name
    area)
    printf( "The length for this %s path is: %f\n " lyr_name
    car(APathArea( crdList width endShp )))
    )
    )
    ("pathSeg"
    crdList = car(sSet)~>pathSeg
    width = car(sSet)~>width
    endShp = car(sSet)~>pathShape
    if(endShp == "bothArrowEnded" ||
    endShp == "singleArrowEnded" then
    ADialogs("warning"
    "Wire must have square or octagon ends."
    )
    return(nil)
    );if
    if(figLength then
    if(printLine then
    printf( "The length for this %s wire is: %f\n " lyr_name
    car(APathArea( crdList width endShp )))
    )
    pLength = car(APathArea( crdList width endShp ))
    return(pLength)
    else
    area = cadr(APathArea( crdList width endShp ))
    printf( "The area for this %s wire is: %f\n" lyr_name
    area)
    printf( "The length for this %s wire is: %f\n " lyr_name
    car(APathArea( crdList width endShp )))
    )
    )
    ("ellipse"
    llBox = caar(sSet~>bBox)
    urBox = cadar(sSet~>bBox)
    /*
    Due to the precision of the database and the accuracy of the conic
    circle generator, we have some discrepancies especially on large figures
    that will throw out the x and y calculation to be different on the bBox
    dimensions.
    */
    diax = round(1000*(xCoord(urBox) - xCoord(llBox) + 0.0005))
    diay = round(1000*(yCoord(urBox) - yCoord(llBox) + 0.0005))
    if(diax == diay then
    radx = diax/2000.0
    area = 3.14159*radx**2
    printf("Area of circle is %f.\n" area)
    else
    radx = diax/2000.0
    rady = diay/2000.0
    area = 3.14159*radx*rady
    printf("Area of ellipse is %f.\n" area)
    )
    )
    ("donut"
    area = 3.14159*(car(sSet)~>outerRadius**2 - car(sSet)~>innerRadius**2)
    printf("Area of donut is %f.\n" area)
    )
    );case
    return(area)
    ); prog
    ); proc

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to Carona

    This was pretty hard to follow with the lack of indentation, so I ran it through a formatter utility I have to indent it. I then found a couple of sections of the code which are using ancient (30 year old, from Edge - so pre-DFII) attributes which are not supported for modern objects. A little bit of debugging on your end ought to have found where it was going wrong. I can't be sure the rest of the code works because I'm missing some of the functions (I implemented a few to test quickly, but I don't know what APathArea does, for example). See my comments with ANDREW in to see what I changed.

    ;Area calculation (for fig calcs)
    procedure(AGeomArea(@key (figLength nil) (printLine t) (fig nil))
      prog(sSet(lyr_name
                sum
                crd
                lastPt
                firstPt
                crdList
                area
                corners
                ll
                ur
                dx
                dy
                shape
                width
                endShp
                diax
                diay
                diay
                radx
                rady
                pLength
               )
           when(null(ALayoutWindowCheck(t))
             return(nil)
            )
           
           if(fig == nil
               then
                   sSet = geGetSelSet(hiGetCurrentWindow())
               else
                   sSet = fig
              )
           
           if(sSet == nil
               then
                   ADialogs("error" "A single object must be pre-selected")
                   return(nil)
              )
           
           ; ANDREW - the ~>type is an undocumented attribute that is
           ; a legacy hangover from Edge (i.e. the 2.4 releases from 30 years ago)
           ; It doesn't show up if you do obj~>? and returns nil for newer objects
           ; like pathSeg. So use the isShape attribute instead
           ;car(sSet)~>type != "geomInst"
           if(!car(sSet)~>isShape
               then
                   ADialogs("error" "Object must be a Wire, polygon or rectangle")
                   return(nil)
              )
           
           ; ANDREW - similarly ~>shape is an undocumented attribute that 
           ; cannot be relied upon
           ;shape = car(sSet)~>shape
           shape = car(sSet)~>objType
           
           if(figLength && (shape != "path") && (shape != "pathSeg") && (shape != "rectangle")
               then
                   ADialogs("error" "Object must be a path or rectangle")
                   return(nil)
              )
           
           lyr_name = techGetLayerName(techGetTechFile(geGetEditCellView())
                                       car(sSet)~>layer
                                      )
           
           case( shape
             ("polygon"
              crdList = car(sSet)~>path
              sum = 0
              firstPt = lastPt = car(crdList)
              crdList = cdr(crdList)
              foreach(crd crdList
                sum = sum + ((xCoord(crd) - xCoord(lastPt)) * (yCoord(crd) + yCoord(lastPt)))
                lastPt = crd
               )
              sum = sum + ((xCoord(firstPt) - xCoord(lastPt)) * (yCoord(firstPt) + yCoord(lastPt)))
              area = 0.5 * abs(sum)
              printf("The area for this %s polygon is: %f\n" lyr_name area)
             )
             ("rectangle"
              corners = car(sSet)~>bBox
              ll = car(corners)
              ur = cadr(corners)
              dx = xCoord(ll) - xCoord(ur)
              dy = yCoord(ll) - yCoord(ur)
              fLength = abs(dx)
              area = abs(dx * dy)
              when(printLine
                printf("The area for this %s rectangle is: %f\n" lyr_name area)
                printf("Length: %n\n" abs(dx))
                printf("Width: %n\n" abs(dy))
               ) ; when
              
              when(figLength
                return(fLength)
               )
             )
             ("path"
              crdList = car(sSet)~>path
              width = car(sSet)~>width
              endShp = car(sSet)~>pathShape
              if((endShp == "bothArrowEnded") || (endShp == "singleArrowEnded")
                  then
                      ADialogs("warning" "Path must have square or octagon ends.")
                      return(nil)
                 ) ;if
              if(figLength
                  then
                      if(printLine
                          then
                              printf("The length for this %s path is: %f\n "
                                     lyr_name
                                     car(APathArea(crdList width endShp))
                                    )
                         )
                      pLength = car(APathArea(crdList width endShp))
                      return(pLength)
                  else
                      area = cadr(APathArea(crdList width endShp))
                      printf("The area for this %s path is: %f\n" lyr_name area)
                      printf("The length for this %s path is: %f\n "
                             lyr_name
                             car(APathArea(crdList width endShp))
                            )
                 )
             )
             ("pathSeg"
              crdList = car(sSet)~>pathSeg
              width = car(sSet)~>width
              endShp = car(sSet)~>pathShape
              if((endShp == "bothArrowEnded") || (endShp == "singleArrowEnded")
                  then
                      ADialogs("warning" "Wire must have square or octagon ends.")
                      return(nil)
                 ) ;if
              if(figLength
                  then
                      if(printLine
                          then
                              printf("The length for this %s wire is: %f\n "
                                     lyr_name
                                     car(APathArea(crdList width endShp))
                                    )
                         )
                      pLength = car(APathArea(crdList width endShp))
                      return(pLength)
                  else
                      area = cadr(APathArea(crdList width endShp))
                      printf("The area for this %s wire is: %f\n" lyr_name area)
                      printf("The length for this %s wire is: %f\n "
                             lyr_name
                             car(APathArea(crdList width endShp))
                            )
                 )
             )
             ("ellipse"
              llBox = caar(sSet~>bBox)
              urBox = cadar(sSet~>bBox)
              /*
    	  Due to the precision of the database and the accuracy of the conic
    	  circle generator, we have some discrepancies especially on large figures
    	  that will throw out the x and y calculation to be different on the bBox
    	  dimensions.
    	  */ 
              diax = round(1000 * ((xCoord(urBox) - xCoord(llBox)) + 0.0005))
              diay = round(1000 * ((yCoord(urBox) - yCoord(llBox)) + 0.0005))
              if(diax == diay
                  then
                      radx = diax / 2000.0
                      area = 3.14159 * expt(radx 2)
                      printf("Area of circle is %f.\n" area)
                  else
                      radx = diax / 2000.0
                      rady = diay / 2000.0
                      area = 3.14159 * radx * rady
                      printf("Area of ellipse is %f.\n" area)
                 )
             )
             ("donut"
              area = 3.14159 * (expt(car(sSet)~>outerRadius 2) - expt(car(sSet)~>innerRadius
                                                                      2
                                                                     ))
              printf("Area of donut is %f.\n" area)
             )
            )
            ;case
           return(area)
          ) ; prog
     ) ; proc
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to Carona

    This was pretty hard to follow with the lack of indentation, so I ran it through a formatter utility I have to indent it. I then found a couple of sections of the code which are using ancient (30 year old, from Edge - so pre-DFII) attributes which are not supported for modern objects. A little bit of debugging on your end ought to have found where it was going wrong. I can't be sure the rest of the code works because I'm missing some of the functions (I implemented a few to test quickly, but I don't know what APathArea does, for example). See my comments with ANDREW in to see what I changed.

    ;Area calculation (for fig calcs)
    procedure(AGeomArea(@key (figLength nil) (printLine t) (fig nil))
      prog(sSet(lyr_name
                sum
                crd
                lastPt
                firstPt
                crdList
                area
                corners
                ll
                ur
                dx
                dy
                shape
                width
                endShp
                diax
                diay
                diay
                radx
                rady
                pLength
               )
           when(null(ALayoutWindowCheck(t))
             return(nil)
            )
           
           if(fig == nil
               then
                   sSet = geGetSelSet(hiGetCurrentWindow())
               else
                   sSet = fig
              )
           
           if(sSet == nil
               then
                   ADialogs("error" "A single object must be pre-selected")
                   return(nil)
              )
           
           ; ANDREW - the ~>type is an undocumented attribute that is
           ; a legacy hangover from Edge (i.e. the 2.4 releases from 30 years ago)
           ; It doesn't show up if you do obj~>? and returns nil for newer objects
           ; like pathSeg. So use the isShape attribute instead
           ;car(sSet)~>type != "geomInst"
           if(!car(sSet)~>isShape
               then
                   ADialogs("error" "Object must be a Wire, polygon or rectangle")
                   return(nil)
              )
           
           ; ANDREW - similarly ~>shape is an undocumented attribute that 
           ; cannot be relied upon
           ;shape = car(sSet)~>shape
           shape = car(sSet)~>objType
           
           if(figLength && (shape != "path") && (shape != "pathSeg") && (shape != "rectangle")
               then
                   ADialogs("error" "Object must be a path or rectangle")
                   return(nil)
              )
           
           lyr_name = techGetLayerName(techGetTechFile(geGetEditCellView())
                                       car(sSet)~>layer
                                      )
           
           case( shape
             ("polygon"
              crdList = car(sSet)~>path
              sum = 0
              firstPt = lastPt = car(crdList)
              crdList = cdr(crdList)
              foreach(crd crdList
                sum = sum + ((xCoord(crd) - xCoord(lastPt)) * (yCoord(crd) + yCoord(lastPt)))
                lastPt = crd
               )
              sum = sum + ((xCoord(firstPt) - xCoord(lastPt)) * (yCoord(firstPt) + yCoord(lastPt)))
              area = 0.5 * abs(sum)
              printf("The area for this %s polygon is: %f\n" lyr_name area)
             )
             ("rectangle"
              corners = car(sSet)~>bBox
              ll = car(corners)
              ur = cadr(corners)
              dx = xCoord(ll) - xCoord(ur)
              dy = yCoord(ll) - yCoord(ur)
              fLength = abs(dx)
              area = abs(dx * dy)
              when(printLine
                printf("The area for this %s rectangle is: %f\n" lyr_name area)
                printf("Length: %n\n" abs(dx))
                printf("Width: %n\n" abs(dy))
               ) ; when
              
              when(figLength
                return(fLength)
               )
             )
             ("path"
              crdList = car(sSet)~>path
              width = car(sSet)~>width
              endShp = car(sSet)~>pathShape
              if((endShp == "bothArrowEnded") || (endShp == "singleArrowEnded")
                  then
                      ADialogs("warning" "Path must have square or octagon ends.")
                      return(nil)
                 ) ;if
              if(figLength
                  then
                      if(printLine
                          then
                              printf("The length for this %s path is: %f\n "
                                     lyr_name
                                     car(APathArea(crdList width endShp))
                                    )
                         )
                      pLength = car(APathArea(crdList width endShp))
                      return(pLength)
                  else
                      area = cadr(APathArea(crdList width endShp))
                      printf("The area for this %s path is: %f\n" lyr_name area)
                      printf("The length for this %s path is: %f\n "
                             lyr_name
                             car(APathArea(crdList width endShp))
                            )
                 )
             )
             ("pathSeg"
              crdList = car(sSet)~>pathSeg
              width = car(sSet)~>width
              endShp = car(sSet)~>pathShape
              if((endShp == "bothArrowEnded") || (endShp == "singleArrowEnded")
                  then
                      ADialogs("warning" "Wire must have square or octagon ends.")
                      return(nil)
                 ) ;if
              if(figLength
                  then
                      if(printLine
                          then
                              printf("The length for this %s wire is: %f\n "
                                     lyr_name
                                     car(APathArea(crdList width endShp))
                                    )
                         )
                      pLength = car(APathArea(crdList width endShp))
                      return(pLength)
                  else
                      area = cadr(APathArea(crdList width endShp))
                      printf("The area for this %s wire is: %f\n" lyr_name area)
                      printf("The length for this %s wire is: %f\n "
                             lyr_name
                             car(APathArea(crdList width endShp))
                            )
                 )
             )
             ("ellipse"
              llBox = caar(sSet~>bBox)
              urBox = cadar(sSet~>bBox)
              /*
    	  Due to the precision of the database and the accuracy of the conic
    	  circle generator, we have some discrepancies especially on large figures
    	  that will throw out the x and y calculation to be different on the bBox
    	  dimensions.
    	  */ 
              diax = round(1000 * ((xCoord(urBox) - xCoord(llBox)) + 0.0005))
              diay = round(1000 * ((yCoord(urBox) - yCoord(llBox)) + 0.0005))
              if(diax == diay
                  then
                      radx = diax / 2000.0
                      area = 3.14159 * expt(radx 2)
                      printf("Area of circle is %f.\n" area)
                  else
                      radx = diax / 2000.0
                      rady = diay / 2000.0
                      area = 3.14159 * radx * rady
                      printf("Area of ellipse is %f.\n" area)
                 )
             )
             ("donut"
              area = 3.14159 * (expt(car(sSet)~>outerRadius 2) - expt(car(sSet)~>innerRadius
                                                                      2
                                                                     ))
              printf("Area of donut is %f.\n" area)
             )
            )
            ;case
           return(area)
          ) ; prog
     ) ; proc
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
  • Carona
    Carona over 5 years ago in reply to Andrew Beckett

    Thanks again, the code partially works now, wires now give results, however there must still be some old attributes breaking things, I get expected results when I use paths and I change their lengths, the resistance scales. However, when I try and use rectangles or wires, I get the following...

    *Error* fprintf/sprintf: format spec. incompatible with data - "Format is 'The length for this %s wire is: %f\n ', argument #2 is 0"

    Rectangles previously worked.

    The length of these types are not being processed.  I will just give you the complete code I am working with so it will be easier for you to see all the functions being used.  I  but arbitrary numbers in for sheet Res etc, As always, your help is most appreciated, this will be a useful tool to have working going forward. Sorry for my poor indentation, I only dable here and there in skill. Let me know if I missed anything, or if anything is unclear

    /***********************************************
    Calculation form : Shift<Key>i
    ************************************************/

    ;Fig Calcs

    procedure(ALaunchFigCalcs()
    unless(boundp('AFigCalcsForm) && hiIsForm(AFigCalcsForm)
    ACreateFigCalcsForm()
    )

    unless(hiIsFormDisplayed(AFigCalcsForm)
    hiDisplayForm(AFigCalcsForm)
    )
    ); proc


    procedure(ACreateFigCalcsForm()
    let((resCur irDrop label current figOpts sep1 irDropOpts
    irLength irWidth metLayers voltage)
    figOpts = hiCreateRadioField(
    ?name 'figOpts
    ?prompt "Options"
    ?choices list("Res/Current" "IR Drop")
    ?value "Res/Current"
    ?callback '("AFigCalcsDefCB(\"figOpts\")")
    )
    sep1 = hiCreateSeparatorField(
    ?name 'sep1
    )
    label = hiCreateLabel(
    ?name 'label
    ?labelText "IR Drop"
    )
    irDropOpts = hiCreateCyclicField(
    ?name 'irDropOpts
    ?prompt "Calculate"
    ?choices '("Width" "Length" "Voltage Drop")
    ?value "Voltage Drop"
    ?enabled nil
    ?callback "AFigCalcsDefCB(\"irDropOpts\")"
    )

    irLength = hiCreateStringField(
    ?name 'irLength
    ?prompt "Length (u)"
    ?defValue ""
    ?enabled nil
    )

    irWidth = hiCreateStringField(
    ?name 'irWidth
    ?prompt "Width (u)"
    ?defValue ""
    ?enabled nil
    )
    metLayers = hiCreateToggleField(
    ?name 'metLayers
    ?prompt "Metal Layers"
    ?choices list('(m1) '(m2) '(m3) '(m4) '(m5) '(m6) '(m7) '(m8) '(m9) '(m10) '(m11) '(m12) '(m13) '(AP))
    ?value '(t t t t t t t t t t t t t t)
    ?numSelect 14
    ?enabled nil
    )
    current = hiCreateStringField(
    ?name 'currentVal
    ?prompt "Current (mA)"
    ?defValue ""
    ?enabled nil
    )

    voltage = hiCreateStringField(
    ?name 'voltVal
    ?prompt "Voltage Drop (mV)"
    ?defValue ""
    ?enabled nil
    )

    hiCreateAppForm(
    ?name 'AFigCalcsForm
    ?fields list(
    figOpts
    sep1
    label
    irDropOpts
    irLength
    irWidth
    metLayers
    current
    voltage
    )
    ?formTitle "Fig Calculations"
    ?callback "AFigCalcsCB()"
    )
    ); let
    ); proc

    procedure(AFigCalcsDefCB(args)
    let((form)
    form = hiGetCurrentForm()
    case(args
    ("figOpts"
    if(form->figOpts->value == "IR Drop" then
    form->irDropOpts->enabled = t
    form->metLayers->enabled = t
    form->currentVal->enabled = t
    case(form->irDropOpts->value
    ("Width"
    form->irLength->enabled = t
    form->voltVal->enabled = t
    )
    ("Length"
    form->irWidth->enabled = t
    form->voltVal->enabled = t
    )
    ("Voltage Drop"
    form->irWidth->enabled = t
    form->irLength->enabled = t
    )
    ); case
    else
    form->irDropOpts->enabled = nil
    form->irWidth->enabled = nil
    form->irLength->enabled = nil
    form->metLayers->enabled = nil
    form->currentVal->enabled = nil
    form->voltVal->enabled = nil
    )
    )
    ("irDropOpts"
    if(form->irDropOpts->value == "Voltage Drop" then
    form->voltVal->enabled = nil
    else
    form->voltVal->enabled = t
    )

    if(form->irDropOpts->value == "Width" then
    form->irWidth->enabled = nil
    else
    form->irWidth->enabled = t
    )

    if(form->irDropOpts->value == "Length" then
    form->irLength->enabled = nil
    else
    form->irLength->enabled = t
    )
    )
    ); case
    ); let
    ); proc

    procedure(AFigCalcsCB()
    prog((fig1 figList form setWarn figCheck layerCheck)
    figCheck = 0
    layerCheck = 0
    form = hiGetCurrentForm()

    when(form->figOpts->value == "Res/Current"
    when(!ALayoutWindowCheck(t)
    return(nil)
    )

    figList = geGetSelectedSet()

    foreach(fig figList
    when(fig~>objType != "path" && fig~>objType != "pathSeg" && fig~>objType != "rect"
    figCheck = 1
    )
    when( fig~>layerName != "M1" &&
    fig~>layerName != "M2" &&
    fig~>layerName != "M3" &&
    fig~>layerName != "M4" &&
    fig~>layerName != "M5" &&
    fig~>layerName != "M6" &&
    fig~>layerName != "M7" &&
    fig~>layerName != "M8" &&
    fig~>layerName != "M9" &&
    fig~>layerName != "M10" &&
    fig~>layerName != "M11" &&
    fig~>layerName != "M12" &&
    fig~>layerName != "M13" &&
    fig~>layerName != "AP"
    layerCheck = 1
    )
    ); foreach

    when(figCheck == 1
    ADialogs("error"
    "Selected set contains objects which are not wires or rectangles")
    figCheck = 0
    return(nil)
    )

    when(layerCheck == 1
    ADialogs("error"
    "Selected Set contains objects not drawn on metal layers")
    layerCheck = 0
    return(nil)
    )

    AFigRes(figList)
    AFigCurDens(figList)
    ); when


    when(form->figOpts->value == "IR Drop"
    APathIRDrop(figList)
    )

    ); prog
    ); proc

    procedure(APathIRDrop(figList)
    prog((form count metCount metLayersList totalRes sheetRes irLength irWidth
    currentVal metLayers irDrop irDropMv techVal)
    form = hiGetCurrentForm()
    count = 1
    metCount = 0
    metLayersList = list()
    totalRes = 0
    sheetRes = 0
    techVal = "foundarytech"

    ;Field checks
    when( !member(t form->metLayers->value) ||
    form->currentVal->value == "" ||
    form->currentVal->value == nil
    ADialogs("warning" "Specify necessary values on form")
    return(nil)
    )

    currentVal = aelNumber(form->currentVal->value)
    metLayers = form->metLayers->value
    foreach(val metLayers
    when(val == t
    metCount = metCount + 1
    metLayersList = cons(strcat("M" || "AP" printstring(count)) metLayersList)
    )
    count = count + 1
    )

    foreach(metLayer metLayersList
    case(metLayer
    ("M1"
    case(techVal
    ("foundarytech"|
    sheetRes = 1
    )
    )
    )
    ("M2" || "M3"
    case(techVal
    ("foundarytech"
    sheetRes = 2
    )
    )
    )
    ("M4"
    case(techVal
    ("foundarytech"
    sheetRes = 4
    )
    )
    )
    ("M5" || "M6" || "M7" || "M8"
    case(techVal
    ("foundarytech"
    sheetRes = .5
    )
    )
    )
    ("M9" || "M10"
    case(techVal
    ("foundarytech"
    sheetRes = .2
    )
    )
    )
    ("M11" || "M12"
    case(techVal
    ("foundarytech"
    sheetRes = .1
    )
    )
    )
    ("M13"
    case(techVal
    ("foundarytech"
    sheetRes = 0.01
    )
    )
    )

    ("AP"
    case(techVal
    ("foundarytech"
    sheetRes = 0.025
    )
    )
    )
    ); case
    if(metCount == 1 then
    totalRes = sheetRes
    else
    when(metCount > 1
    totalRes = totalRes + (1/sheetRes)
    )
    )
    ); foreach

    when(metCount > 1
    totalRes = 1/totalRes
    )

    case(form->irDropOpts->value
    ("Voltage Drop"
    when(form->irLength->value == "" ||
    form->irLength->value == nil ||
    form->irWidth->value == "" ||
    form->irWidth->value == nil
    ADialogs("warning" "Specify necessary values on form")
    return(nil)
    )
    irLength = aelNumber(form->irLength->value)
    irWidth = aelNumber(form->irWidth->value)
    irDrop = (irLength/irWidth) * totalRes * currentVal
    printf("IR Drop across metal stack is %gmV\n" irDrop)
    when(irDrop > 30
    ADialogs("warning" "IR Drop is greater than 30mV")
    )
    )
    ("Length"
    when(form->irWidth->value == "" ||
    form->irWidth->value == nil ||
    form->voltVal->value == "" ||
    form->voltVal->value == nil
    ADialogs("warning" "Specify necessary values on form")
    return(nil)
    )
    irWidth = aelNumber(form->irWidth->value)
    irLength = 0.0
    irDrop = aelNumber(form->voltVal->value)
    irLength = (irDrop*irWidth)/(totalRes*currentVal)
    printf("Length of metal stack for IR Drop of %gmV is %gu\n" irDrop irLength
    )
    )
    ("Width"
    when(form->irLength->value == "" ||
    form->irLength->value == nil ||
    form->voltVal->value == "" ||
    form->voltVal->value == nil
    ADialogs("warning" "Specify necessary values on form")
    return(nil)
    )
    irLength = aelNumber(form->irLength->value)
    irWidth = 0.0
    irDrop = aelNumber(form->voltVal->value)
    irWidth = (irLength*totalRes*currentVal)/irDrop
    printf("Width of metal stack for IR Drop of %gmV is %gu\n" irDrop irWidth)
    )
    ); case
    ); prog
    ); proc

    procedure(AFigCurDens(figList)
    prog((techVal m1JMax m2JMax m3JMax m4JMax m5JMax m6JMax m7JMax m8JMax m9JMax m10JMax m11JMax m12JMax m13JMax APJMax layerName
    figWidth ll ur jMax figCurrent)
    techVal ="foundarytech"
    case(techVal
    ("foundarytech"
    ;mA/um (width)
    m1JMax = 2
    m2JMax = 1.7
    m3JMax = 1.7
    m4JMax = 1.5
    m5JMax = 2
    m6JMax = 2
    m7JMax = 2
    m8JMax = 2
    m9JMax = 5
    m10JMax = 5
    m11JMax = 15
    m12JMax = 15
    m13JMax = 50
    APJMax = 8
    )
    ); case

    foreach(fig figList
    layerName = fig->layerName

    if(fig->objType == "path" || fig~>objType == "pathSeg" then
    figWidth = fig->width
    else
    ll = car(fig~>bBox)
    ur = cadr(fig~>bBox)
    figWidth = abs(yCoord(ll) - yCoord(ur))
    )

    case(layerName
    ("M1"
    jMax = m1JMax
    )
    ("M2"
    jMax = m2JMax
    )
    ("M3"
    jMax = m3JMax
    )
    ("M4"
    jMax = m4JMax
    )
    ("M5"
    jMax = m5JMax
    )
    ("M6"
    jMax = m6JMax
    )
    ("M7"
    jMax = m7JMax
    )
    ("M8"
    jMax = m8JMax
    )
    ("M9"
    jMax = m9JMax
    )
    ("M10"
    jMax = m10JMax
    )
    ("M11"
    jMax = m11JMax
    )
    ("M12"
    jMax = m12JMax
    )
    ("M13"
    jMax = m13JMax
    )
    ("AP"
    jMax = APJMax
    )
    ); case



    figCurrent = jMax*figWidth*1 ; Calclated with no optical shrink from 7nm process


    if(fig->objType == "path" || fig~>objType == "pathSeg" then
    printf("Max Current of %s path is: %gmA\n" layerName figCurrent)
    else
    printf("Max Current of %s rectangle is: %gmA\n" layerName figCurrent)
    )

    ); foreach

    ); prog
    ); proc


    procedure(AFigRes(figList)
    prog((cornerVal m1SheetRes m2to3SheetRes m4SheetRes m5to8SheetRes m9to10SheetRes m11to12SheetRes m13SheetRes APSheetRes techVal)
    ;% of a square (typically range from 0.5 to 0.65)
    ;obtained from res callbacks in tsmc13 skill dir
    cornerVal = 0.56
    techVal ="foundarytech"

    ;tsmc7 sheet resistance
    ; mean value

    case(techVal
    ("foundarytech"
    m1SheetRes = 2
    m2to3SheetRes = 1.7
    m4SheetRes = 1
    m5to8SheetRes = .5
    m9to10SheetRes = .3
    m11to12SheetRes = .02
    m13SheetRes = .005
    APSheetRes = .01
    )
    ); case

    foreach(fig figList
    if(rodGetObj(fig) then
    AGetRodPathRes(fig cornerVal m1SheetRes m2to3SheetRes m4SheetRes m5to8SheetRes m9to10SheetRes m11to12SheetRes m13SheetRes APSheetRes)
    else
    if(fig->objType == "rect" then
    AGetRectRes(fig m1SheetRes m2to3SheetRes m4SheetRes m5to8SheetRes m9to10SheetRes m11to12SheetRes m13SheetRes APSheetRes)
    else
    AGetOtherPathRes(fig cornerVal m1SheetRes m2to3SheetRes m4SheetRes m5to8SheetRes m9to10SheetRes m11to12SheetRes m13SheetRes APSheetRes)
    )
    ); if
    ); foreach
    ); prog
    ); proc


    procedure(AGetRectRes(fig1 m1SheetRes m2to3SheetRes m4SheetRes m5to8SheetRes m9to10SheetRes m11to12SheetRes m13SheetRes APSheetRes)
    prog((totalLength rectBBox ll ur rectW layerName sheetRes
    numSquares resVal)
    totalLength = AGeomArea(?figLength t ?printLine nil ?fig list(fig1))
    printf("Length %g\n" totalLength)
    rectBBox = fig1~>bBox
    ll = car(rectBBox)
    ur = cadr(rectBBox)
    rectW = abs(yCoord(ll) - yCoord(ur))
    layerName = fig1~>layerName
    case(layerName
    ("M1"
    sheetRes = m1SheetRes
    )
    ("M2" || "M3"
    sheetRes = m2to3SheetRes
    )
    ("M4"
    sheetRes = m4SheetRes
    )
    ("M5" || "M6" || "M7" || "M8"
    sheetRes = m5to8SheetRes
    )
    ("M9" || "M10"
    sheetRes = m9to10SheetRes
    )
    ("M11" || "M12"
    sheetRes = m11to12SheetRes
    )
    ("M13"
    sheetRes = m13SheetRes
    )
    ("AP"
    sheetRes = APSheetRes
    )
    );case

    numSquares = totalLength/rectW

    resVal = numSquares * sheetRes
    printf("Resistance of %s Rectangle is: %g Ohms\n" layerName resVal)
    ); prog
    ); proc

    procedure(AGetOtherPathRes(fig1 cornerVal m1SheetRes m2to3SheetRes m4SheetRes m5to8SheetRes m9to10SheetRes m11to12SheetRes m13SheetRes APSheetRes)
    let((numSegments i index1 index2 totalLength pathW numCorners
    numSquares layerName sheetRes resVal pointList
    pointListLength x1 y1 x2 y2)

    numSegments = 0
    i = 0

    totalLength = AGeomArea(?figLength t ?printLine nil ?fig list(fig1))
    pathW = fig1~>width
    pointList = fig1->points
    pointListLength = length(pointList)
    declare(pointArray[pointListLength])

    numSegments = pointListLength - 1

    numCorners = numSegments - 1

    numSquares = (totalLength / pathW) -
    (numCorners * cornerVal)

    layerName = fig1~>layerName

    case(layerName
    ("M1"
    sheetRes = m1SheetRes
    )
    ("M2" || "M3"
    sheetRes = m2to3SheetRes
    )
    ("M4"
    sheetRes = m4SheetRes
    )
    ("M5" || "M6" || "M7" || "M8"
    sheetRes = m5to8SheetRes
    )
    ("M9" || "M10"
    sheetRes = m9to10SheetRes
    )
    ("M11" || "M12"
    sheetRes = m11to12SheetRes
    )
    ("M13"
    sheetRes = m13SheetRes
    )
    ("AP"
    sheetRes = APSheetRes
    )
    );case

    resVal = numSquares * sheetRes

    printf("Resistance of %s path is: %g Ohms\n" layerName resVal)
    ); let
    ); proc


    ;Rod path procs

    procedure(AGetRodPathLength(rodId)
    let((subLength)
    subLength = 0
    for(i 0 (rodId~>numSegments - 1)
    subLength = subLength +
    rodGetHandle(rodId symbolToString(concat("length" i)))
    )

    subLength
    ); let
    ); proc

    procedure(AGetRodPathRes(fig1 cornerVal m1SheetRes m2to3SheetRes m4SheetRes m5to8SheetRes m9to10SheetRes m11to12SheetRes m13SheetRes APSheetRes)
    let((rodId layerName pathW numSegments numCorners totalLength
    numSquares sheetRes resVal)

    rodId = rodGetObj(fig1)
    layerName = rodId~>dbId~>layerName

    case(layerName
    ("M1"
    sheetRes = m1SheetRes
    )
    ("M2" || "M3"
    sheetRes = m2to3SheetRes
    )
    ("M4"
    sheetRes = m4SheetRes
    )
    ("M5" || "M6" || "M7" || "M8"
    sheetRes = m5to8SheetRes
    )
    ("M9" || "M10"
    sheetRes = m9to10SheetRes
    )
    ("M11" || "M12"
    sheetRes = m11to12SheetRes
    )
    ("M13"
    sheetRes = m13SheetRes
    )
    ("AP"
    sheetRes = APSheetRes
    )
    );case

    pathW = rodId~>dbId~>width
    numSegments = rodId~>numSegments
    numCorners = numSegments - 1
    totalLength = AGetRodPathLength(rodId)

    numSquares = (totalLength / pathW) -
    (numCorners * cornerVal)

    resVal = numSquares * sheetRes
    printf("Resistance of %s wire is: %g Ohms\n" layerName resVal)
    ); let
    ); proc

    /***********************************************
    Area calculation: Shift<Key>p
    ************************************************/
    ;Area calculation (for fig calcs)
    procedure(AGeomArea(@key (figLength nil) (printLine t) (fig nil))
    prog(sSet(lyr_name
    sum
    crd
    lastPt
    firstPt
    crdList
    area
    corners
    ll
    ur
    dx
    dy
    shape
    width
    endShp
    diax
    diay
    diay
    radx
    rady
    pLength
    )
    when(null(ALayoutWindowCheck(t))
    return(nil)
    )

    if(fig == nil
    then
    sSet = geGetSelSet(hiGetCurrentWindow())
    else
    sSet = fig
    )

    if(sSet == nil
    then
    ADialogs("error" "A single object must be pre-selected")
    return(nil)
    )

    if(!car(sSet)~>isShape
    then
    ADialogs("error" "Object must be a Wire, polygon or rectangle")
    return(nil)
    )

    shape = car(sSet)~>objType

    if(figLength && (shape != "path") && (shape != "pathSeg") && (shape != "rectangle")
    then
    ADialogs("error" "Object must be a path or rectangle")
    return(nil)
    )

    lyr_name = techGetLayerName(techGetTechFile(geGetEditCellView())
    car(sSet)~>layer
    )

    case( shape
    ("polygon"
    crdList = car(sSet)~>path
    sum = 0
    firstPt = lastPt = car(crdList)
    crdList = cdr(crdList)
    foreach(crd crdList
    sum = sum + ((xCoord(crd) - xCoord(lastPt)) * (yCoord(crd) + yCoord(lastPt)))
    lastPt = crd
    )
    sum = sum + ((xCoord(firstPt) - xCoord(lastPt)) * (yCoord(firstPt) + yCoord(lastPt)))
    area = 0.5 * abs(sum)
    printf("The area for this %s polygon is: %f\n" lyr_name area)
    )
    ("rectangle"
    corners = car(sSet)~>bBox
    ll = car(corners)
    ur = cadr(corners)
    dx = xCoord(ll) - xCoord(ur)
    dy = yCoord(ll) - yCoord(ur)
    fLength = abs(dx)
    area = abs(dx * dy)
    when(printLine
    printf("The area for this %s rectangle is: %f\n" lyr_name area)
    printf("Length: %n\n" abs(dx))
    printf("Width: %n\n" abs(dy))
    ) ; when

    when(figLength
    return(fLength)
    )
    )
    ("path"
    crdList = car(sSet)~>path
    width = car(sSet)~>width
    endShp = car(sSet)~>pathShape
    if((endShp == "bothArrowEnded") || (endShp == "singleArrowEnded")
    then
    ADialogs("warning" "Path must have square or octagon ends.")
    return(nil)
    ) ;if
    if(figLength
    then
    if(printLine
    then
    printf("The length for this %s path is: %f\n "
    lyr_name
    car(APathArea(crdList width endShp))
    )
    )
    pLength = car(APathArea(crdList width endShp))
    return(pLength)
    else
    area = cadr(APathArea(crdList width endShp))
    printf("The area for this %s path is: %f\n" lyr_name area)
    printf("The length for this %s path is: %f\n "
    lyr_name
    car(APathArea(crdList width endShp))
    )
    )
    )
    ("pathSeg"
    crdList = car(sSet)~>pathSeg
    width = car(sSet)~>width
    endShp = car(sSet)~>pathShape
    if((endShp == "bothArrowEnded") || (endShp == "singleArrowEnded")
    then
    ADialogs("warning" "Wire must have square or octagon ends.")
    return(nil)
    ) ;if
    if(figLength
    then
    if(printLine
    then
    printf("The length for this %s wire is: %f\n "
    lyr_name
    car(APathArea(crdList width endShp))
    )
    )
    pLength = car(APathArea(crdList width endShp))
    return(pLength)
    else
    area = cadr(APathArea(crdList width endShp))
    printf("The area for this %s wire is: %f\n" lyr_name area)
    printf("The length for this %s wire is: %f\n "
    lyr_name
    car(APathArea(crdList width endShp))
    )
    )
    )
    ("ellipse"
    llBox = caar(sSet~>bBox)
    urBox = cadar(sSet~>bBox)
    /*
    Due to the precision of the database and the accuracy of the conic
    circle generator, we have some discrepancies especially on large figures
    that will throw out the x and y calculation to be different on the bBox
    dimensions.
    */
    diax = round(1000 * ((xCoord(urBox) - xCoord(llBox)) + 0.0005))
    diay = round(1000 * ((yCoord(urBox) - yCoord(llBox)) + 0.0005))
    if(diax == diay
    then
    radx = diax / 2000.0
    area = 3.14159 * expt(radx 2)
    printf("Area of circle is %f.\n" area)
    else
    radx = diax / 2000.0
    rady = diay / 2000.0
    area = 3.14159 * radx * rady
    printf("Area of ellipse is %f.\n" area)
    )
    )
    ("donut"
    area = 3.14159 * (expt(car(sSet)~>outerRadius 2) - expt(car(sSet)~>innerRadius
    2
    ))
    printf("Area of donut is %f.\n" area)
    )
    )
    ;case
    return(area)
    ) ; prog
    ) ; proc


    procedure(APathArea(crdlist wid endShape)
    prog( (sum crd xlen ylen pathLength)
    lastcrd=car(crdlist)
    sum=0
    crdlist=cdr(crdlist)
    foreach(crd crdlist
    xlen=(xCoord(crd)-xCoord(lastcrd))
    ylen=(yCoord(crd)-yCoord(lastcrd))
    sum=sum+sqrt((xlen*xlen+ylen*ylen))
    lastcrd=crd
    )
    if( endShape == "squareOffset" then
    sum = sum + wid
    )
    if( endShape == "octagonEnded" then
    sum = sum + 3*wid/4
    )
    if( endShape == "varExtendExtend" then
    sum = sum + car(sSet)~>beginExt + car(sSet)~>endExt
    )
    pathLength = sum
    sum=wid*sum
    return(list(pathLength sum))
    )
    ); proc

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to Carona

    If your code is really indented as above, it's no wonder you can't get it to work. Indentation is vital for program understanding - I normally would have just refused to even try to debug it given the lack of formatting (see my presentation Writing Good SKILL Code (Video) ). Luckily I have a utility to reformat the code to make it easier to understand.

    There were numerous mistakes in the code, and to be honest, you really should be able to debug these yourself (it's even easier in the SKILL IDE because you can then see where it broke). I can't guarantee that the code below is correct, and to be honest I cannot spend any more time fixing this for you (I do this in my spare time, and you've just expended quite a bit of that!). It seems now to run OK on rectangles and pathSegs (no idea whether the results are correct because I didn't check whether the computations were correct or doing the right thing). I've no idea what the origin of this code is, but it seems to have all sorts of odd and ancient legacy things that haven't been really supported/documented in the database for decades.

    Note that I changed the code to use Metal1 to Metal13 etc rather than M1 to M13 so you may need to just do a search and replace for Metal and replace with M. I've put "ANDREW" comments next to everything I changed (other than the layer names).

    Good luck.

    Andrew.

    /***********************************************
    Calculation form : Shift<Key>i
    ************************************************/ 
    
    ;; ANDREW - these functions were missing, so I added them to help debug
    ;; Note, I changed all the M1 to M13 to be Metal1 to Metal13 etc so I could
    ;; test - you might want to change it back
    procedure(ALayoutWindowCheck(arg) t)
    procedure(ADialogs(type message)
      printf("%s: %s\n" type message)
    )
    
    ;Fig Calcs
    
    procedure(ALaunchFigCalcs()
      unless(boundp('AFigCalcsForm) && hiIsForm(AFigCalcsForm)
        ACreateFigCalcsForm()
       )
      
      unless(hiIsFormDisplayed(AFigCalcsForm)
        hiDisplayForm(AFigCalcsForm)
       )
     ) ; proc
    
    
    procedure(ACreateFigCalcsForm()
      let((resCur
           irDrop
           label
           current
           figOpts
           sep1
           irDropOpts
           irLength
           irWidth
           metLayers
           voltage
          )
        figOpts = hiCreateRadioField(?name 'figOpts
                                     ?prompt "Options"
                                     ?choices list("Res/Current" "IR Drop")
                                     ?value "Res/Current"
                                     ?callback '("AFigCalcsDefCB(\"figOpts\")")
                                    )
        sep1 = hiCreateSeparatorField(?name 'sep1)
        label = hiCreateLabel(?name 'label ?labelText "IR Drop")
        irDropOpts = hiCreateCyclicField(?name 'irDropOpts
                                         ?prompt "Calculate"
                                         ?choices '("Width" "Length" "Voltage Drop")
                                         ?value "Voltage Drop"
                                         ?enabled nil
                                         ?callback "AFigCalcsDefCB(\"irDropOpts\")"
                                        )
        
        irLength = hiCreateStringField(?name 'irLength
                                       ?prompt "Length (u)"
                                       ?defValue ""
                                       ?enabled nil
                                      )
        
        irWidth = hiCreateStringField(?name 'irWidth ?prompt "Width (u)" ?defValue "" ?enabled nil)
        metLayers = hiCreateToggleField(?name 'metLayers
                                        ?prompt "Metal Layers"
                                        ?choices list(
                                                  '(m1)
                                                  '(m2)
                                                  '(m3)
                                                  '(m4)
                                                  '(m5)
                                                  '(m6)
                                                  '(m7)
                                                  '(m8)
                                                  '(m9)
                                                  '(m10)
                                                  '(m11)
                                                  '(m12)
                                                  '(m13)
                                                  '(AP)
                                                 )
                                        ?value '(t t t t t t t t t t t t t t)
                                        ?numSelect 14
                                        ?enabled nil
                                       )
        current = hiCreateStringField(?name 'currentVal
                                      ?prompt "Current (mA)"
                                      ?defValue ""
                                      ?enabled nil
                                     )
        
        voltage = hiCreateStringField(?name 'voltVal
                                      ?prompt "Voltage Drop (mV)"
                                      ?defValue ""
                                      ?enabled nil
                                     )
        
        hiCreateAppForm(?name 'AFigCalcsForm
                        ?fields list(
                                 figOpts
                                 sep1
                                 label
                                 irDropOpts
                                 irLength
                                 irWidth
                                 metLayers
                                 current
                                 voltage
                                )
                        ?formTitle "Fig Calculations"
                        ?callback "AFigCalcsCB()"
                       )
       ) ; let
     ) ; proc
    
    procedure(AFigCalcsDefCB(args)
      let((form
          )
        form = hiGetCurrentForm()
        case( args
          ("figOpts"
           if(form->figOpts->value == "IR Drop"
               then
                   form->irDropOpts->enabled = t
                   form->metLayers->enabled = t
                   form->currentVal->enabled = t
                   case( ((form->irDropOpts)->value)
                     ("Width"
                      form->irLength->enabled = t
                      form->voltVal->enabled = t
                     )
                     ("Length"
                      form->irWidth->enabled = t
                      form->voltVal->enabled = t
                     )
                     ("Voltage Drop"
                      form->irWidth->enabled = t
                      form->irLength->enabled = t
                     )
                    ) ; case
               else
                   form->irDropOpts->enabled = nil
                   form->irWidth->enabled = nil
                   form->irLength->enabled = nil
                   form->metLayers->enabled = nil
                   form->currentVal->enabled = nil
                   form->voltVal->enabled = nil
              )
          )
          ("irDropOpts"
           if(form->irDropOpts->value == "Voltage Drop"
               then
                   form->voltVal->enabled = nil
               else
                   form->voltVal->enabled = t
              )
           
           if(form->irDropOpts->value == "Width"
               then
                   form->irWidth->enabled = nil
               else
                   form->irWidth->enabled = t
              )
           
           if(form->irDropOpts->value == "Length"
               then
                   form->irLength->enabled = nil
               else
                   form->irLength->enabled = t
              )
          )
         ) ; case
       ) ; let
     ) ; proc
    
    procedure(AFigCalcsCB()
      prog(fig1(figList form setWarn figCheck layerCheck)
           figCheck = 0
           layerCheck = 0
           form = hiGetCurrentForm()
           
           when(form->figOpts->value == "Res/Current"
             when(null(ALayoutWindowCheck(t))
               return(nil)
              )
             
             figList = geGetSelectedSet()
             
             foreach(fig figList
               when((fig~>objType != "path") && (fig~>objType != "pathSeg") && (fig~>objType != "rect")
                 figCheck = 1
                )
               when((fig~>layerName != "Metal1") && (fig~>layerName != "Metal2") && (fig~>layerName != "Metal3") && (fig~>layerName != "Metal4") && (fig~>layerName != "Metal5") && (fig~>layerName != "Metal6") && (fig~>layerName != "Metal7") && (fig~>layerName != "Metal8") && (fig~>layerName != "Metal9") && (fig~>layerName != "Metal10") && (fig~>layerName != "Metal11") && (fig~>layerName != "Metal12") && (fig~>layerName != "Metal13") && (fig~>layerName != "AP")
                 layerCheck = 1
                )
              ) ; foreach
             
             when(figCheck == 1
               ADialogs("error" "Selected set contains objects which are not wires or rectangles")
               figCheck = 0
               return(nil)
              )
             
             when(layerCheck == 1
               ADialogs("error" "Selected Set contains objects not drawn on metal layers")
               layerCheck = 0
               return(nil)
              )
             
             AFigRes(figList)
             AFigCurDens(figList)
            )
            ; when
           
           
           when(form->figOpts->value == "IR Drop"
             APathIRDrop(figList)
            )
           
           
          ) ; prog
     ) ; proc
    
    procedure(APathIRDrop(figList)
      prog(form(count
                metCount
                metLayersList
                totalRes
                sheetRes
                irLength
                irWidth
                currentVal
                metLayers
                irDrop
                irDropMv
                techVal
               )
           form = hiGetCurrentForm()
           count = 1
           metCount = 0
           metLayersList = list()
           totalRes = 0
           sheetRes = 0
           techVal = "foundarytech"
           
           ;Field checks
           when(null(member(t form->metLayers->value)) || (form->currentVal->value == "") || (form->currentVal->value == nil)
             ADialogs("warning" "Specify necessary values on form")
             return(nil)
            )
           
           currentVal = aelNumber((form->currentVal->value))
           metLayers = form->metLayers->value
           foreach(val metLayers
             when(val == t
               metCount = metCount + 1
               metLayersList = cons(strcat("M" || "AP" printstring(count)) metLayersList)
              )
             count = count + 1
            )
           
           foreach(metLayer metLayersList
             case( metLayer
               ("Metal1"
                case( techVal
                  ("foundarytech" ;; ANDREW - there was a pipe character on this line: |
                   sheetRes = 1
                  )
                 )
               )
               ("Metal2" || "Metal3"
                case( techVal
                  ("foundarytech"
                   sheetRes = 2
                  )
                 )
               )
               ("Metal4"
                case( techVal
                  ("foundarytech"
                   sheetRes = 4
                  )
                 )
               )
               ("Metal5" || "Metal6" || "Metal7" || "Metal8"
                case( techVal
                  ("foundarytech"
                   sheetRes = 0.5
                  )
                 )
               )
               ("Metal9" || "Metal10"
                case( techVal
                  ("foundarytech"
                   sheetRes = 0.2
                  )
                 )
               )
               ("Metal11" || "Metal12"
                case( techVal
                  ("foundarytech"
                   sheetRes = 0.1
                  )
                 )
               )
               ("Metal13"
                case( techVal
                  ("foundarytech"
                   sheetRes = 0.01
                  )
                 )
               )
               
               ("AP"
                case( techVal
                  ("foundarytech"
                   sheetRes = 0.025
                  )
                 )
               )
              ) ; case
             if(metCount == 1
                 then
                     totalRes = sheetRes
                 else
                     when(metCount > 1
                       totalRes = totalRes + (1 / sheetRes)
                      )
                )
            )
            ; foreach
           
           when(metCount > 1
             totalRes = 1 / totalRes
            )
           
           case( ((form->irDropOpts)->value)
             ("Voltage Drop"
              when((form->irLength->value == "") || (form->irLength->value == nil) || (form->irWidth->value == "") || (form->irWidth->value == nil)
                ADialogs("warning" "Specify necessary values on form")
                return(nil)
               )
              irLength = aelNumber((form->irLength->value))
              irWidth = aelNumber((form->irWidth->value))
              irDrop = (irLength / irWidth) * totalRes * currentVal
              printf("IR Drop across metal stack is %gmV\n" irDrop)
              when(irDrop > 30
                ADialogs("warning" "IR Drop is greater than 30mV")
               )
             )
             ("Length"
              when((form->irWidth->value == "") || (form->irWidth->value == nil) || (form->voltVal->value == "") || (form->voltVal->value == nil)
                ADialogs("warning" "Specify necessary values on form")
                return(nil)
               )
              irWidth = aelNumber((form->irWidth->value))
              irLength = 0.0
              irDrop = aelNumber((form->voltVal->value))
              irLength = (irDrop * irWidth) / (totalRes * currentVal)
              printf("Length of metal stack for IR Drop of %gmV is %gu\n" irDrop irLength)
             )
             ("Width"
              when((form->irLength->value == "") || (form->irLength->value == nil) || (form->voltVal->value == "") || (form->voltVal->value == nil)
                ADialogs("warning" "Specify necessary values on form")
                return(nil)
               )
              irLength = aelNumber((form->irLength->value))
              irWidth = 0.0
              irDrop = aelNumber((form->voltVal->value))
              irWidth = (irLength * totalRes * currentVal) / irDrop
              printf("Width of metal stack for IR Drop of %gmV is %gu\n" irDrop irWidth)
             )
            )
            ; case
           
          ) ; prog
     ) ; proc
    
    procedure(AFigCurDens(figList)
      prog(techVal(m1JMax
                   m2JMax
                   m3JMax
                   m4JMax
                   m5JMax
                   m6JMax
                   m7JMax
                   m8JMax
                   m9JMax
                   m10JMax
                   m11JMax
                   m12JMax
                   m13JMax
                   APJMax
                   layerName
                   figWidth
                   ll
                   ur
                   jMax
                   figCurrent
                  )
           techVal = "foundarytech"
           case( techVal
             ("foundarytech"
              ;mA/um (width)
              m1JMax = 2
              m2JMax = 1.7
              m3JMax = 1.7
              m4JMax = 1.5
              m5JMax = 2
              m6JMax = 2
              m7JMax = 2
              m8JMax = 2
              m9JMax = 5
              m10JMax = 5
              m11JMax = 15
              m12JMax = 15
              m13JMax = 50
              APJMax = 8
             )
            )
            ; case
           
           foreach(fig figList
             layerName = fig->layerName
             
             if((fig->objType == "path") || (fig~>objType == "pathSeg")
                 then
                     figWidth = fig->width
                 else
                     ll = car(fig~>bBox)
                     ur = cadr(fig~>bBox)
                     figWidth = abs(yCoord(ll) - yCoord(ur))
                )
             
             case( layerName
               ("Metal1"
                jMax = m1JMax
               )
               ("Metal2"
                jMax = m2JMax
               )
               ("Metal3"
                jMax = m3JMax
               )
               ("Metal4"
                jMax = m4JMax
               )
               ("Metal5"
                jMax = m5JMax
               )
               ("Metal6"
                jMax = m6JMax
               )
               ("Metal7"
                jMax = m7JMax
               )
               ("Metal8"
                jMax = m8JMax
               )
               ("Metal9"
                jMax = m9JMax
               )
               ("Metal10"
                jMax = m10JMax
               )
               ("Metal11"
                jMax = m11JMax
               )
               ("Metal12"
                jMax = m12JMax
               )
               ("Metal13"
                jMax = m13JMax
               )
               ("AP"
                jMax = APJMax
               )
              ) ; case
             
             
             
             figCurrent = jMax * figWidth * 1 ; Calclated with no optical shrink from 7nm process
             
             
             if((fig->objType == "path") || (fig~>objType == "pathSeg")
                 then
                     printf("Max Current of %s path is: %gmA\n" layerName figCurrent)
                 else
                     printf("Max Current of %s rectangle is: %gmA\n" layerName figCurrent)
                )
             
            )
            ; foreach
           
           
          ) ; prog
     ) ; proc
    
    
    procedure(AFigRes(figList)
      prog(cornerVal(m1SheetRes
                     m2to3SheetRes
                     m4SheetRes
                     m5to8SheetRes
                     m9to10SheetRes
                     m11to12SheetRes
                     m13SheetRes
                     APSheetRes
                     techVal
                    )
           ;% of a square (typically range from 0.5 to 0.65)
           ;obtained from res callbacks in tsmc13 skill dir
           cornerVal = 0.56
           techVal = "foundarytech"
           
           ;tsmc7 sheet resistance
           ; mean value
           
           case( techVal
             ("foundarytech"
              m1SheetRes = 2
              m2to3SheetRes = 1.7
              m4SheetRes = 1
              m5to8SheetRes = 0.5
              m9to10SheetRes = 0.3
              m11to12SheetRes = 0.02
              m13SheetRes = 0.005
              APSheetRes = 0.01
             )
            )
            ; case
           
           foreach(fig figList
             if(rodGetObj(fig)
                 then
                     AGetRodPathRes(fig
                                    cornerVal
                                    m1SheetRes
                                    m2to3SheetRes
                                    m4SheetRes
                                    m5to8SheetRes
                                    m9to10SheetRes
                                    m11to12SheetRes
                                    m13SheetRes
                                    APSheetRes
                                   )
                 else
                     if(fig->objType == "rect"
                         then
                             AGetRectRes(fig
                                         m1SheetRes
                                         m2to3SheetRes
                                         m4SheetRes
                                         m5to8SheetRes
                                         m9to10SheetRes
                                         m11to12SheetRes
                                         m13SheetRes
                                         APSheetRes
                                        )
                         else
                             AGetOtherPathRes(fig
                                              cornerVal
                                              m1SheetRes
                                              m2to3SheetRes
                                              m4SheetRes
                                              m5to8SheetRes
                                              m9to10SheetRes
                                              m11to12SheetRes
                                              m13SheetRes
                                              APSheetRes
                                             )
                        )
                ) ; if
            )
            ; foreach
           
          ) ; prog
     ) ; proc
    
    
    procedure(AGetRectRes(fig1 m1SheetRes m2to3SheetRes m4SheetRes m5to8SheetRes m9to10SheetRes m11to12SheetRes
                          m13SheetRes APSheetRes)
      prog(totalLength(rectBBox ll ur rectW layerName sheetRes numSquares resVal)
           totalLength = AGeomArea(?figLength t ?printLine nil ?fig list(fig1))
           printf("Length %g\n" totalLength)
           rectBBox = fig1~>bBox
           ll = car(rectBBox)
           ur = cadr(rectBBox)
           rectW = abs(yCoord(ll) - yCoord(ur))
           layerName = fig1~>layerName
           case( layerName
             ("Metal1"
              sheetRes = m1SheetRes
             )
             ("Metal2" || "Metal3"
              sheetRes = m2to3SheetRes
             )
             ("Metal4"
              sheetRes = m4SheetRes
             )
             ("Metal5" || "Metal6" || "Metal7" || "Metal8"
              sheetRes = m5to8SheetRes
             )
             ("Metal9" || "Metal10"
              sheetRes = m9to10SheetRes
             )
             ("Metal11" || "Metal12"
              sheetRes = m11to12SheetRes
             )
             ("Metal13"
              sheetRes = m13SheetRes
             )
             ("AP"
              sheetRes = APSheetRes
             )
            )
            ;case
           
           numSquares = totalLength / rectW
           
           resVal = numSquares * sheetRes
           printf("Resistance of %s Rectangle is: %g Ohms\n" layerName resVal)
          ) ; prog
     ) ; proc
    
    procedure(AGetOtherPathRes(fig1 cornerVal m1SheetRes m2to3SheetRes m4SheetRes m5to8SheetRes m9to10SheetRes
                               m11to12SheetRes m13SheetRes APSheetRes)
      let((numSegments
           i
           index1
           index2
           totalLength
           pathW
           numCorners
           numSquares
           layerName
           sheetRes
           resVal
           pointList
           pointListLength
           x1
           y1
           x2
           y2
          )
        
        numSegments = 0
        i = 0
        
        totalLength = AGeomArea(?figLength t ?printLine nil ?fig list(fig1))
        pathW = fig1~>width
        pointList = fig1->points
        pointListLength = length(pointList)
        declare(pointArray[pointListLength])
        
        numSegments = pointListLength - 1
        
        numCorners = numSegments - 1
        
        numSquares = (totalLength / pathW) - (numCorners * cornerVal)
        
        layerName = fig1~>layerName
        
        case( layerName
          ("Metal1"
           sheetRes = m1SheetRes
          )
          ("Metal2" || "Metal3"
           sheetRes = m2to3SheetRes
          )
          ("Metal4"
           sheetRes = m4SheetRes
          )
          ("Metal5" || "Metal6" || "Metal7" || "Metal8"
           sheetRes = m5to8SheetRes
          )
          ("Metal9" || "Metal10"
           sheetRes = m9to10SheetRes
          )
          ("Metal11" || "Metal12"
           sheetRes = m11to12SheetRes
          )
          ("Metal13"
           sheetRes = m13SheetRes
          )
          ("AP"
           sheetRes = APSheetRes
          )
         ) ;case
        
        resVal = numSquares * sheetRes
        
        printf("Resistance of %s path is: %g Ohms\n" layerName resVal)
       ) ; let
     ) ; proc
    
    
    ;Rod path procs
    
    procedure(AGetRodPathLength(rodId)
      let((subLength
          )
        subLength = 0
        for(i 0 rodId~>numSegments - 1
          subLength = subLength + rodGetHandle(rodId symbolToString(concat("length" i)))
         )
        
        subLength
       ) ; let
     ) ; proc
    
    procedure(AGetRodPathRes(fig1 cornerVal m1SheetRes m2to3SheetRes m4SheetRes m5to8SheetRes m9to10SheetRes
                             m11to12SheetRes m13SheetRes APSheetRes)
      let((rodId
           layerName
           pathW
           numSegments
           numCorners
           totalLength
           numSquares
           sheetRes
           resVal
          )
        
        rodId = rodGetObj(fig1)
        layerName = rodId~>dbId~>layerName
        
        case( layerName
          ("Metal1"
           sheetRes = m1SheetRes
          )
          ("Metal2" || "Metal3"
           sheetRes = m2to3SheetRes
          )
          ("Metal4"
           sheetRes = m4SheetRes
          )
          ("Metal5" || "Metal6" || "Metal7" || "Metal8"
           sheetRes = m5to8SheetRes
          )
          ("Metal9" || "Metal10"
           sheetRes = m9to10SheetRes
          )
          ("Metal11" || "Metal12"
           sheetRes = m11to12SheetRes
          )
          ("Metal13"
           sheetRes = m13SheetRes
          )
          ("AP"
           sheetRes = APSheetRes
          )
         ) ;case
        
        pathW = rodId~>dbId~>width
        numSegments = rodId~>numSegments
        numCorners = numSegments - 1
        totalLength = AGetRodPathLength(rodId)
        
        numSquares = (totalLength / pathW) - (numCorners * cornerVal)
        
        resVal = numSquares * sheetRes
        printf("Resistance of %s wire is: %g Ohms\n" layerName resVal)
       ) ; let
     ) ; proc
    
    /***********************************************
    Area calculation: Shift<Key>p
    ************************************************/ 
    ;Area calculation (for fig calcs)
    procedure(AGeomArea(@key (figLength nil) (printLine t) (fig nil))
      prog(sSet(lyr_name
                sum
                crd
                lastPt
                firstPt
                crdList
                area
                corners
                ll
                ur
                dx
                dy
                shape
                width
                endShp
                diax
                diay
                diay
                radx
                rady
                pLength
               )
           when(null(ALayoutWindowCheck(t))
             return(nil)
            )
           
           if(fig == nil
               then
                   sSet = geGetSelSet(hiGetCurrentWindow())
               else
                   sSet = fig
              )
           
           if(sSet == nil
               then
                   ADialogs("error" "A single object must be pre-selected")
                   return(nil)
              )
           
           if(null(car(sSet)~>isShape)
               then
                   ADialogs("error" "Object must be a Wire, polygon or rectangle")
                   return(nil)
              )
           
           shape = car(sSet)~>objType
           
           ;; ANDREW - this was "rectangle" but the objType is actually "rect"
           if(figLength && (shape != "path") && (shape != "pathSeg") && (shape != "rect")
               then
                   ADialogs("error" "Object must be a path or rectangle")
                   return(nil)
              )
           
           lyr_name = techGetLayerName(techGetTechFile(geGetEditCellView())
                                       car(sSet)~>layer
                                      )
           
           case( shape
             ("polygon"
              ;; ANDREW - another obsolete attribute
    	  ;; crdList = car(sSet)~>path
              crdList = car(sSet)~>points
              sum = 0
              firstPt = lastPt = car(crdList)
              crdList = cdr(crdList)
              foreach(crd crdList
                sum = sum + ((xCoord(crd) - xCoord(lastPt)) * (yCoord(crd) + yCoord(lastPt)))
                lastPt = crd
               )
              sum = sum + ((xCoord(firstPt) - xCoord(lastPt)) * (yCoord(firstPt) + yCoord(lastPt)))
              area = 0.5 * abs(sum)
              printf("The area for this %s polygon is: %f\n" lyr_name area)
             )
             ;; ANDREW - this was "rectangle" but the objType is actually "rect"
             ("rect"
              corners = car(sSet)~>bBox
              ll = car(corners)
              ur = cadr(corners)
              dx = xCoord(ll) - xCoord(ur)
              dy = yCoord(ll) - yCoord(ur)
              fLength = abs(dx)
              area = abs(dx * dy)
              when(printLine
                printf("The area for this %s rectangle is: %f\n" lyr_name area)
                printf("Length: %n\n" abs(dx))
                printf("Width: %n\n" abs(dy))
               ) ; when
              
              when(figLength
                return(fLength)
               )
             )
             ("path"
              ;; ANDREW - two obsolete attributes
              ;; crdList = car(sSet)~>path
              ;; endShp = car(sSet)~>pathShape
              crdList = car(sSet)~>points
              width = car(sSet)~>width
              endShp = car(sSet)~>pathStyle
              ;; ANDREW - not convinced these ever exist any more
              if((endShp == "bothArrowEnded") || (endShp == "singleArrowEnded")
                  then
                      ADialogs("warning" "Path must have square or octagon ends.")
                      return(nil)
                 ) ;if
              if(figLength
                  then
                      if(printLine
                          then
                              printf("The length for this %s path is: %f\n "
                                     lyr_name
                                     car(APathArea(crdList width endShp))
                                    )
                         )
                      pLength = car(APathArea(crdList width endShp))
                      return(pLength)
                  else
                      area = cadr(APathArea(crdList width endShp))
                      printf("The area for this %s path is: %f\n" lyr_name area)
                      printf("The length for this %s path is: %f\n "
                             lyr_name
                             car(APathArea(crdList width endShp))
                            )
                 )
             )
             ("pathSeg"
              ;; ANDREW - these two attributes have never existed, so replacing with
              ;; something suitable
              ;; crdList = car(sSet)~>pathSeg
              ;; endShp = car(sSet)~>pathShape
              crdList = list(car(sSet)~>beginPt car(sSet)~>endPt)
              width = car(sSet)~>width
              endShp = nil ; there is no suitable attribute - so the next bit is irrelevant
              if((endShp == "bothArrowEnded") || (endShp == "singleArrowEnded")
                  then
                      ADialogs("warning" "Wire must have square or octagon ends.")
                      return(nil)
                 ) ;if
              if(figLength
                  then
                      if(printLine
                          then
                              printf("The length for this %s wire is: %f\n "
                                     lyr_name
                                     car(APathArea(crdList width endShp))
                                    )
                         )
                      pLength = car(APathArea(crdList width endShp))
                      return(pLength)
                  else
                      area = cadr(APathArea(crdList width endShp))
                      printf("The area for this %s wire is: %f\n" lyr_name area)
                      printf("The length for this %s wire is: %f\n "
                             lyr_name
                             car(APathArea(crdList width endShp))
                            )
                 )
             )
             ("ellipse"
              llBox = caar(sSet~>bBox)
              urBox = cadar(sSet~>bBox)
              /*
    Due to the precision of the database and the accuracy of the conic
    circle generator, we have some discrepancies especially on large figures
    that will throw out the x and y calculation to be different on the bBox
    dimensions.
    */ 
              diax = round(1000 * ((xCoord(urBox) - xCoord(llBox)) + 0.0005))
              diay = round(1000 * ((yCoord(urBox) - yCoord(llBox)) + 0.0005))
              if(diax == diay
                  then
                      radx = diax / 2000.0
                      area = 3.14159 * expt(radx 2)
                      printf("Area of circle is %f.\n" area)
                  else
                      radx = diax / 2000.0
                      rady = diay / 2000.0
                      area = 3.14159 * radx * rady
                      printf("Area of ellipse is %f.\n" area)
                 )
             )
             ("donut"
              area = 3.14159 * (expt(car(sSet)~>outerRadius 2) - expt(car(sSet)~>innerRadius
                                                                      2
                                                                     ))
              printf("Area of donut is %f.\n" area)
             )
            )
           ;case
           return(area)
          ) ; prog
     ) ; proc
    
    
    procedure(APathArea(crdlist wid endShape)
      prog(sum(crd xlen ylen pathLength)
           lastcrd = car(crdlist)
           ;; ANDREW - the issue here is that you're expecting the result
           ;; to be a float, and it's initialised to an integer, so that is what
           ;; caused the fprintf error (other than the point list being nil)
           ;; sum = 0
           sum = 0.0
           crdlist = cdr(crdlist)
           foreach(crd crdlist
             xlen = xCoord(crd) - xCoord(lastcrd)
             ylen = yCoord(crd) - yCoord(lastcrd)
             sum = sum + sqrt((xlen * xlen) + (ylen * ylen))
             lastcrd = crd
            )
           if(endShape == "squareOffset"
               then
                   sum = sum + wid
              )
           if(endShape == "octagonEnded"
               then
                   sum = sum + ((3 * wid) / 4)
              )
           if(endShape == "varExtendExtend"
               then
                   sum = sum + car(sSet)~>beginExt + car(sSet)~>endExt
              )
           pathLength = sum
           sum = wid * sum
           return(list(pathLength sum))
          )
     ) ; proc
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to Andrew Beckett

    I initially posted the wrong code (the version I posted last time) so I've edited the post and replaced it with the correct version. So don't look at what's in the email just sent, but in the thread on the community site...

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Carona
    Carona over 5 years ago in reply to Andrew Beckett

    I will take a look at it now, appreciate the help.  Sorry this took up a lot of your free time, if there are any more issues, I will sort it out myself and try not to bother you with it.  This forum has helped me in the past years ago, and I do appreciate the help you provide. Best of luck and stay safe.

    • 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