preeee
Instuctions.scals
package components
import chisel3.util.BitPat
/**
* LoongArch-C3指令集定义
*
* 定义了CPU支持的21条LoongArch指令的BitPat模式
* 这些模式用于指令译码器进行指令识别和分类
*
* 指令分类:
* - 算术指令:加法、减法运算
* - 立即数加载:地址计算相关指令
* - 逻辑指令:按位逻辑运算
* - 移位指令:逻辑移位操作
* - 跳转指令:无条件跳转和链接跳转
* - 分支指令:条件分支跳转
* - 访存指令:内存读写操作
*
* 注意:当前使用通配符模式,实际实现时需要根据LoongArch规范
* 填入具体的指令编码格式
*/
object Instructions {
// ========== 算术指令 ==========
/** 立即数加法:rd = rj + si12 */
def ADDI_W = BitPat("b????????????????????????????????") // addi.w rd, rj, si12
/** 寄存器加法:rd = rj + rk */
def ADD_W = BitPat("b????????????????????????????????") // add.w rd, rj, rk
/** 寄存器减法:rd = rj - rk */
def SUB_W = BitPat("b????????????????????????????????") // sub.w rd, rj, rk
/** 寄存器乘法:rd = rj * rk */
def MUL_W = BitPat("b????????????????????????????????") // mul.w rd, rj, rk
// ========== 立即数加载指令 ==========
/** 加载高20位立即数:rd = si20 << 12 */
def LU12I_W = BitPat("b????????????????????????????????") // lu12i.w rd, si20
/** PC相对地址计算:rd = PC + (si20 << 12) */
def PCADDU12I = BitPat("b????????????????????????????????") // pcaddu12i rd, si20
// ========== 逻辑指令 ==========
/** 按位或:rd = rj | rk */
def OR = BitPat("b????????????????????????????????") // or rd, rj, rk
/** 立即数按位或:rd = rj | si12 */
def ORI = BitPat("b????????????????????????????????") // ori rd, rj, si12
/** 按位与:rd = rj & rk */
def AND = BitPat("b????????????????????????????????") // and rd, rj, rk
/** 立即数按位与:rd = rj & si12 */
def ANDI = BitPat("b????????????????????????????????") // andi rd, rj, si12
/** 按位异或:rd = rj ^ rk */
def XOR = BitPat("b????????????????????????????????") // xor rd, rj, rk
// ========== 移位指令 ==========
/** 逻辑右移:rd = rj >> ui5 */
def SRLI_W = BitPat("b????????????????????????????????") // srli.w rd, rj, ui5
/** 逻辑左移:rd = rj << ui5 */
def SLLI_W = BitPat("b????????????????????????????????") // slli.w rd, rj, ui5
// ========== 跳转指令 ==========
/** 跳转并链接:rd = PC + 4; PC = rj + si16 */
def JIRL = BitPat("b????????????????????????????????") // jirl rd, rj, si16
/** 无条件跳转:PC = PC + (si20 << 2) */
def B = BitPat("b????????????????????????????????") // b si20
/** 跳转并链接:rd = PC + 4; PC = PC + (si20 << 2) */
def BL = BitPat("b????????????????????????????????") // bl si20
// ========== 分支指令 ==========
/** 相等分支:if (rj == rd) PC = PC + (si16 << 2) */
def BEQ = BitPat("b????????????????????????????????") // beq rj, rd, si16
/** 不等分支:if (rj != rd) PC = PC + (si16 << 2) */
def BNE = BitPat("b????????????????????????????????") // bne rj, rd, si16
// ========== 访存指令 ==========
/** 存储字:Mem[rj + si12] = rd */
def ST_W = BitPat("b????????????????????????????????") // st.w rd, rj, si12
/** 加载字:rd = Mem[rj + si12] */
def LD_W = BitPat("b????????????????????????????????") // ld.w rd, rj, si12
/** 存储字节:Mem[rj + si12] = rd[7:0] */
def ST_B = BitPat("b????????????????????????????????") // st.b rd, rj, si12
/** 加载字节:rd = {24'b0, Mem[rj + si12][7:0]} */
def LD_B = BitPat("b????????????????????????????????") // ld.b rd, rj, si12
}
Decoder.s
package components
import chisel3._
import chisel3.util._
import components.ALUOps._
import components.Instructions._
/**
* 指令译码器模块
*
* 功能:将32位指令字翻译成控制信号,用于控制CPU各个功能单元的操作
*
* 输入:32位指令字 (inst)
* 输出:控制信号束 (ControlSigs),包含ALU操作、寄存器写使能、立即数类型等
*/
import Instructions._
class DecoderIO extends Bundle {
val inst = Input(UInt(32.W)) // 输入的32位指令字
val sigs = Output(new ControlSigs) // 输出的控制信号束
}
class Decoder extends Module {
val io = IO(new DecoderIO)
/**
* 默认控制信号列表
*
* 当指令不匹配任何已知模式时使用的默认控制信号
* 元素顺序必须与ControlSigs Bundle中的字段顺序完全一致:
* [alu_op, reg_write_en, imm_type, branch, jump, mem_read_en, mem_write_en, mem_size]
*/
val default: List[UInt] = List(ALUOps.ADD, true.B, 0.U, false.B, false.B, false.B, false.B, 0.U)
/**
* 指令译码映射表
*
* 将指令模式(BitPat)映射到对应的控制信号列表
* 每个控制信号列表的格式:[alu_op, reg_write_en, imm_type, branch, jump, mem_read_en, mem_write_en, mem_size]
*/
val mapping: Array[(BitPat, List[UInt])] = Array(
// ========== 算术运算指令 ==========
// 寄存器-寄存器运算
ADD_W -> List(ALUOps.ADD, true.B, 0.U, false.B, false.B, false.B, false.B, 0.U), // 加法
SUB_W -> List(ALUOps.SUB, true.B, 0.U, false.B, false.B, false.B, false.B, 0.U), // 减法
MUL_W -> List(ALUOps.MUL, true.B, 0.U, false.B, false.B, false.B, false.B, 0.U), // 乘法
// ========== 逻辑运算指令 ==========
Instructions.OR -> List(ALUOps.OR, true.B, 0.U, false.B, false.B, false.B, false.B, 0.U), // 或运算
Instructions.AND -> List(ALUOps.AND, true.B, 0.U, false.B, false.B, false.B, false.B, 0.U), // 与运算
Instructions.XOR -> List(ALUOps.XOR, true.B, 0.U, false.B, false.B, false.B, false.B, 0.U), // 异或运算
// ========== 移位指令 ==========
SLLI_W -> List(ALUOps.SLL, true.B, 1.U, false.B, false.B, false.B, false.B, 0.U), // 左移(5位立即数)
SRLI_W -> List(ALUOps.SRL, true.B, 1.U, false.B, false.B, false.B, false.B, 0.U), // 右移(5位立即数)
// ========== 立即数运算指令 ==========
ADDI_W -> List(ALUOps.ADD, true.B, 2.U, false.B, false.B, false.B, false.B, 0.U), // 立即数加法(12位)
ORI -> List(ALUOps.OR, true.B, 2.U, false.B, false.B, false.B, false.B, 0.U), // 立即数或(12位)
ANDI -> List(ALUOps.AND, true.B, 2.U, false.B, false.B, false.B, false.B, 0.U), // 立即数与(12位)
LU12I_W -> List(ALUOps.ADD, true.B, 3.U, false.B, false.B, false.B, false.B, 0.U), // 加载高20位立即数
PCADDU12I -> List(ALUOps.ADD, true.B, 4.U, false.B, false.B, false.B, false.B, 0.U), // PC相对地址计算
// ========== 内存访问指令 ==========
LD_W -> List(ALUOps.ADD, true.B, 2.U, false.B, false.B, true.B, false.B, 2.U), // 加载字(32位)
ST_W -> List(ALUOps.ADD, false.B, 2.U, false.B, false.B, false.B, true.B, 2.U), // 存储字(32位)
LD_B -> List(ALUOps.ADD, true.B, 2.U, false.B, false.B, true.B, false.B, 0.U), // 加载字节(8位)
ST_B -> List(ALUOps.ADD, false.B, 2.U, false.B, false.B, false.B, true.B, 0.U), // 存储字节(8位)
// ========== 跳转和分支指令 ==========
JIRL -> List(ALUOps.ADD, true.B, 2.U, false.B, true.B, false.B, false.B, 0.U), // 跳转并链接
B -> List(ALUOps.ADD, false.B, 0.U, false.B, true.B, false.B, false.B, 0.U), // 无条件跳转
BL -> List(ALUOps.ADD, true.B, 0.U, false.B, true.B, false.B, false.B, 0.U), // 跳转并链接(长)
BEQ -> List(ALUOps.SUB, false.B, 0.U, true.B, false.B, false.B, false.B, 0.U), // 相等分支
BNE -> List(ALUOps.SUB, false.B, 0.U, true.B, false.B, false.B, false.B, 0.U), // 不等分支
)
/**
* 指令译码查表
*
* 使用ListLookup根据输入指令查找对应的控制信号列表
* 如果指令不匹配任何模式,则使用默认控制信号
*/
val sigs_list = ListLookup(io.inst, default, mapping)
/**
* 控制信号分配
*
* 将查表得到的信号列表中的各个元素分配到ControlSigs Bundle的对应字段
* 注意:索引顺序必须与ControlSigs Bundle中字段的声明顺序一致
*/
io.sigs.alu_op := sigs_list(0) // ALU操作类型
io.sigs.reg_write_en := sigs_list(1) // 寄存器写使能
io.sigs.imm_type := sigs_list(2) // 立即数类型
io.sigs.branch := sigs_list(3) // 分支指令标志
io.sigs.jump := sigs_list(4) // 跳转指令标志
io.sigs.mem_read_en := sigs_list(5) // 内存读使能
io.sigs.mem_write_en := sigs_list(6) // 内存写使能
io.sigs.mem_size := sigs_list(7) // 内存访问大小
}
/**
* =======================================================
* LoongArch 指令的 BitPat 模板定义
* =======================================================
*
* 注意:指令的BitPat模板定义在Instructions.scala文件中
* 这里只是引用,具体的指令编码格式请参考LoongArch指令集手册
*/
Control.s
package components
import chisel3._
import chisel3.util._
import components.ALUOps._
/**
* 控制信号束定义
*
* 这个Bundle包含了CPU执行指令时需要的所有控制信号
* 由指令译码器(Decoder)生成,用于控制CPU各个功能单元的操作
*/
class ControlSigs extends Bundle {
/** ALU操作类型
* 指定算术逻辑单元执行的具体操作(ADD, SUB, OR, AND, XOR, SLL, SRL等)
*/
val alu_op = UInt(ALUOps.opWidth.W)
/** 寄存器写使能
* 控制是否将ALU结果写入目标寄存器
* true: 写入寄存器; false: 不写入
*/
val reg_write_en = Bool()
/** 立即数类型
* 指定指令中立即数的格式和长度
* 0: 无立即数; 1: 5位立即数; 2: 12位立即数; 3: 20位立即数; 4: PC相对地址
*/
val imm_type = UInt(2.W)
/** 分支指令标志
* 标识当前指令是否为条件分支指令(BEQ, BNE等)
* true: 分支指令; false: 非分支指令
*/
val branch = Bool()
/** 跳转指令标志
* 标识当前指令是否为跳转指令(B, BL, JIRL等)
* true: 跳转指令; false: 非跳转指令
*/
val jump = Bool()
/** 内存读使能
* 控制是否从内存读取数据
* true: 读取内存; false: 不读取内存
*/
val mem_read_en = Bool()
/** 内存写使能
* 控制是否向内存写入数据
* true: 写入内存; false: 不写入内存
*/
val mem_write_en = Bool()
/** 内存访问大小
* 指定内存访问的数据宽度
* 0: 字节(8位); 1: 半字(16位); 2: 字(32位)
*/
val mem_size = UInt(2.W)
}
ALU.s
package components
import chisel3._
import chisel3.util._
import components.ALUOps._
/**
* 算术逻辑单元(ALU)模块
*
* 功能:执行各种算术、逻辑、移位和比较运算
* 支持的操作:加法、减法、逻辑运算、移位、比较、数据传递等
*
* 设计特点:
* - 使用预计算方式提高性能
* - 支持零标志输出用于分支判断
* - 可配置数据位宽,默认32位
*/
/**
* ALU输入输出接口
*
* @param dataBits 数据位宽,默认为32位
*/
class ALUIO(dataBits: Int) extends Bundle {
val a = Input(UInt(dataBits.W)) // 操作数A
val b = Input(UInt(dataBits.W)) // 操作数B
val op = Input(UInt(ALUOps.opWidth.W)) // 操作码
val out = Output(UInt(dataBits.W)) // 运算结果
val zero = Output(Bool()) // 零标志(用于分支判断)
}
/**
* ALU模块实现
*
* @param dataBits 数据位宽,默认为32位
*/
class ALU(dataBits: Int = 32) extends Module {
val io = IO(new ALUIO(dataBits))
// 导入ALU操作码常量
import ALUOps._
/**
* 预计算所有可能的运算结果
* 这种设计可以提高性能,避免在运行时进行复杂的条件判断
*/
val add_res = io.a + io.b // 加法运算
val sub_res = io.a - io.b // 减法运算
val mul_res = io.a * io.b // 乘法运算
val and_res = io.a & io.b // 按位与运算
val or_res = io.a | io.b // 按位或运算
val xor_res = io.a ^ io.b // 按位异或运算
val shamt = io.b(4, 0) // 提取移位量(低5位)
val sll_res = io.a << shamt // 逻辑左移
val srl_res = io.a >> shamt // 逻辑右移
// 比较运算结果
val eq_res = (io.a === io.b) // 相等比较
val ne_res = (io.a =/= io.b) // 不等比较
/**
* 操作码选择器
* 使用MuxCase根据操作码选择对应的运算结果
* 默认返回0.U作为未定义操作的默认值
*/
val result = MuxCase(0.U, Seq(
(io.op === ADD) -> add_res, // 加法
(io.op === SUB) -> sub_res, // 减法
(io.op === MUL) -> mul_res, // 乘法
(io.op === AND) -> and_res, // 按位与
(io.op === OR) -> or_res, // 按位或
(io.op === XOR) -> xor_res, // 按位异或
(io.op === SLL) -> sll_res, // 逻辑左移
(io.op === SRL) -> srl_res, // 逻辑右移
(io.op === EQ) -> eq_res, // 相等比较
(io.op === NE) -> ne_res, // 不等比较
(io.op === COPY_A) -> io.a, // 传递操作数A
(io.op === COPY_B) -> io.b, // 传递操作数B
(io.op === COPY_IMM) -> io.b, // 传递立即数(通过B端口)
))
/**
* 输出连接
* zero标志基于减法结果判断,用于分支指令的条件判断
*/
io.out := result // 输出运算结果
io.zero := (sub_res === 0.U) // 零标志输出
}
ALUOP.s
package components
import chisel3._
/**
* ALU操作码定义
*
* 定义了算术逻辑单元支持的所有操作类型
* 使用4位编码,支持最多16种不同的操作
*
* 操作码分类:
* - 算术运算:加法、减法
* - 逻辑运算:按位与、或、异或
* - 移位运算:逻辑左移、右移
* - 比较运算:相等、不等比较
* - 数据传递:直接传递操作数或立即数
*/
object ALUOps {
/** 操作码位宽:4位,支持16种操作 */
val opWidth = 4
// ========== 算术运算 ==========
/** 加法运算:result = a + b */
val ADD = "b0001".U(opWidth.W)
/** 减法运算:result = a - b */
val SUB = "b0010".U(opWidth.W)
/** 乘法运算:result = a * b */
val MUL = "b0011".U(opWidth.W)
// ========== 逻辑运算 ==========
/** 按位与运算:result = a & b */
val AND = "b0100".U(opWidth.W)
/** 按位或运算:result = a | b */
val OR = "b0101".U(opWidth.W)
/** 按位异或运算:result = a ^ b */
val XOR = "b0110".U(opWidth.W)
// ========== 移位运算 ==========
/** 逻辑左移:result = a << b[4:0] */
val SLL = "b0111".U(opWidth.W)
/** 逻辑右移:result = a >> b[4:0] */
val SRL = "b1000".U(opWidth.W)
// ========== 比较运算 ==========
/** 相等比较:result = (a == b) ? 1 : 0 */
val EQ = "b1001".U(opWidth.W)
/** 不等比较:result = (a != b) ? 1 : 0 */
val NE = "b1010".U(opWidth.W)
// ========== 数据传递 ==========
/** 传递操作数A:result = a */
val COPY_A = "b1011".U(opWidth.W)
/** 传递操作数B:result = b */
val COPY_B = "b1100".U(opWidth.W)
/** 传递立即数:result = b (立即数通过B端口传入) */
val COPY_IMM = "b1101".U(opWidth.W)
}
ImmGen.s
package components
import chisel3._
import chisel3.util._
/**
* 立即数生成单元
*
* 功能:从32位指令中提取并扩展各种类型的立即数
* 支持LoongArch指令集的多种立即数格式
*
* 支持的立即数类型:
* - 5位立即数:用于移位指令
* - 12位有符号立即数:用于算术和访存指令
* - 20位立即数:用于地址计算指令
*/
class ImmGen extends Module {
val io = IO(new Bundle {
/** 输入的32位指令字 */
val inst = Input(UInt(32.W))
/** 立即数类型选择信号(3位,支持8种类型) */
val imm_type = Input(UInt(3.W))
/** 输出的32位立即数 */
val imm_out = Output(UInt(32.W))
})
// 提取指令中的立即数字段
val inst = io.inst
/**
* 5位立即数提取和扩展
* 用于移位指令(SLLI_W, SRLI_W)
* 格式:指令位[14:10],零扩展到32位
*/
val imm_5bit = Cat(0.U(27.W), inst(14, 10))
/**
* 12位有符号立即数提取和扩展
* 用于算术指令(ADDI_W, ORI, ANDI)和访存指令(LD_W, ST_W)
* 格式:指令位[21:10],符号扩展到32位
*/
val imm_12bit = Cat(Fill(20, inst(21)), inst(21, 10))
/**
* 20位立即数提取和扩展
* 用于地址计算指令(LU12I_W, PCADDU12I)
* 格式:指令位[19:0],左移12位后零扩展到32位
*/
val imm_20bit = Cat(inst(19, 0), 0.U(12.W))
/**
* 立即数类型选择器
* 根据imm_type信号选择对应的立即数格式
*/
io.imm_out := MuxCase(0.U, Seq(
(io.imm_type === 0.U) -> 0.U, // 无立即数
(io.imm_type === 1.U) -> imm_5bit, // 5位立即数(移位指令)
(io.imm_type === 2.U) -> imm_12bit, // 12位立即数(算术/访存指令)
(io.imm_type === 3.U) -> imm_20bit, // 20位立即数(LU12I_W)
(io.imm_type === 4.U) -> imm_20bit // 20位立即数(PCADDU12I)
))
}

浙公网安备 33010602011771号