/******************************************************************************/
/* */
/* Copyright (c) 1999 Sun Microsystems, Inc. All rights reserved. */
/* */
/* The contents of this file are subject to the current version of the Sun */
/* Community Source License, microSPARCII ("the License"). You may not use */
/* this file except in compliance with the License. You may obtain a copy */
/* of the License by searching for "Sun Community Source License" on the */
/* World Wide Web at http://www.sun.com. See the License for the rights, */
/* obligations, and limitations governing use of the contents of this file. */
/* */
/* Sun Microsystems, Inc. has intellectual property rights relating to the */
/* technology embodied in these files. In particular, and without limitation, */
/* these intellectual property rights may include one or more U.S. patents, */
/* foreign patents, or pending applications. */
/* */
/* Sun, Sun Microsystems, the Sun logo, all Sun-based trademarks and logos, */
/* Solaris, Java and all Java-based trademarks and logos are trademarks or */
/* registered trademarks of Sun Microsystems, Inc. in the United States and */
/* other countries. microSPARC is a trademark or registered trademark of */
/* SPARC International, Inc. All SPARC trademarks are used under license and */
/* are trademarks or registered trademarks of SPARC International, Inc. in */
/* the United States and other countries. Products bearing SPARC trademarks */
/* are based upon an architecture developed by Sun Microsystems, Inc. */
/* */
/******************************************************************************/
/***************************************************************************
****************************************************************************
***
*** Program File: @(#)pc_cntl.v
***
***
****************************************************************************
****************************************************************************/
// @(#)pc_cntl.v 1.154 4/8/94
// pc_cntl.v
/*
Program Counter Control Logic
*/
module Mpc_cntl
(
// OUTPUTS
sel_lta_fpc,
sel_idpc_fpc,
sel_post_reset,
sel_p_fpc,
sel_alt_tag,
sel_i1pfpc_fpc,
sel_i2dpc_fpc,
fetch_ic_even,
fetch_ic_odd,
fetch_TOQ,
fetch_alt,
fetch_SIQ,
ncant_unload,
hold_alt,
fold_annul,
fold_annul2,
fold_annul3,
fold_annul4,
fold_annul5,
fold_annul6,
fold_annul7,
nfold_annul,
mispredicted,
untaken_empty_ilock,
sv_rest_fold_ilock,
sv_rest_recirc,
sel_shift1,
sel_shift2,
sel_shift3,
sel_fold1,
sel_fold2,
sel_even1,
sel_odd1,
hold_q1,
sel_even2,
sel_odd2,
hold_q2,
sel_even3,
sel_odd3,
hold_q3,
hold_q4,
sel_last_gen,
recirc2_default,
sel_inc_ll_gen,
sel_inc_dpc,
sel_inc_alttag,
sel_gpc,
sel_recirc,
sel_recirc_inc,
sel_lgen_iva,
sel_gpc_ic,
sel_recirc_ic,
sel_recirc_inc_ic,
sadr_zero_ic,
force_ifill,
flush_ic_e,
force_dva,
fwd_wpc,
use_tpc,
fwd_tpcm4,
lta_hold,
dbr_cond,
hld_car_mar,
hld_lgens,
hld_backup,
take_icdata,
sel_old_aa,
hld_dir2,
sel_lgen_ica,
stop_fetch,
did_fetch,
// INPUTS
nANNUL,
s,
fcc_taken,
bicc_taken,
d_hop3,
e_opcode_hi,
w_hop3,
iu_fetch_f,
gen_help,
gen_help_op,
nfold_taken,
IU_in_trap,
TRAP,
ER_SDOUT,
trap_cyc1,
trap_cyc2,
fpc_low,
nlta_low,
ndpc_low,
nalttag_low,
iacc_exc_mmumiss_d,
d_nop,
d_trap,
fcc_ilock,
sadr_jmprett,
sadr_tbr,
sadr_zero,
toq_entry_bits,
nq1_entry_hi,
iexc_for_br,
niexc1_hi,
ilock,
valid_decode,
valid_decode_nilock,
hold_noic,
hold_ic,
iu_asi_e_4,
ic_force_ifill_g,
mm_istat_avail,
i_dva_req,
iwait_f,
dwait_w_for_flush,
// extend_tag_miss,
enbl_br_fold,
start_itag_inv,
q3_iae, q3_ptc, q2_iae, q2_ptc, q1_iae, q1_ptc,
hnop_into_ex,
wo_trap_w, wu_trap_w,
// MISC
ss_clock,
hold,
reset,
del_resetm
);
output sel_lta_fpc
;
output sel_idpc_fpc
;
output sel_post_reset
;
output sel_p_fpc
;
output sel_alt_tag
;
output sel_i1pfpc_fpc
;
output sel_i2dpc_fpc
;
output fetch_ic_even
;
output fetch_ic_odd
;
output fetch_TOQ
;
output fetch_alt
;
output fetch_SIQ
;
output ncant_unload
;
output hold_alt
;
output fold_annul
;
output fold_annul2
;
output fold_annul3
;
output fold_annul4
;
output fold_annul5
;
output fold_annul6
;
output fold_annul7
;
output nfold_annul
;
output mispredicted
;
output untaken_empty_ilock
;
output sv_rest_fold_ilock
;
output sv_rest_recirc
;
output sel_shift1
;
output sel_shift2
;
output sel_shift3
;
output sel_fold1
;
output sel_fold2
;
output sel_even1
;
output sel_odd1
;
output hold_q1
;
output sel_even2
;
output sel_odd2
;
output hold_q2
;
output sel_even3
;
output sel_odd3
;
output hold_q3
;
output hold_q4
;
output sel_last_gen
;
// output sel_ll_gen;
// output sel_inc_last_gen;
output recirc2_default
;
output sel_inc_ll_gen
;
output sel_inc_dpc
;
output sel_inc_alttag
;
output sel_gpc
;
output sel_recirc
;
output sel_recirc_inc
;
output sel_lgen_iva
;
output sel_gpc_ic
;
output sel_recirc_ic
;
output sel_recirc_inc_ic
;
output sadr_zero_ic
;
output force_ifill
;
output flush_ic_e
;
output force_dva
;
// output sadr_fold_aa;
output fwd_wpc
;
output use_tpc
;
output fwd_tpcm4
;
output lta_hold
;
output [3:0] dbr_cond
;
output hld_car_mar
;
output hld_lgens
;
output hld_backup
;
output take_icdata
;
output sel_old_aa
;
output hld_dir2
;
output sel_lgen_ica
;
output stop_fetch
;
output did_fetch
;
input nANNUL
;
input s
;
input fcc_taken
;
input bicc_taken
;
input [8:0] d_hop3
;
input [10:2] e_opcode_hi
;
input [8:0] w_hop3
;
input iu_fetch_f
;
input gen_help
;
input gen_help_op
;
input nfold_taken
;
input IU_in_trap
;
input TRAP
;
input ER_SDOUT
;
input trap_cyc1
;
input trap_cyc2
;
input fpc_low
;
input nlta_low
;
input ndpc_low
;
input nalttag_low
;
input iacc_exc_mmumiss_d
;
input d_nop
;
input d_trap
;
input fcc_ilock
;
input sadr_jmprett
;
input sadr_tbr
;
input sadr_zero
;
input [31:22] toq_entry_bits
;
input [31:22] nq1_entry_hi
;
input [10:2] iexc_for_br
;
input [10:2] niexc1_hi
;
input ilock
;
input valid_decode
;
input valid_decode_nilock
;
input hold_noic
;
input hold_ic
;
input iu_asi_e_4
;
input ic_force_ifill_g
;
input mm_istat_avail
;
input i_dva_req
;
input iwait_f
;
input dwait_w_for_flush
;
// input extend_tag_miss;
input enbl_br_fold
;
input start_itag_inv
;
input q3_iae
, q3_ptc
, q2_iae
, q2_ptc
, q1_iae
, q1_ptc
;
input hnop_into_ex
;
input wo_trap_w
;
input wu_trap_w
;
input ss_clock
;
input hold
;
input reset
;
input del_resetm
;
// FORWARD DECLARATIONS
wire [4:0] q_state
;
wire sequential_f
;
wire fold_in_d
;
wire fold_in_e
;
wire last_predict_taken
;
wire fwd_wpc_almost
;
wire trap_before_fold
;
wire keep_alt
;
wire last_force_dva
;
wire last_can_fold
;
wire mispredicted;
wire sel_post_reset;
wire kill_fetch_fill
;
wire [8:0] e_hop3
= e_opcode_hi[10:2];
wire [2:0] d_hop
= d_hop3[8:6];
wire [5:0] d_hop2
= d_hop3[8:3];
wire [2:0] e_hop
= e_hop3[8:6];
wire [5:0] e_hop2
= e_hop3[8:3];
// wire br_in_e = e_hop2==BICC;
// wire fbr_in_e = e_hop2==BFCC;
// wire br_fbr_in_e = br_in_e | fbr_in_e;
// wire call_in_e = e_hop==CALL;
// wire rett_in_e = e_hop3==RETT;
// wire jmp_in_e = (e_hop3==JMP);
wire hld_llc
;
wire part_stuff_q
;
wire hld_car_mar;
wire last_taken
;
// wire last_taken;
wire sv_rest_recirc;
wire kill_jmp_ld
;
wire cant_unload
;
wire untaken_empty_ilock;
wire fetch_alt;
wire force_ifill;
wire force_dva;
wire nkill_jmp_ld
;
wire fld_hlp_misp
;
wire nmispredicted
;
wire [4:0] nq_state
;
wire nlast_taken
;
wire ncant_unload;
wire can_fold
;
wire fold_annul;
wire fold_annul2;
wire fold_annul3;
wire fold_annul4;
wire fold_annul5;
wire fold_annul6;
wire fold_annul7;
wire flush_asi_e
;
wire hold_alt;
wire flushq
;
wire hld_dir2;
/******************** some pipeline stuff *********************/
wire br_in_d
= valid_decode_nilock & (d_hop2==`BICC);
wire fbr_in_d
= valid_decode_nilock & (d_hop2==`BFCC);
wire br_in_dec
= br_in_d | fbr_in_d;
wire br_in_dec_nvd
= d_hop2==`BICC | d_hop2==`BFCC;
wire br_in_d_vd
= valid_decode & (d_hop2==`BICC);
wire fbr_in_d_vd
= valid_decode & (d_hop2==`BFCC);
// REGWIRE br_in_e;
// REG(br_in_e_reg,1,br_in_e,br_in_d_vd,ss_clock,hold)
// REGWIRE fbr_in_e;
// REG(fbr_in_e_reg,1,fbr_in_e,fbr_in_d_vd,ss_clock,hold)
wire br_fbr_in_d
= br_in_d_vd | fbr_in_d_vd;
wire br_fbr_in_e
;
Mflipflop_1 br_fbr_in_e_reg_1(br_fbr_in_e,br_fbr_in_d,ss_clock,hold) ;
wire call_in_d
= valid_decode_nilock & (d_hop==`CALL);
wire call_in_d_nvd
= d_hop==`CALL;
wire call_in_d_vd
= valid_decode & (d_hop==`CALL);
wire call_in_e
;
Mflipflop_1 call_in_e_reg_1(call_in_e,call_in_d_vd,ss_clock,hold) ;
wire jmp_in_d
= d_hop3==`JMP;
// wire njmp_in_e = jmp_in_d & ~hnop_into_ex & ~reset & ~trap_cyc1;
wire njmp_in_e
= jmp_in_d & valid_decode;
wire jmp_in_e
;
Mflipflop_1 jmp_in_e_reg_1(jmp_in_e,njmp_in_e,ss_clock,hold) ;
wire njmp_in_w
= jmp_in_e & ~fold_annul2 & ~trap_cyc1;
wire rett_in_d
= d_hop3==`RETT;
// wire nrett_in_e = rett_in_d & ~hnop_into_ex & ~reset & ~trap_cyc1;
wire nrett_in_e
= rett_in_d & valid_decode;
wire rett_in_e
;
Mflipflop_1 rett_in_e_reg_1(rett_in_e,nrett_in_e,ss_clock,hold) ;
wire nrett_in_w
= rett_in_e & ~fold_annul2 & ~trap_cyc1;
wire njmp_rett_in_w
= nrett_in_w | njmp_in_w;
// REGWIRE jmp_rett_in_w;
// REG(jmp_rett_in_w_reg,1,jmp_rett_in_w,njmp_rett_in_w,ss_clock,hold)
// wire cti_in_e = br_fbr_in_e | call_in_e | jmp_in_w;
/******************** BRANCH FOLDING ********************/
/*
* check if can fold TOQ
*/
wire jmp_in_d_nvd
=
jmp_in_d
| jmp_in_e
;
wire rett_in_d_nvd
=
rett_in_d
| rett_in_e
;
// this term is used only in can_fold. it
// does not include valid_decode_nilock - vdni
// is in the can_fold equation already
wire cti_in_d_nvd
=
br_in_dec_nvd | fold_in_d
| call_in_d_nvd
| jmp_in_d_nvd | rett_in_d_nvd
;
// this term used only for nsequential_f determination - by definition,
// can't be sequential with this on, since target fetch occurs.
wire cti_in_d_nof
=
br_in_dec
| call_in_d
| e_hop3==`JMP
| e_hop3==`RETT
;
// this stuff was moved from the queue for timing reasons
// this is the inst_for_br
wire hold_q1_real
= hold_q1 | hold;
wire [31:22] dum_toq
;
Mflipflop_10 dum_toq_reg_10(dum_toq,nq1_entry_hi,ss_clock,hold_q1_real) ;
wire hld_dir2_real
= hld_dir2 | hold;
wire [31:22] backup_bdir
;
Mflipflop_10 backup_dir_reg_10(backup_bdir,toq_entry_bits,ss_clock, hld_dir2_real) ;
wire [31:22] new_toq_entry_bits
;
// Expanded macro begin.
// cmux2(nteb_mux, 10, new_toq_entry_bits, dum_toq, backup_bdir, cant_unload)
function [10:1] nteb_mux ;
input [10:1] in0_fn ;
input [10:1] in1_fn ;
input select_fn ;
reg [10: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
nteb_mux = out_fn ;
end
endfunction
assign new_toq_entry_bits = nteb_mux( dum_toq, backup_bdir, cant_unload) ;
// Expanded macro end.
wire [4:0] toq_op_op2
=
{new_toq_entry_bits[31:30],new_toq_entry_bits[24:22]};
wire br_in_TOQ
= toq_op_op2==5'b00_010; // op_op2 for BICC
// better check that cti_in_e is correct and isn't too pessimistic
// don't need rett in cti_in_e since that would mean a br/rett combo
// wire looks_seq =
// fold_in_e & cti_in_e // & last_predict_taken
// ;
// fold_in_e & ~last_predict_taken
// enable fold now comes from MMU - enbl_br_fold
// wire enable_fold = 1'b1; // temp - make scan only reg
wire ntaken_cti_in_e
=
nlast_taken
| call_in_d_vd
| ~fold_annul2 & (jmp_in_e | rett_in_e)
;
// REGWIRE taken_cti_in_e;
// REG(taken_cti_in_e_reg,1,taken_cti_in_e,ntaken_cti_in_e,ss_clock,hold)
/*
wire taken_cti_in_e =
last_taken // indicates taken BICC or BFCC in E
| call_in_e
| jmp_in_w
| rett_in_w
;
*/
// the wrspec_in_pipe term is used to prevent folding cuz S
// bit may change on wrpsr and don't want to cause problems
// if ic_sup_only (iexc_for_br[2]) is on. also, cuz
// we are guaranteed SPARCness as long as the following
// 3 instructions are clean with respect to WSpecreg.
// if we fold, then that 4th inst will appear in the
// 3rd inst's slot and cause problems.
wire wrspec_in_d
= d_hop3[7:0] == 6'b101100;
// op=10, top 4 bits of op3
// 1100 for Write state
// register (wrpsr, etc)
wire nwrspec_in_e
= wrspec_in_d & valid_decode;
wire wrspec_in_e
;
Mflipflop_1 wrspec_in_e_reg_1(wrspec_in_e,nwrspec_in_e,ss_clock,hold) ;
wire nwrspec_in_w
= wrspec_in_e & ~fold_annul2;
wire wrspec_in_w
;
Mflipflop_1 wrspec_in_w_reg_1(wrspec_in_w,nwrspec_in_w,ss_clock,hold) ;
wire wrspec_in_pipe
=
wrspec_in_d | wrspec_in_e | wrspec_in_w
;
// wire rett_in_pipe = // need this term cuz we don't want
// d_hop3==RETT // to fold br if S bit is changing
// | e_hop3==RETT // in R cycle of rett in case
// ; // ic_sup_only (iexc_for_br[2]) and
// S bit cause a priv trap.
// | rett_in_w // already in taken_cti_in_e
wire d_help
= d_hop3[8];
// don't allow folding if the TOQ had a fetch problem.
// need to qualify iexc_for_br[2] (ic_sup_only) with
// s bit. if s bit is off and ic_sup_only on, the
// branch cannot folded since it will take a
// priv trap
// some of this stuff was moved from the queue for timing
// reasons. this is iexc_for_br
wire [10:2] dum_q1_iexc
;
Mflipflop_9 dum_q1_iexc_reg_9(dum_q1_iexc,niexc1_hi,ss_clock,hold_q1_real) ;
wire [10:2] backup_biexc
;
Mflipflop_9 backup_biexc_reg_9(backup_biexc,iexc_for_br[10:2], ss_clock,hld_dir2_real) ;
wire [10:2] new_iexc_for_br
;
// Expanded macro begin.
// cmux2(nifb_mux, 9, new_iexc_for_br, dum_q1_iexc, backup_biexc, cant_unload)
function [9:1] nifb_mux ;
input [9:1] in0_fn ;
input [9:1] in1_fn ;
input select_fn ;
reg [9: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
nifb_mux = out_fn ;
end
endfunction
assign new_iexc_for_br = nifb_mux( dum_q1_iexc, backup_biexc, cant_unload) ;
// Expanded macro end.
wire bad_toq_t1
=
new_iexc_for_br[10] | new_iexc_for_br[9]
| new_iexc_for_br[8] | new_iexc_for_br[7]
;
wire bad_toq_t2
=
new_iexc_for_br[6] | new_iexc_for_br[5]
| new_iexc_for_br[4] | new_iexc_for_br[3]
;
wire bad_toq_t3
= new_iexc_for_br[2] & ~s;
wire bad_toq
=
bad_toq_t1 | bad_toq_t2 | bad_toq_t3
;
// determine whether the instruction at TOQ can be folded.
// use some pipelining to reduce the logic where possible.
wire ncf_pterms1
=
~nmispredicted & ~nq_state[0]
& enbl_br_fold
& ~ntaken_cti_in_e
;
wire cf_pterms1
;
Mflipflop_1 cf_pterms1_reg_1(cf_pterms1,ncf_pterms1,ss_clock,hold) ;
wire ncf_pterms2
=
~(ncant_unload & ~can_fold)
& ~trap_cyc1 & ~reset
;
wire cf_pterms2
;
Mflipflop_1 cf_pterms2_reg_1(cf_pterms2,ncf_pterms2,ss_clock,hold) ;
// added last minterm because of a bug found in the
// system. a folded branch followed an instruction that
// was interlocked. the branch/del-slot were stripped
// from the queue and put into the oops register.
// the state of the machine is configured to use the
// oops registers as the next instructions, but because
// the fall thru instruction has a bad inst fetch trap
// associated with it, the sequential_f turned off, which
// turns off can_fold_am. thus, the branch in the oops
// register that was folded disappears and if the branch
// is to be taken, it looks like the branch never occured
// and the fall thru path is executed. this last minterm
// fixes this bug by making sure that if a branch got folded
// into the oops register, it will still be folded from the
// oops register.
wire can_fold_am
=
cf_pterms1 & cf_pterms2
& br_in_TOQ // & ~bad_toq
& ~gen_help_op
& ~cti_in_d_nvd
// & ~TRAP
& ~kill_fetch_fill // we'll see
& valid_decode_nilock
// & ~rett_in_pipe // same term in cti_in_d_nvd
& ~wrspec_in_pipe & (
~q_state[1] & ~q_state[2]
| sequential_f
)
| (~reset & last_can_fold & cant_unload
& ~(trap_cyc1 | trap_cyc2))
;
assign can_fold = ~bad_toq & can_fold_am;
/* wire can_fold =
~reset & ~mispredicted
& br_in_TOQ & ~q_state[0] & ~bad_toq
& ~(cant_unload & ~last_can_fold)
& ~gen_help_op
& ~(cti_in_d) // | d_help)
& enable_fold & ~taken_cti_in_e & ~TRAP
& valid_decode_nilock
& ~trap_cyc2 & ~rett_in_pipe
& ~wrspec_in_pipe & (
~q_state[1] & ~q_state[2]
| sequential_f // | looks_seq
)
// & valid_decode
;
*/
wire sel_old_aa = cant_unload & last_can_fold;
Mflipflop_1 last_cf_reg_1(last_can_fold,can_fold,ss_clock,hold) ;
/*
* branch pipeline
*/
// hold_br must be on with interlock and ~iu_fetch_f
// wire hold_br1 = ~reset & (
// ilock
// | ~iu_fetch_f & ~gen_help
// )
// | hold
// ;
// see nmult_fold_d for changes to hold_br1
wire hold_br1
= ~reset & ~fold_in_e & (
ilock
| gen_help_op & ~fold_in_d & valid_decode_nilock
)
| ~reset & ~fold_in_d & ilock // see note
| hold
;
// note - this term keeps fold_in_d from turning on
// if can_fold is on, but interlock is on, too.
// can_fold uses valid_decode_nilock, instead of
// valid_decode.
wire [3:0] toq_cond
= new_toq_entry_bits[28:25];
wire [3:0] dbr_cond;
Mflipflop_4 dbr_cond_reg_4(dbr_cond,toq_cond,ss_clock,hold_br1) ;
wire toq_annul
= new_toq_entry_bits[29];
wire dbr_annul
;
Mflipflop_1 dbr_annul_reg_1(dbr_annul,toq_annul,ss_clock,hold_br1) ;
Mflipflop_1 f_in_d_reg_1(fold_in_d,can_fold,ss_clock,hold_br1) ;
// wire hold_br2 = ~reset & (ilock | hold);
// wire hold_br2 = hold;
/*
* not needed anymore - keep in case i need to bring em back
REGWIRE [3:0] ebr_cond;
REG(ebr_cond_reg,4,ebr_cond,dbr_cond,ss_clock,hold)
REGWIRE ebr_annul;
REG(ebr_annul_reg,1,ebr_annul,dbr_annul,ss_clock,hold)
*/
wire nfold_in_e
= fold_in_d & ~ilock & ~IU_in_trap;
Mflipflop_1 f_in_e_reg_1(fold_in_e,nfold_in_e,ss_clock,hold) ;
/*
* branch prediction stuff
*/
// wire prediction = 1'b1;
// wire predict_taken = prediction & fold_in_d;
wire predict_taken
= fold_in_d; // always predict taken
/*
* try speedup by doing fold_taken, mispredicted and fold_annul
* determination in D of folded br instead of E.
REG(lptaken_reg,1,last_predict_taken,predict_taken,ss_clock,hold)
wire fold_taken;
Miccev_fold iccev_fold (fold_taken, ebr_cond, ccm);
wire mispredicted = fold_in_e & (fold_taken ^ last_predict_taken);
*/
/*
* don't need to pipeline this - we'll see
REGWIRE fold_taken;
REG(fold_taken_reg,1,fold_taken,nfold_taken,ss_clock,hold_br1)
*/
assign nmispredicted =
fold_in_d
& ~IU_in_trap
& (nfold_taken ^ predict_taken);
Mflipflop_1 misp_reg_1(mispredicted,nmispredicted,ss_clock,hold_br1) ;
wire nmult_fold_d
= ~reset & ( // based on hold_br1
ilock
| gen_help & ~fold_in_d
)
;
wire lta_hold = ~reset & (
ilock
| gen_help & ~fold_in_d
)
;
// used to detect if a folded bicc is held up in D (typically
// due to the inst in D is interlocked).
wire multiple_fold_d
;
Mflipflop_1 mult_fold_d_reg_1(multiple_fold_d,nmult_fold_d,ss_clock,hold) ;
wire first_fold_d_predict
=
predict_taken & ~multiple_fold_d;
/*
* Check annul for folded branch - annul E into W
*/
/*
* try faster fold annul by doing it in D, not in E
wire e_condbr_always = ebr_cond==BR_ALWAYS;
wire fold_ba_annul = e_condbr_always & fold_in_e & ebr_annul;
wire fold_bicc_annul = fold_in_e & ebr_annul & ebr_annul & ~fold_taken;
wire fold_annul = fold_ba_annul | fold_bicc_annul;
*/
wire d_condbr_always
= dbr_cond==`BR_ALWAYS;
wire nfold_ba_annul
= d_condbr_always & fold_in_d & dbr_annul;
wire nfold_bicc_annul
= fold_in_d & dbr_annul & ~nfold_taken;
// 9-19-96 duplicate nfold_annul signal to ease the loading problem here
wire nfold_annul = ~reset & ~IU_in_trap &
(nfold_ba_annul | nfold_bicc_annul);
wire nfold_annul_1
= ~reset & ~IU_in_trap &
(nfold_ba_annul | nfold_bicc_annul);
wire nfold_annul_2
= ~reset & ~IU_in_trap &
(nfold_ba_annul | nfold_bicc_annul);
wire nfold_annul_3
= ~reset & ~IU_in_trap &
(nfold_ba_annul | nfold_bicc_annul);
// 9-19-96: duplicate fold_annul flops to individually feed each decode subblock
Mflipflop_1 fold_annul_reg_1( fold_annul, nfold_annul, ss_clock, hold );
Mflipflop_1 fold_annul_reg_2( fold_annul2, nfold_annul_1, ss_clock, hold );
Mflipflop_1 fold_annul_reg_3( fold_annul3, nfold_annul_1, ss_clock, hold );
Mflipflop_1 fold_annul_reg_4( fold_annul4, nfold_annul_2, ss_clock, hold );
Mflipflop_1 fold_annul_reg_5( fold_annul5, nfold_annul_2, ss_clock, hold );
Mflipflop_1 fold_annul_reg_6( fold_annul6, nfold_annul_3, ss_clock, hold );
Mflipflop_1 fold_annul_reg_7( fold_annul7, nfold_annul_3, ss_clock, hold );
// REG(fold_annul_reg,1,fold_annul,nfold_annul,ss_clock,hold_br1)
/********************* FPC SELECTS ***********************/
/*
* generate selects for FPC
*/
// note there is something wrong with fcc_taken - it turns on
// when there is a sethi in D or bicc in D.
assign nlast_taken = ~nfold_annul & (
fcc_taken & fbr_in_d_vd
| bicc_taken & br_in_d_vd
);
Mflipflop_1 last_taken_reg_1(last_taken,nlast_taken,ss_clock,hold) ;
/*
REGWIRE last_fbtaken;
REG(last_fbtaken_reg,1,last_fbtaken,fcc_taken,ss_clock,hold)
REGWIRE last_brtaken;
REG(last_brtaken_reg,1,last_brtaken,bicc_taken,ss_clock,hold)
assign last_taken = ~fold_annul & (
last_fbtaken & fbr_in_e
| last_brtaken & br_in_e
);
*/
// sel_post_reset - this is to hold the FPC for the first fetch
// since DPC is already 0 after the reset. without this select,
// the 1st DPC would be 4. hld_dpc may be a long path, so rethink
// how to do this.
wire nsel_post_reset
= reset & del_resetm;
Mflipflop_1 sel_pr_reg_1(sel_post_reset,nsel_post_reset,ss_clock,hold) ;
wire last_null_fetch
;
Mflipflop_1 last_null_fetch_reg_1(last_null_fetch,~iu_fetch_f,ss_clock,hold) ;
/*
* cant_unload is too slow, even with all registered operands
REGWIRE p_reset1;
REG(p_reset1_reg,1,p_reset1,reset,ss_clock,hold)
REGWIRE p_untaken_empty_ilock;
REG(p_uteil_reg,1,p_untaken_empty_ilock,untaken_empty_ilock,
ss_clock,hold)
assign cant_unload = last_null_fetch & ~p_reset1 & ~ANNUL
& ~p_untaken_empty_ilock & ~fetch_alt;
*/
assign ncant_unload =
~iu_fetch_f & ~reset
& ~nANNUL & ~untaken_empty_ilock
& ~(fld_hlp_misp | nmispredicted)
;
Mflipflop_1 cant_unload_reg_1(cant_unload,ncant_unload,ss_clock,hold) ;
assign hld_dir2 = cant_unload;
// hold | cant_unload
// | (~untaken_empty_ilock & p_untaken_empty_ilock)
// ;
// ~last_can_fold & can_fold - used to disable sel_p_fpc if prev cycle
// no fetch was done and can_fold was off (because queue empty) *and*
// an inst was loaded to Q which fulfills can_fold criteria in
// *next* cycle. need to put out sel_i2dpc_fpc instead of sel_p_fpc,
wire nselpfpc_t1
=
~iu_fetch_f & ~njmp_rett_in_w
& ~trap_cyc1;
wire nselpfpc_t2
=
~(nmispredicted & gen_help)
& ~(nfold_annul & ~gen_help)
;
wire selpfpc_t1
, selpfpc_t2
;
Mflipflop_1 selpfpc_t1_reg_1(selpfpc_t1,nselpfpc_t1,ss_clock,hold) ;
Mflipflop_1 selpfpc_t2_reg_1(selpfpc_t2,nselpfpc_t2,ss_clock,hold) ;
wire sel_p_fpc =
selpfpc_t1 & selpfpc_t2 & ~sel_post_reset
& ~(~last_can_fold & can_fold)
& ~fold_in_d
;
// this version assumes can_fold = 1
wire sel_p_fpc_cf1
=
selpfpc_t1 & selpfpc_t2 & ~sel_post_reset
& last_can_fold
& ~fold_in_d
;
// this version assumes can_fold = 0
wire sel_p_fpc_cf0
=
selpfpc_t1 & selpfpc_t2 & ~sel_post_reset
& ~fold_in_d
;
/*
* try to do this faster
wire sel_p_fpc = last_null_fetch & ~sel_post_reset & ~jmp_rett_in_w
& ~trap_cyc2 & ~(mispredicted & d_help)
& ~(~last_can_fold & can_fold)
& ~fold_in_d
& ~(fold_annul & ~d_help)
;
*/
wire nltafpc_t1
=
njmp_rett_in_w
| (call_in_d_vd & ~nfold_annul)
;
wire nltafpc_t2
=
trap_cyc1 & ~ER_SDOUT
| (br_fbr_in_d & nlast_taken)
;
wire ltafpc_t1
, ltafpc_t2
;
Mflipflop_1 ltafpc_t1_reg_1(ltafpc_t1,nltafpc_t1,ss_clock,hold) ;
Mflipflop_1 ltafpc_t2_reg_1(ltafpc_t2,nltafpc_t2,ss_clock,hold) ;
wire sel_lta_fpc = ~sel_post_reset &
(ltafpc_t1 | ltafpc_t2 | predict_taken)
;
/*
* try to do this faster
wire sel_lta_fpc = ~sel_post_reset &
((br_fbr_in_e & last_taken)
| call_in_e & ~fold_annul
| jmp_rett_in_w
| trap_cyc2 | predict_taken);
*/
wire sel_alt_tag = mispredicted &
~(last_null_fetch & ~fold_annul2 & ~d_help);
wire sel_i1pfpc_fpc =
~last_can_fold & can_fold
& last_null_fetch & ~sel_p_fpc;
// this version assumes can_fold = 1. there is no
// mirror that assumes can_fold = 0 since it will
// always be 0.
wire sel_i1pfpc_fpc_cf1
=
~last_can_fold
& last_null_fetch & ~sel_p_fpc_cf1;
wire sel_i2dpc_fpc = can_fold & ~sel_p_fpc & ~sel_i1pfpc_fpc;
// this version assumes can_fold = 1. again, no
// version with cf=0 is required
wire sel_i2dpc_fpc_cf1
= ~sel_p_fpc_cf1 & ~sel_i1pfpc_fpc_cf1;
wire sel_idpc_fpc = ~sel_lta_fpc & ~sel_post_reset
& ~sel_p_fpc & ~sel_alt_tag & ~sel_i2dpc_fpc
& ~sel_i1pfpc_fpc;
// this version assumes can_fold = 1
wire sel_idpc_fpc_cf1
= ~sel_lta_fpc & ~sel_post_reset
& ~sel_p_fpc_cf1 & ~sel_alt_tag & ~sel_i2dpc_fpc_cf1
& ~sel_i1pfpc_fpc_cf1;
// this version assumes can_fold = 0
wire sel_idpc_fpc_cf0
= ~sel_lta_fpc & ~sel_post_reset
& ~sel_p_fpc_cf0 & ~sel_alt_tag
;
// faster way of determining if the low bit of FPC is 1 or 0.
// if in the DP's, too many boundary crossings. i'm
// hoping that this is faster.
wire lta_hold_real
= lta_hold | hold;
wire lta_low
;
Mflipflop_1 lta_low_reg_1(lta_low,nlta_low,ss_clock,lta_hold_real) ;
wire dpc_low
;
Mflipflop_1 dpc_low_reg_1(dpc_low,ndpc_low,ss_clock,hold) ;
wire pfpc_low
;
Mflipflop_1 pfpc_low_reg_1(pfpc_low,fpc_low,ss_clock,hold) ;
This page: |
Created: | Thu Aug 19 11:59:46 1999 |
| From: |
../../../sparc_v8/ssparc/iu/Mdecode/rtl/pc_cntl.v
|