HNU计算机体系结构-实验一:RISC-V指令理解

news2024/11/23 17:08:33

HNU计算机体系结构-实验一

  • 前言
    • 1.实验目的
    • 2.实验步骤
      • 1.安装模拟器Ripes
      • 2.生成汇编指令
      • 3.思考问题
        • 1)指令`add x15, x14, x15`
        • 2)指令`bge x15 x14 -68`
        • 3)指令`lw x15, -20 x8`
        • 4)指令`sw x15, -20 x8`
        • 5)简述BranchE信号的作用
        • 6)NPC Generator
      • 4.附加思考题:
        • 1)插入气泡
        • 2)branch指令
    • 3.实验总结

前言

体系结构的第一个实验,实际上是中科大的实验,GitHub直接搜ustc_ca可以搜出很多,我也是借鉴了几位大佬的。这个课是计科第一年开课的,所以以后的实验内容可能会有所调整。

这次实验的内容也很简单,用ripes跑一遍即可,这个软件还是很智能的,每一步骤干什么,用的哪个寄存器,以及数值是多少都能显示出来。

闲麻烦不想在GitHub上下载的,直接放到网盘了。

具体用法是先打开ripes.exe,左上角editor->setiing,然后
在这里插入图片描述
选择另一个文件夹里的编译器,然后就可以运行代码了。
在这里插入图片描述

一般这个实验都在期中前做的,所以一定要认认真真的跑一遍流水线,把一些基本指令的流程都弄懂,期中必考的。
还有一个坑就是bge指令的立即数那里,它那个是要左移一位的,最高位补的数字和次高位一样

1.实验目的

参考提供为了更好的理解RISC-V,通过学习RV32I Core的设计图,理解每条指令的数据流和控制信号,为之后指令流水线及乱序发射实验打下基础。

看不清的可以下载
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b2v9Zhr2-1686648622231)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1680504587112.png)]

各部分的部件的主要控制信号如下:

1.HarzardUnit

流水线冲突处理模块,基本手段:(1)插入气泡stall,(2)定向路径(前递,转发)forward,(3)冲刷流水段flush,组合逻辑电路,信号说明:

输入:

  • CpuRst: 外部信号,用来初始化CPU,当CpuRst1时CPU全局复位清零(所有段寄存器flush),Cpu_Rst0时cpu开始执行指令
  • ICacheMiss, DCacheMiss:为后续实验预留信号,暂时可以无视,用来处理cache miss
  • BranchE,JalrE,JalD: 控制相关处理信号
  • Rs1D,Rs2D,Rs1E,Rs2E,RdE,RdM,RdW: 译码,执行,访存,写会阶段处理数据相关的信号,对应的源寄存器和目标寄存器号码。
  • RegReadE: 标记A1A2对应的寄存器值是否被用到。
  • MemToRegE: 标志EX段从data mamory加载数据到寄存器
  • RegWriteM,RegWriteW: 标记MEM段和WB段是否有目标寄存器写入操作。

输出:

  • StallF,FlushF: IF段插入气泡(维持状态不变)/冲刷(清零)
  • StallD,FlushD: ID段插入气泡/冲刷
  • StallE,FlushE: EX段插入气泡/冲刷
  • StallM,FlushM: MEM段插入气泡/冲刷
  • StallW,FlushW: WB段插入气泡/冲刷
  • Forward1E,Forward2E: 定向路径控制信号

2.ControlUnit

控制模块(译码器),根据指令的操作码部分Op,func3部分Fn3和func7部分Fn7产生如下控制信号:

输入:

  • Op:是指令的操作码部分
  • Fn3:是指令的func3部分
  • Fn7:是指令的func7部分

输出:

  • JalD==1: 标志Jal指令到达指令ID译码阶段
  • JalrD==1: 标志Jalr指令到达指令ID译码阶段
  • RegWriteD: 表示指令ID译码阶段的寄存器写入模式
  • MemToRegD==1: 标志ID阶段指令需要从data memory读取数据到寄存器
  • MemWriteD: 共4bit,为1的部分有效,指示data memory的四个字节中哪些需要写入
  • LoadNpcD: 标志将NextPC输出到ResultM
  • RegReadD: 标志两个源寄存器的使用情况,RegReadD[1] == 1,表示A1对应的寄存器值被使用到了,RegReadD[0] == 1,表示A2对应的寄存器值被使用到了,用于forward处理
  • BranchTypeD: 表示不同分支类型(参见BranchDecisionMaking部分)
  • AluContrlD: 表示不同算数逻辑运算种类(参见ALU部分)
  • AluSrc2D: Alu输入源Operand2的选择
  • AluSrc1D: Alu输入源Operand1的选择
  • ImmType: 立即数编码格式类型

3.NPC_Generator

用来生成Next PC值的模块,根据不同的跳转信号选择不同的新PC值

输入:

  • PCF:旧的PC值
  • JalrTarget:jalr指令的对应的跳转目标
  • BranchTarget:branch指令的对应的跳转目标
  • JalTarget:jal指令的对应的跳转目标
  • BranchE==1:Ex阶段的Branch指令确定跳转
  • JalD==1:ID阶段的Jal指令确定跳转
  • JalrE==1:Ex阶段的Jalr指令确定跳转

输出:

  • PC_In:NPC的值

4.RegisterFile

上升沿写入,异步读的寄存器堆,0号寄存器值始终为32’b0

5.ImmOperandUnit

利用正在被译码的指令的部分编码值,生成不同类型的32bit立即数

输入:

  • IN:是指令除了opcode以外的部分编码值
  • Type:表示立即数编码类型,全部类型定义在Parameters中

输出:

  • OUT:表示指令对应的立即数32bit实际值

6.BranchDecisionMaking

跳转判断单元,根据控制信号BranchTypeE指定的分支类型,对操作数Operand1Operand2进行比较并决定是否跳转,将判断结果通过BranchE输出。各分支类型对应的控制信号如下

7.ALU

算数逻辑运算单元,接受Operand1Operand2两个操作数,按照控制信号AluContrl执行对应的算术逻辑运算,将结果从AluOut输出

8.DataExt

输入:

  • IN:是从Data Memory中load的32bit字
  • LoadedBytesSelect:等价于AluOutM[1:0],是读Data Memory地址的低两位,因为DataMemory是按字(32bit)进行访问的,所以需要把字节地址转化为字地址传给DataMem,DataMem一次返回一个字,低两位地址用来从32bit字中挑选出我们需要的字节
  • RegWriteW:表示不同的寄存器写入模式,所有模式定义在Parameters中

输出:

  • OUT:表示要写入寄存器的最终值

2.实验步骤

参考提供的RISC-V 32I的设计图,思考每条指令的数据通路,熟悉RISC-V电路图,并且为后续动态分支预测和Tomasulo实验打下基础。

1.安装模拟器Ripes

具体步骤见https://github.com/mortbopet/Ripes

已提供riscv32gcc编译器的ubuntu版本和windows版本,其余版本下载参考:

https://github.com/mortbopet/Ripes/blob/master/docs/c_programming.md

下载后页面如下:

在这里插入图片描述

2.生成汇编指令

输入以下代码后生成对应汇编指令

void main()
{
     int A[100];
     int i;
     for(i=0;i<100;i++)
       A[i]=i;
     for(i=1;i<100;i++)
       A[i]=A[i-1]+1000;
}

生成的汇编指令如下:

00010144 <main>://主函数的开始
	//x2的值减去432,然后存回x2。x2寄存器是栈指针,这条指令是为了分配栈空间
    10144:        e5010113        addi x2 x2 -432
    //x8的值存储到x2加上428的内存地址。x8寄存器是帧指针,所以这条指令是为了保存帧指针。
    10148:        1a812623        sw x8 428 x2
    //x2寄存器的值加上432,然后存回x8寄存器。这条指令是为了更新帧指针
    1014c:        1b010413        addi x8 x2 432
    //x0寄存器的值存储到x8寄存器减去20的内存地址。这条指令初始化一个局部变量i为0
    10150:        fe042623        sw x0 -20 x8
    //无条件跳转到当前地址加上40的位置,并将返回地址存储到x0寄存器。
    //因为x0寄存器是零寄存器,所以返回地址会被丢弃。这条指令是为了跳过下面的循环体。
    10154:        0280006f        jal x0 40
    //将x8寄存器减去20的内存地址的值加载到x15寄存器。这条指令是为了读取局部变量i的值
    10158:        fec42783        lw x15 -20 x8
    //将x15寄存器的值左移两位,然后存回x15寄存器。这条指令相当于将i乘以4,因为每个整数占4个字节
    1015c:        00279793        slli x15 x15 2
    //将x8寄存器的值减去16,然后存回x14寄存器。这条指令是为了计算数组A在栈上的起始地址
    10160:        ff040713        addi x14 x8 -16
    //将x14寄存器和x15寄存器的值相加,然后存回x15寄存器。这条指令是为了计算A[i]在栈上的地址
    10164:        00f707b3        add x15 x14 x15
    //将x8寄存器减去20的内存地址的值加载到x14寄存器。这条指令又一次读取局部变量i的值
    10168:        fec42703        lw x14 -20 x8
    //将x14寄存器的值存储到x15寄存器减去404的内存地址。这条指令相当于执行A[i]=i
    1016c:        e6e7a623        sw x14 -404 x15
    //将x8寄存器减去20的内存地址的值加载到x15寄存器。这条指令又一次读取局部变量i的值
    10170:        fec42783        lw x15 -20 x8
    //将x15寄存器的值加上1,然后存回x15寄存器。这条指令相当于执行i++
    10174:        00178793        addi x15 x15 1
    //将x15寄存器的值存储到x8寄存器减去20的内存地址。这条指令相当于更新局部变量i的值
    10178:        fef42623        sw x15 -20 x8
    //将x8寄存器减去20的内存地址的值加载到x14寄存器。这条指令又一次读取局部变量i的值
    1017c:        fec42703        lw x14 -20 x8
    //将x0寄存器的值加上99,然后存回x15寄存器。这条指令相当于将99赋值给一个临时变量
    10180:        06300793        addi x15 x0 99
    //比较x15寄存器和x14寄存器的值,如果x15大于等于x14,就跳转到当前地址减去44的位置。
    //这条指令相当于执行if(i<100) goto loop
    10184:        fce7dae3        bge x15 x14 -44
    //将x0寄存器的值加上1,然后存回x15寄存器。这条指令相当于初始化一个局部变量j为1
    10188:        00100793        addi x15 x0 1
    //将x15寄存器的值存储到x8寄存器减去20的内存地址。这条指令相当于更新局部变量j的值
    1018c:        fef42623        sw x15 -20 x8
    //无条件跳转到当前地址加上64的位置,并将返回地址存储到x0寄存器。
    //因为x0寄存器是零寄存器,所以返回地址会被丢弃。这条指令是为了跳过下面的循环体。
    10190:        0400006f        jal x0 64
    //将x8寄存器减去20的内存地址的值加载到x15寄存器。这条指令是为了读取局部变量j的值
    10194:        fec42783        lw x15 -20 x8
    //将x15寄存器的值减去1,然后存回x15寄存器。这条指令相当于执行j–1
    10198:        fff78793        addi x15 x15 -1
    //将x15的值左移两位,然后存回x15寄存器。这条指令相当于将j-1乘以4,因为每个整数占4个字节
    1019c:        00279793        slli x15 x15 2
    //将x8寄存器的值减去16,然后存回x14寄存器。这条指令是为了计算数组A在栈上的起始地址
    101a0:        ff040713        addi x14 x8 -16
    //将x14寄存器和x15寄存器的值相加,然后存回x15寄存器。这条指令是为了计算A[j-1]在栈上的地址
    *101a4:        00f707b3        add x15 x14 x15
    //将x15寄存器减去404的内存地址的值加载到x15寄存器。这条指令相当于获得A[j-1]的值
    101a8:        e6c7a783        lw x15 -404 x15
    //将x15寄存器的值加上1000,然后存回x14寄存器。这条指令相当于将A[j-1]+1000的值存在x14中
    101ac:        3e878713        addi x14 x15 1000
    //将x8寄存器减去20的内存地址的值加载到x15寄存器。这条指令又一次读取局部变量j的值
    101b0:        fec42783        lw x15 -20 x8
    //将x15寄存器的值左移两位,然后存回x15寄存器。这条指令相当于将j乘以4,因为每个整数占4个字节
    101b4:        00279793        slli x15 x15 2
    //将x8寄存器的值减去16,然后存回x13寄存器。这条指令是为了计算数组A在栈上的起始地址
    101b8:        ff040693        addi x13 x8 -16
    //将x13寄存器和x15寄存器的值相加,然后存回x15寄存器。这条指令是为了计算A[j]在栈上的地址
    101bc:        00f687b3        add x15 x13 x15
    //将x14寄存器的值存储到x15寄存器减去404的内存地址。这条指令相当于执行A[j]=A[j-1]+1000
    101c0:        e6e7a623        sw x14 -404 x15
    //将x8寄存器减去20的内存地址的值加载到x15寄存器。这条指令又一次读取局部变量j的值
    *101c4:        fec42783        lw x15 -20 x8
    //将x15寄存器的值加上1,然后存回x15寄存器。这条指令相当于执行j++
    101c8:        00178793        addi x15 x15 1
    //将x15寄存器的值存储到x8寄存器减去20的内存地址。这条指令相当于更新局部变量j的值
    *101cc:        fef42623        sw x15 -20 x8
    //将x8寄存器减去20的内存地址的值加载到x14寄存器。这条指令又一次读取局部变量j的值
    101d0:        fec42703        lw x14 -20 x8
    //将x0寄存器的值加上99,然后存回x15寄存器。这条指令相当于将99赋值给一个临时变量
    101d4:        06300793        addi x15 x0 99
    //比较x15寄存器和x14寄存器的值,如果x15大于等于x14,就跳转到当前地址减去68的位置。
    //这条指令相当于执行if(j<100) goto loop;
    *101d8:        fae7dee3        bge x15 x14 -68
    //将x0寄存器的值加上0,然后存回x0寄存器。这条指令没有实际作用,只是为了占位
    101dc:        00000013        addi x0 x0 0
    //将x2寄存器加上428的内存地址的值加载到x8寄存器。这条指令是为了恢复帧指针
    101e0:        1ac12403        lw x8 428 x2
    //将x2寄存器的值加上432,然后存回x2寄存器。这条指令是为了释放栈空间
    101e4:        1b010113        addi x2 x2 432
    //跳转到x1寄存器加上0的地址,并将返回地址存储到x0寄存器。
    //因为x0寄存器是零寄存器,所以返回地址会被丢弃。这条指令是为了从main函数返回
    101e8:        00008067        jalr x0 x1 0

3.思考问题

找出循环A[i]=A[i-1]+1000;对应的汇编代码,思考以下问题:

1)指令add x15, x14, x15

问题描述:分析指令add x15, x14, x15(x是指以x开头的通用寄存器),写出该指令在流水线五个阶段(IF、ID、EX、MEM和WB)关键的控制信号(参考RISC V电路设计图),并通过分析指出数据通路

答:这条指令的作用是将x14寄存器中的值加上x15寄存器中的值存到x15寄存器中,其中x14寄存器存入的是数组A的基址地址,x15存入的是偏移量,两者相加后获得A[j-1]的地址

R-型指令funct7rs2rs1funct3rdopcode
add00000000111101110000011110110011

这条指令是一条R类型的指令

  • IF阶段

    • 数据通路
    • 根据PCF,从指令存储器中取出指令00000000111101110000011110110011
      • PC寄存器的值加4,更新为下一条指令的地址
    • 控制信号:无
  • ID阶段

    • 数据通路
    • IF/ID寄存器中译码出指令的操作码(inst[6:0])
      • 在寄存器文件中读出源寄存器地址(inst[24:20],inst[19:15])对应地址的值,送入A1A2寄存器,送往ID/EX寄存器
      • 将目的寄存器地址(inst[11:7]) 送往ID/EX寄存器
      • IF/ID中得到指令段,送往Control Unit控制单元产生控制信号
    • 控制信号
      • ImmType=3'd0(代表是R类型指令,无需生成立即数)
  • EX阶段

    • 数据通路:
      • A1A2寄存器中取出两个源操作数,送入ALU进行加法运算,得到结果,送入ALUOutE,结果送入EX/MEM寄存器。
      • 上一级传入的控制信号传入下一阶段
      • ID/EX中得到Rd(目的寄存器地址),送往EX/MEM寄存器
    • 控制信号:
      • AluContrlE=3ALU执行加法操作
      • Forward1E=2'b00,第一个操作数选择来自A1寄存器的值
      • Forward2E=2'b00,第二个操作数选择来自A2寄存器的值
      • ALUSrc1E=1ALU第一个操作数来自A1寄存器
      • ALUSrc2E=2'00ALU第二个操作数来自A2寄存器
      • RegReadE[1]=1A1对应的寄存器值被使用到了
      • RegReadE[0]=1A2对应的寄存器值被使用到了
  • MEM阶段

    • 数据通路:
      • EX/MEM寄存器中取出运算结果ALUOutM,送入数据存储器和MemData多路选择器,存入MEM/WB寄存器中。
      • 上一级控制信号传入下一阶段
      • EX/MEM中得到Rd(目的寄存器地址),送往MEM/WB寄存器
    • 控制信号:
      • LoadNpcD=1: 将下一条指令的地址存储到ResultM中,以便在WB阶段更新PC寄存器的值
      • MemWriteM=4'0,不写内存
  • WB阶段

    • 数据通路

      • MEM/WB寄存器中取出写回数据,根据RegDst信号选择目的寄存器地址,将数据写入寄存器文件。
    • 控制信号

      • MemToRegW=1,选择将ALU运算结果传入寄存器文件中
      • RegWriteW=1,写回目的寄存器

2)指令bge x15 x14 -68

问题描述:分析指令bge x15, x14, -68,写出该指令在流水线五个阶段(IF、ID、EX、MEM和WB)关键的控制信号(参考RISC V电路设计图),并通过分析指出数据通路

答:这条指令的作用是比较x15寄存器和x14寄存器的值,如果x15大于等于x14,就跳转到当前地址减去68的位置。这条指令相当于执行if(j<100) goto loop。

指令输入SB-型指令,只会执行IF,ID和EX段。

  • IF阶段
    • 数据通路
      • 根据PCF,从指令存储器中取出指令11111010111001111101111011100011。
      • PC寄存器的值加4,更新为下一条指令的地址。
    • 控制信号:无
  • ID阶段:
    • 数据通路:
      • 寄存器堆A1A2地址分别为rs1rs2,读出待比较的值RegOut1DRegOut2D
      • Immediate Generate生成立即数并传入ImmD,左移一位后与PCD相加得到JalNPC,传入段寄存器
      • 指令Inst传给Controller Decoder,生成控制信号
    • 控制信号:
      • ImmTypeD=3’b011,Imm左移两位并符号扩展,传入ImmD,结果为-224
  • EX阶段:
    • 数据通路:
      • Branch Decision单元执行Reg1-Reg2 ,如果结果大于等于0,则BrE信号应该被设置为1,表示应该跳转。
      • 否则BrE应该被设置为0,表示不跳转,指令继续按地址的顺序执行
    • 控制信号:
      • BranchTypeE=3’001,代表BEQ指令
      • BrE=1,代表跳转,
      • BrT信号应该被设置为当前指令地址加上偏移量(-68),即PC + ImmE,即-68<<2(PC是当前指令的地址,左移两位是因为指令存储器是四字节地址寻址的)
      • BrE=0,代表不跳转, 则BrT信号被设置为下一条指令的地址,即PC+4
      • Forward1E=2'b00,第一个操作数选择来自A1寄存器的值
      • Forward2E=2'b00,第二个操作数选择来自A2寄存器的值
      • ALUSrc1E=1,reg1来自A1寄存器
      • ALUSrc2E=2'00,reg2来自A2寄存器

3)指令lw x15, -20 x8

问题描述:分析指令lw x15, -20 x8,写出该指令在流水线五个阶段(IF、ID、EX、MEM和WB)关键的控制信号(参考RISC V电路设计图),并通过分析指出数据通路

答:指令的作用是将x8寄存器减去20的内存地址的值加载到x15寄存器。其中x8寄存器减去20的内存地址的值即为局部变量i的值,所以这里是将i的值赋给x15寄存器

I-型指令immediaters1funct3rdopcode
lw11111110110001000010011110000011

这是一条I-型指令:

  • IF阶段
    • 数据通路:
      • 根据PCF,从指令存储器中取出指令11111110110001000010011110000011
      • PC寄存器的值加4,更新为下一条指令的地址。
    • **控制信号:**无
  • ID阶段
    • 数据通路:
      • 指令Inst传给Controller Decoder,生成控制信号
      • A1读入源寄存器地址(inst[19:15]),将读出的值RegOut1D送入ID/EX寄存器
      • 将目的寄存器地址(inst[11:7])rd送往ID/EX寄存器
      • Immediate Generate生成立即数,将立即数扩展为32位,送入ImmD,接着送入ID/EX寄存器。
    • 控制信号:
      • ImmType=3'd1,代表是I类型指令,需要生成立即数
      • RegWriteW=1,结果写回目的寄存器x15
  • EX阶段
    • 数据通路:
      • 从A1寄存器和ImmOperandUnit中取出两个源操作数,送入ALU进行加法运算,得到内存地址,送入ALUOutE,结果送入EX/MEM寄存器。
      • 从上一级获得控制信号并传入下一级
      • ID/EX中得到Rd地址,送往EX/MEM寄存器
    • 控制信号:
      • AluContrlE=4'b0011ALU执行加法操作
      • Forward1E=2'b00,第一个操作数选择来自A1寄存器的值
      • Forward2E=2'b01,第二个操作数选择来自立即数
      • ALUSrc1E=1'b1ALU第一个操作数来自A1寄存器
      • ALUSrc2E=2'b00ALU第二个操作数来自Imm寄存器
      • RegReadE[1]=1A1对应的寄存器值被使用到了
  • MEM阶段
    • 数据通路:
      • EX/MEM中得到ALU运算结果,送往数据存储器取出对应地址内容,内容送往MEM/WB寄存器
      • 从上一级获得控制信号并传入下一级
      • EX/MEM中得到Rd地址,送往MEM/WB寄存器
    • 控制信号:
      • LoadNpcD=0,将NextPC输出到ResultM
      • MemWriteM=4'b0000,不写内存
  • WB阶段
    • 数据通路:
      • MEM/WB中得到存储器内容,送往DataExt数据扩展单元扩展后送往寄存器堆
      • MEM/WB中得到Rd写回地址,送往寄存器堆用于写回上方内容
    • 控制信号:
      • MemToRegW=0,标志WB阶段指令需要从内存读取数据到寄存器
      • RegWriteW=1,写回目的寄存器x15
      • LoadedBytesSelect=4,相当于ResultW[3:0],即选取要取的4字节数据

4)指令sw x15, -20 x8

问题描述:分析指令sw x15, -20 x8,写出该指令在流水线五个阶段(IF、ID、EX、MEM和WB)关键的控制信号(参考RISC V电路设计图),并通过分析指出数据通路

答:这是一条S-型指令,它的作用是将寄存器x15中的值存储到地址为寄存器x8中的值减去20处的内存中。这条指令相当于更新局部变量i的值

  • IF阶段
    • 数据通路:
      • 根据PCF,从指令存储器中取出指令11111110111101000010011000100011
      • PC寄存器的值加4,更新为下一条指令的地址。
    • 控制信号:无
  • ID阶段
    • 数据通路:
      • 指令Inst传给Controller Decoder,生成控制信号
      • A2读入源寄存器地址(inst[24:20]),将读出的值RegOut2D送入ID/EX寄存器
      • A1读入目的寄存器地址(inst[19:15]),将读出的值RegOut1D送入ID/EX寄存器
      • Immediate Generate生成立即数,将立即数扩展为32位,送入ImmD,接着送入ID/EX寄存器。
    • 控制信号:
      • ImmType,S类型指令,需要生成立即数
  • EX阶段
    • 数据通路:
      • A1寄存器和ImmOperandUnit中取出两个源操作数,送入ALU进行加法运算,得到要写入的内存地址,送入ALUOutE,结果送入EX/MEM寄存器。
      • 从上一级获得控制信号并传入下一级
      • ID/EX中得到A2寄存器读出的值RegOut2E,送往EX/MEM寄存器
    • 控制信号:
      • AluContrlE=3,代表ALU执行ADD运算
      • Forward1E=2'b00,第一个操作数选择来自A1寄存器的值
      • Forward2E=2'b00,将A2寄存器读出的值RegOut2E传递下去
      • AluSrc1E=1'b1,代表ALU第一个操作数来自A1寄存器
      • AluSrc2E=2'b10,代表ALU第二个操作数来自Imm寄存器
      • RegReadE[1]=1A1对应的寄存器值被使用到了
  • MEM阶段
    • 数据通路:
      • EX/MEM寄存器读出要写入内存的值,通过StoreDataM写入Data MemoryWD接口
      • EX/MEM寄存器读出要写入的内存地址,AluOutM写入A接口
      • 从上一级获得控制信号并传入下一级
    • 控制信号:
      • LoadNpcD=1,将NextPC输出到ResultM
      • MemWriteM=1,本条指令需要将数据写入内存
  • WB阶段
    • 数据通路:无需进行写回操作。
    • 控制信号:
      • MemToRegW=0,不需要从内存读取数据到寄存器
      • RegWriteW=0,不需要写回目的寄存器

5)简述BranchE信号的作用

BranchE信号是指令执行(EX)阶段的一个控制信号,用于判断是否需要进行分支跳转。在流水线的EX阶段

  • 如果指令是分支指令,例如beq、bne等,那么BranchE信号将被设置为1,表示需要进行分支跳转。同时,根据指令的操作数和ALU的计算结果,计算出是否需要跳转,即将BrT信号设置为1或0。
    • 如果需要跳转,则将跳转目标地址计算出来,并将其写入PC寄存器,以便在下一次IF阶段时取出目标指令进行执行。
    • 否则,PC寄存器继续累加4,直接取出下一条指令进行执行

6)NPC Generator

NPC Generator 中对于不同跳转 target 的选择有没有优先级?如果有,请举例并分析。如果没有,请解释原因

答:有。

JalrT、BrT 和 JalT 是 RISC-V CPU 中用于控制跳转指令的信号。

  • JalrT:Jalr Target,用于指示 CPU 是否需要跳转到 Jalr 指令中给定的目标地址。当 JalrT 信号为高电平时,CPU 将跳转到 Jalr 指令中给定的目标地址。
  • BrT:Branch Target,用于指示 CPU 是否需要跳转到分支指令中给定的目标地址。当 BrT 信号为高电平时,CPU 将跳转到分支指令中给定的目标地址。
  • JalT:Jal Target,用于指示 CPU 是否需要跳转到 Jal 指令中给定的目标地址。当 JalT 信号为高电平时,CPU 将跳转到 Jal 指令中给定的目标地址。

Jalr 指令的目标地址是通过寄存器的内容计算得到的,而 Jal 指令的目标地址则是在指令中直接给出的。

branch和jalr是EX段跳转,而jal是在ID段跳转。所以必须设置优先级,使得在后的指令先跳转。因此JalrT和BrT的优先级高于JalT

同时,若修改数据通路,使得br,jal,jalr均在EX段跳转,则不会有冲突,此时也就不需要设置优先级。

4.附加思考题:

1)插入气泡

Harzard模块中,有哪几类冲突需要插入气泡(NOP指令),分别使流水线停顿几个周期。(提示:有三类冲突)

答:

  • RAW类冲突:如Load和ALU指令,在ALU计算时,操作数还未读出来。在EX段Stall,使流水线停顿1个周期
  • 控制相关的冲突:如在跳转时,需要插入气泡,flush掉IF段取的指令,停顿1个周期
  • 条件转移的冲突:在条件转移时,需要插入气泡,flush掉IF,ID段取的指令,停顿2个周期

2)branch指令

Harzard模块中,采用静态分支预测器,即默认不跳转,遇到branch指令时,如何控制flush和stall信号?

答:

Branch指令在EX段判断。如果发生分支,则需要Flush IF/ID和ID/EX段寄存器来保证数据不被后方指令错误使用。否则不需要flush或stall。

3.实验总结

在实验中,我学习了RISC-V指令集架构的基本概念和特点,了解了RISC-V Core的基本组成和工作原理,学习了每条指令的数据流和控制信号。

总的来说,通过本实验的学习,我对RISC-V指令集架构有了更深入的理解,了解了每条指令的数据流和控制信号,同时也对RISC-V Core的组成和工作原理有了更清晰的认识。在实验中,我还了解了一些常用的数字电路和计算机体系结构的概念,例如时钟信号、寄存器、ALU等等。

计算时,操作数还未读出来。在EX段Stall,使流水线停顿1个周期

  • 控制相关的冲突:如在跳转时,需要插入气泡,flush掉IF段取的指令,停顿1个周期
  • 条件转移的冲突:在条件转移时,需要插入气泡,flush掉IF,ID段取的指令,停顿2个周期

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/643142.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通达信筹码集中度计算公式,解决了结果不同的问题

筹码分布图基本上是国内股票交易软件的标配&#xff0c;一般在K线图窗口的右侧。通达信软件中&#xff0c;在右下角有个“筹”&#xff0c;点击之后就可以看到“筹码分布图”。&#xff08;如下图&#xff09;筹码分布图是根据一定的模型计算出的流通股票持仓成本分布情况&…

postman接口关联实战解析

在使用postman做接口测试时&#xff0c;有时候后面的接口需要获取前面接口的某一个返回值做为请求参数&#xff0c;这时就可以使用关联。 如从A接口提取出a字段的值&#xff0c;供B接口的b字段使用。 一个接口的返回报文如下&#xff1a; {"retCode": "0&quo…

【数据库原理与实践】知识点归纳(上)

第1章 数据库系统概述 &#xff08;数据处理技术的发展 数据库的基本概念和特点&#xff09; 一&#xff1a;数据、信息、知识、决策 对应&#xff1a;Data、Information、Knowledge、Decision 二&#xff1a;数据库技术的产生与发展 产生原因&#xff1a;数据管理任务的…

如何正确使用Postman变量?又该如何灵活设置变量?

目录 引言 理解变量 postman的变量类型 变量作用域 变量覆盖规则 创建变量 创建全局变量 创建环境变量 创建集合变量 使用变量 引言 Postman变量可以帮助你快速生成测试数据、模拟不同的场景和环境。 但是&#xff0c;如何正确使用Postman变量&#xff1f;又该如何…

Android的服务Service

Android学了太久了&#xff0c;都忘了。复习下四大组件之一的Service。 介绍 Android的Service是一种在后台执行长时间运行操作的组件&#xff0c;它可以在没有用户界面的情况下执行任务&#xff0c;并且可以与应用程序的其他组件进行通信。Service通常用于处理网络请求、音乐…

快速创建Django项目

环境搭建 安装Django之前需要先安装python环境和pycharm。 目前 Django 1.6.x 以上版本已经完全兼容 Python 3.x。 python安装教程&#xff1a;https://blog.csdn.net/David_house/article/details/100110542 项目创建 打开pycharm&#xff0c;选择文件–>新建项目 创建D…

MySQL操作基础

文章目录 一、Mysql的基本概念1.1数据库有哪些组成数据表数据库 1.2数据库系统和数据库管理系统1.3数据库的发展史 二、数据库的分类三、数据库的数据类型三、数据库的操作3.1查看数据库的结构3.2创建及删除数据库和表3.3管理表中的数据记录3.4修改表名和表结构 Linux操作系统&…

11.JavaWeb-Spring框架

1.Spring概念 Spring框架是一个轻量级开源的应用程序框架&#xff0c;用于开发Java企业级应用程序。它提供了一种综合的编程和配置模型&#xff0c;可以帮助开发人员构建灵活、可扩展且易于维护的应用程序。 Spring的根本使命&#xff1a;简化Java开发 【Spring给予了Java新生】…

文心一言 VS 讯飞星火 VS chatgpt (40)-- 算法导论5.4 4题

四、一次聚会需要邀请多少人&#xff0c;才能让其中 3 人的生日很可能相同? 文心一言&#xff1a; 为了解决这个问题&#xff0c;我们需要先计算出所有可能的生日组合数&#xff0c;然后计算出其中生日相同的组合数。 已知需要邀请的人数为&#xff1a;23人 根据组合数公式…

大数据开发之Hive案例篇12:HDFS rebalance 一例

文章目录 一. 问题描述二. 解决方案2.1 增加节点2.2 rebalance2.3 rebalance引发的问题 一. 问题描述 公司的离线数仓是CDH集群&#xff0c;19个节点&#xff0c;HDFS存储空间大约400TB左右&#xff0c;使用量在200TB左右。 由于历史遗留的问题&#xff0c;数据仓库需要重构&a…

将Qtcreator编译器、调试器等配置为MSVC2017/2019

目录 1. 前言 2. 工具/原料 2.1. 安装Windows下的软件开发调试器 3. 配置Qtcreator 1. 前言 安装Qt或Qtcreator时&#xff0c;一般选择MinGW 64-bit或MSVC编译器。对于MinGW 64-bit很简单&#xff0c;一般安装后会自动在Qtcreator配置好&#xff0c;不用费心就可以进行开发…

一种对不同类型齐格勒-尼科尔斯 P-I-D 控制器调谐算法研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

基于NIM_DUILIB_FRAMEWORK框架的网易云信demo:NIM_PC_DEMO

NIM_PC_DEMO 网易云信 PC IM Demo 是基于网易云信 PC SDK 制作的即时通讯示例程序&#xff0c;UI 库使用 NIM Duilib 制作。 github地址:。 1、预览 2、最低要求 CMake 3.10 或以上版本。Visual Studio 2017 或以上版本。Git。 3、开发步骤 NIM Demo 从 8.4.0 版本开始使…

selenium面试题总结

今天有同学问到seleinum面试的时候会问到的问题&#xff0c;随便想了想&#xff0c;暂时纪录一下。欢迎大家在评论中提供更多问题。 1.selenium中如何判断元素是否存在&#xff1f; selenium中没有提供原生的方法判断元素是否存在&#xff0c;一般我们可以通过定位元素异常捕获…

Java网络开发(Tomcat同步数据增删改查)—— 用Jsp语法实现同步请求的 增删改查

目录 引出显示所有数据到前端&#xff08;1&#xff09;前端代码&#xff1a;list.jsp&#xff08;2&#xff09;后端代码&#xff1a;CompanyListServlet.java 新增数据---转发类型信息---新增信息业务&#xff08;1&#xff09;在list.jsp页面点击添加&#xff08;2&#xff…

don‘t have write permissions for the /System/Library/Frameworks/Ruby.framework

don’t have write permissions for the /System/Library/Frameworks/Ruby.framework sudo gem install sigh或sudo gem install -n /usr/local/bin cocoapods --pre出现&#xff1a; appleCQIMAC-L1A9Q05R ~ % sudo gem update --system Password: Updating rubygems-update F…

社会心理学(1) 社会心理学的定义

今天开始 我们一起学习一门课程 社会心理学 社会心理学 他是 应用心理学 或者 心理学专业的一个必修课 吴江霖教授说过 心理学应该分为两大分支 生理心理学 和 社会心理学 如果认同他的观点 那么 社会心理学可谓是相当重要了 社会心理学的定义之广可以说 有多少社会心理学教…

书山有路勤为径 学海无涯苦作舟(AI引领时代浪潮)

书山有路勤为径 学海无涯苦作舟 AI模型是如何训练的&#xff1f; 数据准备 在训练AI模型之前&#xff0c;需要准备大量的数据集。数据集的质量和多样性直接影响模型训练的效果。数据集准备的主要工作包括&#xff1a; 数据清洗&#xff1a;清除数据中的噪声、错误、重复等不…

STM32单片机(六)TIM定时器 -> 第一节:TIM定时中断

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

震惊!kratos的make命令windows下无法使用

Make 命令 kratos想在windows下开发的舒服&#xff0c;各种 命令必须得支持&#xff0c;不然一个protoc就是噩梦&#xff0c;好在官方内置了一些make api这样的命令&#xff0c;坏在windows不支持make命令&#x1f602; MinGw 百度一搜大概是MinGW 这么个东西&#xff0c;这…