Autogeneration framework architecture

Softblocks

Wrappers

How wrapper, config, desc, vhdl entities, test benches are generated

Config_d entries

common.python.configs.pad(name, spaces=19)[source]

Pad the right of a name with spaces until it is at least spaces long

common.python.configs.all_subclasses(cls)[source]

Recursively find all the subclasses of cls

class common.python.configs.BlockConfig(name, type, number, ini_path, site=(None, None, None))[source]

The config for a single Block

name

The name of the Block, like LUT

number

The number of instances Blocks that will be created, like 8

module_path

The path to the module that holds this block ini

ini_path

The path to the ini file for this Block, relative to ROOT

block_address

The Block section of the register address space

entity

The VHDL entity name, like lut

type

Is the block soft, sfp, fmc or dma?

constraints

Any constraints?

ip

Does the block require IP?

description

The description, like “Lookup table”

fields

All the child fields

calc_extensions

List of Extension fields in the block

block_suffixes

Are there any suffixes?

register_addresses(block_counters)[source]

Register this block in the address space

filter_fields(regex, matching=True)[source]

Filter our child fields by typ. If not matching return those that don’t match

generateInterfaceConstraints()[source]

Generate MGT Pints constraints

class common.python.configs.RegisterConfig(name, number=-1, prefix='', extension='', write_extension='', read_extension='')[source]

A low level register name and number backing this field

name

The name of the register, like INPA_DLY

number

The register number relative to Block, like 9

extension

For an extension field, the register path

write_extension

If there is a write extension

read_extension

If there is a write extension

class common.python.configs.BusEntryConfig(name, bus, index)[source]

A bus entry belonging to a field

name

The name of the register, like INPA_DLY

bus

The bus the output is on, like bit

index

The bus index, like 5

class common.python.configs.FieldConfig(name, number, type, description, extra_config)[source]

The config for a single Field of a Block

type_regex = None

Regex for matching a type string to this field

name

The name of the field relative to it’s Block, like INPA

number

The number of instances Blocks that will be created, like 8

type

The complete type string, like param lut

description

The long description of the field

registers

The list of registers this field uses

bus_entries

The list of bus entries this field has

wstb

If a write strobe is required, set wstb to 1

option_filter

If the field is associated to an option

initial_value

Store the initial value, if supplied - only for params

extension

Store the extension register info

extra_config_lines

All the other extra config items

parse_extra_config(extra_config)[source]

Produce any extra config lines from self.kwargs

register_addresses(counters)[source]

Create registers using the FieldCounter object

address_line()[source]

Produce the line that should go in the registers file after name

config_line()[source]

Produce the line that should go in the config file after name

numbered_registers()[source]

Filter self.registers, only producing registers with a number (not those that are purely extension registers)

class common.python.configs.BitOutFieldConfig(name, number, type, description, extra_config)[source]

These fields represent a single entry on the bit bus

type_regex = 'bit_out'

Regex for matching a type string to this field

register_addresses(counters)[source]

Create registers using the FieldCounter object

class common.python.configs.PosOutFieldConfig(name, number, type, description, extra_config)[source]

These fields represent a position output

type_regex = 'pos_out'

Regex for matching a type string to this field

register_addresses(counters)[source]

Create registers using the FieldCounter object

parse_extra_config(extra_config)[source]

Produce any extra config lines from self.kwargs

config_line()[source]

Produce the line that should go in the config file after name

class common.python.configs.ExtOutFieldConfig(name, number, type, description, extra_config)[source]

These fields represent a ext output

type_regex = 'ext_out'

Regex for matching a type string to this field

register_addresses(counters)[source]

Create registers using the FieldCounter object

class common.python.configs.ExtOutTimeFieldConfig(name, number, type, description, extra_config)[source]

These fields represent a ext output timestamp, which requires two registers

type_regex = 'ext_out timestamp'

Regex for matching a type string to this field

register_addresses(counters)[source]

Create registers using the FieldCounter object

class common.python.configs.TableFieldConfig(name, number, type, description, extra_config)[source]

These fields represent a table field

type_regex = 'table'

Regex for matching a type string to this field

words = None

How many 32-bit words per line?

register_addresses(counters)[source]

Create registers using the FieldCounter object

config_line()[source]

Produce the line that should go in the config file after name

parse_extra_config(extra_config)[source]

Produce any extra config lines from self.kwargs

class common.python.configs.TableShortFieldConfig(name, number, type, description, extra_config)[source]

These fields represent a table field

type_regex = 'table short'

Regex for matching a type string to this field

lines = None

How many lines in the table?

parse_extra_config(extra_config)[source]

Produce any extra config lines from self.kwargs

register_addresses(counters)[source]

Create registers using the FieldCounter object

class common.python.configs.ParamFieldConfig(name, number, type, description, extra_config)[source]

These fields represent all other set/get parameters backed with a single register

type_regex = '(param|read|write).*'

Regex for matching a type string to this field

register_addresses(counters)[source]

Create registers using the FieldCounter object

config_line()[source]

Produce the line that should go in the config file after name

class common.python.configs.CalcExtensionFieldConfig(name, number, type, description, extra_config)[source]

These fields act in the same way as write record from the VHDL generation point of view, but do not have a config entry

type_regex = '(extension_write|extension_read)'

Regex for matching a type string to this field

register_addresses(counters)[source]

Create registers using the FieldCounter object

class common.python.configs.EnumParamFieldConfig(name, number, type, description, extra_config)[source]

An enum field with its integer entries and string values

type_regex = '(param|read|write) enum'

Regex for matching a type string to this field

parse_extra_config(extra_config)[source]

Produce any extra config lines from self.kwargs

class common.python.configs.UintParamFieldConfig(name, number, type, description, extra_config)[source]

A special These fields represent all other set/get parameters backed with a single register

type_regex = '(param|read|write) uint'

Regex for matching a type string to this field

parse_extra_config(extra_config)[source]

Produce any extra config lines from self.kwargs

config_line()[source]

Produce the line that should go in the config file after name

class common.python.configs.ScalarParamFieldConfig(name, number, type, description, extra_config)[source]

A special Read config for reading the different config of a read scalar

type_regex = '(param|read|write) scalar'

Regex for matching a type string to this field

parse_extra_config(extra_config)[source]

Produce any extra config lines from self.kwargs

config_line()[source]

Produce the line that should go in the config file after name

class common.python.configs.BitMuxFieldConfig(name, number, type, description, extra_config)[source]

These fields represent a single entry on the pos bus

type_regex = 'bit_mux'

Regex for matching a type string to this field

register_addresses(counters)[source]

Create registers using the FieldCounter object

class common.python.configs.PosMuxFieldConfig(name, number, type, description, extra_config)[source]

The fields represent a position input multiplexer selection

type_regex = 'pos_mux'

Regex for matching a type string to this field

register_addresses(counters)[source]

Create registers using the FieldCounter object

class common.python.configs.TimeFieldConfig(name, number, type, description, extra_config)[source]

The fields represent a configurable timer parameter

type_regex = 'time'

Regex for matching a type string to this field

register_addresses(counters)[source]

Create registers using the FieldCounter object

class common.python.configs.TargetSiteConfig(name, num, capabilitiy=None, type=None)[source]

The config for the target sites

type_regex = None

Regex for matching a type string to this field

name

The type of target site (SFP/FMC etc)

number

The info i in a string such as “3, i, io, o”

Test benches

A generic outline is common across the testbenches for the different blocks. There are four main areas of required functionality: Assigning signals, reading expected data, assigning inputs to the UUT and reading the outputs and comparing the outputs.

A template can therefore be used to autogenerate the testbench, with this common functionality, with the modifications required for use with the different blocks.

Required signals in the block

Python code used has extracted the different signals which are required from the .block.ini file for each block. Using this information, register signals are produced in the testbench for each signal, using the names from the INI file. However, not all signals are used in the same manner. Therefore the field type of each signal is also read to determine the size of the required register for each signals. This is also used to determine whether the signal is an input or an output signal. Each output signal requires a register signal similar to the the inputs, however they also require wire signals for use with the UUT, this is differentiated by the suffix “_UUT” and an error register which is differentiated by the suffix “_error”.

Integer signals are also declared for holding the file identifier, the $fscanf return value and the timestamp.

Read expected.csv

From the .timing.ini file within the block, a CSV file is generated which describes how the UUT should behave under certain inputs at different times. The first line of the file contains strings with the names of each of the signals, the first column being the timestamp data. All other lines contain numeric data for the timestamp, inputs and corresponding outputs.

The file is opened in the testbench and read line by line. The first line, containing the names of the signals is discarded. The numeric data is then read, when the timestamp value is equal to that in the file the values are assigned to the corresponding registers in the testbench. The data in the file is ordered in the same way as the .block.ini file so iterating through the signals in order, will assign the data to the correct registers.

Assign signals

The inputs to the entity for the block will have the same name as for those used in the testbench. It is therefore straightforward to connect the signals. The registers with the same name as the outputs are being used for holding the expected values, therefore the wire signals with the suffix “_uut” are used to read the output signals.

Compare output signals

To verify the correct functionality of the block, the outputted values will need to be compared to the expected values. A simple comparison is implemented, if the two signals are not equal, set that output’s error signal to one and display an error message to the user.