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

Subversion Repositories ht_tunnel

[/] [ht_tunnel/] [trunk/] [rtl/] [systemc/] [databuffer_l2/] [databuffer_l2.h] - Rev 19

Compare with Previous | Blame | View Log

//databuffer_l2.h
 
/* ***** 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 ***** */
 
#ifndef HT_DATABUFFER_H
#define HT_DATABUFFER_H
 
#include "../core_synth/synth_datatypes.h"
#include "../core_synth/constants.h"
 
 
 
///Buffer to store HyperTransport data packets
/**
	The data buffer is, as it names states, a buffer for the data part
	of the packet.  When a command packet arrives that has data associated,
	the data needs to be stored somewhere while the command packet gets
	decoded, analyzed, stored and sent to the appropriate destination.  Once
	the command packet is sent to a destination (the CSR for example), the
	destination needs to retrieve the data associated with the packet.  There is
	two read ports (accepted and forward) and 3 erase ports (accepted, forward and
	error handler) plus 1 more erase port in retry mode (decoder).
 
	To allow this, when the command packet is received that has data associated, 
	the "Command decoder" requests a tracking number from the data buffer.
	Then the data starts flowing to the data buffer.  Later, the tracking number
	will allow to retrieve the data when requested by the destination of the
	command packet.The size of the data packet is contained in the command
	packet, so the destination must erase the packet.
 
	When there is a reset, all the registers tracking the content of the buffers
	and the buffer counts are cleared.  When all the content of a buffer has
	been read from a read port, that entry is also cleared.  Data packets can
	also simply be dropped from the decoder (in retry mode).
	The decoder can activate the drop signal to drop the packet currently being
	received : this can happen when a packet is stomped in retry mode.  Data packets
	can also simply be erased from the accepted and forward ports
 
 
	All read ports can  access the databuffer simultaneously, the data
	buffer requires a memory with two read ports and a write port.  In real life, it
	will probably be implemented using two one read port and one write port memory.
	A fast memory might be able to run at higher frequency than the logic.
	if running at 2x the speed of the logic, it could potentialy be done with
	a single one read and one write memory.
*/
class databuffer_l2 : public sc_module
{
	/**Give a number for ports to allow to treat all the ports 
	in for loops*/
	enum InputPorts{ ACCEPTED_PORT = 0, FWD_PORT = 1};
 
 
public:
	/// Global system cold reset signal.
	sc_in< bool >								resetx;
	/// LDTSTOP
	sc_in< bool >								ldtstopx;
	/// Global system clock signal.
	sc_in_clk		 							clk;
 
	/// Command Decoder data.
    sc_in< sc_bv<32> > 							cd_data_db;
	/// Command Decoder data length in dword.
	sc_in< sc_uint<4> > 						cd_datalen_db;
	/// Command Decoder virtual channel of the data
	sc_in< VirtualChannel >						cd_vctype_db;
	/// Command Decoder write request flag
	sc_in< bool > 								cd_write_db;
	/// Command Decoder flag for getting the address of the data
	/**
		This is the signal to start a transfert.  cd_datalen_db is 
		read when this signal is active.  Following the asertion of
		this signal for a single cycle, data can be sent with the use of
		cd_data_db and cd_write_db.
	*/
	sc_in< bool >								cd_getaddr_db;
 
#ifdef RETRY_MODE_ENABLED
	/// Command Decoder flag for erasing data
	sc_in< bool > 								cd_drop_db;
	///A retry disconnect is initiated by the link
	sc_in< bool > 								lk_initiate_retry_disconnect;
	///A retry disconnect is initiated by the command decoder
	sc_in< bool >								cd_initiate_retry_disconnect;
	///The retry mode is activated
	sc_in< bool >								csr_retry;
#endif
	/// Command Decoder return address of the sent data
	sc_out< sc_uint<BUFFERS_ADDRESS_WIDTH> >	db_address_cd;
 
	/// Error Handler address of the data to drop
	sc_in< sc_uint<BUFFERS_ADDRESS_WIDTH> >		eh_address_db;
	/// Error Handler virtual channel of the data to drop
	sc_in< VirtualChannel >						eh_vctype_db;
	/// Error Handler flag for erasing data
	sc_in< bool > 								eh_erase_db;
 
	/// CSR address of data to read
	sc_in< sc_uint<BUFFERS_ADDRESS_WIDTH> >		csr_address_db;
	/// CSR flag to read data
	sc_in< bool > 								csr_read_db;
	/// CSR virtual channel of data to read
	sc_in< VirtualChannel > 					csr_vctype_db;
	/// To erase the packet currently being read
	sc_in< bool >						csr_erase_db;
 
	/// User Interface address of data to read
	sc_in< sc_uint<BUFFERS_ADDRESS_WIDTH> >		ui_address_db;
	/// User Interface flag to read data
	sc_in< bool > 								ui_read_db;
	/// User Interface virtual channel of data to read
	sc_in< VirtualChannel >						ui_vctype_db;
	/// To erase the packet currently being read
	sc_in< bool >						ui_erase_db;
 
	/// Data for the accepted destination (shared CSR and UI output)
	/// The output is selected by the ui_grant_csr_access_db signal
	sc_out< sc_bv<32> >							db_data_accepted;
 
	/// Forward address of data to read
	sc_in< sc_uint<BUFFERS_ADDRESS_WIDTH> >		fwd_address_db;
	/// Forward flag to read data
	sc_in< bool > 								fwd_read_db;
	/// Forward virtual channel of data to read
	sc_in< VirtualChannel >						fwd_vctype_db;
	/// Forward return data 
	sc_out< sc_bv<32> >							db_data_fwd;
	/// Forward return flag meaning the last data forming the packet
	sc_in< bool >								fwd_erase_db;
 
	/// Flow Control flag meaning a NOP packet was sent
	/**
		Signal activated when db_buffer_cnt_fc is being read.  Should
		probably read fc_sending_nop instead as it is not activated after
		the nop is sent.
	*/
	sc_in< bool >								fc_nop_sent;
	/// Flow Control return free buffers counters since last NOP request
	/// [5,4]: nonposted;  [3,2]: response. [1,0]: posted;
	sc_out< sc_bv<6> >							db_buffer_cnt_fc;
	/// Flow Control return flag for a request of a NOP packet.
	sc_out< bool >								db_nop_req_fc;
	///Activated when we receive more data than we can store
	sc_out< bool >								db_overflow_csr;
 
	//By default, the accepted port is for the UI.  When the UI grants the right
	//of access to the CSR, it becomes the CSR's right.  The grant signal is read
	//to know what data to output.
	sc_in<bool> ui_grant_csr_access_db;
 
 
 
	////////////////////////////////////
	//Interface to memory - synchronous
	////////////////////////////////////
 
	sc_out<bool> memory_write;///<Write signal for databuffer memory
	sc_out<sc_uint<2> > memory_write_address_vc;///<MSB address where to write in databuffer memory (values 0 to 2)
	sc_out<sc_uint<BUFFERS_ADDRESS_WIDTH> > 
		memory_write_address_buffer;///< Center address for where to write in databuffer memory
	sc_out<sc_uint<4> > memory_write_address_pos;///<LSB address where to write in databuffer memory
	sc_out<sc_bv<32> > memory_write_data;///<Data to write in databuffer memory
 
	sc_out<sc_uint<2> > memory_read_address_vc[2];///<MSB address where to read in databuffer memory (values 0 to 2)
	sc_out<sc_uint<BUFFERS_ADDRESS_WIDTH> >
		memory_read_address_buffer[2];///< Center address for where to read in databuffer memory
	sc_out<sc_uint<4> > memory_read_address_pos[2];///<LSB address where to write in databuffer memory
 
	sc_in<sc_bv<32> > memory_output[2];///<Data output from read in databuffer memory
 
 
 
	//Virtual channel that we will be outputed
	sc_signal<sc_uint<2> > outputReadVcIndex_s[2];
	//Virtual buffer that we will be outputed
	sc_signal<sc_uint<BUFFERS_ADDRESS_WIDTH> > outputReadAddress_s[2];
 
	///////////////////////////////////////
	//Global variables read on clock edge
	///////////////////////////////////////
 
 
public:	
	/// Constructor of the module
	/**
		Constructor of a Data Buffer module.
 
		@param name Name of the module
	*/
	databuffer_l2( sc_module_name name);
 
	///SystemC macro fror modules
	SC_HAS_PROCESS(databuffer_l2);
 
	///Handles registered operations and outputs of the module
	void clockProcess();
	///Takes care of writing to the memory
	void write_memory();
	///Takes care of reading in the memory
	void read_memory();
	///Redirects the memories output to the output of the module
	void redirect_memory_output();
 
 
	/** The number of buffers freed for all the VC's is kept in
		bufferFreedNop.  This function is simply a mux that selects
		the bits correspondif to the correct VC.
	*/
	sc_uint<2> getBufferFreedNop(const VirtualChannel  &vc);
 
	///Determine when to sent 
	/** Taking into account how many buffers could be freed with a nop and how many
		buffers are free currently, it determines if there is need to send a nop to
		notify that the buffers have been freed.
 
		This algorithm prevents the link from being flooded with NOPs every
		time a buffer is freed.
 
		@param buffersThatCanBeFreedWithNop_0 The number of buffers that that we can notify
			as being free with a nop for the vc 0
		@param buffersThatCanBeFreedWithNop_1 The number of buffers that that we can notify
			as being free with a nop for the vc 1
		@param buffersThatCanBeFreedWithNop_2 The number of buffers that that we can notify
			as being free with a nop for the vc 2
		@param freeBuffers_0 The number of free buffers in the VC 0
		@param freeBuffers_1 The number of free buffers in the VC 1
		@param freeBuffers_2 The number of free buffers in the VC 2
	*/
	void outputNopRequest(	
		const sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> &buffersThatCanBeFreedWithNop_0,
		const sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> &buffersThatCanBeFreedWithNop_1,
		const sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> &buffersThatCanBeFreedWithNop_2,
		const sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> &freeBuffers_0,
		const sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> &freeBuffers_1,
		const sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> &freeBuffers_2);
 
	///Resets the databuffer to an initial starting state
	void doReset();
 
	///Process which outputs the tag number for a buffer requested by the decoder
	/**
		The process is asynchronous to respond immediately to the decoder when it requests
		a buffer number for a specific VirtualChannel.  Actually, the next buffer number
		for every VC is chosen synchronously, so this process is just a mux of the values
		selected with the VC sent by the decoder
	*/
	void sendAddressToCommandDecoder();
 
	///A priority encode
	/**
		@description Takes a vector at the input and outputs the positition of the highest bit
			to have the value of 1.
		@param to_encode The vector to encode
		@param found Return value by reference : if there was a value found to encode.  It is false
			is the vector is 0
		@return The encoded value
	*/
	sc_uint<DATABUFFER_LOG2_NB_BUFFERS> priority_encoder(
		sc_bv<DATABUFFER_NB_BUFFERS> to_encode,	bool &found);
 
	///Tree of or that modifies the input vector
	/**
		@description Takes a vector at the input and modifies it so that if a bit in a vector
			is 1, all lower bits also become 1's.  ie: 00100 becomes 00111, 01010 becomes 01111
		@param or_modify The vector to modify
	*/
	void or_tree_modify(sc_bv<DATABUFFER_NB_BUFFERS> *or_modify);
 
//private:
 
	///Internal count of the number of buffers free as seen from the next HT node
	/**
		Used to find out how many buffers to notify as free on the nops.  At reset,
		it is 0.  If we have more free buffers than the bufferCount, it means that
		we can notify that we have freed buffers.
 
		The count goes up by 0-3 when we send a nop (the value carried on the nop)
		The count goes down by 1 when we receive a data packet
	*/
	sc_signal<sc_uint<DATABUFFER_LOG2_NB_BUFFERS+1> >				bufferCount[3];
 
	///If the buffer is free
	sc_signal<bool >												bufferFree[3][DATABUFFER_NB_BUFFERS];
 
	///The first buffer which is free in every VC
	sc_signal<sc_uint<DATABUFFER_LOG2_NB_BUFFERS> >			firstFreeBuffer[3];
 
	/**
		The number of writes done in the current buffer.  Used to know
		when to switch to a new virtual buffer.
	*/
	sc_signal<sc_uint<4> >	nbWritesInBufferDone;
 
	/**
		The current buffer we are currently writing in
	*/
	sc_signal<sc_uint<DATABUFFER_LOG2_NB_BUFFERS> >			currentWriteBuffer;
	/**
		The current virtual channel we are currently writing in
	*/
	sc_signal<VirtualChannel>										currentWriteVC;
 
	/**
		If we are currently reading from the 2 read ports.  Once read has begun, the
		currentReadVc and currentReadAddress are fixed until the buffer is finished reading
	*/
	sc_signal<bool>													currentlyReading[2];
 
	/**
		If we are currently reading, the virtual channel being read for every read port.
	*/
	sc_signal<VirtualChannel>									currentReadVc[2];
	/**
		If we are currently reading, the address being read for every read port.
	*/
	sc_signal<sc_uint<DATABUFFER_LOG2_NB_BUFFERS> >			currentReadAddress[2];
	/**
		If we are currently reading, the number of reads done in the current virtual buffer
	*/
	sc_signal<sc_uint<4> >	nbReadsInBufferDone[2];
 
	///Keeps track if a nop was already requested
	sc_signal<bool >												nopRequested;
 
	//The number of VIRTUAL buffers that are free for each VC
	sc_signal<sc_uint<DATABUFFER_LOG2_NB_BUFFERS + 1> > freeBuffers[3];
};
 
 
#ifdef SYSTEMC_SIM
void sc_trace(	sc_trace_file *tf, const databuffer_l2& v,
			const sc_string& NAME );
#endif
 
#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.