From a62e59c47e36d578be5ce7206b1a3bf6cf2ba161 Mon Sep 17 00:00:00 2001 From: Andrey Smolyakov Date: Mon, 26 Jun 2023 21:27:16 +0300 Subject: [PATCH 1/2] Make change_size safer Allow an input vector to have any bits direction (downto and to). Add checks preventing an ill-formed resize operation. --- rtl/extras_2008/sizing_2008.vhdl | 61 ++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/rtl/extras_2008/sizing_2008.vhdl b/rtl/extras_2008/sizing_2008.vhdl index a958ffb..16819ef 100644 --- a/rtl/extras_2008/sizing_2008.vhdl +++ b/rtl/extras_2008/sizing_2008.vhdl @@ -264,29 +264,68 @@ package body sizing is end function; + --## Checks if resize is correct + function is_resize_ill_formed(new_size, + old_size : natural; + method : resize_method) + return boolean is + begin + case method is + when truncate_LSBs | truncate_MSBs => + return (old_size < new_size); + when extend_LSBs | extend_MSBs => + return (old_size > new_size); + end case; + end function; + --## Resizizng function for std_ulogic_vector clearly stating how exactly the --# resizing will be done. function change_size (s : std_ulogic_vector; new_size : positive; method : resize_method; extension : std_ulogic := '0' ) return std_ulogic_vector is - variable v : std_ulogic_vector(new_size-1 downto 0); + variable v : std_ulogic_vector(s'high downto s'low); -- var to resize + variable r : std_ulogic_vector(new_size-1 downto 0); -- result + + alias sr : std_ulogic_vector(s'reverse_range) is s; + alias rr : std_ulogic_vector(r'reverse_range) is r; + + -- Null range sulv to trigger elaboration failure + constant NASULV : std_ulogic_vector (0 downto 1) := (others => '0'); begin + -- Safeguards against ill-formed resize attempts + if is_resize_ill_formed(new_size, s'length, method) then + assert false report "Ill-formed resize." severity failure; + return NASULV; + end if; + + -- No need to do anything + if s'length = new_size then + return s; + end if; + + -- v'range is downto regardless of s'range + v := sr when s'ascending else s; + case method is when truncate_LSBs => - return s( s'high downto (s'length - new_size) ); + r := v( v'left downto (v'left - (new_size - 1)) ); when truncate_MSBs => - return s(new_size-1 downto 0); + r := v( (v'right + (new_size - 1)) downto v'right); when extend_LSBs => - v(v'high downto new_size - s'length) := s; - v(new_size - s'length - 1 downto 0) := (others => extension); - return v; + r(r'left downto (new_size - v'length)) := v; + r(r'left - v'length downto 0) := (others => extension); when extend_MSBs => - v(new_size-1 downto s'high+1) := (others => extension); - v(s'high downto 0) := s; - return v; + r(r'left downto v'length) := (others => extension); + r(v'length-1 downto 0) := v; end case; - + + -- Choose the same range as input + if s'ascending then + return rr; + else + return r; + end if; end function; --## Resizizng function for unsigned number clearly stating how exactly the @@ -308,7 +347,7 @@ package body sizing is case method is when extend_MSBs => return u_signed( - change_size(std_ulogic_vector(s), new_size, method, s(s'high))); + change_size(std_ulogic_vector(s), new_size, method, s(s'left))); when others => return u_signed( change_size(std_ulogic_vector(s), new_size, method, '0')); From 9a6b2a33f011ead573a14fd41d84f5d5bcceaa9a Mon Sep 17 00:00:00 2001 From: Andrey Smolyakov Date: Mon, 26 Jun 2023 21:28:50 +0300 Subject: [PATCH 2/2] Clarify MSB position in change_size (in comments) --- rtl/extras_2008/sizing_2008.vhdl | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/rtl/extras_2008/sizing_2008.vhdl b/rtl/extras_2008/sizing_2008.vhdl index 16819ef..9c001b8 100644 --- a/rtl/extras_2008/sizing_2008.vhdl +++ b/rtl/extras_2008/sizing_2008.vhdl @@ -50,6 +50,8 @@ --# Additionally the package provides functions for vectors resizing with --# interfaces which show clearly, how resizing should be performed (extending --# or truncating, most significant bits or least significant bits). +--# The leftmost bit is treated as the most significant bit (like in +--# NUMERIC_STD). --# --# This implementation excludes the overload of change_size for resolved --# std_logic_vector, because it breaks VHDL-2008 compiler (slv and sulv are @@ -141,7 +143,8 @@ package sizing is type resize_method is (truncate_LSBs, truncate_MSBs, extend_LSBs, extend_MSBs); --## Resizizng function for std_ulogic_vector clearly stating how exactly the - --# resizing will be done. + --# resizing will be done. The leftmost bit is treated as the most significant + --# bit (like in NUMERIC_STD). --# --# Args: --# s: Vector to resize @@ -154,7 +157,8 @@ package sizing is extension : std_ulogic := '0' ) return std_ulogic_vector; --## Resizizng function for unsigned number clearly stating how exactly the - --# resizing will be done. Extends numbers with zeros. + --# resizing will be done. Extends numbers with zeros. The leftmost bit is + --# treated as the most significant bit (like in NUMERIC_STD). --# --# Args: --# s: Vector to resize @@ -167,7 +171,8 @@ package sizing is --## Resizizng function for signed number clearly stating how exactly the --# resizing will be done. Extends most significant bits with a sign bit, - --# and least significant bits with zeros. + --# and least significant bits with zeros. The leftmost bit is treated as the + --# most significant bit (like in NUMERIC_STD). --# --# Args: --# s: Vector to resize @@ -279,7 +284,8 @@ package body sizing is end function; --## Resizizng function for std_ulogic_vector clearly stating how exactly the - --# resizing will be done. + --# resizing will be done. The leftmost bit is treated as the most significant + --# bit (like in NUMERIC_STD). function change_size (s : std_ulogic_vector; new_size : positive; method : resize_method; extension : std_ulogic := '0' ) return std_ulogic_vector is @@ -329,7 +335,8 @@ package body sizing is end function; --## Resizizng function for unsigned number clearly stating how exactly the - --# resizing will be done. Extends numbers with zeros. + --# resizing will be done. Extends numbers with zeros. The leftmost bit is + --# treated as the most significant bit (like in NUMERIC_STD). function change_size (s : u_unsigned; new_size : positive; method : resize_method) return u_unsigned is begin @@ -339,7 +346,8 @@ package body sizing is --## Resizizng function for signed number clearly stating how exactly the --# resizing will be done. Extends most significant bits with a sign bit, - --# and least significant bits with zeros. + --# and least significant bits with zeros. The leftmost bit is treated as the + --# most significant bit (like in NUMERIC_STD). function change_size (s : u_signed; new_size : positive; method : resize_method) return u_signed is begin