Skip to content

Commit

Permalink
Merge pull request #43 from lorenzschmid/gen-struct-matlab
Browse files Browse the repository at this point in the history
Structured constant generation (and Matlab)
  • Loading branch information
tgingold-cern authored Apr 17, 2024
2 parents 41aaecc + 40a5af0 commit bac5e3e
Show file tree
Hide file tree
Showing 24 changed files with 214 additions and 35 deletions.
11 changes: 8 additions & 3 deletions doc/cheby-ug.txt
Original file line number Diff line number Diff line change
Expand Up @@ -851,9 +851,14 @@ defines the address of the registers, the offset and a mask for each fields.
$ cheby --consts-style=STYLE --gen-consts -i INPUT.cheby
----

The `STYLE` can be either `verilog`, `sv`, `h`, `python`, `vhdl`, or `vhdl-ohwr`.
For vhdl the addresses and the offsets are integers, and the mask is not generated
(as it would often overflow the integer range).
The `STYLE` can be either `h`, `matlab`, `python`, `sv`, `tcl`, `verilog`,
`vhdl`, `vhdl-ohwr`, or `vhdl-orig`. For vhdl the addresses and the offsets are
integers, and the mask is not generated (as it would often overflow the integer
range).

Some styles also support the generation of structured constant files by adding a
`-struct` suffix to it. Thereby, the constants are grouped in a hierarchical
structure instead of individual constants. E.g., `matlab-struct`.

=== Generating SILECS file

Expand Down
12 changes: 7 additions & 5 deletions proto/cheby/gen_header.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@
def get_comment_token(language):
# Find comment token for the given language
comment_token_dict = {
'verilog': '//',
'sv': '//',
'h': '//', # C header file
'vhdl': '--',
'vhdl-orig': '--',
'vhdl-ohwr': '--',
'matlab': '%',
'matlab-struct': '%',
'python': '#',
'sv': '//',
'tcl': '#',
'verilog': '//',
'vhdl': '--',
'vhdl-ohwr': '--',
'vhdl-orig': '--',
}
return comment_token_dict[language]

Expand Down
23 changes: 19 additions & 4 deletions proto/cheby/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,23 @@ def decode_args():
help='select language for hdl generation')
aparser.add_argument('--gen-hdl', nargs='?', const='-',
help='generate hdl file')
aparser.add_argument('--consts-style', choices=['vhdl', 'vhdl-ohwr', 'vhdl-orig',
'verilog', 'sv', 'h', 'python', 'tcl'],
default='verilog',
help='select style for --gen-consts')
aparser.add_argument(
'--consts-style',
choices=[
'h',
'matlab',
'matlab-struct',
'python',
'sv',
'tcl',
'verilog',
'vhdl',
'vhdl-ohwr',
'vhdl-orig',
],
default='verilog',
help='select style for --gen-consts',
)
aparser.add_argument('--gen-consts', nargs='?', const='-',
help='generate constants as hdl file')
aparser.add_argument('--gen-edge', nargs='?', const='-',
Expand Down Expand Up @@ -274,10 +287,12 @@ def handle_file(args, filename):
print_latex.copy_template(f)
else:
raise AssertionError('Unknown doc format {} for template copying.'.format(args.doc))

if args.gen_consts is not None:
with open_filename(args.gen_consts) as f:
gen_header.gen_comment_header_maybe(f, args.header, args.consts_style)
print_consts.pconsts_cheby(f, t, args.consts_style)

if args.gen_wbgen_hdl is not None:
h = gen_wbgen_hdl.expand_hdl(t)
with open_filename(args.gen_wbgen_hdl) as f:
Expand Down
143 changes: 120 additions & 23 deletions proto/cheby/print_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@


class ConstsPrinter(object):
def __init__(self, fd, root):
def __init__(self, fd, root, sep="_", num="({})", indexOff=0):
super(ConstsPrinter, self).__init__()
self.fd = fd
self.root = root
self.pfx = root.name.upper()
self.sep = sep
self.num = num
self.indexOff = indexOff

def pr_raw(self, s):
self.fd.write(s)
Expand All @@ -17,7 +20,7 @@ def pr_header(self):

def pr_const(self, name, val):
"""Print a constant, :param val: is a string.
Must be overriden"""
Must be overridden"""
raise Exception

def pr_hex_const(self, name, val):
Expand All @@ -39,24 +42,41 @@ def pr_name(self, n):
if n == self.root:
return self.pfx
else:
return "{}_{}".format(self.pfx, n.c_name.upper())
if self.sep != "_":
# Return node names concatenated with separator
if n.name.isdecimal():
num = int(n.name) + self.indexOff
return "{}{}".format(self.pr_name(n.parent), self.num.format(num))
else:
return "{}{}{}".format(self.pr_name(n.parent), self.sep, n.name)
else:
# Return c_name with prefix
return "{}_{}".format(self.pfx, n.c_name.upper())

def pr_address(self, n):
self.pr_hex_addr("ADDR_" + self.pr_name(n), n.c_abs_addr)
if self.sep != "_":
name = self.pr_name(n) + self.sep + "ADDR"
else:
name = "ADDR_" + self.pr_name(n)
self.pr_hex_addr(name, n.c_abs_addr)

def pr_address_mask(self, n):
self.pr_hex_addr("ADDR_MASK_" + self.pr_name(n),
layout.round_pow2(n._parent.c_size) - n.c_size)
if self.sep != "_":
name = self.pr_name(n) + self.sep + "MASK"
else:
name = "ADDR_MASK_" + self.pr_name(n)

self.pr_hex_addr(name, layout.round_pow2(n._parent.c_size) - n.c_size)

def pr_size(self, n, sz):
self.pr_dec_const(self.pr_name(n) + "_SIZE", sz)
self.pr_dec_const(self.pr_name(n) + self.sep + "SIZE", sz)

def pr_version(self, n, name, nums):
v = (nums[0] << 16) | (nums[1] << 8) | nums[2]
self.pr_hex_const(self.pr_name(n) + "_" + name, v)
self.pr_hex_const(self.pr_name(n) + self.sep + name, v)

def pr_ident(self, n, name, val):
self.pr_hex_const(self.pr_name(n) + "_" + name, val)
self.pr_hex_const(self.pr_name(n) + self.sep + name, val)

def pr_reg(self, n):
if n.has_fields():
Expand All @@ -66,27 +86,41 @@ def pr_reg(self, n):
self.pr_preset(self.pr_name(n), f.c_preset, n.width)

def pr_field_offset(self, f):
self.pr_dec_const(self.pr_name(f) + "_OFFSET", f.lo)
self.pr_dec_const(self.pr_name(f) + self.sep + "OFFSET", f.lo)

def compute_mask(self, f):
def compute_width(self, f):
if f.hi is None:
mask = 1
return 1
else:
mask = (1 << (f.hi - f.lo + 1)) - 1
return f.hi - f.lo + 1

def compute_mask(self, f):
mask = (1 << self.compute_width(f)) - 1
return mask << f.lo

def pr_field_address(self, f):
if self.sep != "_":
name = self.pr_name(f) + self.sep + "ADDR"
else:
name = "ADDR_" + self.pr_name(f)
self.pr_hex_addr(name, f.parent.c_abs_addr)

def pr_field_width(self, f):
self.pr_dec_const(self.pr_name(f) + self.sep + "WIDTH", self.compute_width(f))

def pr_field_mask(self, f):
self.pr_hex_data(self.pr_name(f), self.compute_mask(f), f._parent.width)

def pr_field(self, f):
self.pr_field_address(f)
self.pr_field_offset(f)
self.pr_field_mask(f)

if f.c_preset is not None:
self.pr_preset(self.pr_name(f), f.c_preset, f.c_rwidth)

def pr_preset(self, name, preset, width):
name = name + '_PRESET'
name = name + self.sep + "PRESET"
self.pr_hex_data(name, preset, width)

def pr_enum(self, name, val, wd):
Expand Down Expand Up @@ -237,6 +271,18 @@ def pr_hex_const(self, name, val):
self.pr_const(name, "0x{:x}".format(val))


class ConstsPrinterMatlab(ConstsPrinter):
def __init__(self, fd, root, sep="_"):
super().__init__(fd, root, sep, num="({})", indexOff=1)

def pr_const(self, name, val):
self.pr_raw("{} = {};\n".format(name, val))

def pr_hex_const(self, name, val):
# Matlab does not support hexadecimal values
self.pr_dec_const(name, val)


class ConstsPrinterTCL(ConstsPrinter):
def pr_const(self, name, val):
self.pr_raw("set {} {}\n".format(name, val))
Expand Down Expand Up @@ -351,16 +397,67 @@ def pconsts_for_gen_c(fd, root):
pr.visit(root)


class StructVisitor(ConstsVisitor):
def __init__(self, printer):
self.printer = printer

# Set hierarchical separator
self.printer.sep = "."

# Avoid printing of mask
# The mask property comes without dedicated suffix and would overwrite/be
# overwritten by the remaining properties of the structure. Instead, the field
# width is printed.
self.printer.pr_field_mask = self.printer.pr_field_width

# Avoid printing of properties on nodes that are not leaves (i.e., fields)
self.printer.pr_size = lambda *args: None
self.printer.pr_version = lambda *args: None
self.printer.pr_ident = lambda *args: None

def pr_address(self, n):
# Avoid printing of properties on nodes that are not leaves (i.e., fields)
pass

def pr_address_mask(self, n):
# Avoid printing of properties on nodes that are not leaves (i.e., fields)
pass

def pr_size(self, n, sz):
# Avoid printing of properties on nodes that are not leaves (i.e., fields)
pass


@StructVisitor.register(tree.RepeatBlock)
def pstruct_repeatblock(pr, n):
# Avoid adding any elements (such as address) to list-like substructure
pconsts_composite_children(pr, n)


def pconsts_cheby(fd, root, style):
cls = {'verilog': ConstsPrinterVerilog,
'sv': ConstsPrinterSystemVerilog,
'vhdl-orig': ConstsPrinterVHDL,
'vhdl-ohwr': ConstsPrinterVHDLOhwr,
'vhdl': ConstsPrinterVHDL,
'h': ConstsPrinterH,
'python': ConstsPrinterPython,
'tcl': ConstsPrinterTCL}
pr = ConstsVisitor(cls[style](fd, root))
form = "consts"
if style.endswith("-struct"):
form = "struct"
style = style[:-7]

cls_style = {
'h': ConstsPrinterH,
'matlab': ConstsPrinterMatlab,
'python': ConstsPrinterPython,
'sv': ConstsPrinterSystemVerilog,
'tcl': ConstsPrinterTCL,
'verilog': ConstsPrinterVerilog,
'vhdl': ConstsPrinterVHDL,
'vhdl-ohwr': ConstsPrinterVHDLOhwr,
'vhdl-orig': ConstsPrinterVHDL,
}
cls_form = {
'consts': ConstsVisitor,
'struct': StructVisitor
}

pr = cls_form[form](cls_style[style](fd, root))

pr.pr_header()
pr.visit(root)
pr.pr_trailer()
7 changes: 7 additions & 0 deletions testfiles/demo_all-consts.h
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
#define DEMO_ALL_SIZE 8448
#define ADDR_DEMO_ALL_REG0 0x0UL
#define ADDR_DEMO_ALL_REG0_FIELD00 0x0UL
#define DEMO_ALL_REG0_FIELD00_OFFSET 1
#define DEMO_ALL_REG0_FIELD00 0x2UL
#define ADDR_DEMO_ALL_REG0_FIELD01 0x0UL
#define DEMO_ALL_REG0_FIELD01_OFFSET 4
#define DEMO_ALL_REG0_FIELD01 0xf0UL
#define ADDR_DEMO_ALL_REG0_FIELD02 0x0UL
#define DEMO_ALL_REG0_FIELD02_OFFSET 8
#define DEMO_ALL_REG0_FIELD02 0x700UL
#define DEMO_ALL_REG0_FIELD02_PRESET 0x2UL
#define ADDR_DEMO_ALL_REG1 0x4UL
#define DEMO_ALL_REG1_PRESET 0x123UL
#define ADDR_DEMO_ALL_REG2 0x8UL
#define ADDR_DEMO_ALL_REG2_FIELD10 0x8UL
#define DEMO_ALL_REG2_FIELD10_OFFSET 0
#define DEMO_ALL_REG2_FIELD10 0xffffUL
#define ADDR_DEMO_ALL_REG2_FIELD11 0x8UL
#define DEMO_ALL_REG2_FIELD11_OFFSET 16
#define DEMO_ALL_REG2_FIELD11 0xffffffffff0000ULL
#define ADDR_DEMO_ALL_BLOCK1 0x10UL
#define DEMO_ALL_BLOCK1_SIZE 16
#define ADDR_DEMO_ALL_BLOCK1_B1REG0 0x10UL
#define ADDR_DEMO_ALL_BLOCK1_B1REG1 0x14UL
#define ADDR_DEMO_ALL_BLOCK1_B1REG1_F0 0x14UL
#define DEMO_ALL_BLOCK1_B1REG1_F0_OFFSET 0
#define DEMO_ALL_BLOCK1_B1REG1_F0 0x1UL
#define ADDR_DEMO_ALL_BLOCK1_B1REG1_F1 0x14UL
#define DEMO_ALL_BLOCK1_B1REG1_F1_OFFSET 1
#define DEMO_ALL_BLOCK1_B1REG1_F1 0xfffffffeUL
#define ADDR_DEMO_ALL_BLOCK1_B1REG2 0x18UL
Expand Down
7 changes: 7 additions & 0 deletions testfiles/demo_all-consts.sv
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
package demo_all_Consts;
localparam DEMO_ALL_SIZE = 8448;
localparam ADDR_DEMO_ALL_REG0 = 'h0;
localparam ADDR_DEMO_ALL_REG0_FIELD00 = 'h0;
localparam DEMO_ALL_REG0_FIELD00_OFFSET = 1;
localparam DEMO_ALL_REG0_FIELD00 = 32'h2;
localparam ADDR_DEMO_ALL_REG0_FIELD01 = 'h0;
localparam DEMO_ALL_REG0_FIELD01_OFFSET = 4;
localparam DEMO_ALL_REG0_FIELD01 = 32'hf0;
localparam ADDR_DEMO_ALL_REG0_FIELD02 = 'h0;
localparam DEMO_ALL_REG0_FIELD02_OFFSET = 8;
localparam DEMO_ALL_REG0_FIELD02 = 32'h700;
localparam DEMO_ALL_REG0_FIELD02_PRESET = 3'h2;
localparam ADDR_DEMO_ALL_REG1 = 'h4;
localparam DEMO_ALL_REG1_PRESET = 32'h123;
localparam ADDR_DEMO_ALL_REG2 = 'h8;
localparam ADDR_DEMO_ALL_REG2_FIELD10 = 'h8;
localparam DEMO_ALL_REG2_FIELD10_OFFSET = 0;
localparam DEMO_ALL_REG2_FIELD10 = 64'hffff;
localparam ADDR_DEMO_ALL_REG2_FIELD11 = 'h8;
localparam DEMO_ALL_REG2_FIELD11_OFFSET = 16;
localparam DEMO_ALL_REG2_FIELD11 = 64'hffffffffff0000;
localparam ADDR_DEMO_ALL_BLOCK1 = 'h10;
localparam DEMO_ALL_BLOCK1_SIZE = 16;
localparam ADDR_DEMO_ALL_BLOCK1_B1REG0 = 'h10;
localparam ADDR_DEMO_ALL_BLOCK1_B1REG1 = 'h14;
localparam ADDR_DEMO_ALL_BLOCK1_B1REG1_F0 = 'h14;
localparam DEMO_ALL_BLOCK1_B1REG1_F0_OFFSET = 0;
localparam DEMO_ALL_BLOCK1_B1REG1_F0 = 32'h1;
localparam ADDR_DEMO_ALL_BLOCK1_B1REG1_F1 = 'h14;
localparam DEMO_ALL_BLOCK1_B1REG1_F1_OFFSET = 1;
localparam DEMO_ALL_BLOCK1_B1REG1_F1 = 32'hfffffffe;
localparam ADDR_DEMO_ALL_BLOCK1_B1REG2 = 'h18;
Expand Down
7 changes: 7 additions & 0 deletions testfiles/demo_all-consts.v
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
`define DEMO_ALL_SIZE 8448
`define ADDR_DEMO_ALL_REG0 'h0
`define ADDR_DEMO_ALL_REG0_FIELD00 'h0
`define DEMO_ALL_REG0_FIELD00_OFFSET 1
`define DEMO_ALL_REG0_FIELD00 'h2
`define ADDR_DEMO_ALL_REG0_FIELD01 'h0
`define DEMO_ALL_REG0_FIELD01_OFFSET 4
`define DEMO_ALL_REG0_FIELD01 'hf0
`define ADDR_DEMO_ALL_REG0_FIELD02 'h0
`define DEMO_ALL_REG0_FIELD02_OFFSET 8
`define DEMO_ALL_REG0_FIELD02 'h700
`define DEMO_ALL_REG0_FIELD02_PRESET 'h2
`define ADDR_DEMO_ALL_REG1 'h4
`define DEMO_ALL_REG1_PRESET 'h123
`define ADDR_DEMO_ALL_REG2 'h8
`define ADDR_DEMO_ALL_REG2_FIELD10 'h8
`define DEMO_ALL_REG2_FIELD10_OFFSET 0
`define DEMO_ALL_REG2_FIELD10 'hffff
`define ADDR_DEMO_ALL_REG2_FIELD11 'h8
`define DEMO_ALL_REG2_FIELD11_OFFSET 16
`define DEMO_ALL_REG2_FIELD11 'hffffffffff0000
`define ADDR_DEMO_ALL_BLOCK1 'h10
`define DEMO_ALL_BLOCK1_SIZE 16
`define ADDR_DEMO_ALL_BLOCK1_B1REG0 'h10
`define ADDR_DEMO_ALL_BLOCK1_B1REG1 'h14
`define ADDR_DEMO_ALL_BLOCK1_B1REG1_F0 'h14
`define DEMO_ALL_BLOCK1_B1REG1_F0_OFFSET 0
`define DEMO_ALL_BLOCK1_B1REG1_F0 'h1
`define ADDR_DEMO_ALL_BLOCK1_B1REG1_F1 'h14
`define DEMO_ALL_BLOCK1_B1REG1_F1_OFFSET 1
`define DEMO_ALL_BLOCK1_B1REG1_F1 'hfffffffe
`define ADDR_DEMO_ALL_BLOCK1_B1REG2 'h18
Expand Down
Loading

0 comments on commit bac5e3e

Please sign in to comment.