From 03d77ea37b14522a258323662b5df309e607fda5 Mon Sep 17 00:00:00 2001 From: Alex Mykyta Date: Mon, 2 May 2022 20:51:31 -0700 Subject: [PATCH] Add workaround to AXI4-Lite cpuif template to avoif quirk in Vivado xsim handling of non-power-of-2 array indexing. #7 --- src/peakrdl/regblock/cpuif/axi4lite/axi4lite_tmpl.sv | 9 ++++++++- src/peakrdl/regblock/cpuif/base.py | 3 ++- src/peakrdl/regblock/utils.py | 3 +++ tests/lib/simulators/xilinx.py | 2 ++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/peakrdl/regblock/cpuif/axi4lite/axi4lite_tmpl.sv b/src/peakrdl/regblock/cpuif/axi4lite/axi4lite_tmpl.sv index 287cc3a..676dbd8 100644 --- a/src/peakrdl/regblock/cpuif/axi4lite/axi4lite_tmpl.sv +++ b/src/peakrdl/regblock/cpuif/axi4lite/axi4lite_tmpl.sv @@ -138,7 +138,14 @@ struct { logic is_wr; logic err; logic [{{cpuif.data_width-1}}:0] rdata; -} axil_resp_buffer[{{cpuif.resp_buffer_size}}]; +} axil_resp_buffer[{{roundup_pow2(cpuif.resp_buffer_size)}}]; +{%- if not is_pow2(cpuif.resp_buffer_size) %} +// axil_resp_buffer is intentionally padded to the next power of two despite there +// only being {{cpuif.resp_buffer_size}} actual entries. +// This is to avoid quirks in some tools that cannot handle indexing into a non-power-of-2 array. +// Unused entries are expected to be optimized away +{% endif %} + logic [{{clog2(cpuif.resp_buffer_size)}}:0] axil_resp_wptr; logic [{{clog2(cpuif.resp_buffer_size)}}:0] axil_resp_rptr; diff --git a/src/peakrdl/regblock/cpuif/base.py b/src/peakrdl/regblock/cpuif/base.py index 090007f..654ca5c 100644 --- a/src/peakrdl/regblock/cpuif/base.py +++ b/src/peakrdl/regblock/cpuif/base.py @@ -4,7 +4,7 @@ import os import jinja2 as jj -from ..utils import get_always_ff_event, clog2, is_pow2 +from ..utils import get_always_ff_event, clog2, is_pow2, roundup_pow2 if TYPE_CHECKING: from ..exporter import RegblockExporter @@ -52,6 +52,7 @@ class CpuifBase: "get_resetsignal": self.exp.dereferencer.get_resetsignal, "clog2": clog2, "is_pow2": is_pow2, + "roundup_pow2": roundup_pow2, } template = jj_env.get_template(self.template_path) diff --git a/src/peakrdl/regblock/utils.py b/src/peakrdl/regblock/utils.py index 285dfdf..2e10940 100644 --- a/src/peakrdl/regblock/utils.py +++ b/src/peakrdl/regblock/utils.py @@ -36,3 +36,6 @@ def clog2(n: int) -> int: def is_pow2(x: int) -> bool: return (x > 0) and ((x & (x - 1)) == 0) + +def roundup_pow2(x: int) -> int: + return 1<<(x-1).bit_length() diff --git a/tests/lib/simulators/xilinx.py b/tests/lib/simulators/xilinx.py index 80171ab..56464f1 100644 --- a/tests/lib/simulators/xilinx.py +++ b/tests/lib/simulators/xilinx.py @@ -59,3 +59,5 @@ class Xilinx(Simulator): self.testcase_cls_inst.fail(line) elif line.startswith("Fatal:"): self.testcase_cls_inst.fail(line) + elif line.startswith("FATAL_ERROR:"): + self.testcase_cls_inst.fail(line)