• 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. Trouble removing symbols and symdefs

Stats

  • Replies 2
  • Subscribers 18
  • Views 9870
  • Members are here 0
More Content

Trouble removing symbols and symdefs

RasmusDK
RasmusDK over 7 years ago

Greetings, dear SKILL-proficient peers,

I am new in the SKILL community, and new to development in SKILL. I have a background as a programmer, and a more limited understanding of PCB design and the PCB Editor. I hope you will bear with me, if I ask something that seem to have an obvious solution to you.

I am developing my first SKILL application for use in PCB Editor, and I have encountered some strange behaviour, that I cannot understand or explain. As such, I have provided an example code, which should be usable on any board file. I have tested it on the board DemoK-ClassColor.brd, which is a demo design in 17.2.

The core of the issue is, that I am unable to delete the symbol and symdef from the design. I make the symbol using SKILL (as seen in the code), but when I try to delete it using SKILL, strange behaviour occur. In some cases, the symbol will leave remnants at the 0,0 position on the board. Attempting to debug with printf, shows that sometimes the symbol is not present, even though it is visible in the design. In either case, I do not seem to be able to remove the symdef.

I have researched any documentation I could find to try an wrap my head around this issue, but to no avail. I hope one of you would read through my code, shake your head at my silly mistake, and enlighten me. Alternatively, I will settle for someone who can explain how I would go about removing the symdef and symbol (including all original and attached artifacts) from the design.

The file is uploaded as MakeTOC.txt, which will need to be renamed to MakeTOC.il. I have also tried to attached the DemoK-ClassColor.brd, but it seems that it did not work. I hope you will find it in your demo designs, or can substitute with another design.

Fullscreen 4073.MakeTOC.txt Download
; 1. Load this script file into PCB Editor
; load("./MakeTOC.il")
; 2. Execute testbrokencleanup()
; A TOC-symbol appears in the top left corner of your design
; No message about matching symbols or symdefs appear - this is expected behaviour
; 3. Execute testbrokencleanup() again.
; Expected behaviour: Both symbol and symdef is found and then removed, then a new TOC-symbol appears
; Observed behaviour: Neither symbol nor symdef is found or removed. The TOC was placed.
; Additional observation: A remnant of the symbol is placed at 0,0. The remnant is not recognized as a symbol, but contains all the lines and text of the original symbol, but none of the text or shapes that were added later.
; 4. Manual Cleanup: Use General Edit to select the symbol and remnant (text and lines) respectively, and remove them. The Symbol is removed with "Unplace Component" and the remnant is removed by selecting all artifacts and then "Delete".
; 5. Execute testbrokencleanup() again.
; Expected behaviour: No symbol nor symdef is recognized. The TOC is placed
; Observed behaviour: A message is displayed that a Symbol was found. The TOC was placed.
; 6. Manually delete the symbol like you did in step 4
; 7. Execute testbrokencleanup() again.
; Now there is no message indicating that any symbol or symdef exists


procedure(drawRectShape(llx lly urx ury layer)
	path = axlPathStart(list(
		llx:lly
		llx:ury
		urx:ury
		urx:lly
		llx:lly
	))
	axlDBCreateShape(path t layer nil)
);procedure

procedure( testbrokencleanup()
	layer = "DRAWING FORMAT/NSCOLOR_LEGEND"
	; Create list of items and colors
	input_list = makeTable("colorlist" nil)
	input_list["Item A"] = 16
	input_list["Item B"] = 32
	input_list["Item C"] = 48
	input_list["Item D"] = 64
	input_list["Item E"] = 96
	
	; ################################
	; Attempt to clean up the design
	; ################################
	
	; Clean up symbols
	slist = axlDBGetDesign()->symbols
	foreach(sid slist
		when(sid->name && lowerCase(sid->name) == "_my_name"
			printf("I have found a matching Symbol with name: %L\n" sid->name)
			foreach(cid sid->children
				axlDeleteObject(cid)
			)
			axlDeleteObject(sid)
		)
	)
	
	; Clean up symbol definitions
	slist = axlDBGetDesign()->symdefs
	foreach(sid slist
		when(sid->name && lowerCase(sid->name) == "_my_name"
			printf("I have found a matching Symbol Definition with name: %L\n" sid->name)
			foreach(inst sid->instances
				axlDeleteObject(inst)
			)
		)
	)
	
	
	; ################################
	; Prepare Symbol
	; ################################
	; Headers
	columna = "COLUMN A"
	columnb = "COLUMN B"
	
	; Get Character dimension properties
	tblockno = 2
	text = axlGetParam(strcat("paramTextBlock:" sprintf(nil "%d" tblockno)))
	charHeight = text->height ; Height of the text
	charWidth = text->width ; Width of a character
	charSpacing = text->charSpace ; Space between characters
	charThickness = text->photoWidth ; Width of the "pen" writting the letter
	textloc = make_axlTextOrientation(?textBlock tblockno, ?rotation 0.0, ?mirrored nil, ?justify "left")
	
	; Table Dimensions
	linew = axlMKS2UU("0.15 millimeters") ; Width of a line in the table
	items = length(input_list) ; Number of items in the legend
	tableheight = (items + 1)* charHeight * 2 
	ctotwidth = (charSpacing + charWidth + charThickness + charSpacing) ; The total width of a character, with space between the chars
	tablewidth = charSpacing + ctotwidth * strlen(columna) + ctotwidth * strlen(columnb) + charSpacing
	llx = 0
	lly = 0 - tableheight
	px = llx + charSpacing + charWidth ; X where the text in the first column is written
	tx = px + strlen(columna) * ctotwidth + charSpacing + charSpacing ; X where the text in the second column is written
	ly = 2 * charHeight ; offset required to shift to the next cell in a column
	urx = 0 + tablewidth
	ury = 0
	; Defining the "drawing area" of the symbol. the 2* linew is a buffer to avoid issues with fat lines
	symextend = list(llx - 2 * linew : lly - 2 * linew 
					urx + 2 * linew : ury + 2 * linew)
	
	; Initialize layer
	when(axlIsLayer(layer)
		axlDeleteByLayer(layer)
		my_layer = axlLayerGet(layer)
		axlDeleteObject(my_layer)
	)
	axlLayerCreateNonConductor(layer)
	axlVisibleLayer(layer t)
	axlVisibleUpdate(t)
	
	; ################################
	; Create Symbol and Symdef
	; ################################
	; Initialize symdef (This draws a table with two columns and 6 items, including header)
	symdef = axlDBCreateSymDefSkeleton('("_my_name" "mechanical") symextend)
	axlDBCreateLine(list(llx:lly llx:ury) linew layer 'line symdef)
	axlDBCreateLine(list(llx:ury urx:ury) linew layer 'line symdef)
	axlDBCreateLine(list(urx:ury urx:lly) linew layer 'line symdef)
	axlDBCreateLine(list(	llx + charSpacing + ctotwidth * strlen(columna) + charSpacing: lly 
							llx + charSpacing + ctotwidth * strlen(columna) + charSpacing:ury) 
							linew layer 'line symdef)
	
	axlDBCreateText(columna px:ury - 1.5 * charHeight  textloc layer symdef)
	axlDBCreateText(columnb tx:ury - 1.5 * charHeight  textloc layer symdef)
	for( i 1 length(input_list)+1 
		axlDBCreateLine(
			list(
				llx : ury - i * ly 
				urx : ury - i * ly
			) linew layer 'line symdef)
	)
	tablex = caar(axlExtentDB('windowfit))
	tabley = caadr(axlExtentDB('windowfit))
	; Place the symbol
	symboldbid = axlDBCreateSymbol('("_my_name" "MECHANICAL") tablex:tabley)
	
	; Add text and shapes to the symbol
	item = 1
	foreach(key input_list
		textdbid = axlDBCreateText(key tablex + px:tabley + ury - 1.5 * charHeight - item * ly textloc layer)
		axlSymbolAttach(car(symboldbid) car(textdbid)) ; attach text to symbol
		; Create the shape
		colorShapedbid = drawRectShape(tablex + tx 
							tabley + ury - 1.5 * charHeight - item * ly 
							tablex + tx + ctotwidth * 3.5 
							tabley + ury - 0.5 * charHeight - item * ly 
							layer)
		; Remove the group members if the group already exists. Otherwise, create the group
		grpName = strcat("_my_name" key)
		grp = car(axlSelectByName("GROUP" grpName nil))
		axlClearSelSet()
		if( grp then
			when(grp 
			axlDeleteObject(grp->groupMembers))
		else
			grp = axlDBCreateGroup(grpName "generic" nil)
		)
		when(colorShapedbid
			axlDBAddGroupObjects(grp car(colorShapedbid))
		)
		axlSymbolAttach(car(symboldbid) car(colorShapedbid))
		
		axlCustomColorObject(grp input_list[key])
		axlDBAddProp(list(car(colorShapedbid)) list("NSCOLOR" key))
		item++
	)
	t
)

  • Cancel
  • Sign in to reply
Parents
  • B Bruekers
    B Bruekers over 7 years ago

    Put after each foreach section containing axlDeleteObject() calls a axlDBRefreshId(nil) call. 

    Then at the end of the function you do a axlUIWUpdate(nil) to refresh the drawing area.

    Btw, you can pass multiple dbId's at axlDeleteObject, so for example to delete all placed symbols and definitions:

    axlDeleteObject(axlDBGetDesign()~>symbols 'ripup)

    axlDeleteObject(axlDBGetDesign()~>symdefs 'ripup)

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • RasmusDK
    RasmusDK over 7 years ago in reply to B Bruekers

    Thank you, B Bruekers. This solved my issue perfectly. I have read the documentation for axlDBRefreshId(nil), and I am not sure I completely understand why this Refresh is needed. I suspect I may have some misconceptions about how data is passed. Could I bother you for a short explanation?

    I should have added the axlUIWUpdate(nil) to my example. In my actual code, I have it at the end of a case segment, because each case would require that call.

    Thank you for the tip about accepting multiple dbids to axlDeleteObject. I will optimize my code to take advantage of this feature.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Reply
  • RasmusDK
    RasmusDK over 7 years ago in reply to B Bruekers

    Thank you, B Bruekers. This solved my issue perfectly. I have read the documentation for axlDBRefreshId(nil), and I am not sure I completely understand why this Refresh is needed. I suspect I may have some misconceptions about how data is passed. Could I bother you for a short explanation?

    I should have added the axlUIWUpdate(nil) to my example. In my actual code, I have it at the end of a case segment, because each case would require that call.

    Thank you for the tip about accepting multiple dbids to axlDeleteObject. I will optimize my code to take advantage of this feature.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Children
No Data
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.

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

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