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
- 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?
- 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
- 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
- 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
- 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
- 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
- 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?
- 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?
- 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
- 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
- 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
- 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
- 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
- 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
- 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
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.