Move unalignment selection into prefetch buffer

This commit is contained in:
Andreas Traber 2015-11-30 14:09:51 +01:00
parent 5de1132e47
commit 965be8059a
3 changed files with 57 additions and 57 deletions

View file

@ -111,9 +111,6 @@ module riscv_if_stage
logic [31:0] fetch_rdata;
logic [31:0] fetch_addr;
logic fetch_unaligned_valid;
logic [31:0] fetch_unaligned_rdata;
logic [31:0] instr_rdata_int;
@ -129,7 +126,6 @@ module riscv_if_stage
if (unaligned) begin
current_pc_if_o = {fetch_addr[31:2], 2'b10};
instr_rdata_int = fetch_unaligned_rdata;
end
end
@ -195,14 +191,12 @@ module riscv_if_stage
.branch_i ( branch_req ),
.addr_i ( {fetch_addr_n[31:2], 2'b00} ),
.unaligned_i ( unaligned ), // is the current address unaligned?
.ready_i ( fetch_ready ),
.valid_o ( fetch_valid ),
.rdata_o ( fetch_rdata ),
.addr_o ( fetch_addr ),
.unaligned_valid_o ( fetch_unaligned_valid ),
.unaligned_rdata_o ( fetch_unaligned_rdata ),
// goes to instruction memory / instruction cache
.instr_req_o ( instr_req_o ),
.instr_addr_o ( instr_addr_o ),
@ -224,14 +218,12 @@ module riscv_if_stage
.branch_i ( branch_req ),
.addr_i ( {fetch_addr_n[31:2], 2'b00} ),
.unaligned_i ( unaligned ), // is the current address unaligned?
.ready_i ( fetch_ready ),
.valid_o ( fetch_valid ),
.rdata_o ( fetch_rdata ),
.addr_o ( fetch_addr ),
.unaligned_valid_o ( fetch_unaligned_valid ),
.unaligned_rdata_o ( fetch_unaligned_rdata ),
// goes to instruction memory / instruction cache
.instr_req_o ( instr_req_o ),
.instr_addr_o ( instr_addr_o ),
@ -304,26 +296,16 @@ module riscv_if_stage
unaligned = 1'b1;
if (fetch_valid) begin
if (is_compressed[1]) begin
valid = 1'b1; // an instruction is ready for ID stage
valid = 1'b1; // an instruction is ready for ID stage
if (req_i && if_valid_o) begin
// next instruction will be aligned
fetch_ready = 1'b1;
if (req_i && if_valid_o) begin
// next instruction will be aligned
fetch_ready = 1'b1;
if (is_compressed[1])
offset_fsm_ns = WAIT_ALIGNED;
end
end else begin
// not compressed, we are looking at a 32 bit instruction
if (fetch_unaligned_valid) begin
valid = 1'b1; // an instruction is ready for ID stage
if (req_i && if_valid_o) begin
// next instruction will be unaligned
fetch_ready = 1'b1;
offset_fsm_ns = WAIT_UNALIGNED;
end
end
else
offset_fsm_ns = WAIT_UNALIGNED;
end
end
end

View file

@ -40,8 +40,7 @@ module riscv_prefetch_L0_buffer
output logic [31:0] rdata_o,
output logic [31:0] addr_o,
output logic unaligned_valid_o,
output logic [31:0] unaligned_rdata_o,
input logic unaligned_i,
// goes to instruction memory / instruction cache
output logic instr_req_o,
@ -67,6 +66,10 @@ module riscv_prefetch_L0_buffer
logic ready_L0;
logic is_prefetch_q, is_prefetch_n;
// prepared data for output
logic [31:0] rdata, unaligned_rdata;
logic valid, unaligned_valid;
assign busy_o = (CS != EMPTY && CS != VALID_L0) || instr_req_o;
@ -112,7 +115,7 @@ module riscv_prefetch_L0_buffer
always_comb
begin
valid_o = 1'b0;
valid = 1'b0;
valid_L0 = 1'b0;
pointer_ns = pointer_cs;
instr_req_o = 1'b0;
@ -165,7 +168,7 @@ module riscv_prefetch_L0_buffer
end
else // else (branch_i)
begin
valid_o = instr_rvalid_i;
valid = instr_rvalid_i;
// prepare address even if we don't need it
// this removes the dependency for instr_addr_o on instr_rvalid_i
@ -206,7 +209,7 @@ module riscv_prefetch_L0_buffer
VALID_L0:
begin
valid_o = 1'b1;
valid = 1'b1;
valid_L0 = 1'b1;
if (branch_i)
@ -308,41 +311,41 @@ module riscv_prefetch_L0_buffer
begin
if (is_prefetch_q)
begin
rdata_o = previous_chunk;
rdata = previous_chunk;
addr_o = { last_address[31:4], 2'b11, 2'b00 };
end
else
begin
if (valid_L0) begin
rdata_o = L0_buffer[pointer_cs];
rdata = L0_buffer[pointer_cs];
addr_o = { current_address[31:4], pointer_cs, 2'b00 };
end
else
begin
rdata_o = instr_rdata_i[pointer_cs];
rdata = instr_rdata_i[pointer_cs];
addr_o = { current_address[31:4], pointer_cs, 2'b00 };
end
end
end
// the lower part of unaligned_rdata_o is always the higher part of rdata_o
assign unaligned_rdata_o[15:0] = rdata_o[31:16];
// the lower part of unaligned_rdata is always the higher part of rdata
assign unaligned_rdata[15:0] = rdata[31:16];
always_comb
begin
if (valid_L0) begin
case(addr_o[3:2])
2'b00: begin unaligned_rdata_o[31:16] = L0_buffer[1][15:0]; unaligned_valid_o = 1'b1; end
2'b01: begin unaligned_rdata_o[31:16] = L0_buffer[2][15:0]; unaligned_valid_o = 1'b1; end
2'b10: begin unaligned_rdata_o[31:16] = L0_buffer[3][15:0]; unaligned_valid_o = 1'b1; end
2'b00: begin unaligned_rdata[31:16] = L0_buffer[1][15:0]; unaligned_valid = 1'b1; end
2'b01: begin unaligned_rdata[31:16] = L0_buffer[2][15:0]; unaligned_valid = 1'b1; end
2'b10: begin unaligned_rdata[31:16] = L0_buffer[3][15:0]; unaligned_valid = 1'b1; end
// this state is only interesting if we have already done a prefetch
2'b11: begin
unaligned_rdata_o[31:16] = L0_buffer[0][15:0];
unaligned_rdata[31:16] = L0_buffer[0][15:0];
if (is_prefetch_q) begin
unaligned_valid_o = 1'b1;
unaligned_valid = 1'b1;
end else begin
unaligned_valid_o = 1'b0;
unaligned_valid = 1'b0;
end
end
endcase // addr_o
@ -351,18 +354,18 @@ module riscv_prefetch_L0_buffer
// icache
case(addr_o[3:2])
2'b00: begin unaligned_rdata_o[31:16] = instr_rdata_i[1][15:0]; unaligned_valid_o = instr_rvalid_i; end
2'b01: begin unaligned_rdata_o[31:16] = instr_rdata_i[2][15:0]; unaligned_valid_o = instr_rvalid_i; end
2'b10: begin unaligned_rdata_o[31:16] = instr_rdata_i[3][15:0]; unaligned_valid_o = instr_rvalid_i; end
2'b00: begin unaligned_rdata[31:16] = instr_rdata_i[1][15:0]; unaligned_valid = instr_rvalid_i; end
2'b01: begin unaligned_rdata[31:16] = instr_rdata_i[2][15:0]; unaligned_valid = instr_rvalid_i; end
2'b10: begin unaligned_rdata[31:16] = instr_rdata_i[3][15:0]; unaligned_valid = instr_rvalid_i; end
2'b11:
begin
unaligned_rdata_o[31:16] = instr_rdata_i[0][15:0];
unaligned_rdata[31:16] = instr_rdata_i[0][15:0];
if (is_prefetch_q)
unaligned_valid_o = instr_rvalid_i;
unaligned_valid = instr_rvalid_i;
else
unaligned_valid_o = 1'b0;
unaligned_valid = 1'b0;
end
endcase // pointer_cs
end
@ -394,4 +397,11 @@ module riscv_prefetch_L0_buffer
end
end
//////////////////////////////////////////////////////////////////////////////
// instruction aligner (if unaligned)
//////////////////////////////////////////////////////////////////////////////
assign rdata_o = unaligned_i ? unaligned_rdata : rdata;
assign valid_o = unaligned_i ? unaligned_valid : valid;
endmodule // prefetch_L0_buffer

View file

@ -198,6 +198,7 @@ module riscv_prefetch_buffer
input logic clk,
input logic rst_n,
input logic unaligned_i,
input logic req_i,
input logic branch_i,
input logic ready_i,
@ -207,9 +208,6 @@ module riscv_prefetch_buffer
output logic [31:0] rdata_o,
output logic [31:0] addr_o,
output logic unaligned_valid_o,
output logic [31:0] unaligned_rdata_o,
// goes to instruction memory / instruction cache
output logic instr_req_o,
output logic [31:0] instr_addr_o,
@ -232,6 +230,9 @@ module riscv_prefetch_buffer
logic fifo_rdata_valid;
logic fifo_rdata_ready;
logic [31:0] rdata, unaligned_rdata;
logic valid, unaligned_valid;
//////////////////////////////////////////////////////////////////////////////
// prefetch buffer status
//////////////////////////////////////////////////////////////////////////////
@ -266,15 +267,22 @@ module riscv_prefetch_buffer
.in_rdata_ready_o ( fifo_rdata_ready ),
.in_rdata_i ( instr_rdata_i ),
.out_valid_o ( valid_o ),
.out_valid_o ( valid ),
.out_ready_i ( ready_i ),
.out_rdata_o ( rdata_o ),
.out_rdata_o ( rdata ),
.out_addr_o ( addr_o ),
.out_unaligned_valid_o ( unaligned_valid_o ),
.out_unaligned_rdata_o ( unaligned_rdata_o )
.out_unaligned_valid_o ( unaligned_valid ),
.out_unaligned_rdata_o ( unaligned_rdata )
);
//////////////////////////////////////////////////////////////////////////////
// instruction aligner (if unaligned)
//////////////////////////////////////////////////////////////////////////////
assign rdata_o = unaligned_i ? unaligned_rdata : rdata;
assign valid_o = unaligned_i ? unaligned_valid : valid;
//////////////////////////////////////////////////////////////////////////////
// instruction fetch FSM