Skip to content

Commit

Permalink
[Vector] refactor vuop (#228)
Browse files Browse the repository at this point in the history
  • Loading branch information
orion160 authored Nov 28, 2024
1 parent cb78046 commit 71fe733
Show file tree
Hide file tree
Showing 9 changed files with 572 additions and 516 deletions.
325 changes: 176 additions & 149 deletions arches/isa_json/gen_uarch_rv64v_json.py

Large diffs are not rendered by default.

440 changes: 220 additions & 220 deletions arches/isa_json/olympia_uarch_rv64v.json

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions core/Dispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ namespace olympia
sparta::Counter::COUNT_NORMAL, getClock()),
sparta::CycleCounter(getStatisticSet(), "stall_vint_busy", "VINT busy",
sparta::Counter::COUNT_NORMAL, getClock()),
sparta::CycleCounter(getStatisticSet(), "stall_vfixed_busy", "VFIXED busy",
sparta::CycleCounter(getStatisticSet(), "stall_vfixed_busy", "VFIXED busy",
sparta::Counter::COUNT_NORMAL, getClock()),
sparta::CycleCounter(getStatisticSet(), "stall_vmask_busy", "VMASK busy",
sparta::Counter::COUNT_NORMAL, getClock()),
Expand Down Expand Up @@ -222,7 +222,7 @@ namespace olympia
sparta::Counter::COUNT_NORMAL),
sparta::Counter(getStatisticSet(), "count_vint_insts", "Total VINT insts",
sparta::Counter::COUNT_NORMAL),
sparta::Counter(getStatisticSet(), "count_vfixed_insts", "Total VFIXED insts",
sparta::Counter(getStatisticSet(), "count_vfixed_insts", "Total VFIXED insts",
sparta::Counter::COUNT_NORMAL),
sparta::Counter(getStatisticSet(), "count_vmask_insts", "Total VMASK insts",
sparta::Counter::COUNT_NORMAL),
Expand Down Expand Up @@ -280,6 +280,8 @@ namespace olympia
"count_cmov_insts + count_div_insts + count_faddsub_insts + count_float_insts + "
"count_fmac_insts + count_i2f_insts + count_f2i_insts + count_int_insts + "
"count_lsu_insts + count_mul_insts + count_br_insts"};

friend class DispatchTester;
};

using DispatchFactory =
Expand All @@ -305,5 +307,8 @@ namespace olympia
}

return os;

}

class DispatchTester;
} // namespace olympia
14 changes: 8 additions & 6 deletions core/InstArchInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@ namespace olympia
};

const InstArchInfo::UopGenMap InstArchInfo::uop_gen_type_map = {
{"ARITH", InstArchInfo::UopGenType::ARITH},
{"ARITH_SINGLE_DEST", InstArchInfo::UopGenType::ARITH_SINGLE_DEST},
{"ARITH_WIDE_DEST", InstArchInfo::UopGenType::ARITH_WIDE_DEST},
{"ARITH_MAC", InstArchInfo::UopGenType::ARITH_MAC},
{"ARITH_MAC_WIDE_DEST", InstArchInfo::UopGenType::ARITH_MAC_WIDE_DEST},
{"NONE", InstArchInfo::UopGenType::NONE}
{"ELEMENTWISE", InstArchInfo::UopGenType::ELEMENTWISE},
{"SINGLE_DEST", InstArchInfo::UopGenType::SINGLE_DEST},
{"WIDENING", InstArchInfo::UopGenType::WIDENING},
{"WIDENING_MIXED", InstArchInfo::UopGenType::WIDENING_MIXED},
{"NARROWING", InstArchInfo::UopGenType::NARROWING},
{"MAC", InstArchInfo::UopGenType::MAC},
{"MAC_WIDE", InstArchInfo::UopGenType::MAC_WIDE},
{"NONE", InstArchInfo::UopGenType::NONE}
};

void InstArchInfo::update(const nlohmann::json & jobj)
Expand Down
12 changes: 7 additions & 5 deletions core/InstArchInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,13 @@ namespace olympia

enum class UopGenType
{
ARITH,
ARITH_SINGLE_DEST,
ARITH_WIDE_DEST,
ARITH_MAC,
ARITH_MAC_WIDE_DEST,
ELEMENTWISE,
SINGLE_DEST,
WIDENING,
WIDENING_MIXED,
NARROWING,
MAC,
MAC_WIDE,
NONE,
UNKNOWN
};
Expand Down
147 changes: 76 additions & 71 deletions core/VectorUopGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ namespace olympia
{
constexpr char VectorUopGenerator::name[];

VectorUopGenerator::VectorUopGenerator(sparta::TreeNode* node, const VectorUopGeneratorParameterSet* p) :
sparta::Unit(node)
VectorUopGenerator::VectorUopGenerator(sparta::TreeNode* node,
const VectorUopGeneratorParameterSet* p) :
sparta::Unit(node),
vuops_generated_(&unit_stat_set_, "vector_uops_generated",
"Number of vector uops generated", sparta::Counter::COUNT_NORMAL)
{
// Vector arithmetic uop generator, increment all src and dest register numbers
// Vector 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
Expand All @@ -19,26 +22,28 @@ namespace olympia
constexpr bool SINGLE_DEST = false;
constexpr bool WIDE_DEST = false;
constexpr bool ADD_DEST_AS_SRC = false;
uop_gen_function_map_.emplace(InstArchInfo::UopGenType::ARITH,
&VectorUopGenerator::generateArithUop<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
uop_gen_function_map_.emplace(
InstArchInfo::UopGenType::ELEMENTWISE,
&VectorUopGenerator::generateUops<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
}

// Vector arithmetic single dest uop generator, only increment all src register numbers
// For a "vmseq.vv v12, v4,v8" with an LMUL of 4:
// Uop 1: vadd.vv v12, v4, v8
// Uop 2: vadd.vv v12, v5, v9
// Uop 3: vadd.vv v12, v6, v10
// Uop 4: vadd.vv v12, v7, v11
// Vector single dest uop generator, only increment all src register numbers
// For a "vmseq.vv v12, v4, v8" with an LMUL of 4:
// Uop 1: vmseq.vv v12, v4, v8
// Uop 2: vmseq.vv v12, v5, v9
// 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::ARITH_SINGLE_DEST,
&VectorUopGenerator::generateArithUop<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
uop_gen_function_map_.emplace(
InstArchInfo::UopGenType::SINGLE_DEST,
&VectorUopGenerator::generateUops<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
}

// Vector arithmetic 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 dest 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
Expand All @@ -49,14 +54,30 @@ namespace olympia
// Uop 8: vwmul.vv v19, v10, v14
{
constexpr bool SINGLE_DEST = false;
constexpr bool WIDE_DEST = true;
constexpr bool WIDENING = true;
constexpr bool ADD_DEST_AS_SRC = false;
uop_gen_function_map_.emplace(InstArchInfo::UopGenType::ARITH_WIDE_DEST,
&VectorUopGenerator::generateArithUop<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
uop_gen_function_map_.emplace(
InstArchInfo::UopGenType::WIDENING,
&VectorUopGenerator::generateUops<SINGLE_DEST, WIDENING, ADD_DEST_AS_SRC>);
}

// Vector arithmetic multiplay-add wide dest uop generator, add dest as source
// Vector arithmetic multiply-add uop generator, add dest as source
// For a "vmacc.vv v12, v4, v8" with an LMUL of 4:
// Uop 1: vmacc.vv v12, v4, v8, v12
// Uop 2: vmacc.vv v13, v5, v9, v13
// 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<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
}

// Vector multiply-add wide dest uop generator, add dest as source
// 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
// Uop 3: vwmacc.vv v14, v5, v9, v14
Expand All @@ -65,69 +86,54 @@ namespace olympia
// Uop 6: vwmacc.vv v17, v6, v10, v17
// 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 = false;
constexpr bool ADD_DEST_AS_SRC = true;
uop_gen_function_map_.emplace(InstArchInfo::UopGenType::ARITH_MAC,
&VectorUopGenerator::generateArithUop<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
}

// Vector arithmetic multiplay-add uop generator, add dest as source
// For a "vmacc.vv v12, v4, v8" with an LMUL of 4:
// Uop 1: vmacc.vv v12, v4, v8, v12
// Uop 2: vmacc.vv v13, v5, v9, v13
// 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 = true;
constexpr bool ADD_DEST_AS_SRC = true;
uop_gen_function_map_.emplace(InstArchInfo::UopGenType::ARITH_MAC_WIDE_DEST,
&VectorUopGenerator::generateArithUop<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
uop_gen_function_map_.emplace(
InstArchInfo::UopGenType::MAC_WIDE,
&VectorUopGenerator::generateUops<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
}
}

void VectorUopGenerator::onBindTreeLate_()
{
mavis_facade_ = getMavis(getContainer());
}
void VectorUopGenerator::onBindTreeLate_() { mavis_facade_ = getMavis(getContainer()); }

void VectorUopGenerator::setInst(const InstPtr & inst)
{
sparta_assert(current_inst_ == nullptr,
"Cannot start generating uops for a new vector instruction, "
"current instruction has not finished: " << current_inst_);
"Cannot start generating uops for a new vector instruction, "
"current instruction has not finished: "
<< current_inst_);

const auto uop_gen_type = inst->getUopGenType();
sparta_assert(uop_gen_type != InstArchInfo::UopGenType::UNKNOWN,
"Inst: " << current_inst_ << " uop gen type is unknown");
"Inst: " << current_inst_ << " uop gen type is unknown");
sparta_assert(uop_gen_type != InstArchInfo::UopGenType::NONE,
"Inst: " << current_inst_ << " uop gen type is none");
"Inst: " << current_inst_ << " uop gen type is none");

// Number of vector elements processed by each uop
const VectorConfigPtr & vector_config = inst->getVectorConfig();
const uint64_t num_elems_per_uop = VectorConfig::VLEN / vector_config->getSEW();
// 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::ARITH_WIDE_DEST) ||
(uop_gen_type == InstArchInfo::UopGenType::ARITH_MAC_WIDE_DEST))
if ((uop_gen_type == InstArchInfo::UopGenType::WIDENING)
|| (uop_gen_type == InstArchInfo::UopGenType::MAC_WIDE))
{
// TODO: Add parameter to support dual dests
num_uops_to_generate_ *= 2;
}

current_inst_ = inst;
ILOG("Inst: " << current_inst_ <<
" is being split into " << num_uops_to_generate_ << " UOPs");
ILOG("Inst: " << current_inst_ << " is being split into " << num_uops_to_generate_
<< " UOPs");
}

const InstPtr VectorUopGenerator::generateUop()
{
const auto uop_gen_type = current_inst_->getUopGenType();
sparta_assert(uop_gen_type <= InstArchInfo::UopGenType::NONE,
"Inst: " << current_inst_ << " uop gen type is unknown");
"Inst: " << current_inst_ << " uop gen type is unknown");

// Generate uop
auto uop_gen_func = uop_gen_function_map_.at(uop_gen_type);
Expand All @@ -141,6 +147,7 @@ namespace olympia
uop->setVectorConfig(vector_config);
uop->setUOpID(num_uops_generated_);
++num_uops_generated_;
++vuops_generated_;

// Set weak pointer to parent vector instruction (first uop)
sparta::SpartaWeakPointer<olympia::Inst> parent_weak_ptr = current_inst_;
Expand All @@ -151,7 +158,7 @@ namespace olympia
uop->setTail((num_elems_per_uop * num_uops_generated_) > vector_config->getVL());

// Handle last uop
if(num_uops_generated_ == num_uops_to_generate_)
if (num_uops_generated_ == num_uops_to_generate_)
{
reset_();
}
Expand All @@ -161,8 +168,8 @@ namespace olympia
return uop;
}

template<bool SINGLE_DEST, bool WIDE_DEST, bool ADD_DEST_AS_SRC>
const InstPtr VectorUopGenerator::generateArithUop()
template <bool SINGLE_DEST, bool WIDE_DEST, bool ADD_DEST_AS_SRC>
const InstPtr VectorUopGenerator::generateUops()
{
// Increment source and destination register values
auto srcs = current_inst_->getSourceOpInfoList();
Expand All @@ -177,8 +184,7 @@ namespace olympia
if constexpr (WIDE_DEST == true)
{
// Only increment source values for even uops
src.field_value += (num_uops_generated_ % 2) ? num_uops_generated_ - 1
: num_uops_generated_;
src.field_value += num_uops_generated_ / 2;
}
else
{
Expand All @@ -188,16 +194,18 @@ namespace olympia

// Add a destination to the list of sources
auto add_dest_as_src = [](auto & srcs, auto & dest)
{
// OperandFieldID is an enum with RS1 = 0, RS2 = 1, etc. with a max RS of RS4
using OperandFieldID = mavis::InstMetaData::OperandFieldID;
const OperandFieldID field_id = static_cast<OperandFieldID>(srcs.size());
sparta_assert(field_id <= OperandFieldID::RS_MAX,
"Mavis does not support instructions with more than " << std::dec <<
static_cast<std::underlying_type_t<OperandFieldID>>(OperandFieldID::RS_MAX) <<
" sources");
srcs.emplace_back(field_id, dest.operand_type, dest.field_value);
};
{
// OperandFieldID is an enum with RS1 = 0, RS2 = 1, etc. with a max RS of RS4
using OperandFieldID = mavis::InstMetaData::OperandFieldID;
const OperandFieldID field_id = static_cast<OperandFieldID>(srcs.size());
sparta_assert(
field_id <= OperandFieldID::RS_MAX,
"Mavis does not support instructions with more than "
<< std::dec
<< static_cast<std::underlying_type_t<OperandFieldID>>(OperandFieldID::RS_MAX)
<< " sources");
srcs.emplace_back(field_id, dest.operand_type, dest.field_value);
};

auto dests = current_inst_->getDestOpInfoList();
if constexpr (SINGLE_DEST == false)
Expand All @@ -219,7 +227,8 @@ namespace olympia
{
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();
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))
{
Expand All @@ -234,17 +243,13 @@ namespace olympia
InstPtr uop;
if (current_inst_->hasImmediate())
{
mavis::ExtractorDirectOpInfoList ex_info(current_inst_->getMnemonic(),
srcs,
dests,
mavis::ExtractorDirectOpInfoList ex_info(current_inst_->getMnemonic(), srcs, dests,
current_inst_->getImmediate());
uop = mavis_facade_->makeInstDirectly(ex_info, getClock());
}
else
{
mavis::ExtractorDirectOpInfoList ex_info(current_inst_->getMnemonic(),
srcs,
dests);
mavis::ExtractorDirectOpInfoList ex_info(current_inst_->getMnemonic(), srcs, dests);
uop = mavis_facade_->makeInstDirectly(ex_info, getClock());
}

Expand All @@ -253,7 +258,7 @@ namespace olympia

void VectorUopGenerator::handleFlush(const FlushManager::FlushingCriteria & flush_criteria)
{
if(current_inst_ && flush_criteria.includedInFlush(current_inst_))
if (current_inst_ && flush_criteria.includedInFlush(current_inst_))
{
reset_();
}
Expand Down
Loading

0 comments on commit 71fe733

Please sign in to comment.