adds merge and move instructions
This commit is contained in:
parent
6852d1d299
commit
77807fec01
@ -385,6 +385,34 @@ if(vector != null) {%>
|
|||||||
throw new std::runtime_error("Unsupported sew bit value");
|
throw new std::runtime_error("Unsupported sew bit value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void vector_vector_merge(uint8_t* V, 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_vector_op<${vlen}, uint8_t>(V, 0, 0, vl, vstart, vtype, vm, vd, vs2, vs1, softvector::carry_t::NO_CARRY, true);
|
||||||
|
case 0b001:
|
||||||
|
return softvector::vector_vector_op<${vlen}, uint16_t>(V, 0, 0, vl, vstart, vtype, vm, vd, vs2, vs1, softvector::carry_t::NO_CARRY, true);
|
||||||
|
case 0b010:
|
||||||
|
return softvector::vector_vector_op<${vlen}, uint32_t>(V, 0, 0, vl, vstart, vtype, vm, vd, vs2, vs1, softvector::carry_t::NO_CARRY, true);
|
||||||
|
case 0b011:
|
||||||
|
return softvector::vector_vector_op<${vlen}, uint64_t>(V, 0, 0, vl, vstart, vtype, vm, vd, vs2, vs1, softvector::carry_t::NO_CARRY, true);
|
||||||
|
default:
|
||||||
|
throw new std::runtime_error("Unsupported sew bit value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void vector_imm_merge(uint8_t* V, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, int64_t imm, uint8_t sew_val){
|
||||||
|
switch(sew_val){
|
||||||
|
case 0b000:
|
||||||
|
return softvector::vector_imm_op<${vlen}, uint8_t>(V, 0, 0, vl, vstart, vtype, vm, vd, vs2, imm, softvector::carry_t::NO_CARRY, true);
|
||||||
|
case 0b001:
|
||||||
|
return softvector::vector_imm_op<${vlen}, uint16_t>(V, 0, 0, vl, vstart, vtype, vm, vd, vs2, imm, softvector::carry_t::NO_CARRY, true);
|
||||||
|
case 0b010:
|
||||||
|
return softvector::vector_imm_op<${vlen}, uint32_t>(V, 0, 0, vl, vstart, vtype, vm, vd, vs2, imm, softvector::carry_t::NO_CARRY, true);
|
||||||
|
case 0b011:
|
||||||
|
return softvector::vector_imm_op<${vlen}, uint64_t>(V, 0, 0, vl, vstart, vtype, vm, vd, vs2, imm, softvector::carry_t::NO_CARRY, true);
|
||||||
|
default:
|
||||||
|
throw new std::runtime_error("Unsupported sew bit value");
|
||||||
|
}
|
||||||
|
}
|
||||||
<%}%>
|
<%}%>
|
||||||
uint64_t fetch_count{0};
|
uint64_t fetch_count{0};
|
||||||
uint64_t tval{0};
|
uint64_t tval{0};
|
||||||
|
@ -74,10 +74,10 @@ uint64_t vector_load_store_index(void* core, std::function<bool(void*, uint64_t,
|
|||||||
uint8_t segment_size, bool ordered);
|
uint8_t segment_size, bool ordered);
|
||||||
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = src2_elem_t>
|
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = src2_elem_t>
|
||||||
void vector_vector_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
|
void vector_vector_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, carry_t carry = carry_t::NO_CARRY);
|
unsigned vs2, unsigned vs1, carry_t carry = carry_t::NO_CARRY, bool merge = false);
|
||||||
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = src2_elem_t>
|
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = src2_elem_t>
|
||||||
void vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
|
void vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
|
||||||
unsigned vs2, typename std::make_signed<src1_elem_t>::type imm, carry_t carry = carry_t::NO_CARRY);
|
unsigned vs2, typename std::make_signed<src1_elem_t>::type imm, carry_t carry = carry_t::NO_CARRY, bool merge = false);
|
||||||
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t>
|
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t = dest_elem_t>
|
||||||
void vector_unary_op(uint8_t* V, unsigned unary_op, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2);
|
void vector_unary_op(uint8_t* V, unsigned unary_op, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2);
|
||||||
template <unsigned VLEN, typename elem_t>
|
template <unsigned VLEN, typename elem_t>
|
||||||
|
@ -131,7 +131,6 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
|
|||||||
return static_cast<std::make_signed_t<dest_elem_t>>(static_cast<std::make_signed_t<src2_elem_t>>(vs2) -
|
return static_cast<std::make_signed_t<dest_elem_t>>(static_cast<std::make_signed_t<src2_elem_t>>(vs2) -
|
||||||
static_cast<std::make_signed_t<src1_elem_t>>(vs1));
|
static_cast<std::make_signed_t<src1_elem_t>>(vs1));
|
||||||
};
|
};
|
||||||
// case 0b010111: // VMERGE / VMV
|
|
||||||
// case 0b100000: // VSADDU
|
// case 0b100000: // VSADDU
|
||||||
// case 0b100001: // VSADD
|
// case 0b100001: // VSADD
|
||||||
// case 0b100010: // VSSUBU
|
// case 0b100010: // VSSUBU
|
||||||
@ -308,9 +307,17 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
|
|||||||
else
|
else
|
||||||
throw new std::runtime_error("Unknown funct3 in get_funct");
|
throw new std::runtime_error("Unknown funct3 in get_funct");
|
||||||
}
|
}
|
||||||
|
template <typename dest_elem_t, typename src2_elem_t = dest_elem_t, typename src1_elem_t = dest_elem_t>
|
||||||
|
std::function<dest_elem_t(bool, dest_elem_t, src2_elem_t, src1_elem_t)> get_merge_funct(bool vm) {
|
||||||
|
if(vm) { // VMV
|
||||||
|
return [](bool vm, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs1; };
|
||||||
|
} else { // VMERGE
|
||||||
|
return [](bool vm, dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vm ? vs1 : vs2; };
|
||||||
|
}
|
||||||
|
};
|
||||||
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t, typename src1_elem_t>
|
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t, typename src1_elem_t>
|
||||||
void vector_vector_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
|
void vector_vector_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, carry_t carry) {
|
unsigned vs2, unsigned vs1, carry_t carry, bool merge) {
|
||||||
uint64_t elem_count = VLEN * vtype.lmul() / vtype.sew();
|
uint64_t elem_count = VLEN * vtype.lmul() / vtype.sew();
|
||||||
vmask_view mask_reg = read_vmask<VLEN>(V, elem_count);
|
vmask_view mask_reg = read_vmask<VLEN>(V, elem_count);
|
||||||
auto vs1_view = get_vreg<VLEN, src1_elem_t>(V, vs1, elem_count);
|
auto vs1_view = get_vreg<VLEN, src1_elem_t>(V, vs1, elem_count);
|
||||||
@ -319,7 +326,16 @@ void vector_vector_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl,
|
|||||||
auto fn = get_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
|
auto fn = get_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
|
||||||
// elements w/ index smaller than vstart are in the prestart and get skipped
|
// elements w/ index smaller than vstart are in the prestart and get skipped
|
||||||
// body is from vstart to min(elem_count, vl)
|
// body is from vstart to min(elem_count, vl)
|
||||||
if(carry == carry_t::NO_CARRY) {
|
if(merge) {
|
||||||
|
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
|
||||||
|
auto merge_fn = get_merge_funct<dest_elem_t, src2_elem_t, src1_elem_t>(vm);
|
||||||
|
auto cur_mask = mask_reg[idx];
|
||||||
|
auto vd_val = vd_view[idx];
|
||||||
|
auto vs2_val = vs2_view[idx];
|
||||||
|
auto vs1_val = vs1_view[idx];
|
||||||
|
vd_view[idx] = merge_fn(mask_reg[idx], vd_view[idx], vs2_view[idx], vs1_view[idx]);
|
||||||
|
}
|
||||||
|
} else if(carry == carry_t::NO_CARRY) {
|
||||||
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
|
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
|
||||||
bool mask_active = vm ? 1 : mask_reg[idx];
|
bool mask_active = vm ? 1 : mask_reg[idx];
|
||||||
if(mask_active) {
|
if(mask_active) {
|
||||||
@ -347,7 +363,7 @@ void vector_vector_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl,
|
|||||||
}
|
}
|
||||||
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t, typename src1_elem_t>
|
template <unsigned VLEN, typename dest_elem_t, typename src2_elem_t, typename src1_elem_t>
|
||||||
void vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
|
void vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd,
|
||||||
unsigned vs2, typename std::make_signed<src1_elem_t>::type imm, carry_t carry) {
|
unsigned vs2, typename std::make_signed<src1_elem_t>::type imm, carry_t carry, bool merge) {
|
||||||
uint64_t elem_count = VLEN * vtype.lmul() / vtype.sew();
|
uint64_t elem_count = VLEN * vtype.lmul() / vtype.sew();
|
||||||
vmask_view mask_reg = read_vmask<VLEN>(V, elem_count);
|
vmask_view mask_reg = read_vmask<VLEN>(V, elem_count);
|
||||||
auto vs2_view = get_vreg<VLEN, src2_elem_t>(V, vs2, elem_count);
|
auto vs2_view = get_vreg<VLEN, src2_elem_t>(V, vs2, elem_count);
|
||||||
@ -355,7 +371,15 @@ void vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, ui
|
|||||||
auto fn = get_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
|
auto fn = get_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
|
||||||
// elements w/ index smaller than vstart are in the prestart and get skipped
|
// elements w/ index smaller than vstart are in the prestart and get skipped
|
||||||
// body is from vstart to min(elem_count, vl)
|
// body is from vstart to min(elem_count, vl)
|
||||||
if(carry == carry_t::NO_CARRY) {
|
if(merge) {
|
||||||
|
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
|
||||||
|
auto cur_mask = mask_reg[idx];
|
||||||
|
auto vd_val = vd_view[idx];
|
||||||
|
auto vs2_val = vs2_view[idx];
|
||||||
|
auto merge_fn = get_merge_funct<dest_elem_t, src2_elem_t, src1_elem_t>(vm);
|
||||||
|
vd_view[idx] = merge_fn(mask_reg[idx], vd_view[idx], vs2_view[idx], imm);
|
||||||
|
}
|
||||||
|
} else if(carry == carry_t::NO_CARRY) {
|
||||||
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
|
for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
|
||||||
bool mask_active = vm ? 1 : mask_reg[idx];
|
bool mask_active = vm ? 1 : mask_reg[idx];
|
||||||
if(mask_active) {
|
if(mask_active) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user