Shortcuts & Formatting

Master !FORMAT directives and field skipping for concise circuit descriptions.

Introduction

To reduce typing, entry time, and file sizes, SNL provides powerful shortcuts through keyword abbreviations and the !FORMAT directive. These features allow you to write compact, readable circuit descriptions without sacrificing clarity.

Keyword-Field Ordering Flexibility

One advantage of a keyword-oriented description language is that the order of the fields within each statement is not important. As an example, the following is a functionally identical restatement of the johnson_counter type block which illustrates SNL's flexibility with regard to part statement and keyword-field ordering.

TYPE=johnson_counter O=q1,q2,q3 I=clock,reset
I=q3 O=back PART=back TYPE=inv
TYPE=and I=reset O=rbuf PART=buf
I=rbuf,one,clock,q1 PART=f2 TYPE=dcf O=q2
I=rbuf,one,clock,q2 TYPE=dcf PART=f3 O=q3
TYPE=dcf I=rbuf,one,clock,back PART=f1 O=q1

It is suggested, however, that a consistent ordering be used to improve readability.

Keyword Abbreviations

SIMIC recognizes abbreviations for almost all SNL keywords. Most keywords can be abbreviated to their first letter or two characters.

Common Abbreviations

Full Keyword Abbreviation Usage Context
TYPE T All statements
PART P Part statements
INPUT-PINS IPINS, I Type statements
INPUT-NETS INETS, I Part statements
OUTPUT-PINS OPINS, O Type statements
OUTPUT-NETS ONETS, O Part statements
BIDIRECTIONALS B All statements

Example Using Abbreviations

t=full-adder i=a,b,cin o=sum,cout

p=xor1 t=exor i=a,b o=xor1_out
p=and1 t=and i=a,b
p=and2 t=and i=xor1_out,cin

For a complete list of SNL keywords and their abbreviations, see the SNL Keywords Reference.

The !FORMAT Directive

The !FORMAT directive goes beyond simple abbreviations by allowing you to eliminate keywords entirely. It specifies the order of keyword-fields in subsequent statements, so only the values need to be entered.

Basic Syntax

!FORMAT <keyword1>= <keyword2>= <keyword3>= ...

Once a !FORMAT is defined, each subsequent statement line is interpreted as a series of values that associate with the keywords in the specified order.

Example: Johnson Counter

This demonstrates the power of !FORMAT for repetitive circuit descriptions:

!format p= t= i= o=
t=johnson_counter i=clock,reset o=q1,q2,q3

buf     and     reset           rbuf
f1      dcf     rbuf,one,clock,back    q1
f2      dcf     rbuf,one,clock,q1      q2
f3      dcf     rbuf,one,clock,q2      q3
back    inv     q3

Breaking this down:

  1. The !FORMAT statement declares: 1st field = PART, 2nd = TYPE, 3rd = INPUTS, 4th = OUTPUTS
  2. Each subsequent line follows this pattern without repeating the keywords
  3. For instance, f1 dcf rbuf,one,clock,back q1 translates to:
    p=f1 t=dcf i=rbuf,one,clock,back o=q1

!FORMAT Guidelines

Scope and Persistence

Canceling !FORMAT

To cancel formatting and return to explicit keyword-field entry:

!format

(A !FORMAT directive with no keywords following it.)

Field Skipping with Hyphen (-)

When a statement doesn't require a value for one of the keywords in the current !FORMAT, use a hyphen (-) as a placeholder to skip that keyword's value.

Key Rule: Use - to skip fields in the middle of the format list. If no values are needed for keywords at the end of the format, hyphens are not required.

Example: Skipping the PART Field

!format part= type= i= o=

-    and    a,b    part=c

The hyphen skips the PART field, so and associates with TYPE. Later in the line, part=c uses an explicit keyword, which overrides formatting for the rest of that statement.

Example: Omitting Trailing Fields

!format p= t= i= o=

c    and    a,b

The OUTPUT field is omitted (defaults to part name c). No placeholder hyphen is needed because no other fields follow.

Mixing Formatted and Explicit Entries

If a statement requires a keyword not in the current !FORMAT, or keywords in a different order, type the complete keyword-field. This suspends formatting for the rest of that statement.

Equivalent Statements Example

All these statements are equivalent when !format part= type= i= o= is active:

!format part= type= i= o=

-         and    a,b    part=c
c         and    a,b
c         and    i=a,b  o=c
part=c type=and i=a,b o=c
Line Explanation
1 Hyphen skips PART, then part=c keyword overrides remaining format
2 Fully formatted; OUTPUT omitted (defaults to part name)
3 Part and type formatted; i=a,b keyword suspends format, requiring o=c
4 All keywords explicit (no formatting used)
Best Practice: The most efficient way to add a keyword-field not in the format is to append it to the end of the line, where formatting has already been exhausted.

Practical Tips

When to Use !FORMAT

When to Avoid !FORMAT

Combining Techniques

For maximum efficiency, combine !FORMAT with abbreviations and implicit naming:

!f p= t= i=
t=adder i=a,b,cin o=sum,cout

ha1    exor   a,b
ha2    exor   ha1,cin
a1     and    a,b
a2     and    ha1,cin
or1    or     a1,a2    o=cout

Here, !f abbreviates !format, and most outputs use implicit naming except cout which needs explicit specification.

The !INCLUDE Directive

The !INCLUDE directive allows you to reference additional SNL files during compilation, enabling modular circuit descriptions and reusable libraries.

Basic Syntax

!INCLUDE FILE=<file list>

Or, since FILE= is the default keyword:

!INCLUDE <file list>

Usage Examples

c= Include a single library file
!INCLUDE cmoslib

c= Include multiple files
!INCLUDE FILE=stdcells,memories,iocells

c= Can also be written as:
!INC stdcells,memories,iocells

When to Use !INCLUDE

Important Restrictions

Maximum Nesting Depth: Included files may themselves contain !INCLUDE statements, but the maximum nesting depth is 4 levels. This means you can have an initial file that includes a second file, which includes a third file, which includes a fourth file, but no deeper.

Section Behavior and Placement

The contents of an included file are logically inserted at the exact location of the !INCLUDE statement. Understanding how sections interact with includes is critical:

Section Directives Are "Sticky"

Section directives (!LOGICAL, !DELAY, !DOCUMENTATION) remain in effect until explicitly changed by another directive or until the end of a file is reached. However:

Practical Implications

c= Example: Including from a !DELAY section
!DELAY
delay=del1 rise=10 fall=12
!INCLUDE stdcells    c= stdcells will start in !LOGICAL by default

c= Example: Including delay definitions
!DELAY
delay=del1 rise=10 fall=12
!INCLUDE moredelays  c= moredelays should start with !DELAY if it contains delays

c= Example: Preserving sections in included files
c= File: moredelays
!DELAY                c= Explicitly declare section to continue delay definitions
delay=del2 rise=15 fall=18

Type Block Boundaries

Since type blocks are not explicitly ended in SNL, place !INCLUDE statements carefully to avoid inadvertently adding included text within a type block definition.

Example: Proper Placement

c= Good practice - include before type definitions
!INCLUDE stdcells

t=counter i=clk,reset o=q[0:3]
p=ff0 t=dff i=clk,reset,d0 o=q[0]
p=ff1 t=dff i=clk,reset,d1 o=q[1]
...

Example: Improper Placement

c= WRONG - include within a type block
t=counter i=clk,reset o=q[0:3]
p=ff0 t=dff i=clk,reset,d0 o=q[0]
!INCLUDE stdcells     c= BAD: This adds stdcells content into the counter type!
p=ff1 t=dff i=clk,reset,d1 o=q[1]

!INCLUDE vs GET FILE

Two methods can specify files for compilation:

Method Specified Best For
GET FILE= In run command Top-level files, user-specified file lists
!INCLUDE Within SNL file Dependencies embedded in the design, library references

The %DECLARE Statement

The %DECLARE statement groups individual signals into arrays (vectors) and assigns a default display radix for simulation output. This makes it easier to work with buses and multi-bit signals.

Basic Syntax

%DECLARE <format>=<array list>

Where <format> is one of:

Format Abbreviation Description
LEVEL LEV Standard 15-character level+strength format (alias for LEVEL15)
LEVEL15 15-character representation with level and strength (G,V,S,0,1,X,W,L,H,D,C,Z,F,T,U)
LEVEL4 4-character level-only representation (0, 1, X, Z)
OCTAL OCT Octal format (0-7)
HEXADECIMAL HEX Hexadecimal format (0-9, A-F)
BIT Alias for HEXADECIMAL
INTEGER1 INT1 One's complement signed integer
INTEGER2 INT, INT2 Two's complement signed integer
POSINTEGER POSINT Positive (unsigned) integer
Level Format Details:
  • LEVEL15 (default) represents signal levels and drive strengths:
    • POWER: G(0), V(1), S(X)
    • DRIVING: 0, 1, X
    • RESISTIVE: W(0), L(1), H(X)
    • FLOATING: D(0), C(1), Z(X)
    • UNKNOWN: F(0), T(1), U(X)
  • LEVEL4 represents only logic levels: 0, 1, X, Z (ignores strength except floating-unknown)

Array Specification

Arrays can be one-dimensional or two-dimensional:

c= One-dimensional array
%DECLARE HEX=data[0:7]

c= Two-dimensional array
%DECLARE INT=memory[0:15][0:7]

c= Multiple arrays in one statement
%DECLARE OCT=address[0:11],status[0:3],control[0:7]

Scope Rules

Local Scope: The %DECLARE statement is local to the type block in which it appears. Each type block has its own independent namespace for declared arrays.

Placement Requirements

%DECLARE statements must appear within a type block, typically after the TYPE statement but before PART statements. They cannot appear at the file level or outside of any type definition.

Example: Correct Placement

t=alu i=a,b,opcode o=result,overflow
%declare int=a[0:7],b[0:7],result[0:7]
%declare hex=opcode[0:3]

p=add t=adder8 i=a,b o=sum
p=sub t=subtr8 i=a,b o=diff
...

Example: Incorrect Placement

c= WRONG - cannot be at file level
%declare hex=data[0:7]     c= ERROR: Not in a type block!

t=processor i=clk,data o=addr
...

Using Declared Arrays

Once declared, the root name (without indices) can reference the entire array:

t=register i=clk,d o=q
%declare hex=d[0:7],q[0:7]

c= Connect entire array using root name
p=ff t=dff8 i=clk,d o=q

c= Equivalent to explicitly listing all bits:
c= p=ff t=dff8 i=clk,d[0],d[1],...,d[7] o=q[0],q[1],...,q[7]

Benefits of %DECLARE

Example: Complete Johnson Counter

t=johnson_counter i=clock,reset o=q
%declare octal=q[1:3]

p=buf  t=and   i=reset          o=rbuf
p=f1   t=dcf   i=rbuf,one,clock,back  o=q[1]
p=f2   t=dcf   i=rbuf,one,clock,q[1]  o=q[2]
p=f3   t=dcf   i=rbuf,one,clock,q[2]  o=q[3]
p=back t=inv   i=q[3]

Here, q[1:3] is declared as octal, so during simulation, the three-bit output will be displayed as a single octal digit (0-7) rather than three separate binary values.