From cd2bc70a5d010161588f3cebcd2891514337e059 Mon Sep 17 00:00:00 2001 From: Rupert Swarbrick Date: Tue, 29 Mar 2022 20:21:21 +0100 Subject: Split isa_parser_t out of processor.* and into its own file (#955) The main motivation for this is that we want to move the ISA parsing logic to run before we even construct a simulator. That's probably a bit nicer if we don't depend on the processor header. It also means that we can stop depending on processor.h in disasm.cc or spike_log_parser.cc (both through disasm.h), which feels a bit cleaner: making sense of an instruction trace shouldn't really require knowledge of the internal state of a processor. --- riscv/disasm.h | 2 +- riscv/isa_parser.cc | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++++ riscv/isa_parser.h | 87 +++++++++++++++++++ riscv/processor.cc | 229 ------------------------------------------------ riscv/processor.h | 75 +--------------- riscv/riscv.mk.in | 1 + 6 files changed, 336 insertions(+), 304 deletions(-) create mode 100644 riscv/isa_parser.cc create mode 100644 riscv/isa_parser.h diff --git a/riscv/disasm.h b/riscv/disasm.h index ce844d6..338cac2 100644 --- a/riscv/disasm.h +++ b/riscv/disasm.h @@ -4,7 +4,7 @@ #define _RISCV_DISASM_H #include "decode.h" -#include "processor.h" +#include "isa_parser.h" #include #include #include diff --git a/riscv/isa_parser.cc b/riscv/isa_parser.cc new file mode 100644 index 0000000..766aa3a --- /dev/null +++ b/riscv/isa_parser.cc @@ -0,0 +1,246 @@ +#include "isa_parser.h" +#include "extension.h" + +static std::string strtolower(const char* str) +{ + std::string res; + for (const char *r = str; *r; r++) + res += std::tolower(*r); + return res; +} + +static void bad_option_string(const char *option, const char *value, + const char *msg) +{ + fprintf(stderr, "error: bad %s option '%s'. %s\n", option, value, msg); + abort(); +} + +static void bad_isa_string(const char* isa, const char* msg) +{ + bad_option_string("--isa", isa, msg); +} + +static void bad_priv_string(const char* priv) +{ + fprintf(stderr, "error: bad --priv option %s\n", priv); + abort(); +} + +isa_parser_t::isa_parser_t(const char* str, const char *priv) + : extension_table(256, false) +{ + 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; + else if (isa_string.compare(0, 4, "rv64") == 0) + max_xlen = 64; + else + bad_isa_string(str, "ISA strings must begin with RV32 or RV64"); + + switch (isa_string[4]) { + case 'g': + // G = IMAFD_Zicsr_Zifencei, but Spike includes the latter two + // unconditionally, so they need not be explicitly added here. + isa_string = isa_string.substr(0, 4) + "imafd" + isa_string.substr(5); + // Fall through + case 'i': + max_isa |= 1L << ('i' - 'a'); + break; + + case 'e': + max_isa |= 1L << ('e' - 'a'); + break; + + default: + bad_isa_string(str, ("'" + isa_string.substr(0, 4) + "' must be followed by I, E, or G").c_str()); + } + + const char* isa_str = isa_string.c_str(); + auto p = isa_str, subset = all_subsets; + for (p += 5; islower(*p) && !strchr("zsx", *p); ++p) { + while (*subset && (*p != *subset)) + ++subset; + + if (!*subset) { + if (strchr(all_subsets, *p)) + bad_isa_string(str, ("Extension '" + std::string(1, *p) + "' appears too late in ISA string").c_str()); + else + bad_isa_string(str, ("Unsupported extension '" + std::string(1, *p) + "'").c_str()); + } + + switch (*p) { + case 'p': extension_table[EXT_ZBPBO] = true; + extension_table[EXT_ZPN] = true; + extension_table[EXT_ZPSFOPERAND] = true; + extension_table[EXT_ZMMUL] = true; break; + case 'q': max_isa |= 1L << ('d' - 'a'); + // Fall through + case 'd': max_isa |= 1L << ('f' - 'a'); + } + max_isa |= 1L << (*p - 'a'); + extension_table[toupper(*p)] = true; + while (isdigit(*(p + 1))) { + ++p; // skip major version, point, and minor version if presented + if (*(p + 1) == 'p') ++p; + } + p += *(p + 1) == '_'; // underscores may be used to improve readability + } + + while (islower(*p) || (*p == '_')) { + p += *p == '_'; // first underscore is optional + auto end = p; + 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)) + 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 == "zicsr") { + // Spike necessarily has Zicsr, because + // Zicsr is implied by the privileged architecture + } else if (ext_str == "zifencei") { + // For compatibility with version 2.0 of the base ISAs, we + // unconditionally include FENCE.I, so Zifencei adds nothing more. + } else if (ext_str == "zihintpause") { + // HINTs encoded in base-ISA instructions are always present. + } else if (ext_str == "zmmul") { + extension_table[EXT_ZMMUL] = true; + } else if (ext_str == "zba") { + extension_table[EXT_ZBA] = true; + } else if (ext_str == "zbb") { + extension_table[EXT_ZBB] = true; + } else if (ext_str == "zbc") { + extension_table[EXT_ZBC] = true; + } else if (ext_str == "zbs") { + extension_table[EXT_ZBS] = true; + } else if (ext_str == "zbkb") { + extension_table[EXT_ZBKB] = true; + } else if (ext_str == "zbkc") { + extension_table[EXT_ZBKC] = true; + } else if (ext_str == "zbkx") { + extension_table[EXT_ZBKX] = true; + } else if (ext_str == "zk") { + extension_table[EXT_ZBKB] = true; + extension_table[EXT_ZBKC] = true; + extension_table[EXT_ZBKX] = true; + extension_table[EXT_ZKND] = true; + extension_table[EXT_ZKNE] = true; + extension_table[EXT_ZKNH] = true; + extension_table[EXT_ZKR] = true; + } else if (ext_str == "zkn") { + extension_table[EXT_ZBKB] = true; + extension_table[EXT_ZBKC] = true; + extension_table[EXT_ZBKX] = true; + extension_table[EXT_ZKND] = true; + extension_table[EXT_ZKNE] = true; + extension_table[EXT_ZKNH] = true; + } else if (ext_str == "zknd") { + extension_table[EXT_ZKND] = true; + } else if (ext_str == "zkne") { + extension_table[EXT_ZKNE] = true; + } else if (ext_str == "zknh") { + extension_table[EXT_ZKNH] = true; + } else if (ext_str == "zks") { + extension_table[EXT_ZBKB] = true; + extension_table[EXT_ZBKC] = true; + extension_table[EXT_ZBKX] = true; + extension_table[EXT_ZKSED] = true; + extension_table[EXT_ZKSH] = true; + } else if (ext_str == "zksed") { + extension_table[EXT_ZKSED] = true; + } else if (ext_str == "zksh") { + extension_table[EXT_ZKSH] = true; + } else if (ext_str == "zkr") { + extension_table[EXT_ZKR] = true; + } else if (ext_str == "zkt") { + } else if (ext_str == "svnapot") { + extension_table[EXT_SVNAPOT] = true; + } else if (ext_str == "svpbmt") { + extension_table[EXT_SVPBMT] = true; + } else if (ext_str == "svinval") { + extension_table[EXT_SVINVAL] = true; + } else if (ext_str == "zicbom") { + extension_table[EXT_ZICBOM] = true; + } else if (ext_str == "zicboz") { + extension_table[EXT_ZICBOZ] = true; + } else if (ext_str == "zicbop") { + } else if (ext_str == "zicntr") { + } else if (ext_str == "zihpm") { + } else if (ext_str[0] == 'x') { + max_isa |= 1L << ('x' - 'a'); + extension_table[toupper('x')] = true; + if (ext_str == "xbitmanip") { + extension_table[EXT_XZBP] = true; + extension_table[EXT_XZBS] = true; + extension_table[EXT_XZBE] = true; + extension_table[EXT_XZBF] = true; + extension_table[EXT_XZBC] = true; + extension_table[EXT_XZBM] = true; + extension_table[EXT_XZBR] = true; + extension_table[EXT_XZBT] = true; + } else if (ext_str == "xzbp") { + extension_table[EXT_XZBP] = true; + } else if (ext_str == "xzbs") { + extension_table[EXT_XZBS] = true; + } else if (ext_str == "xzbe") { + extension_table[EXT_XZBE] = true; + } else if (ext_str == "xzbf") { + extension_table[EXT_XZBF] = true; + } else if (ext_str == "xzbc") { + extension_table[EXT_XZBC] = true; + } else if (ext_str == "xzbm") { + extension_table[EXT_XZBM] = true; + } else if (ext_str == "xzbr") { + extension_table[EXT_XZBR] = true; + } else if (ext_str == "xzbt") { + extension_table[EXT_XZBT] = true; + } else if (ext_str.size() == 1) { + bad_isa_string(str, "single 'X' is not a proper name"); + } else if (ext_str != "xdummy") { + extension_t* x = find_extension(ext_str.substr(1).c_str())(); + if (!extensions.insert(std::make_pair(x->name(), x)).second) { + fprintf(stderr, "extensions must have unique names (got two named \"%s\"!)\n", x->name()); + abort(); + } + } + } else { + bad_isa_string(str, ("unsupported extension: " + ext_str).c_str()); + } + p = end; + } + if (*p) { + bad_isa_string(str, ("can't parse: " + std::string(p)).c_str()); + } + + std::string lowercase = strtolower(priv); + bool user = false, supervisor = false; + + if (lowercase == "m") + ; + else if (lowercase == "mu") + user = true; + else if (lowercase == "msu") + user = supervisor = true; + 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; + } +} diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h new file mode 100644 index 0000000..f32036c --- /dev/null +++ b/riscv/isa_parser.h @@ -0,0 +1,87 @@ +// See LICENSE for license details. +#ifndef _RISCV_ISA_PARSER_H +#define _RISCV_ISA_PARSER_H + +#include "decode.h" + +#include +#include +#include + +class extension_t; + +typedef enum { + // 65('A') ~ 90('Z') is reserved for standard isa in misa + EXT_ZFH, + EXT_ZFHMIN, + EXT_ZBA, + EXT_ZBB, + EXT_ZBC, + EXT_ZBS, + EXT_ZBKB, + EXT_ZBKC, + EXT_ZBKX, + EXT_ZKND, + EXT_ZKNE, + EXT_ZKNH, + EXT_ZKSED, + EXT_ZKSH, + EXT_ZKR, + EXT_ZMMUL, + EXT_ZBPBO, + EXT_ZPN, + EXT_ZPSFOPERAND, + EXT_SVNAPOT, + EXT_SVPBMT, + EXT_SVINVAL, + EXT_ZDINX, + EXT_ZFINX, + EXT_ZHINX, + EXT_ZHINXMIN, + EXT_ZICBOM, + EXT_ZICBOZ, + EXT_ZICNTR, + EXT_ZIHPM, + EXT_XZBP, + EXT_XZBS, + EXT_XZBE, + EXT_XZBF, + EXT_XZBC, + EXT_XZBM, + EXT_XZBR, + EXT_XZBT, +} isa_extension_t; + +typedef enum { + IMPL_MMU_SV32, + IMPL_MMU_SV39, + IMPL_MMU_SV48, + IMPL_MMU_SBARE, + IMPL_MMU, +} impl_extension_t; + +class isa_parser_t { +public: + isa_parser_t(const char* str, const char *priv); + ~isa_parser_t(){}; + unsigned get_max_xlen() const { return max_xlen; } + 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 { + if (ext >= 'A' && ext <= 'Z') + return (max_isa >> (ext - 'A')) & 1; + else + return extension_table[ext]; + } + const std::unordered_map & + get_extensions() const { return extensions; } + +protected: + unsigned max_xlen; + reg_t max_isa; + std::vector extension_table; + std::string isa_string; + std::unordered_map extensions; +}; + +#endif diff --git a/riscv/processor.cc b/riscv/processor.cc index dfb85da..e991afe 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -82,17 +82,6 @@ static void bad_option_string(const char *option, const char *value, abort(); } -static void bad_isa_string(const char* isa, const char* msg) -{ - bad_option_string("--isa", isa, msg); -} - -static void bad_priv_string(const char* priv) -{ - fprintf(stderr, "error: bad --priv option %s\n", priv); - abort(); -} - static void bad_varch_string(const char* varch, const char *msg) { bad_option_string("--varch", varch, msg); @@ -174,224 +163,6 @@ void processor_t::parse_varch_string(const char* s) VU.vstart_alu = vstart_alu; } -isa_parser_t::isa_parser_t(const char* str, const char *priv) - : extension_table(256, false) -{ - 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; - else if (isa_string.compare(0, 4, "rv64") == 0) - max_xlen = 64; - else - bad_isa_string(str, "ISA strings must begin with RV32 or RV64"); - - switch (isa_string[4]) { - case 'g': - // G = IMAFD_Zicsr_Zifencei, but Spike includes the latter two - // unconditionally, so they need not be explicitly added here. - isa_string = isa_string.substr(0, 4) + "imafd" + isa_string.substr(5); - // Fall through - case 'i': - max_isa |= 1L << ('i' - 'a'); - break; - - case 'e': - max_isa |= 1L << ('e' - 'a'); - break; - - default: - bad_isa_string(str, ("'" + isa_string.substr(0, 4) + "' must be followed by I, E, or G").c_str()); - } - - const char* isa_str = isa_string.c_str(); - auto p = isa_str, subset = all_subsets; - for (p += 5; islower(*p) && !strchr("zsx", *p); ++p) { - while (*subset && (*p != *subset)) - ++subset; - - if (!*subset) { - if (strchr(all_subsets, *p)) - bad_isa_string(str, ("Extension '" + std::string(1, *p) + "' appears too late in ISA string").c_str()); - else - bad_isa_string(str, ("Unsupported extension '" + std::string(1, *p) + "'").c_str()); - } - - switch (*p) { - case 'p': extension_table[EXT_ZBPBO] = true; - extension_table[EXT_ZPN] = true; - extension_table[EXT_ZPSFOPERAND] = true; - extension_table[EXT_ZMMUL] = true; break; - case 'q': max_isa |= 1L << ('d' - 'a'); - // Fall through - case 'd': max_isa |= 1L << ('f' - 'a'); - } - max_isa |= 1L << (*p - 'a'); - extension_table[toupper(*p)] = true; - while (isdigit(*(p + 1))) { - ++p; // skip major version, point, and minor version if presented - if (*(p + 1) == 'p') ++p; - } - p += *(p + 1) == '_'; // underscores may be used to improve readability - } - - while (islower(*p) || (*p == '_')) { - p += *p == '_'; // first underscore is optional - auto end = p; - 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)) - 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 == "zicsr") { - // Spike necessarily has Zicsr, because - // Zicsr is implied by the privileged architecture - } else if (ext_str == "zifencei") { - // For compatibility with version 2.0 of the base ISAs, we - // unconditionally include FENCE.I, so Zifencei adds nothing more. - } else if (ext_str == "zihintpause") { - // HINTs encoded in base-ISA instructions are always present. - } else if (ext_str == "zmmul") { - extension_table[EXT_ZMMUL] = true; - } else if (ext_str == "zba") { - extension_table[EXT_ZBA] = true; - } else if (ext_str == "zbb") { - extension_table[EXT_ZBB] = true; - } else if (ext_str == "zbc") { - extension_table[EXT_ZBC] = true; - } else if (ext_str == "zbs") { - extension_table[EXT_ZBS] = true; - } else if (ext_str == "zbkb") { - extension_table[EXT_ZBKB] = true; - } else if (ext_str == "zbkc") { - extension_table[EXT_ZBKC] = true; - } else if (ext_str == "zbkx") { - extension_table[EXT_ZBKX] = true; - } else if (ext_str == "zk") { - extension_table[EXT_ZBKB] = true; - extension_table[EXT_ZBKC] = true; - extension_table[EXT_ZBKX] = true; - extension_table[EXT_ZKND] = true; - extension_table[EXT_ZKNE] = true; - extension_table[EXT_ZKNH] = true; - extension_table[EXT_ZKR] = true; - } else if (ext_str == "zkn") { - extension_table[EXT_ZBKB] = true; - extension_table[EXT_ZBKC] = true; - extension_table[EXT_ZBKX] = true; - extension_table[EXT_ZKND] = true; - extension_table[EXT_ZKNE] = true; - extension_table[EXT_ZKNH] = true; - } else if (ext_str == "zknd") { - extension_table[EXT_ZKND] = true; - } else if (ext_str == "zkne") { - extension_table[EXT_ZKNE] = true; - } else if (ext_str == "zknh") { - extension_table[EXT_ZKNH] = true; - } else if (ext_str == "zks") { - extension_table[EXT_ZBKB] = true; - extension_table[EXT_ZBKC] = true; - extension_table[EXT_ZBKX] = true; - extension_table[EXT_ZKSED] = true; - extension_table[EXT_ZKSH] = true; - } else if (ext_str == "zksed") { - extension_table[EXT_ZKSED] = true; - } else if (ext_str == "zksh") { - extension_table[EXT_ZKSH] = true; - } else if (ext_str == "zkr") { - extension_table[EXT_ZKR] = true; - } else if (ext_str == "zkt") { - } else if (ext_str == "svnapot") { - extension_table[EXT_SVNAPOT] = true; - } else if (ext_str == "svpbmt") { - extension_table[EXT_SVPBMT] = true; - } else if (ext_str == "svinval") { - extension_table[EXT_SVINVAL] = true; - } else if (ext_str == "zicbom") { - extension_table[EXT_ZICBOM] = true; - } else if (ext_str == "zicboz") { - extension_table[EXT_ZICBOZ] = true; - } else if (ext_str == "zicbop") { - } else if (ext_str == "zicntr") { - } else if (ext_str == "zihpm") { - } else if (ext_str[0] == 'x') { - max_isa |= 1L << ('x' - 'a'); - extension_table[toupper('x')] = true; - if (ext_str == "xbitmanip") { - extension_table[EXT_XZBP] = true; - extension_table[EXT_XZBS] = true; - extension_table[EXT_XZBE] = true; - extension_table[EXT_XZBF] = true; - extension_table[EXT_XZBC] = true; - extension_table[EXT_XZBM] = true; - extension_table[EXT_XZBR] = true; - extension_table[EXT_XZBT] = true; - } else if (ext_str == "xzbp") { - extension_table[EXT_XZBP] = true; - } else if (ext_str == "xzbs") { - extension_table[EXT_XZBS] = true; - } else if (ext_str == "xzbe") { - extension_table[EXT_XZBE] = true; - } else if (ext_str == "xzbf") { - extension_table[EXT_XZBF] = true; - } else if (ext_str == "xzbc") { - extension_table[EXT_XZBC] = true; - } else if (ext_str == "xzbm") { - extension_table[EXT_XZBM] = true; - } else if (ext_str == "xzbr") { - extension_table[EXT_XZBR] = true; - } else if (ext_str == "xzbt") { - extension_table[EXT_XZBT] = true; - } else if (ext_str.size() == 1) { - bad_isa_string(str, "single 'X' is not a proper name"); - } else if (ext_str != "xdummy") { - extension_t* x = find_extension(ext_str.substr(1).c_str())(); - if (!extensions.insert(std::make_pair(x->name(), x)).second) { - fprintf(stderr, "extensions must have unique names (got two named \"%s\"!)\n", x->name()); - abort(); - } - } - } else { - bad_isa_string(str, ("unsupported extension: " + ext_str).c_str()); - } - p = end; - } - if (*p) { - bad_isa_string(str, ("can't parse: " + std::string(p)).c_str()); - } - - std::string lowercase = strtolower(priv); - bool user = false, supervisor = false; - - if (lowercase == "m") - ; - else if (lowercase == "mu") - user = true; - else if (lowercase == "msu") - user = supervisor = true; - 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; - } -} - static int xlen_to_uxl(int xlen) { if (xlen == 32) diff --git a/riscv/processor.h b/riscv/processor.h index 7f64857..7d05346 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -14,6 +14,7 @@ #include "debug_rom_defines.h" #include "entropy_source.h" #include "csrs.h" +#include "isa_parser.h" class processor_t; class mmu_t; @@ -250,56 +251,6 @@ typedef enum { OPERATION_LOAD, } trigger_operation_t; -typedef enum { - // 65('A') ~ 90('Z') is reserved for standard isa in misa - EXT_ZFH, - EXT_ZFHMIN, - EXT_ZBA, - EXT_ZBB, - EXT_ZBC, - EXT_ZBS, - EXT_ZBKB, - EXT_ZBKC, - EXT_ZBKX, - EXT_ZKND, - EXT_ZKNE, - EXT_ZKNH, - EXT_ZKSED, - EXT_ZKSH, - EXT_ZKR, - EXT_ZMMUL, - EXT_ZBPBO, - EXT_ZPN, - EXT_ZPSFOPERAND, - EXT_SVNAPOT, - EXT_SVPBMT, - EXT_SVINVAL, - EXT_ZDINX, - EXT_ZFINX, - EXT_ZHINX, - EXT_ZHINXMIN, - EXT_ZICBOM, - EXT_ZICBOZ, - EXT_ZICNTR, - EXT_ZIHPM, - EXT_XZBP, - EXT_XZBS, - EXT_XZBE, - EXT_XZBF, - EXT_XZBC, - EXT_XZBM, - EXT_XZBR, - EXT_XZBT, -} isa_extension_t; - -typedef enum { - IMPL_MMU_SV32, - IMPL_MMU_SV39, - IMPL_MMU_SV48, - IMPL_MMU_SBARE, - IMPL_MMU, -} impl_extension_t; - // Count number of contiguous 1 bits starting from the LSB. static int cto(reg_t val) { @@ -309,30 +260,6 @@ static int cto(reg_t val) return res; } -class isa_parser_t { -public: - isa_parser_t(const char* str, const char *priv); - ~isa_parser_t(){}; - unsigned get_max_xlen() const { return max_xlen; } - 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 { - if (ext >= 'A' && ext <= 'Z') - return (max_isa >> (ext - 'A')) & 1; - else - return extension_table[ext]; - } - const std::unordered_map & - get_extensions() const { return extensions; } - -protected: - unsigned max_xlen; - reg_t max_isa; - std::vector extension_table; - std::string isa_string; - std::unordered_map extensions; -}; - // this class represents one processor in a RISC-V machine. class processor_t : public abstract_device_t { diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index a803b2a..ecbda5d 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -39,6 +39,7 @@ riscv_precompiled_hdrs = \ insn_template.h \ riscv_srcs = \ + isa_parser.cc \ processor.cc \ execute.cc \ dts.cc \ -- cgit v1.1