• 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. Allegro X Scripting - Skill
  3. Skill script for checking BGA pitch

Stats

  • Replies 2
  • Subscribers 20
  • Views 78
  • Members are here 0
More Content

Skill script for checking BGA pitch

SG20260713408
SG20260713408 1 day ago

This is a skill for inspecting the pitch of BGAs on a board.

If you know of a more concise and elegant code than this, please let me know. (SKILL++, OOP...)

Thank you.


/*
============================================================================================
* Tool Name : min_pitch_bga (Enhanced Version)
* Description : Automatically checks the minimum pitch of BGA components to prevent fine-pitch routing defects.
* Features :
* 1. Support multiple symbol filtering cases (Property, SymType)
* 2. Performance Optimization: Auto-bounding box shrinkage for
* high pin-count components to prevent computation lag.
* 3. Auto-sorting and reporting with an interactive .log viewer.
* Command : min_pitch_bga [Optional Pitch Value, default "0.5"]
* To change the pitch value, simply apply the desired pitch value after the command. (min_pitch_bga 1.0 or min_pitch_bga 0.5 .......)
============================================================================================
*/

axlCmdRegister("min_pitch_bga" 'min_pitch_bga ?cmdType "interactive")

procedure(min_pitch_bga(@optional (argu_bga_pitch "0.5") "S")

let((min_bga_pitch symbols loop sym_pins_locs obj1 objPairs pitch_datas min_pitch_data

pair_count var_x var_y delta_x delta_y refdes sym_xy layer sym_rot all_x_loc all_y_loc min_x min_y max_x max_y sym_pins total_results)


min_bga_pitch = atof(argu_bga_pitch)

when(min_bga_pitch

;;========================================================================================

;;Comment : Please select and use the case that fits the situation.

;;Comment(Case1) : Use when a symbol(footprint) is given a property name("DFA_DEV_CLASS") and a property value("bga").

;; Property values are entered by the user, so they are case-sensitive.


symbols = foreach(mapcan item axlSelectByProperty("symdef" "DFA_DEV_CLASS" "bga") ~> instances item) ;; Use if applicable to Case 1

;;symbols = foreach(mapcan item axlSelectByProperty("symdef" "DFA_DEV_CLASS" "bg*" t) ~> instances item) ;; Use if applicable to Case 1

;;symbols = foreach(mapcan item axlSelectByProperty("symdef" "REF_PATTERN_NAME" "BGA*" t) ~> instances item) ;; Use if applicable to Case 1

;;========================================================================================

;; Comment(Case2) : The name given when generating the symbol(footprint).

;; In other words, when the symbol name(footprint name) starts with "BGAXXXXXXXX_XXX_XXX"


;;symbols = axlSelectByName("SYMTYPE" "BGA*" t) ;; Use if applicable to Case 2, Delete ";;" and use

;;========================================================================================

axlClearSelSet()

if(symbols then

foreach(symbol symbols

loop = t

sym_rot = nil

sym_pins = nil

sym_pins_locs = nil

all_x_loc = nil

all_y_loc = nil

objPairs = nil

pitch_datas = nil

min_pitch_data = nil

pair_count = nil

var_x = nil

var_y = nil

delta_x = nil

delta_y = nil

sym_xy = symbol -> xy

refdes = symbol -> refdes

unless(refdes refdes = "No RefDes")

layer = if(symbol -> isMirrored then "BOTTOM" else "TOP")

sym_pins = setof(e symbol -> pins e -> number != "" || e -> isMech != t)


when(sym_pins && length(sym_pins) > 1

sym_rot = symbol -> rotation

if(axlGeoEqual(sym_rot 0.0) || axlGeoEqual(sym_rot 90.0) || axlGeoEqual(sym_rot 180.0) || axlGeoEqual(sym_rot 27.0) then

sym_pins_locs = sym_pins ~> xy

else

foreach(sym_pin sym_pins

sym_pin_xy = sym_pin -> xy

rot_pin = axlGeoRotatePt(minus(sym_rot) car(sym_pin_xy):cadr(sym_pin_xy) car(sym_xy):cadr(sym_xy))

sym_pins_locs = cons(rot_pin sym_pins_locs)

)

)


all_x_loc = foreach(mapcar item sym_pins_locs car(item))

all_y_loc = foreach(mapcar item sym_pins_locs cadr(item))


var_x = apply('min all_x_loc)

sym_x = apply('max all_x_loc)

var_y = apply('min all_y_loc)

sym_y = apply('max all_y_loc)

delta_x = abs(sym_x - var_x)

delta_y = abs(sym_y - var_y)

sym_xy = list((sym_x - (delta_x / 2)) (sym_y - (delta_y / 2)))


delta_x = delta_x / 30

delta_y = delta_y / 30

sym_pins_locs = setof(e sym_pins_locs axlIsPointInsideBox(e list(sym_xy list(var_x var_y))))


when(length(sym_pins_locs) > 1

pair_count = (length(sym_pins_locs) * (length(sym_pins_locs) - 1)) / 2

when(pair_count > 1500

while(loop

var_x = var_x + delta_x

var_y = var_y + delta_y

delta_x = (car(sym_xy) - var_x) / 30

delta_y = (cadr(sym_xy) - var_y) / 30

sym_pins_locs = setof(e sym_pins_locs axlIsPointInsideBox(e list(sym_xy list(var_x var_y))))

pair_count = (length(sym_pins_locs) * (length(sym_pins_locs) - 1)) / 2

when(pair_count < 1500 loop = nil)

)

)

when(sym_pins_locs

while(sym_pins_locs

obj1 = car(sym_pins_locs)

sym_pins_locs = cdr(sym_pins_locs)

foreach(obj2 sym_pins_locs objPairs = cons(list(obj1, obj2), objPairs))

)

)

when(objPairs

foreach(objPair objPairs

pitch_datas = cons(axlDistance(car(objPair) cadr(objPair)) pitch_datas)

)

min_pitch_data = car(sort(pitch_datas 'lessp))

)

when(min_pitch_data

when(min_pitch_data < min_bga_pitch

axlHighlightObject(symbol)

total_results = cons(list(layer refdes min_pitch_data symbol -> xy symbol -> name) total_results)

)

)

)

)

)

total_results = reverse(sortcar(total_results 'axlStrcmpAlpNum))

MPB_Create_log_File(total_results min_bga_pitch)

else

printf("###### BGA cannot be found. !! ######\n")

)

)

)

)


procedure(MPB_Create_log_File(total_results min_bga_pitch)

let((err_count Date Min_Pitch_BGA_Log_File)

err_count = 0

Date = (getCurrentTime)
Date = parseString(Date " ")
Date = strcat(nth(3 Date) " " nth(0 Date) " " nth(1 Date) " " nth(2 Date))

Min_Pitch_BGA_Log_File = outfile("./Min_Pitch_BGA.log" "w")

fprintf(Min_Pitch_BGA_Log_File "\nDATE : %s\n" Date)

fprintf(Min_Pitch_BGA_Log_File "\nTarGet Pitch : %f\n" min_bga_pitch)

fprintf(Min_Pitch_BGA_Log_File "\nSyntax : nIndex, Layer, RefDes, Pitch, Symbol_XY, Symbol_Name\n")

fprintf(Min_Pitch_BGA_Log_File "\n=========================================================================\n")

if(length(total_results) == 0 then

fprintf(Min_Pitch_BGA_Log_File "\n=========================================================================\n")

fprintf(Min_Pitch_BGA_Log_File "\n Total Error Count = 0\n")

else

fprintf(Min_Pitch_BGA_Log_File "\nIndex, Layer, RefDes, Pitch, Symbol_XY, Symbol_Name\n")

foreach(total_result total_results

err_count = ++err_count

fprintf(Min_Pitch_BGA_Log_File "\n%d, %s, %s, %f, %L, %s\n" err_count nth(0 total_result) nth(1 total_result) nth(2 total_result) nth(3 total_result) nth(4 total_result))

)

fprintf(Min_Pitch_BGA_Log_File "\n=========================================================================\n")

fprintf(Min_Pitch_BGA_Log_File "\n Total Error Count = %d.\n" err_count)

)

close(Min_Pitch_BGA_Log_File)

axlShell("viewlog ./Min_Pitch_BGA.log")

)

)

  • Sign in to reply
  • Cancel
Parents
  • Elecguy
    Elecguy 16 hours ago

    Just took a quick look at it and it seems good. Any special conditions for the board where it should be used?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Reply
  • Elecguy
    Elecguy 16 hours ago

    Just took a quick look at it and it seems good. Any special conditions for the board where it should be used?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Children
  • SG20260713408
    SG20260713408 8 hours ago in reply to Elecguy

    There are no special conditions.

    I uploaded the relevant code a while ago, but I have improved the parts that were lacking and uploaded it again.

    I was just curious to see what ideas others might have.

    Thank you.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Cadence Guidelines

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.

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

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