diff --git a/controller.sv b/controller.sv index 502fc700..0f19fc68 100644 --- a/controller.sv +++ b/controller.sv @@ -1029,6 +1029,11 @@ module controller ctrl_fsm_ns = BRANCH_DELAY; end + // handle hwloops + if (hwloop_jump_i) begin + pc_mux_sel_o = `PC_HWLOOP; + end + // handle illegal instructions if (illegal_insn_int) begin illegal_insn_o = 1'b1; diff --git a/hwloop_controller.sv b/hwloop_controller.sv index 35f583f2..683edbc7 100644 --- a/hwloop_controller.sv +++ b/hwloop_controller.sv @@ -50,8 +50,11 @@ module hwloop_controller logic [`HWLOOP_REGS-1:0] pc_is_end_addr; + // end address detection + integer j; - // generate comparators. check for end address and the loop counter + + // generate comparators. check for end address and the loop counter genvar i; for (i = 0; i < `HWLOOP_REGS; i++) begin assign pc_is_end_addr[i] = ( @@ -65,30 +68,18 @@ module hwloop_controller assign hwloop_jump_o = |pc_is_end_addr; - // select corresponding start address and decrement counter. give highest priority to register 0 + // select corresponding start address and decrement counter always_comb begin hwloop_targ_addr_o = 32'b0; hwloop_dec_cnt_o = '0; - if (pc_is_end_addr[0]) begin - hwloop_targ_addr_o = hwloop_start_addr_i[0]; - hwloop_dec_cnt_o[0] = 1'b1; + for (j = `HWLOOP_REGS-1; j >= 0; j--) begin + if (pc_is_end_addr[j]) begin + hwloop_targ_addr_o = hwloop_start_addr_i[j]; + hwloop_dec_cnt_o[j] = 1'b1; + end end - else if (pc_is_end_addr[1]) begin - hwloop_targ_addr_o = hwloop_start_addr_i[1]; - hwloop_dec_cnt_o[1] = 1'b1; - end -/* -----\/----- EXCLUDED -----\/----- - else if (pc_is_end_addr[2]) begin - hwloop_targ_addr_o = hwloop_start_addr_i[2]; - hwloop_dec_cnt_o[2] = 1'b1; - end - else if (pc_is_end_addr[3]) begin - hwloop_targ_addr_o = hwloop_start_addr_i[3]; - hwloop_dec_cnt_o[3] = 1'b1; - end - -----/\----- EXCLUDED -----/\----- */ end endmodule diff --git a/id_stage.sv b/id_stage.sv index 0490e64e..3934403d 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -94,6 +94,7 @@ module id_stage input logic data_misaligned_i, output logic [31:0] hwloop_targ_addr_o, + output logic hwloop_jump_o, output logic csr_access_ex_o, output logic [1:0] csr_op_ex_o, @@ -706,13 +707,10 @@ module id_stage ( // from ID stage .enable_i ( hwloop_enable ), - .current_pc_i ( current_pc_if_i ), - // to controller + // to IF stage/controller .hwloop_jump_o ( hwloop_jump ), - - // to if stage .hwloop_targ_addr_o ( hwloop_targ_addr_o ), // from hwloop_regs @@ -724,6 +722,8 @@ module id_stage .hwloop_dec_cnt_o ( hwloop_dec_cnt ) ); + assign hwloop_jump_o = hwloop_jump; + hwloop_regs hwloop_regs_i ( .clk ( clk ), diff --git a/if_stage.sv b/if_stage.sv index 24704715..1d28afde 100644 --- a/if_stage.sv +++ b/if_stage.sv @@ -61,7 +61,6 @@ module if_stage // Forwarding ports - control signals input logic force_nop_i, // insert a NOP in the pipe input logic [31:0] exception_pc_reg_i, // address used to restore PC when the interrupt/exception is served - input logic [31:0] pc_from_hwloop_i, // pc from hwloop start addr input logic [2:0] pc_mux_sel_i, // sel for pc multiplexer input logic [1:0] exc_pc_mux_i, // select which exception to execute @@ -72,6 +71,10 @@ module if_stage input logic [31:0] jump_target_ex_i, // jump target address input logic branch_decision_i, + // from hwloop controller + input logic hwloop_jump_i, + input logic [31:0] hwloop_target_i, // pc from hwloop start addr + // from debug unit input logic [31:0] dbg_npc_i, input logic dbg_set_npc_i, @@ -160,7 +163,7 @@ module if_stage `PC_INCR: fetch_addr_n = fetch_addr_Q + 32'd4; // incremented PC `PC_EXCEPTION: fetch_addr_n = exc_pc; // set PC to exception handler `PC_ERET: fetch_addr_n = exception_pc_reg_i; // PC is restored when returning from IRQ/exception - `PC_HWLOOP: fetch_addr_n = pc_from_hwloop_i; // PC is taken from hwloop start addr + `PC_HWLOOP: fetch_addr_n = hwloop_target_i; // PC is taken from hwloop start addr `PC_DBG_NPC: fetch_addr_n = dbg_npc_i; // PC is taken from debug unit default: begin @@ -180,7 +183,7 @@ module if_stage `PC_JUMP: unaligned_jump = jump_target_id_i[1]; `PC_BRANCH: unaligned_jump = jump_target_ex_i[1]; `PC_ERET: unaligned_jump = exception_pc_reg_i[1]; - `PC_HWLOOP: unaligned_jump = pc_from_hwloop_i[1]; + `PC_HWLOOP: unaligned_jump = hwloop_target_i[1]; `PC_DBG_NPC: unaligned_jump = dbg_npc_i[1]; endcase end @@ -389,7 +392,10 @@ module if_stage offset_fsm_ns = WAIT_JUMPED_ALIGNED; end - end else if (jump_in_id_i == `BRANCH_JAL || jump_in_id_i == `BRANCH_JALR || dbg_set_npc_i) begin + end else if (jump_in_id_i == `BRANCH_JAL || jump_in_id_i == `BRANCH_JALR + || dbg_set_npc_i + || hwloop_jump_i) begin + // switch to new PC from ID stage fetch_req = 1'b1; if (unaligned_jump) offset_fsm_ns = WAIT_JUMPED_UNALIGNED; diff --git a/riscv_core.sv b/riscv_core.sv index db639a29..a003d465 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -179,7 +179,8 @@ module riscv_core // Hardware loop controller signals - logic [31:0] hwlp_targ_addr; // from hwloop controller to if stage + logic hwloop_jump; + logic [31:0] hwloop_target; // from hwloop controller to if stage // Debug Unit @@ -246,10 +247,13 @@ module riscv_core // Forwrding ports - control signals .force_nop_i ( force_nop_id ), // select incoming instr or NOP .exception_pc_reg_i ( epcr ), // Exception PC register - .pc_from_hwloop_i ( hwlp_targ_addr ), // pc from hwloop start address .pc_mux_sel_i ( pc_mux_sel_id ), // sel for pc multiplexer .exc_pc_mux_i ( exc_pc_mux_id ), // selector for exception multiplexer + // from hwloop controller + .hwloop_jump_i ( hwloop_jump ), + .hwloop_target_i ( hwloop_target ), // pc from hwloop start address + // from debug unit .dbg_npc_i ( dbg_npc ), .dbg_set_npc_i ( dbg_set_npc ), @@ -279,116 +283,117 @@ module riscv_core ///////////////////////////////////////////////// id_stage id_stage_i ( - .clk ( clk ), - .rst_n ( rst_n ), + .clk ( clk ), + .rst_n ( rst_n ), // Processor Enable - .fetch_enable_i ( fetch_enable_i ), + .fetch_enable_i ( fetch_enable_i ), - .jump_in_id_o ( jump_in_id ), - .jump_in_ex_o ( jump_in_ex ), - .branch_decision_i ( branch_decision ), + .jump_in_id_o ( jump_in_id ), + .jump_in_ex_o ( jump_in_ex ), + .branch_decision_i ( branch_decision ), - .jump_target_o ( jump_target_id ), + .jump_target_o ( jump_target_id ), - .core_busy_o ( core_busy ), + .core_busy_o ( core_busy ), // Interface to instruction memory - .instr_rdata_i ( instr_rdata_id ), - .instr_req_o ( instr_req_int ), - .instr_gnt_i ( instr_grant_i ), - .instr_ack_i ( instr_ack_int ), + .instr_rdata_i ( instr_rdata_id ), + .instr_req_o ( instr_req_int ), + .instr_gnt_i ( instr_grant_i ), + .instr_ack_i ( instr_ack_int ), - .pc_mux_sel_o ( pc_mux_sel_id ), - .exc_pc_mux_o ( exc_pc_mux_id ), - .force_nop_o ( force_nop_id ), + .pc_mux_sel_o ( pc_mux_sel_id ), + .exc_pc_mux_o ( exc_pc_mux_id ), + .force_nop_o ( force_nop_id ), - .current_pc_if_i ( current_pc_if ), - .current_pc_id_i ( current_pc_id ), + .current_pc_if_i ( current_pc_if ), + .current_pc_id_i ( current_pc_id ), - .compressed_instr_o ( compressed_instr ), + .compressed_instr_o ( compressed_instr ), // STALLS - .stall_if_o ( stall_if ), - .stall_id_o ( stall_id ), - .stall_ex_o ( stall_ex ), - .stall_wb_o ( stall_wb ), + .stall_if_o ( stall_if ), + .stall_id_o ( stall_id ), + .stall_ex_o ( stall_ex ), + .stall_wb_o ( stall_wb ), // From the Pipeline ID/EX - .regfile_rb_data_ex_o ( regfile_rb_data_ex ), + .regfile_rb_data_ex_o ( regfile_rb_data_ex ), - .alu_operand_a_ex_o ( alu_operand_a_ex ), - .alu_operand_b_ex_o ( alu_operand_b_ex ), - .alu_operand_c_ex_o ( alu_operand_c_ex ), - .alu_operator_ex_o ( alu_operator_ex ), + .alu_operand_a_ex_o ( alu_operand_a_ex ), + .alu_operand_b_ex_o ( alu_operand_b_ex ), + .alu_operand_c_ex_o ( alu_operand_c_ex ), + .alu_operator_ex_o ( alu_operator_ex ), - .vector_mode_ex_o ( vector_mode_ex ), // from ID to EX stage - .alu_cmp_mode_ex_o ( alu_cmp_mode_ex ), // from ID to EX stage - .alu_vec_ext_ex_o ( alu_vec_ext_ex ), // from ID to EX stage + .vector_mode_ex_o ( vector_mode_ex ), // from ID to EX stage + .alu_cmp_mode_ex_o ( alu_cmp_mode_ex ), // from ID to EX stage + .alu_vec_ext_ex_o ( alu_vec_ext_ex ), // from ID to EX stage - .mult_en_ex_o ( mult_en_ex ), // from ID to EX stage - .mult_sel_subword_ex_o ( mult_sel_subword_ex ), // from ID to EX stage - .mult_signed_mode_ex_o ( mult_signed_mode_ex ), // from ID to EX stage - .mult_mac_en_ex_o ( mult_mac_en_ex ), // from ID to EX stage + .mult_en_ex_o ( mult_en_ex ), // from ID to EX stage + .mult_sel_subword_ex_o ( mult_sel_subword_ex ), // from ID to EX stage + .mult_signed_mode_ex_o ( mult_signed_mode_ex ), // from ID to EX stage + .mult_mac_en_ex_o ( mult_mac_en_ex ), // from ID to EX stage - .regfile_waddr_ex_o ( regfile_waddr_ex ), - .regfile_we_ex_o ( regfile_we_ex ), + .regfile_waddr_ex_o ( regfile_waddr_ex ), + .regfile_we_ex_o ( regfile_we_ex ), - .regfile_alu_we_ex_o ( regfile_alu_we_ex ), - .regfile_alu_waddr_ex_o ( regfile_alu_waddr_ex ), + .regfile_alu_we_ex_o ( regfile_alu_we_ex ), + .regfile_alu_waddr_ex_o ( regfile_alu_waddr_ex ), // CSR ID/EX - .csr_access_ex_o ( csr_access_ex ), - .csr_op_ex_o ( csr_op_ex ), + .csr_access_ex_o ( csr_access_ex ), + .csr_op_ex_o ( csr_op_ex ), // hwloop signals - .hwloop_targ_addr_o ( hwlp_targ_addr ), + .hwloop_jump_o ( hwloop_jump ), + .hwloop_targ_addr_o ( hwloop_target ), - .prepost_useincr_ex_o ( useincr_addr_ex ), - .data_misaligned_i ( data_misaligned ), + .prepost_useincr_ex_o ( useincr_addr_ex ), + .data_misaligned_i ( data_misaligned ), - .data_we_ex_o ( data_we_ex ), // to load store unit - .data_type_ex_o ( data_type_ex ), // to load store unit - .data_sign_ext_ex_o ( data_sign_ext_ex ), // to load store unit - .data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit - .data_req_ex_o ( data_req_ex ), // to load store unit - .data_misaligned_ex_o ( data_misaligned_ex ), // to load store unit - .data_ack_i ( data_ack_int ), // from load store unit - .data_rvalid_i ( data_r_valid_i ), + .data_we_ex_o ( data_we_ex ), // to load store unit + .data_type_ex_o ( data_type_ex ), // to load store unit + .data_sign_ext_ex_o ( data_sign_ext_ex ), // to load store unit + .data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit + .data_req_ex_o ( data_req_ex ), // to load store unit + .data_misaligned_ex_o ( data_misaligned_ex ), // to load store unit + .data_ack_i ( data_ack_int ), // from load store unit + .data_rvalid_i ( data_r_valid_i ), // Interrupt Signals - .irq_i ( irq_i ), // incoming interrupts - .irq_nm_i ( irq_nm_i ), // incoming interrupts - .irq_enable_i ( irq_enable ), // global interrupt enable - .save_pc_if_o ( save_pc_if ), // control signal to save pc - .save_pc_id_o ( save_pc_id ), // control signal to save pc + .irq_i ( irq_i ), // incoming interrupts + .irq_nm_i ( irq_nm_i ), // incoming interrupts + .irq_enable_i ( irq_enable ), // global interrupt enable + .save_pc_if_o ( save_pc_if ), // control signal to save pc + .save_pc_id_o ( save_pc_id ), // control signal to save pc // Debug Unit Signals - .dbg_flush_pipe_i ( dbg_flush_pipe ), - .dbg_st_en_i ( dbg_st_en ), - .dbg_dsr_i ( dbg_dsr ), - .dbg_stall_i ( dbg_stall ), - .dbg_trap_o ( dbg_trap ), - .dbg_reg_mux_i ( dbg_reg_mux ), - .dbg_reg_we_i ( dbg_reg_we ), - .dbg_reg_addr_i ( dbg_reg_addr[4:0] ), - .dbg_reg_wdata_i ( dbg_reg_wdata ), - .dbg_reg_rdata_o ( dbg_reg_rdata ), - .dbg_set_npc_i ( dbg_set_npc ), + .dbg_flush_pipe_i ( dbg_flush_pipe ), + .dbg_st_en_i ( dbg_st_en ), + .dbg_dsr_i ( dbg_dsr ), + .dbg_stall_i ( dbg_stall ), + .dbg_trap_o ( dbg_trap ), + .dbg_reg_mux_i ( dbg_reg_mux ), + .dbg_reg_we_i ( dbg_reg_we ), + .dbg_reg_addr_i ( dbg_reg_addr[4:0] ), + .dbg_reg_wdata_i ( dbg_reg_wdata ), + .dbg_reg_rdata_o ( dbg_reg_rdata ), + .dbg_set_npc_i ( dbg_set_npc ), // Forward Signals - .regfile_alu_waddr_fw_i ( regfile_alu_waddr_fw ), - .regfile_alu_we_fw_i ( regfile_alu_we_fw ), - .regfile_alu_wdata_fw_i ( regfile_alu_wdata_fw ), + .regfile_alu_waddr_fw_i ( regfile_alu_waddr_fw ), + .regfile_alu_we_fw_i ( regfile_alu_we_fw ), + .regfile_alu_wdata_fw_i ( regfile_alu_wdata_fw ), - .regfile_waddr_wb_i ( regfile_waddr_fw_wb_o ), // Write address ex-wb pipeline - .regfile_we_wb_i ( regfile_we_wb ), // write enable for the register file - .regfile_wdata_wb_i ( regfile_wdata ), // write data to commit in the register file + .regfile_waddr_wb_i ( regfile_waddr_fw_wb_o), // Write address ex-wb pipeline + .regfile_we_wb_i ( regfile_we_wb ), // write enable for the register file + .regfile_wdata_wb_i ( regfile_wdata ), // write data to commit in the register file - .perf_jump_o ( perf_jump ), - .perf_branch_o ( perf_branch ), - .perf_jr_stall_o ( perf_jr_stall ), - .perf_ld_stall_o ( perf_ld_stall ) + .perf_jump_o ( perf_jump ), + .perf_branch_o ( perf_branch ), + .perf_jr_stall_o ( perf_jr_stall ), + .perf_ld_stall_o ( perf_ld_stall ) );