Skip to content

Commit

Permalink
VHDL Consts - Use std_logic_vector instead of natural for sized const…
Browse files Browse the repository at this point in the history
…ants

Naturals are limited to <= 2^31 in VHDL. This can cause problems with
presets for 32-bit registers (if the MSB is 1).

Also add an elaboration test for the VHDL constants files.
  • Loading branch information
stefanlippuner committed Nov 21, 2023
1 parent 87fe2bc commit 86fb2fd
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 32 deletions.
24 changes: 18 additions & 6 deletions proto/cheby/print_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,28 @@ def __init__(self, fd, root):
self.pkg_name = root.hdl_module_name + '_Consts'

def pr_header(self):
# Enums use std_logic_vector.
if self.root.x_enums:
self.pr_raw("library ieee;\n")
self.pr_raw("use ieee.std_logic_1164.all;\n")
self.pr_raw("\n")
# Enums and constants use std_logic_vector.
self.pr_raw("library ieee;\n")
self.pr_raw("use ieee.std_logic_1164.all;\n")
self.pr_raw("\n")

self.pr_raw("package {} is\n".format(self.pkg_name))

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

def pr_const_width(self, name, val, width):
self.pr_raw(" constant {} : std_logic_vector({}-1 downto 0) := {};\n".format(name, width, val))

def pr_hex_const(self, name, val):
self.pr_const(name, "16#{:x}#".format(val))

def pr_hex_data(self, name, val, reg):
hex_width = round(reg.width / 4)
assert(4*hex_width == reg.width)
hex_val = "{:x}".format(val).zfill(hex_width)
self.pr_const_width(name, "x\"{}\"".format(hex_val), reg.width)

def pr_field_mask(self, f):
# Not printed as a mask may overflow a natural.
pass
Expand All @@ -160,7 +169,10 @@ def __init__(self, fd, root):
self.pkg_name = root.hdl_module_name + '_consts_pkg'

def pr_const(self, name, val):
self.pr_raw(" constant c_{} : Natural := {};\n".format(name, val))
super().pr_const("c_" + name, val)

def pr_const_width(self, name, val, width):
super().pr_const_width("c_" + name, val, width)

def pr_address(self, n):
# ADDR is a suffix.
Expand Down
64 changes: 38 additions & 26 deletions proto/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,27 @@ def write(self, s):
def get(self):
return self.buffer

def elab_vhdl(vhdl_file):
"""Function to elaborate VHDL"""
vhdl_pkgs = [srcdir + 'tb/cheby_pkg.vhd', srcdir + 'tb/wishbone_pkg.vhd']
res = subprocess.run(['ghdl', '-s', '-Werror=runtime-error'] + vhdl_pkgs + [vhdl_file])
if res.returncode != 0:
error('VHDL elaboration failed for {}'.format(vhdl_file))

def elab_sv(sv_file, top_entity):
"""Function to elaborate SV/Verilog"""
# Allow the definition of a different verilator command
if 'VERILATOR' in os.environ:
verilator_cmd = os.environ['VERILATOR']
else:
verilator_cmd = 'verilator'
if args.verbose:
print('Running elaboration with verilator command {}.'.format(verilator_cmd))

sv_pkgs = [srcdir + 'tb/dpssram.sv', srcdir + 'tb/wishbone_pkg.sv']
res = subprocess.run([verilator_cmd, '--lint-only', '--top-module', top_entity] + sv_pkgs + [sv_file])
if res.returncode != 0:
error('SV/Verilog elaboration failed for {}'.format(sv_file))

def parse_ok(f):
try:
Expand Down Expand Up @@ -348,15 +369,6 @@ def test_hdl_ref():
# Generate HDL, compare with a baseline and potentially elaborate.
global nbr_tests

if args.elaborate:
# Allow the definition of a different verilator command
if 'VERILATOR' in os.environ:
verilator_cmd = os.environ['VERILATOR']
else:
verilator_cmd = 'verilator'
if args.verbose:
print('Running elaboration with verilator command {}.'.format(verilator_cmd))

for f in ['fmc-adc01/fmc_adc_alt_trigin', 'fmc-adc01/fmc_adc_alt_trigout',
'issue9/test', 'issue10/test',
'issue8/simpleMap_bug', 'issue8/simpleMap_noBug',
Expand Down Expand Up @@ -435,22 +447,12 @@ def test_hdl_ref():
# Elaboration tests
top_entity = t.hdl_module_name

# Elaborate VHDL usign GHDL
vhdl_pkgs = [srcdir + 'tb/cheby_pkg.vhd', srcdir + 'tb/wishbone_pkg.vhd']
res = subprocess.run(['ghdl', '-s'] + vhdl_pkgs + [vhdl_file])
if res.returncode != 0:
error('VHDL elaboration failed for {}'.format(f))

# Elaborate SV using Verilator
sv_pkgs = [srcdir + 'tb/dpssram.sv', srcdir + 'tb/wishbone_pkg.sv']
res = subprocess.run([verilator_cmd, '--lint-only', '--top-module', top_entity] + sv_pkgs + [sv_file])
if res.returncode != 0:
error('SV elaboration failed for {}'.format(f))
# Elaborate VHDL using GHDL
elab_vhdl(vhdl_file)

# Elaborate Verilog using Verilator
res = subprocess.run([verilator_cmd, '--lint-only', '--top-module', top_entity] + sv_pkgs + [verilog_file])
if res.returncode != 0:
error('Verilog elaboration failed for {}'.format(f))
# Elaborate SV and Verilog using Verilator
elab_sv(sv_file, top_entity)
elab_sv(verilog_file, top_entity)

nbr_tests += 1

Expand Down Expand Up @@ -864,9 +866,10 @@ def test_wbgen2cheby():
def test_consts():
# Generate constants and compare with a baseline.
global nbr_tests

for f in ['demo_all', 'features/semver1', 'features/mapinfo1',
'issue64/simple_reg1', 'bug-consts/blkpfx',
'features/enums1', 'features/enums2']:
'features/enums1', 'features/enums2', 'bug-const-range/const_range']:
if args.verbose:
print('test consts: {}'.format(f))
cheby_file = srcdir + f + '.cheby'
Expand All @@ -887,8 +890,17 @@ def test_consts():
print_consts.pconsts_cheby(buf, t, style)
if not compare_buffer_and_file(buf, file):
error('consts {} generation error for {}'.format(style, f))
nbr_tests += 1

if args.elaborate:
# Elaboration tests

if style == 'vhdl' or style == 'vhdl-ohwr':
# Elaborate VHDL using GHDL
elab_vhdl(file)

# We don't test SV elaboration here because Verilator requires a top-level instance

nbr_tests += 1

def test_doc():
# Generate html and md, compare with a baseline.
Expand Down

0 comments on commit 86fb2fd

Please sign in to comment.