/******************************************************************************/
/* */
/* 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. */
/* */
/******************************************************************************/
// @(#)fhold_ctl.v 1.22 2/20/93
//
// **************************************************************
// High-level verilog model of FHOLD control including FPC
// dependency checking logic.
//
// This module decodes FPops, checks for dependencies between ldf's,
// stf's, and FPop's, and generates FHOLD and FCCV.
//
// It also generates load/store control signals and contains the
// pipeline registers for the destination register field rd (5-bits),
// and the load/store control signals (4-bits).
//
// **************************************************************
module fhold_ctl
(ss_clock, ss_reset, ext_flush, ext_hold, ext_valid_decode,
fold_annul_e, exemode, qne_fhold, fq_full_next, fq_full,
fcmp_q0, fcmp_q1q2, funimp_in_q, writeback_q0, wbq0_fhold,
fq_qne, ir_d, ir_rd_e,
fq_rd_dbl, fq_rd_used, fq_rs1_dbl, fq_rs1_used,
fq_ir_0, fq_ir_1, fq_ir_2,
fpop_e, rs1_dbl_e, rs1_used_e, rd_dbl_e, unimpl_fpop_e,
fstore_d, fstore_w, finst_nostore_d, mul_fpop_d,
stdfq_e, stdfq_w, stdfq_r_noexc, ext_fhold, ext_fccv,
fhold_d1, fhold_fqfull_d1, fload_w, ldf_w, op3_w, fload_r,
ir_rd_w, ss_scan_mode);
input ss_clock
, // FPU clock
ss_reset
, // FPU reset
ext_flush
, // FPU flush (IU in trap)
ext_hold
, // IU pipeline held (frozen)
ext_valid_decode
, // decode contains a valid instruction
fold_annul_e
, // inst in E is annuled
exemode
, // FPC is in execution state
qne_fhold
, // special qne signal for fhold logic
fq_full_next
, // fq has only 1 entry available
fq_full
, // fq is full
fcmp_q0
, // fcmp in q0
fcmp_q1q2
, // fcmp in q1 or q2
funimp_in_q
, // unimplemented FPop in any fq
writeback_q0
, // result writeback signal
wbq0_fhold
; // writeback_q0 for fhold logic
input [ 2:0] fq_qne
; // FQ not empty status bits
input [31:0] ir_d
; // output of D-stage instruction register
input [ 4:0] ir_rd_e
; // E-stage instr. reg. field outputs
input [ 2:0] fq_rd_dbl
, // size of fq result
fq_rd_used
, // indicates whether or not rd is used
fq_rs1_dbl
, // size of rs1,rs2
fq_rs1_used
; // indicates whether rs1 is used
input [15:0] fq_ir_0
, // output of FQ instruction registers
fq_ir_1
,
fq_ir_2
;
input ss_scan_mode
;
output fpop_e
, // FPop in E-stage
rs1_dbl_e
, // FPop rs1 field size
rs1_used_e
, // FPop rs1 field used
rd_dbl_e
, // FPop rd field size
unimpl_fpop_e
, // unimplemented FPop in E-stage
fstore_d
, // valid FP STORE in D-stage
fstore_w
, // valid FP STORE in W-stage
finst_nostore_d
, // valid non-store FP instr in decode
mul_fpop_d
, // (FMULs, FMULd, or FsMULd) in decode
stdfq_e
, // stdfq in E-stage
stdfq_w
, // stdfq in W-stage
stdfq_r_noexc
, // stdfq in R-stage, no data access exception
ext_fhold
, // FHOLD signal causes IU to interlock
ext_fccv
, // FP condition codes valid
fhold_d1
, // delayed ext_fhold used by perf counter
fhold_fqfull_d1
; // delayed fq_full used by perf counter
output fload_w
;
output ldf_w
; // ldf in W-stage; registered for speed
output [1:0] op3_w
;
output fload_r
;
output [4:0] ir_rd_w
; // W-stage destination register field
wire no_holds
= ~ext_hold;
wire reset_l
= ~ss_reset ;
// resetflush = (~ext_hold & ext_flush) | ss_reset;
// resetflush_l = (ext_hold | ~ext_flush) & ~ss_reset;
ME_O2A1_D iu_hold_gate_1 (.a(ext_hold), .b(~ext_flush), .c(reset_l),
.z(resetflush_l
) );
// clear_e = (~ext_hold & (ext_flush | fold_annul_e) ) | ss_reset;
// clear_e_l = (ext_hold | ~(ext_flush | fold_annul_e) ) & ~ss_reset;
ME_O2A1_D iu_hold_gate_2 (.a(ext_hold), .b( ~(ext_flush | fold_annul_e) ),
.c(reset_l), .z(clear_e_l
) );
// *******************************************************
wire [1:0] ir_op_d
; // D-stage instr. reg. fields
wire [4:0] ir_rd_d
, ir_rs1_d
, ir_rs2_d
;
wire [5:0] ir_op3_d
;
wire [8:0] ir_opf_d
;
assign {ir_op_d, ir_rd_d, ir_op3_d, ir_rs1_d, ir_opf_d, ir_rs2_d} = ir_d[31:0];
// *******************************************************
wire [7:0] ls_e
, ls_w
; // control signals
wire [4:0] ls_r
;
wire [1:0] op3_e
= ls_e[1:0];
wire [1:0] op3_w = ls_w[1:0];
wire [1:0] op3_r
= ls_r[1:0];
// *******************************************************
wire [4:0] fq_rd_q0
, fq_rs1_q0
, fq_rs2_q0
; // FQ instr. reg. fields
wire [4:0] fq_rd_q1
, fq_rs1_q1
, fq_rs2_q1
;
wire [4:0] fq_rd_q2
, fq_rs1_q2
, fq_rs2_q2
;
wire fq_op3_0_q0
, fq_op3_0_q1
, fq_op3_0_q2
;
assign {fq_rd_q0, fq_op3_0_q0, fq_rs1_q0, fq_rs2_q0} = fq_ir_0[15:0] ;
assign {fq_rd_q1, fq_op3_0_q1, fq_rs1_q1, fq_rs2_q1} = fq_ir_1[15:0] ;
assign {fq_rd_q2, fq_op3_0_q2, fq_rs1_q2, fq_rs2_q2} = fq_ir_2[15:0] ;
// *******************************************************
// decode controls
wire rs1_dbl_d
, rs1_used_d
; // rs2 is always used
wire rd_dbl_d
, rd_used_d
;
wire unimpl_fpop_d_nval
;
wire mul_fpop_d ;
// FP instruction decode module
fpinst_decode fpdec1 (ir_op_d, ir_op3_d, dir_fop_nval
, dir_ldreg_nval
,
dir_streg_nval
, dir_ldstreg_nval
,
dir_fload_nval
, dir_fstore_nval
, dir_ldstrfsr_nval
,
dir_finst_nostore_nval
);
// non-store FP instruction is in decode
wire finst_nostore_d = dir_finst_nostore_nval & ext_valid_decode ;
// FP ldf/lddf in decode
wire dir_ldreg
= dir_ldreg_nval & ext_valid_decode ;
// FP load in decode
wire dir_fload
= dir_fload_nval & ext_valid_decode ;
// FP store in decode
wire fstore_d = dir_fstore_nval & ext_valid_decode ;
// Basic Floating pt. opcode mask (includes FCMP) in decode
wire fpop_d
= dir_fop_nval & ext_valid_decode ;
// FCMP in decode
wire fcmp_d
= dir_fop_nval & ir_op3_d[0] ;
// FP instruction (except bfcc) in D-stage
wire finst_d
= finst_nostore_d | fstore_d ;
// FP instruction (except bfcc) in E-stage
ME_FDS2LP finst_e_ff(.q(finst_e_nval
), .cp(ss_clock), .cr(resetflush_l),
.d(finst_d), .ld(no_holds) );
wire finst_e
= finst_e_nval & ~fold_annul_e ;
// FPop in E-stage
ME_FDS2LP fop_e_ff(.q(fpop_e_nval
), .cp(ss_clock), .cr(resetflush_l),
.d(fpop_d), .ld(no_holds) );
assign fpop_e = fpop_e_nval & ~fold_annul_e ;
// FCMP in decode
wire fcmp_e
= fpop_e & op3_e[0] ;
wire rd_reg_ld
= no_holds;
wire [4:0] ir_rd_w;
// *******************************************************
// Pipeline to hold rd field (5-bits) for W stage
//
ME_FDS2LP5 rd_wreg (.Q(ir_rd_w), .CP(ss_clock), .CR(reset_l), .D(ir_rd_e),
.LD(rd_reg_ld) );
// *******************************************************
// decode the load/store control signals
wire ldf_d
= dir_ldreg & ~ir_op3_d[1] & ~ir_op3_d[0]; // ldf in D
wire ldfsr_d
= dir_fload & ~ir_op3_d[1] & ir_op3_d[0]; // ldfsr in D
wire stfsr_d
= fstore_d & ~ir_op3_d[1] & ir_op3_d[0]; // stfsr in D
wire stdfq_d
= fstore_d & ir_op3_d[1] & ~ir_op3_d[0]; // stdfq in D
wire dir_dbldst
= ir_op3_d[1] & ir_op3_d[0]; // ld/st double
wire [7:0] ls_d
= { ldf_d, ldfsr_d, dir_fload, stdfq_d, fstore_d,
dir_dbldst, ir_op3_d[1:0] };
wire ls_reg_ld
= no_holds;
// *******************************************************
// Pipeline to hold dir_ldreg control signal.
//
ME_FDS2LP ldreg_e_ff (.q(ldreg_e_nval
), .cp(ss_clock), .cr(resetflush_l),
.d(dir_ldreg), .ld(ls_reg_ld) );
wire ldreg_e
= ldreg_e_nval & ~fold_annul_e ;
ME_FDS2LP ldreg_w_ff (.q(ldreg_w
), .cp(ss_clock), .cr(resetflush_l),
.d(ldreg_e), .ld(ls_reg_ld) );
// *******************************************************
// Pipeline to hold decoded load/store control signals (8-bits)
//
ME_FDS2LP8 ls_ereg (.Q(ls_e), .CP(ss_clock), .CR(resetflush_l), .D(ls_d),
.LD(ls_reg_ld) );
ME_FDS2LP8 ls_wreg (.Q(ls_w), .CP(ss_clock), .CR(clear_e_l), .D(ls_e),
.LD(ls_reg_ld) );
wire [4:0] ls_wuse
= {ls_w[7], ls_w[5:4], ls_w[1:0] } ;
ME_FDS2LP5 ls_rreg (.Q(ls_r), .CP(ss_clock), .CR(resetflush_l), .D(ls_wuse),
.LD(ls_reg_ld) );
// *******************************************************
wire ldst_dbl_e
= ls_e[2] & ~fold_annul_e ; // load/store double
wire ldst_dbl_w
= ls_w[2];
wire fstore_e
= ls_e[3] & ~fold_annul_e ; // fstore (stf,stfsr,stdfq,stdf)
wire fstore_w = ls_w[3];
wire stfsr_e
= fstore_e & ~op3_e[1] & op3_e[0]; // stfsr in E
wire stdfq_e = ls_e[4] & ~fold_annul_e ; // stdfq in E
wire stdfq_w = ls_w[4];
wire stdfq_r
= ls_r[2];
// clear when ext_hold==0
ME_FD1R held_stdfq_ff (.q(stdfq_r_held
), .cp(ss_clock), .cr(ext_hold),
.d(stdfq_r) );
// stdfq_r, valid for 1 cycle maximum
wire stdfq_r_noexc = stdfq_r & ~stdfq_r_held ;
wire fload_e
= ls_e[5] & ~fold_annul_e ; // fload (ldf,ldfsr,lddf)
wire fload_w = ls_w[5];
wire fload_r = ls_r[3];
wire ldfsr_e
= ls_e[6] & ~fold_annul_e ; // ldfsr in E
wire ldfsr_w
= ls_w[6];
wire ldf_e
= ls_e[7] & ~fold_annul_e ;
wire ldf_w = ls_w[7]; // ldf (module outputs)
// *******************************************************
// Determine the size of each register field for decode and
// QI, and whether or not it is used
rfield_size di_rfdsize ( ir_opf_d[7:0], rs1_dbl_d, rs1_used_d,
rd_dbl_d, rd_used_d );
ME_FDS2LP rs1dbl_e_ff(.q(rs1_dbl_e), .cp(ss_clock), .cr(resetflush_l),
.ld(no_holds), .d(rs1_dbl_d) );
ME_FDS2LP rs1used_e_ff(.q(rs1_used_e), .cp(ss_clock), .cr(resetflush_l),
.ld(no_holds), .d(rs1_used_d) );
ME_FDS2LP rddbl_e_ff(.q(rd_dbl_e), .cp(ss_clock), .cr(resetflush_l),
.ld(no_holds), .d(rd_dbl_d) );
ME_FDS2LP rdused_e_ff(.q(rd_used_e
), .cp(ss_clock), .cr(resetflush_l),
.ld(no_holds), .d(rd_used_d) );
// Determine whether or not an FPop is implemented.
fpop_decd unimp_decd ( ir_op3_d[0], ir_opf_d, unimpl_fpop_d_nval,
mul_fpop_d_nval
);
assign mul_fpop_d = mul_fpop_d_nval & ext_valid_decode ;
wire unimpl_fpop_d
= fpop_d & unimpl_fpop_d_nval ;
ME_FDS2LP unimp_e_ff(.q(unimpl_fpop_e_nval
), .cp(ss_clock), .cr(resetflush_l),
.ld(no_holds), .d(unimpl_fpop_d ));
wire unimpl_fpop_e = unimpl_fpop_e_nval & ~fold_annul_e ;
// *******************************************************
// load/store/fq register dependency check logic
// For SPARC FPops, rs2 is always used, and is always the
// same size as rs1.
// **********************************
// d(rd) -> q0(rd), q1(rd), q2(rd)
chkdep_rd_all chk_d_all (ir_rd_d[4:1], fq_rd_q0[4:1], fq_rd_q1[4:1],
fq_rd_q2[4:1], match4_d_0
, match4_d_1
, match4_d_2
) ;
wire match_d_0
= match4_d_0 & ((ir_rd_d[0] ~^ fq_rd_q0[0]) | ir_op3_d[1] |
fq_rd_dbl[0] );
wire match_d_1
= match4_d_1 & ((ir_rd_d[0] ~^ fq_rd_q1[0]) | ir_op3_d[1] |
fq_rd_dbl[1] );
wire match_d_2
= match4_d_2 & ((ir_rd_d[0] ~^ fq_rd_q2[0]) | ir_op3_d[1] |
fq_rd_dbl[2] );
// **********************************
// d(rd) -> e(rd)
ME_COMP4 cmp_d_rd_e (ir_rd_d[4:1], ir_rd_e[4:1], match4_d_rd_e
) ;
wire match_d_rd_e
= match4_d_rd_e & ((ir_rd_d[0] ~^ ir_rd_e[0]) | ir_op3_d[1] |
rd_dbl_e );
wire st_dep_d_fq
= fstore_d &
((match_d_0 & fq_qne[0] & fq_rd_used[0] & ~wbq0_fhold) |
(match_d_1 & fq_qne[1] & fq_rd_used[1]) |
(match_d_2 & fq_qne[2] & fq_rd_used[2]) |
(match_d_rd_e & fpop_e & rd_used_e)) ;
// **********************************
// e(rd) -> q0(rd), q0(rs1), q0(rs2)
chkdep_rd_all chk_e_q0 (ir_rd_e[4:1], fq_rd_q0[4:1], fq_rs1_q0[4:1],
fq_rs2_q0[4:1], match4_e_rd_0
, match4_e_rs1_0
,
match4_e_rs2_0
) ;
wire match_e_rd_0
= match4_e_rd_0 & ((ir_rd_e[0] ~^ fq_rd_q0[0]) |
op3_e[1] | fq_rd_dbl[0] );
wire match_e_rs1_0
= match4_e_rs1_0 & ((ir_rd_e[0] ~^ fq_rs1_q0[0]) |
op3_e[1] | fq_rs1_dbl[0] );
wire match_e_rs2_0
= match4_e_rs2_0 & ((ir_rd_e[0] ~^ fq_rs2_q0[0]) |
op3_e[1] | fq_rs1_dbl[0] );
wire ld_dep_e_q0
= ldreg_e & fq_qne[0] & ~wbq0_fhold &
((match_e_rd_0 & fq_rd_used[0]) |
(match_e_rs1_0 & fq_rs1_used[0]) |
match_e_rs2_0) ;
// **********************************
// e(rd) -> q1(rd), q1(rs1), q1(rs2)
chkdep_rd_all chk_e_q1 (ir_rd_e[4:1], fq_rd_q1[4:1], fq_rs1_q1[4:1],
fq_rs2_q1[4:1], match4_e_rd_1
, match4_e_rs1_1
,
match4_e_rs2_1
) ;
wire match_e_rd_1
= match4_e_rd_1 & ((ir_rd_e[0] ~^ fq_rd_q1[0]) |
op3_e[1] | fq_rd_dbl[1] );
wire match_e_rs1_1
= match4_e_rs1_1 & ((ir_rd_e[0] ~^ fq_rs1_q1[0]) |
op3_e[1] | fq_rs1_dbl[1] );
wire match_e_rs2_1
= match4_e_rs2_1 & ((ir_rd_e[0] ~^ fq_rs2_q1[0]) |
op3_e[1] | fq_rs1_dbl[1] );
wire ld_dep_e_q1
= ldreg_e & fq_qne[1] & ((match_e_rd_1 & fq_rd_used[1]) |
(match_e_rs1_1 & fq_rs1_used[1]) |
match_e_rs2_1) ;
// **********************************
// e(rd) -> q2(rd), q2(rs1), q2(rs2)
chkdep_rd_all chk_e_q2 (ir_rd_e[4:1], fq_rd_q2[4:1], fq_rs1_q2[4:1],
fq_rs2_q2[4:1], match4_e_rd_2
, match4_e_rs1_2
,
match4_e_rs2_2
) ;
wire match_e_rd_2
= match4_e_rd_2 & ((ir_rd_e[0] ~^ fq_rd_q2[0]) |
op3_e[1] | fq_rd_dbl[2] );
wire match_e_rs1_2
= match4_e_rs1_2 & ((ir_rd_e[0] ~^ fq_rs1_q2[0]) |
op3_e[1] | fq_rs1_dbl[2] );
wire match_e_rs2_2
= match4_e_rs2_2 & ((ir_rd_e[0] ~^ fq_rs2_q2[0]) |
op3_e[1] | fq_rs1_dbl[2] );
wire ld_dep_e_q2
= ldreg_e & fq_qne[2] & ((match_e_rd_2 & fq_rd_used[2]) |
(match_e_rs1_2 & fq_rs1_used[2]) |
match_e_rs2_2) ;
wire ld_dep_e_fq
= ld_dep_e_q0 | ld_dep_e_q1 | ld_dep_e_q2 ;
wire st_dep_e_fq
= fstore_e &
((match_e_rd_0 & fq_qne[0] & fq_rd_used[0] & ~wbq0_fhold) |
(match_e_rd_1 & fq_qne[1] & fq_rd_used[1]) |
(match_e_rd_2 & fq_qne[2] & fq_rd_used[2])) ;
// **********************************
// w(rd) -> q0(rd), q0(rs1), q0(rs2)
chkdep_rd_all chk_w_q0 (ir_rd_w[4:1], fq_rd_q0[4:1], fq_rs1_q0[4:1],
fq_rs2_q0[4:1], match4_w_rd_0
, match4_w_rs1_0
,
match4_w_rs2_0
) ;
wire match_w_rd_0
= match4_w_rd_0 & ((ir_rd_w[0] ~^ fq_rd_q0[0]) |
op3_w[1] | fq_rd_dbl[0] );
wire match_w_rs1_0
= match4_w_rs1_0 & ((ir_rd_w[0] ~^ fq_rs1_q0[0]) |
op3_w[1] | fq_rs1_dbl[0] );
wire match_w_rs2_0
= match4_w_rs2_0 & ((ir_rd_w[0] ~^ fq_rs2_q0[0]) |
op3_w[1] | fq_rs1_dbl[0] );
wire ld_dep_w_q0
= ldreg_w & fq_qne[0] & ~wbq0_fhold &
((match_w_rd_0 & fq_rd_used[0]) |
(match_w_rs1_0 & fq_rs1_used[0]) |
match_w_rs2_0) ;
// **********************************
// w(rd) -> q1(rd), q1(rs1), q1(rs2)
chkdep_rd_all chk_w_q1 (ir_rd_w[4:1], fq_rd_q1[4:1], fq_rs1_q1[4:1],
fq_rs2_q1[4:1], match4_w_rd_1
, match4_w_rs1_1
,
match4_w_rs2_1
) ;
wire match_w_rd_1
= match4_w_rd_1 & ((ir_rd_w[0] ~^ fq_rd_q1[0]) |
op3_w[1] | fq_rd_dbl[1] );
wire match_w_rs1_1
= match4_w_rs1_1 & ((ir_rd_w[0] ~^ fq_rs1_q1[0]) |
op3_w[1] | fq_rs1_dbl[1] );
wire match_w_rs2_1
= match4_w_rs2_1 & ((ir_rd_w[0] ~^ fq_rs2_q1[0]) |
op3_w[1] | fq_rs1_dbl[1] );
wire ld_dep_w_q1
= ldreg_w & fq_qne[1] & ((match_w_rd_1 & fq_rd_used[1]) |
(match_w_rs1_1 & fq_rs1_used[1]) |
match_w_rs2_1) ;
// **********************************
// w(rd) -> q2(rd), q2(rs1), q2(rs2)
chkdep_rd_all chk_w_q2 (ir_rd_w[4:1], fq_rd_q2[4:1], fq_rs1_q2[4:1],
fq_rs2_q2[4:1], match4_w_rd_2
, match4_w_rs1_2
,
match4_w_rs2_2
) ;
wire match_w_rd_2
= match4_w_rd_2 & ((ir_rd_w[0] ~^ fq_rd_q2[0]) |
op3_w[1] | fq_rd_dbl[2] );
wire match_w_rs1_2
= match4_w_rs1_2 & ((ir_rd_w[0] ~^ fq_rs1_q2[0]) |
op3_w[1] | fq_rs1_dbl[2] );
wire match_w_rs2_2
= match4_w_rs2_2 & ((ir_rd_w[0] ~^ fq_rs2_q2[0]) |
op3_w[1] | fq_rs1_dbl[2] );
wire ld_dep_w_q2
= ldreg_w & fq_qne[2] & ((match_w_rd_2 & fq_rd_used[2]) |
(match_w_rs1_2 & fq_rs1_used[2]) |
match_w_rs2_2) ;
wire ld_dep_w_fq
= ld_dep_w_q0 | ld_dep_w_q1 | ld_dep_w_q2 ;
// ldst_depend = (no_holds & ldst_depend_1) | ldst_depend_2;
wire ldst_depend_1
= st_dep_d_fq | ld_dep_e_fq ;
wire ldst_depend_2
= st_dep_e_fq | ld_dep_w_fq ;
// *************************************************************
// FCCV logic
// fcmp in any fq
wire fcmp_in_q
= (fcmp_q0 & ~wbq0_fhold) | fcmp_q1q2 ;
// ext_fccv will be deasserted as soon as fcmp enters QI (E-cycle)
// The ldfsr term is not strictly required by SPARC (fcc may be
// undefined for 3 cycles after a ldfsr)
wire in_fccv
= ~(exemode &
((ldfsr_d | fcmp_d) |
(ldfsr_e | fcmp_e | fcmp_in_q) |
(unimpl_fpop_e | funimp_in_q))
);
ME_FD1P fccv_ff (.q(ext_fccv), .cp(ss_clock), .d(in_fccv) );
// ***************************************************************
// FHOLD logic
// stdfq in decode while fq not empty, and FPU is in exemode
// stdfq_qne = (no_holds & stdfq_qne_1) | stdfq_qne_2;
wire stdfq_qne_1
= stdfq_d & (qne_fhold | fpop_e) ;
wire stdfq_qne_2
= stdfq_e & qne_fhold ;
// LDFSR or STFSR while fq is not empty
// fpop_ldstrfsr = (no_holds & fpop_ldstrfsr_1) | fpop_ldstrfsr_2;
wire fpop_ldstrfsr_1
= (stfsr_d | ldfsr_e) & (qne_fhold | fpop_e) ;
wire fpop_ldstrfsr_2
= (stfsr_e | ldfsr_w) & qne_fhold ;
// FPop in the pipe while the fq is full.
// fpop_fqfull = (no_holds & fpop_fqfull_1) | fpop_fqfull_2;
wire fpop_fqfull_1
= fpop_d & (fq_full | (fpop_e & fq_full_next) );
wire fpop_fqfull_2
= fpop_e & fq_full ;
// unimplemented FPop holds the pipe, when another fp-inst reaches
// E-stage, until the unimp FPop takes an exception
// unimpl_fpop = (no_holds & unimpl_fpop_1) | unimpl_fpop_2;
wire unimpl_fpop_1
= finst_d & (unimpl_fpop_e | funimp_in_q);
wire unimpl_fpop_2
= finst_e & funimp_in_q ;
// collision between fload and fpop writeback
wire fload_collision
= (fload_w & writeback_q0) ;
// cases for FHOLD : (l) load/store dependency, (2) FPop in decode
// while fq is full, (3) LDFSR/STFSR in decode
// while fq not empty, (4) fp-inst in decode
// and unimplemented FPop in fq
wire fhold_1_d
= exemode & (ldst_depend_1 | fpop_fqfull_1 | fpop_ldstrfsr_1 |
unimpl_fpop_1 | stdfq_qne_1) ;
wire fhold_2_d
= exemode & (ldst_depend_2 | fpop_fqfull_2 | fpop_ldstrfsr_2 |
unimpl_fpop_2 | stdfq_qne_2) ;
// fhold_d = (fhold_1_d & ~ext_hold) | fhold_2_d;
ME_AI2O1_C iu_hold_gate_3 (.a(fhold_1_d), .b(ext_hold), .c(fhold_2_d),
.z(fhold_d
) );
ME_FD1R fhold_ff (.q(reg_fhold
), .cp(ss_clock), .cr(resetflush_l),
.d(fhold_d) );
wire ext_fhold = reg_fhold | fload_collision ;
// **********************************************************************
// fpu signals for the performance counters
ME_FD1P fhold_perf1_ff (.q(fhold_d1), .cp(ss_clock), .d(ext_fhold) );
ME_AI2O1_C iu_hold_gate_4 (.a(fpop_fqfull_1), .b(ext_hold), .c(fpop_fqfull_2),
.z(fhold_fqfull
) );
ME_FD1P fhold_perf2_ff (.q(fhold_fqfull_d1), .cp(ss_clock), .d(fhold_fqfull) );
endmodule
// **************************************************************
// High-level verilog model of FP instruction decode
//
//
// This module decodes FP instructions, and generates control
// signals for FPop's, and loads/stores. They are decoded seperately
// to improve timing for the critical signals.
//
//
// **************************************************************
module fpinst_decode
(dir_op, dir_op3, dir_fop_nval, dir_ldreg_nval,
dir_streg_nval, dir_ldstreg_nval,
dir_fload_nval, dir_fstore_nval, dir_ldstrfsr_nval,
dir_finst_nostore_nval );
input [1:0] dir_op
; // fields of instr in decode
input [5:0] dir_op3
;
output dir_fop_nval
, // Basic Floating pt. opcode (includes FCMP)
// in decode (not validated)
dir_ldreg_nval
, // ldf,lddf in decode (not validated)
dir_streg_nval
, // stf,stdf in decode (not validated)
dir_ldstreg_nval
, // FP load or store in decode (not validated)
dir_fload_nval
, // FP load in decode (not validated)
dir_fstore_nval
, // FP store in decode (not validated)
dir_ldstrfsr_nval
, // ldfsr/stfsr in decode (not validated)
dir_finst_nostore_nval
; // non-store FP instruction in decode
// (not validated)
parameter [7:0]
FPOP = 8'o264, /* Floating-Point OPerate */
FPCMP = 8'o265, /* Floating-Point CoMPare */
LDF = 8'o340, /* LoaD Floating */
LDDF = 8'o343, /* LoaD Double Floating */
LDFSR = 8'o341, /* LoaD Floating Status Register */
STF = 8'o344, /* STore Floating */
STDF = 8'o347, /* STore Double Floating */
STFSR = 8'o345, /* STore Floating Status Register */
STDFQ = 8'o346; /* STore Double Floating Queue */
// BFCC = 5'o06; /* Branch Floating-point Condition Code */
// wire [4:0] dir_op_op2 = {dir_op, dir_op3[5:3]} ;
wire [7:0] dir_op_op3
= {dir_op, dir_op3} ;
// Basic Floating pt. opcode (includes FCMP) in decode (not validated)
wire dir_fop_nval = (dir_op_op3==FPOP) | (dir_op_op3==FPCMP) ;
// ldf,lddf in decode (not validated)
wire dir_ldreg_nval = (dir_op_op3==LDF) | (dir_op_op3==LDDF) ;
// stf,stdf in decode (not validated)
wire dir_streg_nval = (dir_op_op3==STF) | (dir_op_op3==STDF) ;
// load or store in decode (excluding ldfsr,stfsr,stdfq)
wire dir_ldstreg_nval = dir_ldreg_nval | dir_streg_nval ;
// FP load in decode (not validated)
wire dir_fload_nval = dir_ldreg_nval | (dir_op_op3==LDFSR) ;
// FP store in decode (not validated)
wire dir_fstore_nval = dir_streg_nval | (dir_op_op3==STFSR) |
(dir_op_op3==STDFQ) ;
// ldfsr/stfsr in decode (not validated)
wire dir_ldstrfsr_nval = (dir_op_op3==LDFSR) | (dir_op_op3==STFSR) ;
// non-store FP instruction in decode (not validated)
// used for sequence error detection
wire dir_finst_nostore_nval = dir_fop_nval | dir_fload_nval ;
endmodule
/***********************************************************************
This module determines whether or not an FPop is implemented, and
if it is a multiply instruction.
All quad precision FPop's, are unimplemented.
The equation was generated from a truth table by Synopsys. Includes
all Rev. 8 FP instructions.
***********************************************************************/
module fpop_decd
( op3_0, opf, unimpl_fpop, mul_fpop );
input op3_0
;
input [8:0] opf
;
output unimpl_fpop
;
output mul_fpop
;
wire impl_fpop
= (
(~op3_0 & ~opf[8] & opf[7] & opf[6] & ~opf[5] & opf[4] & ~opf[3]
& ~opf[2] & opf[1] & ~opf[0] ) |
(~op3_0 & ~opf[8] & opf[7] & opf[6] & ~opf[5] & opf[4] & ~opf[3]
& ~opf[2] & ~opf[1] & opf[0] ) |
(~op3_0 & ~opf[8] & ~opf[7] & ~opf[6] & opf[5] & ~opf[4] & opf[3]
& ~opf[2] & opf[1] & ~opf[0] ) |
(~op3_0 & ~opf[8] & opf[7] & opf[6] & ~opf[5] & ~opf[4] & ~opf[3]
& opf[2] & ~opf[0] ) |
(~op3_0 & ~opf[8] & opf[7] & opf[6] & ~opf[5] & ~opf[4] & opf[3]
& ~opf[2] & ~opf[1] ) |
(~op3_0 & ~opf[8] & ~opf[7] & opf[6] & ~opf[5] & ~opf[4] & ~opf[1]
& opf[0] ) |
(~op3_0 & ~opf[8] & ~opf[7] & ~opf[4] & opf[3] & ~opf[2] & ~opf[1]
& opf[0] ) |
(~op3_0 & ~opf[8] & ~opf[7] & opf[6] & ~opf[5] & ~opf[4] & opf[1]
& ~opf[0] ) |
(~op3_0 & ~opf[8] & ~opf[7] & ~opf[5] & ~opf[4] & ~opf[3] & ~opf[1]
& opf[0] ) |
( op3_0 & ~opf[8] & ~opf[7] & opf[6] & ~opf[5] & opf[4] & ~opf[3]
& ~opf[1] & opf[0] ) |
( op3_0 & ~opf[8] & ~opf[7] & opf[6] & ~opf[5] & opf[4] & ~opf[3]
& opf[1] & ~opf[0] ));
assign unimpl_fpop = ~impl_fpop ;
wire mul_fpop =
(~op3_0 & ~opf[8] & ~opf[7] & opf[6] & ~opf[5] & ~opf[4] & opf[3]
& ~opf[2] & ~opf[1] & opf[0] ) |
(~op3_0 & ~opf[8] & ~opf[7] & opf[6] & ~opf[5] & ~opf[4] & opf[3]
& ~opf[2] & opf[1] & ~opf[0] ) |
(~op3_0 & ~opf[8] & ~opf[7] & opf[6] & opf[5] & ~opf[4] & opf[3]
& ~opf[2] & ~opf[1] & opf[0] ) ;
endmodule
/***********************************************************************
This module determines the size of a register field
(single, double, or quad) and whether or not that
field is used:
rs2 is always used,
rs1 and rs2 always have the same size operands (don't care about the
size of rs1 when it isn't used)
quad dbl size used
------- -------- ------- ----
0 0 single 0 not used
0 1 double 1 used
1 1 quad
These equations are "flattened" equations, generated from a
truth table by Synopsys. Includes all Rev. 8 FP instructions.
***********************************************************************/
module rfield_size
( opf, rs1_dbl, rs1_used,
rd_dbl, rd_used );
input [7:0] opf
;
output rs1_dbl
, rs1_used
, rd_dbl
, rd_used
;
buf( rs1_dbl, opf[1] );
assign rs1_used = (~opf[7] & opf[6] );
assign rd_dbl = ((opf[6] & opf[5] ) | (opf[7] & opf[3] ) |
(~opf[7] & opf[1] ));
assign rd_used = ((opf[7] ) | (~opf[4] ));
// assign rs1_quad = (opf[1] & opf[0] );
//
// assign rd_quad = ((opf[2] & opf[7] & opf[3] ) | (~opf[7] & opf[1]
// & opf[0] ) | (opf[5] & opf[2] ));
endmodule
/***********************************************************************
This module checks for dependencies (4-bit compare) between the rd
register field of one register and the rs1, rs2, and rd fields of
another.
***********************************************************************/
![[Up: fhold_ctl chk_d_all]](v2html-up.gif)
![[Up: fhold_ctl chk_e_q0]](v2html-up.gif)
![[Up: fhold_ctl chk_e_q1]](v2html-up.gif)
![[Up: fhold_ctl chk_e_q2]](v2html-up.gif)
![[Up: fhold_ctl chk_w_q0]](v2html-up.gif)
![[Up: fhold_ctl chk_w_q1]](v2html-up.gif)
module chkdep_rd_all
(ins1_rd, ins2_rd, ins2_rs1, ins2_rs2, rd_match,
rs1_match, rs2_match);
input [3:0] ins1_rd
, // instruction_1 rd reg field
ins2_rd
, ins2_rs1
, ins2_rs2
; // instruction_2 reg fields
output rd_match
, rs1_match
, rs2_match
;
ME_COMP4 cmp_rd_rd (ins1_rd[3:0], ins2_rd[3:0], rd_match);
ME_COMP4 cmp_rd_rs1 (ins1_rd[3:0], ins2_rs1[3:0], rs1_match);
ME_COMP4 cmp_rd_rs2 (ins1_rd[3:0], ins2_rs2[3:0], rs2_match);
endmodule
/***********************************************************************
This module checks for dependencies (4-bit compare) between the rd
register field of one register, and the rs1 and rs2 fields of
another.
***********************************************************************/
![[Up: qcore_ctl chk_q0_q1]](v2html-up.gif)
![[Up: qcore_ctl chk_q0_q2]](v2html-up.gif)
![[Up: qcore_ctl chk_q0_ers]](v2html-up.gif)
![[Up: qcore_ctl chk_q1_q2]](v2html-up.gif)
module chkdep_rd_src
(ins1_rd, ins2_rs1, ins2_rs2, rs1_match, rs2_match);
input [3:0] ins1_rd
, // instruction_1 rd reg field
ins2_rs1
, ins2_rs2
; // instruction_2 reg fields
output rs1_match
, rs2_match
;
ME_COMP4 cmp_rd_rs1 (ins1_rd[3:0], ins2_rs1[3:0], rs1_match);
ME_COMP4 cmp_rd_rs2 (ins1_rd[3:0], ins2_rs2[3:0], rs2_match);
endmodule
This page: |
Created: | Thu Aug 19 11:59:39 1999 |
| From: |
../../../sparc_v8/ssparc/fpu/fp_fpc/rtl/fhold_ctl.v
|