From 830324dcd2fc75adc621939eed5a6639c62075bf Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 13 Jan 2023 14:21:15 -0800 Subject: Lift artificial limit of 191 extensions Add new accessors that accept the isa_extension_t enum. Retain the original ones that accept unsigned char to avoid churn. --- riscv/isa_parser.cc | 2 +- riscv/isa_parser.h | 4 ++++ riscv/processor.h | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/riscv/isa_parser.cc b/riscv/isa_parser.cc index 9893c8a..9600a69 100644 --- a/riscv/isa_parser.cc +++ b/riscv/isa_parser.cc @@ -28,7 +28,7 @@ static void bad_priv_string(const char* priv) } isa_parser_t::isa_parser_t(const char* str, const char *priv) - : extension_table(256, false) + : extension_table(NUM_ISA_EXTENSIONS, false) { isa_string = strtolower(str); const char* all_subsets = "mafdqchpv"; diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 1426e42..69df34a 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -62,6 +62,7 @@ typedef enum { EXT_XZBR, EXT_XZBT, EXT_SSTC, + NUM_ISA_EXTENSIONS } isa_extension_t; typedef enum { @@ -83,6 +84,9 @@ public: reg_t get_max_isa() const { return max_isa; } std::string get_isa_string() const { return isa_string; } bool extension_enabled(unsigned char ext) const { + return extension_enabled(isa_extension_t(ext)); + } + bool extension_enabled(isa_extension_t ext) const { if (ext >= 'A' && ext <= 'Z') return (max_isa >> (ext - 'A')) & 1; else diff --git a/riscv/processor.h b/riscv/processor.h index c03f2de..5daa6f4 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -217,6 +217,9 @@ public: return !custom_extensions.empty(); } bool extension_enabled(unsigned char ext) const { + return extension_enabled(isa_extension_t(ext)); + } + bool extension_enabled(isa_extension_t ext) const { if (ext >= 'A' && ext <= 'Z') return state.misa->extension_enabled(ext); else @@ -226,6 +229,9 @@ public: // possibly be disabled dynamically. Useful for documenting // assumptions about writable misa bits. bool extension_enabled_const(unsigned char ext) const { + return extension_enabled_const(isa_extension_t(ext)); + } + bool extension_enabled_const(isa_extension_t ext) const { if (ext >= 'A' && ext <= 'Z') return state.misa->extension_enabled_const(ext); else -- cgit v1.1 From 57ae9e68442047b7ea2f3461a0d1c8cd8b2e89e2 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 13 Jan 2023 14:29:36 -0800 Subject: Use more appropriate data structure for extension_table We know its size at compile time. --- riscv/isa_parser.cc | 1 - riscv/isa_parser.h | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/riscv/isa_parser.cc b/riscv/isa_parser.cc index 9600a69..d3ef076 100644 --- a/riscv/isa_parser.cc +++ b/riscv/isa_parser.cc @@ -28,7 +28,6 @@ static void bad_priv_string(const char* priv) } isa_parser_t::isa_parser_t(const char* str, const char *priv) - : extension_table(NUM_ISA_EXTENSIONS, false) { isa_string = strtolower(str); const char* all_subsets = "mafdqchpv"; diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 69df34a..0575d92 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -4,7 +4,7 @@ #include "decode.h" -#include +#include #include #include @@ -98,7 +98,7 @@ public: protected: unsigned max_xlen; reg_t max_isa; - std::vector extension_table; + std::bitset extension_table; std::string isa_string; std::unordered_map extensions; }; -- cgit v1.1 From 5badd68ae1694d6c089a33a106a0c12bbee2bb9a Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 13 Jan 2023 15:11:32 -0800 Subject: Keep max_isa and extension_table in sync in exactly one place This fixes a bug where --isa=rv64imafdc would fail to set extension_table['F'] because of the ad hoc manner in which we were synchronizing max_isa and extension_table. --- riscv/isa_parser.cc | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/riscv/isa_parser.cc b/riscv/isa_parser.cc index d3ef076..c0cada7 100644 --- a/riscv/isa_parser.cc +++ b/riscv/isa_parser.cc @@ -32,13 +32,12 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) isa_string = strtolower(str); const char* all_subsets = "mafdqchpv"; - max_isa = reg_t(2) << 62; // enable zicntr and zihpm unconditionally for backward compatibility extension_table[EXT_ZICNTR] = true; extension_table[EXT_ZIHPM] = true; if (isa_string.compare(0, 4, "rv32") == 0) - max_xlen = 32, max_isa = reg_t(1) << 30; + max_xlen = 32; else if (isa_string.compare(0, 4, "rv64") == 0) max_xlen = 64; else @@ -51,11 +50,11 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) isa_string = isa_string.substr(0, 4) + "imafd" + isa_string.substr(5); // Fall through case 'i': - max_isa |= 1L << ('i' - 'a'); + extension_table['I'] = true; break; case 'e': - max_isa |= 1L << ('e' - 'a'); + extension_table['E'] = true; break; default: @@ -81,11 +80,10 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) extension_table[EXT_ZPSFOPERAND] = true; extension_table[EXT_ZMMUL] = true; break; case 'v': // even rv32iv implies double float - case 'q': max_isa |= 1L << ('d' - 'a'); + case 'q': extension_table['D'] = true; // Fall through - case 'd': max_isa |= 1L << ('f' - 'a'); + case 'd': extension_table['F'] = true; } - max_isa |= 1L << (*p - 'a'); extension_table[toupper(*p)] = true; while (isdigit(*(p + 1))) { ++p; // skip major version, point, and minor version if presented @@ -100,13 +98,13 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) do ++end; while (*end && *end != '_'); auto ext_str = std::string(p, end); if (ext_str == "zfh" || ext_str == "zfhmin") { - if (!((max_isa >> ('f' - 'a')) & 1)) + if (!extension_table['F']) bad_isa_string(str, ("'" + ext_str + "' extension requires 'F'").c_str()); extension_table[EXT_ZFHMIN] = true; if (ext_str == "zfh") extension_table[EXT_ZFH] = true; } else if (ext_str == "zvfh" || ext_str == "zvfhmin") { - if (!((max_isa >> ('v' - 'a')) & 1)) + if (!extension_table['V']) bad_isa_string(str, ("'" + ext_str + "' extension requires 'V'").c_str()); extension_table[EXT_ZVFHMIN] = true; @@ -224,8 +222,7 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) } else if (ext_str == "sstc") { extension_table[EXT_SSTC] = true; } else if (ext_str[0] == 'x') { - max_isa |= 1L << ('x' - 'a'); - extension_table[toupper('x')] = true; + extension_table['X'] = true; if (ext_str == "xbitmanip") { extension_table[EXT_XZBP] = true; extension_table[EXT_XZBS] = true; @@ -277,7 +274,7 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) extension_table[EXT_ZCD] = true; } - if (extension_table[EXT_ZFINX] && ((max_isa >> ('f' - 'a')) & 1)) { + if (extension_table[EXT_ZFINX] && extension_table['F']) { bad_isa_string(str, ("Zfinx/Zdinx/Zhinx{min} extensions conflict with 'F/D/Q/Zfh{min}' extensions")); } @@ -310,16 +307,15 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) else bad_priv_string(priv); - if (user) { - max_isa |= reg_t(user) << ('u' - 'a'); - extension_table['U'] = true; - } - - if (supervisor) { - max_isa |= reg_t(supervisor) << ('s' - 'a'); - extension_table['S'] = true; - } + extension_table['U'] = user; + extension_table['S'] = supervisor; - if (((max_isa >> ('h' - 'a')) & 1) && !supervisor) + if (extension_table['H'] && !supervisor) bad_isa_string(str, "'H' extension requires S mode"); + + max_isa = max_xlen == 32 ? reg_t(1) << 30 : reg_t(2) << 62; + for (unsigned char ch = 'A'; ch <= 'Z'; ch++) { + if (extension_table[ch]) + max_isa |= 1UL << (ch - 'A'); + } } -- cgit v1.1 From 39acd8e2eaf65e97dc4dbb31534285dcf591766a Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 13 Jan 2023 14:49:29 -0800 Subject: Simplify isa_parser_t::extension_enabled Now that we guarantee that max_isa and extension_table are synchronized, we only need to check the latter. --- riscv/isa_parser.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 0575d92..4be81d8 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -87,10 +87,7 @@ public: return extension_enabled(isa_extension_t(ext)); } bool extension_enabled(isa_extension_t ext) const { - if (ext >= 'A' && ext <= 'Z') - return (max_isa >> (ext - 'A')) & 1; - else - return extension_table[ext]; + return extension_table[ext]; } const std::unordered_map & get_extensions() const { return extensions; } -- cgit v1.1