// See LICENSE for license details.
package mini
import chisel3._
import chisel3.util._
import freechips.rocketchip.config.Parameters
object ALU {
val ALU_ADD = 0.U(4.W)
val ALU_SUB = 1.U(4.W)
val ALU_AND = 2.U(4.W)
val ALU_OR = 3.U(4.W)
val ALU_XOR = 4.U(4.W)
val ALU_SLT = 5.U(4.W)
val ALU_SLL = 6.U(4.W)
val ALU_SLTU = 7.U(4.W)
val ALU_SRL = 8.U(4.W)
val ALU_SRA = 9.U(4.W)
val ALU_COPY_A = 10.U(4.W)
val ALU_COPY_B = 11.U(4.W)
val ALU_XXX = 15.U(4.W)
}
单例ALU对象中定义ALU模块常用的常数。
ALU_后面不同的字段代表 不同的指令对应的不同的ALU操作,ALU模块中的op和control模块 译码解析出来的控制信号对应。
二、接口信号定义
class ALUIo(implicit p: Parameters) extends CoreBundle()(p) {
val A = Input(UInt(xlen.W))
val B = Input(UInt(xlen.W))
val alu_op = Input(UInt(4.W))
val out = Output(UInt(xlen.W))
val sum = Output(UInt(xlen.W))
}
ALU模块的几口信号有3个输入和2个输出,A 和B 代表ALU 输入的两个操作数,操作数的来源由control模块中A_sel,和B_sel来选择,不同指令选择的两个 操作数不同,选择的alu_op也不同。
out和sum 代表alu计算的结果
三、ALU具体实现
import ALU._
abstract class ALU(implicit val p: Parameters) extends Module with CoreParams {
val io = IO(new ALUIo)
}
class ALUSimple(implicit p: Parameters) extends ALU()(p) {
val shamt = io.B(4,0).asUInt
io.out := MuxLookup(io.alu_op, io.B, Seq(
ALU_ADD -> (io.A + io.B),
ALU_SUB -> (io.A - io.B),
ALU_SRA -> (io.A.asSInt >> shamt).asUInt,
ALU_SRL -> (io.A >> shamt),
ALU_SLL -> (io.A << shamt),
ALU_SLT -> (io.A.asSInt < io.B.asSInt),
ALU_SLTU -> (io.A < io.B),
ALU_AND -> (io.A & io.B),
ALU_OR -> (io.A | io.B),
ALU_XOR -> (io.A ^ io.B),
ALU_COPY_A -> io.A))
io.sum := io.A + Mux(io.alu_op(0), -io.B, io.B)
}
可以看到ALUSimple 继承抽象类ALU
io.out 通过MuxLookup 模型实现选择输出,第一个参数是alu_op, 第二个参数是默认值io.B,
第3个参数是一个映射表
io.sum 根据加法和减法,进行加和减运算。
class ALUArea(implicit p: Parameters) extends ALU()(p) {
val sum = io.A + Mux(io.alu_op(0), -io.B, io.B)
val cmp = Mux(io.A(xlen-1) === io.B(xlen-1), sum(xlen-1),
Mux(io.alu_op(1), io.B(xlen-1), io.A(xlen-1)))
val shamt = io.B(4,0).asUInt
val shin = Mux(io.alu_op(3), io.A, Reverse(io.A))
val shiftr = (Cat(io.alu_op(0) && shin(xlen-1), shin).asSInt >> shamt)(xlen-1, 0)
val shiftl = Reverse(shiftr)
val out =
Mux(io.alu_op === ALU_ADD || io.alu_op === ALU_SUB, sum,
Mux(io.alu_op === ALU_SLT || io.alu_op === ALU_SLTU, cmp,
Mux(io.alu_op === ALU_SRA || io.alu_op === ALU_SRL, shiftr,
Mux(io.alu_op === ALU_SLL, shiftl,
Mux(io.alu_op === ALU_AND, (io.A & io.B),
Mux(io.alu_op === ALU_OR, (io.A | io.B),
Mux(io.alu_op === ALU_XOR, (io.A ^ io.B),
Mux(io.alu_op === ALU_COPY_A, io.A, io.B))))))))
io.out := out
io.sum := sum
ALUArea是另外一种定义形式,综合出来的电路会有更小的资源。
先根据指令类型,把结果选择出来,一些相同的操作的类型共用加法器,移位等逻辑资源,通过选择取反实现。综合出来的面积更小,但是路径会变长。以时间换取资源