adds vector_imm instructions to vector_functions, makes size of all involved registers a template parameter
This commit is contained in:
		@@ -224,6 +224,70 @@ if(vector != null) {%>
 | 
				
			|||||||
                throw new std::runtime_error("Unsupported sew bit value");
 | 
					                throw new std::runtime_error("Unsupported sew bit value");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    void vector_vector_wv(uint8_t* V, uint8_t funct, 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:
 | 
				
			||||||
 | 
					                softvector::vector_vector_op<${vlen}, uint16_t, uint8_t>(V, funct, vl, vstart, vtype, vm, vs2, vs1, vd);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0b001:
 | 
				
			||||||
 | 
					                softvector::vector_vector_op<${vlen}, uint32_t, uint16_t>(V, funct, vl, vstart, vtype, vm, vs2, vs1, vd);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0b010:
 | 
				
			||||||
 | 
					                softvector::vector_vector_op<${vlen}, uint64_t, uint32_t>(V, funct, vl, vstart, vtype, vm, vs2, vs1, vd);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0b011: // would widen to 128 bits
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                throw new std::runtime_error("Unsupported sew bit value");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void vector_imm_wv(uint8_t* V, uint8_t funct, 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:
 | 
				
			||||||
 | 
					                softvector::vector_imm_op<${vlen}, uint16_t, uint8_t>(V, funct, vl, vstart, vtype, vm, vs2, imm, vd);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0b001:
 | 
				
			||||||
 | 
					                softvector::vector_imm_op<${vlen}, uint32_t, uint16_t>(V, funct, vl, vstart, vtype, vm, vs2, imm, vd);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0b010:
 | 
				
			||||||
 | 
					                softvector::vector_imm_op<${vlen}, uint64_t, uint32_t>(V, funct, vl, vstart, vtype, vm, vs2, imm, vd);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0b011: // would widen to 128 bits
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                throw new std::runtime_error("Unsupported sew bit value");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void vector_vector_ww(uint8_t* V, uint8_t funct, 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:
 | 
				
			||||||
 | 
					                softvector::vector_vector_op<${vlen}, uint16_t, uint16_t, uint8_t>(V, funct, vl, vstart, vtype, vm, vs2, vs1, vd);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0b001:
 | 
				
			||||||
 | 
					                softvector::vector_vector_op<${vlen}, uint32_t, uint32_t, uint16_t>(V, funct, vl, vstart, vtype, vm, vs2, vs1, vd);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0b010:
 | 
				
			||||||
 | 
					                softvector::vector_vector_op<${vlen}, uint64_t, uint64_t, uint32_t>(V, funct, vl, vstart, vtype, vm, vs2, vs1, vd);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0b011: // would widen to 128 bits
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                throw new std::runtime_error("Unsupported sew bit value");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void vector_imm_ww(uint8_t* V, uint8_t funct, 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:
 | 
				
			||||||
 | 
					                softvector::vector_imm_op<${vlen}, uint16_t, uint16_t, uint8_t>(V, funct, vl, vstart, vtype, vm, vs2, imm, vd);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0b001:
 | 
				
			||||||
 | 
					                softvector::vector_imm_op<${vlen}, uint32_t, uint32_t, uint16_t>(V, funct, vl, vstart, vtype, vm, vs2, imm, vd);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0b010:
 | 
				
			||||||
 | 
					                softvector::vector_imm_op<${vlen}, uint64_t, uint64_t, uint32_t>(V, funct, vl, vstart, vtype, vm, vs2, imm, vd);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0b011: // would widen to 128 bits
 | 
				
			||||||
 | 
					            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};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,9 +71,12 @@ uint64_t vector_load_store_index(void* core, std::function<bool(void*, uint64_t,
 | 
				
			|||||||
                                 uint16_t VLEN, uint8_t XLEN, uint8_t addressed_register, uint8_t index_register, uint64_t base_addr,
 | 
					                                 uint16_t VLEN, uint8_t XLEN, uint8_t addressed_register, uint8_t index_register, uint64_t base_addr,
 | 
				
			||||||
                                 uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, uint8_t elem_size_byte, uint64_t elem_count,
 | 
					                                 uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, uint8_t elem_size_byte, uint64_t elem_count,
 | 
				
			||||||
                                 uint8_t segment_size, bool ordered);
 | 
					                                 uint8_t segment_size, bool ordered);
 | 
				
			||||||
template <unsigned VLEN, typename 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, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vs2, unsigned vs1,
 | 
					void vector_vector_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vs2, unsigned vs1,
 | 
				
			||||||
                      unsigned vd);
 | 
					                      unsigned vd);
 | 
				
			||||||
 | 
					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, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vs2,
 | 
				
			||||||
 | 
					                   typename std::make_signed<src1_elem_t>::type imm, unsigned vd);
 | 
				
			||||||
} // namespace softvector
 | 
					} // namespace softvector
 | 
				
			||||||
#include "vm/vector_functions.hpp"
 | 
					#include "vm/vector_functions.hpp"
 | 
				
			||||||
#endif /* _VM_VECTOR_FUNCTIONS_H_ */
 | 
					#endif /* _VM_VECTOR_FUNCTIONS_H_ */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,49 +64,50 @@ template <unsigned VLEN> vmask_view read_vmask(uint8_t* V, uint16_t elem_count,
 | 
				
			|||||||
    assert(mask_start + elem_count / 8 <= V + VLEN * RFS / 8);
 | 
					    assert(mask_start + elem_count / 8 <= V + VLEN * RFS / 8);
 | 
				
			||||||
    return {mask_start, elem_count};
 | 
					    return {mask_start, elem_count};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
template <typename elem_t> std::function<elem_t(elem_t, elem_t)> get_funct(unsigned 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(src2_elem_t, src1_elem_t)> get_funct(unsigned funct) {
 | 
				
			||||||
    switch(funct) {
 | 
					    switch(funct) {
 | 
				
			||||||
    case 0b000000: {
 | 
					    case 0b000000: // VADD
 | 
				
			||||||
        // VADD
 | 
					    case 0b110000: // VWADDU
 | 
				
			||||||
        return [](elem_t vs2, elem_t vs1) { return vs2 + vs1; };
 | 
					    case 0b110100: // VWADDU.W
 | 
				
			||||||
    }
 | 
					        return [](src2_elem_t vs2, src1_elem_t vs1) { return vs2 + vs1; };
 | 
				
			||||||
    case 0b000010: {
 | 
					    case 0b000010: // VSUB
 | 
				
			||||||
        // VSUB
 | 
					    case 0b110010: // VWSUBU
 | 
				
			||||||
    }
 | 
					    case 0b110110: // VWSUBU.W
 | 
				
			||||||
    case 0b000100: {
 | 
					        return [](src2_elem_t vs2, src1_elem_t vs1) { return vs2 - vs1; };
 | 
				
			||||||
        // VMINU
 | 
					    case 0b000011: // VRSUB
 | 
				
			||||||
    }
 | 
					        return [](src2_elem_t vs2, src1_elem_t vs1) { return vs1 - vs2; };
 | 
				
			||||||
    case 0b000101: {
 | 
					    case 0b001001: // VAND
 | 
				
			||||||
        // VMIN
 | 
					        return [](src2_elem_t vs2, src1_elem_t vs1) { return vs1 & vs2; };
 | 
				
			||||||
    }
 | 
					    case 0b001010: // VOR
 | 
				
			||||||
    case 0b000110: {
 | 
					        return [](src2_elem_t vs2, src1_elem_t vs1) { return vs1 | vs2; };
 | 
				
			||||||
        // VMAXU
 | 
					    case 0b001011: // VXOR
 | 
				
			||||||
    }
 | 
					        return [](src2_elem_t vs2, src1_elem_t vs1) { return vs1 ^ vs2; };
 | 
				
			||||||
    case 0b000111: {
 | 
					    case 0b110001: // VWADD
 | 
				
			||||||
        // VMAX
 | 
					    case 0b110101: // VWADD.W
 | 
				
			||||||
    }
 | 
					        return [](src2_elem_t vs2, src1_elem_t vs1) {
 | 
				
			||||||
    case 0b001001: {
 | 
					            return static_cast<typename std::make_signed_t<dest_elem_t>>(static_cast<typename std::make_signed_t<src2_elem_t>>(vs2) +
 | 
				
			||||||
        // VAND
 | 
					                                                                         static_cast<typename std::make_signed_t<src1_elem_t>>(vs1));
 | 
				
			||||||
    }
 | 
					        };
 | 
				
			||||||
    case 0b001010: {
 | 
					    case 0b110011: // VWSUB
 | 
				
			||||||
        // VOR
 | 
					    case 0b110111: // VWSUB.W
 | 
				
			||||||
    }
 | 
					        return [](src2_elem_t vs2, src1_elem_t vs1) {
 | 
				
			||||||
    case 0b001011: {
 | 
					            return static_cast<typename std::make_signed_t<dest_elem_t>>(static_cast<typename std::make_signed_t<src2_elem_t>>(vs2) -
 | 
				
			||||||
        // VXOR
 | 
					                                                                         static_cast<typename std::make_signed_t<src1_elem_t>>(vs1));
 | 
				
			||||||
    }
 | 
					        };
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        throw new std::runtime_error("Uknown funct in get_funct");
 | 
					        throw new std::runtime_error("Uknown funct in get_funct");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
template <unsigned VLEN, typename 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, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vs2, unsigned vs1,
 | 
					void vector_vector_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vs2, unsigned vs1,
 | 
				
			||||||
                      unsigned vd) {
 | 
					                      unsigned vd) {
 | 
				
			||||||
    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, elem_t>(V, vs1, elem_count);
 | 
					    auto vs1_view = get_vreg<VLEN, src1_elem_t>(V, vs1, elem_count);
 | 
				
			||||||
    auto vs2_view = get_vreg<VLEN, elem_t>(V, vs2, elem_count);
 | 
					    auto vs2_view = get_vreg<VLEN, src2_elem_t>(V, vs2, elem_count);
 | 
				
			||||||
    auto vd_view = get_vreg<VLEN, elem_t>(V, vd, elem_count);
 | 
					    auto vd_view = get_vreg<VLEN, dest_elem_t>(V, vd, elem_count);
 | 
				
			||||||
    auto fn = get_funct<elem_t>(funct6);
 | 
					    auto fn = get_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6);
 | 
				
			||||||
    // 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)
 | 
				
			||||||
    for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
 | 
					    for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
 | 
				
			||||||
@@ -119,20 +120,20 @@ void vector_vector_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vstart,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    // elements w/ index larger than elem_count are in the tail (fractional LMUL)
 | 
					    // elements w/ index larger than elem_count are in the tail (fractional LMUL)
 | 
				
			||||||
    // elements w/ index larger than vl are in the tail
 | 
					    // elements w/ index larger than vl are in the tail
 | 
				
			||||||
    unsigned maximum_elems = VLEN * vtype.lmul() / (sizeof(elem_t) * 8);
 | 
					    unsigned maximum_elems = VLEN * vtype.lmul() / (sizeof(dest_elem_t) * 8);
 | 
				
			||||||
    for(unsigned idx = std::min(elem_count, vl); idx < maximum_elems; idx++) {
 | 
					    for(unsigned idx = std::min(elem_count, vl); idx < maximum_elems; idx++) {
 | 
				
			||||||
        vd_view[idx] = vtype.vta() ? vd_view[idx] : vd_view[idx];
 | 
					        vd_view[idx] = vtype.vta() ? vd_view[idx] : vd_view[idx];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
template <unsigned VLEN, typename 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, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vs2,
 | 
					void vector_imm_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vs2,
 | 
				
			||||||
                   typename std::make_signed<elem_t>::type imm, unsigned vd) {
 | 
					                   typename std::make_signed<src1_elem_t>::type imm, unsigned vd) {
 | 
				
			||||||
    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, elem_t>(V, vs2, elem_count);
 | 
					    auto vs2_view = get_vreg<VLEN, src2_elem_t>(V, vs2, elem_count);
 | 
				
			||||||
    auto vd_view = get_vreg<VLEN, elem_t>(V, vd, elem_count);
 | 
					    auto vd_view = get_vreg<VLEN, dest_elem_t>(V, vd, elem_count);
 | 
				
			||||||
    auto fn = get_funct<elem_t>(funct6);
 | 
					    auto fn = get_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6);
 | 
				
			||||||
    // 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)
 | 
				
			||||||
    for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
 | 
					    for(unsigned idx = vstart; idx < std::min(elem_count, vl); idx++) {
 | 
				
			||||||
@@ -145,7 +146,7 @@ void vector_imm_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vstart, vt
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    // elements w/ index larger than elem_count are in the tail (fractional LMUL)
 | 
					    // elements w/ index larger than elem_count are in the tail (fractional LMUL)
 | 
				
			||||||
    // elements w/ index larger than vl are in the tail
 | 
					    // elements w/ index larger than vl are in the tail
 | 
				
			||||||
    unsigned maximum_elems = VLEN * vtype.lmul() / (sizeof(elem_t) * 8);
 | 
					    unsigned maximum_elems = VLEN * vtype.lmul() / (sizeof(dest_elem_t) * 8);
 | 
				
			||||||
    for(unsigned idx = std::min(elem_count, vl); idx < maximum_elems; idx++) {
 | 
					    for(unsigned idx = std::min(elem_count, vl); idx < maximum_elems; idx++) {
 | 
				
			||||||
        vd_view[idx] = vtype.vta() ? vd_view[idx] : vd_view[idx];
 | 
					        vd_view[idx] = vtype.vta() ? vd_view[idx] : vd_view[idx];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user