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)

  ))

}
posted @ 2025-11-07 19:55  when-epoch  阅读(2)  评论(0)    收藏  举报