Contributing to Regif
Relevant source files
The following files were used as context for generating this wiki page:regif is a tool for automatically generating register interface RTL (Verilog) and documentation from a structured Excel file. Contributing to the project involves understanding the Python-based generation engine, the specific Excel input format, and the Verilog templates used to create the output. The core of the project lies in a single Python script, regif.py, which handles parsing, validation, and generation.
This guide provides a technical overview of the system architecture and processes to help new contributors understand the codebase. All contributions must be compatible with the project's GPLv3 license.
Sources: regif.py, readme.md, LICENSE
Setting up the Development Environment
To contribute to regif, you will need a Python environment and the required dependencies.
Prerequisites
- Python: Version 3.3 or higher is required.
Sources: setup.py:23 - Dependencies: The project relies on external libraries for Excel parsing and document creation. These can be installed via
pip.
| Dependency | Version | Purpose |
|---|---|---|
xlrd | >=1.1.0 | Reading data from Excel (.xls) files. |
python_docx | >=1.11.3 | Creating and manipulating .docx files. |
Sources: setup.py:25-28, regif.py:30-35
Installation for Development
You can install the package locally for development or run the script directly. The recommended way to start is by using the script directly after installing dependencies.
- Clone the repository.
- Install dependencies:
pip install xlrd python_docx - You can run the tool using
python regif.py <args>.
The .gitignore file specifies that standard Python artifacts (*.pyc, __pycache__/) and packaging directories (dist/, build/, *.egg-info/) should be excluded from version control.
Sources: readme.md:28-30, .gitignore:1-5
Core Architecture
The entire logic for parsing, validation, and code generation is encapsulated within regif.py. The architecture is object-oriented, with several key classes responsible for managing register data.
The following diagram illustrates the relationship between the main classes.
This class diagram shows the main data structures used to model the register map.
Sources: regif.py:338-348, 385-393, 513-529, 1004-1021
Class Responsibilities
Regif: The main orchestrator class. It is initialized with aBooksheet object fromxlrd. It extracts all register and field data, performs static and dynamic validation, and drives the generation of Verilog and.docxfiles.
Sources: regif.py:1004-1021Reg: Represents a single register. It holds the register's name, address, and aRegFieldsobject containing all its fields. It is responsible for generating the top-level Verilogdefinefor its address and coordinating the generation of its read/write logic.
Sources: regif.py:338-344RegFields: Manages all theFieldobjects within a single register. It contains the logic for generating the Verilogalwaysblocks for writes (w_block) and the case statement entry for reads (read_express). It also handles complex interactions between fields, such as write protection.
Sources: regif.py:385-403Field: Represents a single field within a register (e.g., a single bit or a range of bits). It stores properties like name, bit section, access type (RW,RO, etc.), and reset value. It is responsible for generating the specific Verilog declarations (wire,reg) and assignments for that field.
Sources: regif.py:513-529
The Generation Process
The tool follows a clear, multi-step process from an Excel input file to the final Verilog and documentation outputs.
This flowchart shows the end-to-end workflow of the regif tool.
Sources: regif.py:1260-1288, readme.md:32-36
Input Format: The Excel Template
The structure and rules for the input Excel file are strictly defined by format-checking regular expressions and parsing logic within regif.py.
Global Configuration
The first few rows of the Excel sheet define global parameters for the module.
| Cell | Parameter | Regex Rule | Description |
|---|---|---|---|
| C2 | moudle | [a-zA-Z]\w* | The name of the Verilog module. |
| F4 | addr_wdith | `([2-9]\Z | [1-9]\d{1,2}\Z)` |
| F5 | data_width | `([4-9]\Z | [1-9]\d{1,2}\Z)` |
| F7 | reg_pre | `"[a-zA-Z_]\w*"\Z | ""\Z` |
| K4 | rw_cg | YES or other | Enable clock gating for RW/WO/RWT regs. |
| B6 | cdc | SYNC or other | SYNC disables CDC logic generation. |
| K6 | reset-macro | YES or other | Use reset macro ctrl_always_ff_begin. |
Sources: regif.py:88-91, 1008-1020
Register and Field Formats
The tool expects specific formats for register and field definitions.
Register Format (reg_format)
| Column | Name | Regex Rule | Example |
|---|---|---|---|
| A | offset | 0x[\da-fA-F]+\Z | "0x001C" |
| B | regname | [a-zA-Z]\w*\Z | "M_DMA_CFG" |
| C | reg_des | .* | Description |
| D | width | [1-9]\d{1,2}\Z | 32 |
Sources: regif.py:53-57
Field Format (field_format)
| Column | Name | Regex Rule | Description |
|---|---|---|---|
| E | section | `[(\d+ | \d+:\d+)]\Z` |
| F | fd_name | [a-zA-Z]\w*\Z | Field name. |
| G | RW | (RW|RC|BP|CP|RO|WO|RWW|RWC|RWT|RWP)\Z | Access type. |
| H | reset | (\d+'(h|H)[\da-fA-F]+\Z|\d+'(d|D)\d+\Z|\d+'(b|B)[01]+\Z|0\Z) | Reset value, e.g., 8'hFF. |
| I | wprotect | `BITWISE|bitwise|[(\d+ | \d+:\d+)]\Z|\A\Z` |
| J | locksig | [a-zA-Z]\w*\Z|\A\Z | External signal to lock the field from being written. |
| K | fd_des | .* | Field description. |
Sources: regif.py:59-67
Code Generation Logic
The Regif class uses a set of string templates to construct the final Verilog files. The genverilog method orchestrates this process.
Verilog File Templates
The primary templates define the overall structure of the generated files.
VFILE: The main template for the_regif.vmodule. It includes placeholders for module definition, ports, declarations, and the write/read logic blocks.WFILE: The template for the optional_regif_wrap.vmodule, which is generated when any field uses thelocksigfeature. This wrapper instantiates the_regifmodule and adds the locking logic.
# Snippet from regif.py showing the main Verilog file template
VFILE = \
'''{defines}{macros}module {modulename}_regif(/*autoarg*/
{vioports}
);
{bmi_io}{iodeclars}
//======================================================
{vdeclars}
{write_part}
{read_part}
endmodule
{undefines}
'''
Sources: regif.py:290-301, 303-336
Logic Generation
The write_part and read_part are built by iterating through the Reg objects.
- Write Logic: The
Reg.writeproperty callsRegFields.w_block(). This method constructs thealwaysblock for register writes. It uses smaller templates (W_ALWAYS_L3,W_L1,RWT_L1, etc.) based on the field's access type (type) and protection attributes. For example, a field of typeRWT(Read-Write-Toggle) uses theRWT_L1template to generate a toggle-on-write behavior. - Read Logic: The
read_partis built from a largecase(bmi_addr)statement inside analwaysblock. EachRegobject contributes acaseitem via itsread()method, which concatenates all its fields' read values. Fields with types likeWO(Write-Only) are read back as0. - Locking Logic: If any field specifies a
locksig, thegen_lock_segmentmethod generates analwaysblock in the wrapper file (_regif_wrap.v) that prevents writes to the field when the lock signal is active.
Sources: regif.py:126-193, 350-355, 755-773
Documentation Generation
The gen_regif_doc function is responsible for creating the _Register_Manual.docx file. It uses the python-docx library to programmatically build the document.
creat_regs_detail: Iterates through each register from the parsed Excel data.creat_reg_table: For each register, it creates a table with a standard header (位数,名称,方向, etc.).fill_reg_fields: Populates the table with data for each field in the register.
Sources: regif.py:1232-1258
Validation and Checks
regif performs extensive validation to prevent the generation of broken Verilog.
- Static Check (
static_check): This function is called before object creation. It uses regex matching to validate that every cell in the Excel file conforms to the expected format defined inreg_format,field_format, andother_format. It also checks for duplicate register names and addresses.
Sources: regif.py:840-867 - Dynamic Check (
_dynamic_check): This is performed after theRegandFieldobjects are created. It checks for logical consistency that depends on relationships between fields._section_continue_check: Ensures that the bit sections of all fields within a register are contiguous and cover the entire register width without gaps or overlaps._protect_check: Validates that write-protection fields are correctly configured.rst_val_check: Confirms that a field's reset value does not exceed the bit width of the field.
Sources: regif.py:421-458, 545-570, 1028-1039