diff options
author | Tristan Gingold <tgingold@free.fr> | 2023-01-14 19:02:44 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2023-01-15 11:36:03 +0100 |
commit | d4e17c57e7cfc895ea927a4f40116f47849d619d (patch) | |
tree | 5843a90941189bd8bd9f5e42f4350e5f98ae98cb /testsuite | |
parent | 9fcf6b6d1b125c0d8a98a6363e4b14618f8686c1 (diff) | |
download | ghdl-d4e17c57e7cfc895ea927a4f40116f47849d619d.tar.gz ghdl-d4e17c57e7cfc895ea927a4f40116f47849d619d.tar.bz2 ghdl-d4e17c57e7cfc895ea927a4f40116f47849d619d.zip |
testsuite/gna: add a test for #664
Diffstat (limited to 'testsuite')
-rw-r--r-- | testsuite/gna/issue664/numeric_system_pkg-orig.vhdl | 404 | ||||
-rw-r--r-- | testsuite/gna/issue664/numeric_system_pkg.vhdl | 404 | ||||
-rw-r--r-- | testsuite/gna/issue664/quire_accumulator.vhdl | 82 | ||||
-rw-r--r-- | testsuite/gna/issue664/quire_accumulator_tb.vhdl | 109 | ||||
-rw-r--r-- | testsuite/gna/issue664/reset_synchronizer.vhdl | 26 | ||||
-rw-r--r-- | testsuite/gna/issue664/tb_pkg.vhdl | 90 | ||||
-rwxr-xr-x | testsuite/gna/issue664/testsuite.sh | 23 |
7 files changed, 1138 insertions, 0 deletions
diff --git a/testsuite/gna/issue664/numeric_system_pkg-orig.vhdl b/testsuite/gna/issue664/numeric_system_pkg-orig.vhdl new file mode 100644 index 000000000..f5513b32a --- /dev/null +++ b/testsuite/gna/issue664/numeric_system_pkg-orig.vhdl @@ -0,0 +1,404 @@ +------------------------------------------------------------------
+---- ----
+---- Content: Numeric System Package ----
+---- for Stillwater KPUs ----
+---- ----
+---- Author: E. Theodore L. Omtzigt ----
+---- theo@stillwater-sc.com ----
+---- ----
+------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2017-2018 ----
+---- E. Theodore L. Omtzigt ----
+---- theo@stillwater-sc.com ----
+---- ----
+------------------------------------------------------------------
+---
+---- A posit is a tapered floating point representation.
+---- To compute with posits, the regime and exponent fields
+---- need to be consolidated. This process generates a triple
+---- (sign, exponent, fraction)
+---- These triples are the input values to the arithmetic units
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+--The numeric_system package defines the number system that the
+--overall system will be using. We are unifying integers, floats, and posits
+--by converting them to a (sign, scale, fraction) triple.
+--
+--Each number system, that is, integer, float, posit, valid, will have
+--a slightly different relationship between <NBITS,ES> and bit sizes
+--for scale and fraction. This pkg configures the root of that configuration.
+
+-- static constexpr size_t escale = size_t(1) << es; // 2^es
+-- static constexpr size_t range = escale * (4 * nbits - 8); // dynamic range of the posit configuration
+-- static constexpr size_t half_range = range >> 1; // position of the fixed point
+-- static constexpr size_t radix_point = half_range;
+-- // the upper is 1 bit bigger than the lower because maxpos^2 has that scale
+-- static constexpr size_t upper_range = half_range + 1; // size of the upper accumulator
+-- static constexpr size_t qbits = range + capacity; // size of the quire minus the sign bit: we are managing the sign explicitly
+
+package numeric_system_pkg is
+
+ generic(
+ NBITS : positive := 8; -- number of bits to represent encoding
+ EBITS : natural := 0; -- number of bits to represent exponent
+ SBITS : positive := 5; -- number of bits to represent scale
+ FBITS : natural := 5; -- number of bits to represent the fraction
+ CBITS : natural := 10 -- number of bits to represent quire capacity
+ );
+
+ -- arithmetic property constants
+ constant GUARDBITS : natural := 3;
+
+ impure function adder_width return positive;
+ impure function multiplier_width return positive;
+ impure function divider_width return positive;
+ impure function posit_dynamic_range return positive;
+ impure function quire_width return positive;
+
+ -- derived entities
+ constant BITS_ADDER_OUT : positive := adder_width;
+ constant BITS_MULTIPLIER_OUT : positive := multiplier_width;
+ constant BITS_DIVIDER_OUT : positive := divider_width;
+ constant BITS_MAX_ARITH_OUT : positive := divider_width;
+ constant BITS_DYNAMIC_RANGE : positive := posit_dynamic_range;
+ constant BITS_QUIRE_WIDTH : positive := quire_width;
+
+ -- posits that don't have fraction bits, still have a hidden bit
+ -- don't know what FBITS - 1 downto 0 evaluates to: possibly empty/null and thus trouble
+
+ -- posit encoding is a 2's complement encoding with respect to relational operators
+ subtype posit_word is signed(NBITS - 1 downto 0);
+ -- scales are integers and operators on scale are add/sub
+ subtype scale_word is signed(SBITS - 1 downto 0);
+ -- fractions are unsigned binary values with radix at FBITS-1
+ subtype fraction_word is unsigned(FBITS - 1 downto 0);
+
+ -- ssf triple === (sign, scale, fraction) normal form
+ -- ssf triples are stored in the register file
+ type ssf_type is record
+ isNaR : std_logic; -- encoding special case of Not a Real
+ isZero : std_logic; -- encoding special case of 0
+ sign : std_logic; -- sign
+ scale : scale_word; -- scale of the posit: useed ^ k * 2^e
+ fraction : fraction_word;
+ end record;
+
+ subtype add_significant_word is std_logic_vector(BITS_ADDER_OUT - 1 downto 0);
+ -- sss triple === (sign, scale, significant) output of an adder/subtractor
+ -- these records flow to the quire and the posit rounding stage
+ type sss_add_output_type is record
+ valid : std_logic;
+ isNaR : std_logic; -- encoding special case of Not a Real
+ isZero : std_logic; -- encoding special case of 0
+ sign : std_logic; -- sign
+ scale : scale_word; -- scale of the posit: useed ^ k * 2^e
+ significant : add_significant_word;
+ end record;
+
+ subtype mul_significant_word is std_logic_vector(BITS_MULTIPLIER_OUT - 1 downto 0);
+ -- sss triple === (sign, scale, signficant) output of a multiplier
+ -- these records flow to the quire and the posit rounding stage
+ type sss_mul_output_type is record
+ valid : std_logic;
+ isNaR : std_logic; -- encoding special case of Not a Real
+ isZero : std_logic; -- encoding special case of 0
+ sign : std_logic; -- sign
+ scale : scale_word; -- scale of the posit: useed ^ k * 2^e
+ significant : mul_significant_word;
+ end record;
+
+ subtype div_significant_word is std_logic_vector(BITS_DIVIDER_OUT - 1 downto 0);
+ -- sss triple === (sign, scale, signficant) output of a divider
+ -- these records flow to the quire and the posit rounding stage
+ type sss_div_output_type is record
+ isNaR : std_logic; -- encoding special case of Not a Real
+ isZero : std_logic; -- encoding special case of 0
+ sign : std_logic; -- sign
+ scale : scale_word; -- scale of the posit: useed ^ k * 2^e
+ significant : div_significant_word;
+ end record;
+
+ -- max sss triple that can come out of the arithmetic data path.
+ -- all smaller sss triples are right extended with '0's to unify
+ type sss_max_result_type is record
+ isNaR : std_logic; -- encoding special case of Not a Real
+ isZero : std_logic; -- encoding special case of 0
+ sign : std_logic; -- sign
+ scale : scale_word; -- scale of the posit: useed ^ k * 2^e
+ significant : std_logic_vector(BITS_MAX_ARITH_OUT - 1 downto 0);
+ end record;
+
+ -- input record to the ALU
+ type alu_input_type is record
+ opcode : std_logic_vector(2 downto 0); -- instruction to execute: add/sub, mul/div, recip, sqrt
+ operand_1 : ssf_type;
+ operand_2 : ssf_type;
+ operand_3 : ssf_type;
+ end record;
+
+ type quire_cmd_type is (LOAD, STORE, CLEAR, NOP); -- ACCUMULATE is default: keeps to 2 bits
+
+ -- are we managing the quire as a sign-magnitude or a 2's complement accumulator?
+ -- subtype quire_word is unsigned(BITS_QUIRE_WIDTH - 1 downto 0);
+ subtype quire_word is signed(BITS_QUIRE_WIDTH - 1 downto 0);
+ constant QUIRE_ZERO : quire_word := (others => '0');
+
+ type quire_in_type is record
+ cmd : quire_cmd_type;
+ d_in : quire_word; -- for quire load
+ end record;
+
+ subtype quire_in_reg is ssf_type; -- adding a raw posit value out of the posit registers
+ subtype quire_in_add is sss_add_output_type; -- adding the result of a posit addition without rounding
+ subtype quire_in_mul is sss_mul_output_type; -- adding the result of a posit multiplication without rounding
+
+ type quire_state_type is (QS_ZERO, QS_NEG, QS_POS, QS_OVERFLOW);
+
+ type quire_out_type is record
+ state : quire_state_type;
+ q_out : quire_word; -- for quire store
+ end record;
+
+ -- stringer for ssf tripslet
+ function ssf_to_string(
+ tag : String;
+ triplet : ssf_type
+ ) return String;
+
+ -- compare two ssf triplets
+ function cmpSSF(
+ val : ssf_type;
+ ref : ssf_type
+ ) return boolean;
+
+ -- report the configuration and the derived constants
+ procedure reportConfiguration;
+
+end package;
+
+package body numeric_system_pkg is
+
+ impure function adder_width return positive is
+ constant fbits_value : positive := FBITS;
+ begin
+ return fbits_value + 2;
+ end function;
+
+ impure function multiplier_width return positive is
+ constant fbits_value : positive := FBITS;
+ begin
+ return 2 * fbits_value + 1;
+ end function;
+
+ impure function divider_width return positive is
+ constant fbits_value : positive := FBITS;
+ begin
+ return 2 * fbits_value + 3;
+ end function;
+
+ impure function posit_dynamic_range return positive is
+ constant ebits_value : natural := EBITS;
+ constant nbits_value : positive := NBITS;
+ variable escale : positive := 1;
+ begin
+ escale := 2 ** ebits_value;
+ return escale * (4 * nbits_value - 8);
+ end function;
+
+ impure function quire_width return positive is
+ constant ebits_value : natural := EBITS;
+ constant nbits_value : positive := NBITS;
+ constant cbits_value : positive := CBITS;
+ variable escale : positive := 1;
+ variable qw : positive := 1;
+ begin
+ escale := 2 ** ebits_value;
+ qw := escale * (4 * nbits_value - 8) + cbits_value;
+ return qw;
+ end function;
+
+ procedure reportConfiguration is
+ begin
+ report "Configuration Parameters";
+ report " NBITS = " & to_string(NBITS);
+ report " EBITS = " & to_string(EBITS);
+ report " SBITS = " & to_string(SBITS);
+ report " FBITS = " & to_string(FBITS);
+ report " CBITS = " & to_string(CBITS);
+
+ report " GUARDBITS = " & to_string(GUARDBITS);
+
+ report "Derived Constants";
+ report " BITS_ADDER_OUT : " & to_string(BITS_ADDER_OUT);
+ report " BITS_MULTIPLIER_OUT : " & to_string(BITS_MULTIPLIER_OUT);
+ report " BITS_DIVIDER_OUT : " & to_string(BITS_DIVIDER_OUT);
+ report " BITS_MAX_ARITH_OUT : " & to_string(BITS_MAX_ARITH_OUT);
+ report " BITS_DYNAMIC_RANGE : " & to_string(BITS_DYNAMIC_RANGE);
+ report " BITS_QUIRE_WIDTH : " & to_string(BITS_QUIRE_WIDTH);
+ end procedure;
+
+ function ssf_to_string(
+ tag : String;
+ triplet : ssf_type
+ ) return String is
+ begin
+ if triplet.isZero = '1' then
+ return tag & " = (zero)";
+ elsif triplet.isNaR = '1' then
+ return tag & " = (NaR)";
+ else
+ return tag & " = (" & to_string(triplet.sign) & "," & to_string(triplet.scale) & "," & to_string(triplet.fraction) & ")";
+ end if;
+ end function;
+
+ function cmpSSF(
+ val : ssf_type;
+ ref : ssf_type
+ ) return boolean is
+ begin
+ -- first check special cases
+ if val.isZero = '1' AND val.isZero = ref.isZero then
+ return true;
+ end if;
+ if val.isNaR = '1' AND val.isNaR = ref.isNaR then
+ return true;
+ end if;
+ -- no special case, so compare ssf values
+ if val.sign = ref.sign AND val.scale = ref.scale AND val.fraction = ref.fraction then
+ return true;
+ else
+ return false;
+ end if;
+
+ end function;
+
+end package body numeric_system_pkg;
+
+------------------------------------------------------------------
+--- posit configuration ---
+------------------------------------------------------------------
+-- configuration for a posit<5,1>@1.0 : [s] [rr] [e] [f] [ggg]
+-- es = 1 -> useed = 2^2^1 = 4
+-- max k = nbits-2 = 3 -> 4^3 = 2^6 -> maxpos = 64
+-- fraction bits [h] [f] [ggg] -> 1 hidden bit, 1 fraction bit, 3 guard bits == 5 bits total
+-- adder out: 5 + 1 = 6
+
+-- configuration for a posit<8,0>@1.0 : [s] [rr] [] [fffff] [ggg]
+-- es = 0 -> useed = 2^2^0 = 2
+-- max k = nbits-2 = 6 -> 2^6 -> maxpos = 64 -> scale is 6+1 bits
+-- fraction bits [h] [ffff] [ggg] -> 1 hidden bit, 4 fraction bit, 3 guard bits == 8 bits total
+-- adder out: 8 + 1 = 9
+
+-- configuration for a posit<8,1>@1.0 : [s] [rr] [e] [ffff] [ggg]
+-- es = 1 -> useed = 2^2^1 = 4
+-- max k = nbits-2 = 6 -> 4^6 = 2^12 -> maxpos = 4096 -> scale is 12+1 bits
+-- fraction bits [h] [ffff] [ggg] -> 1 hidden bit, 4 fraction bit, 3 guard bits == 8 bits total
+-- adder out: 8 + 1 = 9
+
+------------------------------------------------------------------
+--- float configuration ---
+------------------------------------------------------------------
+-- configuation for a 8-bit float : [s] [ee] [f ffff] [ggg]
+-- nbits = 8, es = 2
+-- configuation for a 16-bit float : [s] [eeee e] [ff ffff ffff] [ggg]
+-- nbits = 16, es = 5
+-- configuation for a 32-bit float : [s] [eeee eeee] [fff ffff ffff ffff ffff ffff] [ggg]
+-- nbits = 32, es = 8
+
+-- Standard posit configurations
+-- posit< 8,0> useed scale 1 minpos scale -6 maxpos scale 6
+-- posit< 16,1> useed scale 2 minpos scale -28 maxpos scale 28
+-- posit< 32,2> useed scale 4 minpos scale -120 maxpos scale 120
+-- posit< 64,3> useed scale 8 minpos scale -496 maxpos scale 496
+
+package p4e0 is new work.numeric_system_pkg
+ generic map(
+ NBITS => 4, -- 4 encoding bits
+ EBITS => 0, -- no exponent bits
+ SBITS => 3, -- posit<4,0> scale ranges from -2 to 2
+ FBITS => 1, -- one fraction bit
+ CBITS => 10 -- 10 capacity bits for the quire
+ );
+
+package p5e0 is new work.numeric_system_pkg
+ generic map(
+ NBITS => 5, -- 5 encoding bits
+ EBITS => 0, -- no exponent bits
+ SBITS => 4, -- posit<5,0> scale ranges from -3 to 3
+ FBITS => 2, -- 2 fraction bits
+ CBITS => 10 -- 10 capacity bits for the quire
+ );
+
+package p8e0 is new work.numeric_system_pkg
+ generic map(
+ NBITS => 8, -- 8 encoding bits
+ EBITS => 0, -- no exponent bits
+ SBITS => 5, -- posit<8,0> scale ranges from -6 to 6
+ FBITS => 5, -- 5 fraction bits
+ CBITS => 10 -- 10 capacity bits for the quire
+ );
+
+package p8e1 is new work.numeric_system_pkg
+ generic map(
+ NBITS => 8, -- 8 encoding bits
+ EBITS => 1, -- 1 exponent bit
+ SBITS => 6, -- posit<8,1> scale ranges from -12 to 12
+ FBITS => 4, -- 4 fraction bits
+ CBITS => 10 -- 10 capacity bits for the quire
+ );
+
+package p8e2 is new work.numeric_system_pkg
+ generic map(
+ NBITS => 8, -- 8 encoding bits
+ EBITS => 2, -- 2 exponent bits
+ SBITS => 7, -- posit<8,2> scale ranges from -24 to 24
+ FBITS => 3, -- 3 fraction bits
+ CBITS => 10 -- 10 capacity bits for the quire
+ );
+
+package p16e1 is new work.numeric_system_pkg
+ generic map(
+ NBITS => 16, -- 16 encoding bits
+ EBITS => 1, -- one exponent bit
+ SBITS => 7, -- posit<16,1> scale ranges from -28 to 28
+ FBITS => 12, -- 12 fraction bits
+ CBITS => 10 -- 10 capacity bits for the quire
+ );
+
+-- posit< 8,0> useed scale 1 minpos scale -6 maxpos scale 6
+-- posit< 8,1> useed scale 2 minpos scale -12 maxpos scale 12
+-- posit< 8,2> useed scale 4 minpos scale -24 maxpos scale 24
+-- posit< 16,0> useed scale 1 minpos scale -14 maxpos scale 14
+-- posit< 16,1> useed scale 2 minpos scale -28 maxpos scale 28
+-- posit< 16,2> useed scale 4 minpos scale -56 maxpos scale 56
+
+------------------------------------------------------------------
+---- ----
+---- Content: Data Path Configuration Package ----
+---- for Stillwater KPUs ----
+---- ----
+---- Author: E. Theodore L. Omtzigt ----
+---- theo@stillwater-sc.com ----
+---- ----
+------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2017-2018 ----
+---- E. Theodore L. Omtzigt ----
+---- theo@stillwater-sc.com ----
+---- ----
+------------------------------------------------------------------
+
+-- generic configuration package name that we can use in the components
+-- and can change here to create different configurations
+package config_pkg is new work.numeric_system_pkg
+ generic map(
+ NBITS => 8, -- 8 encoding bits
+ EBITS => 1, -- no exponent bits
+ SBITS => 5, -- posit<8,0> scale ranges from -6 to 6
+ FBITS => 5, -- 5 fraction bits
+ CBITS => 8 -- 8 capacity bits for quire
+ );
+
diff --git a/testsuite/gna/issue664/numeric_system_pkg.vhdl b/testsuite/gna/issue664/numeric_system_pkg.vhdl new file mode 100644 index 000000000..196da2442 --- /dev/null +++ b/testsuite/gna/issue664/numeric_system_pkg.vhdl @@ -0,0 +1,404 @@ +------------------------------------------------------------------
+---- ----
+---- Content: Numeric System Package ----
+---- for Stillwater KPUs ----
+---- ----
+---- Author: E. Theodore L. Omtzigt ----
+---- theo@stillwater-sc.com ----
+---- ----
+------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2017-2018 ----
+---- E. Theodore L. Omtzigt ----
+---- theo@stillwater-sc.com ----
+---- ----
+------------------------------------------------------------------
+---
+---- A posit is a tapered floating point representation.
+---- To compute with posits, the regime and exponent fields
+---- need to be consolidated. This process generates a triple
+---- (sign, exponent, fraction)
+---- These triples are the input values to the arithmetic units
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+--The numeric_system package defines the number system that the
+--overall system will be using. We are unifying integers, floats, and posits
+--by converting them to a (sign, scale, fraction) triple.
+--
+--Each number system, that is, integer, float, posit, valid, will have
+--a slightly different relationship between <NBITS,ES> and bit sizes
+--for scale and fraction. This pkg configures the root of that configuration.
+
+-- static constexpr size_t escale = size_t(1) << es; // 2^es
+-- static constexpr size_t range = escale * (4 * nbits - 8); // dynamic range of the posit configuration
+-- static constexpr size_t half_range = range >> 1; // position of the fixed point
+-- static constexpr size_t radix_point = half_range;
+-- // the upper is 1 bit bigger than the lower because maxpos^2 has that scale
+-- static constexpr size_t upper_range = half_range + 1; // size of the upper accumulator
+-- static constexpr size_t qbits = range + capacity; // size of the quire minus the sign bit: we are managing the sign explicitly
+
+package numeric_system_pkg is
+
+ generic(
+ NBITS : positive := 8; -- number of bits to represent encoding
+ EBITS : natural := 0; -- number of bits to represent exponent
+ SBITS : positive := 5; -- number of bits to represent scale
+ FBITS : natural := 5; -- number of bits to represent the fraction
+ CBITS : natural := 10 -- number of bits to represent quire capacity
+ );
+
+ -- arithmetic property constants
+ constant GUARDBITS : natural := 3;
+
+ impure function adder_width return positive;
+ impure function multiplier_width return positive;
+ impure function divider_width return positive;
+ impure function posit_dynamic_range return positive;
+ impure function quire_width return positive;
+
+ -- derived entities
+ constant BITS_ADDER_OUT : positive := FBITS + 2;
+ constant BITS_MULTIPLIER_OUT : positive := 2 * FBITS + 1;
+ constant BITS_DIVIDER_OUT : positive := 2 * FBITS + 3;
+ constant BITS_MAX_ARITH_OUT : positive := 2 * FBITS + 3;
+ constant BITS_DYNAMIC_RANGE : positive := (2**EBITS) * (4 * NBITS - 8);
+ constant BITS_QUIRE_WIDTH : positive := BITS_DYNAMIC_RANGE + CBITS;
+
+ -- posits that don't have fraction bits, still have a hidden bit
+ -- don't know what FBITS - 1 downto 0 evaluates to: possibly empty/null and thus trouble
+
+ -- posit encoding is a 2's complement encoding with respect to relational operators
+ subtype posit_word is signed(NBITS - 1 downto 0);
+ -- scales are integers and operators on scale are add/sub
+ subtype scale_word is signed(SBITS - 1 downto 0);
+ -- fractions are unsigned binary values with radix at FBITS-1
+ subtype fraction_word is unsigned(FBITS - 1 downto 0);
+
+ -- ssf triple === (sign, scale, fraction) normal form
+ -- ssf triples are stored in the register file
+ type ssf_type is record
+ isNaR : std_logic; -- encoding special case of Not a Real
+ isZero : std_logic; -- encoding special case of 0
+ sign : std_logic; -- sign
+ scale : scale_word; -- scale of the posit: useed ^ k * 2^e
+ fraction : fraction_word;
+ end record;
+
+ subtype add_significant_word is std_logic_vector(BITS_ADDER_OUT - 1 downto 0);
+ -- sss triple === (sign, scale, significant) output of an adder/subtractor
+ -- these records flow to the quire and the posit rounding stage
+ type sss_add_output_type is record
+ valid : std_logic;
+ isNaR : std_logic; -- encoding special case of Not a Real
+ isZero : std_logic; -- encoding special case of 0
+ sign : std_logic; -- sign
+ scale : scale_word; -- scale of the posit: useed ^ k * 2^e
+ significant : add_significant_word;
+ end record;
+
+ subtype mul_significant_word is std_logic_vector(BITS_MULTIPLIER_OUT - 1 downto 0);
+ -- sss triple === (sign, scale, signficant) output of a multiplier
+ -- these records flow to the quire and the posit rounding stage
+ type sss_mul_output_type is record
+ valid : std_logic;
+ isNaR : std_logic; -- encoding special case of Not a Real
+ isZero : std_logic; -- encoding special case of 0
+ sign : std_logic; -- sign
+ scale : scale_word; -- scale of the posit: useed ^ k * 2^e
+ significant : mul_significant_word;
+ end record;
+
+ subtype div_significant_word is std_logic_vector(BITS_DIVIDER_OUT - 1 downto 0);
+ -- sss triple === (sign, scale, signficant) output of a divider
+ -- these records flow to the quire and the posit rounding stage
+ type sss_div_output_type is record
+ isNaR : std_logic; -- encoding special case of Not a Real
+ isZero : std_logic; -- encoding special case of 0
+ sign : std_logic; -- sign
+ scale : scale_word; -- scale of the posit: useed ^ k * 2^e
+ significant : div_significant_word;
+ end record;
+
+ -- max sss triple that can come out of the arithmetic data path.
+ -- all smaller sss triples are right extended with '0's to unify
+ type sss_max_result_type is record
+ isNaR : std_logic; -- encoding special case of Not a Real
+ isZero : std_logic; -- encoding special case of 0
+ sign : std_logic; -- sign
+ scale : scale_word; -- scale of the posit: useed ^ k * 2^e
+ significant : std_logic_vector(BITS_MAX_ARITH_OUT - 1 downto 0);
+ end record;
+
+ -- input record to the ALU
+ type alu_input_type is record
+ opcode : std_logic_vector(2 downto 0); -- instruction to execute: add/sub, mul/div, recip, sqrt
+ operand_1 : ssf_type;
+ operand_2 : ssf_type;
+ operand_3 : ssf_type;
+ end record;
+
+ type quire_cmd_type is (LOAD, STORE, CLEAR, NOP); -- ACCUMULATE is default: keeps to 2 bits
+
+ -- are we managing the quire as a sign-magnitude or a 2's complement accumulator?
+ -- subtype quire_word is unsigned(BITS_QUIRE_WIDTH - 1 downto 0);
+ subtype quire_word is signed(BITS_QUIRE_WIDTH - 1 downto 0);
+ constant QUIRE_ZERO : quire_word := (others => '0');
+
+ type quire_in_type is record
+ cmd : quire_cmd_type;
+ d_in : quire_word; -- for quire load
+ end record;
+
+ subtype quire_in_reg is ssf_type; -- adding a raw posit value out of the posit registers
+ subtype quire_in_add is sss_add_output_type; -- adding the result of a posit addition without rounding
+ subtype quire_in_mul is sss_mul_output_type; -- adding the result of a posit multiplication without rounding
+
+ type quire_state_type is (QS_ZERO, QS_NEG, QS_POS, QS_OVERFLOW);
+
+ type quire_out_type is record
+ state : quire_state_type;
+ q_out : quire_word; -- for quire store
+ end record;
+
+ -- stringer for ssf tripslet
+ function ssf_to_string(
+ tag : String;
+ triplet : ssf_type
+ ) return String;
+
+ -- compare two ssf triplets
+ function cmpSSF(
+ val : ssf_type;
+ ref : ssf_type
+ ) return boolean;
+
+ -- report the configuration and the derived constants
+ procedure reportConfiguration;
+
+end package;
+
+package body numeric_system_pkg is
+
+ impure function adder_width return positive is
+ constant fbits_value : positive := FBITS;
+ begin
+ return fbits_value + 2;
+ end function;
+
+ impure function multiplier_width return positive is
+ constant fbits_value : positive := FBITS;
+ begin
+ return 2 * fbits_value + 1;
+ end function;
+
+ impure function divider_width return positive is
+ constant fbits_value : positive := FBITS;
+ begin
+ return 2 * fbits_value + 3;
+ end function;
+
+ impure function posit_dynamic_range return positive is
+ constant ebits_value : natural := EBITS;
+ constant nbits_value : positive := NBITS;
+ variable escale : positive := 1;
+ begin
+ escale := 2 ** ebits_value;
+ return escale * (4 * nbits_value - 8);
+ end function;
+
+ impure function quire_width return positive is
+ constant ebits_value : natural := EBITS;
+ constant nbits_value : positive := NBITS;
+ constant cbits_value : positive := CBITS;
+ variable escale : positive := 1;
+ variable qw : positive := 1;
+ begin
+ escale := 2 ** ebits_value;
+ qw := escale * (4 * nbits_value - 8) + cbits_value;
+ return qw;
+ end function;
+
+ procedure reportConfiguration is
+ begin
+ report "Configuration Parameters";
+ report " NBITS = " & to_string(NBITS);
+ report " EBITS = " & to_string(EBITS);
+ report " SBITS = " & to_string(SBITS);
+ report " FBITS = " & to_string(FBITS);
+ report " CBITS = " & to_string(CBITS);
+
+ report " GUARDBITS = " & to_string(GUARDBITS);
+
+ report "Derived Constants";
+ report " BITS_ADDER_OUT : " & to_string(BITS_ADDER_OUT);
+ report " BITS_MULTIPLIER_OUT : " & to_string(BITS_MULTIPLIER_OUT);
+ report " BITS_DIVIDER_OUT : " & to_string(BITS_DIVIDER_OUT);
+ report " BITS_MAX_ARITH_OUT : " & to_string(BITS_MAX_ARITH_OUT);
+ report " BITS_DYNAMIC_RANGE : " & to_string(BITS_DYNAMIC_RANGE);
+ report " BITS_QUIRE_WIDTH : " & to_string(BITS_QUIRE_WIDTH);
+ end procedure;
+
+ function ssf_to_string(
+ tag : String;
+ triplet : ssf_type
+ ) return String is
+ begin
+ if triplet.isZero = '1' then
+ return tag & " = (zero)";
+ elsif triplet.isNaR = '1' then
+ return tag & " = (NaR)";
+ else
+ return tag & " = (" & to_string(triplet.sign) & "," & to_string(triplet.scale) & "," & to_string(triplet.fraction) & ")";
+ end if;
+ end function;
+
+ function cmpSSF(
+ val : ssf_type;
+ ref : ssf_type
+ ) return boolean is
+ begin
+ -- first check special cases
+ if val.isZero = '1' AND val.isZero = ref.isZero then
+ return true;
+ end if;
+ if val.isNaR = '1' AND val.isNaR = ref.isNaR then
+ return true;
+ end if;
+ -- no special case, so compare ssf values
+ if val.sign = ref.sign AND val.scale = ref.scale AND val.fraction = ref.fraction then
+ return true;
+ else
+ return false;
+ end if;
+
+ end function;
+
+end package body numeric_system_pkg;
+
+------------------------------------------------------------------
+--- posit configuration ---
+------------------------------------------------------------------
+-- configuration for a posit<5,1>@1.0 : [s] [rr] [e] [f] [ggg]
+-- es = 1 -> useed = 2^2^1 = 4
+-- max k = nbits-2 = 3 -> 4^3 = 2^6 -> maxpos = 64
+-- fraction bits [h] [f] [ggg] -> 1 hidden bit, 1 fraction bit, 3 guard bits == 5 bits total
+-- adder out: 5 + 1 = 6
+
+-- configuration for a posit<8,0>@1.0 : [s] [rr] [] [fffff] [ggg]
+-- es = 0 -> useed = 2^2^0 = 2
+-- max k = nbits-2 = 6 -> 2^6 -> maxpos = 64 -> scale is 6+1 bits
+-- fraction bits [h] [ffff] [ggg] -> 1 hidden bit, 4 fraction bit, 3 guard bits == 8 bits total
+-- adder out: 8 + 1 = 9
+
+-- configuration for a posit<8,1>@1.0 : [s] [rr] [e] [ffff] [ggg]
+-- es = 1 -> useed = 2^2^1 = 4
+-- max k = nbits-2 = 6 -> 4^6 = 2^12 -> maxpos = 4096 -> scale is 12+1 bits
+-- fraction bits [h] [ffff] [ggg] -> 1 hidden bit, 4 fraction bit, 3 guard bits == 8 bits total
+-- adder out: 8 + 1 = 9
+
+------------------------------------------------------------------
+--- float configuration ---
+------------------------------------------------------------------
+-- configuation for a 8-bit float : [s] [ee] [f ffff] [ggg]
+-- nbits = 8, es = 2
+-- configuation for a 16-bit float : [s] [eeee e] [ff ffff ffff] [ggg]
+-- nbits = 16, es = 5
+-- configuation for a 32-bit float : [s] [eeee eeee] [fff ffff ffff ffff ffff ffff] [ggg]
+-- nbits = 32, es = 8
+
+-- Standard posit configurations
+-- posit< 8,0> useed scale 1 minpos scale -6 maxpos scale 6
+-- posit< 16,1> useed scale 2 minpos scale -28 maxpos scale 28
+-- posit< 32,2> useed scale 4 minpos scale -120 maxpos scale 120
+-- posit< 64,3> useed scale 8 minpos scale -496 maxpos scale 496
+
+package p4e0 is new work.numeric_system_pkg
+ generic map(
+ NBITS => 4, -- 4 encoding bits
+ EBITS => 0, -- no exponent bits
+ SBITS => 3, -- posit<4,0> scale ranges from -2 to 2
+ FBITS => 1, -- one fraction bit
+ CBITS => 10 -- 10 capacity bits for the quire
+ );
+
+package p5e0 is new work.numeric_system_pkg
+ generic map(
+ NBITS => 5, -- 5 encoding bits
+ EBITS => 0, -- no exponent bits
+ SBITS => 4, -- posit<5,0> scale ranges from -3 to 3
+ FBITS => 2, -- 2 fraction bits
+ CBITS => 10 -- 10 capacity bits for the quire
+ );
+
+package p8e0 is new work.numeric_system_pkg
+ generic map(
+ NBITS => 8, -- 8 encoding bits
+ EBITS => 0, -- no exponent bits
+ SBITS => 5, -- posit<8,0> scale ranges from -6 to 6
+ FBITS => 5, -- 5 fraction bits
+ CBITS => 10 -- 10 capacity bits for the quire
+ );
+
+package p8e1 is new work.numeric_system_pkg
+ generic map(
+ NBITS => 8, -- 8 encoding bits
+ EBITS => 1, -- 1 exponent bit
+ SBITS => 6, -- posit<8,1> scale ranges from -12 to 12
+ FBITS => 4, -- 4 fraction bits
+ CBITS => 10 -- 10 capacity bits for the quire
+ );
+
+package p8e2 is new work.numeric_system_pkg
+ generic map(
+ NBITS => 8, -- 8 encoding bits
+ EBITS => 2, -- 2 exponent bits
+ SBITS => 7, -- posit<8,2> scale ranges from -24 to 24
+ FBITS => 3, -- 3 fraction bits
+ CBITS => 10 -- 10 capacity bits for the quire
+ );
+
+package p16e1 is new work.numeric_system_pkg
+ generic map(
+ NBITS => 16, -- 16 encoding bits
+ EBITS => 1, -- one exponent bit
+ SBITS => 7, -- posit<16,1> scale ranges from -28 to 28
+ FBITS => 12, -- 12 fraction bits
+ CBITS => 10 -- 10 capacity bits for the quire
+ );
+
+-- posit< 8,0> useed scale 1 minpos scale -6 maxpos scale 6
+-- posit< 8,1> useed scale 2 minpos scale -12 maxpos scale 12
+-- posit< 8,2> useed scale 4 minpos scale -24 maxpos scale 24
+-- posit< 16,0> useed scale 1 minpos scale -14 maxpos scale 14
+-- posit< 16,1> useed scale 2 minpos scale -28 maxpos scale 28
+-- posit< 16,2> useed scale 4 minpos scale -56 maxpos scale 56
+
+------------------------------------------------------------------
+---- ----
+---- Content: Data Path Configuration Package ----
+---- for Stillwater KPUs ----
+---- ----
+---- Author: E. Theodore L. Omtzigt ----
+---- theo@stillwater-sc.com ----
+---- ----
+------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2017-2018 ----
+---- E. Theodore L. Omtzigt ----
+---- theo@stillwater-sc.com ----
+---- ----
+------------------------------------------------------------------
+
+-- generic configuration package name that we can use in the components
+-- and can change here to create different configurations
+package config_pkg is new work.numeric_system_pkg
+ generic map(
+ NBITS => 8, -- 8 encoding bits
+ EBITS => 1, -- no exponent bits
+ SBITS => 5, -- posit<8,0> scale ranges from -6 to 6
+ FBITS => 5, -- 5 fraction bits
+ CBITS => 8 -- 8 capacity bits for quire
+ );
+
diff --git a/testsuite/gna/issue664/quire_accumulator.vhdl b/testsuite/gna/issue664/quire_accumulator.vhdl new file mode 100644 index 000000000..0c1800c5b --- /dev/null +++ b/testsuite/gna/issue664/quire_accumulator.vhdl @@ -0,0 +1,82 @@ +------------------------------------------------------------------
+---- ----
+---- Content: Parameterized quire accumulator unit: ----
+---- quire accumulator for deferred rounding ctrl ----
+---- ----
+---- Author: E. Theodore L. Omtzigt ----
+---- theo@stillwater-sc.com ----
+---- ----
+------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2017-2018 ----
+---- E. Theodore L. Omtzigt ----
+---- theo@stillwater-sc.com ----
+---- ----
+------------------------------------------------------------------
+
+---- A quire is a super accumulator that receives unrounded
+---- results from the adder and/or multiplier and accumulates
+---- the unrounded results enabling to user controlled rounding.
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.config_pkg.all;
+
+entity quire_accumulator is
+ port(
+ clk : in std_logic;
+ rst_n : in std_logic;
+ q_in : in quire_in_type;
+ reg : in quire_in_reg; -- output from register file
+ add : in quire_in_add; -- output from adder/subtractor
+ mul : in quire_in_mul; -- output from multiplier
+ q_out : out quire_out_type
+ );
+end entity;
+
+architecture behavior of quire_accumulator is
+
+ signal r, r_in : quire_word;
+
+begin
+ COMBINATORIAL : process(rst_n, q_in)
+ variable v : quire_word := QUIRE_ZERO;
+ variable state : quire_state_type := QS_ZERO;
+ begin
+ v := r; -- default assignment
+
+ if rst_n = '0' then
+ v := QUIRE_ZERO;
+ else
+ if q_in.cmd = LOAD then
+ v := q_in.d_in;
+ elsif q_in.cmd = CLEAR then
+ v := QUIRE_ZERO;
+ elsif q_in.cmd = NOP then
+ v := r;
+ end if;
+
+ if v = QUIRE_ZERO then
+ state := QS_ZERO;
+ else
+ state := QS_POS;
+ end if;
+ end if;
+
+ r_in <= v;
+ q_out.q_out <= r;
+ q_out.state <= state;
+
+ end process;
+
+ SEQUENTIAL : process(clk)
+ begin
+ if rising_edge(clk) then
+ r <= r_in;
+ end if;
+ end process;
+
+end architecture;
diff --git a/testsuite/gna/issue664/quire_accumulator_tb.vhdl b/testsuite/gna/issue664/quire_accumulator_tb.vhdl new file mode 100644 index 000000000..30292cde5 --- /dev/null +++ b/testsuite/gna/issue664/quire_accumulator_tb.vhdl @@ -0,0 +1,109 @@ +library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.config_pkg.all;
+use work.reset_synchronizer;
+--use work.quire_accumulator;
+
+entity quire_accumulator_tb is
+end entity;
+
+architecture behavior of quire_accumulator_tb is
+ component reset_synchronizer
+ port(
+ clk : in std_logic;
+ async_rst_n : in std_logic;
+ rst_n : out std_logic
+ );
+ end component reset_synchronizer;
+
+ -- component quire_accumulator
+ -- port(
+ -- clk : in std_logic;
+ -- rst_n : in std_logic;
+ -- q_in : in quire_in_type;
+ -- reg : in quire_in_reg;
+ -- add : in quire_in_add;
+ -- mul : in quire_in_mul;
+ -- q_out : out quire_out_type
+ -- );
+ -- end component quire_accumulator;
+
+ signal clk : std_logic := '0';
+ signal async_rst_n : std_logic := '0';
+ signal rst_n : std_logic := '0';
+ signal finished : std_logic := '0';
+
+ -- signal q_in : quire_in_type := (cmd => CLEAR, d_in => QUIRE_ZERO);
+ -- signal q_in_reg : quire_in_reg := (
+ -- isNaR => '0',
+ -- isZero => '1',
+ -- sign => '0',
+ -- scale => (others => '0'),
+ -- fraction => (others => '0')
+ -- );
+ -- signal q_in_add : quire_in_add := (
+ -- valid => '0',
+ -- isNaR => '0',
+ -- isZero => '1',
+ -- sign => '0',
+ -- scale => (others => '0'),
+ -- significant => (others => '0')
+ -- );
+ -- signal q_in_mul : quire_in_mul := (
+ -- valid => '0',
+ -- isNaR => '0',
+ -- isZero => '1',
+ -- sign => '0',
+ -- scale => (others => '0'),
+ -- significant => (others => '0')
+ -- );
+
+ -- signal q_out : quire_out_type := (
+ -- state => QS_ZERO,
+ -- q_out => QUIRE_ZERO
+ -- );
+ signal q_out : quire_out_type;
+begin
+ CLKGEN : process(clk, finished)
+ begin
+ clk <= not clk after 2500 ps when finished /= '1' else '0';
+ end process;
+
+ RESET_PULSE : process
+ begin
+ reportConfiguration;
+
+ wait for 5 ns;
+ async_rst_n <= '1';
+ wait;
+ end process;
+
+ END_OF_SIM : process
+ begin
+ wait for 100 ns;
+ finished <= '1';
+ wait;
+ end process;
+
+ RESET_SYNC : reset_synchronizer
+ port map(
+ clk => clk,
+ async_rst_n => async_rst_n,
+ rst_n => rst_n
+ );
+
+ -- SUT_PROC : quire_accumulator
+ -- port map(
+ -- clk => clk,
+ -- rst_n => rst_n,
+ -- q_in => q_in,
+ -- reg => q_in_reg,
+ -- add => q_in_add,
+ -- mul => q_in_mul,
+ -- q_out => q_out
+ -- );
+
+end architecture behavior;
diff --git a/testsuite/gna/issue664/reset_synchronizer.vhdl b/testsuite/gna/issue664/reset_synchronizer.vhdl new file mode 100644 index 000000000..1384d5c8f --- /dev/null +++ b/testsuite/gna/issue664/reset_synchronizer.vhdl @@ -0,0 +1,26 @@ +library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity reset_synchronizer is
+ port(
+ clk : in std_logic;
+ async_rst_n : in std_logic;
+ rst_n : out std_logic
+ );
+end entity reset_synchronizer;
+
+architecture behavior of reset_synchronizer is
+ signal r_ff1 : std_logic;
+begin
+ SYNCHRONIZE : process(clk, async_rst_n)
+ begin
+ if async_rst_n = '0' then
+ r_ff1 <= '0';
+ rst_n <= '0';
+ elsif rising_edge(clk) then
+ r_ff1 <= '1';
+ rst_n <= r_ff1;
+ end if;
+ end process;
+end architecture;
diff --git a/testsuite/gna/issue664/tb_pkg.vhdl b/testsuite/gna/issue664/tb_pkg.vhdl new file mode 100644 index 000000000..f7e59b998 --- /dev/null +++ b/testsuite/gna/issue664/tb_pkg.vhdl @@ -0,0 +1,90 @@ +------------------------------------------------------------------
+---- ----
+---- Content: testbench package ----
+---- ----
+---- Author: E. Theodore L. Omtzigt ----
+---- theo@stillwater-sc.com ----
+---- ----
+------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2017-2018 ----
+---- E. Theodore L. Omtzigt ----
+---- theo@stillwater-sc.com ----
+---- ----
+------------------------------------------------------------------
+
+---- A posit is a tapered floating point representation. To compute
+---- with posits, the regime and exponent fields need to be consolidated.
+---- This process generates a triple (sign, exponent, significant).
+---- These triples are the input values to the arithmetic units.
+
+library ieee;
+use ieee.std_logic_1164.all;
+use std.textio.all;
+
+package tb_pkg is
+
+ -- Procedure for clock generation
+ procedure clk_gen(signal clk : out std_logic; constant FREQ : real);
+ -- How to use
+ --architecture sim of tb is
+ -- -- Clock frequency and signal
+ -- signal clk_166 : std_logic;
+ -- signal clk_125 : std_logic;
+ --
+ --begin
+ --
+ -- -- Clock generation with concurrent procedure call
+ -- clk_gen(clk_166, 166.667E6); -- 166.667 MHz clock
+ -- clk_gen(clk_125, 125.000E6); -- 125.000 MHz clock
+ --
+ -- -- Time resolution show
+ -- assert FALSE report "Time resolution: " & time'image(time'succ(0 fs)) severity NOTE;
+ --
+ --end architecture;
+
+ --- trackError
+ function trackError(
+ condition : boolean;
+ message : String;
+ nrErrors : integer
+ ) return integer;
+
+end package;
+
+package body tb_pkg is
+
+ -- Procedure for clock generation
+ procedure clk_gen(signal clk : out std_logic; constant FREQ : real) is
+ constant PERIOD : time := 1 sec / FREQ; -- Full period
+ constant HIGH_TIME : time := PERIOD / 2; -- High time
+ constant LOW_TIME : time := PERIOD - HIGH_TIME; -- Low time; always >= HIGH_TIME
+ begin
+ -- Check the arguments
+ assert (HIGH_TIME /= 0 fs) report "clk_plain: High time is zero; time resolution to large for frequency" severity FAILURE;
+ -- Generate a clock cycle
+ loop
+ clk <= '1';
+ wait for HIGH_TIME;
+ clk <= '0';
+ wait for LOW_TIME;
+ end loop;
+ end procedure;
+
+ -- trackError
+ function trackError(
+ condition : boolean;
+ message : String;
+ nrErrors : integer) return integer is
+ variable runningCount : integer;
+ begin
+ assert (condition) report message;
+ if condition = FALSE then
+ runningCount := nrErrors + 1;
+ else
+ runningCount := nrErrors;
+ end if;
+ return runningCount;
+ end function;
+
+end package body;
diff --git a/testsuite/gna/issue664/testsuite.sh b/testsuite/gna/issue664/testsuite.sh new file mode 100755 index 000000000..4b4aca623 --- /dev/null +++ b/testsuite/gna/issue664/testsuite.sh @@ -0,0 +1,23 @@ +#! /bin/sh + +. ../../testenv.sh + +export GHDL_STD_FLAGS=--std=08 +analyze tb_pkg.vhdl +analyze numeric_system_pkg.vhdl +analyze reset_synchronizer.vhdl +analyze quire_accumulator.vhdl +analyze quire_accumulator_tb.vhdl +elab quire_accumulator_tb + +simulate quire_accumulator_tb + +# if ghdl_has_feature quire_accumulator_tb ghw; then +# simulate quire_accumulator_tb --wave=w.ghw +# fi + +rm -f w.ghw +clean + +echo "Test successful" + |