Simplified fetch logic a little bit

This will probably not get us much performance though
This commit is contained in:
Andreas Traber 2015-09-01 09:53:03 +02:00
parent fbf8874e13
commit d5802e5e62
4 changed files with 43 additions and 114 deletions

View file

@ -498,7 +498,7 @@ module id_stage
.rst_n ( rst_n ),
// Read port a
.raddr_a_i ( (dbg_reg_mux_i == 1'b0) ? regfile_addr_ra_id : dbg_reg_addr_i ),
.raddr_a_i ( regfile_addr_ra_id ),
.rdata_a_o ( regfile_data_ra_id ),
// Read port b
@ -506,7 +506,7 @@ module id_stage
.rdata_b_o ( regfile_data_rb_id ),
// Read port c
.raddr_c_i ( regfile_addr_rc_id ),
.raddr_c_i ( (dbg_reg_mux_i == 1'b0) ? regfile_addr_rc_id : dbg_reg_addr_i ),
.rdata_c_o ( regfile_data_rc_id ),
// Write port a

View file

@ -101,8 +101,7 @@ module if_stage
logic fetch_req;
logic [31:0] fetch_rdata;
logic fetch_valid;
logic [31:0] fetch_addr, fetch_addr_n;
logic [31:0] fetch_addr_Q;
logic [31:0] fetch_addr_n, fetch_addr_Q, fetch_addr_QQ;
logic [31:0] instr_rdata_int;
@ -117,27 +116,27 @@ module if_stage
begin
// default values for regular aligned access
instr_rdata_int = fetch_rdata;
current_pc_if_o = {fetch_addr[31:2], 2'b00};
current_pc_if_o = {fetch_addr_Q[31:2], 2'b00};
if (unaligned) begin
if (crossword) begin
// cross-word access, regular instruction
instr_rdata_int = {fetch_rdata[15:0], data_arr};
current_pc_if_o = {fetch_addr_Q[31:2], 2'b10};
current_pc_if_o = {fetch_addr_QQ[31:2], 2'b10};
end else begin
// unaligned compressed instruction
// don't care about upper half-word, insert good value for
// optimization
instr_rdata_int = {fetch_rdata[15:0], fetch_rdata[31:16]};
current_pc_if_o = {fetch_addr[31:2], 2'b10};
current_pc_if_o = {fetch_addr_Q[31:2], 2'b10};
end
end
end
// compressed instruction detection
assign is_compressed[0] = fetch_rdata[1:0] != 2'b11;
assign is_compressed[1] = fetch_rdata[17:16] != 2'b11;
assign is_compressed[0] = (fetch_rdata[1:0] != 2'b11);
assign is_compressed[1] = (fetch_rdata[17:16] != 2'b11);
// exception PC selection mux
@ -158,7 +157,7 @@ module if_stage
`PC_BOOT: fetch_addr_n = {boot_addr_i[31:5], `EXC_OFF_RST};
`PC_JUMP: fetch_addr_n = {jump_target_id_i[31:2], 2'b0};
`PC_BRANCH: fetch_addr_n = {jump_target_ex_i[31:2], 2'b0};
`PC_INCR: fetch_addr_n = fetch_addr + 32'd4; // incremented PC
`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
@ -195,16 +194,12 @@ module if_stage
.valid_o ( fetch_valid ),
.addr_i ( fetch_addr_n ),
.rdata_o ( fetch_rdata ),
.last_addr_o ( fetch_addr ),
.instr_req_o ( instr_req_o ),
.instr_addr_o ( instr_addr_o ),
.instr_gnt_i ( instr_gnt_i ),
.instr_rvalid_i ( instr_rvalid_i ),
.instr_rdata_i ( instr_rdata_i ),
.stall_if_i ( 1'b0 ),
.drop_request_i ( 1'b0 ) // TODO: Remove?
.instr_rdata_i ( instr_rdata_i )
);
@ -403,15 +398,20 @@ module if_stage
// store instr_core_if data in local cache
// store last address used to fetch an instruction
// we also store the address we used before, so
// fetch_addr_n -> fetch_addr_Q -> fetch_addr_QQ
always_ff @(posedge clk, negedge rst_n)
begin
if (rst_n == 1'b0) begin
data_arr <= 16'b0;
fetch_addr_Q <= 32'b0;
data_arr <= 16'b0;
fetch_addr_Q <= 32'b0;
fetch_addr_QQ <= 32'b0;
end else begin
if (fetch_req) begin
data_arr <= fetch_rdata[31:16];
fetch_addr_Q <= fetch_addr;
data_arr <= fetch_rdata[31:16];
fetch_addr_Q <= fetch_addr_n;
fetch_addr_QQ <= fetch_addr_Q;
end
end
end
@ -421,7 +421,7 @@ module if_stage
offset_fsm_cs == VALID_JUMPED_UNALIGNED ||
offset_fsm_cs == VALID_ALIGNED ||
offset_fsm_cs == VALID_UNALIGNED_32 ||
offset_fsm_cs == UNALIGNED_16) || instr_req_o;
offset_fsm_cs == UNALIGNED_16) || instr_req_o;
// IF-ID pipeline registers, frozen when the ID stage is stalled

View file

@ -359,7 +359,6 @@ endfunction // prettyPrintInstruction
`define PC_EXCEPTION 3'b100
`define PC_ERET 3'b101
`define PC_HWLOOP 3'b110
`define PC_BRANCH_PRED 3'b111
// Exception PC mux selector defines
`define EXC_PC_NO_INCR 2'b00

View file

@ -39,16 +39,11 @@ module instr_core_interface
output logic [31:0] instr_addr_o,
input logic instr_gnt_i,
input logic instr_rvalid_i,
input logic [31:0] instr_rdata_i,
input logic stall_if_i,
input logic drop_request_i
input logic [31:0] instr_rdata_i
);
enum logic [2:0] {IDLE, PENDING, WAIT_RVALID, WAIT_IF_STALL, WAIT_GNT, ABORT} CS, NS;
enum logic [1:0] {IDLE, PENDING, WAIT_RVALID, WAIT_GNT } CS, NS;
logic save_rdata;
logic [31:0] rdata_Q;
logic wait_gnt;
@ -72,46 +67,40 @@ module instr_core_interface
if (wait_gnt)
addr_Q <= addr_i;
if (save_rdata)
if (instr_rvalid_i)
rdata_Q <= instr_rdata_i;
end
end
assign last_addr_o = addr_Q;
assign valid_o = instr_rvalid_i;
always_comb
begin
instr_req_o = 1'b0;
valid_o = 1'b0;
save_rdata = 1'b0;
rdata_o = instr_rdata_i;
instr_addr_o = addr_i;
wait_gnt = 1'b0;
unique case(CS)
// default state, not waiting for requested data
IDLE:
begin
instr_req_o = req_i;
valid_o = 1'b0;
rdata_o = rdata_Q;
if(req_i)
begin
NS = IDLE;
instr_req_o = req_i;
if(req_i) begin
if(instr_gnt_i) //~> granted request
NS = PENDING;
else begin //~> got a request but no grant
NS = WAIT_GNT;
wait_gnt = 1'b1;
end
end //~> if(req_i == 0)
else
begin
NS = IDLE;
end
end // case: IDLE
// we sent a request but did not yet get a grant
WAIT_GNT:
begin
instr_addr_o = addr_Q;
@ -121,81 +110,39 @@ module instr_core_interface
NS = PENDING;
else
begin
// if (drop_request_i)
// NS = IDLE;
// else
NS = WAIT_GNT;
NS = WAIT_GNT;
end
end // case: WAIT_GNT
// we got a grant, so now we wait for the rvalid
PENDING:
begin
if (instr_rvalid_i) begin
save_rdata = 1'b1;
valid_o = 1'b1;
NS = IDLE;
instr_req_o = req_i;
if (stall_if_i) begin
NS = WAIT_IF_STALL;
instr_req_o = 1'b0;
end else begin
NS = IDLE;
instr_req_o = req_i;
if (req_i) begin
if (instr_gnt_i) begin
NS = PENDING;
end else begin
NS = WAIT_GNT;
wait_gnt = 1'b1;
end
if (req_i) begin
if (instr_gnt_i) begin
NS = PENDING;
end else begin
NS = WAIT_GNT;
wait_gnt = 1'b1;
end
end
end else begin
NS = WAIT_RVALID;
instr_req_o = 1'b0;
valid_o = 1'b0;
end
end // case: PENDING
// we wait for rvalid, after that we are ready to serve a new request
WAIT_RVALID :
begin
NS = WAIT_RVALID;
valid_o = 1'b0;
instr_req_o = 1'b0;
if (instr_rvalid_i) begin
valid_o = 1'b1;
save_rdata = 1'b1;
if (stall_if_i) begin
instr_req_o = 1'b0;
NS = WAIT_IF_STALL;
end else begin
instr_req_o = req_i;
if (req_i) begin
if (instr_gnt_i)
NS = PENDING;
else begin
NS = WAIT_GNT;
wait_gnt = 1'b1;
end
end else
NS = IDLE;
end
end
end // case: WAIT_RVALID
WAIT_IF_STALL:
begin
valid_o = 1'b1;
rdata_o = rdata_Q;
if (stall_if_i) begin
NS = WAIT_IF_STALL;
instr_req_o = 1'b0;
end
else
begin
NS = IDLE;
instr_req_o = req_i;
if (req_i) begin
@ -205,26 +152,9 @@ module instr_core_interface
NS = WAIT_GNT;
wait_gnt = 1'b1;
end
end else
NS = IDLE;
end
end // case: WAIT_IF_STALL
ABORT:
begin
NS = IDLE;
valid_o = 1'b1;
instr_req_o = 1'b1;
if (req_i) begin
if(instr_gnt_i) //~> granted request
NS = PENDING;
else begin //~> got a request but no grant
NS = WAIT_GNT;
wait_gnt = 1'b1;
end
end
end // case: ABORT
end // case: WAIT_RVALID
default:
begin