//===-- VCIX.td - VCIX dialect operation definitions *- tablegen -*--------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // The file defines the basic operations for the VCIX dialect. // // The SiFive Vector Coprocessor Interface (VCIX) provides a flexible mechanism // to extend application processors with custom coprocessors and // variable-latency arithmetic units. The interface offers throughput comparable // to that of standard RISC-V vector instructions. To accelerate performance, // system designers may use VCIX as a low-latency, high-throughput interface to // a coprocessor // // https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software // //===----------------------------------------------------------------------===// #ifndef VCIXIR_OPS include "mlir/IR/OpBase.td" include "mlir/Dialect/LLVMIR/LLVMOpBase.td" //===----------------------------------------------------------------------===// // VCIX dialect definition. //===----------------------------------------------------------------------===// def VCIX_Dialect : Dialect { let name = "vcix"; let cppNamespace = "::mlir::vcix"; let dependentDialects = ["LLVM::LLVMDialect"]; let description = [{ The SiFive Vector Coprocessor Interface (VCIX) provides a flexible mechanism to extend application processors with custom coprocessors and variable-latency arithmetic units. The interface offers throughput comparable to that of standard RISC-V vector instructions. To accelerate performance, system designers may use VCIX as a low-latency, high-throughput interface to a coprocessor https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software }]; } // Special version for intrinsic version where int attr is zext to i32 or i64 // depending on xlen of the target. def VCIX_VectorOrScalar : AnyTypeOf<[LLVM_AnyVector, I<64>, I<32>, F<16>, F<32>, F<64>]>; def VCIX_OpcodeAttr : AnyAttrOf<[I32Attr, I64Attr]>; def VCIX_Register : AnyTypeOf<[I32, I64]>; def VCIX_ImmAttr : AnyAttrOf<[I32Attr, I64Attr]>; def VCIX_VL : AnyTypeOf<[I<64>, I<32>]>; class VCIX_Op traits = []> : LLVM_OpBase { } def VCIX_BinaryImmOp : VCIX_Op<"v.iv">, Results<(outs LLVM_AnyVector: $res)>, Arguments<(ins VCIX_OpcodeAttr: $opcode, LLVM_AnyVector: $vs2, VCIX_ImmAttr: $imm, Optional: $vl)> { let summary = "Binary VCIX operation with an immediate second operand"; let description = [{ Binary VCIX operation with an immediate second operand. Correponds to: |Mnemonic|funct6|vm|rs2|rs1|funct3|rd|Destination|Sources| |--|--|--|--|--|--|--|--|--| |sf.vc.v.iv|0010--|0|vs2|simm|011|vd|vector vd| simm[4:0] vector vs2| }]; string llvmBuilder = [{ llvm::Type *xlen =getXlenType($opcode, moduleTranslation); llvm::Value *opcodeConst = mlir::LLVM::detail::getLLVMConstant( xlen, $opcode, $_location, moduleTranslation); llvm::Value *immConst = mlir::LLVM::detail::getLLVMConstant( xlen, $imm, $_location, moduleTranslation); VectorType vt = mlir::cast(op.getResult().getType()); llvm::Value *vl = createVL(builder, $vl, vt, xlen, $_location, moduleTranslation); $res = createIntrinsicCall( builder, llvm::Intrinsic::riscv_sf_vc_v_iv_se, {opcodeConst, $vs2, immConst, vl}, {$_resultType, xlen, $vs2->getType(), xlen, xlen}); }]; } def VCIX_BinaryOp : VCIX_Op<"v.sv">, Results<(outs LLVM_AnyVector: $res)>, Arguments<(ins VCIX_OpcodeAttr: $opcode, LLVM_AnyVector: $vs2, VCIX_VectorOrScalar: $op, Optional: $vl)> { let summary = "Binary VCIX operation"; let description = [{ Binary VCIX operation with an integer scalar, or floating pointer scalar or vector second operand. Correponds to: |Mnemonic|funct6|vm|rs2|rs1|funct3|rd|Destination| Sources| |--|--|--|--|--|--|--|--|--|--| |sf.vc.v.vv|0010--|0|vs2|vs1|000|vd|vector vd|vector vs1, vector vs| |sf.vc.v.xv|0010--|0|vs2|xs1|100|vd|vector vd|scalar xs1, vector vs2| |sf.vc.v.fv|0010--|0|vs2|fs1|101|vd|vector vd|scalar fs1, vector vs2| }]; string llvmBuilder = [{ llvm::Type *xlen = getXlenType($opcode, moduleTranslation); llvm::Value *opcodeConst = mlir::LLVM::detail::getLLVMConstant( xlen, $opcode, $_location, moduleTranslation); llvm::Intrinsic::ID id; llvm::Type *opType = $op->getType(); if (opType->isVectorTy()) { id = llvm::Intrinsic::riscv_sf_vc_v_vv_se; } else if (opType->isIntegerTy()) { id = llvm::Intrinsic::riscv_sf_vc_v_xv_se; } else { id = llvm::Intrinsic::riscv_sf_vc_v_fv_se; } VectorType vt = mlir::cast(op.getResult().getType()); llvm::Value *vl = createVL(builder, $vl, vt, xlen, $_location, moduleTranslation); $res = createIntrinsicCall( builder, id, {opcodeConst, $vs2, $op, vl}, {$_resultType, xlen, $vs2->getType(), $op->getType(), xlen}); }]; } #endif // VCIXIR_OPS