gem5 v24.0.0.0
Loading...
Searching...
No Matches
utility.hh
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013 ARM Limited
3 * Copyright (c) 2014-2015 Sven Karlsson
4 * Copyright (c) 2018 TU Dresden
5 * Copyright (c) 2020 Barkhausen Institut
6 * All rights reserved
7 *
8 * The license below extends only to copyright in the software and shall
9 * not be construed as granting a license to any other intellectual
10 * property including but not limited to intellectual property relating
11 * to a hardware implementation of the functionality of the software
12 * licensed hereunder. You may use the software subject to the license
13 * terms below provided that you ensure that this notice is replicated
14 * unmodified and in its entirety in all distributions of the software,
15 * modified or unmodified, in source code or in binary form.
16 *
17 * Copyright (c) 2016-2017 The University of Virginia
18 * All rights reserved.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions are
22 * met: redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer;
24 * redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution;
27 * neither the name of the copyright holders nor the names of its
28 * contributors may be used to endorse or promote products derived from
29 * this software without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
37 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
38 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
39 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
41 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 */
43
44#ifndef __ARCH_RISCV_UTILITY_HH__
45#define __ARCH_RISCV_UTILITY_HH__
46
47#include <cmath>
48#include <cstdint>
49#include <sstream>
50#include <string>
51
55#include "base/types.hh"
56#include "cpu/reg_class.hh"
57#include "cpu/static_inst.hh"
58#include "cpu/thread_context.hh"
59#include "enums/RiscvType.hh"
60#include "rvk.hh"
61
62namespace gem5
63{
64
65namespace RiscvISA
66{
67
68template<typename Type> struct double_width;
69template<> struct double_width<uint8_t> { using type = uint16_t;};
70template<> struct double_width<uint16_t> { using type = uint32_t;};
71template<> struct double_width<uint32_t> { using type = uint64_t;};
72template<> struct double_width<uint64_t> { using type = __uint128_t;};
73template<> struct double_width<int8_t> { using type = int16_t; };
74template<> struct double_width<int16_t> { using type = int32_t; };
75template<> struct double_width<int32_t> { using type = int64_t; };
76template<> struct double_width<int64_t> { using type = __int128_t; };
77template<> struct double_width<float32_t> { using type = float64_t;};
78template<> struct double_width<float16_t> { using type = float32_t;};
79template<> struct double_width<float8_t> { using type = float16_t;};
80
81template<typename Type> struct double_widthf;
82template<> struct double_widthf<uint32_t> { using type = float64_t;};
83template<> struct double_widthf<int32_t> { using type = float64_t;};
84template<> struct double_widthf<uint16_t> { using type = float32_t;};
85template<> struct double_widthf<int16_t> { using type = float32_t;};
86template<> struct double_widthf<uint8_t> { using type = float16_t;};
87template<> struct double_widthf<int8_t> { using type = float16_t;};
88
89template<typename T> inline bool
91{
92 return false;
93}
94
95template<> inline bool
97{
98 return std::isnan(val)
99 && (reinterpret_cast<uint32_t&>(val)&0x00400000);
100}
101
102template<> inline bool
104{
105 return std::isnan(val)
106 && (reinterpret_cast<uint64_t&>(val)&0x0008000000000000ULL);
107}
108
109template<typename T> inline bool
111{
112 return false;
113}
114
115template<> inline bool
117{
118 return std::isnan(val)
119 && (reinterpret_cast<uint32_t&>(val)&0x00200000);
120}
121
122template<> inline bool
124{
125 return std::isnan(val)
126 && (reinterpret_cast<uint64_t&>(val)&0x0004000000000000ULL);
127}
128
129inline std::string
131{
132 if (reg.is(IntRegClass)) {
133 if (reg.index() >= int_reg::NumArchRegs) {
134 /*
135 * This should only happen if a instruction is being speculatively
136 * executed along a not-taken branch, and if that instruction's
137 * width was incorrectly predecoded (i.e., it was predecoded as a
138 * full instruction rather than a compressed one or vice versa).
139 * It also should only happen if a debug flag is on that prints
140 * disassembly information, so rather than panic the incorrect
141 * value is printed for debugging help.
142 */
143 std::stringstream str;
144 str << "?? (x" << reg.index() << ')';
145 return str.str();
146 }
147 return int_reg::RegNames[reg.index()];
148 } else if (reg.is(FloatRegClass)) {
149 if (reg.index() >= float_reg::NumRegs) {
150 std::stringstream str;
151 str << "?? (f" << reg.index() << ')';
152 return str.str();
153 }
154 return float_reg::RegNames[reg.index()];
155 } else if (reg.is(VecRegClass)) {
156 if (reg.index() >= NumVecRegs) {
157 std::stringstream str;
158 str << "?? (v" << reg.index() << ')';
159 return str.str();
160 }
161 return VecRegNames[reg.index()];
162 } else {
163 /* It must be an InvalidRegClass, in RISC-V we should treat it as a
164 * zero register for the disassembler to work correctly.
165 */
166 return int_reg::RegNames[reg.index()];
167 }
168}
169
170template <typename T> inline std::make_unsigned_t<T>
171mulhu(std::make_unsigned_t<T> rs1, std::make_unsigned_t<T> rs2)
172{
173 using WideT = typename double_width<std::make_unsigned_t<T>>::type;
174 return ((WideT)rs1 * rs2) >> (sizeof(T) * 8);
175}
176
177template <typename T> inline std::make_signed_t<T>
178mulh(std::make_signed_t<T> rs1, std::make_signed_t<T> rs2)
179{
180 using WideT = typename double_width<std::make_signed_t<T>>::type;
181 return ((WideT)rs1 * rs2) >> (sizeof(T) * 8);
182}
183
184template <typename T> inline std::make_signed_t<T>
185mulhsu(std::make_signed_t<T> rs1, std::make_unsigned_t<T> rs2)
186{
187 using WideT = typename double_width<std::make_signed_t<T>>::type;
188 return ((WideT)rs1 * rs2) >> (sizeof(T) * 8);
189}
190
191template<typename T> inline T
193{
194 constexpr T kRsMin = std::numeric_limits<T>::min();
195 if (rs2 == 0) {
196 return -1;
197 } else if (rs1 == kRsMin && rs2 == -1) {
198 return kRsMin;
199 } else {
200 return rs1 / rs2;
201 }
202}
203
204template<typename T> inline T
206{
207 if (rs2 == 0) {
208 return std::numeric_limits<T>::max();
209 } else {
210 return rs1 / rs2;
211 }
212}
213
214template<typename T> inline T
216{
217 constexpr T kRsMin = std::numeric_limits<T>::min();
218 if (rs2 == 0) {
219 return rs1;
220 } else if (rs1 == kRsMin && rs2 == -1) {
221 return 0;
222 } else {
223 return rs1 % rs2;
224 }
225}
226
227template<typename T> inline T
229{
230 return (rs2 == 0) ? rs1 : rs1 % rs2;
231}
232
233// Vector extension functions
234inline uint64_t
235vtype_SEW(const uint64_t vtype)
236{
237 return 8 << bits(vtype, 5, 3);
238}
239
240/*
241* Encode LMUL to lmul as follows:
242* LMUL vlmul lmul
243* 1 000 0
244* 2 001 1
245* 4 010 2
246* 8 011 3
247* - 100 -
248* 1/8 101 -3
249* 1/4 110 -2
250* 1/2 111 -1
251*
252* then, we can calculate VLMAX = vlen >> (vsew + 3 - lmul)
253* e.g. vlen = 256 bits, SEW = 16, LMUL = 1/8
254* => VLMAX = vlen >> (1 + 3 - (-3))
255* = 256 >> 7
256* = 2
257* Ref: https://github.com/qemu/qemu/blob/5e9d14f2/target/riscv/cpu.h
258*/
259inline uint64_t
260vtype_VLMAX(const uint64_t vtype, const uint64_t vlen,
261 const bool per_reg = false)
262{
263 int64_t lmul = (int64_t)sext<3>(bits(vtype, 2, 0));
264 lmul = per_reg ? std::min<int64_t>(0, lmul) : lmul;
265 int64_t vsew = bits(vtype, 5, 3);
266 return vlen >> (vsew + 3 - lmul);
267}
268
269inline int64_t
270vtype_vlmul(const uint64_t vtype)
271{
272 return (int64_t)sext<3>(bits(vtype, 2, 0));
273}
274
275inline uint64_t
276vtype_regs_per_group(const uint64_t vtype)
277{
278 int64_t lmul = (int64_t)sext<3>(bits(vtype, 2, 0));
279 return 1 << std::max<int64_t>(0, lmul);
280}
281
282inline void
283vtype_set_vill(uint64_t& vtype)
284{
285 vtype = (uint64_t)0 ^ (1UL << (sizeof(RegVal) * 8 - 1));
286}
287
288inline uint64_t
290{
291 switch (width) {
292 case 0b000: return 8;
293 case 0b101: return 16;
294 case 0b110: return 32;
295 case 0b111: return 64;
296 default: GEM5_UNREACHABLE;
297 }
298}
299
300/*
301 * Spec Section 4.5
302 * Ref:
303 * https://github.com/qemu/qemu/blob/c7d773ae/target/riscv/vector_helper.c
304*/
305template<typename T>
306inline int
307elem_mask(const T* vs, const int index)
308{
309 static_assert(std::is_integral_v<T>);
310 int idx = index / (sizeof(T)*8);
311 int pos = index % (sizeof(T)*8);
312 return (vs[idx] >> pos) & 1;
313}
314
315template<typename T>
316inline int
317elem_mask_vseg(const T* vs, const int elem, const int num_fields)
318{
319 int index = floor(elem / num_fields);
320 static_assert(std::is_integral_v<T>);
321 int idx = index / (sizeof(T)*8);
322 int pos = index % (sizeof(T)*8);
323 return (vs[idx] >> pos) & 1;
324}
325
326template<typename FloatType, typename IntType = decltype(FloatType::v)> auto
327ftype(IntType a) -> FloatType
328{
329 if constexpr(std::is_same_v<uint32_t, IntType>)
330 return f32(a);
331 else if constexpr(std::is_same_v<uint64_t, IntType>)
332 return f64(a);
333 else if constexpr(std::is_same_v<uint16_t, IntType>)
334 return f16(a);
335 GEM5_UNREACHABLE;
336}
337
338// TODO: Consolidate ftype_freg(freg_t a) and ftype(IntType a) into a
339// single function
340template<typename FloatType, typename IntType = decltype(FloatType::v)> auto
341ftype_freg(freg_t a) -> FloatType
342{
343 if constexpr(std::is_same_v<uint32_t, IntType>)
344 return f32(a);
345 else if constexpr(std::is_same_v<uint64_t, IntType>)
346 return f64(a);
347 else if constexpr(std::is_same_v<uint16_t, IntType>)
348 return f16(a);
349 GEM5_UNREACHABLE;
350}
351
352template<typename FloatType> FloatType
353fadd(FloatType a, FloatType b)
354{
355 if constexpr(std::is_same_v<float32_t, FloatType>)
356 return f32_add(a, b);
357 else if constexpr(std::is_same_v<float64_t, FloatType>)
358 return f64_add(a, b);
359 else if constexpr(std::is_same_v<float16_t, FloatType>)
360 return f16_add(a, b);
361 GEM5_UNREACHABLE;
362}
363
364template<typename FloatType> FloatType
365fsub(FloatType a, FloatType b)
366{
367 if constexpr(std::is_same_v<float32_t, FloatType>)
368 return f32_sub(a, b);
369 else if constexpr(std::is_same_v<float64_t, FloatType>)
370 return f64_sub(a, b);
371 else if constexpr(std::is_same_v<float16_t, FloatType>)
372 return f16_sub(a, b);
373 GEM5_UNREACHABLE;
374}
375
376template<typename FloatType> FloatType
377fmin(FloatType a, FloatType b)
378{
379 if constexpr(std::is_same_v<float32_t, FloatType>)
380 return f32_min(a, b);
381 else if constexpr(std::is_same_v<float64_t, FloatType>)
382 return f64_min(a, b);
383 else if constexpr(std::is_same_v<float16_t, FloatType>)
384 return f16_min(a, b);
385 GEM5_UNREACHABLE;
386}
387
388template<typename FloatType> FloatType
389fmax(FloatType a, FloatType b)
390{
391 if constexpr(std::is_same_v<float32_t, FloatType>)
392 return f32_max(a, b);
393 else if constexpr(std::is_same_v<float64_t, FloatType>)
394 return f64_max(a, b);
395 else if constexpr(std::is_same_v<float16_t, FloatType>)
396 return f16_max(a, b);
397 GEM5_UNREACHABLE;
398}
399
400template<typename FloatType> FloatType
401fdiv(FloatType a, FloatType b)
402{
403 if constexpr(std::is_same_v<float32_t, FloatType>)
404 return f32_div(a, b);
405 else if constexpr(std::is_same_v<float64_t, FloatType>)
406 return f64_div(a, b);
407 else if constexpr(std::is_same_v<float16_t, FloatType>)
408 return f16_div(a, b);
409 GEM5_UNREACHABLE;
410}
411
412template<typename FloatType> FloatType
413fmul(FloatType a, FloatType b)
414{
415 if constexpr(std::is_same_v<float32_t, FloatType>)
416 return f32_mul(a, b);
417 else if constexpr(std::is_same_v<float64_t, FloatType>)
418 return f64_mul(a, b);
419 else if constexpr(std::is_same_v<float16_t, FloatType>)
420 return f16_mul(a, b);
421 GEM5_UNREACHABLE;
422}
423
424template<typename FloatType> FloatType
425fsqrt(FloatType a)
426{
427 if constexpr(std::is_same_v<float32_t, FloatType>)
428 return f32_sqrt(a);
429 else if constexpr(std::is_same_v<float64_t, FloatType>)
430 return f64_sqrt(a);
431 else if constexpr(std::is_same_v<float16_t, FloatType>)
432 return f16_sqrt(a);
433 GEM5_UNREACHABLE;
434}
435
436template<typename FloatType> FloatType
437frsqrte7(FloatType a)
438{
439 if constexpr(std::is_same_v<float32_t, FloatType>)
440 return f32_rsqrte7(a);
441 else if constexpr(std::is_same_v<float64_t, FloatType>)
442 return f64_rsqrte7(a);
443 else if constexpr(std::is_same_v<float16_t, FloatType>)
444 return f16_rsqrte7(a);
445 GEM5_UNREACHABLE;
446}
447
448template<typename FloatType> FloatType
449frecip7(FloatType a)
450{
451 if constexpr(std::is_same_v<float32_t, FloatType>)
452 return f32_recip7(a);
453 else if constexpr(std::is_same_v<float64_t, FloatType>)
454 return f64_recip7(a);
455 else if constexpr(std::is_same_v<float16_t, FloatType>)
456 return f16_recip7(a);
457 GEM5_UNREACHABLE;
458}
459
460template<typename FloatType> FloatType
461fclassify(FloatType a)
462{
463 if constexpr(std::is_same_v<float32_t, FloatType>)
464 return f32(f32_classify(a));
465 else if constexpr(std::is_same_v<float64_t, FloatType>)
466 return f64(f64_classify(a));
467 else if constexpr(std::is_same_v<float16_t, FloatType>)
468 return f16(f16_classify(a));
469 GEM5_UNREACHABLE;
470}
471
472template<typename FloatType> FloatType
473fsgnj(FloatType a, FloatType b, bool n, bool x)
474{
475 if constexpr(std::is_same_v<float32_t, FloatType>)
476 return fsgnj32(a, b, n, x);
477 else if constexpr(std::is_same_v<float64_t, FloatType>)
478 return fsgnj64(a, b, n, x);
479 else if constexpr(std::is_same_v<float16_t, FloatType>)
480 return fsgnj16(a, b, n, x);
481 GEM5_UNREACHABLE;
482}
483
484template<typename FloatType> bool
485fle(FloatType a, FloatType b)
486{
487 if constexpr(std::is_same_v<float32_t, FloatType>)
488 return f32_le(a, b);
489 else if constexpr(std::is_same_v<float64_t, FloatType>)
490 return f64_le(a, b);
491 else if constexpr(std::is_same_v<float16_t, FloatType>)
492 return f16_le(a, b);
493 GEM5_UNREACHABLE;
494}
495
496template<typename FloatType> bool
497feq(FloatType a, FloatType b)
498{
499 if constexpr(std::is_same_v<float32_t, FloatType>)
500 return f32_eq(a, b);
501 else if constexpr(std::is_same_v<float64_t, FloatType>)
502 return f64_eq(a, b);
503 else if constexpr(std::is_same_v<float16_t, FloatType>)
504 return f16_eq(a, b);
505 GEM5_UNREACHABLE;
506}
507
508template<typename FloatType> bool
509flt(FloatType a, FloatType b)
510{
511 if constexpr(std::is_same_v<float32_t, FloatType>)
512 return f32_lt(a, b);
513 else if constexpr(std::is_same_v<float64_t, FloatType>)
514 return f64_lt(a, b);
515 else if constexpr(std::is_same_v<float16_t, FloatType>)
516 return f16_lt(a, b);
517 GEM5_UNREACHABLE;
518}
519
520template<typename FloatType> FloatType
521fmadd(FloatType a, FloatType b, FloatType c)
522{
523 if constexpr(std::is_same_v<float32_t, FloatType>)
524 return f32_mulAdd(a, b, c);
525 else if constexpr(std::is_same_v<float64_t, FloatType>)
526 return f64_mulAdd(a, b, c);
527 else if constexpr(std::is_same_v<float16_t, FloatType>)
528 return f16_mulAdd(a, b, c);
529 GEM5_UNREACHABLE;
530}
531
532template<typename FloatType> FloatType
533fneg(FloatType a)
534{
535 if constexpr(std::is_same_v<float32_t, FloatType>)
536 return f32(a.v ^ uint32_t(mask(31, 31)));
537 else if constexpr(std::is_same_v<float64_t, FloatType>)
538 return f64(a.v ^ mask(63, 63));
539 else if constexpr(std::is_same_v<float16_t, FloatType>)
540 return f16(a.v ^ uint16_t(mask(15, 15)));
541 GEM5_UNREACHABLE;
542}
543
544template<typename FT, typename WFT = typename double_width<FT>::type> WFT
546{
547 if constexpr(std::is_same_v<float32_t, FT>)
548 return f32_to_f64(a);
549 else if constexpr(std::is_same_v<float16_t, FT>)
550 return f16_to_f32(a);
551 GEM5_UNREACHABLE;
552}
553
554template<typename FloatType, typename IntType = decltype(FloatType::v)> IntType
555f_to_ui(FloatType a, uint_fast8_t mode)
556{
557 if constexpr(std::is_same_v<float32_t, FloatType>)
558 return f32_to_ui32(a, mode, true);
559 else if constexpr(std::is_same_v<float64_t, FloatType>)
560 return f64_to_ui64(a, mode, true);
561 else if constexpr(std::is_same_v<float16_t, FloatType>)
562 return f16_to_ui16(a, mode, true);
563 GEM5_UNREACHABLE;
564}
565
566template<
567 typename FloatType,
568 typename IntType = decltype(double_width<FloatType>::type::v)
569> IntType
570f_to_wui(FloatType a, uint_fast8_t mode)
571{
572 if constexpr(std::is_same_v<float32_t, FloatType>)
573 return f32_to_ui64(a, mode, true);
574 else if constexpr(std::is_same_v<float16_t, FloatType>)
575 return f16_to_ui32(a, mode, true);
576 GEM5_UNREACHABLE;
577}
578
579template<
580 typename IntType,
581 typename FloatType = typename double_widthf<IntType>::type
582> IntType
583f_to_nui(FloatType a, uint_fast8_t mode)
584{
585 if constexpr(std::is_same_v<float64_t, FloatType>)
586 return f64_to_ui32(a, mode, true);
587 else if constexpr(std::is_same_v<float32_t, FloatType>)
588 return f32_to_ui16(a, mode, true);
589 else if constexpr(std::is_same_v<float16_t, FloatType>)
590 return f16_to_ui8(a, mode, true);
591 GEM5_UNREACHABLE;
592}
593
594template<typename FloatType, typename IntType = decltype(FloatType::v)> IntType
595f_to_i(FloatType a, uint_fast8_t mode)
596{
597 if constexpr(std::is_same_v<float32_t, FloatType>)
598 return (uint32_t)f32_to_i32(a, mode, true);
599 else if constexpr(std::is_same_v<float64_t, FloatType>)
600 return (uint64_t)f64_to_i64(a, mode, true);
601 else if constexpr(std::is_same_v<float16_t, FloatType>)
602 return (uint16_t)f16_to_i16(a, mode, true);
603 GEM5_UNREACHABLE;
604}
605
606template<
607 typename FloatType,
608 typename IntType = decltype(double_width<FloatType>::type::v)
609> IntType
610f_to_wi(FloatType a, uint_fast8_t mode)
611{
612 if constexpr(std::is_same_v<float32_t, FloatType>)
613 return (uint64_t)f32_to_i64(a, mode, true);
614 else if constexpr(std::is_same_v<float16_t, FloatType>)
615 return (uint32_t)f16_to_i32(a, mode, true);
616 GEM5_UNREACHABLE;
617}
618
619template<
620 typename IntType,
621 typename FloatType = typename double_widthf<IntType>::type
622> IntType
623f_to_ni(FloatType a, uint_fast8_t mode)
624{
625 if constexpr(std::is_same_v<float64_t, FloatType>)
626 return (uint32_t)f64_to_i32(a, mode, true);
627 else if constexpr(std::is_same_v<float32_t, FloatType>)
628 return (uint16_t)f32_to_i16(a, mode, true);
629 else if constexpr(std::is_same_v<float16_t, FloatType>)
630 return (uint8_t)f16_to_i8(a, mode, true);
631 GEM5_UNREACHABLE;
632}
633
634template<typename FloatType, typename IntType = decltype(FloatType::v)>
635FloatType
636ui_to_f(IntType a)
637{
638 if constexpr(std::is_same_v<float32_t, FloatType>)
639 return ui32_to_f32(a);
640 else if constexpr(std::is_same_v<float64_t, FloatType>)
641 return ui64_to_f64(a);
642 else if constexpr(std::is_same_v<float16_t, FloatType>)
643 return ui32_to_f16(a);
644 GEM5_UNREACHABLE;
645}
646
647template<
648 typename IntType,
649 typename FloatType = typename double_widthf<IntType>::type
650> FloatType
651ui_to_wf(IntType a)
652{
653 if constexpr(std::is_same_v<float64_t, FloatType>)
654 return ui32_to_f64(a);
655 else if constexpr(std::is_same_v<float32_t, FloatType>)
656 return ui32_to_f32(a);
657 else if constexpr(std::is_same_v<float16_t, FloatType>)
658 return ui32_to_f16(a);
659 GEM5_UNREACHABLE;
660}
661
662template<
663 typename FloatType,
664 typename IntType = decltype(double_width<FloatType>::type::v)
665> FloatType
666ui_to_nf(IntType a)
667{
668 if constexpr(std::is_same_v<float32_t, FloatType>)
669 return ui64_to_f32(a);
670 else if constexpr(std::is_same_v<float16_t, FloatType>)
671 return ui32_to_f16(a);
672 GEM5_UNREACHABLE;
673}
674
675template<typename FloatType, typename IntType = decltype(FloatType::v)>
676FloatType
677i_to_f(IntType a)
678{
679 if constexpr(std::is_same_v<float32_t, FloatType>)
680 return i32_to_f32((int32_t)a);
681 else if constexpr(std::is_same_v<float64_t, FloatType>)
682 return i64_to_f64((int64_t)a);
683 else if constexpr(std::is_same_v<float16_t, FloatType>)
684 return i32_to_f16((int16_t)a);
685 GEM5_UNREACHABLE;
686}
687
688template<
689 typename IntType,
690 typename FloatType = typename double_widthf<IntType>::type
691> FloatType
692i_to_wf(IntType a)
693{
694 if constexpr(std::is_same_v<float64_t, FloatType>)
695 return i32_to_f64((int32_t)a);
696 else if constexpr(std::is_same_v<float32_t, FloatType>)
697 return i32_to_f32((int16_t)a);
698 else if constexpr(std::is_same_v<float16_t, FloatType>)
699 return i32_to_f16((int8_t)a);
700 GEM5_UNREACHABLE;
701}
702
703template<
704 typename FloatType,
705 typename IntType = std::make_signed_t<
707 >
708> FloatType
709i_to_nf(IntType a)
710{
711 if constexpr(std::is_same_v<float32_t, FloatType>)
712 return i64_to_f32(a);
713 else if constexpr(std::is_same_v<float16_t, FloatType>)
714 return i32_to_f16(a);
715 GEM5_UNREACHABLE;
716}
717
718template<
719 typename FloatType,
720 typename FloatWType = typename double_width<FloatType>::type
721> FloatWType
722f_to_wf(FloatType a)
723{
724 if constexpr(std::is_same_v<float32_t, FloatType>)
725 return f32_to_f64(a);
726 else if constexpr(std::is_same_v<float16_t, FloatType>)
727 return f16_to_f32(a);
728 GEM5_UNREACHABLE;
729}
730
731template<
732 typename FloatNType,
733 typename FloatType = typename double_width<FloatNType>::type
734> FloatNType
735f_to_nf(FloatType a)
736{
737 if constexpr(std::is_same_v<float64_t, FloatType>)
738 return f64_to_f32(a);
739 else if constexpr(std::is_same_v<float32_t, FloatType>)
740 return f32_to_f16(a);
741 GEM5_UNREACHABLE;
742}
743
744//ref: https://locklessinc.com/articles/sat_arithmetic/
745template<typename T> T
746sat_add(T x, T y, bool* sat)
747{
748 using UT = std::make_unsigned_t<T>;
749 UT ux = x;
750 UT uy = y;
751 UT res = ux + uy;
752
753 int sh = sizeof(T) * 8 - 1;
754
755 ux = (ux >> sh) + (((UT)0x1 << sh) - 1);
756
757 if ((T) ((ux ^ uy) | ~(uy ^ res)) >= 0) {
758 res = ux;
759 *sat = true;
760 }
761 return res;
762}
763
764template<typename T> T
765sat_sub(T x, T y, bool* sat)
766{
767 using UT = std::make_unsigned_t<T>;
768 UT ux = x;
769 UT uy = y;
770 UT res = ux - uy;
771
772 int sh = sizeof(T) * 8 - 1;
773
774 ux = (ux >> sh) + (((UT)0x1 << sh) - 1);
775
776 if ((T) ((ux ^ uy) & (ux ^ res)) < 0) {
777 res = ux;
778 *sat = true;
779 }
780 return res;
781}
782
783template<typename T> T
784sat_addu(T x, T y, bool* sat)
785{
786 T res = x + y;
787
788 bool t = res < x;
789 if (false == *sat){
790 *sat = t;
791 }
792 res |= -(res < x);
793
794 return res;
795}
796
797template<typename T> T
798sat_subu(T x, T y, bool* sat)
799{
800 T res = x - y;
801
802 bool t = !(res <= x);
803 if (false == *sat){
804 *sat = t;
805 }
806
807 res &= -(res <= x);
808
809 return res;
810}
811
816template<typename T> T
817int_rounding(T result, uint8_t xrm, unsigned gb) {
818 const uint64_t lsb = 1UL << gb;
819 const uint64_t lsb_half = lsb >> 1;
820 switch (xrm) {
821 case 0 /* RNU */:
822 result += lsb_half;
823 break;
824 case 1 /* RNE */:
825 if ((result & lsb_half) &&
826 ((result & (lsb_half - 1)) || (result & lsb)))
827 result += lsb;
828 break;
829 case 2 /* RDN */:
830 break;
831 case 3 /* ROD */:
832 if (result & (lsb - 1))
833 result |= lsb;
834 break;
835 default:
836 panic("Invalid xrm value %d", (int)xrm);
837 }
838
839 return result;
840}
841
842} // namespace RiscvISA
843} // namespace gem5
844
845#endif // __ARCH_RISCV_UTILITY_HH__
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
Register ID: describe an architectural register with its class and index.
Definition reg_class.hh:94
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
constexpr uint64_t sext(uint64_t val)
Sign-extend an N-bit value to 64 bits.
Definition bitfield.hh:129
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
Bitfield< 31 > n
Bitfield< 5 > t
Definition misc_types.hh:71
Bitfield< 7 > b
Bitfield< 8, 7 > sh
const std::vector< std::string > RegNames
Definition float.hh:201
const std::vector< std::string > RegNames
Definition int.hh:125
float32_t fsgnj32(float32_t a, float32_t b, bool n, bool x)
Definition float.hh:222
FloatType ui_to_nf(IntType a)
Definition utility.hh:666
float16_t fsgnj16(float16_t a, float16_t b, bool n, bool x)
Definition float.hh:215
bool flt(FloatType a, FloatType b)
Definition utility.hh:509
float64_t freg_t
Definition float.hh:69
T sat_subu(T x, T y, bool *sat)
Definition utility.hh:798
std::make_unsigned_t< T > mulhu(std::make_unsigned_t< T > rs1, std::make_unsigned_t< T > rs2)
Definition utility.hh:171
Bitfield< 14, 12 > width
Definition types.hh:160
FloatWType f_to_wf(FloatType a)
Definition utility.hh:722
static constexpr float32_t f32(uint32_t v)
Definition float.hh:98
int elem_mask(const T *vs, const int index)
Definition utility.hh:307
FloatType fclassify(FloatType a)
Definition utility.hh:461
FloatType frsqrte7(FloatType a)
Definition utility.hh:437
bool issignalingnan< double >(double val)
Definition utility.hh:123
Bitfield< 5, 3 > vsew
Definition vector.hh:81
uint64_t vtype_VLMAX(const uint64_t vtype, const uint64_t vlen, const bool per_reg=false)
Definition utility.hh:260
IntType f_to_i(FloatType a, uint_fast8_t mode)
Definition utility.hh:595
Bitfield< 6 > a
Definition pagetable.hh:69
std::make_signed_t< T > mulh(std::make_signed_t< T > rs1, std::make_signed_t< T > rs2)
Definition utility.hh:178
int elem_mask_vseg(const T *vs, const int elem, const int num_fields)
Definition utility.hh:317
Bitfield< 30, 0 > index
IntType f_to_ni(FloatType a, uint_fast8_t mode)
Definition utility.hh:623
IntType f_to_ui(FloatType a, uint_fast8_t mode)
Definition utility.hh:555
FloatType fadd(FloatType a, FloatType b)
Definition utility.hh:353
FloatType frecip7(FloatType a)
Definition utility.hh:449
IntType f_to_wui(FloatType a, uint_fast8_t mode)
Definition utility.hh:570
Bitfield< 24, 20 > rs2
Definition types.hh:80
bool isquietnan< double >(double val)
Definition utility.hh:103
static constexpr float16_t f16(uint16_t v)
Definition float.hh:97
T div(T rs1, T rs2)
Definition utility.hh:192
bool issignalingnan(T val)
Definition utility.hh:110
bool isquietnan< float >(float val)
Definition utility.hh:96
T rem(T rs1, T rs2)
Definition utility.hh:215
std::string registerName(RegId reg)
Definition utility.hh:130
FloatType fmadd(FloatType a, FloatType b, FloatType c)
Definition utility.hh:521
FloatType i_to_f(IntType a)
Definition utility.hh:677
WFT fwiden(FT a)
Definition utility.hh:545
const std::vector< std::string > VecRegNames
Definition vector.hh:58
FloatType fmin(FloatType a, FloatType b)
Definition utility.hh:377
bool feq(FloatType a, FloatType b)
Definition utility.hh:497
bool fle(FloatType a, FloatType b)
Definition utility.hh:485
auto ftype_freg(freg_t a) -> FloatType
Definition utility.hh:341
std::make_signed_t< T > mulhsu(std::make_signed_t< T > rs1, std::make_unsigned_t< T > rs2)
Definition utility.hh:185
uint64_t vtype_regs_per_group(const uint64_t vtype)
Definition utility.hh:276
T int_rounding(T result, uint8_t xrm, unsigned gb)
Ref: https://github.com/riscv-software-src/riscv-isa-sim.
Definition utility.hh:817
FloatType fmul(FloatType a, FloatType b)
Definition utility.hh:413
FloatNType f_to_nf(FloatType a)
Definition utility.hh:735
FloatType i_to_nf(IntType a)
Definition utility.hh:709
T sat_add(T x, T y, bool *sat)
Definition utility.hh:746
void vtype_set_vill(uint64_t &vtype)
Definition utility.hh:283
Bitfield< 19, 15 > rs1
Definition types.hh:79
int64_t vtype_vlmul(const uint64_t vtype)
Definition utility.hh:270
static constexpr float64_t f64(uint64_t v)
Definition float.hh:99
FloatType fsub(FloatType a, FloatType b)
Definition utility.hh:365
float64_t fsgnj64(float64_t a, float64_t b, bool n, bool x)
Definition float.hh:229
T sat_addu(T x, T y, bool *sat)
Definition utility.hh:784
Bitfield< 3 > x
Definition pagetable.hh:73
FloatType fsgnj(FloatType a, FloatType b, bool n, bool x)
Definition utility.hh:473
FloatType i_to_wf(IntType a)
Definition utility.hh:692
FloatType fneg(FloatType a)
Definition utility.hh:533
T remu(T rs1, T rs2)
Definition utility.hh:228
Bitfield< 5 > ux
T divu(T rs1, T rs2)
Definition utility.hh:205
FloatType fsqrt(FloatType a)
Definition utility.hh:425
T sat_sub(T x, T y, bool *sat)
Definition utility.hh:765
FloatType ui_to_wf(IntType a)
Definition utility.hh:651
FloatType fmax(FloatType a, FloatType b)
Definition utility.hh:389
Bitfield< 9, 5 > vs
bool issignalingnan< float >(float val)
Definition utility.hh:116
Bitfield< 5, 3 > c
IntType f_to_nui(FloatType a, uint_fast8_t mode)
Definition utility.hh:583
const int NumVecRegs
Definition vector.hh:56
uint64_t vtype_SEW(const uint64_t vtype)
Definition utility.hh:235
FloatType fdiv(FloatType a, FloatType b)
Definition utility.hh:401
auto ftype(IntType a) -> FloatType
Definition utility.hh:327
IntType f_to_wi(FloatType a, uint_fast8_t mode)
Definition utility.hh:610
FloatType ui_to_f(IntType a)
Definition utility.hh:636
bool isquietnan(T val)
Definition utility.hh:90
uint64_t width_EEW(uint64_t width)
Definition utility.hh:289
Bitfield< 5, 3 > reg
Definition types.hh:92
Bitfield< 63 > val
Definition misc.hh:804
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t RegVal
Definition types.hh:173
@ FloatRegClass
Floating-point register.
Definition reg_class.hh:62
@ VecRegClass
Vector Register.
Definition reg_class.hh:64
@ IntRegClass
Integer register.
Definition reg_class.hh:61
constexpr bool isnan(gem5::AMDGPU::fp16_e5m10_info a)
Definition fp16_e5m10.hh:83

Generated on Tue Jun 18 2024 16:23:57 for gem5 by doxygen 1.11.0