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.         */ 
/*                                                                            */ 
/******************************************************************************/ 
//  @(#)qcore_ctl.v	1.31  12/7/93
//
// **************************************************************
//  High-level verilog model of QCORE control
//
//  This module contains 3 main sections that control and regulate
//  the FP Queue:
//    1.  FQ load control
//    2.  FQ issue control and dependency checks
//    3.  FQ writeback control
// **************************************************************

[Up: fpc_ctl qctl1]
module qcore_ctl (ss_clock, ss_reset, ext_flush, ext_hold, FpBusyPhi2,
		  fpm_unfin, fpop_e, rs1_dbl_e, rs1_used_e, rd_dbl_e,
		  unimpl_fpop_e, mul_fpop_d, notrap_writeback, exemode,
		  exemode_two, stdfq_r_noexc, opf5_q0,
		  ir_rs1_e, ir_rs2_e, fq_ir_0, fq_ir_1, fq_ir_2,
		  fq_rd_used, fq_rs1_used, fq_rs1_dbl,
		  fq_qne, fq_ld_nval, fq_rd_dbl, fq_src_sel,
		  fpm_start, fpp_fop, fpp_ld, fpp_reset,
		  qne, qne_r, qne_fhold, fq_empty_next, fq_full_next,
		  fq_full, fq_started_0, fq_type_0, fcmp_q1q2, fcmp_q0,
		  funimp_in_q, done_q0, writeback_q0, wbq0_fhold, fq_update,
		  unfin_fsmuld, fload_wait_w, res_select, ss_scan_mode);

input	ss_clock,		// FPU clock
	ss_reset,		// FPU reset
	ext_flush,		// FPU flush (IU trap)
	ext_hold,		// IU pipeline held (frozen)
	FpBusyPhi2,		// Meiko FPP busy signal
	fpm_unfin,		// mul unfinished signal
	fpop_e,			// FPop in E-stage (includes fold_annul_e term)
	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
	mul_fpop_d,		// (FMULs, FMULd, or FsMULd) in decode
	notrap_writeback,	// writeback q0 if no fpu exception
	exemode,		// execute mode
	exemode_two,		// exemode delayed 2 cycles
	stdfq_r_noexc,		// stdfq in R-stage, no data access exception
	opf5_q0,		// opf[5] of fq0, indicates fsmuld
	ss_scan_mode;

input [4:0] ir_rs1_e,		// E-stage instr. reg. field outputs
	    ir_rs2_e ;
input [15:0] fq_ir_0,		// output of FQ instruction registers
	     fq_ir_1,
	     fq_ir_2 ;
input [2:0] fq_rd_used,		// register field used
	    fq_rs1_used,
	    fq_rs1_dbl ;

output [2:0] fq_qne;		// FQ not empty status bits
output [2:0] fq_ld_nval,	// FQ load controls, not validated
	     fq_rd_dbl;		// size of FQ rd field
output [1:0] fq_src_sel;	// FQ instr mux selects
output  fpm_start,		// start signal for the multiplier
	fpp_fop,		// FpOp for Meiko FPP (start instruction)
	fpp_ld,			// FpLd for Meiko FPP (load operands)
	fpp_reset,		// when an FPop needs to be flushed from
				// the pipeline, the Meiko FPP core also needs
				// to be reset
	qne,			// FQ not empty status bit
	qne_r,			// indicates FPop has reached R-stage
	qne_fhold,		// qne signal for the fhold logic
	fq_empty_next,		// only 1 entry used
	fq_full_next,		// fq has only 1 entry available
	fq_full,		// fq is full
	fq_started_0,		// launch status of fq0
	fq_type_0,		// type of fq0 (1=mul, 0=meiko)
	fcmp_q1q2,		// fcmp in q1 or q2
	fcmp_q0,		// fcmp in q0
	funimp_in_q,		// unimplemented FPop in any fq
	done_q0,		// FPop in q0 (if any) has finished
	writeback_q0,		// result writeback signal
	wbq0_fhold,		// writeback_q0 for fhold logic
	fq_update,		// update fifo for writeback or stdfq
	unfin_fsmuld,		// unfinished for fsmuld
	fload_wait_w ;		// FPop is currently executing, and may trap
output [1:0] res_select ;	// result mux selects


assign fpp_reset = ss_reset ;
wire   qne_e  = 1'b0 ;
wire   qne_w  = 1'b0 ;

wire [2:0] fq_qne, fq_qne_val ;
wire [2:0] fq_started, fq_type, fq_unimp ;
wire issue_q0_nval, issue_q1_nval, issue_q2_nval ;
wire issue_q0_x, issue_q1_x, issue_q2_x ;
wire issue_q0_y, issue_q1_y, issue_q2_y ;
wire fpm_busy, restart_mul, fq_update, fast_fq_update ;
wire cancel_fpop ;

wire reset_l    = ~ss_reset ;
	// wire resetflush   = (~ext_hold & ext_flush) | ss_reset ;
	// wire resetflush_l = (ext_hold | ~ext_flush) & ~ss_reset ;
ME_O2A1 iu_hold_gate_24 (.a(ext_hold), .b(~ext_flush), .c(reset_l),
			 .z(resetflush_l) );

wire no_holds   = ~ext_hold ;
wire no_flush   = ~ext_flush ;
wire no_hold_no_flush  = ~ext_hold & ~ext_flush ;

// **********************************************************************
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] ;

// **********************************************************************
						// miscellaneous ctl signals

ME_FDS2LP fmul_e_ff(.q(mul_fpop_e), .cp(ss_clock), .cr(resetflush_l),
		    .d(mul_fpop_d), .ld(~ext_hold) );

						// Meiko busy
ME_FD1P fpp_busy_ff (.q(me_busy_1), .cp(ss_clock), .d(FpBusyPhi2) );

wire fpp_busy = me_busy_1 | fpp_ld ;


// **********************************************************************


// During normal operation, QI is loaded when the pipe moves from E-stage
// to W-stage; a trap that occurs while the FPop is in W-stage will flush
// that queue entry.


// **********************************************************************

wire decode_zero = ~fq_qne[2] & ~fq_qne[1] & ~fq_qne[0] ;		// 000
wire decode_one =  ~fq_qne[2] & ~fq_qne[1] &  fq_qne[0] ;		// 001
wire decode_two =  ~fq_qne[2] &  fq_qne[1] &  fq_qne[0] ;		// 011
wire decode_three = fq_qne[2] &  fq_qne[1] &  fq_qne[0] ;		// 111

						// FQ has 0 entries
wire zero_qne = fq_update ? decode_one : decode_zero ;
wire fast_zero_qne = fast_fq_update ? decode_one : decode_zero ;
assign qne_fhold = ~((fq_update | cancel_fpop) ? decode_one : decode_zero) ;

						// FQ has 1 entry
wire one_qne  = fq_update ? decode_two : decode_one ;
wire fast_one_qne = fast_fq_update ? decode_two : decode_one ;

						// FQ has 2 entries
wire two_qne  = fq_update ? decode_three : decode_two ;
wire fast_two_qne = fast_fq_update ? decode_three : decode_two ;

						// FQ has 3 entries
wire three_qne = ~fq_update & decode_three ;

assign fq_empty_next = decode_one ;
assign fq_full_next = two_qne & ~cancel_fpop ;
assign fq_full      = three_qne & ~cancel_fpop ;
assign qne   = ~zero_qne ;
assign qne_r = fq_qne_val[0] ;

// **********************************************************************
						// FQ load controls

						// FPop in E, FPU in exemode
wire fpop_nval_e = fpop_e & exemode ;

wire [2:0] fq_ld_nh, fq_ld_nval, fast_fq_ld_nval, fq_ld, fq_ld_ctl ;
wire [2:0] fq_ld_ctl_l ;
						// fq_ld terms are duplicated
						// in fp_qst for speed
assign fq_ld_nval[0] = fpop_nval_e & zero_qne ;
assign fq_ld_nval[1] = fpop_nval_e & one_qne ;
assign fq_ld_nval[2] = fpop_nval_e & two_qne ;

assign fast_fq_ld_nval[0] = fpop_nval_e & fast_zero_qne ;
assign fast_fq_ld_nval[1] = fpop_nval_e & fast_one_qne ;
assign fast_fq_ld_nval[2] = fpop_nval_e & fast_two_qne ;


assign fq_ld_nh[0] = fq_ld_nval[0] & no_flush ;
assign fq_ld_nh[1] = fq_ld_nval[1] & no_flush ;
assign fq_ld_nh[2] = fq_ld_nval[2] & no_flush ;

ME_NOR2_B iu_hold_gate_1 (.a(ext_hold), .b(~fq_ld_nh[0]), .z(fq_ld[0]) );
ME_NOR2_B iu_hold_gate_2 (.a(ext_hold), .b(~fq_ld_nh[1]), .z(fq_ld[1]) );
ME_NOR2_B iu_hold_gate_3 (.a(ext_hold), .b(~fq_ld_nh[2]), .z(fq_ld[2]) );

				// fq_ld_ctl[x] = fq_ld[x] | fq_update ;
ME_O2A1 iu_hold_gate_4 (.a(ext_hold), .b(~fq_ld_nh[0]), .c(~fq_update),
			.z(fq_ld_ctl_l[0]) );

ME_O2A1 iu_hold_gate_5 (.a(ext_hold), .b(~fq_ld_nh[1]), .c(~fq_update),
			.z(fq_ld_ctl_l[1]) );

ME_O2A1 iu_hold_gate_6 (.a(ext_hold), .b(~fq_ld_nh[2]), .c(~fq_update),
			.z(fq_ld_ctl_l[2]) );

assign fq_ld_ctl[2:0] = ~fq_ld_ctl_l[2:0];


// **********************************************************************
		// Operations supported by the qne logic:
		// 1. hold		(do nothing)
		// 2. load, no update	(fq load)
		// 3. update, no load	(fq update==writeback==shift fifo)
		// 4. load and update	(simultaneous fq load and writeback)
wire [2:0] in_qne ;

		// in_qne[0] = fq_ld[0] | fq_qne[1] ;
ME_AI2O1_C iu_hold_gate_7 (.a(fq_ld_nh[0]), .b(ext_hold), .c(fq_qne[1]),
			   .z(in_qne[0]) );

		// in_qne[1] = fq_ld[1] | fq_qne[2] ;
ME_AI2O1_C iu_hold_gate_8 (.a(fq_ld_nh[1]), .b(ext_hold), .c(fq_qne[2]),
			   .z(in_qne[1]) );

assign in_qne[2] = fq_ld[2] ;
						// qne may be cleared in
						// W-stage by ext_flush 
wire [2:0] clear_qne, clear_qne_x ;
assign clear_qne_x[0] = reset_l & (no_flush | fq_qne_val[0]) ;
assign clear_qne_x[1] = reset_l & (no_flush | fq_qne_val[1]) ;
assign clear_qne_x[2] = reset_l & (no_flush | fq_qne_val[2]) ;

ME_A2O1_B iu_hold_gate_9  (.a( ext_hold ), .b( reset_l ), .c( clear_qne_x[0] ),
			   .z( clear_qne[0] ) );
ME_A2O1_B iu_hold_gate_10 (.a( ext_hold ), .b( reset_l ), .c( clear_qne_x[1] ),
			   .z( clear_qne[1] ) );
ME_A2O1_B iu_hold_gate_11 (.a( ext_hold ), .b( reset_l ), .c( clear_qne_x[2] ),
			   .z( clear_qne[2] ) );

wire [2:0] ld_qne ;
assign ld_qne[2:0] = fq_ld_ctl[2:0] ;


ME_FDS2LP qne_0_ff(.q(fq_qne[0]), .cp(ss_clock), .cr(clear_qne[0]),
			.d(in_qne[0]), .ld(ld_qne[0]) );

ME_FDS2LP qne_1_ff(.q(fq_qne[1]), .cp(ss_clock), .cr(clear_qne[1]),
			.d(in_qne[1]), .ld(ld_qne[1]) );

ME_FDS2LP qne_2_ff(.q(fq_qne[2]), .cp(ss_clock), .cr(clear_qne[2]),
			.d(in_qne[2]), .ld(ld_qne[2]) );


// **********************************************************************
						// qne valid until cleared.
			// used to determine whether or not an FPop can trap
			// (don't want an FPop to "shoot itself in the foot"
			// by trapping itself.)
wire [2:0] in_qne_val ;

	// in_qne_val[0] = no_hold_no_flush ?
	//		(fq_update ? fq_qne[1] : fq_qne[0]) : fq_qne_val[1] ;
	//
	// in_qne_val[0] = (fq_qne_val[1] & ext_hold) |
	//		   (in_qne_val_0_y & ~ext_hold) | in_qne_val_0_z ;

wire in_qne_val_0_y = ~ext_flush & (fq_update ? fq_qne[1] : fq_qne[0]) ;
wire in_qne_val_0_z = ext_flush & fq_qne_val[1] ;

ME_AI22O1_C iu_hold_gate_25 (.a1( in_qne_val_0_y ), .a2( ext_hold ),
			     .b1( fq_qne_val[1] ), .b2( ext_hold ),
			     .c( in_qne_val_0_z ), .z( in_qne_val[0] ) );


	// in_qne_val[1] = no_hold_no_flush ?
	//		(fq_update ? fq_qne[2] : fq_qne[1]) : fq_qne_val[2] ;

wire in_qne_val_1_y = ~ext_flush & (fq_update ? fq_qne[2] : fq_qne[1]) ;
wire in_qne_val_1_z = ext_flush & fq_qne_val[2] ;

ME_AI22O1_C iu_hold_gate_26 (.a1( in_qne_val_1_y ), .a2( ext_hold ),
			     .b1( fq_qne_val[2] ), .b2( ext_hold ),
			     .c( in_qne_val_1_z ), .z( in_qne_val[1] ) );


	// in_qne_val[2] = no_hold_no_flush & ~fq_update & fq_qne[2] ;

ME_NOR4 iu_hold_gate_27 (.a( ext_hold ), .b( ext_flush ), .c( fq_update ),
			 .d( ~fq_qne[2] ), .z( in_qne_val[2] ) );


wire [2:0] ld_qne_val ;
wire ld_qne_val_l ;

	// ld_qne_val[0] = no_hold_no_flush | fq_update ;
ME_O2A1 iu_hold_gate_28 (.a( ext_hold ), .b( ext_flush ), .c( ~fq_update ),
			 .z( ld_qne_val_l ) );

assign ld_qne_val[0] = ~ld_qne_val_l;
assign ld_qne_val[1] = ~ld_qne_val_l;
assign ld_qne_val[2] = ~ld_qne_val_l;

ME_FDS2LP qne_val_0_ff(.q(fq_qne_val[0]), .cp(ss_clock), .cr(clear_qne[0]),
			.d(in_qne_val[0]), .ld(ld_qne_val[0]) );

ME_FDS2LP qne_val_1_ff(.q(fq_qne_val[1]), .cp(ss_clock), .cr(clear_qne[1]),
			.d(in_qne_val[1]), .ld(ld_qne_val[1]) );

ME_FDS2LP qne_val_2_ff(.q(fq_qne_val[2]), .cp(ss_clock), .cr(clear_qne[2]),
			.d(in_qne_val[2]), .ld(ld_qne_val[2]) );


			// an FPop that traps in W-stage should be flushed out
			// (may_cancel term added to fix bug #593)
			// (would be prettier to use fq_update as a mux
			//  select, but the equation below works and makes
			//  the gate fix easier)
wire may_cancel = ( fq_update & fq_qne[1] & ~fq_qne_val[1] ) |
		  ( fq_qne[0] & ~fq_qne_val[0] );
wire cancel_fpop_in = ext_flush & may_cancel & exemode ;
ME_FD1P cancel_ff (.q(cancel_fpop), .cp(ss_clock), .d(cancel_fpop_in) );


// **********************************************************************
						// FPop type (1=mul, 0=meiko)
wire [2:0] in_fq_type ;
	// in_fq_type[0] = fq_ld[0] ? (mul_fpop_e & ~restart_mul) :
	//				(fq_type[1] & ~restart_mul) ;

wire in_fq_type_0_x = fq_type[1] & ~restart_mul;
wire in_fq_type_0_y =  fq_ld_nh[0] & (mul_fpop_e & ~restart_mul);
wire in_fq_type_0_z = ~fq_ld_nh[0] & (fq_type[1] & ~restart_mul);

ME_AI22O1_C iu_hold_gate_29 (.a1( in_fq_type_0_y ), .a2( ext_hold ),
			     .b1( in_fq_type_0_x ), .b2( ext_hold ),
			     .c( in_fq_type_0_z ), .z( in_fq_type[0] ) );


	// in_fq_type[1] = fq_ld[1] ? mul_fpop_e : fq_type[2] ;

wire in_fq_type_1_y = fq_ld_nh[1] & mul_fpop_e ;
wire in_fq_type_1_z = ~fq_ld_nh[1] & fq_type[2];

ME_AI22O1_C iu_hold_gate_30 (.a1( in_fq_type_1_y ), .a2( ext_hold ),
			     .b1( fq_type[2] ), .b2( ext_hold ),
			     .c( in_fq_type_1_z ), .z( in_fq_type[1] ) );

assign in_fq_type[2] = mul_fpop_e ;

wire [2:0] ld_fq_type ;
wire ld_fq_type_0_l ;

	// ld_fq_type[0] = fq_ld[0] | fq_update | restart_mul ;
ME_O2A1 iu_hold_gate_21 (.a( ext_hold ), .b( ~fq_ld_nh[0] ),
			 .c( ~(fq_update | restart_mul) ),
			 .z( ld_fq_type_0_l ));

assign ld_fq_type[0] = ~ld_fq_type_0_l ;
assign ld_fq_type[2:1] = fq_ld_ctl[2:1] ;

ME_FDS2LP fq_type_0_ff(.q(fq_type[0]), .cp(ss_clock), .cr(reset_l),
			.d(in_fq_type[0]), .ld(ld_fq_type[0]) );

ME_FDS2LP fq_type_1_ff(.q(fq_type[1]), .cp(ss_clock), .cr(reset_l),
			.d(in_fq_type[1]), .ld(ld_fq_type[1]) );

ME_FDS2LP fq_type_2_ff(.q(fq_type[2]), .cp(ss_clock), .cr(reset_l),
			.d(in_fq_type[2]), .ld(ld_fq_type[2]) );

assign fq_type_0 = fq_type[0] ;


// **********************************************************************
						// FPop unimplemented
wire [2:0] in_fq_unimp ;

	// in_fq_unimp[0] = fq_ld[0] ? unimpl_fpop_e : fq_unimp[1] ;
wire in_fq_unimp_0_y = fq_ld_nh[0] & unimpl_fpop_e ;
wire in_fq_unimp_0_z = ~fq_ld_nh[0] & fq_unimp[1] ;

ME_AI22O1_C iu_hold_gate_31 (.a1( in_fq_unimp_0_y ), .a2( ext_hold ),
			     .b1( fq_unimp[1] ), .b2( ext_hold ),
			     .c( in_fq_unimp_0_z ), .z( in_fq_unimp[0] ) );


	// in_fq_unimp[1] = fq_ld[1] ? unimpl_fpop_e : fq_unimp[2] ;
wire in_fq_unimp_1_y = fq_ld_nh[1] & unimpl_fpop_e ;
wire in_fq_unimp_1_z = ~fq_ld_nh[1] & fq_unimp[2] ;

ME_AI22O1_C iu_hold_gate_32 (.a1( in_fq_unimp_1_y ), .a2( ext_hold ),
			     .b1( fq_unimp[2] ), .b2( ext_hold ),
			     .c( in_fq_unimp_1_z ), .z( in_fq_unimp[1] ) );


	// in_fq_unimp[2] = fq_ld[2] & unimpl_fpop_e ;
ME_NOR3 iu_hold_gate_33 (.a( ext_hold ), .b( ~fq_ld_nh[2] ),
			 .c( ~unimpl_fpop_e ), .z( in_fq_unimp[2] ) );


wire [2:0] ld_fq_unimp ;
assign ld_fq_unimp[2:0] = fq_ld_ctl[2:0] ;

ME_FDS2LP fq_unimp_0_ff(.q(fq_unimp[0]), .cp(ss_clock), .cr(reset_l),
			.d(in_fq_unimp[0]), .ld(ld_fq_unimp[0]) );

ME_FDS2LP fq_unimp_1_ff(.q(fq_unimp[1]), .cp(ss_clock), .cr(reset_l),
			.d(in_fq_unimp[1]), .ld(ld_fq_unimp[1]) );

ME_FDS2LP fq_unimp_2_ff(.q(fq_unimp[2]), .cp(ss_clock), .cr(reset_l),
			.d(in_fq_unimp[2]), .ld(ld_fq_unimp[2]) );

			// add cancel_fpop term to fix bug #601
assign funimp_in_q = (fq_unimp[0] & fq_qne[0] & ~cancel_fpop) |
		     (fq_unimp[1] & fq_qne[1]) | (fq_unimp[2] & fq_qne[2]) ;


// **********************************************************************
						// FPop rd size
wire [2:0] in_fq_rd_dbl ;

	// in_fq_rd_dbl[0] = fq_ld[0] ? rd_dbl_e : fq_rd_dbl[1] ;

wire in_fq_rd_dbl_0_y = fq_ld_nh[0] & rd_dbl_e ;
wire in_fq_rd_dbl_0_z = ~fq_ld_nh[0] & fq_rd_dbl[1] ;

ME_AI22O1_C iu_hold_gate_34 (.a1( in_fq_rd_dbl_0_y ), .a2( ext_hold ),
			     .b1( fq_rd_dbl[1] ), .b2( ext_hold ),
			     .c( in_fq_rd_dbl_0_z ), .z( in_fq_rd_dbl[0] ) );


	// in_fq_rd_dbl[1] = fq_ld[1] ? rd_dbl_e : fq_rd_dbl[2] ;
wire in_fq_rd_dbl_1_y = fq_ld_nh[1] & rd_dbl_e ;
wire in_fq_rd_dbl_1_z = ~fq_ld_nh[1] & fq_rd_dbl[2] ;

ME_AI22O1_C iu_hold_gate_35 (.a1( in_fq_rd_dbl_1_y ), .a2( ext_hold ),
			     .b1( fq_rd_dbl[2] ), .b2( ext_hold ),
			     .c( in_fq_rd_dbl_1_z ), .z( in_fq_rd_dbl[1] ) );


	// in_fq_rd_dbl[2] = fq_ld[2] & rd_dbl_e ;
ME_NOR3 iu_hold_gate_36 (.a( ext_hold ), .b( ~fq_ld_nh[2] ),
			 .c( ~rd_dbl_e ), .z( in_fq_rd_dbl[2] ) );


wire [2:0] ld_fq_rd_dbl ;
assign ld_fq_rd_dbl[2:0] = fq_ld_ctl[2:0] ;

ME_FDS2LP fq_rd_dbl_0_ff(.q(fq_rd_dbl[0]), .cp(ss_clock), .cr(reset_l),
			 .d(in_fq_rd_dbl[0]), .ld(ld_fq_rd_dbl[0]) );

ME_FDS2LP fq_rd_dbl_1_ff(.q(fq_rd_dbl[1]), .cp(ss_clock), .cr(reset_l),
			 .d(in_fq_rd_dbl[1]), .ld(ld_fq_rd_dbl[1]) );

ME_FDS2LP fq_rd_dbl_2_ff(.q(fq_rd_dbl[2]), .cp(ss_clock), .cr(reset_l),
			 .d(in_fq_rd_dbl[2]), .ld(ld_fq_rd_dbl[2]) );


// **********************************************************************
						// FPop started

wire [2:0] in_fq_started, in_fq_started_x, in_fq_started_y ;

	// in_fq_started[0] = fq_update ? (issue_q1 | fq_started[1]) : issue_q0
assign in_fq_started_x[0] = fq_update ? issue_q1_x : issue_q0_x ;
assign in_fq_started_y[0] = fq_update ? (issue_q1_y | fq_started[1]) :
					issue_q0_y ;

ME_AI2O1_C iu_hold_gate_15 (.a( in_fq_started_x[0] ), .b( ext_hold ),
			    .c( in_fq_started_y[0] ), .z( in_fq_started[0] ) );

	// in_fq_started[1] = fq_update ? (issue_q2 | fq_started[2]) : issue_q1
assign in_fq_started_x[1] = fq_update ? issue_q2_x : issue_q1_x ;
assign in_fq_started_y[1] = fq_update ? (issue_q2_y | fq_started[2]) :
					issue_q1_y ;

ME_AI2O1_C iu_hold_gate_16 (.a( in_fq_started_x[1] ), .b( ext_hold ),
			    .c( in_fq_started_y[1] ), .z( in_fq_started[1] ) );

	// in_fq_started[2] = issue_q2 & ~fq_update ;
assign in_fq_started_x[2] = issue_q2_x & ~fq_update ;
assign in_fq_started_y[2] = issue_q2_y & ~fq_update ;

ME_AI2O1_C iu_hold_gate_17 (.a( in_fq_started_x[2] ), .b( ext_hold ),
			    .c( in_fq_started_y[2] ), .z( in_fq_started[2] ) );

wire [2:0] ld_fq_started, ld_fq_started_l ;
	// ld_fq_started[0] = issue_q0 | fq_update | restart_mul ;
ME_O2A1 iu_hold_gate_18 (.a( ext_hold ), .b( ~issue_q0_x ),
			 .c( ~(issue_q0_y | fq_update | restart_mul) ),
			 .z( ld_fq_started_l[0] ) );

	// ld_fq_started[1] = issue_q1 | fq_update ;
ME_O2A1 iu_hold_gate_19 (.a( ext_hold ), .b( ~issue_q1_x ),
			 .c( ~(issue_q1_y | fq_update) ),
			 .z( ld_fq_started_l[1] ) );

	// ld_fq_started[2] = issue_q2 | fq_update ;
ME_O2A1 iu_hold_gate_20 (.a( ext_hold ), .b( ~issue_q2_x ),
			 .c( ~(issue_q2_y | fq_update) ),
			 .z( ld_fq_started_l[2] ) );

assign ld_fq_started[2:0] = ~ld_fq_started_l[2:0];


wire [2:0] clr_started ;
assign clr_started[0] = clear_qne[0] ;

	// clr_started[1] = clear_qne[1] & ~(restart_mul & ~fq_type[1]) ;
wire clr_started_1_b = reset_l & ~(restart_mul & ~fq_type[1]) ;
wire clr_started_1_c = clear_qne_x[1] & ~(restart_mul & ~fq_type[1]) ;

ME_A2O1_B iu_hold_gate_22 (.a( ext_hold ), .b( clr_started_1_b ),
			   .c( clr_started_1_c ), .z( clr_started[1] ) );

	// clr_started[2] = clear_qne[2] & ~(restart_mul & ~fq_type[2]) ;
wire clr_started_2_b = reset_l & ~(restart_mul & ~fq_type[2]) ;
wire clr_started_2_c = clear_qne_x[2] & ~(restart_mul & ~fq_type[2]) ;

ME_A2O1_B iu_hold_gate_23 (.a( ext_hold ), .b( clr_started_2_b ),
			   .c( clr_started_2_c ), .z( clr_started[2] ) );


ME_FDS2LP fq_start_0_ff(.q(fq_started[0]), .cp(ss_clock), .cr(clr_started[0]),
			.d(in_fq_started[0]), .ld(ld_fq_started[0]) );

ME_FDS2LP fq_start_1_ff(.q(fq_started[1]), .cp(ss_clock), .cr(clr_started[1]),
			.d(in_fq_started[1]), .ld(ld_fq_started[1]) );

ME_FDS2LP fq_start_2_ff(.q(fq_started[2]), .cp(ss_clock), .cr(clr_started[2]),
			.d(in_fq_started[2]), .ld(ld_fq_started[2]) );

assign fq_started_0 = fq_started[0] ;


// **********************************************************************
// For SPARC FPops, rs2 is always used, and is always the same size as rs1

				// dependency checks between FQ entries,
				// including the E-stage rd field:

						// **********************
						// q0(rd) -> q1(rs1,rs2)
chkdep_rd_src chk_q0_q1 (fq_rd_q0[4:1], fq_rs1_q1[4:1], fq_rs2_q1[4:1],
			 match4_0_1_rs1, match4_0_1_rs2) ;

wire match_0_1_rs1 = match4_0_1_rs1 & ((fq_rd_q0[0] ~^ fq_rs1_q1[0]) |
					fq_rd_dbl[0] | fq_rs1_dbl[1] );
wire match_0_1_rs2 = match4_0_1_rs2 & ((fq_rd_q0[0] ~^ fq_rs2_q1[0]) |
					fq_rd_dbl[0] | fq_rs1_dbl[1] );

wire dep_q0_q1 =  fq_qne[0] & fq_rd_used[0] & fq_qne[1] &
		  ((match_0_1_rs1 & fq_rs1_used[1]) | match_0_1_rs2) ;


						// **********************
						// q0(rd) -> q2(rs1,rs2)
chkdep_rd_src chk_q0_q2 (fq_rd_q0[4:1], fq_rs1_q2[4:1], fq_rs2_q2[4:1],
			 match4_0_2_rs1, match4_0_2_rs2) ;

wire match_0_2_rs1 = match4_0_2_rs1 & ((fq_rd_q0[0] ~^ fq_rs1_q2[0]) |
					fq_rd_dbl[0] | fq_rs1_dbl[2] );
wire match_0_2_rs2 = match4_0_2_rs2 & ((fq_rd_q0[0] ~^ fq_rs2_q2[0]) |
					fq_rd_dbl[0] | fq_rs1_dbl[2] );

wire dep_q0_q2 = fq_qne[0] & fq_rd_used[0] & fq_qne[2] &
		 ((match_0_2_rs1 & fq_rs1_used[2]) | match_0_2_rs2) ;


						// **********************
						// q0(rd) -> E(rs1,rs2)
chkdep_rd_src chk_q0_ers (fq_rd_q0[4:1], ir_rs1_e[4:1], ir_rs2_e[4:1],
			  match4_0_e_rs1, match4_0_e_rs2) ;

wire match_0_e_rs1 = match4_0_e_rs1 & ((fq_rd_q0[0] ~^ ir_rs1_e[0]) |
					fq_rd_dbl[0] | rs1_dbl_e );
wire match_0_e_rs2 = match4_0_e_rs2 & ((fq_rd_q0[0] ~^ ir_rs2_e[0]) |
					fq_rd_dbl[0] | rs1_dbl_e );

wire dep_q0_ers = fq_qne[0] & fq_rd_used[0] &
		  ((match_0_e_rs1 & rs1_used_e) | match_0_e_rs2) ;


						// **********************
						// q1(rd) -> q2(rs1,rs2)
chkdep_rd_src chk_q1_q2 (fq_rd_q1[4:1], fq_rs1_q2[4:1], fq_rs2_q2[4:1],
			 match4_1_2_rs1, match4_1_2_rs2) ;

wire match_1_2_rs1 = match4_1_2_rs1 & ((fq_rd_q1[0] ~^ fq_rs1_q2[0]) |
					fq_rd_dbl[1] | fq_rs1_dbl[2] );
wire match_1_2_rs2 = match4_1_2_rs2 & ((fq_rd_q1[0] ~^ fq_rs2_q2[0]) |
					fq_rd_dbl[1] | fq_rs1_dbl[2] );

wire dep_q1_q2 = fq_qne[1] & fq_rd_used[1] & fq_qne[2] &
		 ((match_1_2_rs1 & fq_rs1_used[2]) | match_1_2_rs2) ;

						// **********************
						// q1(rd) -> E(rs1,rs2)
chkdep_rd_src chk_q1_ers (fq_rd_q1[4:1], ir_rs1_e[4:1], ir_rs2_e[4:1],
			  match4_1_e_rs1, match4_1_e_rs2) ;

wire match_1_e_rs1 = match4_1_e_rs1 & ((fq_rd_q1[0] ~^ ir_rs1_e[0]) |
					fq_rd_dbl[1] | rs1_dbl_e );
wire match_1_e_rs2 = match4_1_e_rs2 & ((fq_rd_q1[0] ~^ ir_rs2_e[0]) |
					fq_rd_dbl[1] | rs1_dbl_e );

wire dep_q1_ers = fq_qne[1] & fq_rd_used[1] &
		  ((match_1_e_rs1 & rs1_used_e) | match_1_e_rs2) ;


						// **********************
						// q2(rd) -> E(rs1,rs2)
// Not needed because an fpop in E can be loaded into q2 during an update,
// but can't be issued as long as ~fq_started[2] term is in issue_q2 equation.
// Same reason that dep_q1_ers isn't checked in issue_q1.
//
// chkdep_rd_src chk_q2_ers (fq_rd_q2[4:1], ir_rs1_e[4:1], ir_rs2_e[4:1],
// 			  match4_2_e_rs1, match4_2_e_rs2) ;
// 
// wire match_2_e_rs1 = match4_2_e_rs1 & ((fq_rd_q2[0] ~^ ir_rs1_e[0]) |
// 					fq_rd_dbl[2] | rs1_dbl_e );
// wire match_2_e_rs2 = match4_2_e_rs2 & ((fq_rd_q2[0] ~^ ir_rs2_e[0]) |
// 					fq_rd_dbl[2] | rs1_dbl_e );
// 
// wire dep_q2_ers = fq_qne[2] & fq_rd_used[2] &
// 		  ((match_2_e_rs1 & rs1_used_e) | match_2_e_rs2) ;


// **********************************************************************
						// FQ issue logic

						// assign priority if 2 fpop's
						// can be issued simultaneously
wire src_q0         = ~fq_qne[0] ;
wire type_q0        = ~restart_mul & ((src_q0) ? mul_fpop_e : fq_type[0] ) ;
wire chk_busy_q0    = (type_q0) ? fpm_busy : fpp_busy ;
wire could_issue_q0 = (fq_qne[0] | fq_ld_nval[0]) &
		      (~fq_started[0] | restart_mul) & ~chk_busy_q0 ;

wire src_q1         = ~fq_qne[1] ;
wire type_q1        = (src_q1) ? mul_fpop_e : fq_type[1] ;
wire chk_busy_q1    = (type_q1) ? fpm_busy : (fpp_busy | restart_mul) ;
wire could_issue_q1 = (fq_qne[1] | fq_ld_nval[1]) & ~fq_started[1]
						  & ~chk_busy_q1 ;

wire src_q2         = ~fq_qne[2] ;
wire type_q2        = (src_q2) ? mul_fpop_e : fq_type[2] ;
wire chk_busy_q2    = (type_q2) ? fpm_busy : (fpp_busy | restart_mul) ;
wire could_issue_q2 = (fq_qne[2] | fq_ld_nval[2]) & ~fq_started[2]
						  & ~chk_busy_q2 ;

wire priority_q1 = could_issue_q1 & ~could_issue_q0 ;

wire priority_q2 = could_issue_q2 & ~(could_issue_q0 | could_issue_q1) ;


		// ************ checks for issuing from FQ0 *************
		// highest priority

		// issue FPop if (in FQ or being loaded) and (has not been
		// started before) and (fpp is available) and no dependencies
assign issue_q0_nval = could_issue_q0 ;

		// issue_q0 = (no_holds & issue_q0_x) | issue_q0_y;
assign issue_q0_x = fq_ld_nh[0] & issue_q0_nval ;
assign issue_q0_y = fq_qne[0] & issue_q0_nval ;

						// fully qualified issue signal
//synopsys translate_off
wire issue_q0  = (fq_qne[0] | fq_ld[0]) & issue_q0_nval ;
//synopsys translate_on


		// ************ checks for issuing from FQ1 *************
		// 2nd priority

wire regdep_q0_q1 = (src_q1) ? dep_q0_ers : dep_q0_q1 ;

wire chk_2nd_q1 = fq_update |				// q0 is going away
		  (~regdep_q0_q1 &			// no reg depend
		   ((fq_type[0] ^ type_q1) |		// no resource depend
		    (type_q1 & ~fpm_busy))) ;

assign issue_q1_nval = priority_q1 & chk_2nd_q1 ;

		// issue_q1 = (no_holds & issue_q1_x) | issue_q1_y;
assign issue_q1_x = fq_ld_nh[1] & issue_q1_nval ;
assign issue_q1_y = fq_qne[1] & issue_q1_nval ;

						// fully qualified issue signal
//synopsys translate_off
wire issue_q1  = (fq_qne[1] | fq_ld[1]) & issue_q1_nval ;
//synopsys translate_on


		// ************ checks for issuing from FQ2 *************
		// 3rd priority

wire regdep_q0_q2 = (src_q2) ? dep_q0_ers : dep_q0_q2 ;
wire regdep_q1_q2 = (src_q2) ? dep_q1_ers : dep_q1_q2 ;

wire chk_3rd_q2 = (fq_update | (~regdep_q0_q2 & (fq_type[0] ^ type_q2))) &
		  ~regdep_q1_q2 &			// no reg depend
		  (fq_type[1] ^ type_q2) ;		// no resource depend

assign issue_q2_nval = priority_q2 & chk_3rd_q2 ;

		// issue_q2 = (no_holds & issue_q2_x) | issue_q2_y;
assign issue_q2_x = fq_ld_nh[2] & issue_q2_nval ;
assign issue_q2_y = fq_qne[2] & issue_q2_nval ;

						// fully qualified issue signal
//synopsys translate_off
wire issue_q2  = (fq_qne[2] | fq_ld[2]) & issue_q2_nval ;
//synopsys translate_on


// **********************************************************************
					// Partial FQ issue logic -- faster
					// logic to use where full issue logic
					// is not required.
					// FQ2 will be selected by default
					// if FQ0 and FQ1 aren't used.

					// assign priority if 2 fpop's
					// can be issued simultaneously
wire fast_could_issue_q0 = (fq_qne[0] | fast_fq_ld_nval[0]) &
			   (~fq_started[0] | restart_mul) & ~chk_busy_q0 ;

wire fast_could_issue_q1 = (fq_qne[1] | fast_fq_ld_nval[1]) & ~fq_started[1]
							    & ~chk_busy_q1 ;

wire fast_priority_q1 = fast_could_issue_q1 & ~fast_could_issue_q0 ;

wire fast_priority_q2 = ~(fast_could_issue_q0 | fast_could_issue_q1) ;


		// ************ checks for issuing from FQ0 *************
		// highest priority

wire fast_issue_q0_nval = fast_could_issue_q0 ;


		// ************ checks for issuing from FQ1 *************
		// 2nd priority

wire fast_issue_q1_nval = fast_priority_q1 ;


		// ************ checks for issuing from FQ2 *************
		// 3rd priority

wire fast_issue_q2_nval = fast_priority_q2 ;


// **********************************************************************
							// source mux selects
							// 00 == qi_0
							// 01 == qi_1
							// 10 == qi_2
							// 11 == ir_e
assign fq_src_sel[1] =	(fast_issue_q1_nval & src_q1) |
			(fast_issue_q0_nval & src_q0) |
			fast_issue_q2_nval ;

assign fq_src_sel[0] =	(fast_issue_q2_nval & src_q2) |
			(fast_issue_q0_nval & src_q0) |
			fast_issue_q1_nval ;


// **********************************************************************
							// Meiko start signals

		// fpp_fop = (issue_q0 & ~type_q0) | (issue_q1 & ~type_q1) |
		//	     (issue_q2 & ~type_q2) ;
wire fpp_fop_x = (issue_q0_x & ~type_q0) | (issue_q1_x & ~type_q1) |
		 (issue_q2_x & ~type_q2);

wire fpp_fop_y = (issue_q0_y & ~type_q0) | (issue_q1_y & ~type_q1) |
		 (issue_q2_y & ~type_q2);

		// fpp_fop = (fpp_fop_x & ~ext_hold) | fpp_fop_y;
ME_AI2O1_C iu_hold_gate_12 (.a( fpp_fop_x ), .b( ext_hold ), .c( fpp_fop_y ),
			    .z( fpp_fop ) );

ME_FD1P fpp_ld_ff (.q(fpp_ld), .cp(ss_clock), .d(fpp_fop) );


							// Mult. start signals
		// fpm_issue =  (issue_q0 & type_q0) | (issue_q1 & type_q1) |
		//		(issue_q2 & type_q2) ;

wire fpm_issue_x = (issue_q0_x & type_q0) | (issue_q1_x & type_q1) |
		   (issue_q2_x & type_q2);

wire fpm_issue_y = (issue_q0_y & type_q0) | (issue_q1_y & type_q1) |
		   (issue_q2_y & type_q2);

ME_AI2O1_C iu_hold_gate_13 (.a( fpm_issue_x ), .b( ext_hold ), .c(fpm_issue_y),
			    .z( fpm_issue ) );


							// mul aborted by trap
wire i_fpm_abort_x = ext_flush &
		((fq_qne[0] & ~fq_qne_val[0] & fq_started[0] & fq_type[0]) |
		 (fq_qne[1] & ~fq_qne_val[1] & fq_started[1] & fq_type[1]) |
		 (fq_qne[2] & ~fq_qne_val[2] & fq_started[2] & fq_type[2]) );

	// i_fpm_abort = ~ext_hold & i_fpm_abort_x;
ME_NOR2 iu_hold_gate_14 (.a(ext_hold), .b(~i_fpm_abort_x), .z(i_fpm_abort) );

ME_FD1P fpm_abort_ff (.q(fpm_abort), .cp(ss_clock), .d(i_fpm_abort) );

							// reset mul state for
							// abort or exception
wire fpm_reset_l = reset_l & ~fpm_abort & exemode ;

							// mul state pipeline
ME_FD1R fpm_st_ff (.q(fpm_start), .cp(ss_clock), .cr(fpm_reset_l),
			.d(fpm_issue) );
ME_FD1R fpm_x1_ff (.q(fpm_passx1), .cp(ss_clock), .cr(fpm_reset_l),
			.d(fpm_start) );
ME_FD1R fpm_x2_ff (.q(fpm_passx2), .cp(ss_clock), .cr(fpm_reset_l),
			.d(fpm_passx1) );
ME_FD1R fpm_x3_ff (.q(fpm_passx3), .cp(ss_clock), .cr(fpm_reset_l),
			.d(fpm_passx2) );

wire fpm_result_ld = fpm_passx3 |			// normal set
		     (writeback_q0 & fq_type[0]) |	// normal clear
		     restart_mul ;			// special clear

			// reset result reg whenever fq is empty (fix
			// for bug #590)
ME_FDS2LP fpm_res_ff(.q(fpm_result), .cp(ss_clock),
			.cr((fpm_reset_l & fq_qne[0])),
			.d(fpm_passx3), .ld(fpm_result_ld) );

assign fpm_busy = (fpm_start | fpm_passx1) ;

wire unfin_mul = fpm_unfin & fpm_result & fq_type[0] & fq_qne[0] ;

wire unfin_fsmuld = unfin_mul & opf5_q0 ;

						// restart unfinished mul, but
						// not fsmuld
assign restart_mul = unfin_mul & ~opf5_q0 ;


// **********************************************************************
							// FP writeback signals


					// prevents false early writeback
wire busy_q0 = (fq_type[0] ? (~fpm_result | restart_mul) : fpp_busy) |
		cancel_fpop ;

					// FPop in q0 (if any) has finished
assign done_q0 = ~busy_q0 ;

					// writeback if q0 FPop has finished
			// used to be fq_qne_val[0]
assign writeback_q0 = ~busy_q0 & fq_qne[0] & fq_started[0] & exemode &
			exemode_two ;

					// writeback_q0 used for fhold logic
					// to prevent deadlock when an FPop
					// is cancelled in W
assign wbq0_fhold = writeback_q0 | cancel_fpop ;

					// fcmp in q0
assign fcmp_q0 = fq_op3_0_q0 & fq_qne[0] ;

					// fcmp in fq1 or fq2
assign fcmp_q1q2 = (fq_op3_0_q1 & fq_qne[1]) | (fq_op3_0_q2 & fq_qne[2]) ;

					// update fifo for writeback or stdfq
assign fq_update = notrap_writeback | stdfq_r_noexc ;

					// version of fq_update without fptrap
assign fast_fq_update = writeback_q0 | stdfq_r_noexc ;

					// result mux select controls
assign res_select[1] = ~fq_type[0] ;
assign res_select[0] = ~fq_rd_dbl[0] ;


// **********************************************************************
// fpu signal to fix bug in mmu--shows when an FPop is executing, and may
//   cause an fp exception.  Used to delay processing of fload to I/O space
//   until FPop cannot cause a trap.

assign fload_wait_w = fq_qne[0] & exemode ;

endmodule
HierarchyFilesModulesSignalsTasksFunctionsHelp

This page: Created:Thu Aug 19 12:00:13 1999
From: ../../../sparc_v8/ssparc/fpu/fp_fpc/rtl/qcore_ctl.v

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