原文链接:CV32E40P处理器源码剖析(四):LSU_Stage - 知乎 (zhihu.com)
cv32e40p_load_store_unit负责实现指令访问数据存储单元,内部仅包含cv32e40p_obi_interface模块,负责根据load/store指令向数据存储单元发起读写请求。
cv32e40p_load_store_unit与周围模块的连接关系
cv32e40p_load_store_unit除了内部包含的cv32e40p_obi_interface模块,还实现:
-
根据待写memory地址赋值data_be和data_wdata。data_be为4b位宽,对应标识4个字节,即标识需要更新哪个字节。对于非对齐写memory操作,cv32e40p_load_store_unit需要分两次写入:首先,lsu_stage将部分数据写入memory,并给id_stage反馈地址没有对齐通知;其次,id_stage将store的memory地址加4,并将其与非对齐信号返回lsu_stage,再执行一次写操作。
if (misaligned_st == 1'b0) begin // non-misaligned case case (data_addr_int[1:0]) 2'b00: data_be = 4'b1111; 2'b01: data_be = 4'b1110; 2'b10: data_be = 4'b1100; 2'b11: data_be = 4'b1000; endcase ; // case (data_addr_int[1:0]) end else begin // misaligned case case (data_addr_int[1:0]) 2'b00: data_be = 4'b0000; // this is not used, but included for completeness 2'b01: data_be = 4'b0001; 2'b10: data_be = 4'b0011; 2'b11: data_be = 4'b0111; endcase ; // case (data_addr_int[1:0]) end
-
根据读memory响应构造读结果。对于非对齐读memory操作,同样需要分两次完成:首先,lsu_stage请求读取部分数据,并给id_stage反馈地址没有对齐通知;其次,id_stage将load指令的memory地址加4,并将其与非对齐信号返回lsu_stage,再执行一次读操作。
assign wdata_offset = data_addr_int[1:0] - data_reg_offset_ex_i[1:0]; always_comb begin case (wdata_offset) 2'b00: data_wdata = data_wdata_ex_i[31:0]; 2'b01: data_wdata = {data_wdata_ex_i[23:0], data_wdata_ex_i[31:24]}; 2'b10: data_wdata = {data_wdata_ex_i[15:0], data_wdata_ex_i[31:16]}; 2'b11: data_wdata = {data_wdata_ex_i[7:0], data_wdata_ex_i[31:8]}; endcase ; // case (wdata_offset) end
其他需要注意的点:
-
局部参数DEPTH == 2,用于保证cv32e40p_load_store_unit模块最多同时接收两个读/写memory请求。在访问memory地址非对齐时候,需要发起两次读写请求。此时,无法再接收新的memory读写指令。
-
lsu_ready_wb_o 用于标识当前正在访问memory,用于通告id_stage不能发起数据依赖相关的新指令,但仍然可以发起依赖关系的访存请求。
assign lsu_ready_wb_o = (cnt_q == 2'b00) ? 1'b1 : resp_valid;
-
lsu_ready_ex_o 用来通告ex_stage是否还可以继续发起数据读写请求,若当前正在访问的读写请求已经等于2,则无法再发起新的访问memoy请求。
assign lsu_ready_ex_o = (data_req_ex_i == 1'b0) ? 1'b1 : (cnt_q == 2'b00) ? ( trans_valid && trans_ready) : (cnt_q == 2'b01) ? (resp_valid && trans_valid && trans_ready) : resp_valid;
-
cv32e40p_obi_interface已在if_stage介绍,这里不再展开介绍。