OpenCores
URL https://opencores.org/ocsvn/s1_core/s1_core/trunk

Subversion Repositories s1_core

[/] [s1_core/] [trunk/] [hdl/] [rtl/] [sparc_core/] [sparc_ifu_milfsm.v] - Rev 105

Go to most recent revision | Compare with Previous | Blame | View Log

// ========== Copyright Header Begin ==========================================
// 
// OpenSPARC T1 Processor File: sparc_ifu_milfsm.v
// Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// 
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
// 
// The above named program is distributed in the hope that it will be 
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
// 
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// 
// ========== Copyright Header End ============================================
////////////////////////////////////////////////////////////////////////
/*
//  Module Name: sparc_ifu_ifqdp
//  Description:	
//  The IFQ is the icache fill queue.  This communicates between the
//  IFU and the outside world.  It handles icache misses and
//  invalidate requests from the crossbar.  
*/
////////////////////////////////////////////////////////////////////////
// Global header file includes
////////////////////////////////////////////////////////////////////////
 
/*
/* ========== Copyright Header Begin ==========================================
* 
* OpenSPARC T1 Processor File: ifu.h
* Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* 
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* 
* The above named program is distributed in the hope that it will be 
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* General Public License for more details.
* 
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* 
* ========== Copyright Header End ============================================
*/
////////////////////////////////////////////////////////////////////////
/*
//
//  Module Name: ifu.h
//  Description:	
//  All ifu defines
*/
 
//--------------------------------------------
// Icache Values in IFU::ICD/ICV/ICT/FDP/IFQDP
//--------------------------------------------
// Set Values
 
// IC_IDX_HI = log(icache_size/4ways) - 1
 
 
// !!IMPORTANT!! a change to IC_LINE_SZ will mean a change to the code as
//   well.  Unfortunately this has not been properly parametrized.
//   Changing the IC_LINE_SZ param alone is *not* enough.
 
 
// !!IMPORTANT!! a change to IC_TAG_HI will mean a change to the code as
//   well.  Changing the IC_TAG_HI param alone is *not* enough to
//   change the PA range. 
// highest bit of PA
 
 
 
// Derived Values
// 4095
 
 
// number of entries - 1 = 511
 
 
// 12
 
 
// 28
 
 
// 7
 
 
// tags for all 4 ways + parity
// 116
 
 
// 115
 
 
 
//----------------------------------------------------------------------
// For thread scheduler in IFU::DTU::SWL
//----------------------------------------------------------------------
// thread states:  (thr_state[4:0])
 
 
 
 
 
 
 
 
 
// thread configuration register bit fields
 
 
 
 
 
 
 
//----------------------------------------------------------------------
// For MIL fsm in IFU::IFQ
//----------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
//---------------------------------------------------
// Interrupt Block
//---------------------------------------------------
 
 
 
 
 
 
 
//-------------------------------------
// IFQ
//-------------------------------------
// valid bit plus ifill
 
 
 
 
 
 
 
 
 
 
 
 
 
//`ifdef SPARC_L2_64B
 
 
//`else
//`define BANK_ID_HI 8
//`define BANK_ID_LO 7
//`endif
 
//`define CPX_INV_PA_HI  116
//`define CPX_INV_PA_LO  112
 
 
 
 
 
 
 
//----------------------------------------
// IFU Traps
//----------------------------------------
// precise
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
// disrupting
 
 
 
 
 
 
 
 
//`define MILFSM_NULL   4'b0000
//`define MILFSM_WAIT   4'b1000
//`define MILFSM_REQ    4'b1100
//`define MILFSM_FILL0  4'b1001
//`define MILFSM_FILL1  4'b1011
 
//`define MIL_V  3
//`define MIL_R  2
//`define MIL_A  1
//`define MIL_F  0
 
 
module sparc_ifu_milfsm(/*AUTOARG*/
   // Outputs
   so, fsm_ifc_errreq, fsm_ifc_wrt_tir, fsm_ifc_comp_valid, 
   fsm_ifc_mil_valid, fsm_ifc_mil_cancel, fsm_ifc_thr_ready, 
   fsm_ifc_pred_rdy, fsm_ifc_pcxreq, fsm_ifc_addrbit4_i2, 
   fsm_ifc_milchld, fsm_ifc_milstate, 
   // Inputs
   ifc_fsm_can_thisthr, ifc_fsm_fill_thisthr_i2, 
   ifc_fsm_wr_complete_f, ifqadv_i2, ifd_ifc_4bpkt_i2, 
   fcl_ifq_thr_s1, ifc_fsm_imiss_thisthr_s, ifc_fsm_milhit_s, 
   ifc_fsm_hiton_thismil_s, ifc_fsm_pcxaccept_thisthr, 
   ifc_fsm_miladdr4, clk, se, si, reset, ifc_fsm_err_thisthr
   );
 
   input       ifc_fsm_can_thisthr,        
	             ifc_fsm_fill_thisthr_i2;
 
   input       ifc_fsm_wr_complete_f;
 
   input       ifqadv_i2;
 
   input       ifd_ifc_4bpkt_i2;
   input [1:0] fcl_ifq_thr_s1;             
   input       ifc_fsm_imiss_thisthr_s;
   input       ifc_fsm_milhit_s;
	 input       ifc_fsm_hiton_thismil_s,
               ifc_fsm_pcxaccept_thisthr;
   input       ifc_fsm_miladdr4;
 
   input       clk, 
               se, 
               si, 
               reset;
 
   input       ifc_fsm_err_thisthr;
 
 
   output      so;
 
   output      fsm_ifc_errreq;
   output      fsm_ifc_wrt_tir;
 
   output      fsm_ifc_comp_valid,
	             fsm_ifc_mil_valid,
               fsm_ifc_mil_cancel,
	             fsm_ifc_thr_ready;
   output      fsm_ifc_pred_rdy,
	             fsm_ifc_pcxreq,
	             fsm_ifc_addrbit4_i2;
 
   output [2:0] fsm_ifc_milchld;
 
   output [3:0] fsm_ifc_milstate;
 
 
//----------------------------------------------------------------------
// Declarations
//----------------------------------------------------------------------
 
 
   // local variables
   reg [3:0] 	next_state;
 
   wire [3:0] 	milstate;
 
   wire [2:0]   local_milchld;
 
   wire 	milchld_valid;
 
   wire   fill_this16b;
 
 
   wire 	cancel_mil,
		      cancel_next;
   wire 	err_pending,
		      err_pending_next;
 
   wire 	valid_d1,
		valid_i2;
 
   wire [2:0] 	next_milchld;
 
 
   // Missed Instruction List State Machine
   // 3   - valid
   // 2   - req
   // 1   - addr for fill fill (1/0)
   // 0   - fill
   //
   // 2   - child valid
   // 1:0 - child thr ptr
   //
 
 
   always @(/*AUTOSENSE*/err_pending or ifc_fsm_err_thisthr
            or ifc_fsm_fill_thisthr_i2 or ifc_fsm_imiss_thisthr_s
            or ifc_fsm_milhit_s or ifc_fsm_pcxaccept_thisthr
            or ifc_fsm_wr_complete_f or ifd_ifc_4bpkt_i2 or ifqadv_i2
            or milstate)
     begin
	      case (milstate)  //  synopsys parallel_case
	        4'b0000: // null
	          begin
	             //ic_wrreq_i2 = 1'b0;	       
	             //  orphan_chld = 1'b0;
               next_state[1:0] = 2'b0;
               if (ifc_fsm_err_thisthr | ifc_fsm_imiss_thisthr_s)
		             begin
		                next_state[3] = 1'b1;
		                if (ifc_fsm_milhit_s & ~ifc_fsm_err_thisthr) 
		                  next_state[2] = 1'b0;  // MILFSM_WAIT
		                else
		                  next_state[2] = 1'b1;  // MILFSM_REQ;
		             end
	             else
		             next_state = milstate;
	          end // case: begin...
 
	        4'b1100:  // req
	          begin
	             // ic_wrreq_i2 = 1'b0;		
	             // if canthr=1, the request will not be sent out in this cycle.
               if ((ifc_fsm_pcxaccept_thisthr) &
                   ~(ifc_fsm_err_thisthr | err_pending))
                 // two requests are made when there is an error.
                 // one, with errbit=1 gets back in invalidate response, 
                 // the other, with errbit=0, gets the regular ifill 
                 // return
		             begin
		                // we invalidate the icache on detecting an error
		                // only if this wasn't an MIL hit as well.  If it
		                // was an MIL we would have gone to the wait state
		                // already and it is too late to invalidate the cache
		                next_state = 4'b1000;
                    //		    orphan_chld = 1'b0;		    
		             end
//	             else if ((cancel_mil | ifc_fsm_can_thisthr) & 
//                        ~milchld_valid & ~ifc_fsm_hiton_thismil_s)
//		             begin
//		                next_state = `MILFSM_NULL;
//		             end
	             else
		             begin
		                next_state = milstate;
                    //		    orphan_chld = 1'b0;
		             end 
	          end // case: 4'b1100
 
	        4'b1000: // wait
	          begin
               //	       orphan_chld = 1'b0;
	             if (ifc_fsm_fill_thisthr_i2)
		             begin
		                // ic_wrreq_i2 = 1'b1;
                    if (ifd_ifc_4bpkt_i2 & ifqadv_i2) // 4B ifill from IOB
                      // don't want to advance too quickly and get fasle compl
                      next_state = 4'b0000;
                    else if (~ifd_ifc_4bpkt_i2)
		                  next_state = 4'b1001;
                    else
                      next_state = milstate;
		             end
	             else
		             begin
		                next_state = milstate;
		                //ic_wrreq_i2 = 1'b0;		    
		             end
	          end // case: 4'b1000
 
	        4'b1001: // fill0
	          begin
               //	       orphan_chld = 1'b0;
               if (ifc_fsm_wr_complete_f)
		             begin
		                next_state = 4'b1011;
		                //ic_wrreq_i2 = 1'b1;
		             end
	             else
		             begin
		                next_state = milstate;
		                //ic_wrreq_i2 = 1'b1;
		             end
	          end // case: 4'b1001
 
	        4'b1011: // fill1
	          // Do we really need this state??  yes, to start thr
	          begin
               //	       orphan_chld = 1'b0;		    
	             if (ifc_fsm_wr_complete_f)
		             begin
		                //ic_wrreq_i2 = 1'b0; 		    
                    //		    if (delay_mil | ifc_fsm_imiss_thisthr_s)
                    //		      next_state = `MILFSM_REQ;
                    //		    else
		                next_state = 4'b0000;
		             end
	             else
		             begin
		                //ic_wrreq_i2 = 1'b1;
		                next_state = milstate;
		             end // else: !if(ifc_fsm_wr_complete_f)
	          end // case: 4'b10001
 
	        default:
	          begin
               // synopsys translate_off
		     // 0in <fire -message "MILSTATE, Error: SPARC/IFU/MILFSM: unknown state!"
 
 
               if ($time > (4* 1))
                 begin
 
 
 
 
	                  $display ("MILSTATE", 
                            "Error: SPARC/IFU/MILFSM: unknown state! %b\n",milstate);
 
                 end
 
               // synopsys translate_on               
	             next_state = milstate;
	             //ic_wrreq_i2 = 1'b0;		    
               //	       orphan_chld = 1'b0;	
	          end // case: default
	      endcase // casex(milstate)
     end // always @ (...
 
 
   // MIL state reg
   dffr #(4) milst_reg(.din  (next_state[3:0]),
		                   .q    (milstate[3:0]),
		                   .clk  (clk),
		                   .rst  (reset),
		                   .se   (se), .si(), .so());
 
   // Cancel - Delay state machine
   // -- not used anymore
   // C D
   // 0 0  - null
   // 1 0  - current thread cancelled but pending from L2
   // 1 1  - one ifill pending from L2, current thread will be sent
   //        out after that.
 
//   assign cancel_next = (ifc_fsm_can_thisthr | 
//			                   cancel_mil) & next_state[`MIL_V];    // reset wins
 
   assign cancel_next = (ifc_fsm_can_thisthr | cancel_mil) & 
                          (milstate[3] | ifc_fsm_imiss_thisthr_s |
                           ifc_fsm_err_thisthr);    // reset wins
 
   dffr #(1) can_ff(.din  (cancel_next),
		                .q    (cancel_mil),
		                .clk  (clk),
		                .rst  (reset),
		                .se   (se), .si(), .so());
 
   // track if we need to send out an error request
   assign err_pending_next = (ifc_fsm_err_thisthr & 
	                      (milstate[2] | ~milstate[3]) |
//	                      err_pending & next_state[`MIL_V]) &	
                        err_pending & milstate[3]) &
	                      ~ifc_fsm_pcxaccept_thisthr;
                         // & ~ifc_fsm_can_thisthr;
 
   dffr #(1) err_ff(.din (err_pending_next),
		                .q   (err_pending),
		                .clk (clk),
		                .rst (reset), .se(se), .si(), .so());
   assign fsm_ifc_errreq = err_pending;
 
   // Track secondary hits
   assign next_milchld[2] = ifc_fsm_hiton_thismil_s |    // hit on MIL by
   	                                                     // someone else
              			    fsm_ifc_milchld[2] & milstate[3]; // reset
 
   assign next_milchld[1:0] = ifc_fsm_hiton_thismil_s ? fcl_ifq_thr_s1 :
			                                                  fsm_ifc_milchld[1:0];
 
   dffr #(3) milchld_reg(.din  (next_milchld),
		                     .clk  (clk),
		                     .rst  (reset),
		                     .q    (local_milchld),
		                     .se   (se), .si(), .so());
 
   assign fsm_ifc_milchld[2] = local_milchld[2] & milstate[3];
   assign fsm_ifc_milchld[1:0] = local_milchld[1:0];
 
   assign milchld_valid = local_milchld[2] & milstate[3];
 
//   assign fsm_ifc_addrbit4_i2 = milstate[`MIL_F];
   assign fsm_ifc_addrbit4_i2 = milstate[0] & milstate[3] & 
                                (milstate[1] | ifc_fsm_wr_complete_f); 
 
   // determine if we want to fill from the first pkt or second pkt
   assign fill_this16b = ~(milstate[0] ^ ifc_fsm_miladdr4) |
                            ifd_ifc_4bpkt_i2;
 
   // write to thread inst reg (TIR)
//   assign fsm_ifc_wrt_tir =  (next_state[`MIL_F]) & ~cancel_mil & 
//	                     ifc_fsm_fill_thisthr_i2;
   assign fsm_ifc_wrt_tir =  (milstate[3] & ~milstate[2]) & 
			                         ~(cancel_mil | ifc_fsm_can_thisthr) & 
                               ifc_fsm_fill_thisthr_i2 &
                               fill_this16b;
 
   // write to Icache 
//   assign fsm_ifc_wrreq_i2 = ic_wrreq_i2;
   assign valid_i2 = milstate[3] & ~fsm_ifc_thr_ready;
 
   dff vld_ff(.din (valid_i2),
	            .q   (valid_d1),
	            .clk (clk),
	            .se  (se), .si(), .so());
 
   // signal thread completion
   assign fsm_ifc_thr_ready = milstate[3] & milstate[0] &
	                      milstate[1] & ifc_fsm_wr_complete_f |
	                      ~milstate[3] & valid_d1;
 
   // predict ready assuming 2nd ifill happens in the next cycle
   assign fsm_ifc_pred_rdy =  milstate[3] & milstate[0] &
                              (ifc_fsm_wr_complete_f |
                               milstate[1]); //  & ifc_fsm_fill_thisthr_i2
 
   // set compare valid for mil hit signal
   assign fsm_ifc_comp_valid = milstate[3] &     // valid entry
	                             ~milstate[0] &    // not f0 or f1
                               ~milchld_valid;        // no chld already
 
   assign fsm_ifc_mil_valid = milstate[3];
   assign fsm_ifc_mil_cancel = cancel_mil;
 
   // In the request state or if we need to send an error invalidate, 
   // ask for bus from LSU. 
//   assign fsm_ifc_pcxreq = (milstate[`MIL_V] & milstate[`MIL_R] |
//			    err_pending | ifc_fsm_err_thisthr) & 
//	                   ~ifc_fsm_pcxaccept_thisthr & 
//                            (milchld_valid | ~cancel_mil);
 
//   assign fsm_ifc_pcxreq = (milstate[`MIL_V] & milstate[`MIL_R] & 
//	                          ~ifc_fsm_pcxaccept_thisthr & 
//                            (milchld_valid | ~cancel_mil));
 
   // removed pcx_accept from critical path
   assign fsm_ifc_pcxreq = milstate[3] & milstate[2];
 
   assign fsm_ifc_milstate = milstate;
 
 
endmodule
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.