/******************************************************************************/
/* */
/* 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. */
/* */
/******************************************************************************/
// @(#)stat_ctl.v 1.16 2/21/93
//
// **************************************************************
// High-level verilog model of STATus control
//
// This module contains FSR and tracks the mode of the FPU.
//
// **************************************************************
module stat_ctl
(ss_clock, ss_reset, fold_annul_e, ext_flush, fpm_inx, fpstat,
fsr_data_in, fq_qne_0, fq_empty_next, qne, qne_r,
fq_started_0, fq_type_0, fcmp_q0,
done_q0, writeback_q0, unfin_fsmuld, fsr_ld_nh,
ext_hold, ext_fxack, fstore_w, stdfq_e, stdfq_w,
stdfq_r_noexc, dir_finst_nostore,
fsr_out, notrap_writeback, ext_fexc, exemode, exemode_two,
ss_scan_mode);
input ss_clock
, // Clock input
ss_reset
, // FPU reset
ext_flush
, // FPU flush (IU trap)
fold_annul_e
, // inst in E is annuled
fpm_inx
; // mul inexact signal
input [7:0] fpstat
; // Meiko status bus
input [18:0] fsr_data_in
; // Output of Load Data Register (ldh):
// {ldh[31:30], ldh[27:23], ldh[11:0]}
input fq_qne_0
, // fq0 not empty
fq_empty_next
, // only 1 entry used
qne
, // Q not empty present state bit
qne_r
, // indicates FPop has at least reached R-stage
fq_started_0
, // launch status of fq0
fq_type_0
, // type of fq0 (1=mul, 0=meiko)
fcmp_q0
, // valid FCMP instr. in QI reg.
done_q0
, // FPop in q0 (if any) has finished
writeback_q0
, // result writeback signal
unfin_fsmuld
, // unfinished fsmuld
fsr_ld_nh
, // FSR load enable (requires "& ~ext_hold" )
ext_hold
, // IU pipeline held (frozen) from mhold, etc.
ext_fxack
, // FPU exception acknowledge-without hold term
fstore_w
, // FP store in W-stage
stdfq_e
, // stdfq in E-stage
stdfq_w
, // stdfq in W-stage
stdfq_r_noexc
, // stdfq in R-stage, no data access exception;
// only instr. to allow exit from excmode
dir_finst_nostore
, // non-store FP instruction in decode
ss_scan_mode
;
output [22:0] fsr_out
; // FPU status reg output (non-constant bits)
output notrap_writeback
, // writeback q0 if no fpu exception
ext_fexc
, // External fexc signal to IU
exemode
, // execute mode
exemode_two
; // exemode delayed 2 cycles
wire fptrap
;
// FSR fields
wire [4:0] fsr_cexc
;
wire [4:0] fsr_aexc
;
wire [1:0] fsr_cc
;
wire [2:0] fsr_ftt
;
wire [4:0] fsr_tem
;
wire [1:0] fsr_rd
;
// States: EXECUTION/EXCEPTION_PENDING/EXCEPTION_ACKNOWLEDGED
wire exemode, exemode_one
, exemode_two, pendmode
, excmode
;
// *******************************************************
wire reset_l
= ~ss_reset ;
// resetflush = (~ext_hold & ext_flush) | ss_reset;
// resetflush_l = (ext_hold | ~ext_flush) & ~ss_reset;
ME_O2A1 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 iu_hold_gate_2 (.a( ext_hold ), .b( ~(ext_flush | fold_annul_e) ),
.c( reset_l ), .z( clear_e_l
) );
// *******************************************************
// Pipeline to determine if a non-store FP instruction is in
// the IU's pipeline
ME_FDS2LP finst_ff_e(.q(finst_nostore_e
), .cp(ss_clock), .cr(resetflush_l),
.ld(~ext_hold), .d(dir_finst_nostore));
ME_FDS2LP finst_ff_w(.q(finst_nostore_w
), .cp(ss_clock), .cr(clear_e_l),
.ld(~ext_hold), .d(finst_nostore_e));
// Sequence error detection
wire seq_err
= excmode & finst_nostore_w ;
// Original logic equations:
//
//wire ipendmode = ( (pendmode & ~(ext_fxack & ~ext_hold)) |
// (seq_err & ~ext_flush & ~ext_hold) |
// (fptrap & exemode & exemode_two & fq_started_0)
// ) & fq_qne_0 ;
//
//wire iexcmode = (pendmode & ext_fxack & ~ext_hold) |
// ( ~(((stdfq_w & fq_empty_next) | seq_err) &
// ~ext_flush & ~ext_hold) &
// excmode
// ) ;
//
//wire iexemode = ~(iexcmode | ipendmode) ;
// Hand-structured equations:
// ----------------------------------------
// ipendmode = (ipendmode_x & ext_hold) | (ipendmode_y & ~ext_hold) |
// ipendmode_z;
wire ipendmode_x
= pendmode & fq_qne_0 ;
wire ipendmode_y
= seq_err & ~ext_flush & fq_qne_0 ;
wire ipendmode_z
= ( (pendmode & ~ext_fxack) |
(fptrap & exemode & exemode_two & fq_started_0)
) & fq_qne_0 ;
ME_AI22O1_C iu_hold_gate_3 (.a1( ipendmode_y ), .a2( ext_hold ),
.b1( ipendmode_x ), .b2( ext_hold ),
.c( ipendmode_z ), .z( ipendmode
) );
// ----------------------------------------
// iexcmode = (iexcmode_x & ext_hold) | (iexcmode_y & ~ext_hold) |
// iexcmode_z;
wire iexcmode_x
= excmode ;
wire iexcmode_y
= pendmode & ext_fxack ;
wire iexcmode_z
= ~(((stdfq_w & fq_empty_next) | seq_err) & ~ext_flush) &
excmode ;
ME_AI22O1_C iu_hold_gate_4 (.a1( iexcmode_y ), .a2( ext_hold ),
.b1( iexcmode_x ), .b2( ext_hold ),
.c( iexcmode_z ), .z( iexcmode
) );
// ----------------------------------------
wire iexemode_x
= ipendmode_x | iexcmode_x ;
wire iexemode_y
= ipendmode_y | iexcmode_y ;
wire iexemode_z
= ipendmode_z | iexcmode_z ;
ME_O22A1 iu_hold_gate_5 (.a1( ext_hold ), .a2( ~iexemode_y ),
.b1( ~ext_hold ), .b2( ~iexemode_x ),
.c( ~iexemode_z ), .z( iexemode
) );
// ******* FPC state variables *******
ME_FD1R exemode_ff(.q(exemode), .cp(ss_clock), .cr(reset_l), .d(iexemode));
ME_FD1R penmode_ff(.q(pendmode), .cp(ss_clock), .cr(reset_l), .d(ipendmode));
ME_FD1R excmode_ff(.q(excmode), .cp(ss_clock), .cr(reset_l), .d(iexcmode));
// delayed versions of exemode used to prevent false traps
ME_FD1P exemode_one_ff (.q(exemode_one), .cp(ss_clock), .d(exemode) );
ME_FD1P exemode_two_ff (.q(exemode_two), .cp(ss_clock), .d(exemode_one) );
//synopsys translate_off
always @ (exemode or pendmode or excmode) begin
if ( ((exemode + pendmode + excmode) !== 2'b01) &&
(~`IU.iuchip.ss_reset && ( $time > 15 )) ) begin
$display("### ERROR: FPU exemode, pendmode, excmode = %d %d %d",
exemode, pendmode, excmode);
end
end
//synopsys translate_on
// generate a special case sequence error for STDFQ when
// fsr.qne==0; This case is the only immediate fp_exception
// trap (not deffered) implemented. This case should only
// happen when the FPC is in execute mode, and it must
// stay in execute mode.
wire i_noqne_err
= stdfq_e & ((stdfq_r_noexc & fq_empty_next) | ~qne) ;
ME_FDS2LP noqne_ff (.q(noqne_err
), .cp(ss_clock), .cr(resetflush_l),
.ld(~ext_hold), .d(i_noqne_err) );
wire int_fexc
;
// don't assert fexc until FPop leaves W-stage
// don't assert fexc when non-dependent fstore is held in W-stage
// Original logic equation:
//wire i_fexc = ipendmode & (qne_r | ~ext_hold) &
// (int_fexc | ~(fstore_w & ext_hold)) ;
// Hand-structured equations:
// ----------------------------------------
wire i_fexc_common
= qne_r & (int_fexc | ~fstore_w) ;
wire i_fexc_x
= i_fexc_common & ipendmode_x ;
wire i_fexc_y
= ipendmode_y | ipendmode_z ;
wire i_fexc_z
= i_fexc_common & ipendmode_z ;
ME_AI22O1_C iu_hold_gate_6 (.a1( i_fexc_y ), .a2( ext_hold ),
.b1( i_fexc_x ), .b2( ext_hold ),
.c( i_fexc_z ), .z( i_fexc
) );
ME_FD1R fexc_ff(.q(int_fexc), .cp(ss_clock), .cr(reset_l), .d(i_fexc));
assign ext_fexc = int_fexc | noqne_err ;
// select mul or Meiko status
wire [5:0] fpu_status
= fq_type_0 ? {4'b0, fpm_inx} : fpstat[5:0] ;
// fixed ieee_uf. mn. 12/27/89
wire ieee_uf
= fpu_status[2] & (fpu_status[0] | fsr_tem[2]);
wire [4:0] cexc
= {fpu_status[4:3], ieee_uf, fpu_status[1:0]};
wire [1:0] fcc
= fpstat[7:6]; // Condition code bits
// Trap exception
wire [4:0] tcexc
= cexc & fsr_tem ;
wire ieee_trap
= | tcexc ;
wire unimp_trap
= fpu_status[5] ; // mn. 12/12/89
wire unfin_trap
= unfin_fsmuld ;
wire fpp_in_trap
= ieee_trap | unimp_trap | unfin_trap ;
assign fptrap = fpp_in_trap & fq_qne_0 & done_q0 ;
wire notrap_writeback = writeback_q0 & ~fpp_in_trap ;
// Accrued exception bits
wire [4:0] aexc
= cexc | fsr_aexc;
// FSR ENables
// ftt_en = writeback_q0 | (seq_err & ~ext_flush & ~ext_hold) |
// (noqne_err & ext_fxack & ~ext_hold) ;
wire ftt_en
, ftt_en_l
;
wire ftt_en_x
= (seq_err & ~ext_flush) | (noqne_err & ext_fxack);
ME_O2A1 iu_hold_gate_7 (.a( ext_hold ), .b( ~ftt_en_x ), .c( ~writeback_q0 ),
.z( ftt_en_l ) );
assign ftt_en = ~ftt_en_l ;
wire fsr_ld
, fsr_ld_l
;
ME_OR2_B iu_hold_gate_8 (.a( ext_hold ), .b( ~fsr_ld_nh ), .z( fsr_ld_l ) );
assign fsr_ld = ~fsr_ld_l ;
wire fcc_en
, fcc_en_l
;
// fcc_en = (notrap_writeback & fcmp_q0) | fsr_ld;
ME_O2A1 iu_hold_gate_9 (.a( ext_hold ), .b( ~fsr_ld_nh ),
.c( ~(notrap_writeback & fcmp_q0) ), .z( fcc_en_l ) );
assign fcc_en = ~fcc_en_l ;
wire aexc_en
, aexc_en_l
;
// aexc_en = notrap_writeback | fsr_ld;
ME_O2A1 iu_hold_gate_10 (.a( ext_hold ), .b( ~fsr_ld_nh ),
.c( ~notrap_writeback ), .z( aexc_en_l ) );
assign aexc_en = ~aexc_en_l ;
wire cexc_en
, cexc_en_l
;
// cexc_en = (writeback_q0 & ~(unimp_trap | unfin_trap)) | fsr_ld;
wire cexc_en_x
= writeback_q0 & ~(unimp_trap | unfin_trap) ;
ME_O2A1 iu_hold_gate_11 (.a( ext_hold ), .b( ~fsr_ld_nh ),
.c( ~cexc_en_x ), .z( cexc_en_l ) );
assign cexc_en = ~cexc_en_l;
// FSR RW Inputs
wire [4:0] hold_4_0
= {5{ext_hold}}; // 5 copies of ext_hold
wire [4:0] fsr_ld_nh_4_0
= {5{fsr_ld_nh}}; // 5 copies of fsr_ld_nh
wire [4:0] icexc
; // fsr_ld ? fsr_data_in[4:0] : cexc;
wire [4:0] icexc_y
= fsr_ld_nh_4_0[4:0] & fsr_data_in[4:0] ;
wire [4:0] icexc_z
= ~fsr_ld_nh_4_0[4:0] & cexc[4:0] ;
ME_AI22O1_C_5 iu_hold_gate_12 ( .a1( icexc_y[4:0] ), .a2( hold_4_0[4:0] ),
.b1( cexc[4:0] ), .b2( hold_4_0[4:0] ),
.c( icexc_z[4:0] ), .z( icexc[4:0] ) );
wire [4:0] iaexc
; // fsr_ld ? fsr_data_in[9:5] : aexc;
wire [4:0] iaexc_y
= fsr_ld_nh_4_0[4:0] & fsr_data_in[9:5] ;
wire [4:0] iaexc_z
= ~fsr_ld_nh_4_0[4:0] & aexc[4:0] ;
ME_AI22O1_C_5 iu_hold_gate_13 ( .a1( iaexc_y[4:0] ), .a2( hold_4_0[4:0] ),
.b1( aexc[4:0] ), .b2( hold_4_0[4:0] ),
.c( iaexc_z[4:0] ), .z( iaexc[4:0] ) );
wire [1:0] ifcc
; // fsr_ld ? fsr_data_in[11:10] : fcc;
wire [1:0] ifcc_y
= fsr_ld_nh_4_0[1:0] & fsr_data_in[11:10] ;
wire [1:0] ifcc_z
= ~fsr_ld_nh_4_0[1:0] & fcc[1:0] ;
ME_AI22O1_C_2 iu_hold_gate_14 ( .a1( ifcc_y[1:0] ), .a2( hold_4_0[1:0] ),
.b1( fcc[1:0] ), .b2( hold_4_0[1:0] ),
.c( ifcc_z[1:0] ), .z( ifcc[1:0] ) );
wire [4:0] ltem
= fsr_data_in[16:12];
wire [1:0] lrd
= fsr_data_in[18:17];
// FSR RO Inputs
wire [2:0] iftt
= (seq_err | noqne_err) ? 3'h4 :
(unimp_trap ? 3'h3 :
(unfin_trap ? 3'h2 :
(ieee_trap ? 3'h1 : 3'h0)));
// FSR (FFs)
ME_FDS2LP5 cexc_ff(fsr_cexc,,ss_clock, reset_l, icexc, cexc_en);
ME_FDS2LP5 aexc_ff(fsr_aexc,,ss_clock, reset_l, iaexc, aexc_en);
ME_FDS2LP5 tem_ff (fsr_tem,, ss_clock, reset_l, ltem, fsr_ld);
ME_FDS2LP2 rd_ff (fsr_rd,, ss_clock, reset_l, lrd, fsr_ld);
ME_FDS2LP3 ftt_ff (fsr_ftt,, ss_clock, reset_l, iftt, ftt_en);
ME_FDS2LP2 fcc_ff (fsr_cc,, ss_clock, reset_l, ifcc, fcc_en);
ME_BUFF b0 (qne, fsr_qne
);
// non-constant FSR bits
wire [22:0] fsr_out = {fsr_rd, fsr_tem, fsr_ftt, fsr_qne, fsr_cc,
fsr_aexc, fsr_cexc};
// ***************************** simulation code ************************
//synopsys translate_off
ME_TIEOFF toff (HI
,LO
);
// Constant bits
ME_INVA g0 (HI, res29
); // FSR[29:28] ==> unused
ME_INVA g1 (HI, res28
);
ME_INVA g2 (HI, res22
); // FSR[22] ==> NS bit unused for Meiko
ME_INVA g3 (HI, res21
); // FSR[21:20] ==> reserved
ME_INVA g4 (HI, res20
);
ME_INVA g5 (LO, res19
); // FSR[19:17] ==> ver# = 4
ME_INVA g6 (HI, res18
);
ME_INVA g7 (HI, res17
);
ME_INVA g8 (HI, res12
); // FSR[12] ==> unused
wire [1:0] res3
= {res29, res28};
wire [5:0] res2
= {res22, res21, res20, res19, res18, res17};
wire [31:0] fsr
= {fsr_rd, res3, fsr_tem, res2, fsr_ftt, fsr_qne, res12,
fsr_cc, fsr_aexc, fsr_cexc};
//synopsys translate_on
endmodule
This page: |
Created: | Thu Aug 19 11:59:24 1999 |
| From: |
../../../sparc_v8/ssparc/fpu/fp_fpc/rtl/stat_ctl.v
|