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

Subversion Repositories ht_tunnel

[/] [ht_tunnel/] [trunk/] [rtl/] [systemc/] [reordering_l2/] [nophandler_l3.cpp] - Rev 19

Compare with Previous | Blame | View Log

//nophandler_l3.cpp
 
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is HyperTransport Tunnel IP Core.
 *
 * The Initial Developer of the Original Code is
 * Ecole Polytechnique de Montreal.
 * Portions created by the Initial Developer are Copyright (C) 2005
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Ami Castonguay <acastong@grm.polymtl.ca>
 *   Laurent Aubray
 *
 * Alternatively, the contents of this file may be used under the terms
 * of the Polytechnique HyperTransport Tunnel IP Core Source Code License 
 * (the  "PHTICSCL License", see the file PHTICSCL.txt), in which case the
 * provisions of PHTICSCL License are applicable instead of those
 * above. If you wish to allow use of your version of this file only
 * under the terms of the PHTICSCL License and not to allow others to use
 * your version of this file under the MPL, indicate your decision by
 * deleting the provisions above and replace them with the notice and
 * other provisions required by the PHTICSCL License. If you do not delete
 * the provisions above, a recipient may use your version of this file
 * under either the MPL or the PHTICSCL License."
 *
 * ***** END LICENSE BLOCK ***** */
 
#include "nophandler_l3.h"
#include "reordering_l2.h"
 
nophandler_l3::nophandler_l3( sc_module_name name ) :
	sc_module(name){
	SC_METHOD(clockedProcess);
	sensitive_pos << clk;
	sensitive_neg << resetx;
}
 
void nophandler_l3::clockedProcess(){
	if(!resetx.read()){
		//On reset, clear all the buffer counds
		for(int n = 0; n < 3; n++){
			bufferCount[n] = 0;
			freeBuffers[n] = NB_OF_BUFFERS;
		}
		ro_buffer_cnt_fc = 0;
		ro_nop_req_fc = false;
		nopRequested = false;
	}
	else{
 
		sc_uint<LOG2_NB_OF_BUFFERS + 1> buffersThatCanBeFreedWithNop[3];
		sc_uint<LOG2_NB_OF_BUFFERS + 1> buffersThatCanBeFreedWithoutNop[3];
 
		//Find how many buffers that can be freed in every VC when taking into acount
		//if a nop was just sent.
		for(int vc = 0; vc < 3; vc++){
 
			sc_uint<LOG2_NB_OF_BUFFERS + 1> bufferCountWithNop;
			sc_uint<LOG2_NB_OF_BUFFERS + 1> bufferCountWithoutNop;
			bufferCountWithNop = bufferCount[vc].read() + 
					getBufferFreedNop((VirtualChannel)vc);
			bufferCountWithoutNop = bufferCount[vc].read();
 
			//The number of buffers that can be freed is the difference between the actual
			//number of buffers that are free and the count of how many buffers have been
			//advertised as being free
			buffersThatCanBeFreedWithNop[vc] = freeBuffers[vc].read() - bufferCountWithNop;
			buffersThatCanBeFreedWithoutNop[vc] = freeBuffers[vc].read() - bufferCountWithoutNop;
		}
 
		//Find the new bufferCount
		for(int vc = 0; vc < 3 ; vc++){
			//By default, keep the same number of buffers
			sc_uint<LOG2_NB_OF_BUFFERS + 1> newBufferCount = bufferCount[vc].read();
 
 
			//If a packet is received, decrease the count
			if(received_packet[vc]){
				newBufferCount--;
			}
 
#ifdef RETRY_MODE
			//When a stomped packet is received, the sender consumed a buffer credit and
			//it must be resent
			if(cd_received_non_flow_stomped_ro.read() && input_packet_vc.read() == vc){
				newBufferCount--;
			}
#endif
 
			//If a nop is sent, add the count sent to the buffer count
			if(fc_nop_sent.read()){
				newBufferCount += getBufferFreedNop((VirtualChannel)vc);
			}
#ifdef RETRY_MODE_ENABLED
			//While a retry sequence, reset buffer count
			if(	csr_retry.read() && !lk_rx_connected.read())
				bufferCount[vc] = 0;
			else
#endif
				bufferCount[vc] = newBufferCount;
		}
 
		//Find new freeBuffersCount
		for(int vc = 0; vc < 3 ; vc++){
			sc_uint<LOG2_NB_OF_BUFFERS + 1> newFreeBufferCount = freeBuffers[vc].read();
			//Decrease the number of free buffers when one is received
			if(received_packet[vc]){
				newFreeBufferCount--;
			}
 
			sc_uint<2> num_buffer_cleared;
			num_buffer_cleared[1] = (sc_bit)buffers_cleared[vc].read()[1] && (sc_bit)buffers_cleared[vc].read()[0];
			num_buffer_cleared[0] = (sc_bit)buffers_cleared[vc].read()[1] ^ (sc_bit)buffers_cleared[vc].read()[0];
 
			//And add the number of buffers that were freed
			newFreeBufferCount += num_buffer_cleared;
			freeBuffers[vc] = newFreeBufferCount;
		}
 
		//Output the result
		if(nopRequested.read())
			outputNopRequest(buffersThatCanBeFreedWithNop[2],buffersThatCanBeFreedWithNop[1],
				buffersThatCanBeFreedWithNop[0]);
		else
			outputNopRequest(buffersThatCanBeFreedWithoutNop[2],buffersThatCanBeFreedWithoutNop[1],
				buffersThatCanBeFreedWithoutNop[0]);
 
		sc_bv<6> bufferFreedNopBufWithNop;
		bufferFreedNopBufWithNop.range(1,0) = buffersThatCanBeFreedWithNop[VC_POSTED] <=3 ? sc_uint<2>(buffersThatCanBeFreedWithNop[VC_POSTED].range(1,0)) : sc_uint<2>(3);
		bufferFreedNopBufWithNop.range(5,4) = buffersThatCanBeFreedWithNop[VC_NON_POSTED] <=3 ? sc_uint<2>(buffersThatCanBeFreedWithNop[VC_NON_POSTED].range(1,0)) : sc_uint<2>(3);
		bufferFreedNopBufWithNop.range(3,2) = buffersThatCanBeFreedWithNop[VC_RESPONSE] <=3 ? sc_uint<2>(buffersThatCanBeFreedWithNop[VC_RESPONSE].range(1,0)) : sc_uint<2>(3);
 
		sc_bv<6> bufferFreedNopBufWithoutNop;
		bufferFreedNopBufWithoutNop.range(1,0) = buffersThatCanBeFreedWithoutNop[VC_POSTED] <=3 ? sc_uint<2>(buffersThatCanBeFreedWithNop[VC_POSTED].range(1,0)) : sc_uint<2>(3);
		bufferFreedNopBufWithoutNop.range(5,4) = buffersThatCanBeFreedWithoutNop[VC_NON_POSTED] <=3 ? sc_uint<2>(buffersThatCanBeFreedWithNop[VC_NON_POSTED].range(1,0)) : sc_uint<2>(3);
		bufferFreedNopBufWithoutNop.range(3,2) = buffersThatCanBeFreedWithoutNop[VC_RESPONSE] <=3 ? sc_uint<2>(buffersThatCanBeFreedWithNop[VC_RESPONSE].range(1,0)) : sc_uint<2>(3);
 
		if(fc_nop_sent.read()){
			ro_buffer_cnt_fc = bufferFreedNopBufWithNop;
		}
		else{
			ro_buffer_cnt_fc = bufferFreedNopBufWithoutNop;
		}
	}
}
 
sc_uint<2> nophandler_l3::getBufferFreedNop(const VirtualChannel vc){
	//A simple mux
	switch(vc){
	case VC_POSTED :
		return sc_bv<2>(ro_buffer_cnt_fc.read().range(1,0));
	case VC_NON_POSTED :
		return sc_bv<2>(ro_buffer_cnt_fc.read().range(5,4));
	case VC_RESPONSE :
		return sc_bv<2>(ro_buffer_cnt_fc.read().range(3,2));
	default :
		return 0;
	}
 
}
 
void nophandler_l3::outputNopRequest(const sc_uint<LOG2_NB_OF_BUFFERS + 1> buffersThatCanBeFreedWithNop_2,
		const sc_uint<LOG2_NB_OF_BUFFERS + 1> buffersThatCanBeFreedWithNop_1,
		const sc_uint<LOG2_NB_OF_BUFFERS + 1> buffersThatCanBeFreedWithNop_0){
 
	//Place the parameters in an array so it can be read from within a loop
	const sc_uint<LOG2_NB_OF_BUFFERS + 1> buffersThatCanBeFreedWithNop[3] = {
		buffersThatCanBeFreedWithNop_0,buffersThatCanBeFreedWithNop_1,buffersThatCanBeFreedWithNop_2};
 
	//Calculate if we will do a nop request
	bool doNopRequest = false;
 
	//Calculate the buffer count to send to the flow control
 
	//Truncate the number of buffers to be freed to a maximum of 3
	for(int vc = 0; vc < 3; vc++){
 
		/** This next part is a simple algorithm so we that we don't monopolize the link by sending
			nops of buffers being freed.  It is strongly possible that this will need to be
			adjusted with profiling */
 
		if(
		//If we have a lot of buffers that are free, we can slack and only request a nop
		//when we have at least 3 buffers to free (the maximum a nop can carry)
		//If we have 3 or more buffers even if a nop has just been sent, request another nop
			(freeBuffers[vc].read() > 4 && buffersThatCanBeFreedWithNop[vc] >= 3) ||
		//Same principle, but if we have less buffers free, we get more aggressive about
		//requesting that a nop be sent!
			(freeBuffers[vc].read() <= 4 && buffersThatCanBeFreedWithNop[vc] >= 2) ||
			(freeBuffers[vc].read() <= 2 && buffersThatCanBeFreedWithNop[vc] > 0)
		)
			doNopRequest = true; 
	}
 
	//Output the results
 
	ro_nop_req_fc = doNopRequest;
	nopRequested = doNopRequest || (nopRequested.read() && !fc_nop_sent.read());
}
 
#ifndef SYSTEMC_SIM
#include "../core_synth/synth_control_packet.cpp"
#endif
 
 

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.