学习了1阶和2阶risc-v处理器后,现在学习3阶的,3阶的没有找到图。按照惯例,我们一个个scala文件进行说明。先进行说明的是alu.scala(算术逻辑单元(arithmetic and logic unit) 是能实现多组算术运算和逻辑运算的组合逻辑电路,简称ALU):
package Sodor
import chisel3._
import chisel3.util._
import Common._
import Constants._
//定义伴生对象,定义一些常量信号
object ALU
{
// TODO is this the optimal encoding?
//定义ALU函数的宽度,这里是4bits,也就是ALU最多可以有16种种类
val SZ_ALU_FN = 4
//ALU_X为0值
val ALU_X = 0.U // TODO use a more optimal decode table, which uses "???" format
//ALU_ADD,加法为0值
val ALU_ADD = 0.U
//ALU_SLL,逻辑左移为1值
val ALU_SLL = 1.U
//ALU_XOR,异或为4值
val ALU_XOR = 4.U
//ALU_OR,或为6值
val ALU_OR = 6.U
//ALU_AND,与为7值
val ALU_AND = 7.U
//ALU_AND,逻辑右移为5值
val ALU_SRL = 5.U
//ALU_SUB,减为10值
val ALU_SUB = 10.U
//ALU_SRA,算数右移为11值
val ALU_SRA = 11.U
//ALU_SLT,小于为12值
val ALU_SLT = 12.U
//ALU_SLTU,小于,无符号U-type为14值
val ALU_SLTU = 14.U
//ALU_COPY1,复制为8值
val ALU_COPY1= 8.U
//定义isSub的方法,提前cmd的第三位数据
def isSub(cmd: UInt) = cmd(3)
//定义isSLTU的方法,提前cmd的第一位数据
def isSLTU(cmd: UInt) = cmd(1)
}
import ALU._
//定义ALU模块的端口,输入函数(fn),in1和in2,得出out或adder_out
class ALUIO(implicit conf: SodorConfiguration) extends Bundle {
val fn = Input(UInt(SZ_ALU_FN.W))
val in2 = Input(UInt(conf.xprlen.W))
val in1 = Input(UInt(conf.xprlen.W))
val out = Output(UInt(conf.xprlen.W))
val adder_out = Output(UInt(conf.xprlen.W))
}
//ALU模块的主题
class ALU(implicit conf: SodorConfiguration) extends Module
{
//调用ALUIO模块,命名为io
val io = IO(new ALUIO)
//msb是Most Significant Bit的缩写,指最高有效位,这里是32-1,也就是31
val msb = conf.xprlen-1
// ADD, SUB
//加法和减法的操作,如果输入的fn信号第三位为1,则运行减法,in1-in2,
//如果为0,则运行加法,将in1+in2
val sum = io.in1 + Mux(isSub(io.fn), -io.in2, io.in2)
// SLT, SLTU
//先做Mux(isSLTU(io.fn), io.in2(msb), io.in1(msb)),利用isSLTU(io.fn)判断fn信号的第一位,若是1,则//输出in2的最高位,否则输出in1的最高位
//然后再做Mux(io.in1(msb) === io.in2(msb), sum(msb), X),其中X,为上面一步的结果,若in1的最高位
//等于in2的最高位,则输出sum的最高位,如果in1最高位和in2最高位不等,则输出X的结果
//这里要看slt指令的说明,比较rs1和rs2的值,如果rs1<rs2,则置1值rd中,rs1和rs2位有符号数,
//sltu则用来判断无符号数,我们先看sltu的,当为无符号数时,且in1(31)==in2(31)时,用sum值来作为//less,也就是当sum为负值,则rs1<rs2,所以less置1,当sum为正,则rs1>rs2,所以less置0,如果//in1(31)不等于in2(31)时,因为是sltu指令,所以isSLTU(io.fn)为1,因此less取in2(31),因为如果in2(31)
//为1,in1(31)必定为0,所以less=in2(31),反过来,如果in2(31)为0,则in1(31)必定为1,所以less为
//0,也是less=in2(31),slt也是同样的方法分析
val less = Mux(io.in1(msb) === io.in2(msb), sum(msb),
Mux(isSLTU(io.fn), io.in2(msb), io.in1(msb)))
require(conf.xprlen == 32)
// SLL, SRL, SRA
//提前指令中需要移动的位数,是in2的第四位置第零位
val shamt = io.in2(4,0).toUInt
//将in1的值赋给shin_r
val shin_r = io.in1(31,0)
//判断(io.fn === ALU_SRL || io.fn === ALU_SRA,如果是,则将shin_r赋给shin,否则赋Reverse(shin_r)
//Reverse是将shin_r取反
val shin = Mux(io.fn === ALU_SRL || io.fn === ALU_SRA, shin_r, Reverse(shin_r))
//算数右移或者逻辑右移的操作
val shout_r = (Cat(isSub(io.fn) & shin(msb), shin).toSInt >> shamt)(msb,0)
//逻辑左移的结果,将shout_r取反
val shout_l = Reverse(shout_r)
//根据in.fn函数来输出bitwise_logic信号,分别有与,或,异或,copy
val bitwise_logic =
Mux(io.fn === ALU_AND, io.in1 & io.in2,
Mux(io.fn === ALU_OR, io.in1 | io.in2,
Mux(io.fn === ALU_XOR, io.in1 ^ io.in2,
io.in1))) // ALU_COPY1
//根据in.fn函数来输出out_xpr_length信号,分别有加,减,小于,小于(无符号数),逻辑右移,算术右//移,逻辑左移和bitwise_logic
val out_xpr_length =
Mux(io.fn === ALU_ADD || io.fn === ALU_SUB, sum,
Mux(io.fn === ALU_SLT || io.fn === ALU_SLTU, less,
Mux(io.fn === ALU_SRL || io.fn === ALU_SRA, shout_r,
Mux(io.fn === ALU_SLL, shout_l,
bitwise_logic))))
//将out_xpr_length的值赋给ALU端口io.out
io.out := out_xpr_length(31,0).toUInt
//将sum的值赋给ALU端口io.adder_out
io.adder_out := sum
}