HierarchyFilesModulesSignalsTasksFunctionsHelp

/******************************************************************************/ 
/*                                                                            */ 
/* 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).
//
// **************************************************************

[Up: fpc_ctl fhold1]
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.
//
//
// **************************************************************

[Up: fhold_ctl fpdec1]
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.
***********************************************************************/
[Up: fhold_ctl unimp_decd]
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.
***********************************************************************/
[Up: fhold_ctl di_rfdsize]
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][Up: fhold_ctl chk_e_q0][Up: fhold_ctl chk_e_q1][Up: fhold_ctl chk_e_q2][Up: fhold_ctl chk_w_q0][Up: fhold_ctl chk_w_q1][Up: fhold_ctl chk_w_q2]
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][Up: qcore_ctl chk_q0_q2][Up: qcore_ctl chk_q0_ers][Up: qcore_ctl chk_q1_q2][Up: qcore_ctl chk_q1_ers]
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
HierarchyFilesModulesSignalsTasksFunctionsHelp

This page: Created:Thu Aug 19 11:59:39 1999
From: ../../../sparc_v8/ssparc/fpu/fp_fpc/rtl/fhold_ctl.v

Verilog converted to html by v2html 5.0 (written by Costas Calamvokis).Help