mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Add lp.setupi instruction
Hardware loops now have their own adder and no longer share it with the jump target calculation. The new lp.setupi instruction makes it possible to truly setup hardware loops with a single instruction. For the lp.setup instruction, a register with the counter had to be prepared first. The range of the new instruction is quite limited though, it uses the shifted z-imm (5 bit, unsigned).
This commit is contained in:
parent
c001c323de
commit
ec00ad8376
3 changed files with 36 additions and 18 deletions
23
decoder.sv
23
decoder.sv
|
@ -80,8 +80,8 @@ module riscv_decoder
|
|||
|
||||
// hwloop signals
|
||||
output logic [2:0] hwloop_we_o, // write enable for hwloop regs
|
||||
output logic hwloop_target_mux_sel_o, // selects immediate for hwloop target
|
||||
output logic hwloop_start_mux_sel_o, // selects hwloop start address input
|
||||
output logic hwloop_end_mux_sel_o, // selects hwloop end address input
|
||||
output logic hwloop_cnt_mux_sel_o, // selects hwloop counter input
|
||||
|
||||
// jump/branches
|
||||
|
@ -143,8 +143,8 @@ module riscv_decoder
|
|||
prepost_useincr_o = 1'b1;
|
||||
|
||||
hwloop_we = 3'b0;
|
||||
hwloop_target_mux_sel_o = 1'b0;
|
||||
hwloop_start_mux_sel_o = 1'b0;
|
||||
hwloop_end_mux_sel_o = 1'b0;
|
||||
hwloop_cnt_mux_sel_o = 1'b0;
|
||||
|
||||
csr_access_o = 1'b0;
|
||||
|
@ -576,7 +576,7 @@ module riscv_decoder
|
|||
///////////////////////////////////////////////
|
||||
|
||||
`OPCODE_HWLOOP: begin
|
||||
jump_target_mux_sel_o = `JT_HWLP; // get PC + I imm from jump target adder
|
||||
hwloop_target_mux_sel_o = 1'b0;
|
||||
|
||||
unique case (instr_rdata_i[14:12])
|
||||
3'b000: begin
|
||||
|
@ -584,31 +584,44 @@ module riscv_decoder
|
|||
hwloop_we[0] = 1'b1;
|
||||
hwloop_start_mux_sel_o = 1'b0;
|
||||
end
|
||||
|
||||
3'b001: begin
|
||||
// lp.endi: set end address to PC + I-type immediate
|
||||
hwloop_we[1] = 1'b1;
|
||||
hwloop_end_mux_sel_o = 1'b0; // jump target
|
||||
end
|
||||
|
||||
3'b010: begin
|
||||
// lp.count: initialize counter from rs1
|
||||
hwloop_we[2] = 1'b1;
|
||||
hwloop_cnt_mux_sel_o = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
end
|
||||
|
||||
3'b011: begin
|
||||
// lp.counti: initialize counter from I-type immediate
|
||||
hwloop_we[2] = 1'b1;
|
||||
hwloop_cnt_mux_sel_o = 1'b0;
|
||||
end
|
||||
|
||||
3'b100: begin
|
||||
// lp.setup: initialize counter from rs1, set start address to
|
||||
// next instruction and end address to PC + I-type immediate
|
||||
hwloop_we = 3'b111;
|
||||
hwloop_start_mux_sel_o = 1'b1;
|
||||
hwloop_end_mux_sel_o = 1'b0;
|
||||
hwloop_cnt_mux_sel_o = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
end
|
||||
|
||||
3'b101: begin
|
||||
// lp.setupi: initialize counter from rs1, set start address to
|
||||
// next instruction and end address to PC + I-type immediate
|
||||
hwloop_we = 3'b111;
|
||||
hwloop_target_mux_sel_o = 1'b1;
|
||||
hwloop_start_mux_sel_o = 1'b1;
|
||||
hwloop_cnt_mux_sel_o = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
end
|
||||
|
||||
default: begin
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
|
|
30
id_stage.sv
30
id_stage.sv
|
@ -252,10 +252,11 @@ module riscv_id_stage
|
|||
logic [2:0] hwloop_we;
|
||||
logic hwloop_jump;
|
||||
logic hwloop_enable;
|
||||
logic hwloop_target_mux_sel;
|
||||
logic hwloop_start_mux_sel;
|
||||
logic hwloop_end_mux_sel;
|
||||
logic hwloop_cnt_mux_sel;
|
||||
|
||||
logic [31:0] hwloop_target;
|
||||
logic [31:0] hwloop_start;
|
||||
logic [31:0] hwloop_end;
|
||||
logic [31:0] hwloop_cnt;
|
||||
|
@ -331,23 +332,26 @@ module riscv_id_stage
|
|||
// hwloop register id
|
||||
assign hwloop_regid = instr[8:7]; // rd contains hwloop register id
|
||||
|
||||
// hwloop target mux
|
||||
always_comb
|
||||
begin
|
||||
unique case (hwloop_target_mux_sel)
|
||||
1'b0: hwloop_target = current_pc_id_i + imm_i_type;
|
||||
1'b1: hwloop_target = current_pc_id_i + {imm_z_type[30:0], 1'b0};
|
||||
endcase
|
||||
end
|
||||
|
||||
// hwloop start mux
|
||||
always_comb
|
||||
begin
|
||||
unique case (hwloop_start_mux_sel)
|
||||
1'b0: hwloop_start = jump_target; // for PC + I imm
|
||||
1'b0: hwloop_start = hwloop_target; // for PC + I imm
|
||||
1'b1: hwloop_start = current_pc_if_i; // for next PC
|
||||
endcase
|
||||
end
|
||||
|
||||
// hwloop end mux
|
||||
always_comb
|
||||
begin
|
||||
unique case (hwloop_end_mux_sel)
|
||||
1'b0: hwloop_end = jump_target; // for PC + I imm
|
||||
1'b1: hwloop_end = jump_target; // TODO: PC + (Z imm << 1) for lp.setupi
|
||||
endcase
|
||||
end
|
||||
assign hwloop_end = hwloop_target;
|
||||
|
||||
// hwloop cnt mux
|
||||
always_comb
|
||||
|
@ -372,9 +376,11 @@ module riscv_id_stage
|
|||
begin : jump_target_mux
|
||||
unique case (jump_target_mux_sel)
|
||||
`JT_JAL: jump_target = current_pc_id_i + imm_uj_type;
|
||||
`JT_JALR: jump_target = regfile_data_ra_id + imm_i_type; // cannot forward rs1 as path is too long
|
||||
`JT_COND: jump_target = current_pc_id_i + imm_sb_type;
|
||||
`JT_HWLP: jump_target = current_pc_id_i + imm_i_type;
|
||||
|
||||
// JALR: Cannot forward RS1, since the path is too long
|
||||
`JT_JALR: jump_target = regfile_data_ra_id + imm_i_type;
|
||||
default: jump_target = regfile_data_ra_id + imm_i_type;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -592,8 +598,8 @@ module riscv_id_stage
|
|||
|
||||
// hwloop signals
|
||||
.hwloop_we_o ( hwloop_we ),
|
||||
.hwloop_target_mux_sel_o ( hwloop_target_mux_sel ),
|
||||
.hwloop_start_mux_sel_o ( hwloop_start_mux_sel ),
|
||||
.hwloop_end_mux_sel_o ( hwloop_end_mux_sel ),
|
||||
.hwloop_cnt_mux_sel_o ( hwloop_cnt_mux_sel ),
|
||||
|
||||
// jump/branches
|
||||
|
|
|
@ -280,7 +280,6 @@
|
|||
`define BRANCH_COND 2'b11 // conditional branches
|
||||
|
||||
// jump target mux
|
||||
`define JT_HWLP 2'b00
|
||||
`define JT_JAL 2'b01
|
||||
`define JT_JALR 2'b10
|
||||
`define JT_COND 2'b11
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue