Line 20... |
Line 20... |
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
//
|
//
|
// ============================================================================
|
// ============================================================================
|
//
|
//
|
|
`include "FT64_config.vh"
|
`include "FT64_defines.vh"
|
`include "FT64_defines.vh"
|
|
|
// FETCH
|
// FETCH
|
//
|
//
|
// fetch exactly two instructions from memory into the fetch buffer
|
// fetch exactly two instructions from memory into the fetch buffer
|
// unless either one of the buffers is still full, in which case we
|
// unless either one of the buffers is still full, in which case we
|
// do nothing (kinda like alpha approach)
|
// do nothing (kinda like alpha approach)
|
// Like to turn this into an independent module at some point.
|
// Like to turn this into an independent module at some point.
|
//
|
//
|
module FT64_fetchbuf(rst, clk4x, clk,
|
module FT64_fetchbuf(rst, clk4x, clk, fcu_clk,
|
cs_i, cyc_i, stb_i, ack_o, we_i, adr_i, dat_i,
|
cs_i, cyc_i, stb_i, ack_o, we_i, adr_i, dat_i,
|
hirq, thread_en,
|
hirq, thread_en,
|
regLR,
|
regLR,
|
insn0, insn1, phit,
|
insn0, insn1, phit,
|
threadx,
|
threadx,
|
Line 51... |
Line 52... |
fetchbuf0_v, fetchbuf1_v,
|
fetchbuf0_v, fetchbuf1_v,
|
codebuf0, codebuf1,
|
codebuf0, codebuf1,
|
btgtA, btgtB, btgtC, btgtD,
|
btgtA, btgtB, btgtC, btgtD,
|
nop_fetchbuf,
|
nop_fetchbuf,
|
take_branch0, take_branch1,
|
take_branch0, take_branch1,
|
stompedRets
|
stompedRets,
|
|
panic
|
);
|
);
|
parameter AMSB = 31;
|
parameter AMSB = `AMSB;
|
parameter RSTPC = 32'hFFFC0100;
|
parameter RSTPC = 32'hFFFC0100;
|
parameter TRUE = 1'b1;
|
parameter TRUE = 1'b1;
|
parameter FALSE = 1'b0;
|
parameter FALSE = 1'b0;
|
input rst;
|
input rst;
|
input clk4x;
|
input clk4x;
|
input clk;
|
input clk;
|
|
input fcu_clk;
|
input cs_i;
|
input cs_i;
|
input cyc_i;
|
input cyc_i;
|
input stb_i;
|
input stb_i;
|
output ack_o;
|
output ack_o;
|
input we_i;
|
input we_i;
|
Line 121... |
Line 124... |
input [AMSB:0] btgtD;
|
input [AMSB:0] btgtD;
|
input [3:0] nop_fetchbuf;
|
input [3:0] nop_fetchbuf;
|
output take_branch0;
|
output take_branch0;
|
output take_branch1;
|
output take_branch1;
|
input [3:0] stompedRets;
|
input [3:0] stompedRets;
|
|
output reg [3:0] panic;
|
integer n;
|
integer n;
|
|
|
//`include "FT64_decode.vh"
|
//`include "FT64_decode.vh"
|
|
|
function IsBranch;
|
function IsBranch;
|
Line 277... |
Line 280... |
pc1 <= thread_en ? (fetchbuf ? pc1b : pc1a) : pc1a;
|
pc1 <= thread_en ? (fetchbuf ? pc1b : pc1a) : pc1a;
|
end
|
end
|
*/
|
*/
|
assign threadx = fetchbuf;
|
assign threadx = fetchbuf;
|
|
|
|
`ifdef FCU_ENH
|
FT64_RSB #(AMSB) ursb1
|
FT64_RSB #(AMSB) ursb1
|
(
|
(
|
.rst(rst),
|
.rst(rst),
|
.clk(clk),
|
.clk(fcu_clk),
|
.regLR(regLR),
|
.regLR(regLR),
|
.queued1(queued1),
|
.queued1(queued1),
|
.queued2(queued2),
|
.queued2(queued2),
|
.fetchbuf0_v(fetchbuf0_v),
|
.fetchbuf0_v(fetchbuf0_v),
|
.fetchbuf0_pc(fetchbuf0_pc),
|
.fetchbuf0_pc(fetchbuf0_pc),
|
Line 298... |
Line 302... |
);
|
);
|
|
|
FT64_RSB #(AMSB) ursb2
|
FT64_RSB #(AMSB) ursb2
|
(
|
(
|
.rst(rst),
|
.rst(rst),
|
.clk(clk),
|
.clk(fcu_clk),
|
.regLR(regLR),
|
.regLR(regLR),
|
.queued1(queued1),
|
.queued1(queued1),
|
.queued2(1'b0),
|
.queued2(1'b0),
|
.fetchbuf0_v(fetchbuf1_v),
|
.fetchbuf0_v(fetchbuf1_v),
|
.fetchbuf0_pc(fetchbuf1_pc),
|
.fetchbuf0_pc(fetchbuf1_pc),
|
Line 312... |
Line 316... |
.fetchbuf1_instr(`NOP_INSN),
|
.fetchbuf1_instr(`NOP_INSN),
|
.stompedRets(stompedRets[3:1]),
|
.stompedRets(stompedRets[3:1]),
|
.stompedRet(stompedRet),
|
.stompedRet(stompedRet),
|
.pc(retpc1)
|
.pc(retpc1)
|
);
|
);
|
|
`else
|
|
assign retpc0 = RSTPC;
|
|
assign retpc1 = RSTPC;
|
|
`endif
|
|
|
wire peclk, neclk;
|
wire peclk, neclk;
|
edge_det ued1 (.rst(rst), .clk(clk4x), .ce(1'b1), .i(clk), .pe(peclk), .ne(neclk), .ee());
|
edge_det ued1 (.rst(rst), .clk(clk4x), .ce(1'b1), .i(clk), .pe(peclk), .ne(neclk), .ee());
|
|
|
always @(posedge clk)
|
always @(posedge clk)
|
Line 327... |
Line 335... |
fetchbufA_v <= 0;
|
fetchbufA_v <= 0;
|
fetchbufB_v <= 0;
|
fetchbufB_v <= 0;
|
fetchbufC_v <= 0;
|
fetchbufC_v <= 0;
|
fetchbufD_v <= 0;
|
fetchbufD_v <= 0;
|
fetchbuf <= 0;
|
fetchbuf <= 0;
|
|
panic <= `PANIC_NONE;
|
end
|
end
|
else begin
|
else begin
|
|
|
did_branchback0 <= take_branch0;
|
did_branchback0 <= take_branch0;
|
did_branchback1 <= take_branch1;
|
did_branchback1 <= take_branch1;
|
Line 345... |
Line 354... |
// keep things simple. For the thread that doesn't miss the current
|
// keep things simple. For the thread that doesn't miss the current
|
// data for the fetch buffer needs to be retrieved again, so the pc
|
// data for the fetch buffer needs to be retrieved again, so the pc
|
// for that thread is assigned the current fetchbuf pc.
|
// for that thread is assigned the current fetchbuf pc.
|
// For the thread that misses the pc is simply assigned the misspc.
|
// For the thread that misses the pc is simply assigned the misspc.
|
if (branchmiss) begin
|
if (branchmiss) begin
|
|
$display("***********");
|
|
$display("Branch miss");
|
|
$display("***********");
|
if (branchmiss_thrd) begin
|
if (branchmiss_thrd) begin
|
pc0 <= fetchbuf0_pc;
|
pc0 <= fetchbuf0_pc;
|
`ifdef SUPPORT_SMT
|
`ifdef SUPPORT_SMT
|
pc1 <= misspc;
|
pc1 <= misspc;
|
`endif
|
`endif
|
Line 719... |
Line 731... |
4'b11_11 : begin // enqueue both and flip fetchbuf
|
4'b11_11 : begin // enqueue both and flip fetchbuf
|
fetchbufA_v <= `INV;
|
fetchbufA_v <= `INV;
|
fetchbufB_v <= `INV;
|
fetchbufB_v <= `INV;
|
fetchbuf <= ~fetchbuf;
|
fetchbuf <= ~fetchbuf;
|
end
|
end
|
default: ;
|
default: panic <= `PANIC_INVALIDIQSTATE;
|
endcase
|
endcase
|
else case ({fetchbufC_v, fetchbufD_v, (queued1|queuedNop), (queued2|queuedNop)})
|
else case ({fetchbufC_v, fetchbufD_v, (queued1|queuedNop), (queued2|queuedNop)})
|
4'b00_00 : ; // do nothing
|
4'b00_00 : ; // do nothing
|
// 4'b00_01 : panic <= `PANIC_INVALIDIQSTATE;
|
// 4'b00_01 : panic <= `PANIC_INVALIDIQSTATE;
|
4'b00_10 : ; // do nothing
|
4'b00_10 : ; // do nothing
|
Line 756... |
Line 768... |
4'b11_11 : begin // enqueue both and flip fetchbuf
|
4'b11_11 : begin // enqueue both and flip fetchbuf
|
fetchbufC_v <= `INV;
|
fetchbufC_v <= `INV;
|
fetchbufD_v <= `INV;
|
fetchbufD_v <= `INV;
|
fetchbuf <= ~fetchbuf;
|
fetchbuf <= ~fetchbuf;
|
end
|
end
|
default: ;
|
default: panic <= `PANIC_INVALIDIQSTATE;
|
endcase
|
endcase
|
//
|
//
|
// get data iff the fetch buffers are empty
|
// get data iff the fetch buffers are empty
|
//
|
//
|
if (fetchbufA_v == `INV && fetchbufB_v == `INV) begin
|
if (fetchbufA_v == `INV && fetchbufB_v == `INV) begin
|
Line 852... |
Line 864... |
fetchbufA_pc <= pc0;
|
fetchbufA_pc <= pc0;
|
if (phit && ~hirq)
|
if (phit && ~hirq)
|
`ifdef SUPPORT_SMT
|
`ifdef SUPPORT_SMT
|
pc0 <= pc0 + fetchbuf0_insln;
|
pc0 <= pc0 + fetchbuf0_insln;
|
`else
|
`else
|
|
if (`WAYS > 1)
|
pc0 <= pc0 + fetchbuf0_insln + fetchbuf1_insln;
|
pc0 <= pc0 + fetchbuf0_insln + fetchbuf1_insln;
|
|
else
|
|
pc0 <= pc0 + fetchbuf0_insln;
|
`endif
|
`endif
|
end
|
end
|
endtask
|
endtask
|
|
|
task FetchB;
|
task FetchB;
|
begin
|
begin
|
fetchbufB_instr <= cinsn1;
|
fetchbufB_instr <= cinsn1;
|
fetchbufB_v <= `VAL;
|
fetchbufB_v <= `WAYS > 1;
|
`ifdef SUPPORT_SMT
|
|
fetchbufB_pc <= pc1;
|
fetchbufB_pc <= pc1;
|
|
`ifdef SUPPORT_SMT
|
if (phit)
|
if (phit)
|
pc1 <= pc1 + fetchbuf1_insln;
|
pc1 <= pc1 + fetchbuf1_insln;
|
`else
|
|
fetchbufB_pc <= pc0 + fetchbuf0_insln;
|
|
`endif
|
`endif
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
Line 888... |
Line 901... |
fetchbufC_pc <= pc0;
|
fetchbufC_pc <= pc0;
|
if (phit && ~hirq)
|
if (phit && ~hirq)
|
`ifdef SUPPORT_SMT
|
`ifdef SUPPORT_SMT
|
pc0 <= pc0 + fetchbuf0_insln;
|
pc0 <= pc0 + fetchbuf0_insln;
|
`else
|
`else
|
|
if (`WAYS > 1)
|
pc0 <= pc0 + fetchbuf0_insln + fetchbuf1_insln;
|
pc0 <= pc0 + fetchbuf0_insln + fetchbuf1_insln;
|
|
else
|
|
pc0 <= pc0 + fetchbuf0_insln;
|
`endif
|
`endif
|
end
|
end
|
endtask
|
endtask
|
|
|
task FetchD;
|
task FetchD;
|
begin
|
begin
|
fetchbufD_instr <= cinsn1;
|
fetchbufD_instr <= cinsn1;
|
fetchbufD_v <= `VAL;
|
fetchbufD_v <= `WAYS > 1;
|
`ifdef SUPPORT_SMT
|
|
fetchbufD_pc <= pc1;
|
fetchbufD_pc <= pc1;
|
|
`ifdef SUPPORT_SMT
|
if (phit)
|
if (phit)
|
pc1 <= pc1 + fetchbuf1_insln;
|
pc1 <= pc1 + fetchbuf1_insln;
|
`else
|
|
fetchbufD_pc <= pc0 + fetchbuf0_insln;
|
|
`endif
|
`endif
|
end
|
end
|
endtask
|
endtask
|
|
|
task FetchCD;
|
task FetchCD;
|