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

Subversion Repositories ht_tunnel

[/] [ht_tunnel/] [tags/] [START/] [rtl/] [systemc/] [databuffer_l2/] [databuffer_l2.cpp] - Rev 19

Compare with Previous | Blame | View Log

//databuffer_l2.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>
 *   Martin Corriveau
 *
 * 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 "databuffer_l2.h"
 
 
databuffer_l2::databuffer_l2( sc_module_name name ) :
	sc_module(name){
	SC_METHOD(clockProcess);
	sensitive_neg << resetx;
	sensitive_pos << clk;
 
	SC_METHOD(sendAddressToCommandDecoder);
	sensitive << cd_vctype_db << firstFreeBuffer[0] << firstFreeBuffer[1] << firstFreeBuffer[2];
 
	SC_METHOD(write_memory);
	sensitive << cd_write_db << currentWriteVC << currentWriteBuffer << nbWritesInBufferDone
		<< cd_data_db;
 
	SC_METHOD(read_memory);
	sensitive << csr_read_db << ui_read_db << fwd_read_db
		<< csr_vctype_db << ui_vctype_db << fwd_vctype_db
		<< csr_address_db << ui_address_db << fwd_address_db
		<< currentReadVc[0] << currentReadVc[1]
		<< currentReadAddress[0] << currentReadAddress[1]
		<< nbReadsInBufferDone[0] << nbReadsInBufferDone[1]
		<< currentlyReading[0] << currentlyReading[1]
		<< ui_grant_csr_access_db;
 
	SC_METHOD(redirect_memory_output);
	sensitive << memory_output[0] << memory_output[1];
 
}
 
///Synchronous process, contains most of the functionality
void databuffer_l2::clockProcess(){
 
	if(resetx.read() == false){
		doReset();
	}
	else{
		//----------------
		//Write in memory
		//----------------
 
		//-------------------------------------------
		//Find new value of nbWritesInBufferDone
		//-------------------------------------------
 
		//If we are starting a new data packet, reset the number of writes done
		if(cd_getaddr_db.read() == true){
			nbWritesInBufferDone = 0;
		}
		//If we are receiving a data dword from CD, increment the number of writes done
		else if(cd_write_db.read()){
			nbWritesInBufferDone = nbWritesInBufferDone.read() + 1;
		}
 
		//------------------------------------
		//Find new value of currentWriteBuffer
		//------------------------------------
 
		//New data packet
		if(cd_getaddr_db.read() == true){
			//The new buffer is first buffer that is free
			currentWriteBuffer = firstFreeBuffer[cd_vctype_db.read()].read();
			currentWriteVC = cd_vctype_db.read();
		}
 
		//-----------------------------
		// Read operation done in own process
		//-----------------------------
 
		/** Start by putting all the input port signals
		in an array format so it can be used easily
		in a for loop.
		*/
		bool inputRead[2];
		if(ui_grant_csr_access_db.read())
			inputRead[ACCEPTED_PORT] = csr_read_db.read();
		else
			inputRead[ACCEPTED_PORT] = ui_read_db.read();
		inputRead[FWD_PORT] = fwd_read_db.read();
 
		VirtualChannel inputReadVC[2];
		if(ui_grant_csr_access_db.read())
			inputReadVC[ACCEPTED_PORT] = csr_vctype_db.read();
		else
			inputReadVC[ACCEPTED_PORT] = ui_vctype_db.read();
		inputReadVC[FWD_PORT] = fwd_vctype_db.read();
 
		sc_uint<BUFFERS_ADDRESS_WIDTH> inputReadAddress[2];
		if(ui_grant_csr_access_db.read())
			inputReadAddress[ACCEPTED_PORT] = csr_address_db.read();
		else
			inputReadAddress[ACCEPTED_PORT] = ui_address_db.read();
		inputReadAddress[FWD_PORT] = fwd_address_db.read();
 
		///If the buffer being outputed should be cleared
		bool clearBuffer[2];
		if(ui_grant_csr_access_db.read())
			clearBuffer[ACCEPTED_PORT] = csr_erase_db.read();
		else
			clearBuffer[ACCEPTED_PORT] = ui_erase_db.read();
		clearBuffer[FWD_PORT] = fwd_erase_db.read();
 
 
		/**
			Manage reading buffers for both read ports (accepted and forward)
			Find the next read state, read address, read VC and read count
		*/
		for(unsigned n = 0; n < 2; n++){
 
			sc_uint<2> currentReadVcIndex = currentReadVc[n];
 
			//If erasing a buffer, stop reading
			if(clearBuffer[n]){
				currentlyReading[n] = false;
				nbReadsInBufferDone[n] = 0;
			}
			else if(inputRead[n] == true){
				nbReadsInBufferDone[n] = nbReadsInBufferDone[n].read() + 1;
				//If not reading, activate reading state
				if(currentlyReading[n].read() == false){
					currentlyReading[n] = true;
				}
 
			}
			//If not currently reading, still store what buffer we are outputing
			if(currentlyReading[n].read() == false){
				currentReadVc[n] = inputReadVC[n];
				currentReadAddress[n] = inputReadAddress[n];
			}
		}
 
		//********************************
		//Buffer management
		//
		// Set if a buffer is free
		// Set the nextDataBuffer
		//********************************
 
		//Go through every buffer
		for(unsigned vc = 0; vc < 3; vc++){
			for(unsigned buffer = 0; buffer < DATABUFFER_NB_BUFFERS;buffer++){
 
#ifdef RETRY_MODE_ENABLED
				//Is it part of a packet dropped from the CD?
				bool drop_from_cd =currentWriteBuffer.read() == buffer &&
					currentWriteVC.read() == vc && cd_drop_db.read();
#endif
 
				//Is it erase by EH
				bool erase_from_eh = eh_address_db.read() == buffer &&
					eh_vctype_db.read() == vc && eh_erase_db.read();
 
				//Is it erase by Accepted port
				bool erase_from_accepted = inputReadAddress[ACCEPTED_PORT] == buffer &&
					inputReadVC[ACCEPTED_PORT] == vc && clearBuffer[ACCEPTED_PORT];
 
				//Is it erase by Forward port
				bool erase_from_forward = fwd_address_db.read() == buffer &&
					fwd_vctype_db.read() == vc && fwd_erase_db.read();
 
				//If we are starting to write in this buffer, tag is as not free
				if(cd_getaddr_db.read() && 
					vc == cd_vctype_db.read() && 
					buffer == firstFreeBuffer[cd_vctype_db.read()].read())
				{
					bufferFree[vc][buffer] = false;
				}
				//If the buffer is either part of a dropped packet or we are finished reading it's
				//data. mark it as free
				else if(erase_from_eh || erase_from_accepted || erase_from_forward
#ifdef RETRY_MODE_ENABLED
					 ||	drop_from_cd
#endif
				){
					bufferFree[vc][buffer] = true;
				}
				//else stay the same
			}
		}
 
 
 
		/**
			This finds the new value for firstFreeBuffer
			At the same time, it finds if the VC is full, which the only purpose
			is to generate an overflow error if necessary
 
			The "firstFreeBuffer" is used to know were the next data packet will
			start to be written.
		*/
		bool full[3] = {false,false,false};
		for(unsigned vc = 0; vc < 3; vc++){
			//Create a vector that contains buffer that are free
			sc_bv<DATABUFFER_NB_BUFFERS> vector_to_encode;
			for(unsigned n = 0; n < DATABUFFER_NB_BUFFERS; n++){
				vector_to_encode[n] = bufferFree[vc][n].read();
			}
 
			//Encode it to find the firt buffer that is free
			bool found = true;
			firstFreeBuffer[vc] = priority_encoder(vector_to_encode,found);
 
			//Log if the buffer is full
			if(!found){
				full[vc] = true;
			}
		}
 
		//Generate overflow if necessary
		if(	full[cd_vctype_db.read()] && cd_getaddr_db.read() == true){
			db_overflow_csr = true;
		}
		else{
			db_overflow_csr = false;
		}
 
		//Find the new bufferCount
		//The bufferCountWithNop is useful for the next block where we calculate how
		//many buffers to notify as freed with a nop
		sc_uint<DATABUFFER_LOG2_NB_BUFFERS+1> bufferCountWithNop[3];
        sc_uint<DATABUFFER_LOG2_NB_BUFFERS+1> bufferCountWithoutNop[3];
 
		//For every VC
		for(unsigned vc = 0; vc < 3 ; vc++){
			//By default, keep the same count
			sc_uint<DATABUFFER_LOG2_NB_BUFFERS+1> newBufferCount = bufferCount[vc].read();
 
			//If a nop was sent, add to the count what was sent on the nop
			sc_uint<2> buffer_freed_nop = getBufferFreedNop(vc);
 
			bufferCountWithNop[vc] = bufferCount[vc].read()+buffer_freed_nop;
			bufferCountWithoutNop[vc] = bufferCount[vc].read();
 
			//When receiving a new packet, buffer count is decreased
			if(cd_getaddr_db.read() == true && vc == cd_vctype_db.read()){
				newBufferCount--;
			}
 
			if(fc_nop_sent.read()){
				newBufferCount += buffer_freed_nop;
			}
 
#ifdef RETRY_MODE_ENABLED
			//In retry mode, when the retry sequence is initiated, buffer count is reset
			if(lk_initiate_retry_disconnect.read() || cd_initiate_retry_disconnect.read() ||
				(csr_retry.read() && !ldtstopx.read())){
				bufferCount[vc] = 0;
			}
			else
#endif
			{
				bufferCount[vc] = newBufferCount;
			}
		}
 
		//Find the new number of free buffers
		sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> buffersThatCanBeFreedWithNop[3];
		sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> buffersThatCanBeFreedWithoutNop[3];
 
		for(unsigned vc = 0; vc < 3; vc++){
			//Reduce the number of free buffers everytime a new buffers is requested
			//from CD
			sc_uint<1> substract_one;
			substract_one[0] = cd_getaddr_db.read() && cd_vctype_db.read() == vc;
 
			//Add the number of buffers that are dropped or erased
			sc_uint<1> add_eh,add_accepted,add_forward;
#ifdef RETRY_MODE_ENABLED
			sc_uint<1> add_cd;
			add_cd[0] = cd_drop_db.read() && currentWriteVC.read() == vc;
#endif
			add_eh[0] = eh_erase_db.read() && eh_vctype_db.read() == vc;
			add_accepted[0] = inputReadVC[ACCEPTED_PORT] == vc && clearBuffer[ACCEPTED_PORT];
			add_forward[0] = fwd_erase_db.read() && fwd_vctype_db.read() == vc ;
 
			//add_forward and add_uicomes in very late, so use it as a mux select 
			//instead of inside the adder
			sc_uint<2> free_buffer_case_selector;
			free_buffer_case_selector[0] = (sc_bit)add_forward[0];
			free_buffer_case_selector[1] = (sc_bit)add_accepted[0];
 
#ifdef RETRY_MODE_ENABLED
			switch(free_buffer_case_selector){//synopsys infer_mux
			case 3:
				freeBuffers[vc] = freeBuffers[vc].read() + (add_cd + add_eh) - substract_one + 2;
				break;
			case 2:
			case 1:
				freeBuffers[vc] = freeBuffers[vc].read() + (add_cd + add_eh) - substract_one + 1;
				break;
			default:
				freeBuffers[vc] = freeBuffers[vc].read() + (add_cd + add_eh) - substract_one;
			}
#else
			switch(free_buffer_case_selector){//synopsys infer_mux
			case 3:
				freeBuffers[vc] = (freeBuffers[vc].read() + add_eh) - substract_one + 2;
				break;
			case 2:
			case 1:
				freeBuffers[vc] = (freeBuffers[vc].read() + add_eh) - substract_one + 1;
				break;
			default:
				freeBuffers[vc] = (freeBuffers[vc].read() + add_eh) - substract_one;
			}
#endif
 
			buffersThatCanBeFreedWithNop[vc] = freeBuffers[vc].read() - bufferCountWithNop[vc];
			buffersThatCanBeFreedWithoutNop[vc] = freeBuffers[vc].read() - bufferCountWithoutNop[vc];
 
		}
 
		//Finally, output the nop request.  
		if(nopRequested.read())
			outputNopRequest(buffersThatCanBeFreedWithNop[2],buffersThatCanBeFreedWithNop[1],
				buffersThatCanBeFreedWithNop[0],freeBuffers[2],freeBuffers[1],freeBuffers[0]);
		else
			outputNopRequest(buffersThatCanBeFreedWithoutNop[2],buffersThatCanBeFreedWithoutNop[1],
				buffersThatCanBeFreedWithoutNop[0],freeBuffers[2],freeBuffers[1],freeBuffers[0]);
 
		sc_bv<6> bufferFreedNopBufWithNop;
		bufferFreedNopBufWithNop.range(1,0) = buffersThatCanBeFreedWithNop[VC_POSTED] <= 3 ? buffersThatCanBeFreedWithNop[VC_POSTED].range(1,0) : sc_uint<2>(3);
		bufferFreedNopBufWithNop.range(5,4) = buffersThatCanBeFreedWithNop[VC_NON_POSTED] <= 3 ? buffersThatCanBeFreedWithNop[VC_NON_POSTED].range(1,0) : sc_uint<2>(3);
		bufferFreedNopBufWithNop.range(3,2) = buffersThatCanBeFreedWithNop[VC_RESPONSE] <= 3 ? buffersThatCanBeFreedWithNop[VC_RESPONSE].range(1,0) : sc_uint<2>(3);
 
		sc_bv<6> bufferFreedNopBufWithoutNop;
		bufferFreedNopBufWithoutNop.range(1,0) = buffersThatCanBeFreedWithoutNop[VC_POSTED] <= 3 ? buffersThatCanBeFreedWithoutNop[VC_POSTED].range(1,0) : sc_uint<2>(3);
		bufferFreedNopBufWithoutNop.range(5,4) = buffersThatCanBeFreedWithoutNop[VC_NON_POSTED] <= 3 ? buffersThatCanBeFreedWithoutNop[VC_NON_POSTED].range(1,0) : sc_uint<2>(3);
		bufferFreedNopBufWithoutNop.range(3,2) = buffersThatCanBeFreedWithoutNop[VC_RESPONSE] <= 3 ? buffersThatCanBeFreedWithoutNop[VC_RESPONSE].range(1,0) : sc_uint<2>(3);
 
		if(fc_nop_sent.read()){
			db_buffer_cnt_fc = bufferFreedNopBufWithNop;
		}
		else{
			db_buffer_cnt_fc = bufferFreedNopBufWithoutNop;
		}
	}
}
 
void databuffer_l2::write_memory(){
	memory_write = cd_write_db;
	memory_write_address_vc = currentWriteVC;
	memory_write_address_buffer = currentWriteBuffer.read();
	memory_write_address_pos = nbWritesInBufferDone.read();
	memory_write_data = cd_data_db.read();
}
 
void databuffer_l2::read_memory(){
	//-----------------------------
	// Read operation
	//-----------------------------
 
	/** Start by putting all the input port signals
	in an array format so it can be used easily
	in a for loop.
	*/
	bool inputRead[2];
	if(ui_grant_csr_access_db.read())
		inputRead[ACCEPTED_PORT] = csr_read_db.read();
	else
		inputRead[ACCEPTED_PORT] = ui_read_db.read();
	inputRead[FWD_PORT] = fwd_read_db.read();
 
	VirtualChannel inputReadVC[2];
	if(ui_grant_csr_access_db.read())
		inputReadVC[ACCEPTED_PORT] = csr_vctype_db.read();
	else
		inputReadVC[ACCEPTED_PORT] = ui_vctype_db.read();
	inputReadVC[FWD_PORT] = fwd_vctype_db.read();
 
	sc_uint<BUFFERS_ADDRESS_WIDTH> inputReadAddress[2];
	if(ui_grant_csr_access_db.read())
		inputReadAddress[ACCEPTED_PORT] = csr_address_db.read();
	else
		inputReadAddress[ACCEPTED_PORT] = ui_address_db.read();
	inputReadAddress[FWD_PORT] = fwd_address_db.read();
 
	//Virtual channel that we will be outputed
	sc_uint<2> outputReadVcIndex[2];
	//Virtual buffer that we will be outputed
	sc_uint<BUFFERS_ADDRESS_WIDTH> outputReadAddress[2];
 
	//------------------------
	//For every read port
	//------------------------
 
	for(unsigned n = 0; n < 2; n++){
 
		sc_uint<2> currentReadVcIndex = currentReadVc[n];
		sc_uint<2> inputReadVcIndex = inputReadVC[n];
 
		//Position in buffer that we will be outputed
		/** This variable goes with outputReadVcIndex and outputReadAddress
		but is not declared at the same location simply because this
		variable will not be needed after the for loop
		*/
		sc_uint<4> outputPosInBuffer;
 
 
		/** In software simulation, if we exceed pointer, it will do an Access violation,
		but in hardware, we don't want to add the logic to prevent this from hapening since
		it has no effect*/
#ifdef SYSTEMC_SIM
		if(currentReadVcIndex == VC_NONE) currentReadVcIndex = 0;
#endif	
 
		//Find what is going to be output
		sc_uint<2> output_sel;
		output_sel[1] = inputRead[n];
		output_sel[0] = currentlyReading[n].read();
		switch(output_sel){
		/**
		If we are reading at the input and are currently in reading mode, just go
		to the next data dword
		*/
		case 3:
		{
			outputPosInBuffer = nbReadsInBufferDone[n].read() + 1;
			outputReadAddress[n] = currentReadAddress[n].read();
			outputReadVcIndex[n] = currentReadVcIndex;
		}
		break;
		/**
		If we get a read message for the first time, it means that the first dword
		has already been read and we are expected to output the next data, hence
		why we output 1 instead of 0.
		*/
		case 2:
		{
			outputPosInBuffer = 1;
			outputReadAddress[n] = currentReadAddress[n].read();
			outputReadVcIndex[n] = currentReadVcIndex;
		}
		break;
		/**
		A simple pos in the reading
		*/
		case 1:
			outputPosInBuffer = nbReadsInBufferDone[n].read();
			outputReadAddress[n] = currentReadAddress[n].read();
			outputReadVcIndex[n] = currentReadVcIndex;
			break;
		/**
		We're not currently reading yet, so simply output the first dword
		of the VC and address that we receive at the inputs.
		*/
		//case 0:
		default:
			outputReadVcIndex[n] = inputReadVcIndex;
			outputReadAddress[n] = inputReadAddress[n];
			outputPosInBuffer = 0;
		}
 
		memory_read_address_vc[n] = outputReadVcIndex[n];
		memory_read_address_buffer[n] = outputReadAddress[n];
		memory_read_address_pos[n] = outputPosInBuffer;
 
		//Store in signal for use in the sychronous method
		outputReadVcIndex_s[n] = outputReadVcIndex[n];
		outputReadAddress_s[n] = outputReadAddress[n];
	}
 
}
 
void databuffer_l2::redirect_memory_output(){
	db_data_accepted.write(memory_output[ACCEPTED_PORT]);
	db_data_fwd.write(memory_output[FWD_PORT]);
}
 
 
//see .h for description
void databuffer_l2::sendAddressToCommandDecoder(){
	switch(cd_vctype_db.read()){
	case VC_POSTED :
		db_address_cd.write(firstFreeBuffer[0].read());
		break;
	case VC_NON_POSTED :
		db_address_cd.write(firstFreeBuffer[1].read());
		break;
	//case VC_RESPONSE :
	default :
		db_address_cd.write(firstFreeBuffer[2].read());
		break;
	}	
}
 
 
//see .h for description
sc_uint<2> databuffer_l2::getBufferFreedNop(const VirtualChannel &vc){
	sc_uint<2> tmp;
	switch(vc){
	case VC_POSTED :
		tmp = sc_bv<2>(db_buffer_cnt_fc.read().range(1,0));
		break;
	case VC_NON_POSTED :
		tmp = sc_bv<2>(db_buffer_cnt_fc.read().range(5,4));
		break;
	case VC_RESPONSE :
		tmp = sc_bv<2>(db_buffer_cnt_fc.read().range(3,2));
		break;
	default :
		tmp = 0;
	}
	return tmp;
}
 
//see .h for description
void databuffer_l2::outputNopRequest(
			const sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> &buffersThatCanBeFreedWithNop_2,
			const sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> &buffersThatCanBeFreedWithNop_1,
			const sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> &buffersThatCanBeFreedWithNop_0,
			const sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> &freeCount_2,
			const sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> &freeCount_1,
			const sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> &freeCount_0){
 
	//Put the parameters in arrays so it's easier to use it in a loop
	sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> buffersThatCanBeFreedWithNop[3] = {
		buffersThatCanBeFreedWithNop_0,buffersThatCanBeFreedWithNop_1,buffersThatCanBeFreedWithNop_2};
	sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> freeCount[3] = {freeCount_0,freeCount_1,freeCount_2};
 
	//If we decide to do a nop request
	bool doNopRequest = false;
 
 
	sc_bv<6> bufferFreedNopBuf;
	for(unsigned 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 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(
			//If we have 3 or more buffers that can be freed with the hypothesis that a nop was
			//just sent, always request nop : if the flow control is currently sending a nop, 
			//it will see another request immediately
			(freeCount[vc] > 4 && buffersThatCanBeFreedWithNop[vc] >= 3) ||
			//Same principle, but if we have less buffers free, we get more aggressive about
			//requesting that a nop be sent!
			(freeCount[vc] <= 4 && buffersThatCanBeFreedWithNop[vc] >= 2 ) || 
			(freeBuffers[vc].read() <= 2 && buffersThatCanBeFreedWithNop[vc] != 0)
		)
			doNopRequest = true;
	}
 
	//Output the results
 
	db_nop_req_fc = doNopRequest;
	nopRequested = doNopRequest || (nopRequested.read() && !fc_nop_sent.read());
 
 
}
 
//see .h for description
void databuffer_l2::doReset(){
	for(int vc = 0; vc < 3 ; vc++){
		for(int n = 0; n < DATABUFFER_NB_BUFFERS; n++){
			bufferFree[vc][n] = true;
		}
		freeBuffers[vc] = DATABUFFER_NB_BUFFERS;
		firstFreeBuffer[vc] = 0;
		bufferCount[vc] = 0;
	}
 
	for(int port = 0; port < 2; port++){
		currentlyReading[port] = false;
		currentReadVc[port] = VC_NONE;
		currentReadAddress[port] = 0;
		nbReadsInBufferDone[port] = 0;
	}
 
	nbWritesInBufferDone = 0;
	currentWriteBuffer = 0;
	currentWriteVC = 0;
 
	nopRequested = false;
	db_nop_req_fc = false;
 
	db_buffer_cnt_fc = 0;
 
	db_overflow_csr = false;
}
 
 
sc_uint<DATABUFFER_LOG2_NB_BUFFERS> databuffer_l2::priority_encoder(
		sc_bv<DATABUFFER_NB_BUFFERS> to_encode,	bool &found)
{
	sc_bv<DATABUFFER_NB_BUFFERS> v = to_encode;
	sc_bv<DATABUFFER_LOG2_NB_BUFFERS> output;
 
	output = 0;
	for(int n = 0; n < DATABUFFER_NB_BUFFERS; n++){
		if((sc_bit)v[n]) output = n;
	}
 
	found = (sc_bit)v[0];
	for(int n = 0; n < DATABUFFER_LOG2_NB_BUFFERS; n++){
		 found =  found || (sc_bit)output[n];
	}
 
	return output;
}
 
#ifdef SYSTEMC_SIM
void sc_trace(	sc_trace_file *tf, const databuffer_l2& v,
			const sc_string& NAME )
{
	sc_trace(tf,v.clk, /*NAME +*/ ".clk");
	sc_trace(tf,v.fc_nop_sent, /*NAME +*/ ".fc_nop_sent");
	sc_trace(tf,v.db_buffer_cnt_fc, /*NAME +*/ ".db_buffer_cnt_fc");
	sc_trace(tf,v.db_nop_req_fc, /*NAME +*/ ".db_nop_req_fc");
	sc_trace(tf,v.cd_getaddr_db, /*NAME +*/ ".cd_getaddr_db");
	sc_trace(tf,v.cd_write_db, /*NAME +*/ ".cd_write_db");
	sc_trace(tf,v.cd_datalen_db, /*NAME +*/ ".cd_datalen_db");
	sc_trace(tf,v.db_address_cd, /*NAME +*/ ".db_address_cd");
 
	sc_trace(tf,v.eh_erase_db, /*NAME +*/ ".eh_erase_db");
#ifdef RETRY_MODE_ENABLED
	sc_trace(tf,v.cd_drop_db, /*NAME +*/ ".cd_drop_db");
#endif
	sc_trace(tf,v.csr_read_db, /*NAME +*/ ".csr_read_db");
	sc_trace(tf,v.ui_read_db, /*NAME +*/ ".ui_read_db");
	sc_trace(tf,v.fwd_read_db, /*NAME +*/ ".fwd_read_db");
 
	sc_trace(tf,v.nbWritesInBufferDone, /*NAME +*/ ".nbWritesInVirtBufferDone");
 
	sc_trace(tf,v.fwd_erase_db, /*NAME +*/ ".fwd_erase_db");
	sc_trace(tf,v.nbReadsInBufferDone[0], /*NAME +*/ ".nbReadsInVirtBufferDone[0]");
	sc_trace(tf,v.bufferFree[0][0], /*NAME +*/ ".bufferFree0");
 
	sc_trace(tf,v.cd_data_db, /*NAME +*/ ".cd_data_db");
	sc_trace(tf,v.db_data_fwd, /*NAME +*/ ".db_data_fwd");
	sc_trace(tf,v.db_data_accepted, /*NAME +*/ ".db_data_accepted");
 
 
	sc_trace(tf,v.bufferCount[0], /*NAME +*/ ".bufferCount(0)");
 
}
#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.