wire alttag_low
;
Mflipflop_1 alttag_low_reg_1(alttag_low,nalttag_low,ss_clock,hold_alt) ;
wire dpc_low_l
= ~dpc_low;
wire pfpc_low_l
= ~pfpc_low;
// a similar mux is in the PC datapath.
wire fpc_low_int
;
// Expanded macro begin.
// cmux7dnm(fpc_low_int_mux, 1, fpc_low_int, lta_low, sel_lta_fpc, dpc_low_l, sel_idpc_fpc, 1'b0, sel_post_reset, pfpc_low, sel_p_fpc, alttag_low, sel_alt_tag, pfpc_low_l, sel_i1pfpc_fpc, dpc_low, sel_i2dpc_fpc)
function [1:1] fpc_low_int_mux ;
input [1:1] in0_fn ;
input s0_fn ;
input [1:1] in1_fn ;
input s1_fn ;
input [1:1] in2_fn ;
input s2_fn ;
input [1:1] in3_fn ;
input s3_fn ;
input [1:1] in4_fn ;
input s4_fn ;
input [1:1] in5_fn ;
input s5_fn ;
input [1:1] in6_fn ;
input s6_fn ;
reg [1:1] out_fn ;
begin
case ({ sel_i2dpc_fpc, sel_i1pfpc_fpc, sel_alt_tag, sel_p_fpc, sel_post_reset, sel_idpc_fpc, sel_lta_fpc}) /* synopsys parallel_case */
7'b0000001: out_fn = in0_fn ;
7'b0000010: out_fn = in1_fn ;
7'b0000100: out_fn = in2_fn ;
7'b0001000: out_fn = in3_fn ;
7'b0010000: out_fn = in4_fn ;
7'b0100000: out_fn = in5_fn ;
7'b1000000: out_fn = in6_fn ;
default: out_fn = 65'hx;
endcase
fpc_low_int_mux = out_fn ;
end
endfunction
assign fpc_low_int = fpc_low_int_mux( lta_low, sel_lta_fpc, dpc_low_l, sel_idpc_fpc, 1'b0, sel_post_reset, pfpc_low,
sel_p_fpc, alttag_low, sel_alt_tag, pfpc_low_l, sel_i1pfpc_fpc, dpc_low, sel_i2dpc_fpc) ;
// Expanded macro end.
// this assumes that can_fold = 1
wire fpc_low_int_cf1
;
// Expanded macro begin.
// cmux7dnm(fpc_low_int_cf1_mux, 1, fpc_low_int_cf1, lta_low, sel_lta_fpc, dpc_low_l, sel_idpc_fpc_cf1, 1'b0, sel_post_reset, pfpc_low, sel_p_fpc_cf1, alttag_low, sel_alt_tag, pfpc_low_l, sel_i1pfpc_fpc_cf1, dpc_low, sel_i2dpc_fpc_cf1)
function [1:1] fpc_low_int_cf1_mux ;
input [1:1] in0_fn ;
input s0_fn ;
input [1:1] in1_fn ;
input s1_fn ;
input [1:1] in2_fn ;
input s2_fn ;
input [1:1] in3_fn ;
input s3_fn ;
input [1:1] in4_fn ;
input s4_fn ;
input [1:1] in5_fn ;
input s5_fn ;
input [1:1] in6_fn ;
input s6_fn ;
reg [1:1] out_fn ;
begin
case ({ sel_i2dpc_fpc_cf1, sel_i1pfpc_fpc_cf1, sel_alt_tag, sel_p_fpc_cf1, sel_post_reset, sel_idpc_fpc_cf1, sel_lta_fpc}) /* synopsys parallel_case */
7'b0000001: out_fn = in0_fn ;
7'b0000010: out_fn = in1_fn ;
7'b0000100: out_fn = in2_fn ;
7'b0001000: out_fn = in3_fn ;
7'b0010000: out_fn = in4_fn ;
7'b0100000: out_fn = in5_fn ;
7'b1000000: out_fn = in6_fn ;
default: out_fn = 65'hx;
endcase
fpc_low_int_cf1_mux = out_fn ;
end
endfunction
assign fpc_low_int_cf1 = fpc_low_int_cf1_mux( lta_low, sel_lta_fpc, dpc_low_l, sel_idpc_fpc_cf1, 1'b0, sel_post_reset, pfpc_low,
sel_p_fpc_cf1, alttag_low, sel_alt_tag, pfpc_low_l, sel_i1pfpc_fpc_cf1, dpc_low, sel_i2dpc_fpc_cf1) ;
// Expanded macro end.
// this accumes that can_fold = 0
wire fpc_low_int_cf0
;
// Expanded macro begin.
// cmux5dnm(fpc_low_int_cf0_mux, 1, fpc_low_int_cf0, lta_low, sel_lta_fpc, dpc_low_l, sel_idpc_fpc_cf0, 1'b0, sel_post_reset, pfpc_low, sel_p_fpc_cf0, alttag_low, sel_alt_tag)
function [1:1] fpc_low_int_cf0_mux ;
input [1:1] in0_fn ;
input s0_fn ;
input [1:1] in1_fn ;
input s1_fn ;
input [1:1] in2_fn ;
input s2_fn ;
input [1:1] in3_fn ;
input s3_fn ;
input [1:1] in4_fn ;
input s4_fn ;
reg [1:1] out_fn ;
begin
case ({ sel_alt_tag, sel_p_fpc_cf0, sel_post_reset, sel_idpc_fpc_cf0, sel_lta_fpc}) /* synopsys parallel_case */
5'b00001: out_fn = in0_fn ;
5'b00010: out_fn = in1_fn ;
5'b00100: out_fn = in2_fn ;
5'b01000: out_fn = in3_fn ;
5'b10000: out_fn = in4_fn ;
default: out_fn = 65'hx;
endcase
fpc_low_int_cf0_mux = out_fn ;
end
endfunction
assign fpc_low_int_cf0 = fpc_low_int_cf0_mux( lta_low, sel_lta_fpc, dpc_low_l, sel_idpc_fpc_cf0, 1'b0, sel_post_reset, pfpc_low, sel_p_fpc_cf0, alttag_low, sel_alt_tag) ;
// Expanded macro end.
/************************* BR INTERLOCK ****************************/
/*
* figure out if we have to interlock - this case involves an
* untaken branch in E and an empty queue
*
* also a save/restore in the delay slot of an annuled and folded
* branch.
*/
wire sv_rest_in_d
=
valid_decode
& (d_hop3==`SAVE | d_hop3==`RESTORE);
wire sv_rest_in_e
;
Mflipflop_1 sv_rest_in_e_reg_1(sv_rest_in_e,sv_rest_in_d,ss_clock,hold) ;
wire nuntaken_emt_il
=
br_fbr_in_d & ~nlast_taken
| call_in_d_vd & nfold_annul
| nkill_jmp_ld
;
wire untaken_emt_il
;
Mflipflop_1 untaken_emt_il_reg_1(untaken_emt_il,nuntaken_emt_il,ss_clock,hold) ;
assign untaken_empty_ilock =
q_state[0] & untaken_emt_il;
// & (
// br_fbr_in_e & ~last_taken
// | call_in_e & fold_annul
// | kill_jmp_ld
// )
// ;
wire sv_rest_fold_ilock =
(sv_rest_in_e & fold_annul2 & ~mispredicted)
;
assign sv_rest_recirc =
sv_rest_in_e & fold_annul2 & ~TRAP;
/************************ IFLUSH junk ********************************/
wire flush_ic_e = ~fold_annul & (
flush_asi_e & e_hop3==`STA
| e_hop3==`IFLUSH)
;
wire nkill_fetch_fill
=
~nq_state[0] & flush_ic_e & ~can_fold;
// wire kffr_hold = ~kill_fetch_fill & hold;
Mflipflop_1 kill_fetch_fill_reg_1(kill_fetch_fill,nkill_fetch_fill, ss_clock,hold) ;
// this term turns on if there is a flush_ic_e and
// an attempt by the I$ or MMU to force the ifill address.
// it is also found in the module Mhold_control to hold
// the pipe if this condition is detected. this logic was
// in the I$ control, but timing problems require it in
// Mdecode and Mhold_control.
wire flsh_fill_conf
= force_ifill & flush_ic_e;
/************************ BR FOLD TRAP LOGIC *************************/
/*
* first case - delay slot of bicc traps and the branch was mispredicted.
* must send wpc to Mexec instead of tpc since tpc has the pc of the
* mispredicted inst.
*/
wire last_misp
;
Mflipflop_1 last_misp_reg_1(last_misp,mispredicted,ss_clock,hold) ;
wire nfwd_wpc_almost
= ~reset & ~trap_cyc2 & (
last_misp & TRAP
| fwd_wpc_almost)
;
// this reg turns on when TRAP detected and stays on until trap_cyc2
Mflipflop_1 fwdwpda_reg_1(fwd_wpc_almost,nfwd_wpc_almost,ss_clock,hold) ;
wire fwd_wpc = fwd_wpc_almost & trap_cyc2;
/*
* second case - inst before a folded pair takes a trap. need to
* fwd tpc-4 not tpc.
*/
wire ntrap_bf_fold
= ~reset & ~trap_cyc2 & (
TRAP & (fold_in_e | multiple_fold_d & fold_in_d)
| trap_before_fold)
;
// this reg turns on when TRAP detected and stays on until trap_cyc2
Mflipflop_1 trap_bf_fold_reg_1(trap_before_fold,ntrap_bf_fold,ss_clock,hold) ;
wire fwd_tpcm4 = trap_before_fold & trap_cyc2;
wire use_tpc = ~fwd_wpc & ~fwd_tpcm4;
/************************* FETCH SELECTION ***************************/
/*
* determine fetch source
*/
wire nfchic_t0
=
~ncant_unload & ~(nmispredicted | fld_hlp_misp);
wire nfchic_t1
=
nlast_taken & br_fbr_in_d
| nq_state[0]
;
wire nfchic_t2
=
call_in_d_vd & ~nfold_annul
| trap_cyc1
| njmp_rett_in_w
;
wire fchic_t0
,fchic_t1
,fchic_t2
;
Mflipflop_1 fchic_t0_reg_1(fchic_t0,nfchic_t0,ss_clock,hold) ;
Mflipflop_1 fchic_t1_reg_1(fchic_t1,nfchic_t1,ss_clock,hold) ;
Mflipflop_1 fchic_t2_reg_1(fchic_t2,nfchic_t2,ss_clock,hold) ;
wire fetch_ic
= fchic_t0 & (
fchic_t1 | fchic_t2
| predict_taken & ~multiple_fold_d
| can_fold & q_state[1]
)
;
// this assumes can_fold = 1
wire fetch_ic_cf1
= fchic_t0 & (
fchic_t1 | fchic_t2
| predict_taken & ~multiple_fold_d
| q_state[1]
)
;
// this assumes can_fold = 0
wire fetch_ic_cf0
= fchic_t0 & (
fchic_t1 | fchic_t2
| predict_taken & ~multiple_fold_d
)
;
// use this version in stop_fetch. don't need the
// can_fold term in here. here's the reasoning:
// fetch_ic would turn on we can fold a branch and the
// Q has one entry. this should cause stop_fetch
// to not be asserted. however can_fold will NOT turn on
// if the TOQ has an iacc exc associated with it, so
// the can_fold & q_state[1] term would not have turned
// on anyway. if the TOQ is a Bicc without iacc exc
// status, but the delay slot in the Q has exc status,
// the can_fold & q_state[1] term will also not turn on
// since there is more than one entry in the Q.
wire fetch_ic_trunc
= fchic_t0 & (
fchic_t1 | fchic_t2
| predict_taken & ~multiple_fold_d
)
;
/*
* try to do this faster
wire fetch_ic = ~cant_unload & ~(mispredicted | keep_alt) & (
last_taken & br_fbr_in_e
| call_in_e & ~fold_annul
| q_state[0]
| trap_cyc2
| jmp_rett_in_w
| predict_taken & ~multiple_fold_d
| can_fold & q_state[1]
)
;
*/
wire toq_2_alt
= predict_taken & ~multiple_fold_d;
assign hold_alt = ~toq_2_alt; // ~iu_fetch_f & ~toq_2_alt
wire use_f_nold
= fetch_ic & fpc_low_int; // & iu_fetch_f
// this version assumes can_fold = 1
wire fetch_ic_even_cf1
=
fetch_ic_cf1 & ~fpc_low_int_cf1 & ~cant_unload;
// this version assumes can_fold = 0
wire fetch_ic_even_cf0
=
fetch_ic_cf0 & ~fpc_low_int_cf0 & ~cant_unload;
wire fetch_ic_even;
// Expanded macro begin.
// cmux2(fetch_ic_even_mux, 1, fetch_ic_even, fetch_ic_even_cf0, fetch_ic_even_cf1, can_fold)
function [1:1] fetch_ic_even_mux ;
input [1:1] in0_fn ;
input [1:1] in1_fn ;
input select_fn ;
reg [1:1] out_fn ;
begin
case (select_fn) /* synopsys parallel_case */
1'b0: out_fn = in0_fn ;
1'b1: out_fn = in1_fn ;
default: out_fn = 65'hx;
endcase
fetch_ic_even_mux = out_fn ;
end
endfunction
assign fetch_ic_even = fetch_ic_even_mux( fetch_ic_even_cf0, fetch_ic_even_cf1, can_fold) ;
// Expanded macro end.
/* wire fetch_ic_even = fetch_ic & ~fpc_low_int & ~cant_unload;*/
// this version assumes can_fold = 1
wire fetch_ic_odd_cf1
=
fetch_ic_cf1 & fpc_low_int_cf1 & ~cant_unload;
// this version assumes can_fold = 0
wire fetch_ic_odd_cf0
=
fetch_ic_cf0 & fpc_low_int_cf0 & ~cant_unload;
wire fetch_ic_odd;
// Expanded macro begin.
// cmux2(fetch_ic_odd_mux, 1, fetch_ic_odd, fetch_ic_odd_cf0, fetch_ic_odd_cf1, can_fold)
function [1:1] fetch_ic_odd_mux ;
input [1:1] in0_fn ;
input [1:1] in1_fn ;
input select_fn ;
reg [1:1] out_fn ;
begin
case (select_fn) /* synopsys parallel_case */
1'b0: out_fn = in0_fn ;
1'b1: out_fn = in1_fn ;
default: out_fn = 65'hx;
endcase
fetch_ic_odd_mux = out_fn ;
end
endfunction
assign fetch_ic_odd = fetch_ic_odd_mux( fetch_ic_odd_cf0, fetch_ic_odd_cf1, can_fold) ;
// Expanded macro end.
/* wire fetch_ic_odd = fetch_ic & fpc_low_int & ~cant_unload; */
// this reg is just for the performance counter that
// counts if the IU has done a fetch. see did_fetch for
// more details
wire pfetch_ic_odd
;
Mflipflop_1 pfetch_ic_odd_reg_1(pfetch_ic_odd,fetch_ic_odd,ss_clock,1'b0) ;
// this wire is so we can tell if we have a mispredicted branch
// folded with a long multicycle inst - inst in E, help in D,
// and that help is generating another help.
// note that gen_help already incorporates fold_annul via valid_decode
assign fld_hlp_misp = ~reset & (
mispredicted & gen_help
| keep_alt & gen_help
);
Mflipflop_1 keep_alt_reg_1(keep_alt,fld_hlp_misp,ss_clock,hold) ;
assign fetch_alt = (mispredicted | keep_alt);
wire fetch_SIQ = can_fold & ~q_state[1] & ~cant_unload;
// this version assumes can_fold = 1
wire fetch_SIQ_cf1
= ~q_state[1] & ~cant_unload;
wire fetch_TOQ = ~fetch_ic & ~fetch_alt & ~fetch_SIQ & ~cant_unload;
// this version assumes can_fold = 1
wire fetch_TOQ_cf1
=
~fetch_ic_cf1 & ~fetch_alt & ~fetch_SIQ_cf1 & ~cant_unload;
// this version assumes can_fold = 0
wire fetch_TOQ_cf0
= ~fetch_ic_cf0 & ~fetch_alt & ~cant_unload;
// REGWIRE last_fetch_TOQ;
// REG(lfT_reg,1,last_fetch_TOQ,fetch_TOQ,ss_clock,hold)
/************************** QUEUE CONTROL ************************/
/*
* determine if can't load $ data into Q
*/
assign nkill_jmp_ld = e_hop3==`JMP & fold_annul;
Mflipflop_1 kill_jmp_ld_reg_1(kill_jmp_ld,nkill_jmp_ld,ss_clock,hold) ;
// this term is used in the event that a bicc/bfcc/call is
// in D and got interlocked. the logic allows the target
// address to go out, but we cannot load that data into
// the queue in the next cycle. reason: because the target
// address will stay on the iva for as long as the interlock
// exists + 1 cycle for the cti to be in D uninterlocked.
// this would cause the target to be fetched multiple times
// and be loaded into the queue.
wire nkill_ilock_br_fetch
=
valid_decode_nilock & ilock
& (d_hop2==`BICC | d_hop2==`BFCC | d_hop==`CALL);
wire kill_ilock_br_fetch
;
Mflipflop_1 kill_ilock_br_fetch_reg_1(kill_ilock_br_fetch, nkill_ilock_br_fetch,ss_clock,hold) ;
// the wo/wu terms were added to fix a possible problem
// if software does not mark configuration registers
// as unexecutable. if a restore/save is followed by
// a jmp, and that restore/save traps from a wo/wu,
// the jmp may read a bad value from the RF. if that
// address points to a configuration register and software
// mistakenly didn't mark that page not-execute, the
// machine will hang since the MMU and I$ do not know
// that that device will not return an instruction,
// and so will never release the pipeline.
// the proper fix is in software.
// we have decided to not put this patch in the IU,
// so it is commented out here.
wire wo_wu_trap_w
= (wo_trap_w | wu_trap_w) & TRAP;
wire wo_wu_trap_r
;
Mflipflop_1 wo_wu_trap_r_reg_1(wo_wu_trap_r,wo_wu_trap_w,ss_clock,hold) ;
// this term is in there to keep the IU from fetching instructions
// if there is an instruction marked with an invalid access
// error or protection violation in the queue. only need to
// look at entries 1-3 since these fetches always occur on
// the double word. if qx_iae and qx_ptc are both 1, that
// indicates a watchpoint trap. do not stop fetching because
// of watchpoint traps, so use XOR, not OR.
wire stop_fetch = ~trap_cyc1 & ~trap_cyc2 & ~fetch_ic_trunc & (
(q_state[3] | q_state[4]) & (q3_iae ^ q3_ptc)
| q_state[2] & (q2_iae ^ q2_ptc)
| q_state[1] & (q1_iae ^ q1_ptc)
)
| wo_wu_trap_r
;
wire cant_load_part1
=
br_fbr_in_e & ~last_taken
| call_in_e & fold_annul
| mispredicted | keep_alt
| kill_jmp_ld
| kill_ilock_br_fetch
| last_force_dva
| kill_fetch_fill
;
// this version has long path thru fpc_low_int
wire cant_load
=
fetch_ic & fpc_low_int
| cant_load_part1
| stop_fetch
;
// this assumes can_fold = 1
wire cant_load_cf1
=
fetch_ic_cf1 & fpc_low_int_cf1
| cant_load_part1
| stop_fetch
;
// this assumes can_fold = 0
wire cant_load_cf0
=
fetch_ic_cf0 & fpc_low_int_cf0
| cant_load_part1
| stop_fetch
;
//| call_in_e
// need to add ic2alt term- what is call_in_e here for?
// i dunno - it shouldn't be
// | hold_br1 & fold_in_d
wire nflshq_t1
=
br_fbr_in_d & nlast_taken
| njmp_rett_in_w
| fld_hlp_misp
;
wire nflshq_t2
=
call_in_d_vd & ~nfold_annul
| nmispredicted
;
wire flshq_t1
, flshq_t2
;
Mflipflop_1 flshq_t1_reg_1(flshq_t1,nflshq_t1,ss_clock,hold) ;
Mflipflop_1 flshq_t2_reg_1(flshq_t2,nflshq_t2,ss_clock,hold) ;
assign flushq =
flshq_t1 | flshq_t2
// | IU_in_trap
| trap_cyc1 | trap_cyc2
| first_fold_d_predict
;
/*
* do this faster
wire flushq =
br_fbr_in_e & last_taken
| call_in_e & ~fold_annul
| jmp_rett_in_w
| IU_in_trap
| first_fold_d_predict
| mispredicted | keep_alt
;
*/
/*
* queue state machine
*/
wire nqs0
= reset |
q_state[0] & cant_load // | ~iu_fetch_f)
| q_state[1] & cant_load & fetch_TOQ
| q_state[2] & cant_load & fetch_SIQ
| flushq & (fetch_ic & fpc_low_int | cant_load)
;
wire nqs1
= ~reset & (
q_state[0] & fetch_ic & ~fpc_low_int & ~cant_load
| q_state[0] & ~cant_unload & ~cant_load & ~flushq & fpc_low_int
| q_state[1] & cant_unload & cant_load & ~flushq
| q_state[1] & can_fold & ~cant_load
| q_state[2] & fetch_TOQ & cant_load
| q_state[3] & fetch_SIQ & cant_load
| flushq & fetch_ic & ~fpc_low_int & ~cant_load
| flushq & cant_unload & fpc_low_int & ~cant_load
)
;
wire nqs2
= ~reset & (
q_state[0] & cant_unload & ~cant_load & ~flushq //&~fpc_low
| q_state[1] & fetch_TOQ & ~cant_load
| q_state[2] & cant_unload & cant_load & ~flushq
| q_state[2] & fetch_SIQ & ~cant_load
| q_state[3] & fetch_TOQ & cant_load
| q_state[4] & fetch_SIQ & cant_load
| flushq & cant_unload & ~fpc_low_int & ~cant_load
)
;
wire nqs3
= ~reset & (
q_state[1] & cant_unload & ~cant_load & ~flushq
| q_state[2] & fetch_TOQ & ~cant_load
| q_state[3] & cant_unload & ~flushq
| q_state[3] & fetch_SIQ & ~cant_load
| q_state[4] & fetch_TOQ
)
;
wire nqs4
= ~reset & (
q_state[2] & cant_unload & ~cant_load & ~flushq
| q_state[3] & fetch_TOQ & ~cant_load
| q_state[4] & cant_unload & ~flushq
| q_state[4] & fetch_SIQ & ~cant_load
)
;
assign nq_state = {nqs4,nqs3,nqs2,nqs1,nqs0};
Mflipflop_5 q_state_reg_5(q_state,nq_state,ss_clock,hold) ;
// REGWIRE [4:0] last_q_state;
// REG(lq_state_reg,5,last_q_state,q_state,ss_clock,hold)
/*
* old style - too slow and complicated
wire load_q =
(nq_state > q_state)
| (nq_state == q_state) & (fetch_TOQ | fetch_SIQ)
| flushq & ~nq_state[0]
;
*/
wire load_q
= ~cant_load & (
part_stuff_q
| fetch_ic & ~fpc_low_int & (q_state[0] | flushq)
);
// this register is for performance counter only. it
// is used in conjuction with pfetch_ic_odd tp indicate
// the IU accepted instruction(s) last cycle. this
// register is different from llastc_reg since it
// is free running
wire pload_q
;
Mflipflop_1 pload_q_reg_1(pload_q,load_q,ss_clock,1'b0) ;
// special performance counter. this one indicates that
// the IU accepted instructions last cycle.
wire did_fetch = pload_q | pfetch_ic_odd;
// loaded last cyc is used to indicate is something was
// loaded into the queue on the last rising edge of clock.
// it is held by hld_llc. hld_mar_car hold turns on in the
// event we get a bicc/bfcc/call in D that gets interlocked.
// hld_llc turns on one cycle later and stays one cycle longer.
// in that event, we want to preserve the loaded_lastcyc
// from from the previous fetch. load_q will be off as
// long as the interlocked bicc/bfcc/call is in D due
// to kill_ilock_br_fetch
wire loaded_lastcyc
;
Mflipflop_1 llastc_reg_1(loaded_lastcyc,load_q,ss_clock,hld_llc) ;
/*
* Q1 control
*/
// this version assumes that can_fold = 1
wire sel_even1_cf1
= ~cant_load_cf1 & (
q_state[0] & cant_unload & ~flushq
| q_state[1] & fetch_TOQ_cf1
| flushq & cant_unload & ~fpc_low_int_cf1
| q_state[2] & fetch_SIQ_cf1
);
// this version assumes that can_fold = 0
wire sel_even1_cf0
= ~cant_load_cf0 & (
q_state[0] & cant_unload & ~flushq
| q_state[1] & fetch_TOQ_cf0
| flushq & cant_unload & ~fpc_low_int_cf0
);
wire sel_even1;
// Expanded macro begin.
// cmux2(sel_even1_mux, 1, sel_even1, sel_even1_cf0, sel_even1_cf1, can_fold)
function [1:1] sel_even1_mux ;
input [1:1] in0_fn ;
input [1:1] in1_fn ;
input select_fn ;
reg [1:1] out_fn ;
begin
case (select_fn) /* synopsys parallel_case */
1'b0: out_fn = in0_fn ;
1'b1: out_fn = in1_fn ;
default: out_fn = 65'hx;
endcase
sel_even1_mux = out_fn ;
end
endfunction
assign sel_even1 = sel_even1_mux( sel_even1_cf0, sel_even1_cf1, can_fold) ;
// Expanded macro end.
// this version assumes that can_fold = 1
wire sel_odd1_cf1
= ~cant_load_cf1 & (
q_state[0] & fetch_ic_cf1 & ~fpc_low_int_cf1
| q_state[0] & ~cant_unload & ~flushq
& fpc_low_int_cf1
| q_state[1]
| flushq & fetch_ic_cf1 & ~fpc_low_int_cf1
| flushq & cant_unload & fpc_low_int_cf1
);
// this version assumes that can_fold = 0
wire sel_odd1_cf0
= ~cant_load_cf0 & (
q_state[0] & fetch_ic_cf0 & ~fpc_low_int_cf0
| q_state[0] & ~cant_unload & ~flushq
& fpc_low_int_cf0
| flushq & fetch_ic_cf0 & ~fpc_low_int_cf0
| flushq & cant_unload & fpc_low_int_cf0
);
wire sel_odd1;
// Expanded macro begin.
// cmux2(sel_odd1_mux, 1, sel_odd1, sel_odd1_cf0, sel_odd1_cf1, can_fold)
function [1:1] sel_odd1_mux ;
input [1:1] in0_fn ;
input [1:1] in1_fn ;
input select_fn ;
reg [1:1] out_fn ;
begin
case (select_fn) /* synopsys parallel_case */
1'b0: out_fn = in0_fn ;
1'b1: out_fn = in1_fn ;
default: out_fn = 65'hx;
endcase
sel_odd1_mux = out_fn ;
end
endfunction
assign sel_odd1 = sel_odd1_mux( sel_odd1_cf0, sel_odd1_cf1, can_fold) ;
// Expanded macro end.
/*
* these are too slow
wire sel_even1 =
q_state[0] & cant_unload & ~cant_load & ~flushq // ~fpc_low
| q_state[1] & fetch_TOQ & ~cant_load
| flushq & cant_unload & ~fpc_low_int & ~cant_load
| q_state[2] & fetch_SIQ & ~cant_load
;
wire sel_odd1 =
q_state[0] & fetch_ic & ~fpc_low_int & ~cant_load
| q_state[0] & ~cant_unload & ~cant_load & ~flushq
& fpc_low_int
| q_state[1] & can_fold & ~cant_load
| flushq & fetch_ic & ~fpc_low_int & ~cant_load
| flushq & cant_unload & fpc_low_int & ~cant_load
;
*/
wire sel_fold1 = can_fold & ~(q_state[1] | q_state[2]);
// this version assumes can_fold = 1
wire sel_shift1_cf1
= ~sel_even1_cf1 & ~sel_odd1_cf1 & ~sel_fold1;
// this version assumes can_fold = 0
wire sel_shift1_cf0
= ~sel_even1_cf0 & ~sel_odd1_cf0 & ~sel_fold1;
wire sel_shift1;
// Expanded macro begin.
// cmux2(sel_shift1_mux, 1, sel_shift1, sel_shift1_cf0, sel_shift1_cf1, can_fold)
function [1:1] sel_shift1_mux ;
input [1:1] in0_fn ;
input [1:1] in1_fn ;
input select_fn ;
reg [1:1] out_fn ;
begin
case (select_fn) /* synopsys parallel_case */
1'b0: out_fn = in0_fn ;
1'b1: out_fn = in1_fn ;
default: out_fn = 65'hx;
endcase
sel_shift1_mux = out_fn ;
end
endfunction
assign sel_shift1 = sel_shift1_mux( sel_shift1_cf0, sel_shift1_cf1, can_fold) ;
// Expanded macro end.
// wire sel_shift1 = fetch_TOQ & ~(sel_even1 | sel_odd1);
wire hold_q1 = cant_unload & ~q_state[0] & ~flushq;
/*
* Q2 control
*/
wire sel_even2 =
q_state[1] & cant_unload & ~cant_load & ~flushq
| q_state[2] & fetch_TOQ & ~cant_load
| q_state[3] & fetch_SIQ & ~cant_load
;
wire sel_odd2 = sel_even1;
/*
wire sel_odd2 =
q_state[0] & cant_unload & ~cant_load & ~flushq // ~fpc_low
| q_state[1] & fetch_TOQ & ~cant_load
| flushq & cant_unload & ~fpc_low_int & ~cant_load
| q_state[2] & fetch_SIQ & ~cant_load
;
*/
// wire sel_fold2 = can_fold & (q_state[3] | q_state[4]);
wire sel_fold2 = can_fold & q_state[4];
wire sel_shift2 = ~sel_even2 & ~sel_odd2 & ~sel_fold2;
// wire sel_shift2 = fetch_TOQ & ~(sel_even2 | sel_odd2);
wire hold_q2 = cant_unload & ~(q_state[0] | q_state[1]) & ~flushq;
/*
* Q3 control
*/
wire sel_even3 =
q_state[2] & cant_unload & ~cant_load
| q_state[3] & fetch_TOQ & ~cant_load
| q_state[4] & fetch_SIQ & ~cant_load
;
wire sel_odd3 =
q_state[1] & cant_unload & ~cant_load & ~flushq
| q_state[2] & fetch_TOQ & ~cant_load
| q_state[3] & fetch_SIQ & ~cant_load
;
wire sel_shift3 = ~sel_even3 & ~sel_odd3;
// wire sel_shift3 = fetch_TOQ & ~(sel_even3 | sel_odd3);
wire hold_q3 = cant_unload & (q_state[3] | q_state[4]) & ~flushq;
/*
* Q4 control
*/
wire hold_q4 = cant_unload & q_state[4] & ~flushq;
/********************* FETCH HOLD CONTROL *************************/
// these signals are to get around the slow hold (from slow it_hit_f
// and dt_hit_w). we can't bring hold into the address generation
// or we will not meet the large setup time required on the I$ address
// at the tag and SRAMs. the idea is to hold the last fetched data
// in a reg in the queue. then mux these into the queue when the
// hold is released. hld_backup is used to hold the register. this
// turns on when fetch data comes back but pipe is held for a non-I$
// related hold. it stays asserted until the hold goes away.
// take_icdata is on to select the I$ directly. it turns off
// when the pipe is held by a non-I$ related hold (pipelined by 1).
wire take_icdata_l
;
wire ntake_icdata_l
=
hold_noic & ~hold_ic
| take_icdata_l & hold
;
Mflipflop_1 take_icdata_reg_1(take_icdata_l,ntake_icdata_l,ss_clock,1'b0) ;
wire take_icdata = ~take_icdata_l;
wire hld_backup_almost
;
wire hld_backup;
wire got_idata
=
hold & ~hold_ic
| hld_backup_almost & hold
// ~hold
;
Mflipflop_1 hld_backup_almost_reg_1(hld_backup_almost,got_idata,ss_clock,1'b0) ;
// the gate with hold has been moved to Mqueue for timing reasons
assign hld_backup =
hld_backup_almost; // & hold
/************************** GEN ADR SELECTION *********************/
// this signal should be on most of the time when we load something
// into the queue. not all the time (we use a modified cant_load,
// that does not include fetch_ic and fpc_low_int). this signal is
// meant only to be used with fetch_ic to determine if the fetch
// data to the IU is being used this cycle or not. this determines
// which address to send to the I$ this cycle for the fetch next cycle.
// we use this signal because it does not depend on fpc_low_int so should
// cause iva generation to be sped up.
assign part_stuff_q =
flushq & cant_unload
| q_state[1] & can_fold
| q_state[2] & cant_unload
| cant_unload & ~flushq & (q_state[0] | q_state[1])
| fetch_TOQ & (q_state[1] | q_state[2] | q_state[3])
| fetch_SIQ & (q_state[2] | q_state[3] | q_state[4])
;
// assumes can_fold = 1
wire part_stuff_q_cf1
=
flushq & cant_unload
| q_state[1]
| q_state[2] & cant_unload
| cant_unload & ~flushq & (q_state[0] | q_state[1])
| fetch_TOQ_cf1 & (q_state[1] | q_state[2] | q_state[3])
| fetch_SIQ_cf1 & (q_state[2] | q_state[3] | q_state[4])
;
// assumes can_fold = 0
wire part_stuff_q_cf0
=
flushq & cant_unload
| q_state[2] & cant_unload
| cant_unload & ~flushq & (q_state[0] | q_state[1])
| fetch_TOQ_cf0 & (q_state[1] | q_state[2] | q_state[3])
;
wire stuff_q
= ~cant_load_part1 & (
part_stuff_q
)
;
// assumes can_fold = 1
wire stuff_q_cf1
= ~cant_load_part1 & (
part_stuff_q_cf1
)
;
// assumes can_fold = 0
wire stuff_q_cf0
= ~cant_load_part1 & (
part_stuff_q_cf0
)
;
/*
* gen addr (iu_iva_g) mux selection
*/
// need the untaken_empty_ilock term because sadr_aa is
// no longer dependant on interlock. what would happen
// is an untaken br in E would turn on untaken_empty_ilock
// but because a call/br in D, sadr_aa would turn on
// causing the wrong inst to be fetched
wire ANNUL_am
;
Mflipflop_1 ANNUL_am_reg2_1(ANNUL_am,nANNUL,ss_clock,hold) ;
wire ANNUL
= ANNUL_am & ~fold_annul;
wire saa_null
=
~reset & ~ANNUL
& ~d_nop & ~d_trap
;
wire d_hop2bfccc
= d_hop2==`BFCC;
wire sadr_aa_callbfcc
= saa_null & (
d_hop2bfccc & ~fcc_ilock
| call_in_d_nvd
);
wire dhop2bicc
= d_hop2==`BICC;
wire sadr_aa_bicc_almost
= saa_null & dhop2bicc;
wire sadr_aa
= ~iacc_exc_mmumiss_d & (
sadr_aa_callbfcc
| sadr_aa_bicc_almost
);
wire sadr_fold_aa
= ~untaken_empty_ilock & (
can_fold & ~mispredicted & ~reset
| sadr_aa & ~mispredicted
)
;
// this version assumes can_fold = 1
wire sadr_fold_aa_cf1
= ~untaken_empty_ilock & (
~mispredicted & ~reset
| sadr_aa & ~mispredicted
)
;
// this version assumes can_fold = 0
wire sadr_fold_aa_cf0
= ~untaken_empty_ilock & (
sadr_aa & ~mispredicted
)
;
wire sel_inc_alttag = mispredicted | keep_alt;
wire kill_cti_in_e
=
br_fbr_in_e & ~last_taken
| call_in_e & fold_annul
| kill_jmp_ld
;
// assumes can_fold = 1
wire sel_last_gen_cf1
= ~sadr_fold_aa_cf1 & ~sel_inc_alttag
& ~(stuff_q_cf1 | fetch_ic_cf1)
& ~(kill_cti_in_e)
;
// assumes can_fold = 0
wire sel_last_gen_cf0
= ~sadr_fold_aa_cf0 & ~sel_inc_alttag
& ~(stuff_q_cf0 | fetch_ic_cf0)
& ~(kill_cti_in_e)
;
wire sel_last_gen;
// Expanded macro begin.
// cmux2(sel_last_gen_mux, 1, sel_last_gen, sel_last_gen_cf0, sel_last_gen_cf1, can_fold)
function [1:1] sel_last_gen_mux ;
input [1:1] in0_fn ;
input [1:1] in1_fn ;
input select_fn ;
reg [1:1] out_fn ;
begin
case (select_fn) /* synopsys parallel_case */
1'b0: out_fn = in0_fn ;
1'b1: out_fn = in1_fn ;
default: out_fn = 65'hx;
endcase
sel_last_gen_mux = out_fn ;
end
endfunction
assign sel_last_gen = sel_last_gen_mux( sel_last_gen_cf0, sel_last_gen_cf1, can_fold) ;
// Expanded macro end.
/*
wire sel_last_gen = ~sadr_fold_aa & ~sel_inc_alttag
& ~(stuff_q | fetch_ic)
& ~(kill_cti_in_e)
;
*/
// assumes can_fold = 1
wire sel_ll_gen_cf1
= ~sadr_fold_aa_cf1 & ~sel_inc_alttag
& ~q_state[0] & ~loaded_lastcyc
This page: |
Created: | Thu Aug 19 11:59:48 1999 |
| From: |
../../../sparc_v8/ssparc/iu/Mdecode/rtl/pc_cntl.v
|