Instuctions.scals
package componentsimport 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 componentsimport 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 componentsimport 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 componentsimport 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 componentsimport 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 componentsimport 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) ))}