## Funcmap

### Introduction

Some integrated circuits like microcontrollers and embedded processors have more features than physical pins and use internal multiplexers to configure which physical pin should serve which functionality (peripheral).

There are different ways to cope with this on the schematics without extra features:

- list all functions in the terminal label
- the above, and let the user draw some marking around the active function's name
- better yet, the user could edit the symbol, change the terminal label, to mark the active function or even remove the inactive ones

However these are time consuming procedures and prone to error as some functionality are in group, e.g. an SPI typically requires a clock and at least a MISO or a MOSI (but usually both). With the above manual processes the software is not doing any verification whether function-terminal assignments are valid (the given terminal indeed has the given function) or whether a group of functions, like SPI, have all relevant terminals marked.

The funcmap plugin provides an automated solution to the majority of the common cases. It works a bit similar to devmap: (alternate pin) function maps, or funcmaps for short, are written by the user in a text file on a per part basis, collected in a funcmap library. Then the file name of the funcmap is set in an attribute in one of the symbols (contributing to a component).

During compilation the component inherits the attribute and the plugin loads and caches the funcmap file into sheet local library (so the sheet file is self-contained without the external funcmap lib shipped with it). Then the plugin looks at the attributes of each port of the component to compute a funcmap name to display - this is how the alternate function is applied. Instead of a hardwired string, the symbol shall print the computed funcmap name attribute. This way, after a successful compilation, the sheet shows the dynamically calculated, verified alternate function of each port.

Furthermore CLI actions and GUI dialog boxes are provided to overview and edit and verify the consistency of the per terminal function selection.

### Details

Further details are sorted into the following sub-sections:

- Funcmap data model and file format
- Attribute usage summary
- Funcmap library
- CLI: actions
- GUI: dialog boxes and menus
- DRC: design rule checks
- boxsym-rnd aspects
- Example: using the system in practice

#### Funcmap data model and file format

A funcmap operates on the abstract model. It lists alternate functions of each port and optionally groups those functions in weak and strong function groups.

A typical example is a microcontroller (MCU) that can have the same port act as a GPIO, as an analog input, a PWM output or part of a sync serial device. The function is selected runtime by software.

As an example for such a situation consider 3 ports of the attiny24 (full example for all pins is also available). Below is the stripped down funcmap file from the external library:

    ha:funcmap.v1 {
      ha:comp_attribs {
        li:funcmap/ports {
          { PB6/PB6      -> sigtype=digital; }
          { PB6/PCINT6   -> sigtype=digital; dir=input  }
          { PB6/MOSI     -> sigtype=digital; }
          { PB6/DI       -> sigtype=digital; dir=input  }
          { PB6/SDA      -> sigtype=digital; }
          { PB6/OC1A     -> sigtype=digital; dir=output }
          { PB6/ADC6     -> sigtype=analog;  dir=input  }

          { PA4/PA4      -> sigtype=digital; }
          { PA4/PCINT4   -> sigtype=digital; dir=input  }
          { PA4/SCK      -> sigtype=digital; }
          { PA4/SCL      -> sigtype=digital; }
          { PA4/ADC4     -> sigtype=analog;  dir=input  }

          { PA5/PA5      -> sigtype=digital; }
          { PA5/PCINT5   -> sigtype=digital; dir=input  }
          { PA5/MISO     -> sigtype=digital; }
          { PA5/DO       -> sigtype=digital; dir=output }
          { PA5/OC1B     -> sigtype=digital; dir=output }
          { PA5/ADC5     -> sigtype=analog;  dir=input  }
        }

        li:funcmap/weak_groups {
          { gpio         -> PB6, PA4, PA5 }
          { pcint        -> PCINT4, PCINT5, PCINT6 }
          { PWM          -> OC1A, OC1B }
          { adc          -> ADC4, ADC5, ADC6 }
        }

        li:funcmap/strong_groups {
          { SPI          -> SCK, MISO, MOSI }
          { I2C          -> SDA, SCL }
          { USI          -> SCK, DI, DO }
        }
      }
    }

The file is a lihata document with the root node ha:funcmap.v1. It hosts a single ha:comp_attribs subtree (similar to devmap), to indicate that the subsequent attributes are component-level (even tho the funcmap plugin will not actually create these attributes in the components).

The li:funcmap/ports attribute is a list of port functions. Each line is a port/function -> port attributes pair. Function names are arbitrary. Once the given function is activated for a port, the funcmap plugin will set all port attributes listed on the right side of the arrow. As a convention the first function shall match the port name; this is going to be the primary function of the port which is also used as a fallback when the user does not activate any function for a port. The typical port attributes to set are sigtype and dir (see coraleda std 002), but any port attribute may be set.

The li:funcmap/weak_groups attribute is a list of groups for displaying purposes. Each line is function group in the form of group_name -> function_list. Group names are arbitrary but must be unique within a funcmap file. A function_list is a comma separated list of function names. (Function names must be defined in the li:funcmap/ports section.)

In a tabular display each group is a column (while ports are rows):

    <port> gpio    pcint  PWM      adc  SPI  I2C USI <no-group>
    PB6    [[PB6]] PCINT6 OC1A     ADC6 MOSI SDA DI  -
    PA4    [[PA4]] PCINT4 -        ADC4 SCK  SCL SCK -
    PA5    PA5     PCINT5 [[OC1B]] ADC5 MISO -   DO  -

The function wrapped in [[]] is the one activated for the given port.

li:funcmap/strong_groups has the same format and display properties as weak_groups. The difference is that a strong group is also checked in the DRC for consistency.

In the above table the <port> column holds raw port names; functions start from the second column. The last column is always called <no-group> and holds any function that is not referenced by any of the function groups. Note: the same function may be referenced from multiple groups (like SCK in this case), but it's generally best practice to avoid that.

#### Attribute usage summary

Component attribute: funcmap. Specifies the name of the funcmap to use. This is the file name in the external library, without the .funcmap suffix. The attribute is typically specified in the symbol. If the component is compiled from multiple symbols, the attribute should be specified only in one of the symbols. If not specified, the component is not affected by funcmap.

Port attribute: funcmap/name (typically specified in a terminal). Specifies the function the given port should take. Shall be one of the functions available for the given port. Shall be used only for ports in components with the funcmap attribute set. If a port in a component with the funcmap attribute does not specify its funcmap/name, it is computed by the funcmap plugin (the port name is copied into the funcmap/name attribute). Thus funcmap/name always contains the valid function name used by the port (of a funcmap capable symbol) and the symbol should print the dyntext %../a.funcmap/name% for pin label.

#### Funcmap library

Funcmap files are loaded from external libs. External lib paths are configured in the conf node plugins/funcmap/search_paths, which has the same syntax as the symbol library.

Once a funcmap is referenced (from the funcmap attribute of a component, typically coming from the funcmap attribute of a symbol), the plugin loads the file from the external lib and places it in the sheet local library. This keeps sheets self-contained and portable, not relying on external files.

Both the sheet local library and the external library can be browsed using the funcmap library dialog. The sheet local library can be flushed (removed) from the File/Maintenance menu; upon the next compilation all funcmap references are imported into the sheet local library from the external libraries again. This is how external library changes can be applied to a sheet.

#### CLI: actions

The generic way to manipulate funcmaps is simply editing symbol and terminal attributes, e.g. using the propedit() action. The funcmap system depends only on funcmap files and attributes, there are not GUI-only aspects.

The specialized CLI actions to manage funcmaps (manually or from scripts) are:

- FuncmapPrintTable that prints the funcmap state table for a component to stdout (same table that the component funcmap dialog presents)
- FuncmapChange that can change port function selection in a verified way and can select function for multiple ports by a function group.

These actions work only if the project is compiled.

#### GUI: dialog boxes and menus

Quick attribute edit for selecting the funcmap for a symbol is available in the attribute editor, once the funcmap attribute is selected. It opens the funcmap library dialog (also accessible from the window menu) which allows browsing the external and sheet local funcmap libs for picking a funcmap.

The per component funcmap summary table dialog can be invoked from the right click context menu of symbols. This dialog box presents the tabular view of all ports (rows) and functions (columns). Once a port is selected, the function of that port can be easily stepped through its available functions. Alternatively the function can also be set by explicitly selecting one of the alternate functions (using the change button). There's a button for activating the whole function group that matches the currently selected port's function. Note: this dialog box does not refresh automatically for changes made elsewhere; if there are relevant changes in the drawing or attributes and the dialog box is still open, click the refresh button.

The per port function selector can be invoked using the right click context menu of a terminal. The dialog popping up allows selecting one of the possible functions the port may have.

These dialog boxes work only if the project is compiled.

#### DRC: design rule checks

DRC checks are ran automatically as part of the normal sch-rnd DRC process, unless it is disabled using the conf node plugins/funcmap/drc_disable.

The funcmap DRC check verifies that each component with an active funcmap has all strong function groups properly utilized. For each function (of a function group) there are three possible states:

- unused: the function is not assigned by any port
- single: the function is used by only one strong function group and is assigned to a port
- multi: the function is used by multiple strong function groups and is assigned to a port

A function group is valid if and only if:

- all of its functions are unused or multi
- all of its functions are single or multi

If a strong function group has some functions unused while other functions single used, that means the function group is partly utilized, which is an error that is reported as a DRC violation.

For example on the attiny24, there are two very similar sync serial devices are available with shared ports: SPI and USI. SPI has SCK, MISO and MOSI while USI has SCK, DI and DO. Both SPI and USI are strong function groups. Considerations when running the verification for the SPI function group:

- SCK is present in both SPI and USI using the same name; if it is assigned to a port, it's multi state, otherwise it is in unusedstate
- If MISO is assigned but MOSI is not, that is a violation
- If MOSI is assigned but MISO is not, that is a violation
- If MISO and MISO are assigned but SCK is not, that is a violation
- If SCK is assigned but neither MISO nor MOSI, that is not reported as a violation (because SCK is multi so it is assumed it'd be used for another group, e.g. USI - but it is not verified while checking on SPI)

Thus either all three functions of SPI must be activated, or none of them; except for SCK, which may be activated (for the function group USI).

#### Example: using the system in practice

A full example is provided in doc/examples/funcmap. It consists of a boxsym-rnd generated monolithic symbol and the corresponding funcmap file. Ports Vcc and GND are not mentioned in the funcmap file since those ports are single-function.

#### boxsym-rnd aspects

The symbol for MCUs and CPUs are typically generated using a tool, such as boxsym-rnd. To play nicely with funcmap, the only requirement is that the tool generates the affected terminal labels to use dyntext %../a.funcmap/name%. In boxsym this is done when the funcmap property (without any argument) is added to a pin block.

Boxsym-rnd does not generate the funcmap file; the funcmap file shall be written manually. It is common that an MCU or CPU symbol is a heavy symbol that works with only one funcmap. In that case the funcmap attribute could be specified on component level (in the global section of the boxsym input file).