Browse Source

Merge pull request #1228 from riscv-software-src/ext-limit

Lift artificial limit of 191 extensions; simplify isa_parser_t::extension_enabled
pull/1230/head
Andrew Waterman 3 years ago
committed by GitHub
parent
commit
e4d2458e7e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 41
      riscv/isa_parser.cc
  2. 13
      riscv/isa_parser.h
  3. 6
      riscv/processor.h

41
riscv/isa_parser.cc

@ -28,18 +28,16 @@ static void bad_priv_string(const char* priv)
} }
isa_parser_t::isa_parser_t(const char* str, const char *priv) isa_parser_t::isa_parser_t(const char* str, const char *priv)
: extension_table(256, false)
{ {
isa_string = strtolower(str); isa_string = strtolower(str);
const char* all_subsets = "mafdqchpv"; const char* all_subsets = "mafdqchpv";
max_isa = reg_t(2) << 62;
// enable zicntr and zihpm unconditionally for backward compatibility // enable zicntr and zihpm unconditionally for backward compatibility
extension_table[EXT_ZICNTR] = true; extension_table[EXT_ZICNTR] = true;
extension_table[EXT_ZIHPM] = true; extension_table[EXT_ZIHPM] = true;
if (isa_string.compare(0, 4, "rv32") == 0) 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) else if (isa_string.compare(0, 4, "rv64") == 0)
max_xlen = 64; max_xlen = 64;
else else
@ -52,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); isa_string = isa_string.substr(0, 4) + "imafd" + isa_string.substr(5);
// Fall through // Fall through
case 'i': case 'i':
max_isa |= 1L << ('i' - 'a'); extension_table['I'] = true;
break; break;
case 'e': case 'e':
max_isa |= 1L << ('e' - 'a'); extension_table['E'] = true;
break; break;
default: default:
@ -82,11 +80,10 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_ZPSFOPERAND] = true; extension_table[EXT_ZPSFOPERAND] = true;
extension_table[EXT_ZMMUL] = true; break; extension_table[EXT_ZMMUL] = true; break;
case 'v': // even rv32iv implies double float case 'v': // even rv32iv implies double float
case 'q': max_isa |= 1L << ('d' - 'a'); case 'q': extension_table['D'] = true;
// Fall through // 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; extension_table[toupper(*p)] = true;
while (isdigit(*(p + 1))) { while (isdigit(*(p + 1))) {
++p; // skip major version, point, and minor version if presented ++p; // skip major version, point, and minor version if presented
@ -101,13 +98,13 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
do ++end; while (*end && *end != '_'); do ++end; while (*end && *end != '_');
auto ext_str = std::string(p, end); auto ext_str = std::string(p, end);
if (ext_str == "zfh" || ext_str == "zfhmin") { 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()); bad_isa_string(str, ("'" + ext_str + "' extension requires 'F'").c_str());
extension_table[EXT_ZFHMIN] = true; extension_table[EXT_ZFHMIN] = true;
if (ext_str == "zfh") if (ext_str == "zfh")
extension_table[EXT_ZFH] = true; extension_table[EXT_ZFH] = true;
} else if (ext_str == "zvfh" || ext_str == "zvfhmin") { } 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()); bad_isa_string(str, ("'" + ext_str + "' extension requires 'V'").c_str());
extension_table[EXT_ZVFHMIN] = true; extension_table[EXT_ZVFHMIN] = true;
@ -225,8 +222,7 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
} else if (ext_str == "sstc") { } else if (ext_str == "sstc") {
extension_table[EXT_SSTC] = true; extension_table[EXT_SSTC] = true;
} else if (ext_str[0] == 'x') { } else if (ext_str[0] == 'x') {
max_isa |= 1L << ('x' - 'a'); extension_table['X'] = true;
extension_table[toupper('x')] = true;
if (ext_str == "xbitmanip") { if (ext_str == "xbitmanip") {
extension_table[EXT_XZBP] = true; extension_table[EXT_XZBP] = true;
extension_table[EXT_XZBS] = true; extension_table[EXT_XZBS] = true;
@ -278,7 +274,7 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_ZCD] = true; 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")); bad_isa_string(str, ("Zfinx/Zdinx/Zhinx{min} extensions conflict with 'F/D/Q/Zfh{min}' extensions"));
} }
@ -311,16 +307,15 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
else else
bad_priv_string(priv); bad_priv_string(priv);
if (user) { extension_table['U'] = user;
max_isa |= reg_t(user) << ('u' - 'a'); extension_table['S'] = supervisor;
extension_table['U'] = true;
}
if (supervisor) {
max_isa |= reg_t(supervisor) << ('s' - 'a');
extension_table['S'] = true;
}
if (((max_isa >> ('h' - 'a')) & 1) && !supervisor) if (extension_table['H'] && !supervisor)
bad_isa_string(str, "'H' extension requires S mode"); 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');
}
} }

13
riscv/isa_parser.h

@ -4,7 +4,7 @@
#include "decode.h" #include "decode.h"
#include <vector> #include <bitset>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@ -62,6 +62,7 @@ typedef enum {
EXT_XZBR, EXT_XZBR,
EXT_XZBT, EXT_XZBT,
EXT_SSTC, EXT_SSTC,
NUM_ISA_EXTENSIONS
} isa_extension_t; } isa_extension_t;
typedef enum { typedef enum {
@ -83,10 +84,10 @@ public:
reg_t get_max_isa() const { return max_isa; } reg_t get_max_isa() const { return max_isa; }
std::string get_isa_string() const { return isa_string; } std::string get_isa_string() const { return isa_string; }
bool extension_enabled(unsigned char ext) const { bool extension_enabled(unsigned char ext) const {
if (ext >= 'A' && ext <= 'Z') return extension_enabled(isa_extension_t(ext));
return (max_isa >> (ext - 'A')) & 1; }
else bool extension_enabled(isa_extension_t ext) const {
return extension_table[ext]; return extension_table[ext];
} }
const std::unordered_map<std::string, extension_t*> & const std::unordered_map<std::string, extension_t*> &
get_extensions() const { return extensions; } get_extensions() const { return extensions; }
@ -94,7 +95,7 @@ public:
protected: protected:
unsigned max_xlen; unsigned max_xlen;
reg_t max_isa; reg_t max_isa;
std::vector<bool> extension_table; std::bitset<NUM_ISA_EXTENSIONS> extension_table;
std::string isa_string; std::string isa_string;
std::unordered_map<std::string, extension_t*> extensions; std::unordered_map<std::string, extension_t*> extensions;
}; };

6
riscv/processor.h

@ -217,6 +217,9 @@ public:
return !custom_extensions.empty(); return !custom_extensions.empty();
} }
bool extension_enabled(unsigned char ext) const { 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') if (ext >= 'A' && ext <= 'Z')
return state.misa->extension_enabled(ext); return state.misa->extension_enabled(ext);
else else
@ -226,6 +229,9 @@ public:
// possibly be disabled dynamically. Useful for documenting // possibly be disabled dynamically. Useful for documenting
// assumptions about writable misa bits. // assumptions about writable misa bits.
bool extension_enabled_const(unsigned char ext) const { 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') if (ext >= 'A' && ext <= 'Z')
return state.misa->extension_enabled_const(ext); return state.misa->extension_enabled_const(ext);
else else

Loading…
Cancel
Save