1//===-- VCIX.td - VCIX dialect operation definitions *- tablegen -*--------===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// The file defines the basic operations for the VCIX dialect. 9// 10// The SiFive Vector Coprocessor Interface (VCIX) provides a flexible mechanism 11// to extend application processors with custom coprocessors and 12// variable-latency arithmetic units. The interface offers throughput comparable 13// to that of standard RISC-V vector instructions. To accelerate performance, 14// system designers may use VCIX as a low-latency, high-throughput interface to 15// a coprocessor 16// 17// https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software 18// 19//===----------------------------------------------------------------------===// 20 21#ifndef VCIXIR_OPS 22 23include "mlir/IR/OpBase.td" 24include "mlir/Dialect/LLVMIR/LLVMOpBase.td" 25 26//===----------------------------------------------------------------------===// 27// VCIX dialect definition. 28//===----------------------------------------------------------------------===// 29 30def VCIX_Dialect : Dialect { 31 let name = "vcix"; 32 let cppNamespace = "::mlir::vcix"; 33 let dependentDialects = ["LLVM::LLVMDialect"]; 34 let description = [{ 35 The SiFive Vector Coprocessor Interface (VCIX) provides a flexible mechanism 36 to extend application processors with custom coprocessors and 37 variable-latency arithmetic units. The interface offers throughput comparable 38 to that of standard RISC-V vector instructions. To accelerate performance, 39 system designers may use VCIX as a low-latency, high-throughput interface to 40 a coprocessor 41 42 https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software 43 }]; 44} 45 46// Special version for intrinsic version where int attr is zext to i32 or i64 47// depending on xlen of the target. 48def VCIX_VectorOrScalar 49 : AnyTypeOf<[LLVM_AnyVector, I<64>, I<32>, F<16>, F<32>, F<64>]>; 50def VCIX_OpcodeAttr : AnyAttrOf<[I32Attr, I64Attr]>; 51def VCIX_Register : AnyTypeOf<[I32, I64]>; 52def VCIX_ImmAttr : AnyAttrOf<[I32Attr, I64Attr]>; 53def VCIX_VL : AnyTypeOf<[I<64>, I<32>]>; 54 55class VCIX_Op<string mnemonic, list<Trait> traits = []> 56 : LLVM_OpBase<VCIX_Dialect, mnemonic, traits> { 57} 58 59def VCIX_BinaryImmOp : VCIX_Op<"v.iv">, 60 Results<(outs LLVM_AnyVector: $res)>, 61 Arguments<(ins VCIX_OpcodeAttr: $opcode, 62 LLVM_AnyVector: $vs2, 63 VCIX_ImmAttr: $imm, 64 Optional<VCIX_VL>: $vl)> { 65 let summary = "Binary VCIX operation with an immediate second operand"; 66 let description = [{ 67 Binary VCIX operation with an immediate second operand. 68 69 Correponds to: 70 |Mnemonic|funct6|vm|rs2|rs1|funct3|rd|Destination|Sources| 71 |--|--|--|--|--|--|--|--|--| 72 |sf.vc.v.iv|0010--|0|vs2|simm|011|vd|vector vd| simm[4:0] vector vs2| 73 }]; 74 75 string llvmBuilder = [{ 76 llvm::Type *xlen =getXlenType($opcode, moduleTranslation); 77 llvm::Value *opcodeConst = mlir::LLVM::detail::getLLVMConstant( 78 xlen, $opcode, $_location, moduleTranslation); 79 llvm::Value *immConst = mlir::LLVM::detail::getLLVMConstant( 80 xlen, $imm, $_location, moduleTranslation); 81 VectorType vt = mlir::cast<VectorType>(op.getResult().getType()); 82 llvm::Value *vl = 83 createVL(builder, $vl, vt, xlen, $_location, moduleTranslation); 84 $res = createIntrinsicCall( 85 builder, llvm::Intrinsic::riscv_sf_vc_v_iv_se, 86 {opcodeConst, $vs2, immConst, vl}, 87 {$_resultType, xlen, $vs2->getType(), xlen, xlen}); 88 }]; 89} 90 91def VCIX_BinaryOp : VCIX_Op<"v.sv">, 92 Results<(outs LLVM_AnyVector: $res)>, 93 Arguments<(ins VCIX_OpcodeAttr: $opcode, 94 LLVM_AnyVector: $vs2, 95 VCIX_VectorOrScalar: $op, 96 Optional<VCIX_VL>: $vl)> { 97 let summary = "Binary VCIX operation"; 98 let description = [{ 99 Binary VCIX operation with an integer scalar, or floating pointer scalar or 100 vector second operand. 101 102 Correponds to: 103 |Mnemonic|funct6|vm|rs2|rs1|funct3|rd|Destination| Sources| 104 |--|--|--|--|--|--|--|--|--|--| 105 |sf.vc.v.vv|0010--|0|vs2|vs1|000|vd|vector vd|vector vs1, vector vs| 106 |sf.vc.v.xv|0010--|0|vs2|xs1|100|vd|vector vd|scalar xs1, vector vs2| 107 |sf.vc.v.fv|0010--|0|vs2|fs1|101|vd|vector vd|scalar fs1, vector vs2| 108 }]; 109 110 string llvmBuilder = [{ 111 llvm::Type *xlen = getXlenType($opcode, moduleTranslation); 112 llvm::Value *opcodeConst = mlir::LLVM::detail::getLLVMConstant( 113 xlen, $opcode, $_location, moduleTranslation); 114 llvm::Intrinsic::ID id; 115 llvm::Type *opType = $op->getType(); 116 if (opType->isVectorTy()) { 117 id = llvm::Intrinsic::riscv_sf_vc_v_vv_se; 118 } else if (opType->isIntegerTy()) { 119 id = llvm::Intrinsic::riscv_sf_vc_v_xv_se; 120 } else { 121 id = llvm::Intrinsic::riscv_sf_vc_v_fv_se; 122 } 123 VectorType vt = mlir::cast<VectorType>(op.getResult().getType()); 124 llvm::Value *vl = 125 createVL(builder, $vl, vt, xlen, $_location, moduleTranslation); 126 $res = createIntrinsicCall( 127 builder, id, {opcodeConst, $vs2, $op, vl}, 128 {$_resultType, xlen, $vs2->getType(), $op->getType(), xlen}); 129 }]; 130} 131 132#endif // VCIXIR_OPS 133