From f8613ef25d7332aeb429e2e25c9842ac9dcdf623 Mon Sep 17 00:00:00 2001 From: Isaac David Date: Sun, 8 Dec 2024 01:56:22 +0000 Subject: [PATCH] [vuop_gen] --- arches/isa_json/gen_uarch_rv64v_json.py | 15 +- arches/isa_json/olympia_uarch_rv64v.json | 36 ++-- core/Inst.hpp | 64 +++++-- core/InstArchInfo.cpp | 1 + core/InstArchInfo.hpp | 1 + core/InstGenerator.cpp | 25 ++- core/VectorUopGenerator.cpp | 155 ++++++++++------ core/VectorUopGenerator.hpp | 2 +- test/core/vector/CMakeLists.txt | 43 +++++ test/core/vector/Vuop_test.cpp | 216 +++++++++++++++++++++++ test/core/vector/elementwise.json | 16 ++ test/core/vector/int_ext.json | 25 +++ test/core/vector/mac.json | 16 ++ test/core/vector/mac_widening.json | 16 ++ test/core/vector/narrowing.json | 16 ++ test/core/vector/single_dest.json | 16 ++ test/core/vector/widening.json | 16 ++ test/core/vector/widening_mixed.json | 16 ++ 18 files changed, 594 insertions(+), 101 deletions(-) create mode 100644 test/core/vector/Vuop_test.cpp create mode 100644 test/core/vector/elementwise.json create mode 100644 test/core/vector/int_ext.json create mode 100644 test/core/vector/mac.json create mode 100644 test/core/vector/mac_widening.json create mode 100644 test/core/vector/narrowing.json create mode 100644 test/core/vector/single_dest.json create mode 100644 test/core/vector/widening.json create mode 100644 test/core/vector/widening_mixed.json diff --git a/arches/isa_json/gen_uarch_rv64v_json.py b/arches/isa_json/gen_uarch_rv64v_json.py index 9307c65f..8f861fde 100755 --- a/arches/isa_json/gen_uarch_rv64v_json.py +++ b/arches/isa_json/gen_uarch_rv64v_json.py @@ -51,14 +51,12 @@ "vwsub.wv" : {"pipe" : "vint", "uop_gen" : "WIDENING_MIXED", "latency" : 1}, "vwsub.wx" : {"pipe" : "vint", "uop_gen" : "WIDENING_MIXED", "latency" : 1}, -# TODO: Vector Integer Arithmetic Instructions: Vector Integer Extension -# FIXME: Requires Mavis fix to support correctly -# "vzext.vf2" : {"pipe" : "vint", "uop_gen" : "ARITH_EXT", "latency" : 1}, -# "vsext.vf2" : {"pipe" : "vint", "uop_gen" : "ARITH_EXT", "latency" : 1}, -# "vzext.vf4" : {"pipe" : "vint", "uop_gen" : "ARITH_EXT", "latency" : 1}, -# "vsext.vf4" : {"pipe" : "vint", "uop_gen" : "ARITH_EXT", "latency" : 1}, -# "vzext.vf8" : {"pipe" : "vint", "uop_gen" : "ARITH_EXT", "latency" : 1}, -# "vsext.vf8" : {"pipe" : "vint", "uop_gen" : "ARITH_EXT", "latency" : 1}, + "vzext.vf2" : {"pipe" : "vint", "uop_gen" : "INT_EXT", "latency" : 1}, + "vsext.vf2" : {"pipe" : "vint", "uop_gen" : "INT_EXT", "latency" : 1}, + "vzext.vf4" : {"pipe" : "vint", "uop_gen" : "INT_EXT", "latency" : 1}, + "vsext.vf4" : {"pipe" : "vint", "uop_gen" : "INT_EXT", "latency" : 1}, + "vzext.vf8" : {"pipe" : "vint", "uop_gen" : "INT_EXT", "latency" : 1}, + "vsext.vf8" : {"pipe" : "vint", "uop_gen" : "INT_EXT", "latency" : 1}, # Vector Integer Arithmetic Instructions: Vector Integer Add-with-Carry/Subtract-with-Borrow Instructions # FIXME: Requires Mavis fix to include vector mask @@ -188,7 +186,6 @@ "vwmaccus.vx" : {"pipe" : "vmul", "uop_gen" : "MAC_WIDE", "latency" : 3}, # Vector Integer Arithmetic Instructions: Vector Integer Merge Instructions -# FIXME: Requires Mavis fix to include vector mask "vmerge.vvm" : {"pipe" : "vint", "uop_gen" : "ELEMENTWISE", "latency" : 1}, "vmerge.vxm" : {"pipe" : "vint", "uop_gen" : "ELEMENTWISE", "latency" : 1}, "vmerge.vim" : {"pipe" : "vint", "uop_gen" : "ELEMENTWISE", "latency" : 1}, diff --git a/arches/isa_json/olympia_uarch_rv64v.json b/arches/isa_json/olympia_uarch_rv64v.json index b1584811..56080fad 100644 --- a/arches/isa_json/olympia_uarch_rv64v.json +++ b/arches/isa_json/olympia_uarch_rv64v.json @@ -1735,21 +1735,21 @@ }, { "mnemonic": "vsext.vf2", - "pipe": "?", - "uop_gen": "NONE", - "latency": 0 + "pipe": "vint", + "uop_gen": "INT_EXT", + "latency": 1 }, { "mnemonic": "vsext.vf4", - "pipe": "?", - "uop_gen": "NONE", - "latency": 0 + "pipe": "vint", + "uop_gen": "INT_EXT", + "latency": 1 }, { "mnemonic": "vsext.vf8", - "pipe": "?", - "uop_gen": "NONE", - "latency": 0 + "pipe": "vint", + "uop_gen": "INT_EXT", + "latency": 1 }, { "mnemonic": "vslide1down.vx", @@ -2209,20 +2209,20 @@ }, { "mnemonic": "vzext.vf2", - "pipe": "?", - "uop_gen": "NONE", - "latency": 0 + "pipe": "vint", + "uop_gen": "INT_EXT", + "latency": 1 }, { "mnemonic": "vzext.vf4", - "pipe": "?", - "uop_gen": "NONE", - "latency": 0 + "pipe": "vint", + "uop_gen": "INT_EXT", + "latency": 1 }, { "mnemonic": "vzext.vf8", - "pipe": "?", - "uop_gen": "NONE", - "latency": 0 + "pipe": "vint", + "uop_gen": "INT_EXT", + "latency": 1 } ] \ No newline at end of file diff --git a/core/Inst.hpp b/core/Inst.hpp index 78f8afb1..c5324af6 100644 --- a/core/Inst.hpp +++ b/core/Inst.hpp @@ -18,11 +18,13 @@ #include "VectorConfig.hpp" #include "MiscUtils.hpp" +#include #include #include #include #include #include +#include namespace olympia { @@ -75,6 +77,22 @@ namespace olympia Reg data_reg_; }; + class Modifier + { + public: + Modifier(std::string name, uint32_t value) : name_{name}, data_{value} {} + + std::string getName() const { return name_; } + + uint32_t getValue() const { return data_; } + + void setValue(uint32_t newValue) { data_ = newValue; } + + private: + std::string name_; + uint32_t data_; + }; + // Used by Mavis using PtrType = sparta::SpartaSharedPointer; @@ -221,29 +239,34 @@ namespace olympia } const VectorConfigPtr getVectorConfig() const { return vector_config_; } + VectorConfigPtr getVectorConfig() { return vector_config_; } void setTail(bool has_tail) { has_tail_ = has_tail; } + bool hasTail() const { return has_tail_; } void setUOpParent(sparta::SpartaWeakPointer & parent_uop) { parent_uop_ = parent_uop; } + sparta::SpartaWeakPointer getUOpParent() { return parent_uop_; } // Branch instruction was taken (always set for JAL/JALR) void setTakenBranch(bool taken) { is_taken_branch_ = taken; } // Is this branch instruction mispredicted? - bool isMispredicted() const { return is_mispredicted_; } - void setMispredicted() { is_mispredicted_ = true; } + bool isMispredicted() const { return is_mispredicted_; } + + void setMispredicted() { is_mispredicted_ = true; } // TBD -- add branch prediction void setSpeculative(bool spec) { is_speculative_ = spec; } // Last instruction within the cache block fetched from the ICache void setLastInFetchBlock(bool last) { last_in_fetch_block_ = last; } + bool isLastInFetchBlock() const { return last_in_fetch_block_; } // Opcode information @@ -271,25 +294,20 @@ namespace olympia bool hasZeroRegSource() const { return std::any_of(getSourceOpInfoList().begin(), getSourceOpInfoList().end(), - [](const mavis::OperandInfo::Element & elem) - { - return elem.field_value == 0; - }); + [](const mavis::OperandInfo::Element & elem) + { return elem.field_value == 0; }); } bool hasZeroRegDest() const { return std::any_of(getDestOpInfoList().begin(), getDestOpInfoList().end(), - [](const mavis::OperandInfo::Element & elem) - { - return elem.field_value == 0; - }); + [](const mavis::OperandInfo::Element & elem) + { return elem.field_value == 0; }); } uint64_t getImmediate() const { - sparta_assert(has_immediate_, - "Instruction does not have an immediate!"); + sparta_assert(has_immediate_, "Instruction does not have an immediate!"); return opcode_info_->getImmediate(); } @@ -298,7 +316,8 @@ namespace olympia try { // If vm bit is 0, masking is enabled - const uint64_t vm_bit = opcode_info_->getSpecialField(mavis::OpcodeInfo::SpecialField::VM); + const uint64_t vm_bit = + opcode_info_->getSpecialField(mavis::OpcodeInfo::SpecialField::VM); return vm_bit == 0; } catch (const mavis::UnsupportedExtractorSpecialFieldID & mavis_exception) @@ -344,7 +363,8 @@ namespace olympia bool isVector() const { return is_vector_; } - void setCoF(const bool &cof) { is_cof_ = cof; } + void setCoF(const bool & cof) { is_cof_ = cof; } + bool isCoF() const { return is_cof_; } // Rename information @@ -419,6 +439,20 @@ namespace olympia return ss.str(); } + void addModifier(std::string name, uint32_t value) { modifiers_.emplace_back(name, value); } + + std::optional getModifier(std::string name) + { + for (auto & m : modifiers_) + { + if (m.getName() == name) + { + return m.getValue(); + } + } + return {}; + } + private: mavis::OpcodeInfo::PtrType opcode_info_; InstArchInfo::PtrType inst_arch_info_; @@ -473,6 +507,8 @@ namespace olympia RegisterBitMaskArray store_data_mask_; RenameData rename_data; static const std::unordered_map status2String; + + std::vector modifiers_; }; using InstPtr = Inst::PtrType; diff --git a/core/InstArchInfo.cpp b/core/InstArchInfo.cpp index 5edd5043..254cbae0 100644 --- a/core/InstArchInfo.cpp +++ b/core/InstArchInfo.cpp @@ -63,6 +63,7 @@ namespace olympia {"NARROWING", InstArchInfo::UopGenType::NARROWING}, {"MAC", InstArchInfo::UopGenType::MAC}, {"MAC_WIDE", InstArchInfo::UopGenType::MAC_WIDE}, + {"INT_EXT", InstArchInfo::UopGenType::INT_EXT}, {"NONE", InstArchInfo::UopGenType::NONE} }; diff --git a/core/InstArchInfo.hpp b/core/InstArchInfo.hpp index 175f5a59..600fded5 100644 --- a/core/InstArchInfo.hpp +++ b/core/InstArchInfo.hpp @@ -78,6 +78,7 @@ namespace olympia NARROWING, MAC, MAC_WIDE, + INT_EXT, NONE, UNKNOWN }; diff --git a/core/InstGenerator.cpp b/core/InstGenerator.cpp index 385b66f8..acb04e37 100644 --- a/core/InstGenerator.cpp +++ b/core/InstGenerator.cpp @@ -134,10 +134,28 @@ namespace olympia mavis::ExtractorDirectOpInfoList ex_info(mnemonic, srcs, dests); inst = mavis_facade_->makeInstDirectly(ex_info, clk); } + if (inst->getUopGenType() == InstArchInfo::UopGenType::INT_EXT) + { + auto modifier = mnemonic.substr(mnemonic.find(".") + 1); + + if (modifier == "vf2") + { + inst->addModifier("viext", 2); + } + else if (modifier == "vf4") + { + inst->addModifier("viext", 4); + } + else if (modifier == "vf8") + { + inst->addModifier("viext", 8); + } + } if (jinst.find("vaddr") != jinst.end()) { - uint64_t vaddr = std::strtoull(jinst["vaddr"].get().c_str(), nullptr, 0); + uint64_t vaddr = + std::strtoull(jinst["vaddr"].get().c_str(), nullptr, 0); inst->setTargetVAddr(vaddr); } @@ -145,7 +163,8 @@ namespace olympia if (jinst.find("vtype") != jinst.end()) { // immediate, so decode from hex - uint64_t vtype = std::strtoull(jinst["vtype"].get().c_str(), nullptr, 0); + uint64_t vtype = + std::strtoull(jinst["vtype"].get().c_str(), nullptr, 0); std::string binaryString = std::bitset<32>(vtype).to_string(); uint32_t sew = std::pow(2, std::stoi(binaryString.substr(26, 3), nullptr, 2)) * 8; uint32_t lmul = std::pow(2, std::stoi(binaryString.substr(29, 3), nullptr, 2)); @@ -155,7 +174,7 @@ namespace olympia if (jinst.find("vta") != jinst.end()) { - const bool vta = jinst["vta"].get() > 0 ? true: false; + const bool vta = jinst["vta"].get() > 0 ? true : false; vector_config->setVTA(vta); } diff --git a/core/VectorUopGenerator.cpp b/core/VectorUopGenerator.cpp index adeb687a..2dd061dd 100644 --- a/core/VectorUopGenerator.cpp +++ b/core/VectorUopGenerator.cpp @@ -1,6 +1,9 @@ #include "VectorUopGenerator.hpp" +#include "Inst.hpp" +#include "InstArchInfo.hpp" #include "mavis/Mavis.h" #include "sparta/utils/LogUtils.hpp" +#include namespace olympia { @@ -12,19 +15,16 @@ namespace olympia vuops_generated_(&unit_stat_set_, "vector_uops_generated", "Number of vector uops generated", sparta::Counter::COUNT_NORMAL) { - // Vector uop generator, increment all src and dest register numbers + // Vector elementwise uop generator, increment all src and dest register numbers // For a "vadd.vv v12, v4,v8" with an LMUL of 4: // Uop 1: vadd.vv v12, v4, v8 // Uop 2: vadd.vv v13, v5, v9 // Uop 3: vadd.vv v14, v6, v10 // Uop 4: vadd.vv v15, v7, v11 { - constexpr bool SINGLE_DEST = false; - constexpr bool WIDE_DEST = false; - constexpr bool ADD_DEST_AS_SRC = false; uop_gen_function_map_.emplace( InstArchInfo::UopGenType::ELEMENTWISE, - &VectorUopGenerator::generateUops); + &VectorUopGenerator::generateUops); } // Vector single dest uop generator, only increment all src register numbers @@ -34,16 +34,14 @@ namespace olympia // Uop 3: vmseq.vv v12, v6, v10 // Uop 4: vmseq.vv v12, v7, v11 { - constexpr bool SINGLE_DEST = true; - constexpr bool WIDE_DEST = false; - constexpr bool ADD_DEST_AS_SRC = false; uop_gen_function_map_.emplace( InstArchInfo::UopGenType::SINGLE_DEST, - &VectorUopGenerator::generateUops); + &VectorUopGenerator::generateUops); } - // Vector wide dest uop generator, only increment src register numbers for even - // uops For a "vwmul.vv v12, v4, v8" with an LMUL of 4: + // Vector wide uop generator, only increment src register numbers for even + // uops + // For a "vwmul.vv v12, v4, v8" with an LMUL of 4: // Uop 1: vwmul.vv v12, v4, v8 // Uop 2: vwmul.vv v13, v4, v8 // Uop 3: vwmul.vv v14, v6, v10 @@ -53,12 +51,25 @@ namespace olympia // Uop 7: vwmul.vv v18, v10, v14 // Uop 8: vwmul.vv v19, v10, v14 { - constexpr bool SINGLE_DEST = false; - constexpr bool WIDENING = true; - constexpr bool ADD_DEST_AS_SRC = false; uop_gen_function_map_.emplace( InstArchInfo::UopGenType::WIDENING, - &VectorUopGenerator::generateUops); + &VectorUopGenerator::generateUops); + } + + // Vector wide mixed uop generator + // For a "vwaddu.wv v12, v4, v8" with an LMUL of 4: + // Uop 1: vwaddu.wv v12, v4, v8 + // Uop 2: vwaddu.wv v13, v5, v8 + // Uop 3: vwaddu.wv v14, v6, v10 + // Uop 4: vwaddu.wv v15, v7, v10 + // Uop 5: vwaddu.wv v16, v8, v12 + // Uop 6: vwaddu.wv v17, v9, v12 + // Uop 7: vwaddu.wv v18, v10, v14 + // Uop 8: vwaddu.wv v19, v11, v14 + { + uop_gen_function_map_.emplace( + InstArchInfo::UopGenType::WIDENING_MIXED, + &VectorUopGenerator::generateUops); } // Vector arithmetic multiply-add uop generator, add dest as source @@ -68,15 +79,12 @@ namespace olympia // Uop 3: vmacc.vv v14, v6, v10, v14 // Uop 4: vmacc.vv v15, v7, v11, v15 { - constexpr bool SINGLE_DEST = false; - constexpr bool WIDE_DEST = false; - constexpr bool ADD_DEST_AS_SRC = true; uop_gen_function_map_.emplace( InstArchInfo::UopGenType::MAC, - &VectorUopGenerator::generateUops); + &VectorUopGenerator::generateUops); } - // Vector multiply-add wide dest uop generator, add dest as source + // Vector multiply-add wide dest uop generator // For a "vwmacc.vv v12, v4, v8" with an LMUL of 4: // Uop 1: vwmacc.vv v12, v4, v8, v12 // Uop 2: vwmacc.vv v13, v4, v8, v13 @@ -87,12 +95,37 @@ namespace olympia // Uop 7: vwmacc.vv v18, v7, v11, v18 // Uop 8: vwmacc.vv v19, v7, v11, v19 { - constexpr bool SINGLE_DEST = false; - constexpr bool WIDE_DEST = true; - constexpr bool ADD_DEST_AS_SRC = true; uop_gen_function_map_.emplace( InstArchInfo::UopGenType::MAC_WIDE, - &VectorUopGenerator::generateUops); + &VectorUopGenerator::generateUops); + } + + // Vector fixed point clip narrow uop generator + // For a "vnclipu.wv v0, v4, v8" with an LMUL of 4: + // Uop 1: vnclipu.wv v0, v4, v12 + // Uop 2: vnclipu.wv v0, v5, v12 + // Uop 3: vnclipu.wv v1, v6, v13 + // Uop 4: vnclipu.wv v1, v7, v13 + // Uop 5: vnclipu.wv v2, v8, v14 + // Uop 6: vnclipu.wv v2, v9, v14 + // Uop 7: vnclipu.wv v3, v10, v15 + // Uop 8: vnclipu.wv v3, v11, v15 + { + uop_gen_function_map_.emplace( + InstArchInfo::UopGenType::NARROWING, + &VectorUopGenerator::generateUops); + } + + // Vector fixed point clip narrow uop generator + // For a "vzext.vf4 v0, v4" with an LMUL of 4: + // Uop 1: vzext.vf4 v0, v4 + // Uop 2: vzext.vf4 v1, v4 + // Uop 3: vzext.vf4 v2, v4 + // Uop 4: vzext.vf4 v3, v4 + { + uop_gen_function_map_.emplace( + InstArchInfo::UopGenType::INT_EXT, + &VectorUopGenerator::generateUops); } } @@ -117,8 +150,10 @@ namespace olympia // TODO: For now, generate uops for all elements even if there is a tail num_uops_to_generate_ = std::ceil(vector_config->getVLMAX() / num_elems_per_uop); - if ((uop_gen_type == InstArchInfo::UopGenType::WIDENING) - || (uop_gen_type == InstArchInfo::UopGenType::MAC_WIDE)) + if (uop_gen_type == InstArchInfo::UopGenType::WIDENING + || uop_gen_type == InstArchInfo::UopGenType::WIDENING_MIXED + || uop_gen_type == InstArchInfo::UopGenType::MAC_WIDE + || uop_gen_type == InstArchInfo::UopGenType::NARROWING) { // TODO: Add parameter to support dual dests num_uops_to_generate_ *= 2; @@ -168,27 +203,46 @@ namespace olympia return uop; } - template - const InstPtr VectorUopGenerator::generateUops() + template const InstPtr VectorUopGenerator::generateUops() { - // Increment source and destination register values auto srcs = current_inst_->getSourceOpInfoList(); for (auto & src : srcs) { - // Do not increment scalar sources for transfer instructions if (src.operand_type != mavis::InstMetaData::OperandTypes::VECTOR) - { continue; - } - if constexpr (WIDE_DEST == true) + if constexpr (Type == InstArchInfo::UopGenType::ELEMENTWISE + || Type == InstArchInfo::UopGenType::MAC) + { + src.field_value += num_uops_generated_; + } + else if constexpr (Type == InstArchInfo::UopGenType::WIDENING + || Type == InstArchInfo::UopGenType::MAC_WIDE) { - // Only increment source values for even uops src.field_value += num_uops_generated_ / 2; } - else + else if constexpr (Type == InstArchInfo::UopGenType::WIDENING_MIXED) { - src.field_value += num_uops_generated_; + if (src.field_id == mavis::InstMetaData::OperandFieldID::RS2) + src.field_value += num_uops_generated_; + else if (src.field_id == mavis::InstMetaData::OperandFieldID::RS1) + src.field_value += num_uops_generated_ / 2; + } + else if constexpr (Type == InstArchInfo::UopGenType::NARROWING) + { + if (src.field_id == mavis::InstMetaData::OperandFieldID::RS2) + src.field_value += num_uops_generated_ / 2; + else if (src.field_id == mavis::InstMetaData::OperandFieldID::RS1) + src.field_value += num_uops_generated_; + } + else if constexpr (Type == InstArchInfo::UopGenType::INT_EXT) + { + auto ext = current_inst_->getModifier("viext"); + if (!ext) + { + throw sparta::SpartaException("Modifier at current instruction doesnt exist."); + } + src.field_value += num_uops_generated_ / ext.value(); } } @@ -208,38 +262,27 @@ namespace olympia }; auto dests = current_inst_->getDestOpInfoList(); - if constexpr (SINGLE_DEST == false) + if constexpr (Type != InstArchInfo::UopGenType::SINGLE_DEST) { for (auto & dest : dests) { - dest.field_value += num_uops_generated_; - - if constexpr (ADD_DEST_AS_SRC == true) + if constexpr (Type == InstArchInfo::UopGenType::NARROWING) { - add_dest_as_src(srcs, dest); + dest.field_value += num_uops_generated_ / 2; + } + else + { + dest.field_value += num_uops_generated_; } - } - } - - // If uop contains tail or masked elements that need to be left undisturbed, we need to add - // the destination registers as source registers - if constexpr (ADD_DEST_AS_SRC == false) - { - const VectorConfigPtr & vector_config = current_inst_->getVectorConfig(); - const uint32_t num_elems_per_uop = vector_config->getVLMAX() / vector_config->getSEW(); - const bool uop_contains_tail_elems = - (num_elems_per_uop * num_uops_generated_) > vector_config->getVL(); - if (uop_contains_tail_elems && (vector_config->getVTA() == false)) - { - for (auto & dest : dests) + if constexpr (Type == InstArchInfo::UopGenType::MAC + || Type == InstArchInfo::UopGenType::MAC_WIDE) { add_dest_as_src(srcs, dest); } } } - // Create uop InstPtr uop; if (current_inst_->hasImmediate()) { diff --git a/core/VectorUopGenerator.hpp b/core/VectorUopGenerator.hpp index 23f55435..41b3cdfc 100644 --- a/core/VectorUopGenerator.hpp +++ b/core/VectorUopGenerator.hpp @@ -46,7 +46,7 @@ namespace olympia const InstPtr generateUop(); - template + template const InstPtr generateUops(); uint64_t getNumUopsRemaining() const { return num_uops_to_generate_; } diff --git a/test/core/vector/CMakeLists.txt b/test/core/vector/CMakeLists.txt index 4f2c404f..d5548676 100644 --- a/test/core/vector/CMakeLists.txt +++ b/test/core/vector/CMakeLists.txt @@ -29,3 +29,46 @@ sparta_named_test(Vector_test_vmulvv Vector_test -l top info vmulvv.out sparta_named_test(Vector_test_vmseqvv Vector_test -l top info vmseqvv.out -c test_cores/test_big_core.yaml --input-file vmseqvv_e8m4.json) sparta_named_test(Vector_test_vsadd Vector_test -l top info vsadd.out -c test_cores/test_big_core.yaml --input-file vsadd.json) sparta_named_test(Vector_unsupported_test Vector_test -l top info unsupported.out -c test_cores/test_big_core.yaml --input-file vrgather.json) + +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/elementwise.json ${CMAKE_CURRENT_BINARY_DIR}/elementwise.json SYMBOLIC) +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/widening.json ${CMAKE_CURRENT_BINARY_DIR}/widening.json SYMBOLIC) +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/widening_mixed.json ${CMAKE_CURRENT_BINARY_DIR}/widening_mixed.json SYMBOLIC) +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/narrowing.json ${CMAKE_CURRENT_BINARY_DIR}/narrowing.json SYMBOLIC) +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/mac.json ${CMAKE_CURRENT_BINARY_DIR}/mac.json SYMBOLIC) +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/mac_widening.json ${CMAKE_CURRENT_BINARY_DIR}/mac_widening.json SYMBOLIC) +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/single_dest.json ${CMAKE_CURRENT_BINARY_DIR}/single_dest.json SYMBOLIC) +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/int_ext.json ${CMAKE_CURRENT_BINARY_DIR}/int_ext.json SYMBOLIC) + +add_executable(Vuop_test + Vuop_test.cpp ${SIM_BASE}/sim/OlympiaSim.cpp +) + +target_link_libraries(Vuop_test + PRIVATE + core common_test ${STF_LINK_LIBS} mavis SPARTA::sparta +) +sparta_named_test(Vuop_test_elementwise + Vuop_test -l top info vuop_elementwise.out -c test_cores/test_big_core.yaml --input-file elementwise.json +) +sparta_named_test(Vuop_test_widening + Vuop_test -l top info vuop_widening.out -c test_cores/test_big_core.yaml --input-file widening.json +) +sparta_named_test(Vuop_test_widening_mixed + Vuop_test -l top info vuop_widening_mixed.out -c test_cores/test_big_core.yaml --input-file widening_mixed.json +) +sparta_named_test(Vuop_test_narrowing + Vuop_test -l top info vuop_narrowing.out -c test_cores/test_big_core.yaml --input-file narrowing.json +) +sparta_named_test(Vuop_test_mac + Vuop_test -l top info vuop_mac.out -c test_cores/test_big_core.yaml --input-file mac.json +) +sparta_named_test(Vuop_test_mac_widening + Vuop_test -l top info vuop_mac_widening.out -c test_cores/test_big_core.yaml --input-file mac_widening.json +) +sparta_named_test(Vuop_test_single_dest + Vuop_test -l top info vuop_single_dest.out -c test_cores/test_big_core.yaml --input-file single_dest.json +) + +sparta_named_test(Vuop_test_int_ext + Vuop_test -l top info vuop_int_ext.out -c test_cores/test_big_core.yaml --input-file int_ext.json +) diff --git a/test/core/vector/Vuop_test.cpp b/test/core/vector/Vuop_test.cpp new file mode 100644 index 00000000..9ede9c10 --- /dev/null +++ b/test/core/vector/Vuop_test.cpp @@ -0,0 +1,216 @@ +#include "OlympiaSim.hpp" +#include "Decode.hpp" +#include "VectorUopGenerator.hpp" + +#include "sparta/app/CommandLineSimulator.hpp" +#include "sparta/kernel/Scheduler.hpp" +#include "sparta/simulation/ClockManager.hpp" +#include "sparta/utils/SpartaSharedPointer.hpp" +#include "sparta/utils/SpartaTester.hpp" + +TEST_INIT + +const char USAGE[] = "Usage:\n" + "\n" + "\n"; + +sparta::app::DefaultValues DEFAULTS; + +class olympia::DecodeTester +{ + public: + DecodeTester(olympia::Decode* decode) : decode_(decode) {} + + void test_waiting_on_vset() { EXPECT_TRUE(decode_->waiting_on_vset_ == true); } + + void test_waiting_on_vset(const bool expected_val) + { + EXPECT_TRUE(decode_->waiting_on_vset_ == expected_val); + } + + void test_vl(const uint32_t expected_vl) + { + EXPECT_TRUE(decode_->vector_config_->getVL() == expected_vl); + } + + void test_sew(const uint32_t expected_sew) + { + EXPECT_TRUE(decode_->vector_config_->getSEW() == expected_sew); + } + + void test_lmul(const uint32_t expected_lmul) + { + EXPECT_TRUE(decode_->vector_config_->getLMUL() == expected_lmul); + } + + void test_vlmax(const uint32_t expected_vlmax) + { + EXPECT_TRUE(decode_->vector_config_->getVLMAX() == expected_vlmax); + } + + void test_vta(const bool expected_vta) + { + EXPECT_TRUE(decode_->vector_config_->getVTA() == expected_vta); + } + + private: + olympia::Decode* decode_; +}; + +class olympia::VectorUopGeneratorTester +{ + public: + VectorUopGeneratorTester(olympia::VectorUopGenerator* vuop) : vuop_{vuop} {} + + void test_num_vuops_generated(const uint64_t expected_num_vuops_generated) + { + EXPECT_TRUE(vuop_->vuops_generated_ == expected_num_vuops_generated); + } + + private: + VectorUopGenerator* vuop_; +}; + +void runTests(int argc, char** argv) +{ + DEFAULTS.auto_summary_default = "off"; + std::string input_file; + + sparta::app::CommandLineSimulator cls(USAGE, DEFAULTS); + auto & app_opts = cls.getApplicationOptions(); + app_opts.add_options()( + "input-file", + sparta::app::named_value("INPUT_FILE", &input_file)->default_value(""), + "Provide a JSON instruction stream", + "Provide a JSON file with instructions to run through Execute"); + + int err_code = 0; + if (!cls.parse(argc, argv, err_code)) + { + sparta_assert(false, "Command line parsing failed"); + } + + sparta::Scheduler scheduler; + uint32_t num_cores = 1; + uint64_t ilimit = 0; + bool show_factories = false; + OlympiaSim sim("simple", scheduler, num_cores, input_file, ilimit, show_factories); + sparta::RootTreeNode* root_node = sim.getRoot(); + cls.populateSimulation(&sim); + + auto* my_decode = root_node->getChild("cpu.core0.decode")->getResourceAs(); + olympia::DecodeTester decode_tester{my_decode}; + + auto* my_vuop_generator = root_node->getChild("cpu.core0.decode.vec_uop_gen") + ->getResourceAs(); + olympia::VectorUopGeneratorTester vuop_tester{my_vuop_generator}; + + if (input_file.find("elementwise.json") != std::string::npos) + { + cls.runSimulator(&sim); + + decode_tester.test_lmul(4); + decode_tester.test_vl(256); + decode_tester.test_vta(false); + decode_tester.test_sew(32); + decode_tester.test_vlmax(128); + + vuop_tester.test_num_vuops_generated(4); + } + else if (input_file.find("widening.json") != std::string::npos) + { + cls.runSimulator(&sim); + + decode_tester.test_lmul(4); + decode_tester.test_vl(256); + decode_tester.test_vta(false); + decode_tester.test_sew(32); + decode_tester.test_vlmax(128); + + vuop_tester.test_num_vuops_generated(8); + } + else if (input_file.find("widening_mixed.json") != std::string::npos) + { + cls.runSimulator(&sim); + + decode_tester.test_lmul(4); + decode_tester.test_vl(256); + decode_tester.test_vta(false); + decode_tester.test_sew(32); + decode_tester.test_vlmax(128); + + vuop_tester.test_num_vuops_generated(8); + } + else if (input_file.find("mac.json") != std::string::npos) + { + cls.runSimulator(&sim); + + decode_tester.test_lmul(4); + decode_tester.test_vl(256); + decode_tester.test_vta(false); + decode_tester.test_sew(32); + decode_tester.test_vlmax(128); + + vuop_tester.test_num_vuops_generated(4); + } + else if (input_file.find("mac_widening.json") != std::string::npos) + { + cls.runSimulator(&sim); + + decode_tester.test_lmul(4); + decode_tester.test_vl(256); + decode_tester.test_vta(false); + decode_tester.test_sew(32); + decode_tester.test_vlmax(128); + + vuop_tester.test_num_vuops_generated(8); + } + else if (input_file.find("single_dest.json") != std::string::npos) + { + cls.runSimulator(&sim); + + decode_tester.test_lmul(4); + decode_tester.test_vl(256); + decode_tester.test_vta(false); + decode_tester.test_sew(32); + decode_tester.test_vlmax(128); + + vuop_tester.test_num_vuops_generated(4); + } + else if (input_file.find("narrowing.json") != std::string::npos) + { + cls.runSimulator(&sim); + + decode_tester.test_lmul(4); + decode_tester.test_vl(256); + decode_tester.test_vta(false); + decode_tester.test_sew(32); + decode_tester.test_vlmax(128); + + vuop_tester.test_num_vuops_generated(8); + } + else if (input_file.find("int_ext.json") != std::string::npos) + { + cls.runSimulator(&sim); + + decode_tester.test_lmul(4); + decode_tester.test_vl(256); + decode_tester.test_vta(false); + decode_tester.test_sew(64); + decode_tester.test_vlmax(64); + + vuop_tester.test_num_vuops_generated(12); + } + else + { + sparta_assert(false, "Invalid input file: " << input_file); + } +} + +int main(int argc, char** argv) +{ + runTests(argc, argv); + + REPORT_ERROR; + return (int)ERROR_CODE; +} diff --git a/test/core/vector/elementwise.json b/test/core/vector/elementwise.json new file mode 100644 index 00000000..5c63fb3d --- /dev/null +++ b/test/core/vector/elementwise.json @@ -0,0 +1,16 @@ +[ + { + "mnemonic": "vsetivli", + "rd": 0, + "imm": 256, + "vtype": "0x12", + "vl": 256, + "vta": 0 + }, + { + "mnemonic": "vadd.vv", + "vd": 12, + "vs2": 4, + "vs1": 8 + } +] diff --git a/test/core/vector/int_ext.json b/test/core/vector/int_ext.json new file mode 100644 index 00000000..cbe19ec1 --- /dev/null +++ b/test/core/vector/int_ext.json @@ -0,0 +1,25 @@ +[ + { + "mnemonic": "vsetivli", + "rd": 0, + "imm": 256, + "vtype": "0x1a", + "vl": 256, + "vta": 0 + }, + { + "mnemonic": "vzext.vf2", + "vd": 4, + "vs2": 8 + }, + { + "mnemonic": "vzext.vf4", + "vd": 4, + "vs2": 8 + }, + { + "mnemonic": "vzext.vf8", + "vd": 4, + "vs2": 8 + } +] diff --git a/test/core/vector/mac.json b/test/core/vector/mac.json new file mode 100644 index 00000000..4934a857 --- /dev/null +++ b/test/core/vector/mac.json @@ -0,0 +1,16 @@ +[ + { + "mnemonic": "vsetivli", + "rd": 0, + "imm": 256, + "vtype": "0x12", + "vl": 256, + "vta": 0 + }, + { + "mnemonic": "vmacc.vv", + "vd": 12, + "vs2": 4, + "vs1": 8 + } +] diff --git a/test/core/vector/mac_widening.json b/test/core/vector/mac_widening.json new file mode 100644 index 00000000..5bd133b0 --- /dev/null +++ b/test/core/vector/mac_widening.json @@ -0,0 +1,16 @@ +[ + { + "mnemonic": "vsetivli", + "rd": 0, + "imm": 256, + "vtype": "0x12", + "vl": 256, + "vta": 0 + }, + { + "mnemonic": "vwmacc.vv", + "vd": 12, + "vs2": 4, + "vs1": 8 + } +] diff --git a/test/core/vector/narrowing.json b/test/core/vector/narrowing.json new file mode 100644 index 00000000..88342956 --- /dev/null +++ b/test/core/vector/narrowing.json @@ -0,0 +1,16 @@ +[ + { + "mnemonic": "vsetivli", + "rd": 0, + "imm": 256, + "vtype": "0x12", + "vl": 256, + "vta": 0 + }, + { + "mnemonic": "vnclipu.wv", + "vd": 0, + "vs2": 4, + "vs1": 8 + } +] diff --git a/test/core/vector/single_dest.json b/test/core/vector/single_dest.json new file mode 100644 index 00000000..bcdcf1e8 --- /dev/null +++ b/test/core/vector/single_dest.json @@ -0,0 +1,16 @@ +[ + { + "mnemonic": "vsetivli", + "rd": 0, + "imm": 256, + "vtype": "0x12", + "vl": 256, + "vta": 0 + }, + { + "mnemonic": "vmseq.vv", + "vd": 0, + "vs2": 4, + "vs1": 8 + } +] diff --git a/test/core/vector/widening.json b/test/core/vector/widening.json new file mode 100644 index 00000000..c803566f --- /dev/null +++ b/test/core/vector/widening.json @@ -0,0 +1,16 @@ +[ + { + "mnemonic": "vsetivli", + "rd": 0, + "imm": 256, + "vtype": "0x12", + "vl": 256, + "vta": 0 + }, + { + "mnemonic": "vwmul.vv", + "vd": 12, + "vs2": 4, + "vs1": 8 + } +] diff --git a/test/core/vector/widening_mixed.json b/test/core/vector/widening_mixed.json new file mode 100644 index 00000000..996e5c3c --- /dev/null +++ b/test/core/vector/widening_mixed.json @@ -0,0 +1,16 @@ +[ + { + "mnemonic": "vsetivli", + "rd": 0, + "imm": 256, + "vtype": "0x12", + "vl": 256, + "vta": 0 + }, + { + "mnemonic": "vwaddu.vv", + "vd": 12, + "vs2": 4, + "vs1": 8 + } +]