计组Lab4 RISCV

问题的思考

1.尽量使用共享资源,主要可以共享的资源有ALU。

2.如何控制

使用2选1多路复用器连接:如果信号少,则方便。多信号很麻烦

使用多选1多路复用器连接:如果信号多,则方便,少信号麻烦

3.CSR的位置

要求:1.需要被硬件直接读写

2.需要被软件读写

考虑CSR放在CtrlUnit之外,如果出现illegal指令,则读写对应的寄存器

3.读写的问题:

写发生在时钟周期开始, 读是常通的。

4.不需要ctrlunit,直接使用opcode即可。

只要opcode设计足够合理,这个想法没有问题。

直接使用opcode的某些指令进行译码。

RISCV指令

指令类型指令格式操作数含义
Radd, sub, sll, slt, sltu, xor, srl, sra, or, andadd rd, rs1, rs2x[rd]=x[rs1]+x[rs2]
SBbeq, bne, blt, bge, bltu, bgeubeq rs1, rs2, immif(rs1==rs2) pc+=sext(imm)
Jjaljal rd, immx[rd]=pc+4,pc+=sext(imm)
Sswsw rs2, imm(rs1)M[x[rs1]+sext(imm)] = x[rs2]
Uluilui rd, immx[rd] = imm<<12
Uauipcauipc rd, immx[rd]=pc+sext(imm<<12)
Iaddi, slti, sltui, xori, ori, andi, slli, srli, sraiaddi, rd, rs1, immx[rd]=x[rs1]+sext(imm)
Ijalrjalr rd, imm(rs1)t=pc+4,pc=(x[rs1]+sext(imm))&~1,x[rd]=t
Ilwlw rd, imm(rs1)x[rd]=M[x[rs1]+sext(imm)]
Icsrrwcsrrw rd, csr,rs1t=CSRs[csr], CSRs[csr] = x[rs1]; x[rd] = t
Icsrrscsrrs rd, csr,rs1t = CSRS[csr], CSRs[csr]=t|x[rs1],x[rd]=t
Icsrrccsrrc rd, csr, rs1t=CSRs[csr], CSRs[csr]=t&~x[rs1], x[rd]=t
Icsrrwicsrrwi rd, csr, immx[rd]=CSRs[csr],CSRs[csr]=imm
Icsrrsicsrrsi rd, csr, immt=CSRs[csr], CSRs[csr]=t|imm,x[rd]=t
Icsrrcicsrrci rd, csr, immt=CSRs[csr], CSRs[csr] = t&~imm, x[rd] = t
Iecallecall触发异常
Imretmretpc=mtvec

RegFile

信号含义
rs1读寄存器序号1
rs2读寄存器序号2
wen写使能
rd写寄存器序号
i_data写入数据
rs1_valrs1寄存器值
rs2_valrs2寄存器值

rs1和rs2永远是inst的19:25和24:20位决定的,rd永远是inst的11:7位决定的,需要选择的只有写入数据和写入使能。

reg_i_data

|opcode[6],opcode[4]|来源|指令|
-|-|-|-
00|mem|ld
01|alu_res|R,I,lui,auipc
10|pc+4|jal,jalr
11|csr_val|csr

只有lw和R, I, U的时候允许写入。

CSRs寄存器

CSRs首先读常开,这个周期开始时,数据就被读取,写入到rd中。

然后CSRs参与ALU的计算,计算结果在下一个周期开始时写入CSRs。

在正常的csr指令下,对它使用csr_ind指定一个寄存器,用csr_wen指定写使能,用i_data决定写入的数据。

如果检测到异常,则直接由Core对其进行写入。

输入含义
csr_ind指定CSR寄存器
wen写使能
i_data写入数据
csr_valcsr_ind对应寄存器的值

如果是csr指令,则csr_wen为1,否则为0.(异常写入不看csr_wen,只有通过写口写入才看csr_wen)

csr_ind永远接在inst的31到22位

csr_i_data

fun[2],fun[1]i_data来源
00rs1_valcsrrw
01, 11alu_rescssrrs, csrrc, csrrsi, csrrci
10immcsrrwi

注意csrrsi和csrrci写着是只改变后6位,其实直接写入即可,由于它的设计,前面几位在计算时不会被改变。

ALU

ALU一般处理的是rs1_val和rs2_val和imm之间的运算,如果涉及到pc,一般使用额外的Adder处理。

输入含义
a_val操作数
b_val操作数
alu_ctrl指定擦操作类型
alu_res运算结果

a_val

opcode[6] opcode[2]来源指令
00rs1_valR,I,S
01immlui,auipc
10csr_valcsr

b_val很复杂,直接用op7选择

|指令类型 |b_val|
-|-|-|-
R|rs2_val
I, sw, lw|imm|
lui|0|
auipc|pc|
csrrsl|rs1_val|
csrrc|~x[rs1]|
csrrsi|imm|
csrrci|~imm|

我的auipc是ALU算出pc+imm写入x[rd], lui是算出imm+0写入x[rd],主要是利用了alu_res能够到达reg_i_data,如果直接通入reg_i_data也是可以的。

alu_ctrl

opcode[6],opcode[4],opcode[2]操作指令
010fun3add,addi
000addsw,lw
011Addlui,auipc
111{1‘b1, fun3}csr

关于R和I二级译码的问题,我觉得R可以直接看inst[30]和fun3,部分I可以看inst[30]和fun3, 还有一部分I可以看{1’b0, fun3}

CMP

输入含义
a_val操作数
b_val操作数
cmp_ctrl指定比较类型
cmp_res比较结果

直接看fun3作为控制

immGen

输入inst[31:0],输出imm

指令类型立即数
jal12’b[31],[19:12],[20],[30:21], 1’b0
jalr20’b[31], [31:20]
I20’b[31], [31:20]
sw20’b[31], [31:25], [11:7]
SB20’b[31],[7], [30:25], [11:8],1’b0
csrrwi27’b0, [19:15]
csrrsi27’b0, [19:15]
csrrci27’b0, [19:15]

注意auipc和lui的拼接是直接拼成了位移完成的。

PC

指令类型
jalpc+sext(imm)
jalrrs1_val+sext(imm)
SBPC+sext(imm)或者pc+4
其他pc+4

我设置了pc_branch,在外部用逻辑算出pc的下一条位置,然后在上升沿更新pc

Mem

地址是alu_res,写入的值是rs2_val

异常处理

这个一开始接触确实比较麻烦,但是理解了其实也简单。

判断异常和中断

用组合逻辑判断一条指令是否是异常,如果是,则设置exc_cause为异常的原因。

mip的第7位接在时钟中断上,mip的第11位接在按钮上,如果为1,说明产生了中断。

在打算更新pc的时候,如果此时exc_cause的值不是no_error,或者mip第7位或者第3位的值是1,说明发生了异常或者中断。

考虑要不要处理的操作:

如果是异常,看mstatus的第3位,如果是1,直接处理,否则不处理。

如果是中断,看一下mstatus的第3位,如果是0, 则不处理,如果是1,看一下mie的对应位是不是1(mie是程序通过csr指令写入的,不是硬件设置的)如果是0,则不处理,否则处理。

处理中断和异常

pc <= mevec

mcause <= exc_cause(就是你检测出的问题,如果检测出了直接赋值也是OK的,不用在上升沿赋值)

mstatus[7] <= mstatus[3]

异常:mepc <= pc+4,中断 mepc <= pc

mtval <= inst或者pc或者alu_res

如果不处理的话,pc <= pc_branch。

然后就处理完成了。

从中断处理中返回 mret

pc <= mepc

mstatus[3] <= mstatus[7]

理解异常和中断

用C++举例,trow时候产生了一个error,对应到RISCV, mip=1,或者判断error的位变为1。

然后程序看这个error是否可以处理,对应到RISCV的mstatus和mie的使能。

如果可以处理,则跳到catch里面执行,对应到RISCV就是跳到了mtvec的位置开始处理。

处理完成以后,接着回到main,对应到RISCV就是跳回到了mtvec的位置(此时mevec需要被程序修改,否则跳回原来的位置)

中断程序到底是什么:它就像写在catch里的那样,正常情况是不执行的,但是遇到中断或者异常会去执行。这个也是写代码的人负责写的,硬件只是负责跳到那里,然后遇到了mret就跳回原来的程序。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值