diff --git a/Makefile b/Makefile index 73b9fcee..fab699db 100644 --- a/Makefile +++ b/Makefile @@ -23,11 +23,18 @@ RISCOF_UTOSS_RISCV_ISA_CONFIG := $(RISCOF_DIR)/utoss_riscv/utoss_riscv_ # ============= UTOSS_RISCV_CONFIG ?= RV32I +UTOSS_RISCV_ENABLE_MUL ?= $(if $(findstring M,$(UTOSS_RISCV_CONFIG)),1,0) +UTOSS_RISCV_ENABLE_DIV ?= $(if $(findstring M,$(UTOSS_RISCV_CONFIG)),1,0) +UTOSS_RISCV_ENABLE_M := $(if $(filter 1,$(UTOSS_RISCV_ENABLE_MUL) $(UTOSS_RISCV_ENABLE_DIV)),1,0) # Convert B extension to Zbb for RISC-V ISA spec RISCOF_ISA_STRING = $(subst B,Zbb,$(UTOSS_RISCV_CONFIG)) -UTOSS_RISCV_VERILATOR_DEFINES := $(if $(findstring B,$(UTOSS_RISCV_CONFIG)),-DUTOSS_RISCV_ENABLE_B_EXT) +UTOSS_RISCV_VERILATOR_DEFINES := \ +$(if $(findstring B,$(UTOSS_RISCV_CONFIG)),-DUTOSS_RISCV_ENABLE_B_EXT) \ +$(if $(filter 1,$(UTOSS_RISCV_ENABLE_M)),-DUTOSS_RISCV__M_ENABLED) \ +$(if $(filter 1,$(UTOSS_RISCV_ENABLE_MUL)),-DUTOSS_RISCV__MUL_ENABLED) \ +$(if $(filter 1,$(UTOSS_RISCV_ENABLE_DIV)),-DUTOSS_RISCV__DIV_ENABLED) UTOSS_RISCV_RISCOF_VERILATOR_DEFINES := -DUTOSS_PIPELINE_LOGGER # =========================== diff --git a/src/ext/m/types.svh b/src/ext/m/types.svh new file mode 100644 index 00000000..f9fc9353 --- /dev/null +++ b/src/ext/m/types.svh @@ -0,0 +1,25 @@ +`ifndef EXT__M__TYPES +`define EXT__M__TYPES + +/* verilator lint_off DECLFILENAME */ +package ext__m__types; +/* verilator lint_on DECLFILENAME */ + typedef enum logic [1:0] + { + M_ALU_CTRL__MUL = 2'b00 + , M_ALU_CTRL__MULH = 2'b01 + , M_ALU_CTRL__MULHSU = 2'b10 + , M_ALU_CTRL__MULHU = 2'b11 + } m_mul_control_t; + + typedef enum logic [1:0] + { + M_ALU_CTRL__DIV = 2'b00 + , M_ALU_CTRL__DIVU = 2'b01 + , M_ALU_CTRL__REM = 2'b10 + , M_ALU_CTRL__REMU = 2'b11 + } m_div_control_t; + +endpackage + +`endif diff --git a/src/hazard_unit.sv b/src/hazard_unit.sv index 139544b4..20e73b76 100644 --- a/src/hazard_unit.sv +++ b/src/hazard_unit.sv @@ -15,13 +15,22 @@ module hazard_unit , input wire [4:0] rs2_d , input wire [4:0] rd_e , input pc_src_t pc_src_e + + , input logic div_e + , input logic div_busy_e + , input logic div_done_e + , output hazard_forward_a_t forward_a_e , output hazard_forward_b_t forward_b_e , output logic stall_f , output logic stall_d + , output logic stall_e , output logic flush_f , output logic flush_d , output logic flush_e + + , output logic div_start_e + , output logic div_cancel_e ); wire result_src_e_0; @@ -48,10 +57,15 @@ module hazard_unit logic lw_stall; - //Stall when a load hazard occurs + // Stall when a load hazard occurs assign lw_stall = result_src_e_0 && ((rs1_d == rd_e) || (rs2_d == rd_e)) && (rd_e != 5'd0); - assign stall_f = lw_stall; - assign stall_d = lw_stall; + + wire div_stall; + assign div_stall = div_e && !div_done_e; + + assign stall_f = lw_stall || div_stall; + assign stall_d = lw_stall || div_stall; + assign stall_e = div_stall; //Flush when a control hazard occurs; we need to flush one cycle later than we discover the // control hazard; this is due to synchronous memory making the instruction available one cycle @@ -66,4 +80,7 @@ module hazard_unit assign flush_d = control_hazard; assign flush_e = lw_stall || control_hazard; + assign div_start_e = div_e && !div_busy_e && !div_done_e; + assign div_cancel_e = control_hazard; + endmodule diff --git a/src/interfaces/id_to_ex_if.svh b/src/interfaces/id_to_ex_if.svh index 2f0bf684..825c27cc 100644 --- a/src/interfaces/id_to_ex_if.svh +++ b/src/interfaces/id_to_ex_if.svh @@ -3,6 +3,7 @@ `include "src/headers/params.svh" `include "src/headers/types.svh" +`include "src/ext/m/types.svh" typedef struct packed { alu_src_a_t alu_src_a; @@ -16,6 +17,10 @@ typedef struct packed { logic mem_write; logic reg_write; alu_control_t alu_control; + logic is_mul; + logic is_div; + ext__m__types::m_mul_control_t mul_control; + ext__m__types::m_div_control_t div_control; logic [2:0] funct3; data_t rd1; data_t rd2; diff --git a/src/stages/execute_stage.sv b/src/stages/execute_stage.sv index 3060ce1c..031b265f 100644 --- a/src/stages/execute_stage.sv +++ b/src/stages/execute_stage.sv @@ -5,16 +5,27 @@ `include "src/interfaces/ex_to_if_if.svh" module execute_stage - ( input id_to_ex_t id_to_ex + ( input logic clk + , input logic reset + , input id_to_ex_t id_to_ex , input hazard_forward_a_t hz_forward_a , input hazard_forward_b_t hz_forward_b , input data_t wb_result , input data_t mem_alu_result + /* verilator lint_off UNUSEDSIGNAL */ + , input logic div_start_e + /* verilator lint_on UNUSEDSIGNAL */ + + , input logic div_cancel_e + , output ex_to_if_t ex_to_if , output ex_to_mem_t ex_to_mem + + , output logic div_busy_e + , output logic div_done_e ); data_t alu_input_a; @@ -22,8 +33,14 @@ module execute_stage data_t safe_rd1; // hazard-safe version of rd1 data_t safe_rd2; // hazard-safe version of rd2 data_t alu_result; + data_t mul_result, div_result; + data_t final_result; logic zero_flag; + /* verilator lint_off UNUSEDSIGNAL */ + logic mul_done; + /* verilator lint_on UNUSEDSIGNAL */ + // ALU computation always_comb @@ -57,13 +74,50 @@ module execute_stage endcase ALU alu - ( .a ( alu_input_a ) - , .b ( alu_input_b ) + ( .a ( alu_input_a ) + , .b ( alu_input_b ) , .alu_control ( id_to_ex.alu_control ) - , .out ( alu_result ) - , .zeroE ( zero_flag ) + , .out ( alu_result ) + , .zeroE ( zero_flag ) ); +`ifdef UTOSS_RISCV__MUL_ENABLED + MUL mul + ( .clk ( clk ) + , .rst_n ( ~reset ) + , .start_i ( id_to_ex.is_mul ) + , .rs1_i ( alu_input_a ) + , .rs2_i ( alu_input_b ) + , .op_i ( id_to_ex.mul_control ) + , .result_o ( mul_result ) + , .ready_o ( mul_done ) + ); +`else + assign mul_result = '0; +`endif + +`ifdef UTOSS_RISCV__DIV_ENABLED + DIV div + ( .clk ( clk ) + , .rst_n ( ~reset ) + , .start_i ( div_start_e ) + , .op_i ( id_to_ex.div_control ) + , .rs1_i ( alu_input_a ) + , .rs2_i ( alu_input_b ) + , .result_o ( div_result ) + , .ready_o ( div_done_e ) + , .busy_o ( div_busy_e ) + ); +`else + assign div_result = '0; + assign div_busy_e = 1'b0; + assign div_done_e = 1'b0; +`endif + + assign final_result = id_to_ex.is_mul ? mul_result : + id_to_ex.is_div ? div_result : + alu_result; + // branching logic typedef enum logic [2:0] @@ -114,7 +168,7 @@ module execute_stage assign ex_to_mem.funct3 = id_to_ex.funct3; assign ex_to_mem.write_data_e = safe_rd2; assign ex_to_mem.rd = id_to_ex.rd; - assign ex_to_mem.alu_result = alu_result; + assign ex_to_mem.alu_result = final_result; assign ex_to_mem.pc_cur = id_to_ex.pc_cur; assign ex_to_mem.pc_plus_4 = id_to_ex.pc_plus_4; assign ex_to_if.imm_ext = id_to_ex.imm_ext; @@ -122,5 +176,6 @@ module execute_stage assign ex_to_if.pc_target = pc_target; assign ex_to_if.pc_old = id_to_ex.pc_cur; - wire unused = &{id_to_ex.rs1, id_to_ex.rs2}; + wire unused = &{id_to_ex.rs1, id_to_ex.rs2, div_cancel_e}; + endmodule diff --git a/src/utoss_riscv.sv b/src/utoss_riscv.sv index 6784aa49..5ac3ffe5 100644 --- a/src/utoss_riscv.sv +++ b/src/utoss_riscv.sv @@ -95,12 +95,17 @@ module utoss_riscv // execute stage begin (@MSh-786 and tandr3w) always_ff @ (posedge clk) - if (reset) id_to_ex_reg <= '0; - else if (flush_e) id_to_ex_reg <= '0; - else id_to_ex_reg <= id_to_ex_out; + if (reset) id_to_ex_reg <= '0; + else if (flush_e) id_to_ex_reg <= '0; + else if (!stall_e) id_to_ex_reg <= id_to_ex_out; + logic div_busy_e, div_done_e; execute_stage u_execute_stage - ( .id_to_ex ( id_to_ex_reg ) + ( .clk ( clk ) + , .reset ( reset ) + , .id_to_ex ( id_to_ex_reg ) + , .div_start_e ( div_start_e ) + , .div_cancel_e ( div_cancel_e ) , .hz_forward_a ( hz_forward_a ) , .hz_forward_b ( hz_forward_b ) @@ -108,8 +113,10 @@ module utoss_riscv , .wb_result ( wb_result ) , .mem_alu_result ( ex_to_mem_reg.alu_result ) - , .ex_to_mem ( ex_to_mem_out ) - , .ex_to_if ( ex_to_if_out ) + , .ex_to_mem ( ex_to_mem_out ) + , .ex_to_if ( ex_to_if_out ) + , .div_busy_e ( div_busy_e ) + , .div_done_e ( div_done_e ) ); // execute stage end @@ -117,8 +124,9 @@ module utoss_riscv // memory stage begin (@Invisipac) always_ff @ (posedge clk) - if (reset) ex_to_mem_reg <= '0; - else ex_to_mem_reg <= ex_to_mem_out; + if (reset) ex_to_mem_reg <= '0; + else if (stall_e) ex_to_mem_reg <= '0; + else ex_to_mem_reg <= ex_to_mem_out; memory_stage u_memory_stage ( .ex_to_mem ( ex_to_mem_reg ) @@ -153,7 +161,8 @@ module utoss_riscv hazard_forward_a_t hz_forward_a; hazard_forward_b_t hz_forward_b; - logic stall_f, stall_d, flush_f, flush_d, flush_e; + logic stall_f, stall_d, flush_f, flush_d, flush_e, stall_e; + logic div_start_e, div_cancel_e; hazard_unit u_hazard_unit ( .clk ( clk ) @@ -169,14 +178,20 @@ module utoss_riscv , .reg_write_w ( mem_to_wb_reg.reg_write ) , .result_src_e ( id_to_ex_reg.result_src ) , .pc_src_e ( ex_to_if_out.pc_src ) - - , .forward_a_e ( hz_forward_a ) - , .forward_b_e ( hz_forward_b ) - , .stall_f ( stall_f ) - , .stall_d ( stall_d ) - , .flush_f ( flush_f ) - , .flush_d ( flush_d ) - , .flush_e ( flush_e ) + , .div_e ( id_to_ex_reg.is_div ) + , .div_busy_e ( div_busy_e ) + , .div_done_e ( div_done_e ) + + , .forward_a_e ( hz_forward_a ) + , .forward_b_e ( hz_forward_b ) + , .stall_f ( stall_f ) + , .stall_d ( stall_d ) + , .stall_e ( stall_e ) + , .flush_f ( flush_f ) + , .flush_d ( flush_d ) + , .flush_e ( flush_e ) + , .div_start_e ( div_start_e ) + , .div_cancel_e ( div_cancel_e ) ); // hazard module end