PicoRV32 笔记 04
PicoRV32 是一款RISC-V指令的实现的软核CPU。
PicoRV32实现指令rdcycle,rdcycleh,用于读取时钟计数,当使能ENABLE_COUNTERS和ENABLE_COUNTERS64,此指令便有效。
PicoRV32内部实现64bit的计数器count_cycle,定义在源码234行
在源码1486行-1492行对cout_cycle操作
由上源码可知,当使能ENABLE_COUNTERS,每个时钟的上升沿对count_cycle操作,
如果复位则count_cycle取值为0,反之自增1,如果没有使能ENABLE_COUNTERS64则把count_cycle的64bit-32bit设置为0,如果没有使能ENABLE_COUNTERS则count_cycle值为任意,与此同时对应的指令也会被取消,此时使用rdcycle,rdcycleh会导致硬件异常。
涉及到源码中对count_cycle操作的另一处,就是读取计数器的内容
在源码的1686行 “ENABLE_COUNTERS && is_rdcycle_rdcycleh_rdinstr_rdinstrh”判断指令是否是 rdcycle, rdcycleh, rdinstr, rdinstrh这四条指令,如果是rdcycle,则把count_cycle[31:0]写到目标寄存器,如果是rdcycleh则把count_cycle[63:32]写到目标寄存器中。
is_rdcycle_rdcycleh_rdinstr_rdinstrh:是一个单bit信号,PicoRV32中有几个此类信号,用于对一类操作指令进行归类。
例如
assign is_rdcycle_rdcycleh_rdinstr_rdinstrh = |{instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh};
is_rdcycle_rdcycleh_rdinstr_rdinstrh:判断指令是否是 instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh其中的一个。注意 |{......} 中的|是个单目运算符,表示把组合后的信号的所有bit进行or运算。
is_lui_auipc_jal <= |{instr_lui, instr_auipc, instr_jal};判断指令是否是instr_lui, instr_auipc, instr_jal
is_lui_auipc_jal_jalr_addi_add_sub <= |{instr_lui, instr_auipc, instr_jal, instr_jalr, instr_addi, instr_add, instr_sub};判断指令是否是instr_lui, instr_auipc, instr_jal, instr_jalr, instr_addi, instr_add, instr_sub
is_slti_blt_slt <= |{instr_slti, instr_blt, instr_slt};判断指令是否是instr_slti, instr_blt, instr_slt
is_lbu_lhu_lw <= |{instr_lbu, instr_lhu, instr_lw};判断指令是否是instr_lbu, instr_lhu, instr_lw
is_compare <= |{is_beq_bne_blt_bge_bltu_bgeu, instr_slti, instr_slt, instr_sltiu, instr_sltu};判断指令是is_beq_bne_blt_bge_bltu_bgeu, instr_slti, instr_slt, instr_sltiu, instr_sltu
is_beq_bne_blt_bge_bltu_bgeu <= mem_rdata_latched[6:0] == 7'b1100011;判断指令是否是beq bne blt bge bltu bgeu
is_lb_lh_lw_lbu_lhu <= mem_rdata_latched[6:0] == 7'b0000011;判断指令是否是lb lh lw lbu lhu
is_sb_sh_sw <= mem_rdata_latched[6:0] == 7'b0100011;判断指令是否是 sb sh sw
is_alu_reg_imm <= mem_rdata_latched[6:0] == 7'b0010011;判断指令的原操作数是否是寄存器和立即数
is_alu_reg_reg <= mem_rdata_latched[6:0] == 7'b0110011;判断指令的原操作数是否是寄存器和寄存器
is_slli_srli_srai <= is_alu_reg_imm && |{
mem_rdata_q[14:12] == 3'b001 && mem_rdata_q[31:25] == 7'b0000000,
mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0000000,
mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0100000
};
判断指令是否是slli srli srai
is_jalr_addi_slti_sltiu_xori_ori_andi <= instr_jalr || is_alu_reg_imm && |{
mem_rdata_q[14:12] == 3'b000,
mem_rdata_q[14:12] == 3'b010,
mem_rdata_q[14:12] == 3'b011,
mem_rdata_q[14:12] == 3'b100,
mem_rdata_q[14:12] == 3'b110,
mem_rdata_q[14:12] == 3'b111
};
判断指令是否是jalr addi slti sltiu xori ori andi
is_sll_srl_sra <= is_alu_reg_reg && |{
mem_rdata_q[14:12] == 3'b001 && mem_rdata_q[31:25] == 7'b0000000,
mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0000000,
mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0100000
};
判断指令是否是sll srl sra
根据RISC-V的基础指令集RV32I表,其中47条指令,有11个opcode
7'b011_0111: lui
7'b001_0111: auipc
7'b110_1111: jal
7'b110_0111:jalr
7'b110_0011: beq, bne, blt, bge, bltu, bgeu
7'b000_0011: lb, lh, lw, lbu, lhu
7'b010_0011: sb, sh, sw
7'b001_0011:addi, slti, sltiu, xori, ori, andi, slli, srli, srai
7'b011_0011:add, sub, sll, slt, sltu, xor, srl, sra, or, and
7'b000_1111: fence, fence.i
7'b111_0011: ecall, ebreak, csrrw, csrrs, csrrc, csrrwi, csrrsi, csrrci
综上所述,PicoRV32首先通过opcode对指令先对指令进行分类
信号名 | 操作吗 | 对应指令 | |
instr_lui | 7'b011_0111 | lui | |
instr_auipc | 7'b001_0111 | auipc | |
instr_jal | 7'b110_1111 | jal | |
instr_jalr | 7'b110_0111, fun3=3'b000 | jalr | |
is_beq_bne_blt_bge_bltu_bgeu | 7'b110_0011 | beq,bne,blt,bge,bltu,bgeu | |
is_lb_lh_lw_lbu_lhu | 7'b000_0011 | lb, lh, lw, lbu, lhu | |
is_sb_sh_sw | 7'b010_0011 | sb, sh, sw | |
is_alu_reg_imm | 7'b001_0011 | addi,slti,sltiu, xori,ori,andi,slli,srli,srai | |
is_alu_reg_reg | 7'b011_0011 | add, sub, sll, slt, sltu,xor, srl,sra,or,and | |
instr_getq | 7'b000_1011,fun7=7'b000_0000 | getq | |
instr_setq | 7'b000_1011,fun7=7'b000_0001 | setq | |
instr_retirq | 7'b000_1011,fun7=7'b000_0010 | retirq | |
instr_maskirq | 7'b000_1011,fun7=7'b000_0011 | maskirq | |
instr_waitirq | 7'b000_1011,fun7=7'b000_0100 | waitirq | |
instr_timer | 7'b000_1011,fun7=7'b000_0101 | timer |
接下来在第一分类的基础上进行细分
跳转类的指令,6条
instr_beq :is_beq_bne_blt_bge_bltu_bgeu && fun3 = 3'b000;
instr_bne:is_beq_bne_blt_bge_bltu_bgeu && fun3 = 3'b001;
instr_blt : is_beq_bne_blt_bge_bltu_bgeu && fun3 = 3'b100;
instr_bge : is_beq_bne_blt_bge_bltu_bgeu && fun3 = 3'b101;
instr_bltu : is_beq_bne_blt_bge_bltu_bgeu && fun3 = 3'b110;
instr_bgeu : is_beq_bne_blt_bge_bltu_bgeu && fun3 = 3'b111;
加载指令,5条
instr_lb : is_lb_lh_lw_lbu_lhu && fun3 = 3'b000;
instr_lh : is_lb_lh_lw_lbu_lhu && fun3 = 3'b001;
instr_lw : is_lb_lh_lw_lbu_lhu && fun3 = 3'b010;
instr_lbu : is_lb_lh_lw_lbu_lhu && fun3 = 3'b100;
instr_lhu : is_lb_lh_lw_lbu_lhu && fun3 = 3'b101;
存储类指令,3条
instr_sb : is_sb_sh_sw && fun3 = 3'b000;
instr_sh : is_sb_sh_sw && fun3 = 3'b001;
instr_sw : is_sb_sh_sw && fun3 = 3'b010;
寄存器和立即数指令,9条
instr_addi : is_alu_reg_imm && fun3 =3'b000;
instr_slti : is_alu_reg_imm && fun3 = 3'b010;
instr_sltiu : is_alu_reg_imm && fun3 = 3'b011;
instr_xori : is_alu_reg_imm && fun3 =3'b100;
instr_ori : is_alu_reg_imm && fun3 = 3'b110;
instr_andi : is_alu_reg_imm && fun3 = 3'b111;
instr_slli : is_alu_reg_imm && fun3 = 3'b001 && fun7 = 7'b0000000;
instr_srli : is_alu_reg_imm && fun3 =3'b101 && fun7 = 7'b0000000;
instr_srai : is_alu_reg_imm && fun3 = 3'b101 && fun7 = 7'b0100000;
寄存器和寄存器指令,10条
instr_add : is_alu_reg_reg &&fun3 = 3'b000 && fun7 = 7'b0000000;
instr_sub : is_alu_reg_reg && fun3 = 3'b000 && fun7 = 7'b0100000;
instr_sll : is_alu_reg_reg && fun3 = 3'b001 && fun7 = 7'b0000000;
instr_slt : is_alu_reg_reg && fun3 = 3'b010 && fun7 = 7'b0000000;
instr_sltu : is_alu_reg_reg && fun3 = 3'b011 && fun7 = 7'b0000000;
instr_xor : is_alu_reg_reg && fun3 = 3'b100 && fun7 = 7'b0000000;
instr_srl : is_alu_reg_reg && fun3 = 3'b101 && fun7 = 7'b0000000;
instr_sra : is_alu_reg_reg && fun3 = 3'b101 && fun7 = 7'b0100000;
instr_or : is_alu_reg_reg && fun3 = 3'b110 && fun7 = 7'b0000000;
instr_and : is_alu_reg_reg && fun3 = 3'b111 && fun7 = 7'b0000000;
经过上述细分,支持的指令都可以识别到,接下来把相近功能的指令进行合并
is_lui_auipc_jal:判断指令是否是instr_lui, instr_auipc, instr_jal,
这三条指令整合到一个信号,是因为这三个指令格式基本相同
20bit立即数 | 5bit rd | 7bit操作码
唯一的差别是jal指令的20位立即数排列方式不一样
对于lui指令,把指令跟随的立即数低位补上12'b0加上高位一同放到目标寄存器,
rd = (imm<<12)
对于auipc指令,把pc寄存器的值加上{立即数,12'b0}放到目标寄存器
rd = pc + (imm<<12)
对于jal指令,跳转到地址,并把跳转前的下一条指令地址存储到rd中
rd = pc + 4
pc = pc + imm
is_slti_blt_slt:判断指令是否是slti, blt, slt.
slti: 小于置位,当rs1 < 立即数[11:0] 时候设置rd为1,反之设置为0。 slt =set less then
slt:小于置位,当rs1 < rs2时候,rd为1,反之为0
blt: 小于跳转,当rs1 < rs2时候
is_lb_lh_lw_lbu_lhu:判断指令是否为lb, lh, lw, lbu, lhu
lb: rs1+12位立即数符号扩展后作为地址,读取一个字节并作符号扩展后存放到rd中
lh: rs1+12位立即数符号扩展后作为地址,读取一个16bit并作符号扩展后存放到rd中
lw: rs1+12位立即数符号扩展后作为地址,读取一个32bit后存放到rd中
lbu: rs1+12位立即数符号扩展后作为地址,读取一个8bit并作0扩展后存放到rd中
lhu: rs1+12位立即数符号扩展后作为地址,读取一个16bit并作0扩展后存放到rd中
公共的操作是提取地址
is_slli_srli_srai:判断指令是否是slli, srli, srai.这三条指令格式相同,除了操作码不一样
slli: 把rs1左移n位,低位补0,结果写入rd中
srli:把rs1右移n位,高位补0,结果写入rd中
srai:把rs1右移n位,高位位补符号位,结果写入rd中
is_sb_sh_sw:判断指令是否为sb, sh,sw
sb: rs1+12位立即数符号扩展后作为地址,把rs2最低8bit作为数据写到总线上
sh: rs1+12位立即数符号扩展后作为地址,把rs2最低16bit作为数据写到总线上
sw: rs1+12位立即数符号扩展后作为地址,把rs2为数据写到总线上
公共部分提取地址
is_sll_srl_sra:判断指令是否为sll, srl, sra,这三条指令格式相同,除了操作码不同
sll :把寄存器rs1 左移 rs2位, rs2只有低5位有效
srl :把寄存器rs1 右移 rs2位, rs2只有低5位有效
sra :把寄存器rs1 右移 rs2位, 高位填充符号位,rs2只有低5位有效
....
PicoRV32 笔记 04相关推荐
- 取得 Git 仓库 —— Git 学习笔记 04
取得 Git 仓库 -- Git 学习笔记 04 我认为, Git 的学习分为两大块:一是工作区.索引.本地版本库之间的交互:二是本地版本库和远程版本库之间的交互.第一块是基础,第二块是难点. 下面, ...
- SpringMVC-学习笔记04【SpringMVC返回值类型及响应数据类型】
Java后端 学习路线 笔记汇总表[黑马程序员] SpringMVC-学习笔记01[SpringMVC概述及入门案例][day01] SpringMVC-学习笔记02[参数绑定及自定义类型转换] Sp ...
- Spring-学习笔记04【Spring的常用注解】
Java后端 学习路线 笔记汇总表[黑马程序员] Spring-学习笔记01[Spring框架简介][day01] Spring-学习笔记02[程序间耦合] Spring-学习笔记03[Spring的 ...
- MyBatis-学习笔记04【04.自定义Mybatis框架基于注解开发】
Java后端 学习路线 笔记汇总表[黑马程序员] MyBatis-学习笔记01[01.Mybatis课程介绍及环境搭建][day01] MyBatis-学习笔记02[02.Mybatis入门案例] M ...
- JavaWeb黑马旅游网-学习笔记04【BaseServlet抽取】
Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...
- Maven-学习笔记04【基础-Maven生命周期和概念模型图】
Java后端 学习路线 笔记汇总表[黑马程序员] 黑马程序员(腾讯微云)Maven基础讲义.pdf Maven-学习笔记01[基础-Maven基本概念] Maven-学习笔记02[基础-Maven的安 ...
- Redis-学习笔记04【Jedis代码操作】
Java后端 学习路线 笔记汇总表[黑马程序员] Redis-学习笔记01[Redis环境搭建] Redis-学习笔记02[Redis命令操作] Redis-学习笔记03[Redis持久化] Redi ...
- Ajax和JSON-学习笔记04【JSON_解析器】
Java后端 学习路线 笔记汇总表[黑马程序员] Ajax和JSON-学习笔记01[原生JS方式实现Ajax] Ajax和JSON-学习笔记02[JQuery方式实现Ajax] Ajax和JSON-学 ...
- JQuery-学习笔记04【基础——JQuery基础案例】
Java后端 学习路线 笔记汇总表[黑马程序员] JQuery-学习笔记01[基础--JQuery基础]--[day01] JQuery-学习笔记02[基础--JQuery选择器] JQuery-学习 ...
最新文章
- 用手指触碰电子,用心灵感受震荡
- python100个必背知识-学Python必背的初级单词,你都背了吗?
- 10进制与16进制之间的转换 delphi
- [转]在ubuntu上安装chrome浏览器
- centos6 配置ip、服务
- [LeetCode] 1091. Shortest Path in Binary Matrix
- 最近读的那些性能测试书
- 匀光匀色--直方图匹配算法实现与应用
- python的类作用_python——类中的self到底的作用及三个应用场景
- D3Vueecharts个人乱记
- 使用Dagger 2在GWT中进行依赖注入
- Jmeter——for循环控制器和if逻辑控制器
- ubuntu 安装yar和使用
- iPhone+wp7并行初体验
- 3.1EDA和数据描述: 探索性数据分析
- 如何在Mac上组合歌曲?
- JAVA输入jdb,解决 JAVA 单步调试键盘输入被 JDB 占用的问题
- dbeaver查看执行计划_SAP学习基础篇(52):PP模块-物料需求计划
- 简单java游戏代码_Java经典小游戏——贪吃蛇简单实现(附源码)
- 软件测试金九银十即将到来,求职套路多你有多大把握拿offer