Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The Structure and Syntax of the CadEnhance Symbol Description Language (SDL) is described here

Table of Contents

Symbol Description Language Structure

The Symbol Description Language (SDL) was designed to be uber-efficient at describing schematic symbol construction, while still being simple to understand and easy to enter.

SDL KEY_WORDS and constructs Constructs are never Not case-sensitive. 

An SDL File is a collection of ordered SYMBOL_NAME_DEFINITIONs enclosing DEFINITIONS which enclose MATCH_STATEMENTS and SpacerSPACER_CommandsCOMMANDS.

The number of symbols you create is generally greater than or equal to the number of SYMBOL_NAME_DEFINITIONs and MATCH_STATEMENTS and Spacer_Commands DEFINITIONS.

Moving pins from one symbol to another is generally a cut and paste operation to move MATCH_STATEMENTS in between a different SYMBOL_NAME_DEFINTION.

To add another symbol, you just add another SYMBOL_NAME_DEFINTION with a new name and add or move your MATCH_STATEMENTS between the start and end.

SYMBOL_NAME_DEFINITIONS, MATCH_STATEMENTS and SPACER_COMMANDS can also appear between the start and end of special LoopLOOP_DirectivesDIRECTIVES

SDL also supports Simple Variable Substitution VARIABLE_SUBSTITUTION commands.

SYMBOL_NAME_DEFINITION

A SYMBOL_NAME_DEFINITION is used to instruct partBuilder to start placing matching pins into a named symbol.

It has 2 parts, a beginning:

SymbolName=

and an end which is just the terminating semicolon.

';'

The SymbolName is the actual name you want to use for the symbol and it should not contain spaces

 in the simple sample file, the start of the first SYMBOL_NAME_DEFINITION  was

DRAM_ACTL_PINS=

That was followed by several MATCH_STATEMENTS  

and was terminated by the

';' 

character

It instructed partBuilder to create a Symbol named DRAM_ACTL_PINS as a place to add the pins matching all the MATCH_STATEMENTS that follow until the SYMBOL_NAME_DEFINITION is closed.

MATCH_STATEMENTS

MATCH_STATEMENTS are  what tell partBuilder which pins to place within the current symbol, what side to place them on  and any other modifier to enable creating special graphics or properites for the pins that match.

MATCH_STATEMENTS are built out of   LOCATOR, MODIFIER and PIN_MATCH elements

The simplest MATCH_STATEMENT only contains a LOCATOR and a PIN_MATCH, and is entered as

LOCATOR=>PIN_MATCH

The equal-Arrow "=>" separates the PIN_MATCH from the list of LOCATORS and MODIFIERS

MODIFIERS are added on the left hand side of the '=>' either before or after the LOCATOR.

For clarity and easier cut and paste in Excel, our examples will show the LOCATOR first.

MODIFIERS and LOCATORS are separated by the colon character ':' as follows;

LOCATOR:MODIFIER1:MODIFIER2:...MODIFIERn=>PIN_MATCH

There is no restriction on the number of valid MODIFIERS that can be included in  a MATCH_STATEMENT. 

It should be obvious that only one LOCATOR is used per MATCH_STATEMENT 

Some simple MATCH_STATEMENTS are provided in the table below to help get a feel for what they look like as you read more about the structure of them.

Examples of Simple MATCH_STATEMENTS.

MATCH_STATEMENTSimple Operation*Notesleft=>a[15:0]

puts bus pins a15...a0 on the left hand side of the symbol starting from the current position on the left hand side

right:dpair=>clk_p

puts diff_pair mates clk_p and clk_n** consceutively on the right hand side of the symbol using the currently configured defaults for diff pair spacing

**presumably clk_n

top:is_pin=>1..17places pins 1 to pin 17 on the top of the symbolbot:bubble=>reset_nplaces pin matching reset_n on the bottom and puts an inversion bubble between the pin and the symbol

LOCATOR Elements

The purpose of the LOCATOR element is to tell partBuilder what side of the symbol to place the matching pins on.

Part builder creates one list for each side  of the symbol, and as it sees a locator, it pushes the matching pins A SYMBOL_NAME_STATEMENT may often create more than one symbol if the number of pins that the MATCH_STATEMENTS assign to that symbol are greater than the current Configuration Setting of the SYMBOL_PIN_LIMIT.  For instance, a GROUND symbol definition often contains only one MATCH_STATEMENT to assign any pin matching GND to that symbol. If the part has 400 Ground pins and the SYMBOL_PIN_LIMIT is set to 100, it will create 4 SYMBOLS and create a new name for each of the extra symbols it creates (GROUND, GROUND_1, GROUND_2 and GROUND_3)

MATCH_STATEMENTS

MATCH_STATEMENTS are  what tell partBuilder which pins to place within the current symbol, what side to place them on  and any other modifier to enable creating special graphics or properites for the pins that match.

MATCH_STATEMENTS are built out of   LOCATOR, MODIFIER and PIN_MATCH elements

The simplest MATCH_STATEMENT only contains a LOCATOR and a PIN_MATCH, and is entered as

LOCATOR=>PIN_MATCH or LOCATOR>>PIN_MATCH 

The equal-Arrow "=>" or double-Arrow (recently added for easier entry in excel) separates the PIN_MATCH from the list of LOCATORS and MODIFIERS

MODIFIERS are added on the left hand side of the '=>' or '>>' either before or after the LOCATOR.

For clarity and easier cut and paste in Excel, our examples will show the LOCATOR first.

MODIFIERS and LOCATORS are separated by the colon character ':' as follows;

LOCATOR:MODIFIER1:MODIFIER2:...MODIFIERn=>PIN_MATCH

There is no restriction on the number of valid MODIFIERS that can be included in  a MATCH_STATEMENT. 

Only one LOCATOR is used per MATCH_STATEMENT 

Some simple MATCH_STATEMENTS are provided in the table below to help get a feel for what they look like as you read more about the structure of them.


Examples of Simple MATCH_STATEMENTS 

MATCH_STATEMENTSimple Operation*Notes
left=>a[15:0]

puts bus pins a15...a0 on the left hand side of the symbol starting from the current position on the left hand side



right:dpair>>clk_p


puts diff_pair mates clk_p and clk_n** consecutively on the right hand side of the symbol using the currently configured defaults for diff pair spacing

**presumably clk_n

showing double-arrow equivalence to =>

top:is_pin=>1..17places pins 1 to pin 17 on the top of the symbol
bot:bubble>>reset_nplaces pin matching reset_n on the bottom and puts an inversion bubble between the pin and the symbolshowing double-arrow equivalence to =>



LOCATOR Elements

The purpose of the LOCATOR element is to tell partBuilder what side of the symbol to place the matching pins on. 

Valid Locators are mostly obvious, and are explained in the following table

LOCATOREffect
LEFTplace matching pins on the Left Hand Side of the symbol
RIGHTplace matching pins on the Right Hand Side of the symbol
BOTHdistribute the matching pins equally on the Left and Right Hand sides of the symbol
TOPplace matching pins on the top side of the symbol
BOT or BOTTOMplace matching pins on the bottom side of the symbol
AUTO

place matching INPUT pins on the Left Hand Side of the symbol

place matching OUTPUT or INOUT pins on the Right Hand Side of the symbol

distribute all other pin_types equally on the Left and Right Hand Sides of the symbol

MODIFIER

If the LOCATOR is not provided, it implies AUTO. This is not recommended going forward, but many older SDL files were written without LOCATORS.

MODIFIER Elements

Valid Modifiers are explained in the following table. Modifiers may be further broken down by partBuilder to impart extra information as shown

PIN_MATCHEffectNOTESDQWill match any pin that contains DQDQSWill match any pin that
MODIFIEREffectSpecial Notes
DOT or BUBBLEInstructs PartBuilder to Add an Inversion Bubble in the proper place for any matching pin
CLK or CLOCKInstructs PartBuilder to Add a clock indicator like '>' in the proper place for any matching pin
SHORTInstructs PartBuilder to create a SHORT Pinworks for Eagle and Orcad Symbols
ZEROInstructs PartBuilder ORCAD zero Length Pins
HIDDEN

Instructs partBuilder to create a Hidden Pin.


This currently only works with AllegroHDL and is not reccomended
VECTOR or VECTORED

Instructs PartBuilder to create one symbol pin to represent 2 or more pins.


This currently only works with AllegroHDL and can be used to significantly reduce the size of power symbols
IS_PIN

Instructs PartBuilder that the PIN_MATCH should be applied to the Pin Number instead of the Pin Name

This makes it very easy to build parts where you layout the pins like they appear on the physical symbol.

Also very efficient when building connectors organized by row or column

DPAIR

DPAIR_{OPT_SUFFIX}

Instructs PartBuilder to place both the matching diff_pair pin AND its mate pin in sequenceThe DPAIR Modifier can be appended with a suffix to impart more information to override the default diff_pair spacing that is configured for partBuilder.
PSG_{swapGroupName}

Instructs PartBuilder that the matching pins are a member of a PIN_SWAP_GROUP.

PartBuilder maintains a list of all the PIN_SWAP group names and properly annotates the matching pins so they can be included in the PIN_SWAP in the PCB side.

The name of the pinSwapGroup must be provided in the suffix to the PSG_ modifier.

This is currentyl supported for AllegroHDL

PIN_MATCH Elements

The PIN_MATCH Element is the string that PartBuilder uses to test all pins in the extracted pinData for a match. 

PIN_MATCHES may be entered as a simple string or with a wildcard.

PartBuilder treats all the PIN_MATCHES it extracts from the SDL as a Regular Expression. It actually converts the wildcard '*' internally to the '.*' used in Regular Expressions.

They may also be entered as a valid Perl Regular Expression.

PartBuilder treats all the PIN_MATCHES it extracts from the SDL as a Regular Expression. It actually converts the wildcard '*' internally to the '.*' used in Regular Expressions.

A Regular Expression is a pattern describing a certain amount of Text.  The Regular Expression can be very general or very restrictive.

In the simplest context, PartBuilder uses a regular expressions to determine if a Pin contains the PIN_MATCH pattern. 

If the PIN_MATCH  is entered as "DQ", PartBuilder will match any pin that Contains DQ anywhere in the pinname.

Excellent references for Regular Expressions exist on the web like the one at this link.

 

Widget Connector
width600
urlhttp://www.regular-expressions.info/quickstart.html
height400

PartBuilder Bus-Enhanced Regular Expressions.

PartBuilder does some behind the scenes work to change the PIN_MATCH  Regular Expressions to enable  placing  bussed pins seamlessly

Its not truly necessary to understand this detail, but In a normal regular expression, the '[]' characters in the pattern match enclose a list of characters to match against

If you were comparing a list of pins dq7 dq6 dq5 dq4 dq3 dq2 dq1 and  dq0 using the regular Expression 'dq[0:7]' , the pattern would only match dq0 and dq7 (and funny enough dq:).

You could get more useful results with 'dq[0-7]' (because 0-7 inside the square brackets says to match any character between 0 and 7) but unfortunately that would not enforce the order of the pins. 

In order to work around this, when PartBuilder sees the 'DQ[0:7]' in a PIN_MATCH it  expands it to 8 seperate PIN_MATCHES DQ0, DQ1, DQ2... DQ7** which are then used as pattern matches.

It also maintains the order of the bits so that they will be added to the symbol in LSB→MSB order if you enter busName[0:7] or MSB→LSB order if you enter busName[7:0]. As described in the table below, it also appends whats called a zero-width-lookahead assertion at the end fo each  to insure that DQ18 doesn't match DQ1 but it would still allow a match of dq1_p

(**it also appends a  zero-width-lookahead assertion to each match to ensure that no other digits are following the ones we want so that DQ18 doesn't match DQ1) 

Examples of Useful PIN_MATCH Regular Expressions

an IS_PIN=>PIN_MATCH must describe existing PinNumbers for the device.

An IS_PIN=>PIN_MATCH can be used to specify a single pin like:

:IS_PIN=>A5 or :IS_PIN=>88

or a range of pins like:

:IS_PIN=>A1:AY34 

which uses the BGA expansion rules to describe all the BGA Pins (see PinData Verification Checks for more details on BGA Pin Expansion rules)

or :IS_PIN=>1..25 or IS_PIN=>1-25 or IS_PIN=>1:25

or :IS_PIN=P[1:11]  (support for this was added in versions after v.20.11.1) 

Pin Ranges can also be entered in reverse like:

11..1 or P[11..1] or A[5..3]

This makes it very easy to build parts where you layout the pins like they appear on the physical symbol for a TQFP or DIP device

This Also makes it extremely efficient to build connectors organized by row or column


DPAIR

DPAIR_{OPT_SUFFIX}

Instructs PartBuilder to place both the matching diff_pair pin AND its mate pin in sequenceThe DPAIR Modifier can be appended with a suffix to impart more information to override the default diff_pair spacing that is configured for partBuilder.
PSG_{swapGroupName}

Instructs PartBuilder that the matching pins are a member of a PIN_SWAP_GROUP.

PartBuilder maintains a list of all the PIN_SWAP group names and properly annotates the matching pins so they can be included in the PIN_SWAP in the PCB side.

The name of the pinSwapGroup must be provided in the suffix to the PSG_ modifier.

This is currently supported for AllegroHDL

BESTInstructs PartBuilder that this Match should be accepted without going through the longest match algorithmsee Description of BEST Modifier below
IF_LAST_MATCHThis modifier is added to SPACER_COMMANDS within loops to avoid adding unnecessary spaces.see Description of IS_LAST_MATCH modifier below
NO_WARN

PartBuilder will not print a warning for any PIN_MATCH with no matching pins if this modifier is applied

PartBuilder normally prints a warning for any PIN_MATCH in the SDL for which no pins were found. This can get very noisy in FPGAs where we allow many PIN_MATCHES to be empty.
EXACTTreat the PIN_MATCH as an exact match.

to match the PIN_NAME must EQUAL the PIN_MATCH

(if EXACT is not specified, the PIN_NAME must Contain the PIN_MATCH)

This can be used to work around rare corner-cases that might have be fixed in another release of the tool

PIN_SPACE_{NUM_SPACES}

The PIN_SPACE modifier allows the user to specify extra spacing when adding the pins that match the PIN_MATCH statement. 

PIN_SPACE_1 tells part builder to add 1 extra spacer between each added pin.


This command is very helpful if the user wants to add power pins or a full bus with extra spacing between the individual pins, but they don't want to change the global spacing grid for all the other pins. 

Video Demo


Anchor
PIN_MATCH_REGEX
PIN_MATCH_REGEX
PIN_MATCH Elements

The PIN_MATCH Element is the string that PartBuilder uses to test all pins in the extracted pinData for a match. 

PIN_MATCHES may be entered as a simple string or with a wildcard.

They may also be entered as a valid Perl Regular Expression.

PartBuilder treats all the PIN_MATCHES it extracts from the SDL as a Regular Expression. It actually converts the wildcard '*' internally to the '.*' used in Regular Expressions.

In the simplest context, PartBuilder uses a regular expressions to determine if a Pin contains the PIN_MATCH pattern. 

If the PIN_MATCH  is entered as "DQ", PartBuilder will match any pin that Contains DQ anywhere in the pinname.

For more background Navigate to this page: Regular Expressions In CadEnhance Tools

Examples of Useful PIN_MATCH Regular Expressions

PIN_MATCHEffectNOTES
DQWill match any pin that contains DQ
DQSWill match any pin that contains DQS
^DQS0Will match any pin that STARTS with DQS0the caret '^' enforces the start of word boundary
DQ[7:0]

PartBuilder will expand this to 8 individual matches DQ7, DQ6, DQ5... DQ0**

it will match and maintain the order of any pins that contain any of those patterns

DQ7, DRAM_DQ6_BUS, DQ5_F would all match

DQA7, DQ06... would not match

DQ3_P and DQ1_N would match but

DQ31_P and DQ18_N would not


In the category of too much information:

DQ1 DQ18_N seems like it would should match because it contains DQ1, but when partBuilder expands the PIN_MATCH

it adds**the also adds what is called a zero-width lookahead look-ahead assertion to assure that any character except another number can matchthe regular expression.

This ensures that the pattern will not match if there is a another digit immediately following the last digit.

^DQ[0:7]

PartBuilder will match any pin that STARTS with DQ0 or DQ1... DQ7

L_DQ0 would not match


DQ[0:7]$

PartBuilder will match any pin that ENDS with DQ0 or DQ1 ... DQ7

DQ0_L would not match since it doesn't end with 0,1,2,3,,4,5,6,or 7

the dollar Sign '$' enforces the end of word boundary
^DQ[0:7]$

PartBuilder will expand to a list of matches

^DQ0$, ^DQ1$, ^DQ2$... ^DQ7$

and will only match DQ0,DQ1,DQ2,DQ3...DQ7...

Would not match L_DQ0, DQ00, DQ01 .....

The caret '^' says it must start with the D and the $ says it must end with the digit at the end

IO_.*?_35

or

IO_*_35

PartBuilder will match any pin that contains IO_, and _35

it would match:

IO__35, IO_A_35, IO1_PIN1_35,

IO_THIS_IS_A_LONG_NAME_35

it would not match IO_A_36, IO_A_37

nor would it match IO35 or IO_35 (since we need 2 underscores)


the '.*?' (which could also be be entered as '*') looks for any number of any of characters

partBuilder converts the '*' to a '.*?' to make it easier to enter wildcards for those not familiar with

Regular Expressions. The ? is special and necessary because it makes the match stop if it sees the _35 after it.


This particular regular Expression is very powerful when building parts with Pins that have

similar names grouped into numeric banks like FPGAs and CPLDS.

IO\d+_\d+

Would match:

IO0_5, IO7324_8910

Would not match:

IO0A_5 because it is not looking for the 'A'

or IO_5 because we need a digit after the IO

the \d+ finds 1 or more consecutive digits in a row.

if we used "IO\d*_\d+", it would match IO_5 because \d* says find 0 or more consecutive digits.

Handling

Assigning Pins that

Match

match multiple

PIN

MATCH_

MATCHES

STATEMENTS

It takes PartBuilder 2 passes to place matching pins into the proper symbols. It first goes through every pin_match and attaches a list of every MATCH_STATEMENT that each pin matches to the pin. It then makes a second pass, and chooses the MATCH_STATEMENT with the longest PIN_MATCH string to pick the proper MATCH_STATEMENT for that pin. 

Lets provide a simple example:

We have are building a fictional part with that has 100 pins named GND, 8 pins named SGND AGND and 2 pins named GTH_RX_SGND AGND and 2 named GTH_TX_SGNDAGND

We have the following 2  SYMBOL_NAME_DEFINTIONS DEFINITIONS in the SDL File

GND_SYM=
LEFT=
>SGND
>AGND
LEFT=>SPACER[1:0]
BOTH=>GND
;
  1. PartBuilder parses the SDL File
  2. It goes through all the pins in the part to find all possible PIN_MATCHES to assign each pin
    1. It Adds the BOTH=>GND MATCH_STATEMENT from the GND_SYM the GND,
SGND
    1. AGND, GTH_RX_
SGND
    1. AGND and GTH_TX_
SGND
    1. AGND pins
    2. It Adds the LEFT=
>SGND
    1. >AGND MATCH_STATEMENT from the GND_SYM symbol to the 8
SGND
    1. AGND pins and the 2 GTH_RX_
SGND
    1. AGND and 2 GTX_TX_
SGND
    1. AGND pins
    2. It Adds the LEFT=>GTH_RX_
SGND
    1. AGND MATCH_STATEMENT to the 2 GTH_RX_
SGND
    1. AGND pins
    2. It Adds the RIGHT=>GTH_TX_
SGND
    1. AGND MATCH_STATEMENT to the 2 GTH_TX_
SGND
    1. AGND_pins
  1. Next PartBuilder goes back through all the part pins and chooses the MATCH_STATEMENT with the longest PIN_MATCH for each pin
    1. The 8
SGND
    1. AGND pins end up being placed first on the LEFT side in the GND_SYM with the LEFT=
>SGND
    1. >AGND MATCH_STATEMENT
    2. All the 100 GND pins end up being placed in the GND_SYM symbol with the BOTH=>GND MATCH_STATEMENT
    3. The 2 GTH_RX_
SGND
    1. AGND pins end up being placed in the GTH_BLOCK symbol with LEFT=>GTH_RX_
SGND
    1. AGND
    2. The 2 GTH_TX_
SGND
    1. AGND pins end up being placed in the GTH_BLOCK symbol with RIGHT=>GTX_TX_
SGND
    1. AGND
GTH_BLOCK=
LEFT:dpair=>GTH_RX[7:0]_P
RIGHT:dpair=>GTH_RX[7:0]_N
!BSS+2
LEFT=>GTH_RX_
SGND
AGND
RIGHT=>GTH_TX_
SGND
AGND
;

Because of this 2 pass approach, the user does not need to concern themselves with what order a MATCH_STATEMENT is placed or what SYMBOL_DEFINTION DEFINITION it is placed in.

They do need to should be aware that the 2 pass approach is necessary and that they need to assign more specific PIN_MATCHES  if they want to seperate separate Pins like the example that have common strings in them 

Anchor
SPACER
BEST_MODIFIER_
COMMANDS

`FOR (var=start;var<=end;var inc/dec) 

`FOR VAR_NAME IN LIST 

`FOR VAR_NAME_LIST IN LIST 

`REPEAT n LOOP
DESC

SPACER_COMMANDS allow the user to easily control spacing between groups of pins

There are 3 types:

  • SINGLE_SPACERS:
    • LOCATOR=>SPACER,
  • MULTIPLE_SPACERS:
    • LOCATOR=>SPACER[5:0]
  • and SPACER_DIRECTIVES:
    • !BALANCE_SYM_SIDES+n (or !BSS+n)

The first 2 resemble the MATCH_STATEMENTS pretty closely and use the LEFT, RIGHT, TOP and BOTTOM LOCATOR commands.

The !BALANCE_SYM_SIDES directive is used to start a new section in the same symbol without having to keep track of the number of pins you have been adding on the sides of your symbols.

For instance if you have 3 pins on the left and 8 pins on the right, The BALANCE_SYM_SIDES+2 directive would add 5 spacer pins on the left to Balance it with the right side, and then add 2 more spacers on each side.

LOOP_DIRECTIVES AND VARIABLE SUBSTITUTION

SDL Loop Constructs and Variables can really enhance the efficiency of creating parts that contain multiple similar interfaces like a microprocessor with 2 DRAM busses or an FPGA with multiple IO Banks with the same number and types of pins.  They can also be used to quickly break up busses into nicely structured sub-busses 

The Expanded SDL File

PartBuilder first scans the input SDL file to see if it contains  LOOP _DIRECTIVES or Variable Substitution. If it finds any, it creates a new, expanded version of the input SDL file which it saves to the local directory and then uses for the pin to symbol assigment step. One benefit of this approach is it allows the user to clearly see how the loops were expanded, and possibly catch any unintended consequences of the loops. While the user is encouraged to examine the expanded SDL File, They  should be careful not to edit it, as any changes they make to that file will be overwritten the next time PartBuilder reads and expands the input SDL file.

VARIABLE Value Assignment and Substitution

The user can use variables within Loops or just globally change a of a set of PIN_MATCHES in some MATCH_STATEMENTS that they cut and paste.

VARIABLES can be substituted anywhere in the SDL including in Comments, SYMBOL_NAME_DEFINITIONS and MATCH_STATEMENTS.

A Variable is assigned with the following statement:

`LET VAR_NAME=SOMETHING

The VAR_NAME cannot contain spaces, but it can consist of The SOMETHING can be a number or a string.  

There are 4 main types of loop constructs. Each Construct starts with the backtick '`' characater to tell partPartbuilder that this is a special line

BEST_MODIFIER_DESC
The BEST Modifier in pin matching

In some odd cases (mostly when using loops and variables), The longest match might place a pin where you don't want it to.

SDL provides the BEST modifier to allow you to work around these cases.

Lets say we have an FPGA with a bunch of pins in bank 37 that we are trying to order using a bus so we use

left=>IO_L[19:0]*_37

but there is a pin in that bank named IO_L4_VREF_37, which we want to place in a different symbol (or somewhere in the same symbol)

if we use the BEST modifier,

left:BEST=>VREF_37

we guarantee that this match will claim the signal matching VREF_37,  and not the longer IO_L4*_37 match.

SPACER_COMMANDS

SPACER_COMMANDS allow the user to easily control spacing between groups of pins

There are 3 types:

  • SINGLE_SPACERS:
    • LOCATOR=>SPACER,
  • MULTIPLE_SPACERS:
    • LOCATOR=>SPACER[5:0]
  • and SPACER_DIRECTIVES:
    • !BALANCE_SYM_SIDES+n (or !BSS+n)


The first 2 resemble the MATCH_STATEMENTS pretty closely and use the LEFT, RIGHT, TOP and BOTTOM LOCATOR commands.

The !BALANCE_SYM_SIDES directive is used to start a new section in the same symbol without having to keep track of the number of pins you have been adding on the sides of your symbols.

For instance if you have 3 pins on the left and 8 pins on the right, The BALANCE_SYM_SIDES+2 directive would add 5 spacer pins on the left to Balance it with the right side, and then add 2 more spacers on each side.

l_spacer, r_spacer shorthand

**Older SDL files used the short-hand

l_spacer for LEFT=>spacer

and

r_spacer for RIGHT=>spacer.

The shorthand is still available but it is not as convienient for cut and paste in the spreadsheet format, and the SDL_EDITOR will automatically convert them to the newer LEFT=>, RIGHT=> format

Anchor
IF_LAST_MATCH_DESC
IF_LAST_MATCH_DESC
IF_LAST_MATCH  modifier for SPACER_COMMANDS

It is very convenient to use loops with ranges of  FPGA bank numbers where some of the bank numbers might not exist. In that loop you would normally place a spacer command to separate the banks. In the normal case, those spacers will always be added even if a bank doesn't exist. The IF_LAST_MATCH modifier can be used to avoid placing unwanted spacers when there are no matched signals between consecutive SPACER_COMMANDS

for instance if you have an FPGA that only contains IO banks 12,13,15,17. (another FPGA in the family could have IO banks 12,13,14,15,16,and 17

You use a loop:



Code Block
`for b in (12..17) 
left=>io.*_`b::
left=>spacer[1:0]
`endfor


which expands to

Code Block
left=>io.*_12
left=>spacer[1:0]
left=>io.*_13
left=>spacer[1:0]
left=>io.*_14
left=>spacer[1:0]
left=>io.*_15
left=>spacer[1:0]
left=>io.*_16
left=>spacer[1:0]
left=>io.*_17
left=>spacer[1:0]


But for this FPGA , there will be no pins that match IO.*_14 or IO.*_16. 

If the spacer is unmodified you will get 4 spacers between the IO.*_13 pins and the IO.*_15 pins, and 4 between the IO.*_15 and IO.*_17 pins. 

if you add the IF_LAST_MATCH modifier as follows



Code Block
linenumberstrue
`for b in (12..17) 
left=>io.*_`b::
left:IF_LAST_MATCH=>spacer[1:0]
`endfor



Code Block
linenumberstrue
left=>io.*_12
left:IF_LAST_MATCH=>spacer[1:0]
left=>io.*_13
left:IF_LAST_MATCH=>spacer[1:0]
left=>io.*_14
left:IF_LAST_MATCH=>spacer[1:0]
left=>io.*_15
left:IF_LAST_MATCH=>spacer[1:0]
left=>io.*_16
left:IF_LAST_MATCH=>spacer[1:0]
left=>io.*_17
left:IF_LAST_MATCH=>spacer[1:0]


With the IF_LAST_MATCH PartBuilder will not add the spacers if it did not see any matching pins between the last occurrence of a spacer and the next one.

so IO_.*13 will match some pins, so  the left:IF_LAST_MATCH=>spacer[1:0] will be honored, then partbuilder will clear the match count, it will look at the io.*_14 match and see no pins.. When it gets to the next IF_LAST_MATCH=>spacer[1:0] command, it will not add those spacers.


GRID_ADJUST  (Still Exists, but not really used)

Support for a  new 

LOCATOR=>!GRID_ADJUST_{fractional_space_specifier}

Command was added in version v18.5.5 to allow partBuilder to move pins off grid to let Smart-Frac exactly match pin locations from previously created symbols.

Normally pins are always added in whole grid increments, but to match pre-existing symbol pin placements it may be necessary to move a pin onto a half grid space

For example:

LEFT=>!GRID_ADJUST_0.5 will move the next pin 0.5 grid spaces so that all the next pins will start on the half grid space (until another !GRID_ADJUST  command would be used to move pins back onto the whole grid)