Line 16... |
Line 16... |
// You should have received a copy of the GNU General Public
|
// You should have received a copy of the GNU General Public
|
// License along with this work; if not, write to the Free Software
|
// License along with this work; if not, write to the Free Software
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
//
|
//
|
// ========== Copyright Header End ============================================
|
// ========== Copyright Header End ============================================
|
|
`ifdef SIMPLY_RISC_TWEAKS
|
|
`define SIMPLY_RISC_SCANIN .si(0)
|
|
`else
|
|
`define SIMPLY_RISC_SCANIN .si()
|
|
`endif
|
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
/*
|
/*
|
// Module Name: sparc_exu_ecl_wb
|
// Module Name: sparc_exu_ecl_wb
|
// Description: Implements the writeback logic for the exu.
|
// Description: Implements the writeback logic for the exu.
|
// This includes the control signals for the w1 and w2 input
|
// This includes the control signals for the w1 and w2 input
|
Line 222... |
Line 227... |
|
|
////////////////////////////////////////////
|
////////////////////////////////////////////
|
// Pass along result of load for one cycle
|
// Pass along result of load for one cycle
|
////////////////////////////////////////////
|
////////////////////////////////////////////
|
assign ld_g = lsu_exu_dfill_vld_g | ecl_byp_ldxa_g;
|
assign ld_g = lsu_exu_dfill_vld_g | ecl_byp_ldxa_g;
|
dff dfill_vld_dff (.din(ld_g), .clk(clk), .q(ld_g2),
|
dff_s dfill_vld_dff (.din(ld_g), .clk(clk), .q(ld_g2),
|
.se(se), .si(), .so());
|
.se(se), `SIMPLY_RISC_SCANIN, .so());
|
assign kill_ld_g2 = flush_w1 & (dfill_tid_g2[1:0] == tid_w1[1:0]);
|
assign kill_ld_g2 = flush_w1 & (dfill_tid_g2[1:0] == tid_w1[1:0]);
|
assign dfill_vld_g2 = ld_g2 & ~kill_ld_g2 & ~lsu_exu_ldst_miss_g2;
|
assign dfill_vld_g2 = ld_g2 & ~kill_ld_g2 & ~lsu_exu_ldst_miss_g2;
|
dff #(2) dfill_tid_dff(.din(ld_tid_g[1:0]), .clk(clk), .q(dfill_tid_g2[1:0]),
|
dff_s #(2) dfill_tid_dff(.din(ld_tid_g[1:0]), .clk(clk), .q(dfill_tid_g2[1:0]),
|
.se(se), .si(), .so());
|
.se(se), `SIMPLY_RISC_SCANIN, .so());
|
dff #(5) dfill_rd_dff(.din(ld_rd_g[4:0]), .clk(clk), .q(dfill_rd_g2[4:0]),
|
dff_s #(5) dfill_rd_dff(.din(ld_rd_g[4:0]), .clk(clk), .q(dfill_rd_g2[4:0]),
|
.se(se), .si(), .so());
|
.se(se), `SIMPLY_RISC_SCANIN, .so());
|
|
|
///////////////////////////////////////////
|
///////////////////////////////////////////
|
// Help with bypassing of long latency ops
|
// Help with bypassing of long latency ops
|
///////////////////////////////////////////
|
///////////////////////////////////////////
|
assign wb_byplog_rd_w2[4:0] = rd_w2[4:0];
|
assign wb_byplog_rd_w2[4:0] = rd_w2[4:0];
|
Line 267... |
Line 272... |
assign ecl_irf_wen_g = (sehold)? ecl_irf_wen_w2:
|
assign ecl_irf_wen_g = (sehold)? ecl_irf_wen_w2:
|
(ecl_byp_sel_load_g & dfill_vld_g2 |
|
(ecl_byp_sel_load_g & dfill_vld_g2 |
|
(ecl_byp_sel_restore_g & restore_wen) |
|
(ecl_byp_sel_restore_g & restore_wen) |
|
(ecl_byp_sel_muldiv_g & divcntl_wb_req_g));
|
(ecl_byp_sel_muldiv_g & divcntl_wb_req_g));
|
|
|
dff wen_w2_dff(.din(ecl_irf_wen_g), .clk(clk), .q(ecl_irf_wen_w2),
|
dff_s wen_w2_dff(.din(ecl_irf_wen_g), .clk(clk), .q(ecl_irf_wen_w2),
|
.se(se), .si(), .so());
|
.se(se), `SIMPLY_RISC_SCANIN, .so());
|
mux4ds #(5) rd_g_mux(.dout(ecl_irf_rd_g[4:0]), .in0(dfill_rd_g2[4:0]),
|
mux4ds #(5) rd_g_mux(.dout(ecl_irf_rd_g[4:0]), .in0(dfill_rd_g2[4:0]),
|
.in1(mdqctl_wb_divrd_g[4:0]),
|
.in1(mdqctl_wb_divrd_g[4:0]),
|
.in2(mdqctl_wb_mulrd_g[4:0]),
|
.in2(mdqctl_wb_mulrd_g[4:0]),
|
.in3(restore_rd[4:0]),
|
.in3(restore_rd[4:0]),
|
.sel0(ecl_byp_sel_load_g),
|
.sel0(ecl_byp_sel_load_g),
|
Line 290... |
Line 295... |
mux2ds setcc_g_mux(.dout(setcc_g),
|
mux2ds setcc_g_mux(.dout(setcc_g),
|
.in0(mdqctl_wb_mulsetcc_g),
|
.in0(mdqctl_wb_mulsetcc_g),
|
.in1(mdqctl_wb_divsetcc_g),
|
.in1(mdqctl_wb_divsetcc_g),
|
.sel0(~ecl_div_sel_div),
|
.sel0(~ecl_div_sel_div),
|
.sel1(ecl_div_sel_div));
|
.sel1(ecl_div_sel_div));
|
dff #(2) dff_thr_g2w2(.din(ecl_irf_tid_g[1:0]), .clk(clk), .q(tid_w2[1:0]), .se(se),
|
dff_s #(2) dff_thr_g2w2(.din(ecl_irf_tid_g[1:0]), .clk(clk), .q(tid_w2[1:0]), .se(se),
|
.si(), .so());
|
`SIMPLY_RISC_SCANIN, .so());
|
dff #(5) dff_rd_g2w2(.din(ecl_irf_rd_g[4:0]), .clk(clk), .q(rd_w2[4:0]), .se(se),
|
dff_s #(5) dff_rd_g2w2(.din(ecl_irf_rd_g[4:0]), .clk(clk), .q(rd_w2[4:0]), .se(se),
|
.si(), .so());
|
`SIMPLY_RISC_SCANIN, .so());
|
// needs wen to setcc
|
// needs wen to setcc
|
assign wb_ccr_setcc_g = wb_divcntl_ack_g & divcntl_wb_req_g & setcc_g;
|
assign wb_ccr_setcc_g = wb_divcntl_ack_g & divcntl_wb_req_g & setcc_g;
|
|
|
|
|
///////////////////
|
///////////////////
|
Line 310... |
Line 315... |
assign ecl_byp_sel_pipe_m = (wb_m | wrsr_m) & ~ecl_byp_sel_ecc_m;
|
assign ecl_byp_sel_pipe_m = (wb_m | wrsr_m) & ~ecl_byp_sel_ecc_m;
|
assign ecl_byp_sel_restore_m = ~(wb_m | wrsr_m | ld_g2 | ecl_byp_sel_ecc_m);
|
assign ecl_byp_sel_restore_m = ~(wb_m | wrsr_m | ld_g2 | ecl_byp_sel_ecc_m);
|
assign wen_no_inst_vld_m = (sehold)? ecl_irf_wen_w:
|
assign wen_no_inst_vld_m = (sehold)? ecl_irf_wen_w:
|
((dfill_vld_g2 & ecl_byp_sel_load_m) |
|
((dfill_vld_g2 & ecl_byp_sel_load_m) |
|
(ecl_byp_sel_restore_m & restore_wen));
|
(ecl_byp_sel_restore_m & restore_wen));
|
dff dff_lsu_wen_m2w(.din(wen_no_inst_vld_m), .clk(clk), .q(wen_no_inst_vld_w), .se(se), .si(),
|
dff_s dff_lsu_wen_m2w(.din(wen_no_inst_vld_m), .clk(clk), .q(wen_no_inst_vld_w), .se(se), `SIMPLY_RISC_SCANIN,
|
.so());
|
.so());
|
// ecc_wen must be kept separate because it needs to check inst_vld but not flush
|
// ecc_wen must be kept separate because it needs to check inst_vld but not flush
|
assign inst_vld_noflush_wen_m = ecl_byp_sel_ecc_m & ~sehold;
|
assign inst_vld_noflush_wen_m = ecl_byp_sel_ecc_m & ~sehold;
|
dff ecc_wen_m2w(.din(inst_vld_noflush_wen_m), .clk(clk), .q(inst_vld_noflush_wen_w), .se(se), .si(), .so());
|
dff_s ecc_wen_m2w(.din(inst_vld_noflush_wen_m), .clk(clk), .q(inst_vld_noflush_wen_w), .se(se), `SIMPLY_RISC_SCANIN, .so());
|
|
|
assign ecl_irf_tid_m[1:0] = ((ecl_byp_sel_load_m)? dfill_tid_g2[1:0]:
|
assign ecl_irf_tid_m[1:0] = ((ecl_byp_sel_load_m)? dfill_tid_g2[1:0]:
|
(ecl_byp_sel_restore_m)? restore_tid[1:0]:
|
(ecl_byp_sel_restore_m)? restore_tid[1:0]:
|
tid_m[1:0]);
|
tid_m[1:0]);
|
|
|
Line 333... |
Line 338... |
.sel3(ecl_byp_sel_restore_m));
|
.sel3(ecl_byp_sel_restore_m));
|
assign wen_w_inst_vld = valid_w | inst_vld_noflush_wen_w;
|
assign wen_w_inst_vld = valid_w | inst_vld_noflush_wen_w;
|
assign ecl_irf_wen_w = ifu_exu_inst_vld_w & wen_w_inst_vld | wen_no_inst_vld_w;
|
assign ecl_irf_wen_w = ifu_exu_inst_vld_w & wen_w_inst_vld | wen_no_inst_vld_w;
|
|
|
// bypass valid logic and flops
|
// bypass valid logic and flops
|
dff dff_wb_d2e(.din(ifu_exu_wen_d), .clk(clk), .q(wb_e), .se(se),
|
dff_s dff_wb_d2e(.din(ifu_exu_wen_d), .clk(clk), .q(wb_e), .se(se),
|
.si(), .so());
|
`SIMPLY_RISC_SCANIN, .so());
|
dff dff_wb_e2m(.din(valid_e), .clk(clk), .q(wb_m), .se(se),
|
dff_s dff_wb_e2m(.din(valid_e), .clk(clk), .q(wb_m), .se(se),
|
.si(), .so());
|
`SIMPLY_RISC_SCANIN, .so());
|
dffr dff_wb_m2w(.din(valid_m), .clk(clk), .q(wb_w), .se(se),
|
dffr_s dff_wb_m2w(.din(valid_m), .clk(clk), .q(wb_w), .se(se),
|
.si(), .so(), .rst(reset));
|
`SIMPLY_RISC_SCANIN, .so(), .rst(reset));
|
assign valid_e = wb_e & ~ifu_exu_kill_e & ~restore_e & ~wrsr_e;// restore doesn't finish on time
|
assign valid_e = wb_e & ~ifu_exu_kill_e & ~restore_e & ~wrsr_e;// restore doesn't finish on time
|
assign bypass_m = wb_m;// bypass doesn't need to check for traps or sehold
|
assign bypass_m = wb_m;// bypass doesn't need to check for traps or sehold
|
assign valid_m = bypass_m & ~rml_ecl_kill_m & ~sehold;// sehold turns off writes from this path
|
assign valid_m = bypass_m & ~rml_ecl_kill_m & ~sehold;// sehold turns off writes from this path
|
assign valid_w = (wb_w & ~early_flush_w & ~ifu_tlu_flush_w);// check inst_vld later
|
assign valid_w = (wb_w & ~early_flush_w & ~ifu_tlu_flush_w);// check inst_vld later
|
// don't check flush for bypass
|
// don't check flush for bypass
|
Line 397... |
Line 402... |
assign ecl_rml_cleanwin_wen_w = sraddr_cleanwin_w & wrsr_w;
|
assign ecl_rml_cleanwin_wen_w = sraddr_cleanwin_w & wrsr_w;
|
assign ecl_rml_otherwin_wen_w = sraddr_otherwin_w & wrsr_w;
|
assign ecl_rml_otherwin_wen_w = sraddr_otherwin_w & wrsr_w;
|
assign ecl_rml_wstate_wen_w = sraddr_wstate_w & wrsr_w;
|
assign ecl_rml_wstate_wen_w = sraddr_wstate_w & wrsr_w;
|
|
|
|
|
dff dff_wrsr_d2e(.din(ifu_tlu_wsr_inst_d), .clk(clk), .q(wrsr_e), .se(se),
|
dff_s dff_wrsr_d2e(.din(ifu_tlu_wsr_inst_d), .clk(clk), .q(wrsr_e), .se(se),
|
.si(), .so());
|
`SIMPLY_RISC_SCANIN, .so());
|
assign exu_ffu_wsr_inst_e = wrsr_e;
|
assign exu_ffu_wsr_inst_e = wrsr_e;
|
dff dff_wrsr_e2m(.din(wrsr_e), .clk(clk), .q(wrsr_m), .se(se),
|
dff_s dff_wrsr_e2m(.din(wrsr_e), .clk(clk), .q(wrsr_m), .se(se),
|
.si(), .so());
|
`SIMPLY_RISC_SCANIN, .so());
|
dff dff_wrsr_m2w(.din(wrsr_m), .clk(clk), .q(wrsr_w), .se(se),
|
dff_s dff_wrsr_m2w(.din(wrsr_m), .clk(clk), .q(wrsr_w), .se(se),
|
.si(), .so());
|
`SIMPLY_RISC_SCANIN, .so());
|
dff #(7) dff_sraddr_d2e(.din(ifu_tlu_sraddr_d[6:0]), .clk(clk), .q(sraddr_e[6:0]), .se(se),
|
dff_s #(7) dff_sraddr_d2e(.din(ifu_tlu_sraddr_d[6:0]), .clk(clk), .q(sraddr_e[6:0]), .se(se),
|
.si(), .so());
|
`SIMPLY_RISC_SCANIN, .so());
|
dff #(7) dff_sraddr_e2m(.din(sraddr_e[6:0]), .clk(clk), .q(sraddr_m[6:0]), .se(se),
|
dff_s #(7) dff_sraddr_e2m(.din(sraddr_e[6:0]), .clk(clk), .q(sraddr_m[6:0]), .se(se),
|
.si(), .so());
|
`SIMPLY_RISC_SCANIN, .so());
|
dff #(7) dff_sraddr_m2w(.din(sraddr_m[6:0]), .clk(clk), .q(sraddr_w[6:0]), .se(se),
|
dff_s #(7) dff_sraddr_m2w(.din(sraddr_m[6:0]), .clk(clk), .q(sraddr_w[6:0]), .se(se),
|
.si(), .so());
|
`SIMPLY_RISC_SCANIN, .so());
|
dff dff_yreg_wen_w2w1(.din(yreg_wen_w), .clk(clk), .q(yreg_wen_w1), .se(se), .si(), .so());
|
dff_s dff_yreg_wen_w2w1(.din(yreg_wen_w), .clk(clk), .q(yreg_wen_w1), .se(se), `SIMPLY_RISC_SCANIN, .so());
|
|
|
// Logic for rdpr/rdsr
|
// Logic for rdpr/rdsr
|
// This mux takes advantage of the fact that these 4 encodings don't overlap
|
// This mux takes advantage of the fact that these 4 encodings don't overlap
|
assign sel_cleanwin_d = ~ifu_tlu_sraddr_d[1] & ~ifu_tlu_sraddr_d[0];
|
assign sel_cleanwin_d = ~ifu_tlu_sraddr_d[1] & ~ifu_tlu_sraddr_d[0];
|
assign sel_otherwin_d = ~ifu_tlu_sraddr_d[1] & ifu_tlu_sraddr_d[0];
|
assign sel_otherwin_d = ~ifu_tlu_sraddr_d[1] & ifu_tlu_sraddr_d[0];
|
Line 442... |
Line 447... |
.sel1(sel_cwp_d),
|
.sel1(sel_cwp_d),
|
.sel2(sel_wstate_d),
|
.sel2(sel_wstate_d),
|
.sel3(sel_rdpr_mux1_d));
|
.sel3(sel_rdpr_mux1_d));
|
|
|
assign read_yreg_e = ~(sraddr_e[3] | sraddr_e[1]);
|
assign read_yreg_e = ~(sraddr_e[3] | sraddr_e[1]);
|
dff #(8) rdpr_dff(.din(rdpr_mux2_out[7:0]), .clk(clk), .q(ecl_byp_eclpr_e[7:0]),
|
dff_s #(8) rdpr_dff(.din(rdpr_mux2_out[7:0]), .clk(clk), .q(ecl_byp_eclpr_e[7:0]),
|
.se(se), .si(), .so());
|
.se(se), `SIMPLY_RISC_SCANIN, .so());
|
|
|
|
|
///////////////////////////////
|
///////////////////////////////
|
// YREG write enable logic
|
// YREG write enable logic
|
///////////////////////////////
|
///////////////////////////////
|
Line 518... |
Line 523... |
assign restore_done[3:0] = restore_thr[3:0] & {4{restore_picked & restore_request}};
|
assign restore_done[3:0] = restore_thr[3:0] & {4{restore_picked & restore_request}};
|
// restore request waits for kills in the w stage. they
|
// restore request waits for kills in the w stage. they
|
// won't start until after the flop
|
// won't start until after the flop
|
assign restore_ready_next = (vld_restore_w | restore_ready) & ~restore_picked;
|
assign restore_ready_next = (vld_restore_w | restore_ready) & ~restore_picked;
|
|
|
dffe #(2) restore_tid_dff(.din(tid_m[1:0]), .clk(clk), .q(restore_tid[1:0]),
|
dffe_s #(2) restore_tid_dff(.din(tid_m[1:0]), .clk(clk), .q(restore_tid[1:0]),
|
.se(se), .si(), .so(), .en(restore_m));
|
.se(se), `SIMPLY_RISC_SCANIN, .so(), .en(restore_m));
|
dffe #(5) restore_rd_dff(.din(rd_m[4:0]), .clk(clk), .q(restore_rd[4:0]),
|
dffe_s #(5) restore_rd_dff(.din(rd_m[4:0]), .clk(clk), .q(restore_rd[4:0]),
|
.se(se), .si(), .so(), .en(restore_m));
|
.se(se), `SIMPLY_RISC_SCANIN, .so(), .en(restore_m));
|
dff return_d2e(.din(ifu_exu_return_d), .clk(clk), .q(return_e),
|
dff_s return_d2e(.din(ifu_exu_return_d), .clk(clk), .q(return_e),
|
.se(se), .si(), .so());
|
.se(se), `SIMPLY_RISC_SCANIN, .so());
|
dff restore_e2m(.din(vld_restore_e), .clk(clk), .q(restore_m),
|
dff_s restore_e2m(.din(vld_restore_e), .clk(clk), .q(restore_m),
|
.se(se), .si(), .so());
|
.se(se), `SIMPLY_RISC_SCANIN, .so());
|
dff restore_m2w(.din(restore_m), .clk(clk), .q(restore_w),
|
dff_s restore_m2w(.din(restore_m), .clk(clk), .q(restore_w),
|
.se(se), .si(), .so());
|
.se(se), `SIMPLY_RISC_SCANIN, .so());
|
dff restore_ready_dff(.din(restore_ready_next), .q(restore_ready),
|
dff_s restore_ready_dff(.din(restore_ready_next), .q(restore_ready),
|
.clk(clk), .se(se), .so(), .si());
|
.clk(clk), .se(se), .so(), `SIMPLY_RISC_SCANIN);
|
|
|
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
// Completion logic for non integer-pipeline operations
|
// Completion logic for non integer-pipeline operations
|
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
// short_longops must check inst_vld_e to protect against invalid completion signal
|
// short_longops must check inst_vld_e to protect against invalid completion signal
|
assign short_longop_done_e = (rml_ecl_rmlop_done_e | (restore_e & ~wb_e & ~return_e)) &
|
assign short_longop_done_e = (rml_ecl_rmlop_done_e | (restore_e & ~wb_e & ~return_e)) &
|
ifu_exu_inst_vld_e & ~ifu_exu_kill_e;
|
ifu_exu_inst_vld_e & ~ifu_exu_kill_e;
|
dff longop_done_e2m (.din(short_longop_done_e), .clk(clk), .q(short_longop_done_m), .se(se), .si(), .so());
|
dff_s longop_done_e2m (.din(short_longop_done_e), .clk(clk), .q(short_longop_done_m), .se(se), `SIMPLY_RISC_SCANIN, .so());
|
assign short_longop_done[3:0] = thr_m[3:0] & {4{short_longop_done_m}};
|
assign short_longop_done[3:0] = thr_m[3:0] & {4{short_longop_done_m}};
|
|
|
assign ecl_longop_done_nokill_m[3:0] = (muldiv_done_g[3:0] | restore_done[3:0] | short_longop_done[3:0] |
|
assign ecl_longop_done_nokill_m[3:0] = (muldiv_done_g[3:0] | restore_done[3:0] | short_longop_done[3:0] |
|
rml_ecl_swap_done[3:0]);
|
rml_ecl_swap_done[3:0]);
|
assign ecl_longop_done_kill_m[3:0] = (muldiv_done_g[3:0] | restore_done[3:0] | rml_ecl_swap_done[3:0]);
|
assign ecl_longop_done_kill_m[3:0] = (muldiv_done_g[3:0] | restore_done[3:0] | rml_ecl_swap_done[3:0]);
|