diff options
author | Jerry Zhao <jerryz123@berkeley.edu> | 2024-06-21 17:23:55 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-21 17:23:55 -0700 |
commit | f03e97c89fb5fa952f1a1264734aecf39619b65d (patch) | |
tree | c65e4bf6c71d8e42e5539d7650581c0168eafc75 | |
parent | 3d4027a2bb559af758a2a9d624a3848ae2485453 (diff) | |
parent | c790f73ae94d358e9493187fdbcc9053ed7af7d8 (diff) | |
download | spike-f03e97c89fb5fa952f1a1264734aecf39619b65d.zip spike-f03e97c89fb5fa952f1a1264734aecf39619b65d.tar.gz spike-f03e97c89fb5fa952f1a1264734aecf39619b65d.tar.bz2 |
Merge pull request #1701 from riscv-software-src/zvl_zve
Correctly determine vector capability from v/zve/zvl ISA strings, remove --varch
-rw-r--r-- | .github/workflows/debug-smoke.yml | 2 | ||||
-rw-r--r-- | config.h.in | 3 | ||||
-rwxr-xr-x | configure | 17 | ||||
-rw-r--r-- | disasm/disasm.cc | 2 | ||||
-rw-r--r-- | disasm/isa_parser.cc | 65 | ||||
-rw-r--r-- | riscv/cfg.cc | 1 | ||||
-rw-r--r-- | riscv/cfg.h | 1 | ||||
-rw-r--r-- | riscv/csrs.cc | 10 | ||||
-rw-r--r-- | riscv/decode_macros.h | 2 | ||||
-rw-r--r-- | riscv/isa_parser.h | 9 | ||||
-rw-r--r-- | riscv/processor.cc | 68 | ||||
-rw-r--r-- | riscv/processor.h | 4 | ||||
-rw-r--r-- | riscv/riscv.ac | 6 | ||||
-rw-r--r-- | riscv/v_ext_macros.h | 20 | ||||
-rw-r--r-- | spike_main/spike.cc | 2 |
15 files changed, 93 insertions, 119 deletions
diff --git a/.github/workflows/debug-smoke.yml b/.github/workflows/debug-smoke.yml index 090e4d9..6ecc5fb 100644 --- a/.github/workflows/debug-smoke.yml +++ b/.github/workflows/debug-smoke.yml @@ -47,7 +47,7 @@ jobs: run: | git clone --recurse-submodules https://github.com/riscv-software-src/riscv-tests.git cd riscv-tests - git checkout bd0a19c136927eaa3b7296a591a896c141affb6b + git checkout 00ab5f0dd4cf56b5a0551bc5adedf60c765d0c66 - name: Run Tests run: | diff --git a/config.h.in b/config.h.in index 95514fd..aef3596 100644 --- a/config.h.in +++ b/config.h.in @@ -12,9 +12,6 @@ /* Default value for --priv switch */ #undef DEFAULT_PRIV -/* Default value for --varch switch */ -#undef DEFAULT_VARCH - /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ #undef DISASM_ENABLED @@ -739,7 +739,6 @@ with_boost_asio with_boost_regex with_isa with_priv -with_varch with_target enable_dual_endian ' @@ -1407,8 +1406,6 @@ Optional Packages: --with-isa=RV64IMAFDC_zicntr_zihpm Sets the default RISC-V ISA --with-priv=MSU Sets the default RISC-V privilege modes supported - --with-varch=vlen:128,elen:64 - Sets the default vector config --with-target=riscv64-unknown-elf Sets the default target config @@ -6593,20 +6590,6 @@ fi -# Check whether --with-varch was given. -if test ${with_varch+y} -then : - withval=$with_varch; -printf "%s\n" "#define DEFAULT_VARCH \"$withval\"" >>confdefs.h - -else $as_nop - -printf "%s\n" "#define DEFAULT_VARCH \"vlen:128,elen:64\"" >>confdefs.h - -fi - - - # Check whether --with-target was given. if test ${with_target+y} then : diff --git a/disasm/disasm.cc b/disasm/disasm.cc index 5c0e9e0..343fff7 100644 --- a/disasm/disasm.cc +++ b/disasm/disasm.cc @@ -1455,7 +1455,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) DISASM_INSN("cm.jalt", cm_jalt, 0, {&rvcm_jt_index}); } - if (isa->extension_enabled('V')) { + if (isa->has_any_vector()) { DISASM_INSN("vsetivli", vsetivli, 0, {&xrd, &zimm5, &v_vtype}); DISASM_INSN("vsetvli", vsetvli, 0, {&xrd, &xrs1, &v_vtype}); DEFINE_RTYPE(vsetvl); diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index 7c607d7..cba5516 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -38,6 +38,11 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) else bad_isa_string(str, "ISA strings must begin with RV32 or RV64"); + vlen = 0; + elen = 0; + zvf = false; + zvd = false; + switch (isa_string[4]) { case 'g': // G = IMAFD_Zicsr_Zifencei, but Spike includes the latter two @@ -70,7 +75,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) } switch (*p) { - case 'v': // even rv32iv implies double float + case 'v': vlen = 128; elen = 64; zvf = true; zvd = true; + // even rv32iv implies double float case 'q': extension_table['D'] = true; // Fall through case 'd': extension_table['F'] = true; @@ -95,9 +101,6 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) if (ext_str == "zfh") extension_table[EXT_ZFH] = true; } else if (ext_str == "zvfh" || ext_str == "zvfhmin") { - if (!extension_table['V']) - bad_isa_string(str, ("'" + ext_str + "' extension requires 'V'").c_str()); - extension_table[EXT_ZVFHMIN] = true; if (ext_str == "zvfh") { @@ -314,6 +317,35 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) extension_table[EXT_ZICFILP] = true; } else if (ext_str == "zicfiss") { extension_table[EXT_ZICFISS] = true; + } else if (ext_str.substr(0, 3) == "zvl") { + reg_t new_vlen; + try { + new_vlen = std::stol(ext_str.substr(3, ext_str.size() - 4)); + } catch (std::logic_error& e) { + new_vlen = 0; + } + if ((new_vlen & (new_vlen - 1)) != 0 || new_vlen < 32) + bad_isa_string(str, ("Invalid Zvl string: " + ext_str).c_str()); + vlen = std::max(vlen, new_vlen); + } else if (ext_str.substr(0, 3) == "zve") { + reg_t new_elen; + try { + new_elen = std::stol(ext_str.substr(3, ext_str.size() - 4)); + } catch (std::logic_error& e) { + new_elen = 0; + } + if (ext_str.substr(5) == "d") { + zvd |= true; zvf |= true; + } else if (ext_str.substr(5) == "f") { + zvf |= true; + } else if (ext_str.substr(5) == "x") { + /* do nothing */ + } else { + new_elen = 0; + } + if (new_elen != 32 && new_elen != 64) + bad_isa_string(str, ("Invalid Zve string: " + ext_str).c_str()); + elen = std::max(elen, new_elen); } else if (ext_str[0] == 'x') { extension_table['X'] = true; if (ext_str.size() == 1) { @@ -424,6 +456,31 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) "extensions are incompatible with WORDS_BIGENDIAN setups."); } #endif + + if (vlen > 4096) { + bad_isa_string(str, "Spike does not currently support VLEN > 4096b"); + } + + if ((vlen != 0) ^ (elen != 0)) { + bad_isa_string(str, "Invalid Zvl/Zve configuration"); + } + + if (extension_table[EXT_ZVFHMIN] && (vlen == 0 || elen == 0 || !zvf)) { + bad_isa_string(str, "'Zvfhmin' extension requires Zve32f"); + } + + if (extension_table[EXT_ZVFH] && (vlen == 0 || elen == 0 || !zvf || !extension_table[EXT_ZVFHMIN])) { + bad_isa_string(str, "'Zvfh' extension requires Zve32f and 'Zvfhmin'"); + } + + if (zvd && !extension_table['D'] && elen < 64) { + bad_isa_string(str, "'ZveXXd' extension requires D"); + } + + if (zvf && !extension_table['F']) { + bad_isa_string(str, "'ZveXXf' extension requires F"); + } + std::string lowercase = strtolower(priv); bool user = false, supervisor = false; diff --git a/riscv/cfg.cc b/riscv/cfg.cc index d105eb5..67dfdb4 100644 --- a/riscv/cfg.cc +++ b/riscv/cfg.cc @@ -35,7 +35,6 @@ cfg_t::cfg_t() bootargs = nullptr; isa = DEFAULT_ISA; priv = DEFAULT_PRIV; - varch = DEFAULT_VARCH; misaligned = false; endianness = endianness_little; pmpregions = 16; diff --git a/riscv/cfg.h b/riscv/cfg.h index 63465e6..c972f03 100644 --- a/riscv/cfg.h +++ b/riscv/cfg.h @@ -67,7 +67,6 @@ public: const char * bootargs; const char * isa; const char * priv; - const char * varch; bool misaligned; endianness_t endianness; reg_t pmpregions; diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 8d7737f..02a2c4f 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -411,9 +411,9 @@ base_status_csr_t::base_status_csr_t(processor_t* const proc, const reg_t addr): reg_t base_status_csr_t::compute_sstatus_write_mask() const noexcept { // If a configuration has FS bits, they will always be accessible no // matter the state of misa. - const bool has_fs = (proc->extension_enabled('S') || proc->extension_enabled('F') - || proc->extension_enabled('V')) && !proc->extension_enabled(EXT_ZFINX); - const bool has_vs = proc->extension_enabled('V'); + const bool has_fs = (proc->extension_enabled('S') || proc->extension_enabled('F')) && !proc->extension_enabled(EXT_ZFINX); + // Implementations w/o V may still have mstatus.vs, + const bool has_vs = proc->any_vector_extensions(); return 0 | (proc->extension_enabled('S') ? (SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP) : 0) | (has_page ? (SSTATUS_SUM | SSTATUS_MXR) : 0) @@ -1429,8 +1429,6 @@ vector_csr_t::vector_csr_t(processor_t* const proc, const reg_t addr, const reg_ void vector_csr_t::verify_permissions(insn_t insn, bool write) const { require_vector_vs; - if (!proc->extension_enabled('V')) - throw trap_illegal_instruction(insn.bits()); basic_csr_t::verify_permissions(insn, write); } @@ -1452,8 +1450,6 @@ vxsat_csr_t::vxsat_csr_t(processor_t* const proc, const reg_t addr): void vxsat_csr_t::verify_permissions(insn_t insn, bool write) const { require_vector_vs; - if (!proc->extension_enabled('V')) - throw trap_illegal_instruction(insn.bits()); masked_csr_t::verify_permissions(insn, write); } diff --git a/riscv/decode_macros.h b/riscv/decode_macros.h index 7365a86..675634a 100644 --- a/riscv/decode_macros.h +++ b/riscv/decode_macros.h @@ -171,7 +171,6 @@ static inline bool is_aligned(const unsigned val, const unsigned pos) #define require_vector(alu) \ do { \ require_vector_vs; \ - require_extension('V'); \ require(!P.VU.vill); \ if (alu && !P.VU.vstart_alu) \ require(P.VU.vstart->read() == 0); \ @@ -181,7 +180,6 @@ static inline bool is_aligned(const unsigned val, const unsigned pos) #define require_vector_novtype(is_log) \ do { \ require_vector_vs; \ - require_extension('V'); \ if (is_log) \ WRITE_VSTATUS; \ dirty_vs_state; \ diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index ae9ed94..afb49f2 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -102,12 +102,17 @@ public: 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; } + reg_t get_vlen() const { return vlen; } + reg_t get_elen() const { return elen; } + bool get_zvf() const { return zvf; } + bool get_zvd() const { return zvd; } bool extension_enabled(unsigned char ext) const { return extension_enabled(isa_extension_t(ext)); } bool extension_enabled(isa_extension_t ext) const { return extension_table[ext]; } + bool has_any_vector() const { return vlen > 0; } std::bitset<NUM_ISA_EXTENSIONS> get_extension_table() const { return extension_table; } @@ -116,6 +121,10 @@ public: protected: unsigned max_xlen; reg_t max_isa; + reg_t vlen; + reg_t elen; + bool zvf; + bool zvd; std::bitset<NUM_ISA_EXTENSIONS> extension_table; std::string isa_string; std::set<std::string> extensions; diff --git a/riscv/processor.cc b/riscv/processor.cc index a813068..9498b8f 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -44,7 +44,7 @@ processor_t::processor_t(const isa_parser_t *isa, const cfg_t *cfg, TM.proc = this; #ifndef HAVE_INT128 - if (isa->extension_enabled('V')) { + if (isa->has_any_vector()) { fprintf(stderr, "V extension is not supported on platforms without __int128 type\n"); abort(); } @@ -55,7 +55,10 @@ processor_t::processor_t(const isa_parser_t *isa, const cfg_t *cfg, } #endif - parse_varch_string(cfg->varch); + VU.VLEN = isa->get_vlen(); + VU.ELEN = isa->get_elen(); + VU.vlenb = isa->get_vlen() / 8; + VU.vstart_alu = 0; register_base_instructions(); mmu = new mmu_t(sim, cfg->endianness, this); @@ -102,11 +105,6 @@ static void bad_option_string(const char *option, const char *value, abort(); } -static void bad_varch_string(const char* varch, const char *msg) -{ - bad_option_string("--varch", varch, msg); -} - static std::string get_string_token(std::string str, const char delimiter, size_t& pos) { size_t _pos = pos; @@ -114,17 +112,6 @@ static std::string get_string_token(std::string str, const char delimiter, size_ return str.substr(_pos, pos - _pos); } -static int get_int_token(std::string str, const char delimiter, size_t& pos) -{ - size_t _pos = pos; - while (pos < str.length() && str[pos] != delimiter) { - if (!isdigit(str[pos])) - bad_varch_string(str.c_str(), "Unsupported value"); // An integer is expected - ++pos; - } - return (pos == _pos) ? 0 : stoi(str.substr(_pos, pos - _pos)); -} - static bool check_pow2(int val) { return ((val & (val - 1))) == 0; @@ -138,51 +125,6 @@ static std::string strtolower(const char* str) return res; } -void processor_t::parse_varch_string(const char* s) -{ - std::string str = strtolower(s); - size_t pos = 0; - size_t len = str.length(); - int vlen = 0; - int elen = 0; - int vstart_alu = 0; - - while (pos < len) { - std::string attr = get_string_token(str, ':', pos); - - ++pos; - - if (attr == "vlen") - vlen = get_int_token(str, ',', pos); - else if (attr == "elen") - elen = get_int_token(str, ',', pos); - else if (attr == "vstartalu") - vstart_alu = get_int_token(str, ',', pos); - else - bad_varch_string(s, "Unsupported token"); - - ++pos; - } - - // The integer should be the power of 2 - if (!check_pow2(vlen) || !check_pow2(elen)) { - bad_varch_string(s, "The integer value should be the power of 2"); - } - - /* Vector spec requirements. */ - if (vlen < elen) - bad_varch_string(s, "vlen must be >= elen"); - - /* spike requirements. */ - if (vlen > 4096) - bad_varch_string(s, "vlen must be <= 4096"); - - VU.VLEN = vlen; - VU.ELEN = elen; - VU.vlenb = vlen / 8; - VU.vstart_alu = vstart_alu; -} - static int xlen_to_uxl(int xlen) { if (xlen == 32) diff --git a/riscv/processor.h b/riscv/processor.h index 9b776e2..14b828c 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -273,6 +273,9 @@ public: bool any_custom_extensions() const { return !custom_extensions.empty(); } + bool any_vector_extensions() const { + return VU.VLEN > 0; + } bool extension_enabled(unsigned char ext) const { return extension_enabled(isa_extension_t(ext)); } @@ -407,7 +410,6 @@ private: friend class plic_t; friend class extension_t; - void parse_varch_string(const char*); void parse_priv_string(const char*); void build_opcode_map(); void register_base_instructions(); diff --git a/riscv/riscv.ac b/riscv/riscv.ac index 5785f27..378fd10 100644 --- a/riscv/riscv.ac +++ b/riscv/riscv.ac @@ -20,12 +20,6 @@ AC_ARG_WITH(priv, AC_DEFINE_UNQUOTED([DEFAULT_PRIV], "$withval", [Default value for --priv switch]), AC_DEFINE_UNQUOTED([DEFAULT_PRIV], "MSU", [Default value for --priv switch])) -AC_ARG_WITH(varch, - [AS_HELP_STRING([--with-varch=vlen:128,elen:64], - [Sets the default vector config])], - AC_DEFINE_UNQUOTED([DEFAULT_VARCH], "$withval", [Default value for --varch switch]), - AC_DEFINE([DEFAULT_VARCH], ["vlen:128,elen:64"], [Default value for --varch switch])) - AC_ARG_WITH(target, [AS_HELP_STRING([--with-target=riscv64-unknown-elf], [Sets the default target config])], diff --git a/riscv/v_ext_macros.h b/riscv/v_ext_macros.h index a95af3e..3e8a653 100644 --- a/riscv/v_ext_macros.h +++ b/riscv/v_ext_macros.h @@ -1449,8 +1449,8 @@ reg_t index[P.VU.vlmax]; \ #define VI_VFP_COMMON \ require_fp; \ require((P.VU.vsew == e16 && p->extension_enabled(EXT_ZVFH)) || \ - (P.VU.vsew == e32 && p->extension_enabled('F')) || \ - (P.VU.vsew == e64 && p->extension_enabled('D'))); \ + (P.VU.vsew == e32 && p->get_isa().get_zvf()) || \ + (P.VU.vsew == e64 && p->get_isa().get_zvd())); \ require_vector(true); \ require(STATE.frm->read() < 0x5); \ reg_t UNUSED vl = P.VU.vl->read(); \ @@ -1662,8 +1662,8 @@ reg_t index[P.VU.vlmax]; \ #define VI_VFP_VV_LOOP_WIDE_REDUCTION(BODY16, BODY32) \ VI_CHECK_REDUCTION(true) \ VI_VFP_COMMON \ - require((P.VU.vsew == e16 && p->extension_enabled('F')) || \ - (P.VU.vsew == e32 && p->extension_enabled('D'))); \ + require((P.VU.vsew == e16 && p->get_isa().get_zvf()) || \ + (P.VU.vsew == e32 && p->get_isa().get_zvd())); \ bool is_active = false; \ switch (P.VU.vsew) { \ case e16: { \ @@ -1948,17 +1948,17 @@ reg_t index[P.VU.vlmax]; \ switch (P.VU.vsew) { \ case e16: \ { VI_VFP_CVT_LOOP(CVT_INT_TO_FP_PARAMS(16, 16, sign), \ - { p->extension_enabled(EXT_ZVFH); }, \ + { require(p->extension_enabled(EXT_ZVFH)); }, \ BODY16); } \ break; \ case e32: \ { VI_VFP_CVT_LOOP(CVT_INT_TO_FP_PARAMS(32, 32, sign), \ - { p->extension_enabled('F'); }, \ + { require(p->get_isa().get_zvf()); }, \ BODY32); } \ break; \ case e64: \ { VI_VFP_CVT_LOOP(CVT_INT_TO_FP_PARAMS(64, 64, sign), \ - { p->extension_enabled('D'); }, \ + { require(p->get_isa().get_zvd()); }, \ BODY64); } \ break; \ default: \ @@ -1972,17 +1972,17 @@ reg_t index[P.VU.vlmax]; \ switch (P.VU.vsew) { \ case e16: \ { VI_VFP_CVT_LOOP(CVT_FP_TO_INT_PARAMS(16, 16, sign), \ - { p->extension_enabled(EXT_ZVFH); }, \ + { require(p->extension_enabled(EXT_ZVFH)); }, \ BODY16); } \ break; \ case e32: \ { VI_VFP_CVT_LOOP(CVT_FP_TO_INT_PARAMS(32, 32, sign), \ - { p->extension_enabled('F'); }, \ + { require(p->get_isa().get_zvf()); }, \ BODY32); } \ break; \ case e64: \ { VI_VFP_CVT_LOOP(CVT_FP_TO_INT_PARAMS(64, 64, sign), \ - { p->extension_enabled('D'); }, \ + { require(p->get_isa().get_zvd()); }, \ BODY64); } \ break; \ default: \ diff --git a/spike_main/spike.cc b/spike_main/spike.cc index 6596bc1..1a298f2 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -45,7 +45,6 @@ static void help(int exit_code = 1) fprintf(stderr, " --pmpregions=<n> Number of PMP regions [default 16]\n"); fprintf(stderr, " --pmpgranularity=<n> PMP Granularity in bytes [default 4]\n"); fprintf(stderr, " --priv=<m|mu|msu> RISC-V privilege modes supported [default %s]\n", DEFAULT_PRIV); - fprintf(stderr, " --varch=<name> RISC-V Vector uArch string [default %s]\n", DEFAULT_VARCH); fprintf(stderr, " --pc=<address> Override ELF entry point\n"); fprintf(stderr, " --hartids=<a,b,...> Explicitly specify hartids, default is 0,1,...\n"); fprintf(stderr, " --ic=<S>:<W>:<B> Instantiate a cache model with S sets,\n"); @@ -404,7 +403,6 @@ int main(int argc, char** argv) parser.option(0, "pmpregions", 1, [&](const char* s){cfg.pmpregions = atoul_safe(s);}); parser.option(0, "pmpgranularity", 1, [&](const char* s){cfg.pmpgranularity = atoul_safe(s);}); parser.option(0, "priv", 1, [&](const char* s){cfg.priv = s;}); - parser.option(0, "varch", 1, [&](const char* s){cfg.varch = s;}); parser.option(0, "device", 1, device_parser); parser.option(0, "extension", 1, [&](const char* s){extensions.push_back(find_extension(s));}); parser.option(0, "dump-dts", 0, [&](const char UNUSED *s){dump_dts = true;}); |