Corsair manual
Introduction
Corsair is a tool that makes it easy to create and maintain control and status register (CSR) map for any HDL project. It allows you to describe your register map in a single file and then generate HDL code, headers, documentation and other things. This effectively eliminates any mismatches between hardware, software and documentation of your IP-core.

Features
Various human-readable input formats: JSON, YAML or plain text table
HDL code generation: Verilog or VHDL module with register map, Verilog header or SystemVerilog package with parameters and definitions
Multi-protocol support: APB, AXI-Lite, Avalon-MM
Documentation generation: Markdown, AsciiDoc
Generation of software-related files: C header, Python module
Extensibility: support of external file generators
API: creation of custom workflow with corsair API
Installing
Install the latest stable version from pypi:
python3 -m pip install -U corsair
Using the CLI
Corsair workflow is clean and straight-forward:
describe your register map in one of the supported formats (check this page to get more details)
create configuration file
csrconfig
(configuration file is explained here)run
corsair
to generate all needed artifacts
Good point for start is to generate templates. For example, to generate YAML register map template just run:
corsair -t yaml
You will have the following catalog structure:
./csrconfig
./regs.yaml
To get all the generation artifacts simply run corsair:
corsair
You can run corsair from other directory. For example, if your configuration file is under project/ip-core/csrconfig
:
corsair project/ip-core
If your csrconfig
has other name you can try this:
corsair -c my.csrconfig
If your csrconfig
has no definition for the register map path you can specify it explicitly:
corsair -r uart.txt
Using the API
You can use corsair classes to build your own workflow inside a Python script. Demonstration of this can be found here.
More information about internal classes can be found in the API section:
Examples
Check the examples directory to see how corsair works.
Register map
Register map is a special memory area that consists of named addresses called registers aka Control and Status Registers (CSR). These registers, in turn, are made up of bit fields - group of bits with special properties. When any register is accessed, collection of bit fields is read or written.
Register map usually is a part of an IP-core like timer, UART, SPI, USB, Ethernet and plenty of others. It is used by software to rule the core.
From the hardware perspective, typical register map has bus interface (APB, AXI-Lite, Avalon-MM or other) on the one end, and group of signals that integrates the map to HDL logic on the other end.

Register
As it said before, register map is nothing but collection of registers. Register have 4 main attributes:
Parameter |
Description |
---|---|
|
Register name |
|
Register description |
|
Register address (offset from register map base address) |
|
List of register bit fields |
Bit field
One level down register consists of one or more bitfields. Attributes of a bitfield:
Parameter |
Description |
---|---|
|
Field name |
|
Field description |
|
Reset value of the field |
|
Field width (bits) |
|
Field least significant bit (LSB) position |
|
Access mode. One of the options below. |
|
Hardware options. Options are below. |
|
Enumerated values for the field |
Access mode for the field is related to the bus accesses from software (or from one who drives the bus interface). Use one of:
Access modes |
Description |
---|---|
|
Read and Write. The field can be read or written. |
|
Read and Write 1 to Clear. The field can be read, and when 1 is written field is cleared. |
|
Read and Write 1 to Set The field can be read, and when 1 is written field is set. |
|
Read Only. Write has no effect. |
|
Read Only to Clear. The field is cleared after every read. |
|
Read Only / Latch Low. The field capture hardware active low pulse signal and stuck in 0. The field is set after every read. |
|
Read Only / Latch High. The field capture hardware active high pulse signal and stuck in 1. Read the field to clear it. |
|
Write only. Zeros are always read. |
|
Write Only / Self Clear. The field is cleared on the next clock tick after write. |
Hardware options is used to define how bit field will interact with HDL logic. All the options are below.
Hardware options |
Description |
---|---|
|
Input. Use input value from hardware to update the field. |
|
Output. Enable output value from the field to be accessed by hardware. |
|
Clear. Add signal to clear the field (fill with all zeros). |
|
Set. Add signal to set the field (fill with all ones). |
|
Enable. Add signal to enable the field to capture input value (must be used with i). |
|
Lock. Add signal to lock the field (to prevent any changes). |
|
Access. Add signals to notify when bus access to the field is performed |
|
Queue. Enable queue (LIFO, FIFO) access |
|
Fixed. Enable fixed mode (field is a constant) |
|
None. No hardware access to the field. |
Set of hardware options is just a string like q
, ioel
. There are few rules:
Options
n
,f
,q
can be used only aloneAny combination of
i
,o
,u
,c
,s
,l
,a
is allowed
These are just some ideas of how bit field access mode and hardware options can be combined with each other. Of course, full list of possible combinations is quite bigger, but these ones cover most of the cases.
Access |
Hardware |
Description |
---|---|---|
|
|
Values can be read and written from software. Hardware can only access the current value. |
|
|
Value that can be always read, but writing is done only when lock signal is inactive. Hardware can only access the current value. |
|
|
Values that can be read and written from software. Hardware either can access the current value or update it. |
|
|
Same as above, but hardware can also track when value was read or written by software. |
|
|
Values that can be read and written from software. Hardware can clean the value. |
|
|
Values that can be read and written from software. Hardware can set the value. |
|
|
Software can read and write data. Hardware transforms these accesses to the queue read/write operations. |
|
|
Software can read and write data. But hardware has no access to the field. |
|
|
Software can read current state and write 1 to clear the field. Hardware can set the value. |
|
|
Software can read current state and write 1 to set the field. Hardware can clear the value. |
|
|
Software can only read the field. Hardware assign current state to some internal variable. |
|
|
Software can only read the constatnt value from the field. Hardware has no access to the field. |
|
|
Software can only read the field. Hardware can update the value when enable signal is active. |
|
|
Software can only read data from the field. Hardware transform this to the queue read operation. |
|
|
Software can only read data from the field, field is cleared after read. Hardware can update the value when enable signal is active. |
|
|
Value of the field will stuck at 0 when assigned hardware variable becomes 0. Software can only read data from the field, field is set after read. |
|
|
Value of the field will stuck at 1 when assigned hardware variable becomes 1. Software can only read data from the field, field is cleared after read. |
|
|
Software can only write the field. Hardware can access the current value. |
|
|
Software can only write data to the field. Hardware transform this to the queue write operation. |
|
|
Software can only write the field, the value will be cleared on the next tick. Hardware can access the field. |
Enumerated value
A bit field may have one or more special named values aka enumerated values aka enums. In fact, they are just mnemonics assigned to specific values being read or written to the field. Every enumerated value has 3 properties:
Parameter |
Description |
---|---|
|
Enum name |
|
Enum description |
|
Enum value |
Input formats
YAML
YAML example:
regmap:
- name: CTRL
description: Control register
address: 8
bitfields:
- name: BAUD
description: Baudrate value
reset: 0
width: 2
lsb: 0
access: rw
hardware: o
enums:
- name: B9600
description: 9600 baud
value: 0
- name: B38400
description: 38400 baud
value: 1
- name: B115200
description: 115200 baud
value: 2
- name: ID
description: IP-core ID register
address: 4092
bitfields:
- name: UID
description: Unique ID
reset: 3405645414
width: 32
lsb: 0
access: ro
hardware: f
enums: []
More detailed example can be found in the repository.
JSON
JSON example is bit more verbose than YAML, but it is still the same register map:
{
"regmap":[
{
"name": "CTRL",
"description": "Control register",
"address": 8,
"bitfields": [
{
"name": "BAUD",
"description": "Baudrate value",
"reset": 0,
"width": 2,
"lsb": 0,
"access": "rw",
"hardware": "o",
"enums": [
{
"name": "B9600",
"description": "9600 baud",
"value": 0
},
{
"name": "B38400",
"description": "38400 baud",
"value": 1
},
{
"name": "B115200",
"description": "115200 baud",
"value": 2
}
]
}
]
},
{
"name": "ID",
"description": "IP-core ID register",
"address": 4092,
"bitfields": [
{
"name": "UID",
"description": "Unique ID",
"reset": 3405645414,
"width": 32,
"lsb": 0,
"access": "ro",
"hardware": "f",
"enums": []
}
]
}
]
}
More detailed example can be found in the repository.
TXT
Simple plain text format. Looks like Markdown table. The example below
| Address | Name | Width | Access | Hardware | Reset | Description |
| ------- | ------ | ----- | ------ | -------- | ---------- | ---------------- |
| 0x0000 | DATA | 32 | rw | ioe | 0x00000000 | Data register |
| 0x0004 | CTRL | 16 | rw | o | 0x00000100 | Control register |
| 0x0008 | STATUS | 8 | ro | i | 0x00000000 | Status register |
| 0x0100 | START | 1 | wosc | o | 0x00000000 | Start register |
It is much simpler than JSON/YAML formats, but it is just enough for many applications. However, you have to pay for this simplicity:
Only one bit field per register is allowed. Columns Address, Name, Description store CSR attributes. Columns Width, Access, Hardware, Reset - bit field ones. LSB for this single bit field is always 0.
No enums
More detailed example can be found in the repository.
Configuration file
Corsair uses simple flat INI configuration file called csrconfig
. It is used for the two things:
to pass global parameters to corsair
to specify all generation targets with their attributes
Example of csrconfig is below:
[globcfg]
data_width = 32
address_width = 16
register_reset = sync_pos
[v_module]
path = regs.v
interface = axil
generator = Verilog
[c_header]
path = regs.h
generator = CHeader
It has one special section globcfg
for global parameters, and one or many sections for generation targets.
globcfg section
Global parameters available:
Parameter |
Default value |
Description |
|||
---|---|---|---|---|---|
|
0 |
Register map base address in global address map |
|||
|
32 |
Width of all data buses and registers |
|||
|
16 |
Address bus width (capacity of the register map) |
|||
|
|
Flip-flop reset style |
|||
|
Synchronous active high reset |
||||
|
Synchronous active low reset |
||||
|
Asynchronous active high reset |
||||
|
Asynchronous active low reset |
||||
|
|
Address auto increment mode, if no address is provided for a register |
|||
|
Address auto increment mode is disabled |
||||
|
Enable address auto increment with value based on |
||||
|
Enable address auto increment with provided number of bytes, e.g 4 |
||||
|
|
Check for address alignment of registers. |
|||
|
No check of address alignment |
||||
|
Enable check of address alignment based on |
||||
|
Enable check of address alignment based on provided number of bytes, e.g 4 |
||||
|
|
Force case for all the names (regsiters, bit fields, enums) |
|||
|
Names used as they are |
||||
|
Force names to have lowercase |
||||
|
Force names to have uppercase |
You can omit any of this in your csrconfig
file - default value will be used.
You also can add your own parameters and access them inside your custom flow the same way as standart ones. This is valid config:
[globcfg]
data_width = 32
address_width = 16
register_reset = sync_pos
foo = bar
Target sections
Target section defines file generator and specify its parameters. Generator is a Python class that produces some output based on input arguments. Usually, one target section - one output file.
Few simple rules to remember:
target name should be unique
targets without
generator
parameter is ignored
Parameter generator
can be defined in the two ways. To use built-in generator:
[target]
generator = Verilog
Or to use custom created one:
[target]
generator = custom_generator.py::MyCustomGenerator
If you are interesting in expanding corsair functionality, there is the example of how to build your own generator and use it with corsair CLI.
Generators
Corsair provides many built-in generators:
Generator |
Description |
---|---|
|
Dump register map to a JSON file |
|
Dump register map to a YAML file |
|
Dump register map to a text file |
|
Create Verilog file with register map |
|
Create VHDL file with register map |
|
Create Verilog header file with register map defines |
|
Create C header file with register map define |
|
Create SystemVerilog package with register map parameters |
|
Create documentation for a register map in Markdown |
|
Create documentation for a register map in AsciiDoc |
|
Create Python file with register map |
There are even more generators but these ones are normally don’t used in csrconfig
file -
they are helpfull for creating custom generators or other development tasks:
Generator |
Description |
---|---|
|
Base generator class |
|
Basic class for rendering Jinja2 templates |
|
Basic class for rendering register images with wavedrom |
|
Create Verilog file with bridge to Local Bus |
|
Create Vhdl file with bridge to Local Bus |
Note
These parameters in csrconfig
file are nothing but arguments for the class constructor.
If parameter is not provided - default value will be used.
Please note that the tables below were created mannualy, while data in Generators API page was collected automaticaly.
As these things are exactrly the same information just in different forms, please refer to API if you have any doubts.
Json
Parameter |
Default |
Description |
---|---|---|
|
|
Path to the output file |
Yaml
Parameter |
Default |
Description |
---|---|---|
|
|
Path to the output file |
Txt
Parameter |
Default |
Description |
---|---|---|
|
|
Path to the output file |
Verilog
Parameter |
Default |
Description |
|
---|---|---|---|
|
|
Path to the output file |
|
|
0 |
Numeric value to return if wrong address was read |
|
|
|
Register map bus protocol |
|
|
AXI4-Lite |
||
|
Avalon-MM |
||
|
APB4 |
||
|
Custom LocalBus interface |
Vhdl
Parameter |
Default |
Description |
|
---|---|---|---|
|
|
Path to the output file |
|
|
0 |
Numeric value to return if wrong address was read |
|
|
|
Register map bus protocol |
|
|
AXI4-Lite |
||
|
Avalon-MM |
||
|
APB4 |
||
|
Custom LocalBus interface |
VerilogHeader
Parameter |
Default |
Description |
---|---|---|
|
|
Path to the output file |
|
|
Prefix for all defines. If empty, output file name will be used. |
CHeader
Parameter |
Default |
Description |
---|---|---|
|
|
Path to the output file |
|
|
Prefix for all defines. If empty, output file name will be used. |
SystemVerilogPackage
Parameter |
Default |
Description |
---|---|---|
|
|
Path to the output file |
|
|
Prefix for the all parameters. If empty, output file name will be used. |
Markdown
Parameter |
Default |
Description |
---|---|---|
|
|
Path to the output file |
|
|
Document title |
|
|
Enable generating images for bit fields of a register |
|
|
Path to directory where all images will be saved |
|
|
Enable generating table with register access modes explained |
Asciidoc
Parameter |
Default |
Description |
---|---|---|
|
|
Path to the output file |
|
|
Document title |
|
|
Enable generating images for bit fields of a register |
|
|
Path to directory where all images will be saved |
|
|
Enable generating table with register access modes explained |
Python
Parameter |
Default |
Description |
---|---|---|
|
|
Path to the output file |
APB
Signals
These signals will be used in the interface of the register map.
Signal |
Width |
Direction |
Description |
---|---|---|---|
psel |
1 |
input |
APB select |
paddr |
>1 |
input |
APB address |
penable |
1 |
input |
APB enable |
pwrite |
1 |
input |
APB write |
pwdata |
>1 |
input |
APB write data |
pstrb |
>1 |
input |
APB write strobe |
prdata |
>1 |
output |
APB read data |
pready |
1 |
output |
APB ready |
pslverr |
1 |
output |
APB slave error |
Note
Specific bit widths for buses are defined in globcfg
section of a csrconfig
file.
Implementation details:
APB4 slave
pprot
signal is not implementedpslverr
tied to 0 - slave is alwaysOKAY
Protocol
Refer to official ARM documentation: IHI0024C AMBA® APB Protocol Version: 2.0.
AXI-Lite
Signals
These signals will be used in the interface of the register map.
Signal |
Width |
Direction |
Description |
---|---|---|---|
axil_awaddr |
>1 |
input |
Write address channel: write address |
axil_awprot |
3 |
input |
Write address channel: protection type |
axil_awvalid |
1 |
input |
Write address channel: write address valid |
axil_awready |
1 |
output |
Write address channel: write address ready |
axil_wdata |
>1 |
input |
Write data channel: write data |
axil_wstrb |
>1 |
input |
Write data channel: write strobes |
axil_wvalid |
1 |
input |
Write data channel: write valid |
axil_wready |
1 |
output |
Write data channel: write ready |
axil_bresp |
2 |
output |
Write response channel: write response |
axil_bvalid |
1 |
output |
Write response channel: write valid |
axil_bready |
1 |
input |
Write response channel: write ready |
axil_araddr |
>1 |
input |
Read address channel: read address |
axil_arprot |
3 |
input |
Read address channel: protection type |
axil_arvalid |
1 |
input |
Read address channel: read address valid |
axil_arready |
1 |
output |
Read address channel: read address ready |
axil_rdata |
>1 |
output |
Read data channel: read data |
axil_rresp |
2 |
output |
Read data channel: read response |
axil_rvalid |
1 |
output |
Read data channel: read valid |
axil_rready |
1 |
input |
Read data channel: read ready |
Note
Specific bit widths for buses are defined in globcfg
section of a csrconfig
file.
Implementation details:
AXI4-Lite slave
*resp
signals are tied to 0 - alwaysOKAY
*prot
signals are not handled
Protocol
Refer to official ARM documentation: IHI0022G AMBA AXI and ACE Protocol Specification AXI3, AXI4, and AXI4-Lite ACE and ACE-Lite.
Avalon-MM
Signals
These signals will be used in the interface of the register map.
Signal |
Width |
Direction |
Description |
---|---|---|---|
address |
>1 |
input |
Avalon-MM address |
read |
1 |
input |
Avalon-MM read |
readdata |
>1 |
output |
Avalon-MM read data |
readdatavalid |
1 |
output |
Avalon-MM read data valid |
byteenable |
>1 |
input |
Avalon-MM byte enable |
write |
1 |
input |
Avalon-MM write |
writedata |
>1 |
input |
Avalon-MM write data |
waitrequest |
1 |
output |
Avalon-MM wait request |
Note
Specific bit widths for buses are defined in globcfg
section of a csrconfig
file.
Protocol
Refer to official Intel documentation: Avalon® Interface Specifications.
LocalBus
LocalBus is a custom bus interface. You can use it for your register map, hovewer, it was designed specially to simplify integrating more common bus interfaces to register map. It acts as internal “virtual” interface.
In fact, all other supported buses (APB, AXI-Lite and etc.) in corsair are nothing more than just bridges to LocalBus interface under the hood.
Signals
Signal |
Width |
Direction |
Description |
---|---|---|---|
waddr |
>1 |
input |
Write address bus |
wdata |
>1 |
input |
Write data bus |
wen |
1 |
input |
Write request enable signal |
wstrb |
>1 |
input |
Write byte strobe bus (one bit for every write data byte) |
wready |
1 |
output |
Write request ready signal |
raddr |
>1 |
input |
Read address bus |
ren |
1 |
input |
Read request enable signal |
rdata |
>1 |
output |
Read data bus |
rvalid |
1 |
output |
Read data valid signal |
Note
Specific bit widths for buses are defined in globcfg
section of a csrconfig
file.
Transfers
Only simple single transfers are supported. No bursts or stream accesses. Every transfer can be extended with special signals.
Just for example, data bus is 32 bits wide for all the waveforms below.
Simple write
Write data D0
to address A0
.
Write with bytes strobes
Byte strobe signalling to write only bytes 1 and 2 (wstrb = 0x6 = 0b0110
) of D0
word.
Write with wait states
Write data D0
to address A0
, then write D1
to A1
ends (wen
goes low) as soon as wready
become high.
Simple read
Read data D0
from address A0
. Minimum response time - 1 tick. “Combinatoral” (in the same tick) read is not supported.
Read ends (ren
goes low) after rvalid
is asserted.
Read with wait states
Read data D0
from address A0
with 2 wait states.
Register map
EnumValue
- class corsair.EnumValue(name='enum', value=0, description='Enumerated value', **args)[source]
Enumerated value.
- Parameters:
name (str) – Enum name
value (int) – Enum value
description (str) – Enum description
- property description
Description of the enum.
- property name
Name of the enum.
- property value
Value of the enum.
BitField
- class corsair.BitField(name='val', description='Value of the register', reset=0, width=1, lsb=0, access='rw', hardware='n', **args)[source]
Bit field.
- Parameters:
name (str) – Bit field name
description (str) – Bit field description
reset (int) – Bit field reset vaue
width (int) – Bit field width vaue
lsb (int) – Bit field LSB vaue
access (str) – Bit field access mode
hardware (str) – Bit field hardware options
- property access
Access mode for the bitfield.
- add_enums(new_enums)[source]
Add enum or list of enums.
Enums are automatically sorted and stored in the ascending order of value attributes.
- property bits
Create list with all positions of the bits represented by the bit field.
- property byte_strobes
Dictionary with LSB and MSB values for the every byte in the write data bus.
- property description
Description of the bitfield.
- property enum_names
List with all enum names.
- property enums
List with enum objects.
- property hardware
Hardware mode for the bitfield.
- property lsb
LSB value of the bitfield.
- property mask
Bit mask for the field.
- property msb
Position of most significant bit (MSB) of the field.
- property name
Name of the bit field.
- property reset
Inital value of the bitfield.
- property width
Width value of the bitfield.
Register
- class corsair.Register(name='csr0', description='Control and status register 0', address=None, **args)[source]
Control and status register.
- Parameters:
name (str) – Bit field name
description (str) – Bit field description
address (int, None) – Register address
- property access
Register access mode, based on bitfields.
- add_bitfields(new_bitfields)[source]
Add bit field or list of bit feilds.
Bit fields are automatically sorted and stored in the ascending order of msb attributes.
- property address
Address of the register.
- property bitfield_names
List with all bit field names.
- property bitfields
List with bit field objects.
- property description
Description of the register.
- property name
Name of the register.
- property reset
Reset value of the refister after reset.
RegisterMap
Generators
Generator
- class corsair.generators.Generator(rmap, **args)[source]
Bases:
object
Base generator class.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map object
Jinja2
- class corsair.generators.Jinja2[source]
Bases:
object
Basic class for rendering Jinja2 templates
- render(template, vars, templates_path=None)[source]
Render text with Jinja2.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
templates_path – Path to search templates. If no path provided, then internal templates will be used
- Returns:
String with rendered text
- render_to_file(template, vars, path, templates_path=None)[source]
Render text with Jinja2 and save it to the file.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
path – Path to the output file
templates_path – Path to search templates. If no path provided, then internal templates will be used
Wavedrom
Json
- class corsair.generators.Json(rmap=None, path='regs.json', **args)[source]
Bases:
Generator
Dump register map to a JSON file.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- validate()
Validate generator parameters.
Yaml
- class corsair.generators.Yaml(rmap=None, path='regs.yaml', **args)[source]
Bases:
Generator
Dump register map to a YAML file.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- validate()
Validate generator parameters.
Txt
- class corsair.generators.Txt(rmap=None, path='regs.txt', **args)[source]
Bases:
Generator
Dump register map to a text table.
Note: only registers with single bitfield are allowed.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- validate()
Validate generator parameters.
Verilog
- class corsair.generators.Verilog(rmap=None, path='regs.v', read_filler=0, interface='axil', **args)[source]
-
Create Verilog file with register map.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
read_filler (int) – Numeric value to return if wrong address was read
interface (str) – Register map bus protocol. Use one of: axil, apb, amm, lb
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- render(template, vars, templates_path=None)
Render text with Jinja2.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
templates_path – Path to search templates. If no path provided, then internal templates will be used
- Returns:
String with rendered text
- render_to_file(template, vars, path, templates_path=None)
Render text with Jinja2 and save it to the file.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
path – Path to the output file
templates_path – Path to search templates. If no path provided, then internal templates will be used
Vhdl
- class corsair.generators.Vhdl(rmap=None, path='regs.vhd', read_filler=0, interface='axil', **args)[source]
-
Create VHDL file with register map.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
read_filler (int) – Numeric value to return if wrong address was read
interface (str) – Register map bus protocol. Use one of: axil, apb, amm, lb
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- render(template, vars, templates_path=None)
Render text with Jinja2.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
templates_path – Path to search templates. If no path provided, then internal templates will be used
- Returns:
String with rendered text
- render_to_file(template, vars, path, templates_path=None)
Render text with Jinja2 and save it to the file.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
path – Path to the output file
templates_path – Path to search templates. If no path provided, then internal templates will be used
VerilogHeader
- class corsair.generators.VerilogHeader(rmap=None, path='regs.vh', prefix='CSR', **args)[source]
-
Create Verilog header file with register map defines.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
prefix (str) – Prefix for the all defines. If empty output file name will be used.
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- render(template, vars, templates_path=None)
Render text with Jinja2.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
templates_path – Path to search templates. If no path provided, then internal templates will be used
- Returns:
String with rendered text
- render_to_file(template, vars, path, templates_path=None)
Render text with Jinja2 and save it to the file.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
path – Path to the output file
templates_path – Path to search templates. If no path provided, then internal templates will be used
- validate()
Validate generator parameters.
CHeader
- class corsair.generators.CHeader(rmap=None, path='regs.h', prefix='CSR', **args)[source]
-
Create C header file with register map defines.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
prefix (str) – Prefix for the all defines and types. If empty output file name will be used.
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- render(template, vars, templates_path=None)
Render text with Jinja2.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
templates_path – Path to search templates. If no path provided, then internal templates will be used
- Returns:
String with rendered text
- render_to_file(template, vars, path, templates_path=None)
Render text with Jinja2 and save it to the file.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
path – Path to the output file
templates_path – Path to search templates. If no path provided, then internal templates will be used
SystemVerilogPackage
- class corsair.generators.SystemVerilogPackage(rmap=None, path='regs_pkg.sv', prefix='CSR', **args)[source]
-
Create SystemVerilog package with register map parameters.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
prefix (str) – Prefix for the all parameters and types. If empty output file name will be used.
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- render(template, vars, templates_path=None)
Render text with Jinja2.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
templates_path – Path to search templates. If no path provided, then internal templates will be used
- Returns:
String with rendered text
- render_to_file(template, vars, path, templates_path=None)
Render text with Jinja2 and save it to the file.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
path – Path to the output file
templates_path – Path to search templates. If no path provided, then internal templates will be used
- validate()
Validate generator parameters.
Markdown
- class corsair.generators.Markdown(rmap=None, path='regs.md', title='Register map', print_images=True, image_dir='regs_img', print_conventions=True, **args)[source]
Bases:
Generator
,Jinja2
,Wavedrom
Create documentation for a register map in Markdown.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
title (str) – Document title
print_images (bool) – Enable generating images for bit fields of a register
image_dir (str) – Path to directory where all images will be saved
print_conventions (bool) – Enable generating table with register access modes explained
- draw_regs(imgdir, rmap)
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- render(template, vars, templates_path=None)
Render text with Jinja2.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
templates_path – Path to search templates. If no path provided, then internal templates will be used
- Returns:
String with rendered text
- render_to_file(template, vars, path, templates_path=None)
Render text with Jinja2 and save it to the file.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
path – Path to the output file
templates_path – Path to search templates. If no path provided, then internal templates will be used
- validate()
Validate generator parameters.
Asciidoc
- class corsair.generators.Asciidoc(rmap=None, path='regs.adoc', title='Register map', print_images=True, image_dir='regs_img', print_conventions=True, **args)[source]
Bases:
Generator
,Jinja2
,Wavedrom
Create documentation for a register map in AsciiDoc.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
title (str) – Document title
print_images (bool) – Enable generating images for bit fields of a register
image_dir (str) – Path to directory where all images will be saved
print_conventions (bool) – Enable generating table with register access modes explained
- draw_regs(imgdir, rmap)
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- render(template, vars, templates_path=None)
Render text with Jinja2.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
templates_path – Path to search templates. If no path provided, then internal templates will be used
- Returns:
String with rendered text
- render_to_file(template, vars, path, templates_path=None)
Render text with Jinja2 and save it to the file.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
path – Path to the output file
templates_path – Path to search templates. If no path provided, then internal templates will be used
- validate()
Validate generator parameters.
Python
- class corsair.generators.Python(rmap=None, path='regs.py', **args)[source]
-
Create Python file to access register map via some interface.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- render(template, vars, templates_path=None)
Render text with Jinja2.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
templates_path – Path to search templates. If no path provided, then internal templates will be used
- Returns:
String with rendered text
- render_to_file(template, vars, path, templates_path=None)
Render text with Jinja2 and save it to the file.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
path – Path to the output file
templates_path – Path to search templates. If no path provided, then internal templates will be used
- validate()
Validate generator parameters.
LbBridgeVerilog
- class corsair.generators.LbBridgeVerilog(rmap=None, path='axil2lb.v', bridge_type='axil', **args)[source]
-
Create Verilog file with bridge to Local Bus.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
bridge_type (str) – Bridge protocol. Use one of axil, apb, amm.
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- render(template, vars, templates_path=None)
Render text with Jinja2.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
templates_path – Path to search templates. If no path provided, then internal templates will be used
- Returns:
String with rendered text
- render_to_file(template, vars, path, templates_path=None)
Render text with Jinja2 and save it to the file.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
path – Path to the output file
templates_path – Path to search templates. If no path provided, then internal templates will be used
LbBridgeVhdl
- class corsair.generators.LbBridgeVhdl(rmap=None, path='axil2lb.v', bridge_type='axil', **args)[source]
-
Create VHDL file with bridge to Local Bus.
- Parameters:
rmap (
corsair.RegisterMap
) – Register map objectpath (str) – Path to the output file
bridge_type (str) – Bridge protocol. Use one of axil, apb, amm.
- make_target(name)
Dump class attributes to dictionary that can be used as target for csrconfig generation.
- Parameters:
name – Name of the target
- Returns:
Target dictionary
- render(template, vars, templates_path=None)
Render text with Jinja2.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
templates_path – Path to search templates. If no path provided, then internal templates will be used
- Returns:
String with rendered text
- render_to_file(template, vars, path, templates_path=None)
Render text with Jinja2 and save it to the file.
- Parameters:
template – Jinja2 template filename
vars – Dictionary with variables for Jinja2 rendering
path – Path to the output file
templates_path – Path to search templates. If no path provided, then internal templates will be used
Configuration
Module to operate with Corsair configuration files
Developer’s guide
Installation
Note
Depending on your system, Python executable might be python
or python3
.
If there any permissions issues, add --user
key to the installation scripts.
Install dependencies first:
python3 -m pip install gitpython pyyaml jinja2 wavedrom
Then clone GitHub repository and you’ll be able to run application from the project root:
git clone https://github.com/esynr3z/corsair.git
cd corsair
python3 -m corsair --help
Or install it:
python3 setup.py install
Code style
PEP 8 Speaks is added to automatically review Python code style over Pull Requests.
Linter settings:
Linter: pycodestyle
Max line length: 120
Errors and warnings to ignore: W504, E402, E731, C406, E741
You can also install PEP8 Git Commit Hook and code style will be checked before any commit.
Testing
Install PyTest:
python3 -m pip install -U pytest pytest-xdist
HDL tests use Modelsim, so make sure that Modelsim is installed and visible in PATH.
Run tests from the root folder on all available cores:
pytest -v -n auto
Run tests for docstrings:
pytest --doctest-modules corsair
Documentation
Install Sphinx and extensions:
python3 -m pip install -r docs/requirements.txt
Run from docs
folder to build the documentation:
make clean html
Changelog
1.0.4 (2023-03-17)
Fix rolh/roll missing latch bug
Fix constants comparison on address in vhdl
Fix C/C++ header generation
1.0.3 (2023-03-06)
Various bug fixes
1.0.2 (2021-09-26)
Fix overlapping of bitfiled names in rendered images for registers
1.0.1 (2021-09-08)
Fix an issue where the input globconfig file was not being applied to generators
1.0.0 (2021-09-03)
Reworking the entire project almost from scratch. Lots of breaking changes.
New configuration file format (INI)
New file generation flow (more clear)
Do refactoring of all core modules
Add enums
Add C header generator
Add Verilog header generator
Add SystemVerilog package generator
Embed bus interface (AXI-Lite, APB, Avalon-MM) into a register map
Add VHDL register map generator
Add plenty of examples
Rework of documentation
Update the tests
Many minor tweaks and fixes
0.3.0 (2021-02-21)
Fix Markdown table row endings.
Add ‘Reserved’ bitfields to Markdown.
Fix installation guides.
Implement access_strobes attribute for register.
Implement complementary registers.
Implement write_lock attribute for register.
Implement FIFO bitfield modifier.
Implement AXI-Lite to Local Bus bridge on Verilog.
Implement Avalon-MM to Local Bus bridge on Verilog.
0.2.0 (2021-01-08)
Rework CLI keys
Fix entry point for CLI
Add Verilog and Markdown writers for a register map
Add Local Bus bridge writer
Implement APB to Local Bus bridge on Verilog
Setup HDL testing environment
Setup CI/CD via Github Actions
Documentation fixes, code prettifying and etc.
0.1.0 (2020-12-16)
Setup repository
Setup documentation
Setup testing
Implementation of core classes
Add support of running from a command line
Add JSON and YAML readers
Add JSON and YAML writers