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:
Sven Stucki 2015-11-03 17:44:17 +01:00
parent c001c323de
commit ec00ad8376
3 changed files with 36 additions and 18 deletions

View file

@ -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

View file

@ -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

View file

@ -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