Rocket-chip-RoCC(4)--software

ROCC软件代码介绍

  • 前情提要:
    需要注意的是custom0~3均采用R类指令格式。RISC-V各指令类别如下图所示。
    在这里插入图片描述

  • mstatus的XS域
    需要打开mstatus的XS域。
    https://blog.csdn.net/a_weiming/article/details/111600428
    我是在底层汇编*.S文件中打开的,代码如下:
    其中MSTATUS_XS在encoding.h有定义。

 # enable accelerator if present
  li t0, MSTATUS_XS
  csrs mstatus, t0
  • ROCC的底层汇编
    我这里有两个版本,一个是很久的,另一个是较新的,较新的需要gcc支持某些特定的语法,例如.inst,我的gcc比较旧,所以使用旧的版本。新旧都是IBM开源在github上的。
    https://github.com/IBM/rocc-software
  • 旧版本代码:
// Copyright 2018 IBM
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ROCC_SOFTWARE_SRC_XCUSTOM_H_
#define ROCC_SOFTWARE_SRC_XCUSTOM_H_

#define STR1(x) #x
#ifndef STR
#define STR(x) STR1(x)
#endif
#define EXTRACT(a, size, offset) (((~(~0 << size) << offset) & a) >> offset)

// rd = rs2[offset + size - 1 : offset]
// rs1 is clobbered
// rs2 is left intact
#define EXTRACT_RAW(rd, rs1, rs2, size, offset) \
  not x ## rs1, x0;                             \
  slli x ## rs1, x ## rs1, size;                \
  not x ## rs1, x ## rs1;                       \
  slli x ## rs1, x ## rs1, offset;              \
  and x ## rd, x ## rs1, x ## rs2;              \
  srai x ## rd, x ## rd, offset;

#定制指令的opcode定义
#define XCUSTOM_OPCODE(x) XCUSTOM_OPCODE_ ## x
#define XCUSTOM_OPCODE_0 0b0001011
#define XCUSTOM_OPCODE_1 0b0101011
#define XCUSTOM_OPCODE_2 0b1011011
#define XCUSTOM_OPCODE_3 0b1111011

#R指令的格式,x为选择的定制指令编号,如0/1/2/3
#define XCUSTOM(x, rd, rs1, rs2, funct)         \
  XCUSTOM_OPCODE(x)                   |         \
  (rd                   << (7))       |         \
  (0x3                  << (7+5))     |         \
  ((rd != 0) & 1        << (7+5+2))   |         \
  (rs1                  << (7+5+3))   |         \
  (rs2                  << (7+5+3+5)) |         \
  (EXTRACT(funct, 7, 0) << (7+5+3+5+5))

#定义ROCC_INSTRUCTION_RAW_R_R_R()调用.word XCUSTOM()
#define ROCC_INSTRUCTION_RAW_R_R_R(x, rd, rs1, rs2, funct)      \
  .word XCUSTOM(x, ## rd, ## rs1, ## rs2, funct)

// Standard macro that passes rd, rs1, and rs2 via registers
#define ROCC_INSTRUCTION(x, rd, rs1, rs2, funct)                \
  ROCC_INSTRUCTION_R_R_R(x, rd, rs1, rs2, funct, 10, 11, 12)

// rd, rs1, and rs2 are data
// rd_n, rs1_n, and rs2_n are the register numbers to use
#define ROCC_INSTRUCTION_R_R_R(x, rd, rs1, rs2, funct, rd_n, rs1_n, rs2_n) \
  {                                                                     \
    register uint64_t rd_  asm ("x" # rd_n);                            \
    register uint64_t rs1_ asm ("x" # rs1_n) = (uint64_t) rs1;          \
    register uint64_t rs2_ asm ("x" # rs2_n) = (uint64_t) rs2;          \
    asm volatile (                                                      \
        ".word " STR(XCUSTOM(x, rd_n, rs1_n, rs2_n, funct)) "\n\t"      \
        : "=r" (rd_)                                                    \
        : [_rs1] "r" (rs1_), [_rs2] "r" (rs2_));                        \
    rd = rd_;                                                           \
  }

#define ROCC_INSTRUCTION_0_R_R(x, rs1, rs2, funct, rs1_n, rs2_n)  \
  {                                                               \
    register uint64_t rs1_ asm ("x" # rs1_n) = (uint64_t) rs1;    \
    register uint64_t rs2_ asm ("x" # rs2_n) = (uint64_t) rs2;    \
    asm volatile (                                                \
        ".word " STR(XCUSTOM(x, 0, rs1_n, rs2_n, funct)) "\n\t"   \
        :: [_rs1] "r" (rs1_), [_rs2] "r" (rs2_));                 \
  }

// [TODO] fix these to align with the above approach
// Macro to pass rs2_ as an immediate
/*
#define ROCC_INSTRUCTION_R_R_I(XCUSTOM_, rd_, rs1_, rs2_, funct_) \
  asm volatile (XCUSTOM_" %[rd], %[rs1], %[rs2], %[funct]"        \
                : [rd] "=r" (rd_)                                 \
                : [rs1] "r" (rs1_), [rs2] "i" (rs2_), [funct] "i" (funct_))

// Macro to pass rs1_ and rs2_ as immediates
#define ROCC_INSTRUCTION_R_I_I(XCUSTOM_, rd_, rs1_, rs2_, funct_) \
  asm volatile (XCUSTOM_" %[rd], %[rs1], %[rs2], %[funct]"        \
                : [rd] "=r" (rd_)                                 \
                : [rs1] "i" (rs1_), [rs2] "i" (rs2_), [funct] "i" (funct_))
*/

#endif  // ROCC_SOFTWARE_SRC_XCUSTOM_H_
  • 新版代码:
// Copyright 2018--2020 IBM
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ROCC_SOFTWARE_SRC_XCUSTOM_H_
#define ROCC_SOFTWARE_SRC_XCUSTOM_H_

#define STR1(x) #x
#ifndef STR
#define STR(x) STR1(x)
#endif

#define CAT_(A, B) A##B
#define CAT(A, B) CAT_(A, B)

/** Assembly macro for creating "raw" Rocket Custom Coproessor (RoCC)
  * assembly language instructions that will return data in rd. These
  * are to be used only in assembly language programs (not C/C++).
  *
  * Example:
  *
  * Consider the following macro consisting of a CUSTOM_0 instruction
  * with func7 "42" that is doing some operation of "a0 = op(a1, a2)":
  *
  *     ROCC_INSTRUCTION_RAW_R_R_R(0, a0, a1, a2, 42)
  *
  * This will produce the following pseudo assembly language
  * instruction:
  *
  *     .insn r CUSTOM_0, 7, 42, a0, a1, a2
  *
  * @param x the custom instruction number: 0, 1, 2, or 3
  * @param rd the destination register, e.g., a0 or x10
  * @param rs1 the first source register, e.g., a0 or x10
  * @param rs2 the second source register, e.g., a0 or x10
  * @param func7 the value of the func7 field
  * @return a raw .insn RoCC instruction
  */
#define ROCC_INSTRUCTION_RAW_R_R_R(x, rd, rs1, rs2, func7) \
  .insn r CAT(CUSTOM_, x), 7, func7, rd, rs1, rs2

/** Assembly macro for creating "raw" Rocket Custom Coproessor (RoCC)
  * assembly language instructions that will *NOT* return data in rd.
  * These are to be used only in assembly language programs (not
  * C/C++).
  *
  * Example:
  *
  * Consider the following macro consisting of a CUSTOM_1 instruction
  * with func7 "42" that is doing some operation of "op(a1, a2)". *NO*
  * data is returned:
  *
  *     ROCC_INSTRUCTION_RAW_0_R_R(1, a1, a2, 42)
  *
  * This will produce the following pseudo assembly language
  * instruction:
  *
  *     .insn r CUSTOM_1, 3, 42, x0, a1, a2
  *
  * @param x the custom instruction number: 0, 1, 2, or 3
  * @param rs1 the first source register, e.g., a0 or x10
  * @param rs2 the second source register, e.g., a0 or x10
  * @param func7 the value of the func7 field
  * @return a raw .insn RoCC instruction
  */
#define ROCC_INSTRUCTION_RAW_0_R_R(x, rs1, rs2, func7) \
  .insn r CAT(CUSTOM_, x), 3, func7, x0, rs1, rs2

/** C/C++ inline assembly macro for creating Rocket Custom Coprocessor
  * (RoCC) instructions that return data in rd. These are to be used
  * only in C/C++ programs (not bare assembly).
  *
  * This is equivalent to ROCC_INSTRUCTION_R_R_R. See it's
  * documentation.
  */
#define ROCC_INSTRUCTION(x, rd, rs1, rs2, func7) \
  ROCC_INSTRUCTION_R_R_R(x, rd, rs1, rs2, func7)

/** C/C++ inline assembly macro for creating Rocket Custom Coprocessor
  * (RoCC) instructions that return data in C variable rd. 
  * These are to be used only in C/C++ programs (not bare assembly).
  *
  * Example:
  *
  * Consider the following macro consisting of a CUSTOM_2 instruction
  * with func7 "42" that is doing some operation of "a0 = op(a1, a2)"
  * (where a0, a1, and a2 are variables defined in C):
  *
  *     ROCC_INSTRUCTION(2, a0, a1, a2, 42)
  *
  * This will produce the following inline assembly:
  *
  *     asm volatile(
  *         ".insn r CUSTOM_2, 0x7, 42, %0, %1, %2"
  *         : "=r"(rd)
  *         : "r"(rs1), "r"(rs2));
  *
  * @param x the custom instruction number: 0, 1, 2, or 3
  * @param rd the C variable to capture as destination operand
  * @param rs1 the C variable to capture for first source register
  * @param rs2 the C variable to capture for second source register
  * @param func7 the value of the func7 field
  * @return an inline assembly RoCC instruction
  */
#define ROCC_INSTRUCTION_R_R_R(x, rd, rs1, rs2, func7)                               \
  {                                                                                  \
    asm volatile(                                                                    \
        ".insn r " STR(CAT(CUSTOM_, x)) ", " STR(0x7) ", " STR(func7) ", %0, %1, %2" \
        : "=r"(rd)                                                                   \
        : "r"(rs1), "r"(rs2));                                                       \
  }

/** C/C++ inline assembly macro for creating Rocket Custom Coprocessor
  * (RoCC) instructions that return data in C variable rd.
  * These are to be used only in C/C++ programs (not bare assembly).
  *
  * Example:
  *
  * Consider the following macro consisting of a CUSTOM_3 instruction
  * with func7 "42" that is doing some operation of "a0 = op(a1, a2)"
  * (where a0, a1, and a2 are variables defined in C):
  *
  *     ROCC_INSTRUCTION(3, a0, a1, a2, 42)
  *
  * This will produce the following inline assembly:
  *
  *     asm volatile(
  *         ".insn r CUSTOM_3, 0x7, 42, %0, %1, %2"
  *         :: "r"(rs1), "r"(rs2));
  *
  * @param x the custom instruction number: 0, 1, 2, or 3
  * @param rs1 the C variable to capture for first source register
  * @param rs2 the C variable to capture for second source register
  * @param funct7 the value of the funct7 f
  * @return an inline assembly RoCC instruction
  */
#define ROCC_INSTRUCTION_0_R_R(x, rs1, rs2, func7)                                   \
  {                                                                                  \
    asm volatile(                                                                    \
        ".insn r " STR(CAT(CUSTOM_, x)) ", " STR(0x3) ", " STR(func7) ", x0, %0, %1" \
        :                                                                            \
        : "r"(rs1), "r"(rs2));                                                       \
  }

// [TODO] fix these to align with the above approach
// Macro to pass rs2_ as an immediate
/*
#define ROCC_INSTRUCTION_R_R_I(XCUSTOM_, rd_, rs1_, rs2_, funct_) \
  asm volatile (XCUSTOM_" %[rd], %[rs1], %[rs2], %[funct]"        \
                : [rd] "=r" (rd_)                                 \
                : [rs1] "r" (rs1_), [rs2] "i" (rs2_), [funct] "i" (funct_))

// Macro to pass rs1_ and rs2_ as immediates
#define ROCC_INSTRUCTION_R_I_I(XCUSTOM_, rd_, rs1_, rs2_, funct_) \
  asm volatile (XCUSTOM_" %[rd], %[rs1], %[rs2], %[funct]"        \
                : [rd] "=r" (rd_)                                 \
                : [rs1] "i" (rs1_), [rs2] "i" (rs2_), [funct] "i" (funct_))
*/

#endif  // ROCC_SOFTWARE_SRC_XCUSTOM_H_

新版本的我没有试过,因为我的gcc还是旧版的,而我又不想重新编译gcc工具链,所以就用旧版吧,只要包上上面的代码,就能直接调用,可以参考我其他文章看怎么使用。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值