软件通过自定义汇编语言利用riscv指令与nice接口交互。
Risc-v指令的功能在Verilog文件中得到定义。在C语言中,使用自定义汇编语言操控使用这些指令。
所定义的指令一共有三个:
指令 | 功能 |
custom_lbuf | 从内存中加载数据至缓存 |
custom_sbuf | 将缓存中的数据存至内存 |
custom_rowsum | 进行行累计值运算,并且将改行三个元素与缓存中的三个元素相加 |
在C语言中使用asm volatile 书写一个汇编语句,例如:
asm volatile (
".insn r 0x7b, 2, 1, x0, %1, x0"
:"=r"(zero)
:"r"(addr)
)
句首“.insn”是这条汇编语言的指令,在这里这是一个自定义指令。接下来依次是riscv指令中的操作数0x7b,fun3代码2,fun7代码1。这些组成riscv指令。fun3由三位xsl, xs2, xd组成。分别用于控制是否需要读源寄存器 rsl,rs2 和写目标寄存器 rd。
第一个冒号之后是输出表达式,r代表随机分配一个寄存器,括号中是C语言对应的变量。第二个冒号之后是输入表达式,如果除了输入输出之外还有别的寄存器使用则需添加第三个冒号,冒号之后的表达式代表除了输入输出之外别的寄存器。这些句子会被编号,输出表达式第一个会被编号为0,之后的所有表达式编号为依次加一。
在第一个冒号之前的句子,后三个表达式代表寄存器以及是否被使用。如被使用,会替换为使用它的语句的编号并在前面加上一个%。依次代表xsl,xs2,xd。
在示例中,首先使用零值进行初始化: custom_lbuf((int)init_buf)。值得注意的是,在定义一个多维数组时,当使用该数组变量时少加一个[]表示该维的地址。如定义init_buf[3]=0,在书写时仅书写init_buf而缺少一个[]来表示该维数组的地址。
之后示例使用for循环:
for (i = 0; i < ROW_LEN; i++)
{
row_sum[i] = custom_rowsum((int)array[i]);
}
来实现行累加。这里由于在硬件代码中对指令功能的定义,还会将改行三个元素与缓存中的三个元素相加。再通过custom_sbuf((int)col_sum)来将缓存中相加的列元素和存储至内存。这里的array被定义为一个二维数组array[i][j],只书写一个[]表示该维的地址。