aboutsummaryrefslogtreecommitdiffstats
path: root/testsuite/gna/issue664/numeric_system_pkg-orig.vhdl
blob: f5513b32a74ff42f603b03fb59e4f71db61ecda3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
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
	);