Skip to content

Commit 71fe733

Browse files
authored
[Vector] refactor vuop (#228)
1 parent cb78046 commit 71fe733

File tree

9 files changed

+572
-516
lines changed

9 files changed

+572
-516
lines changed

arches/isa_json/gen_uarch_rv64v_json.py

Lines changed: 176 additions & 149 deletions
Large diffs are not rendered by default.

arches/isa_json/olympia_uarch_rv64v.json

Lines changed: 220 additions & 220 deletions
Large diffs are not rendered by default.

core/Dispatch.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ namespace olympia
178178
sparta::Counter::COUNT_NORMAL, getClock()),
179179
sparta::CycleCounter(getStatisticSet(), "stall_vint_busy", "VINT busy",
180180
sparta::Counter::COUNT_NORMAL, getClock()),
181-
sparta::CycleCounter(getStatisticSet(), "stall_vfixed_busy", "VFIXED busy",
181+
sparta::CycleCounter(getStatisticSet(), "stall_vfixed_busy", "VFIXED busy",
182182
sparta::Counter::COUNT_NORMAL, getClock()),
183183
sparta::CycleCounter(getStatisticSet(), "stall_vmask_busy", "VMASK busy",
184184
sparta::Counter::COUNT_NORMAL, getClock()),
@@ -222,7 +222,7 @@ namespace olympia
222222
sparta::Counter::COUNT_NORMAL),
223223
sparta::Counter(getStatisticSet(), "count_vint_insts", "Total VINT insts",
224224
sparta::Counter::COUNT_NORMAL),
225-
sparta::Counter(getStatisticSet(), "count_vfixed_insts", "Total VFIXED insts",
225+
sparta::Counter(getStatisticSet(), "count_vfixed_insts", "Total VFIXED insts",
226226
sparta::Counter::COUNT_NORMAL),
227227
sparta::Counter(getStatisticSet(), "count_vmask_insts", "Total VMASK insts",
228228
sparta::Counter::COUNT_NORMAL),
@@ -280,6 +280,8 @@ namespace olympia
280280
"count_cmov_insts + count_div_insts + count_faddsub_insts + count_float_insts + "
281281
"count_fmac_insts + count_i2f_insts + count_f2i_insts + count_int_insts + "
282282
"count_lsu_insts + count_mul_insts + count_br_insts"};
283+
284+
friend class DispatchTester;
283285
};
284286

285287
using DispatchFactory =
@@ -305,5 +307,8 @@ namespace olympia
305307
}
306308

307309
return os;
310+
308311
}
312+
313+
class DispatchTester;
309314
} // namespace olympia

core/InstArchInfo.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,14 @@ namespace olympia
5050
};
5151

5252
const InstArchInfo::UopGenMap InstArchInfo::uop_gen_type_map = {
53-
{"ARITH", InstArchInfo::UopGenType::ARITH},
54-
{"ARITH_SINGLE_DEST", InstArchInfo::UopGenType::ARITH_SINGLE_DEST},
55-
{"ARITH_WIDE_DEST", InstArchInfo::UopGenType::ARITH_WIDE_DEST},
56-
{"ARITH_MAC", InstArchInfo::UopGenType::ARITH_MAC},
57-
{"ARITH_MAC_WIDE_DEST", InstArchInfo::UopGenType::ARITH_MAC_WIDE_DEST},
58-
{"NONE", InstArchInfo::UopGenType::NONE}
53+
{"ELEMENTWISE", InstArchInfo::UopGenType::ELEMENTWISE},
54+
{"SINGLE_DEST", InstArchInfo::UopGenType::SINGLE_DEST},
55+
{"WIDENING", InstArchInfo::UopGenType::WIDENING},
56+
{"WIDENING_MIXED", InstArchInfo::UopGenType::WIDENING_MIXED},
57+
{"NARROWING", InstArchInfo::UopGenType::NARROWING},
58+
{"MAC", InstArchInfo::UopGenType::MAC},
59+
{"MAC_WIDE", InstArchInfo::UopGenType::MAC_WIDE},
60+
{"NONE", InstArchInfo::UopGenType::NONE}
5961
};
6062

6163
void InstArchInfo::update(const nlohmann::json & jobj)

core/InstArchInfo.hpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,13 @@ namespace olympia
6868

6969
enum class UopGenType
7070
{
71-
ARITH,
72-
ARITH_SINGLE_DEST,
73-
ARITH_WIDE_DEST,
74-
ARITH_MAC,
75-
ARITH_MAC_WIDE_DEST,
71+
ELEMENTWISE,
72+
SINGLE_DEST,
73+
WIDENING,
74+
WIDENING_MIXED,
75+
NARROWING,
76+
MAC,
77+
MAC_WIDE,
7678
NONE,
7779
UNKNOWN
7880
};

core/VectorUopGenerator.cpp

Lines changed: 76 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ namespace olympia
66
{
77
constexpr char VectorUopGenerator::name[];
88

9-
VectorUopGenerator::VectorUopGenerator(sparta::TreeNode* node, const VectorUopGeneratorParameterSet* p) :
10-
sparta::Unit(node)
9+
VectorUopGenerator::VectorUopGenerator(sparta::TreeNode* node,
10+
const VectorUopGeneratorParameterSet* p) :
11+
sparta::Unit(node),
12+
vuops_generated_(&unit_stat_set_, "vector_uops_generated",
13+
"Number of vector uops generated", sparta::Counter::COUNT_NORMAL)
1114
{
12-
// Vector arithmetic uop generator, increment all src and dest register numbers
15+
// Vector uop generator, increment all src and dest register numbers
1316
// For a "vadd.vv v12, v4,v8" with an LMUL of 4:
1417
// Uop 1: vadd.vv v12, v4, v8
1518
// Uop 2: vadd.vv v13, v5, v9
@@ -19,26 +22,28 @@ namespace olympia
1922
constexpr bool SINGLE_DEST = false;
2023
constexpr bool WIDE_DEST = false;
2124
constexpr bool ADD_DEST_AS_SRC = false;
22-
uop_gen_function_map_.emplace(InstArchInfo::UopGenType::ARITH,
23-
&VectorUopGenerator::generateArithUop<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
25+
uop_gen_function_map_.emplace(
26+
InstArchInfo::UopGenType::ELEMENTWISE,
27+
&VectorUopGenerator::generateUops<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
2428
}
2529

26-
// Vector arithmetic single dest uop generator, only increment all src register numbers
27-
// For a "vmseq.vv v12, v4,v8" with an LMUL of 4:
28-
// Uop 1: vadd.vv v12, v4, v8
29-
// Uop 2: vadd.vv v12, v5, v9
30-
// Uop 3: vadd.vv v12, v6, v10
31-
// Uop 4: vadd.vv v12, v7, v11
30+
// Vector single dest uop generator, only increment all src register numbers
31+
// For a "vmseq.vv v12, v4, v8" with an LMUL of 4:
32+
// Uop 1: vmseq.vv v12, v4, v8
33+
// Uop 2: vmseq.vv v12, v5, v9
34+
// Uop 3: vmseq.vv v12, v6, v10
35+
// Uop 4: vmseq.vv v12, v7, v11
3236
{
3337
constexpr bool SINGLE_DEST = true;
3438
constexpr bool WIDE_DEST = false;
3539
constexpr bool ADD_DEST_AS_SRC = false;
36-
uop_gen_function_map_.emplace(InstArchInfo::UopGenType::ARITH_SINGLE_DEST,
37-
&VectorUopGenerator::generateArithUop<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
40+
uop_gen_function_map_.emplace(
41+
InstArchInfo::UopGenType::SINGLE_DEST,
42+
&VectorUopGenerator::generateUops<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
3843
}
3944

40-
// Vector arithmetic wide dest uop generator, only increment src register numbers for even uops
41-
// For a "vwmul.vv v12, v4, v8" with an LMUL of 4:
45+
// Vector wide dest uop generator, only increment src register numbers for even
46+
// uops For a "vwmul.vv v12, v4, v8" with an LMUL of 4:
4247
// Uop 1: vwmul.vv v12, v4, v8
4348
// Uop 2: vwmul.vv v13, v4, v8
4449
// Uop 3: vwmul.vv v14, v6, v10
@@ -49,14 +54,30 @@ namespace olympia
4954
// Uop 8: vwmul.vv v19, v10, v14
5055
{
5156
constexpr bool SINGLE_DEST = false;
52-
constexpr bool WIDE_DEST = true;
57+
constexpr bool WIDENING = true;
5358
constexpr bool ADD_DEST_AS_SRC = false;
54-
uop_gen_function_map_.emplace(InstArchInfo::UopGenType::ARITH_WIDE_DEST,
55-
&VectorUopGenerator::generateArithUop<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
59+
uop_gen_function_map_.emplace(
60+
InstArchInfo::UopGenType::WIDENING,
61+
&VectorUopGenerator::generateUops<SINGLE_DEST, WIDENING, ADD_DEST_AS_SRC>);
5662
}
5763

58-
// Vector arithmetic multiplay-add wide dest uop generator, add dest as source
64+
// Vector arithmetic multiply-add uop generator, add dest as source
5965
// For a "vmacc.vv v12, v4, v8" with an LMUL of 4:
66+
// Uop 1: vmacc.vv v12, v4, v8, v12
67+
// Uop 2: vmacc.vv v13, v5, v9, v13
68+
// Uop 3: vmacc.vv v14, v6, v10, v14
69+
// Uop 4: vmacc.vv v15, v7, v11, v15
70+
{
71+
constexpr bool SINGLE_DEST = false;
72+
constexpr bool WIDE_DEST = false;
73+
constexpr bool ADD_DEST_AS_SRC = true;
74+
uop_gen_function_map_.emplace(
75+
InstArchInfo::UopGenType::MAC,
76+
&VectorUopGenerator::generateUops<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
77+
}
78+
79+
// Vector multiply-add wide dest uop generator, add dest as source
80+
// For a "vwmacc.vv v12, v4, v8" with an LMUL of 4:
6081
// Uop 1: vwmacc.vv v12, v4, v8, v12
6182
// Uop 2: vwmacc.vv v13, v4, v8, v13
6283
// Uop 3: vwmacc.vv v14, v5, v9, v14
@@ -65,69 +86,54 @@ namespace olympia
6586
// Uop 6: vwmacc.vv v17, v6, v10, v17
6687
// Uop 7: vwmacc.vv v18, v7, v11, v18
6788
// Uop 8: vwmacc.vv v19, v7, v11, v19
68-
{
69-
constexpr bool SINGLE_DEST = false;
70-
constexpr bool WIDE_DEST = false;
71-
constexpr bool ADD_DEST_AS_SRC = true;
72-
uop_gen_function_map_.emplace(InstArchInfo::UopGenType::ARITH_MAC,
73-
&VectorUopGenerator::generateArithUop<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
74-
}
75-
76-
// Vector arithmetic multiplay-add uop generator, add dest as source
77-
// For a "vmacc.vv v12, v4, v8" with an LMUL of 4:
78-
// Uop 1: vmacc.vv v12, v4, v8, v12
79-
// Uop 2: vmacc.vv v13, v5, v9, v13
80-
// Uop 3: vmacc.vv v14, v6, v10, v14
81-
// Uop 4: vmacc.vv v15, v7, v11, v15
8289
{
8390
constexpr bool SINGLE_DEST = false;
8491
constexpr bool WIDE_DEST = true;
8592
constexpr bool ADD_DEST_AS_SRC = true;
86-
uop_gen_function_map_.emplace(InstArchInfo::UopGenType::ARITH_MAC_WIDE_DEST,
87-
&VectorUopGenerator::generateArithUop<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
93+
uop_gen_function_map_.emplace(
94+
InstArchInfo::UopGenType::MAC_WIDE,
95+
&VectorUopGenerator::generateUops<SINGLE_DEST, WIDE_DEST, ADD_DEST_AS_SRC>);
8896
}
8997
}
9098

91-
void VectorUopGenerator::onBindTreeLate_()
92-
{
93-
mavis_facade_ = getMavis(getContainer());
94-
}
99+
void VectorUopGenerator::onBindTreeLate_() { mavis_facade_ = getMavis(getContainer()); }
95100

96101
void VectorUopGenerator::setInst(const InstPtr & inst)
97102
{
98103
sparta_assert(current_inst_ == nullptr,
99-
"Cannot start generating uops for a new vector instruction, "
100-
"current instruction has not finished: " << current_inst_);
104+
"Cannot start generating uops for a new vector instruction, "
105+
"current instruction has not finished: "
106+
<< current_inst_);
101107

102108
const auto uop_gen_type = inst->getUopGenType();
103109
sparta_assert(uop_gen_type != InstArchInfo::UopGenType::UNKNOWN,
104-
"Inst: " << current_inst_ << " uop gen type is unknown");
110+
"Inst: " << current_inst_ << " uop gen type is unknown");
105111
sparta_assert(uop_gen_type != InstArchInfo::UopGenType::NONE,
106-
"Inst: " << current_inst_ << " uop gen type is none");
112+
"Inst: " << current_inst_ << " uop gen type is none");
107113

108114
// Number of vector elements processed by each uop
109115
const VectorConfigPtr & vector_config = inst->getVectorConfig();
110116
const uint64_t num_elems_per_uop = VectorConfig::VLEN / vector_config->getSEW();
111117
// TODO: For now, generate uops for all elements even if there is a tail
112118
num_uops_to_generate_ = std::ceil(vector_config->getVLMAX() / num_elems_per_uop);
113119

114-
if((uop_gen_type == InstArchInfo::UopGenType::ARITH_WIDE_DEST) ||
115-
(uop_gen_type == InstArchInfo::UopGenType::ARITH_MAC_WIDE_DEST))
120+
if ((uop_gen_type == InstArchInfo::UopGenType::WIDENING)
121+
|| (uop_gen_type == InstArchInfo::UopGenType::MAC_WIDE))
116122
{
117123
// TODO: Add parameter to support dual dests
118124
num_uops_to_generate_ *= 2;
119125
}
120126

121127
current_inst_ = inst;
122-
ILOG("Inst: " << current_inst_ <<
123-
" is being split into " << num_uops_to_generate_ << " UOPs");
128+
ILOG("Inst: " << current_inst_ << " is being split into " << num_uops_to_generate_
129+
<< " UOPs");
124130
}
125131

126132
const InstPtr VectorUopGenerator::generateUop()
127133
{
128134
const auto uop_gen_type = current_inst_->getUopGenType();
129135
sparta_assert(uop_gen_type <= InstArchInfo::UopGenType::NONE,
130-
"Inst: " << current_inst_ << " uop gen type is unknown");
136+
"Inst: " << current_inst_ << " uop gen type is unknown");
131137

132138
// Generate uop
133139
auto uop_gen_func = uop_gen_function_map_.at(uop_gen_type);
@@ -141,6 +147,7 @@ namespace olympia
141147
uop->setVectorConfig(vector_config);
142148
uop->setUOpID(num_uops_generated_);
143149
++num_uops_generated_;
150+
++vuops_generated_;
144151

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

153160
// Handle last uop
154-
if(num_uops_generated_ == num_uops_to_generate_)
161+
if (num_uops_generated_ == num_uops_to_generate_)
155162
{
156163
reset_();
157164
}
@@ -161,8 +168,8 @@ namespace olympia
161168
return uop;
162169
}
163170

164-
template<bool SINGLE_DEST, bool WIDE_DEST, bool ADD_DEST_AS_SRC>
165-
const InstPtr VectorUopGenerator::generateArithUop()
171+
template <bool SINGLE_DEST, bool WIDE_DEST, bool ADD_DEST_AS_SRC>
172+
const InstPtr VectorUopGenerator::generateUops()
166173
{
167174
// Increment source and destination register values
168175
auto srcs = current_inst_->getSourceOpInfoList();
@@ -177,8 +184,7 @@ namespace olympia
177184
if constexpr (WIDE_DEST == true)
178185
{
179186
// Only increment source values for even uops
180-
src.field_value += (num_uops_generated_ % 2) ? num_uops_generated_ - 1
181-
: num_uops_generated_;
187+
src.field_value += num_uops_generated_ / 2;
182188
}
183189
else
184190
{
@@ -188,16 +194,18 @@ namespace olympia
188194

189195
// Add a destination to the list of sources
190196
auto add_dest_as_src = [](auto & srcs, auto & dest)
191-
{
192-
// OperandFieldID is an enum with RS1 = 0, RS2 = 1, etc. with a max RS of RS4
193-
using OperandFieldID = mavis::InstMetaData::OperandFieldID;
194-
const OperandFieldID field_id = static_cast<OperandFieldID>(srcs.size());
195-
sparta_assert(field_id <= OperandFieldID::RS_MAX,
196-
"Mavis does not support instructions with more than " << std::dec <<
197-
static_cast<std::underlying_type_t<OperandFieldID>>(OperandFieldID::RS_MAX) <<
198-
" sources");
199-
srcs.emplace_back(field_id, dest.operand_type, dest.field_value);
200-
};
197+
{
198+
// OperandFieldID is an enum with RS1 = 0, RS2 = 1, etc. with a max RS of RS4
199+
using OperandFieldID = mavis::InstMetaData::OperandFieldID;
200+
const OperandFieldID field_id = static_cast<OperandFieldID>(srcs.size());
201+
sparta_assert(
202+
field_id <= OperandFieldID::RS_MAX,
203+
"Mavis does not support instructions with more than "
204+
<< std::dec
205+
<< static_cast<std::underlying_type_t<OperandFieldID>>(OperandFieldID::RS_MAX)
206+
<< " sources");
207+
srcs.emplace_back(field_id, dest.operand_type, dest.field_value);
208+
};
201209

202210
auto dests = current_inst_->getDestOpInfoList();
203211
if constexpr (SINGLE_DEST == false)
@@ -219,7 +227,8 @@ namespace olympia
219227
{
220228
const VectorConfigPtr & vector_config = current_inst_->getVectorConfig();
221229
const uint32_t num_elems_per_uop = vector_config->getVLMAX() / vector_config->getSEW();
222-
const bool uop_contains_tail_elems = (num_elems_per_uop * num_uops_generated_) > vector_config->getVL();
230+
const bool uop_contains_tail_elems =
231+
(num_elems_per_uop * num_uops_generated_) > vector_config->getVL();
223232

224233
if (uop_contains_tail_elems && (vector_config->getVTA() == false))
225234
{
@@ -234,17 +243,13 @@ namespace olympia
234243
InstPtr uop;
235244
if (current_inst_->hasImmediate())
236245
{
237-
mavis::ExtractorDirectOpInfoList ex_info(current_inst_->getMnemonic(),
238-
srcs,
239-
dests,
246+
mavis::ExtractorDirectOpInfoList ex_info(current_inst_->getMnemonic(), srcs, dests,
240247
current_inst_->getImmediate());
241248
uop = mavis_facade_->makeInstDirectly(ex_info, getClock());
242249
}
243250
else
244251
{
245-
mavis::ExtractorDirectOpInfoList ex_info(current_inst_->getMnemonic(),
246-
srcs,
247-
dests);
252+
mavis::ExtractorDirectOpInfoList ex_info(current_inst_->getMnemonic(), srcs, dests);
248253
uop = mavis_facade_->makeInstDirectly(ex_info, getClock());
249254
}
250255

@@ -253,7 +258,7 @@ namespace olympia
253258

254259
void VectorUopGenerator::handleFlush(const FlushManager::FlushingCriteria & flush_criteria)
255260
{
256-
if(current_inst_ && flush_criteria.includedInFlush(current_inst_))
261+
if (current_inst_ && flush_criteria.includedInFlush(current_inst_))
257262
{
258263
reset_();
259264
}

0 commit comments

Comments
 (0)