It is a tool written in Golang to automatically generate code of registers and fields in registers of a chip by reading a register-description file.
Now it firstly supports the auto-generation of C format because it's the most application scence.
To see the usage information:
$ reggen -h
Usage of reggen:
-d enable debug
-f string
output format type. [c] (default "c")
-i string
input file. (default "input.regs")So to output what you want, just:
$ reggen -i input.regs > regs.hBy redirection, you will get regs.h containing the macros about registers and
fields.
The content of input.regs is:
# This is a simple regs file
<chip>:simpleChip
<REG>[Control]: 0
BYPASS: 1
FREE_RUN: 7 - 6
<REG>: 0x2
type: 4-5 (0b00: client, 0x01: server, 2: route, 3: peer)
And the output of C format will be:
#pragma once
#ifndef BIT
#define BIT(x) (1 << (x))
#endif
// ONLY for _8bit-width_ register
#define MASK(a, b) (((uint8_t)-1 >> (7-(b))) & ~((1U<<(a))-1))
// Registers of simpleChip
#define REG_CONTROL 0x0 // 0
#define REG_BYPASS_BIT BIT(1)
#define REG_BYPASS_POS 1
#define REG_BYPASS_VAL(rv) (((rv) & BIT(1)) >> 1)
#define REG_BYPASS_ENABLE 1 // 0b1 0x1
#define REG_BYPASS_DISABLE 0 // 0b0 0x0
#define REG_FREE_RUN_STR 6
#define REG_FREE_RUN_END 7
#define REG_FREE_RUN_MSK MASK(6, 7)
#define REG_FREE_RUN_VAL(rv) (((rv) & REG_FREE_RUN_MSK) >> 6)
#define REG_FREE_RUN_SFT(v) (((v) & MASK(0, 1)) << 6)
#define REG_2 0x2 // 2
#define REG_TYPE_STR 4
#define REG_TYPE_END 5
#define REG_TYPE_MSK MASK(4, 5)
#define REG_TYPE_VAL(rv) (((rv) & REG_TYPE_MSK) >> 4)
#define REG_TYPE_SFT(v) (((v) & MASK(0, 1)) << 4)
#define REG_TYPE_CLIENT 0 // 0b0 0x0
#define REG_TYPE_SERVER 1 // 0b1 0x1
#define REG_TYPE_ROUTE 2 // 0b10 0x2
#define REG_TYPE_PEER 3 // 0b11 0x3The above example shows the input file's basic format which contains only a few keywords and follows simple and loose rules. All keywords are case-insensitive.
-
COMMENT: A line is treated as comment line if starting with#. Example:# si5324 is a clock generator. -
CHIP: Specify the chip's name. It is optional and name is empty. Example:<chip>:si5324, wheresi5324is the name. -
REG: : It defines the name (optional) and offset of a register and generally followed with serveralFIELDlines which defines this register's fields.Example:
<REG>[Control]: 0, where the register's name isControland offset is 0. -
FIELD: As says above,FIELDlines contains information of a register's field, including name, offset and enumrations (optional) in the format ofname: offset (enumVal: enumName,)that contains two parts. Thename-offsetpart is mandatory contrasting to theenumspart. Below explains more details aboutFIELDline.Example:
ck_prior1 : 0-1, where the field's name isck_prior1, offset range is0-1and there is noenumspart.
This part of FIELD line contains contains field's name and offset. The offset
are either bit or range which use - to connect. The start bit and end bit can
in either sides of -.
This part of FIELD line is optional and gives the enumeration range this
field can have, which is usually used when the field's offset is not only one
bit.
Embraced by ( and ), the enums are paired with :, where the enum value
is at left and value name right. Enum pairs are separated with ,.
For example, the chip spec have one field like:
4:3 | VALTIME[2]
00: 2ms
01: 100ms
10: 200ms
11: 13 seconds
Then the FIELD line should be one of lines below:
VALTIME: 4-3 (0b00: 2ms, 0b01: 100ms, 0b10: 200ms, 0b11: 13s)
VALTIME: 4-3 (0: 2ms, 1: 100ms, 2: 200ms, 3: 13s)
As the example shows, the enum number can be decimal and binary. Actually, it support four formats:
- dec, like 10 = 10
- bin, like 0b11 = 3
- oct, like 012 = 10
- hex, like 0x1f = 31
A formal-like sepcification is:
<chip>: chipName
<reg>[regName]: offset
field_1: bit
field_2: startBit - endBit
field_3: endBit - startBit (val1: val1Name, val2: val2Name)
Right now, the only one output format is the C format which uses #define
macros to represent all registers and fields and capitalize all their names.
It handle two types of field: bit and range. There are some common macros and
some are not. The common macros are:
-
REG_XXX_VAL(rv): Forbittype, it gets the value of this field, 1 or 0 of course. Forrange, it can get this field's value from register valuerv. For example,REG_XXX_VAL(0x10) = 2for3-4. -
REG_XXX_VALNAME VALNUM: It is often used forrangetype. As the above exampletype: 4-5 (0b00: client, 0x01: server, 2: route, 3: peer), the ouput is:#define REG_TYPE_CLIENT 0 // 0b0 0x0 #define REG_TYPE_SERVER 1 // 0b1 0x1 #define REG_TYPE_ROUTE 2 // 0b10 0x2 #define REG_TYPE_PEER 3 // 0b11 0x3 -
The macros only for
bittype are:REG_XXX_BIT: i.e. BIT(n), n is the offset.REG_XXX_POS: it is the offset of this field.
-
The macros only for
rangetype are:REG_XXX_MSK: the mask for this field. For example,REG_XXX_MSK = 0x18for3-4.REG_XXX_SFT(v): it shifts the field's valuevto the correct offset. For example,REG_XXX_SFT(1) = 0x08for3-4.
simple chip:
REG: REG_<reg>
FLD: REG_<field>
ENU: REG_<filed>_<enum>complex chip with module:
//////////////////////////////////////////////
// <module>
MOD: REG_<module>_BASE_ADDR 0x0000000
REG: REG_<module>_<reg>
FLD: REG_<module>_<field>
ENM: REG_<module>_<filed>_<enum>simple chip:
REG: REG_<reg>
FLD: REG_<reg>_<field>
ENU: REG_<reg>_<filed>_<enum>complex chip with module:
//////////////////////////////////////////////
// <module>
MOD: REG_<module>_BASE_ADDR 0x0000000
REG: REG_<module>_<reg>
FLD: REG_<module>_<reg>_<field>
ENM: REG_<module>_<reg>_<filed>_<enum>