BUAA-CO-P5 基于verilog的流水线MIPS架构CPU(1)

要求

  • 全力转发!
  • 支持指令集:{add,sub,ori,lui,lw,sw,beq,jr,jal,nop}

需要重构的地方

译码方式

选择集中式译码 & 控制信号驱动型译码

e.g.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  //宏定义
`define ADDU 6'b100001
`define RTYPE 6'b000000;
//定义信号
wire Rtype,addu;
wire [1:0]NPCOp;
wire RFWr;
//decode
assign RType = (opcode == RTYPE);
assign addu = RType&(funct == ADDU);
//生成控制信号
assign NPCOp[0] = beq | jr | jalr;
assign NPCOp[1] = jal | jr | jalr | j;

assign RFWr = addu | subu | ori | lw | jal | lui | lb | lh | addi | jalr ;

Splitter

要取代的:

  1. ControlSplitter
  2. InstrSplitter
  • 核心思想:用宏定义代替splitter
    • 各种控制信号在D级生成后打包成controlbus向后传
    • instruction和controlbus都直接完整向后传,如果要用再利用宏定义在对应阶段取出即可

专门建立一个define.v,在里面进行宏定义

1
2
3
4
5
// constants.v
`ifndef DEFINES_V
`define DEFINES_V
//宏定义
`endif

这样可以保证不重复宏定义

命名方式

E_xx:来自E Register的 xx 值/在E stage产生的 xx 值

添加BranchControl模块

原alu输出equal等跳转判断信号原npc使用equal等信号判断是否跳转的功能集成到BranchControl模块中。

  • 实现分支判断提前到ID

拆分P4中的grfSel模块

grfSel = WASel + WDSel

  • WASel:放在ID中实现,然后一路传递
  • WDSel:WB中实现

GRF内部转发

  • 当GRF同时在WB被写入,在ID被读出,且存在读写寄存器冲突,读出的寄存器值应为新写入的值

    1
    2
    assign RD1 = (RA1 != 0 && RA1 == WA && RegWrite) ? WD : register[RA1];
    assign RD2 = (RA2 != 0 && RA2 == WA && RegWrite) ? WD : register[RA2];

前置知识

延迟槽

跳转指令的下一条指令必执行一次(下一条指令已经在IF被取出)

时序相关

时序

  • 规定CCn的上升沿 指的是 CCn开始的上升沿
  • 初始状态:第0个周期,实际上已经预加载了第一条指令的IF阶段。也就是说,CC1上升沿第一条指令实际上是进入ID阶段。

冒险

数据冒险

  • 转发/旁路:

    • 概念:将尚未写入RF已经暂存在流水线寄存器中的计算结果传递给相关功能部件(或流水线寄存器)的技术
    • 基本要点:
      1. 前递:将M(后级)保存的ALUresult向EX stage(前级)的ALU传递
      2. 选择:
        1. 有依赖才转发
        2. 不依赖不转发,就直接用grf读出的数据参与计算
      3. 转发的数据一定是已经锁存过的数据,而不能从正在计算的组合逻辑里拉线!!!
  • 完备性

    转发到/数据来源 M锁存的ALUresult W_WD M_PC8 E_PC8
    ID stage RtData/RsData RtData/RsData RtData/RsData RtData/RsData
    EX stage RtData/RsData RtData/RsData RtData/RsData 不存在
    MEM stage 不存在 RtData 不存在 不存在

    例如:

    • lw - R:
      • lw处于ME时插入空拍,R指令仍处于ID stage,PC冻结;
      • lw处于WB时,R型指令进入EX stage,将W_reg暂存的计算结果转发到ALU输入端(代替operand1/operand2
    • lw - xxx - R:
      • R型指令处于ID stage时,将W_reg暂存的计算结果转发进E_reg(代替RsData/RtData
  • 阻塞的实现

    • 冻结PC
    • 冻结D_reg
    • 清零E_reg (本质上是向EX stage插入nop指令)

控制冒险

  • 提前分支判断:在D级就完成分支判断(已经用D级 BranchControl模块实现)
  • 延迟槽:即使判断跳转,也至少让紧接着的那条指令执行(不用舍弃IF已经取到的指令)

加指令思路

分析指令RTL

严格按照指令说明来!!!

  1. branch类
  • 修改BranchControlifLinkD_flushBranchEn的输出逻辑
  • 清空延迟槽(NullifyCurrentInstruction()) = D_flush(清空延迟槽)
  1. 是否为条件写寄存器? 改造类似条件linkControlBus添加isConditionalWrite,在能确定是否写入的阶段设置ifConditionalWrite并随流水线向后传递,参与TrueRegWrite的选择实现。
    1. 涉及访存的条件写:在MEM阶段才能确定是否要写入(M_TrueRegWrite\W_TrueRegWrite)
    2. 不涉及访存的条件写:在ID阶段就可以确定是否要写入
  2. 是否为条件选择写入寄存器数据?
    1. 不涉及到访存:增加ALU逻辑即可,在MEM阶段确定写入的数据
    2. 涉及到访存:增加ALU逻辑 & 增加WDsel逻辑,在WB阶段确定写入的数据(本质:lw)

易错点

  1. STALL时不能清空延迟槽(因为此时D级还没有取到正确的data,分支判断无法进行,输出的D_flush不对)
    • STALL > D_flush

计算用组合逻辑积累

  1. rtData是否为rsData相反数? wire isNegPair = (rsData + rtData == 0) && (rsData != 32'h8000_0000); 相反数

  2. 取部分信号 data[i*4 +:4]等价于data[i*4+3:i*4]

  3. 对比有无符号

    • 默认无符号
    • $signed()
  4. 判断奇偶 wire isOdd = rsData[0]; wire isEven = ~rsData[0];

  5. 判断是否是2^n 只有一个 bit 是 1

  6. 是否为 rs 的绝对值比 rt 大

1
2
3
wire absgt =
($signed(rsData[31] ? -rsData : rsData)) >
($signed(rtData[31] ? -rtData : rtData));

模块设计

顶层设计

mips.v

数据通路

  • 五个转发去处(D_NewRsData/D_NewRtData/E_NewRsData/E_NewRtData/M_NewRtData):

  • 本质上是两种转发来源

    • 来自M级:ALUresult、PC+4
    • 来自W级:WD
  • 以D_NewRsData为例: D_RsData数据来源

IF

IFU

  • 模块规格
    信号名 方向 位宽 描述
    reset I 1 同步复位信号
    clk I 1 时钟信号
    NPC I 32 pc更新值
    stall I 32 冻住
    instruction O 32 指令机器码
    PC O 32 当前PC

D

Reg_D

  • 模块规格
    信号名 方向 位宽 描述
    clk I 1 clock
    reset I 1 同步复位信号
    F_instruction I 32 F_instruction
    F_PC I 32 F_PC
    stall I 1 冻住
    D_flush I 1 是否清空延迟槽
    E_instruction O 32 E_instruction
    E_PC O 32 E_PC

ID

Control

  • 控制信号表;

    控制信号\指令 add sub ori lw sw beq lui jal jr
    RegWrite 1 1 1 1 0 0 1 1 0
    aluControlSel 000 000 001 001 001 000 001 000 000
    ALUop 0000 0001 0011 0000 0000 0000 0100 0000 0000
    MemWrite 0 0 0 0 1 0 0 0 0
    MemRead 0 0 0 1 0 0 0 0 0
    EXTop 0 0 0 1 1 1 0 0 0
    RegDst 000 000 001 001 000 000 001 011 000
    WDsel 00 00 00 01 00 00 00 10 00
    NPCop 000 000 000 000 000 001 000 010 011
    MemWriteDataOp 00 00 00 00 00 00 00 00 00
    ifB 0 0 0 0 0 1 0 0 0
    ifJ 0 0 0 0 0 0 0 1 1
    BranchOp 000 000 000 000 000 000 000 000 000
    useRt 1 1 0 0 1 1 0 0 0
    islink 0 0 0 0 0 0 0 1 0
    isConditionalLink 0 0 0 0 0 0 0 0 0
    isLikely 0 0 0 0 0 0 0 0 0
  • T模型时间表

    • Tuse :这条指令位于 D 级的时候,再经过多少个时钟周期就必须要使用相应的数据

    • Tnew :位于某个流水级的某个指令,它经过 Tnew 个时钟周期,该指令的结果(即最终要写回 GRF 的值)才会被计算出来,并存入对应的流水级寄存器中,从而可以被后续指令安全使用或转发。

      • Tnew=0GRF
      指令\T RsTuse RtTuse D_Tnew 说明
      R_cal 1 1 2 Rs、Rt在E级送入ALU,结果在E级产生
      I_cal 1 \ 2 只用Rs,结果在E级产生
      lw(及所有涉及到读内存的指令) 1 \ 3 Rs(base)在E级用于算地址,结果在M级(访存后)产生
      sw 1 2 0 Rs(地址)在E级,Rt(要写入内存的数据)在M级,无需写回GRF
      j \ \ 0 不读寄存器、不写寄存器
      jal \ \ 1 不读寄存器,要写入寄存器的值在D级生成(PC + 4)
      jr 0 \ 0 Rs在D级作为跳转目标被使用,不写寄存器
      beq 0 0 0 Rs\Rt在D级参与跳转判断;不写入寄存器
  • 模块规格

    信号名 方向 位宽 描述
    opcode I 6 指令[31:26]位
    funct I 6 指令[5:0]位
    RegWrite O 1 GRF写使能信号
    aluControlSel O 3 alu操作数选择信号
    000:rs/rt
    001:rs/imm
    ALUop O 4 ALU运算模式选择信号
    MemWrite O 1 DM写使能信号
    MemRead O 1 DM读使能信号
    EXTop O 1 EXT扩展模式选择信号
    RegDst O 3 GRF写回地址选择信号:
    001:rt
    000:rd
    010:rs
    011:GPR[31]
    WDsel O 2 GRF写入数据选择信号:
    00:ALU运算结果
    01:DM读出的数据(lw)
    10:PC + 8(延迟槽)
    NPCop O 3 PC更新模式选择信号:
    000:顺序执行
    001:beq分支跳转
    010:j/jal跳转
    011:jr跳转
    MemWriteDataOp O 2 写入DM数据选择信号
    00:RtData
    ifB O 1 是否为B类指令
    ifJ O 1 是否为J类指令
    BranchOp O 3 判断是否跳转的规则的选择信号
    3’b000:if(rsData == rtData) 跳转
    useRt O 1 判断该指令是否涉及到读Rt
    islink O 1 判断该指令是否要link(将PC + 8写入$31
    isConditionalLink O 1 判断该指令是否是条件link
    isLikely O 1 判断该指令是否涉及分支清空延迟槽

HCU(冒险控制单元)

  • 核心任务:(按优先级实现)

    1. 顶层是否空拍一周期?
    2. 是否需要转发?转发路径?
    3. 维持原数据
  • 模块规格

    信号名 方向 位宽 描述
    D_Rs I 5 ID中指令对应的Rs地址
    D_Rt I 5 ID中指令对应的Rt地址
    E_Rs I 5 EX中指令对应的Rs地址
    E_Rt I 5 EX中指令对应的Rt地址
    M_Rt I 5 MEM中指令对应的Rt地址
    E_WA I 5 “上一条”指令(EX中指令)最终要写入的寄存器地址
    M_WA I 5 “上上条”指令(MEM中指令)最终要写入的寄存器地址
    W_WA I 5 (WB中指令)最终要写入的寄存器地址
    E_RegWrite I 1 EX中指令是否涉及写寄存器
    M_RegWrite I 1 MEM中指令是否涉及写寄存器
    W_RegWrite I 1 WB中指令是否涉及写寄存器
    D_useRt I 1 ID中指令是否涉及到读Rt
    M_ifLink I 1 M中指令是否要link
    stall O 1 是否空拍一次
    D_RsData_Sel O 3 实际写入E_reg\NPC的数据选择信号
    000:原RsData
    001:M_ALUresult
    010:W_WD
    011:M_PC8
    100:EPC8
    tip:必须先判断是否涉及写入$0,再判断001&011,最后判断011(即是否涉及从最近的一条MEM的指令跳转)
    D_RtData_Sel O 3 实际写入E_reg的数据选择信号
    000:原RtData
    001:M_ALUresult
    010:W_WD
    011:M_PC8
    100:EPC8
    E_RsData_Sel O 3 实际写入ALUControl的数据选择信号
    000:原RsData
    001:M_ALUresult
    010: W_WD
    011: M_PC8
    100:EPC8
    E_RtData_Sel O 3 实际写入ALUControl的数据选择信号
    000:原RtData
    001:M_ALUresult
    010: W_WD
    011: M_PC8
    100:EPC8
    M_RtData_Sel O 3 实际写入MemWriteDataSel的数据选择信号
    000: 原RtData
    001: W_WD

BranchControl

  • 核心任务: 判断是否需要跳转
  • 整体设计:
  • 模块规格
    信号名 方向 位宽 描述
    rsData I 32 rs data
    rtData I 32 rt data
    ifB I 1 是否是B类指令
    ifJ I 1 是否为J类指令
    islink I 1 判断该指令是否要link(将PC + 8写入$31
    isConditionalLink I 1 判断该指令是否是条件link
    isLikely I 1 判断该指令是否涉及分支清空延迟槽
    BranchOp I 3 跳转规则的选择信号
    3’b000:beq
    BranchEn O 1 是否跳转
    ifLink O 1 是否真正要link
    D_flush O 1 是否清空延迟槽

NPC

  • 核心任务 计算下一周期PC应更新成的值

  • 整体设计 所有分支/跳转目标地址必须基于 D_PC

    • 顺序执行: NPC = PC + 4
    • 分支跳转:NPC = (PC + 4) + (SignExtend(offset))
    • j跳转:NPC = (PC + 4)31...28||instr_index||00
    • jr跳转:NPC = GPR[rs]
  • 模块规格

    信号名 方向 位宽 描述
    immEXT I 32 拓展后的立即数(offset)
    instr_index I 26 instr_index
    NPCop I 3 000:NPC = PC + 4
    001:分支跳转
    010:j
    011:jr
    rd1OrRs I 32 rs储存的值
    BranchEn I 1 B型指令是否跳转
    F_PC I 32 刚进入流水线(IF阶段取出)的指令地址
    D_PC I 32 D_PC
    NPC O 32 IFU中PC更新值

GRF

  • 整体设计
    • 读数据:指令最多需要同时读取两个不同地址的数据 - 两个读端口
    • 写数据
    • 0 号寄存器的值始终保持为 0。其他寄存器初始值(复位后)均为 0,无需专门设置

  • 模块规格:
    信号名 方向 位宽 描述
    reset I 1 异步复位信号
    clk I 1 时钟信号
    RA1 I 5 读地址1
    RA2 I 5 读地址2
    WA I 5 写地址
    WD I 32 写数据
    RegWrite I 1 写使能信号
    RD1 O 32 读数据1
    RD2 O 32 读数据2

WASel

  • 整体设计 选择存入GRF的地址
  • 模块规格:
    信号名 方向 位宽 描述
    RegDst I 3 GRF写回地址选择信号:
    001:rt
    000:rd
    010:rs
    011:GPR[31]
    rs I 5 rs
    rt I 5 rt
    rd I 5 rd

EXT

  • 核心任务 把16位立即数扩展到32位
  • 整体设计 能够对立即数进行零扩展/符号扩展
  • 模块规格
    信号名 方向 位宽 描述
    immOrOffset I 16 待扩展的立即数
    EXTop I 1 扩展方式选择信号:
    1 - 符号扩展
    0 - 零扩展
    immEXT O 32 扩展后的立即数

E

Reg_E

  • 模块规格
    信号名 方向 位宽 描述
    clk I 1 clock
    reset I 1 同步复位信号
    stall I 1 清零信号
    D_ControlBus I CTL_BUS_WIDTH D_ControlBus
    D_instruction I 32 D_instruction
    D_RD1 I 32 D_RD1
    D_RD2 I 32 D_RD2
    D_immEXT I 32 D_immEXT
    D_PC I 32 D_PC
    D_WA I 5 D_WA
    D_ifLink I 1 D_ifLink
    E_ControlBus O CTL_BUS_WIDTH E_ControlBus
    E_instruction O 32 E_instruction
    E_RD1 O 32 E_RD1
    E_RD2 O 32 E_RD2
    E_immEXT O 32 E_immEXT
    E_PC O 32 E_PC
    E_WA O 5 E_WA
    E_ifLink O 1 E_ifLInk

EX

ALUControl

  • 整体设计 为alu选择operand1,operand2
  • 模块规格
    信号名 方向 位宽 描述
    RsData I 32 RsData
    RtData I 32 RtData
    immEXT I 32 扩展后的立即数
    shamt I 5 shamt
    aluControlSel I 3 选择信号
    000:rs/rt
    001:rs/imm
    operand1 O 32 operand1
    operand2 O 32 operand2

ALU

  • 整体设计
    • 能够实现多种运算功能,并根据ALUop选择对应功能
      ALUop 运算
      0000 无符号op1 + op2
      0001 无符号op1 - op2
      0010 op1 & op2
      0011 op1 | op2
      0100 op2低16位加载至高位,低位补0
      0101 $signed(operand1)<$signed(operand2) ? 1:0
  • 模块规格
    信号名 方向 位宽 描述
    ALUop I 4 选择运算功能
    operand1 I 32 operand1
    operand2 I 32 operand2
    ALUresult O 32 运算结果

M

Reg_M

  • 模块规格
    信号名 方向 位宽 描述
    clk I 1 clock
    reset I 1 同步复位信号
    E_ControlBus I CTL_BUS_WIDTH+1 来自 E 级的控制信号
    E_instruction I 32 E_instruction
    E_ALUresult I 32 E_ALUresult
    E_RD1 I 32 E_RD1
    E_RD2 I 32 E_RD2
    E_immEXT I 32 E_immEXT
    E_MemWriteData I 32 E_MemWriteData
    E_PC I 32 E_PC
    E_WA I 5 E_WA
    E_ifLink I 1 E_ifLInk
    M_ControlBus O CTL_BUS_WIDTH+1 M_ControlBus
    M_instruction O 32 M_instruction
    M_ALUresult O 32 M_ALUresult
    M_RD1 O 32 M_RD1
    M_RD2 O 32 M_RD2
    M_immEXT O 32 M_immEXT
    M_MemWriteData O 32 M_MemWriteData
    M_PC O 32 M_PC
    M_WA O 5 M_WA
    M_ifLink O 1 M_ifLInk

MEM

MemWriteDataSel

  • 整体设计 选择写入内存的数据
  • 模块规格
    信号名 方向 位宽 描述
    MemWriteDataOp I 2 写入DM数据选择信号
    00:RtData
    RtData I 32 rt data
    MemWriteData O 32 写入DM的数据

DM

  • 模块规格
    信号名 方向 位宽 描述
    Address I 32 读/写地址,默认是ALUresult
    WriteData I 32 要写入的数据
    MemWrite I 1 写使能信号
    MemRead I 1 读使能信号
    clk I 1 时钟信号
    reset I 1 异步复位信号
    PC I 32 当前指令的地址
    LoadType I 2 load模式选择信号
    2’b00:lw
    2’b01:lh
    SaveType I 2 Save模式选择信号
    2’b00:sw
    2’b01:sh
    MemReadData O 32 读出的数据

W

Reg_W

  • 模块规格
    信号名 方向 位宽 描述
    clk I 1 clock
    reset I 1 同步复位信号
    M_ControlBus I CTL_BUS_WIDTH+1 来自 M 级的控制信号
    M_instruction I 32 M_instruction
    M_ALUresult I 32 M_ALUresult
    M_RD1 I 32 M_RD1
    M_RD2 I 32 M_RD2
    M_immEXT I 32 M_immEXT
    M_MemReadData I 32 M_MemReadData
    M_PC I 32 M_PC
    M_WA I 5 M_WA
    M_ifLink I 1 M_ifLInk
    W_ControlBus O CTL_BUS_WIDTH+1 W_ControlBus
    W_instruction O 32 W_instruction
    W_ALUresult O 32 W_ALUresult
    W_RD1 O 32 W_RD1
    W_RD2 O 32 W_RD2
    W_immEXT O 32 W_immEXT
    W_MemReadData O 32 W_MemReadData
    W_PC O 32 W_PC
    W_WA O 5 W_WA
    W_ifLink O 1 W_ifLInk

WB

WDSel

  • 整体思路 选择写回GRF的数据
  • 模块规格
    信号名 方向 位宽 描述
    WDsel I 2 GRF写入数据选择信号:
    00:ALU运算结果
    01:DM读出的数据(lw)
    10:PC + 8(延迟槽)
    ALUresult I 32 ALU运算结果
    MemData I 32 DM读出的数据
    PC I 32 PC
    WD O 32 WD

测试

测试覆盖

  1. 基本指令功能
  2. 转发测试
  3. 暂停测试

基本指令功能测试

转发测试

按照完备性表格分类测试

转发到/数据来源 M锁存的ALUresult W_WD M_PC8
ID stage RtData/RsData RtData/RsData RtData/RsData
EX stage RtData/RsData RtData/RsData RtData/RsData
MEM stage 不存在 RtData 不存在
  • (1,1):ID ← M_ALUresult

    1
    2
    3
    4
    5
    ori $3, $0, 1
    ori $4, $0, 2
    beq $5, $3, label
    label:
    nop
  • (1,2):ID ← W_WD

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
      ori $3, $0, 1
    ori $4, $0, 2
    ori $6, $0, 2
    beq $5, $3, label
    label:
    nop
    ```
    - (13):ID ← M_PC + 8

    ```mips
    jal return
    ori $4, $0, 2
    beq $5, $31, label
    return:
    jr $31
    label:
    nop
    ```
    - (21):EX ← M_ALUresult

    ```mips
    ori $3, $0, 1
    ori $4, $3, 2
    ```
    - (22):EX ← W_WD

    ```mips
    ori $3, $0, 1
    add $5, $3, $3
    ori $4, $3, 2
    ```
    - (23):EX ← M_PC + 8

    ```mips
    jal return
    ori $4, $31, 2
    return:
    jr $31
    label:
    nop
    ```


    - (32):MEM ← W_WD

    ```mips
    ori $3, $0, 5
    sw $3, 0($0)
    ```

    ## 暂停测试
    - E_Conflict:
    ```mips
    ori $1,$0,3
    beq $1,$0,label
    label:
    nop
  • M_Conflict:

    1
    2
    3
    4
    5
    lw $1, 0($0)      
    nop
    beq $1, $0, label
    label:
    nop

测试出来的问题

link类

  • 问题
    • 我默认传递的PC值不会被覆盖,所以在WB阶段直接写入W_PC + 4。但实际上由于stall、D_flush的存在,PC值在中间是可能被覆盖的。
      • 所以为了保证link的正确性,我们应该额外设置数据通路,将实际要写回的D_PC + 4往后传。

What is FLUSH ?

  • D_flush(likely导致的):在D级注入一条nop(本质:REPLACEMENT
    • 清空instruction
    • PC保持原值
  • E_flush(stall导致的):在E级注入一条nop(本质:INSERTION
    • 清空instruction
    • PC保持原值(该nop是凭空加在两条指令之间的,没有对应的PC)

思考题

  1. 我们使用提前分支判断的方法尽早产生结果来减少因不确定而带来的开销,但实际上这种方法并非总能提高效率,请从流水线冒险的角度思考其原因并给出一个指令序列的例子。

    • 原因:提前判断需要RsData和RtData,而这两个数据可能需要转发。如果HCU判断需要stall,那么提前判断节省的一个T和stall延迟的一个T就抵消了,并没有提高效率。
    • 例如:
      1
      2
      lw   $t0, 0($t1)    
      beq $t0, $zero, L
  2. 因为延迟槽的存在,对于 jal 等需要将指令地址写入寄存器的指令,要写回 PC + 8,请思考为什么这样设计?

    • jal把下一条“应该执行”的指令地址写入$ra$31),但由于延迟槽的存在,下一条要执行的指令实际上是PC + 8处的(下下条)指令。
  3. 我们要求大家所有转发数据都来源于流水寄存器而不能是功能部件(如 DM 、 ALU ),请思考为什么?

    • 功能部件在同一周期内输出还不稳定,但来自流水寄存器的数据已经进行过一次锁存,是稳定的数据
    • 运用其它阶段正在计算的中间值本质上破坏了流水线的时序结构,相当于又类似单周期CPU一样形成了横跨各阶段的巨大组合逻辑
  4. 我们为什么要使用 GPR 内部转发?该如何实现?

    • 内部转发本质:当GRF同时在WB被写入,在ID被读出,且存在读写寄存器冲突,读出的寄存器值应为新写入的值
    • 如果不实现内部转发,就会引发同周期的WD-ID数据冒险
    • 实现:
      1
      2
      assign RD1 = (RA1 != 0 && RA1 == WA && RegWrite) ? WD : register[RA1];
      assign RD2 = (RA2 != 0 && RA2 == WA && RegWrite) ? WD : register[RA2];
  5. 我们转发时数据的需求者和供给者可能来源于哪些位置?共有哪些转发数据通路? 需求者\供给者|M锁存的ALUresult|W_WD|M_PC8|E_PC8 —|—|—|— ID stage:|RtData/RsData|RtData/RsData|RtData/RsData|RtData/RsData EX stage:|RtData/RsData|RtData/RsData|RtData/RsData|不存在 MEM stage:|不存在|RtData|不存在|不存在

  6. 在课上测试时,我们需要你现场实现新的指令,对于这些新的指令,你可能需要在原有的数据通路上做哪些扩展或修改?提示:你可以对指令进行分类,思考每一类指令可能修改或扩展哪些位置。

    • 对指令进行分类
      • R_cal
      • I_cal
      • B
      • J
        • B&J可能有以下属性
          • Link
          • Likely
          • ConditionalLink
      • Load:所有涉及到读dm的指令
      • Save
    • 具体见上“加指令思路”
  7. 确定你的译码方式,简要描述你的译码器架构,并思考该架构的优势以及不足。

    • 选择集中式译码 & 控制信号驱动型译码
    • 优势:
      • 集中式译码:只用设置一个Control单元,译码之后把ControlBus一直往后传即可
      • 控制信号驱动型译码:代码简洁,拓展性好
    • 不足:
      • 集中式译码:ControlBus位宽大(即数据通路过宽)

Copyright © 2026 CRZ's Blog

Powered by Hexo • Theme Candelas