adds Integer Reduction Instructions
This commit is contained in:
parent
28ac169cfe
commit
f049d8cbb3
@ -467,6 +467,20 @@ if(vector != null) {%>
|
||||
throw new std::runtime_error("Unsupported sew bit value");
|
||||
}
|
||||
}
|
||||
void vector_red_op(uint8_t* V, uint8_t funct6, uint8_t funct3, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t vs1, uint8_t sew_val){
|
||||
switch(sew_val){
|
||||
case 0b000:
|
||||
return softvector::vector_red_op<${vlen}, uint8_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
|
||||
case 0b001:
|
||||
return softvector::vector_red_op<${vlen}, uint16_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
|
||||
case 0b010:
|
||||
return softvector::vector_red_op<${vlen}, uint32_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
|
||||
case 0b011:
|
||||
return softvector::vector_red_op<${vlen}, uint64_t>(V, funct6, funct3, vl, vstart, vtype, vm, vd, vs2, vs1);
|
||||
default:
|
||||
throw new std::runtime_error("Unsupported sew bit value");
|
||||
}
|
||||
}
|
||||
<%}%>
|
||||
uint64_t fetch_count{0};
|
||||
uint64_t tval{0};
|
||||
|
@ -97,6 +97,9 @@ bool sat_vector_vector_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t
|
||||
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = dest_elem_t>
|
||||
bool sat_vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, int64_t vxrm, bool vm,
|
||||
unsigned vd, unsigned vs2, typename std::make_signed<src1_elem_t>::type imm);
|
||||
template <unsigned VLEN, typename dest_elem_t, typename src_elem_t = dest_elem_t>
|
||||
void vector_red_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
|
||||
unsigned vs2, unsigned vs1);
|
||||
} // namespace softvector
|
||||
#include "vm/vector_functions.hpp"
|
||||
#endif /* _VM_VECTOR_FUNCTIONS_H_ */
|
||||
|
@ -147,21 +147,11 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
|
||||
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
||||
return static_cast<std::make_signed_t<src2_elem_t>>(vs2) >> (vs1 & shift_mask<src2_elem_t>());
|
||||
};
|
||||
// case 0b110000: // VWREDSUMU
|
||||
// case 0b110001: // VWREDSUM
|
||||
default:
|
||||
throw new std::runtime_error("Unknown funct6 in get_funct");
|
||||
}
|
||||
else if(funct3 == OPMVV || funct3 == OPMVX)
|
||||
switch(funct6) {
|
||||
// case 0b000000: // VREDSUM
|
||||
// case 0b000001: // VREDAND
|
||||
// case 0b000010: // VREDOR
|
||||
// case 0b000011: // VREDXOR
|
||||
// case 0b000100: // VREDMINU
|
||||
// case 0b000101: // VREDMIN
|
||||
// case 0b000110: // VREDMAXU
|
||||
// case 0b000111: // VREDMAX
|
||||
// case 0b001110: // VSLID1EUP
|
||||
// case 0b001111: // VSLIDE1DOWN
|
||||
// case 0b010111: // VCOMPRESS
|
||||
@ -804,4 +794,68 @@ bool sat_vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl
|
||||
}
|
||||
return saturated;
|
||||
}
|
||||
template <typename dest_elem_t, typename src_elem_t>
|
||||
std::function<void(dest_elem_t&, src_elem_t)> get_red_funct(unsigned funct6, unsigned funct3) {
|
||||
if(funct3 == OPIVV || funct3 == OPIVX || funct3 == OPIVI)
|
||||
switch(funct6) {
|
||||
// case 0b110000: // VWREDSUMU
|
||||
// case 0b110001: // VWREDSUM
|
||||
default:
|
||||
throw new std::runtime_error("Unknown funct6 in get_funct");
|
||||
}
|
||||
else if(funct3 == OPMVV || funct3 == OPMVX)
|
||||
switch(funct6) {
|
||||
case 0b000000: // VREDSUM
|
||||
return [](dest_elem_t& running_total, src_elem_t vs2) { return running_total += vs2; };
|
||||
case 0b000001: // VREDAND
|
||||
return [](dest_elem_t& running_total, src_elem_t vs2) { return running_total &= vs2; };
|
||||
case 0b000010: // VREDOR
|
||||
return [](dest_elem_t& running_total, src_elem_t vs2) { return running_total |= vs2; };
|
||||
case 0b000011: // VREDXOR
|
||||
return [](dest_elem_t& running_total, src_elem_t vs2) { running_total ^= vs2; };
|
||||
case 0b000100: // VREDMINU
|
||||
return [](dest_elem_t& running_total, src_elem_t vs2) { running_total = std::min(running_total, vs2); };
|
||||
case 0b000101: // VREDMIN
|
||||
return [](dest_elem_t& running_total, src_elem_t vs2) {
|
||||
running_total =
|
||||
std::min(static_cast<std::make_signed_t<dest_elem_t>>(running_total), static_cast<std::make_signed_t<src_elem_t>>(vs2));
|
||||
};
|
||||
case 0b000110: // VREDMAXU
|
||||
return [](dest_elem_t& running_total, src_elem_t vs2) { running_total = std::max(running_total, vs2); };
|
||||
case 0b000111: // VREDMAX
|
||||
return [](dest_elem_t& running_total, src_elem_t vs2) {
|
||||
running_total =
|
||||
std::max(static_cast<std::make_signed_t<dest_elem_t>>(running_total), static_cast<std::make_signed_t<src_elem_t>>(vs2));
|
||||
};
|
||||
default:
|
||||
throw new std::runtime_error("Unknown funct6 in get_funct");
|
||||
}
|
||||
else
|
||||
throw new std::runtime_error("Unknown funct3 in get_funct");
|
||||
}
|
||||
template <unsigned VLEN, typename dest_elem_t, typename src_elem_t>
|
||||
void vector_red_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
|
||||
unsigned vs2, unsigned vs1) {
|
||||
if(vl == 0)
|
||||
return;
|
||||
uint64_t elem_count = VLEN * vtype.lmul() / vtype.sew();
|
||||
vmask_view mask_reg = read_vmask<VLEN>(V, elem_count);
|
||||
auto vs1_elem = get_vreg<VLEN, src_elem_t>(V, vs1, elem_count)[0];
|
||||
auto vs2_view = get_vreg<VLEN, src_elem_t>(V, vs2, elem_count);
|
||||
auto vd_view = get_vreg<VLEN, dest_elem_t>(V, vd, elem_count);
|
||||
auto fn = get_red_funct<dest_elem_t, src_elem_t>(funct6, funct3);
|
||||
dest_elem_t& running_total = {vs1_elem};
|
||||
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
|
||||
bool mask_active = vm ? 1 : mask_reg[idx];
|
||||
if(mask_active) {
|
||||
fn(running_total, vs2_view[idx]);
|
||||
}
|
||||
}
|
||||
vd_view[0] = running_total;
|
||||
// the tail is all elements of the destination register beyond the first one
|
||||
for(unsigned idx = 1; idx < VLEN / (vtype.sew() * RFS); idx++) {
|
||||
vd_view[idx] = vtype.vta() ? vd_view[idx] : vd_view[idx];
|
||||
}
|
||||
return;
|
||||
}
|
||||
} // namespace softvector
|
Loading…
x
Reference in New Issue
Block a user