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

Subversion Repositories ht_tunnel

[/] [ht_tunnel/] [trunk/] [bench/] [reordering_l2/] [reordering_l2_tb.cpp] - Rev 21

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

//reordering_l2_tb.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>
 *
 * 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 "reordering_l2_tb.h"
 
using namespace std;
 
reordering_l2_tb::reordering_l2_tb(sc_module_name name){
	SC_THREAD(simulate);
	sensitive_pos(clk);
 
	SC_METHOD(consume_data);
	sensitive << ro_available_csr << ro_available_ui << ro_available_fwd;
	sensitive << read_csr << read_fwd << read_ui;
 
	SC_METHOD(manage_memories);
	sensitive_pos << clk;
 
	srand(7941);
 
}
 
void reordering_l2_tb::simulate(){
	//Start with a reset
	resetx = false;
 
	//Randomly set par addresses
	sc_uint<40> tmp_40b[NbRegsBars];
	for(int n = 0; n < NbRegsBars; n++){
		//Generate a random 40-bit vector
		tmp_40b[n].range(14,0) = sc_uint<32>(rand()).range(14,0);
		tmp_40b[n].range(29,15) = sc_uint<32>(rand()).range(14,0);
		tmp_40b[n].range(39,30) = sc_uint<32>(rand()).range(9,0);
	}
 
	//Lower part of bar is zero, set the random part to zero
	tmp_40b[0].range(Header_BarSlotHarwireSize0_m1,0) = 0;
	if(NbRegsBars > 0) tmp_40b[1].range(Header_BarSlotHarwireSize1_m1,0) = 0;
	if(NbRegsBars > 1) tmp_40b[2].range(Header_BarSlotHarwireSize2_m1,0) = 0;
	if(NbRegsBars > 2) tmp_40b[3].range(Header_BarSlotHarwireSize3_m1,0) = 0;
	if(NbRegsBars > 3) tmp_40b[4].range(Header_BarSlotHarwireSize4_m1,0) = 0;
	if(NbRegsBars > 4) tmp_40b[5].range(Header_BarSlotHarwireSize5_m1,0) = 0;
 
	for(int n = 0; n < NbRegsBars; n++){
		//Set the bar address
		csr_bar[n] = tmp_40b[n];
	}
	//Choose a random unitID for this node
	csr_unit_id = (sc_uint<5>)sc_uint<32>(rand()).range(4,0);
 
	//////////////////////////////////////////////
	// Set some initial values
	//////////////////////////////////////////////	
 
	csr_ack_ro = false;
	ui_ack_ro = false;	
	fwd_ack_ro = false;
	eh_ack_ro = false;
 
	fc_nop_sent = true;
 
	cd_available_ro = false;
 
	cd_data_pending_ro = false;
 
	csr_memory_space_enable = true;
	csr_io_space_enable = true;
 
	csr_direct_route_enable = true;
	csr_sync = false;
 
	//csr_clumping_configuration = "00000000111000000000000000000000";
	/**ID's 20 to 23 are clumped together*/
	for(int n = 0; n < 32; n++)
		clumped_unit_id[n] = n;
	clumped_unit_id[21] = 20;
	clumped_unit_id[22] = 20;
	clumped_unit_id[23] = 20;
 
    //The unitID's that have directRoute enabled
	csr_direct_route_enable =    "00000000000000000000000000000000";
 
#ifdef ENABLE_REORDERING
	csr_unitid_reorder_disable = false;
#endif
	fwd_next_node_buffer_status_ro = "111111";
 
 
#ifdef RETRY_MODE_ENABLED
	lk_rx_connected = true;
	csr_retry = false;
#endif
 
	//Hold reset for a some cycles
	for(int n = 0; n < 3; n++)
		wait();
 
	//Stop reset
	resetx = true;
 
	//A temporary packet variable to reuse
	ReorderTBPacket tb_pkt;
 
	/////////////////////////////////////////
	// Send Misc packets, no reordering
	// Test one VC at the time
	// This tests the proper operation of the entrance reordering
	// dans the buffers when not being reordered
	/////////////////////////////////////////
	fc_nop_sent = true;
	cd_data_pending_ro = false;
	cout << "Begin test: Send Misc packets, no reordering" << endl;
 
	for(int vc = 0; vc < 3; vc++){
		cout << "Begin test for vc: " << vc << endl;
 
		int packet_to_send = 25;
		int packets_received = 0;
 
		int idle_counter = 0;
 
		while(packets_received != 25){
 
			////////////////////////////////////////////
			// Read reordering output
			////////////////////////////////////////////
 
			//Make sure we don't fall in an infinite loop
			if(!ro_available_csr.read() &&
				!ro_available_ui.read() &&
				!ro_available_fwd.read() && 
				!packet_sent.empty())
			{
				idle_counter++;
				if(idle_counter > 10){
					cout << "ERROR: No packets are being received!" << endl;
					return;
				}
			}
			else{
				idle_counter = 0;
			}
 
			//80% chance of reading from the many destination
			read_csr = (rand() % 10) < 8;
			read_fwd = (rand() % 10) < 8;
			read_ui = (rand() % 10) < 8;
 
			//Find the first packet in the list of packets 
			//Start by creating an iterator
			deque<ReorderTBPacket>::iterator first_accepted = packet_sent.begin();
			bool found_accepted = false;
			//loop over all elements until an accepted is found
			while(first_accepted != packet_sent.end()){
				if(first_accepted->accepted){
					found_accepted = true;
					break;
				}
				first_accepted++;
			}
 
			//Accepted packet can only be sent to one destination, CSR or UI
			if(ui_ack_ro.read() && csr_ack_ro.read()){
				cout << "ERROR: Packets sent to UI and CSR simulaneoulsy" << endl;
				return;					
			}
 
			//If CSR acks a packet
			if(csr_ack_ro.read()){
				//Check if there is a packet to send
				if(packet_sent.size() == 0 || !found_accepted){
					cout << "ERROR: Packet available when none in buffers..." << endl;
					return;					
				}
				//If not the correct packet, display an error 
				if(ro_packet_csr.read().packet != first_accepted->pkt.packet 
					|| ! first_accepted->csr)
				{
					cout << "ERROR: Packet sent to CSR by error" << endl;
					return;					
				}
				//If correct, remove from queue
				else{
					packet_sent.erase(first_accepted);
					packets_received++;
				}
 
			}
			//If UI acks 
			if(ui_ack_ro.read()){
				//Check if there was a packet to sent
				if(packet_sent.size() == 0 || !found_accepted){
					cout << "ERROR: Packet available when none in buffers..." << endl;
					return;					
				}
				//If not the correct packet, display an error 
				if(ro_packet_ui.read().packet != first_accepted->pkt.packet 
					|| first_accepted->csr)
				{
					cout << "ERROR: Packet sent to UI by error, " << 
						ro_packet_ui.read().packet.to_string(SC_HEX) << endl;
					cout << "   expected: " << 
						first_accepted->pkt.packet.to_string(SC_HEX) << endl;
					resetx = false;
					return;					
				}
				else{
					//If the packet must also go to forward (like for a broadcast), just
					//erase the fact that it must go to accepted
					if(first_accepted->forward) first_accepted->accepted = false;
					//Otherwise, erase the packet
					else{
						packet_sent.erase(first_accepted);
						packets_received++;
					}
 
				}
			}
 
			//Find the first packet for the forward destination in the list of packet sent
			deque<ReorderTBPacket>::iterator first_forward = packet_sent.begin();;
			bool found_forward = false;
			while(first_forward != packet_sent.end()){
				if(first_forward->forward){
					found_forward = true;
					break;
				}
				first_forward++;
			}
 
 
			//If packet is acked
			if(fwd_ack_ro.read()){
				//Check that there is a packet to ack
				if(packet_sent.size() == 0 || !found_forward){
					cout << "ERROR: Packet available when none in buffers..." << endl;
					return;					
				}
				//If it is not the correct packet, display error
				if(ro_packet_fwd.read().packet != first_forward->pkt.packet)
				{
					cout << "ERROR: Packet sent to FWD by error, " << 
						ro_packet_fwd.read().packet.to_string(SC_HEX) << 
						" expected: " << first_forward->pkt.packet.to_string(SC_HEX) << endl;
					return;					
				}
				else{
					//If the packet must also go to accepted (like for a broadcast), just
					//erase the fact that it must go to forward
					if(first_forward->accepted) first_forward->forward = false;
					//Otherwise, erase the packet
					else{
						packet_sent.erase(first_forward);
						packets_received++;
					}
				}
 
			}
 
			////////////////////////////////////////////
			// Send packets
			////////////////////////////////////////////
 
			//80% chance of sending packet
			bool send = (rand() % 10) < 8;
 
			//If there is room in buffers, we still have packet to send (from the initial
			//number that was set and we want to send
			if(packet_sent.size() < NB_OF_BUFFERS && packet_to_send > 0 && send){
				if(vc == VC_POSTED){
					generate_random_posted_pkt(tb_pkt,POSTED_ANY);
					//Make sure  passpw = false
					tb_pkt.pkt.packet[15] = false;
				}
				else if(vc == VC_NON_POSTED){
					generate_random_nposted_pkt(tb_pkt,NPOSTED_ANY);
					//Make sure  passpw = false
					tb_pkt.pkt.packet[15] = false;
				}
				else{
					generate_random_response_pkt(tb_pkt,RESPONSE_ANY);
					//Make sure  passpw = false
					tb_pkt.pkt.packet[15] = false;
				}
 
				cd_available_ro = true;
				cd_packet_ro = tb_pkt.pkt;
				packet_to_send--;
				packet_sent.push_back(tb_pkt);
			}
			else{
				cd_available_ro = false;
			}
			wait();
		}
		cout << "Test done for vc: " << vc << endl;
	}
 
	cout << "Test successful" << endl << endl;
 
	/////////////////////////////////////////
	// Send Misc packets, reordering
	/////////////////////////////////////////
 
	/**
		The previous tests sent completely random packets and checked
		that they were still in order and correct.  For the reordering,
		it is not so easy, so this sends a series of pre-defined
		vectors and makes sure they are received in the also pre-defined
		correct order.
 
		Only send packets for the forward destination to simplify tests.
	*/
 
	wait();
 
	cout << "Begin packet reordering test"<< endl;
 
	read_csr = false;
	read_fwd = false;
	read_ui = false;
 
	//There are 4 tests to make
	deque<ReorderTBPacket> to_send[4];
	deque<ReorderTBPacket> to_receive[4];
 
	//Test 1 & 2 - passPW and sequence for posted and non-posted
	//Create a bunch of packets alternating passPW = true and false
	tb_pkt.pkt.isPartOfChain = false;
	tb_pkt.pkt.data_address = sc_uint<32>(rand()).range(BUFFERS_ADDRESS_WIDTH-1,0);
	tb_pkt.accepted = false;
	tb_pkt.forward = true;
	tb_pkt.pkt.error64BitExtension = false;
 
	for(int n = 0; n < 8; n++){
		generate_random_forward_posted_pkt(tb_pkt.pkt.packet,false);
		tb_pkt.pkt.packet[15] = n % 2 || n == 0;
		to_send[0].push_back(tb_pkt);
		generate_random_forward_nposted_pkt(tb_pkt.pkt.packet);
		tb_pkt.pkt.packet[15] = n % 2 || n == 0;
		to_send[1].push_back(tb_pkt);
	}
 
	//Insert a sequence in the packets, also testing unitID clumping
	for(int n = 3; n < 6; n++){
		to_send[0][n].pkt.packet.range(7,6) = "01";
		to_send[0][n].pkt.packet.range(14,10) = "10101";
		//Different unitID, but same clumped UnitID
		to_send[0][n].pkt.packet.range(9,8) = sc_uint<2>(n-3);
		to_send[1][n].pkt.packet.range(7,6) = "01";
		to_send[1][n].pkt.packet.range(14,10) = "10101";
		//Different unitID, but same clumped UnitID
		to_send[1][n].pkt.packet.range(9,8) = sc_uint<2>(n-3);
	}
 
	//Generate the order which the packet should be received
	to_receive[0].push_back(to_send[0][0]);
	to_receive[1].push_back(to_send[1][0]);
	to_receive[0].push_back(to_send[0][1]);
	to_receive[1].push_back(to_send[1][1]);
	to_receive[0].push_back(to_send[0][3]);
	to_receive[1].push_back(to_send[1][3]);
	to_receive[0].push_back(to_send[0][2]);
	to_receive[1].push_back(to_send[1][2]);
	to_receive[0].push_back(to_send[0][4]);
	to_receive[1].push_back(to_send[1][4]);
	to_receive[0].push_back(to_send[0][5]);
	to_receive[1].push_back(to_send[1][5]);
	to_receive[0].push_back(to_send[0][7]);
	to_receive[1].push_back(to_send[1][7]);
	to_receive[0].push_back(to_send[0][6]);
	to_receive[1].push_back(to_send[1][6]);
 
	//Test 3 - posted chains
	//Create a bunch of packets alternating passPW = true and false
	for(int n = 0; n < 8; n++){
		generate_random_forward_posted_pkt(tb_pkt.pkt.packet,n == 4 || n==5);
		tb_pkt.pkt.packet[15] = n % 2 || n == 0;
		to_send[2].push_back(tb_pkt);
	}
 
	//Generate the order which the packet should be received
	to_receive[2].push_back(to_send[2][0]);
	to_receive[2].push_back(to_send[2][1]);
	to_receive[2].push_back(to_send[2][3]);
	to_receive[2].push_back(to_send[2][2]);
	to_receive[2].push_back(to_send[2][4]);
	to_receive[2].push_back(to_send[2][5]);
	to_receive[2].push_back(to_send[2][6]);
	to_receive[2].push_back(to_send[2][7]);
 
	//Test 4 - PassPW responses
	//Create a bunch of responses with different passPW values
	for(int n = 0; n < 8; n++){
		generate_random_forward_response_pkt(tb_pkt.pkt.packet);
		tb_pkt.pkt.packet[15] = (n == 0 || n == 1 || n == 4 || n == 5 || n == 7);
		to_send[3].push_back(tb_pkt);
	}
	to_receive[3].push_back(to_send[3][0]);
	to_receive[3].push_back(to_send[3][1]);
	to_receive[3].push_back(to_send[3][4]);
	to_receive[3].push_back(to_send[3][5]);
	to_receive[3].push_back(to_send[3][7]);
	to_receive[3].push_back(to_send[3][2]);
	to_receive[3].push_back(to_send[3][3]);
	to_receive[3].push_back(to_send[3][6]);
 
	//Run through the 4 tests
	for(int test = 0; test < 4; test++){
		//Send packets until they are all sent
		while(!to_send[test].empty()){
			cd_available_ro = true;
			cd_packet_ro = to_send[test].front().pkt;
			to_send[test].pop_front();
			wait();
		}
		cd_available_ro = false;
 
		//Wait for packets to reorganize
		for(int n = 0; n < 16; n++) wait();
 
		int idle = 0;
 
		//until all packet are ceived
		while(!to_receive[test].empty()){
			//80% chance of reading the packet if available
			read_fwd = (rand() % 10) < 8;
			//If it is acked
			if(fwd_ack_ro.read()){
				idle = 0;
				//display error if not the correct packet received
				if(ro_packet_fwd.read().packet != 
					to_receive[test].front().pkt.packet)
				{
					cout << "ERROR in reordering test: " << test << endl
						 << "    Received: " << ro_packet_fwd.read().packet.to_string(SC_HEX)
						 << " Expected: " << to_receive[test].front().pkt.packet.to_string(SC_HEX)
						 << endl;
					return;
				}
				to_receive[test].pop_front();
			}
			else{
				//If read is active but no packet available, increment an idle counter to make
				//sure the reordering doesn't just sit idle until the end of the simulation
				if(read_fwd.read()){
					idle++;
				}
				if(idle > 5){
					cout << "ERROR: reordering idle for too long in test: " << test << endl;
					return;
				}
			}
			wait();
		}
		read_fwd = false;
	}
	cout << "Test successful" << endl << endl;
 
	/////////////////////////////////////////
	// Test data packet not commited before
	// completely received
	/////////////////////////////////////////
	cout << "Test waiting for data to be commited"<< endl;
	cd_data_pending_ro = true;
	sc_uint<BUFFERS_ADDRESS_WIDTH> pending_addr = rand() % DATABUFFER_NB_BUFFERS;
	cd_data_pending_addr_ro = pending_addr;
	generate_random_posted_pkt(tb_pkt,POSTED_FORWARD);
	generate_random_64b_vector(tb_pkt.pkt.packet);
	//Posted write, not configured in BARs
	tb_pkt.pkt.packet.range(5,3) = "101";
 
	sc_bv<40> addr;
	generate_random_not_bar_address(addr);
	tb_pkt.pkt.packet.range(63,25) = addr.range(39,2);
 
	tb_pkt.pkt.data_address = pending_addr;
 
	cd_available_ro = true;
	cd_packet_ro = tb_pkt.pkt;
	read_ui = false;	
	wait();
	cd_available_ro = false;
 
	for(int n = 0; n <5; n++){
		if(ro_available_fwd.read()){
			cout << "ERROR: Packet sent out even if data not fully commited"<< endl;
			return;
		}
		wait();
	}
 
	cd_data_pending_addr_ro = pending_addr + 1;
 
	bool received = false;
	read_ui = true;	
	for(int n = 5; !received; n--){
		if(ro_available_fwd.read()) received = true;
		if(n == 0){
			cout << "ERROR: Packet not sent out even if data fully commited"<< endl;
			return;
		}
		wait();
	}
	read_ui = false;	
	cout << "Test successful" << endl << endl;
 
	/////////////////////////////////////////
	// Test directroute
	/////////////////////////////////////////
 
	cout << "Test DirectRoute" << endl ;
 
	csr_direct_route_enable =    "00000000000001110000000000000000";
 
	generate_random_64b_vector(tb_pkt.pkt.packet);
	//Write to bar address
	int bar = rand() % NbRegsBars;
	tb_pkt.pkt.packet.range(5,3) = "101";
	tb_pkt.pkt.packet.range(63,63-Header_BarLength[bar] + 1) = 
		csr_bar[bar].read().range(39,Header_BarSlotSize[bar]);
	//Don't want compat on
	tb_pkt.pkt.packet[21] = 0;
	//make it from 
	tb_pkt.pkt.packet.range(12,8) = sc_uint<5>(17);
	//adjust if chain
	tb_pkt.pkt.packet[19] = false;
	tb_pkt.pkt.error64BitExtension = false;
 
	cd_available_ro = true;
	cd_packet_ro = tb_pkt.pkt;
	read_ui = false;	
	wait();
	cd_available_ro = false;
 
	received = false;
	read_ui = true;	
	for(int n = 5; !received; n--){
		if(ro_available_ui.read()) received = true;
		if(n == 0){
			cout << "ERROR: Packet not correctly directrouted to UI: "
				<< tb_pkt.pkt.packet.to_string(SC_HEX) << endl;
			return;
		}
		wait();
	}
	read_ui = false;	
	csr_direct_route_enable =    "00000000000000000000000000000000";
 
	cout << "Test successful" << endl << endl;
 
 
 
	/////////////////////////////////////////
	// Test overflow
	/////////////////////////////////////////
 
	cout << "Test overflow" << endl;
 
	generate_random_posted_pkt(tb_pkt,POSTED_ANY);
	cd_packet_ro = tb_pkt.pkt;
	read_ui = false;	
	read_fwd = false;	
	read_csr = false;	
	for(int n = 0; n < 9; n++){
		cd_available_ro = true;
		wait();
	}
 
	for(int n = 0; n <3; n++){
		if(ro_overflow_csr.read()){
			cout << "Buffer overflow activated without real overflow" << endl;
			return;
		}
	}
	cd_available_ro = true;
	wait();
	cd_available_ro = false;
 
	bool got_overflow = false;
	for(int n = 0; !got_overflow; n++){
		if(ro_overflow_csr.read()){
			got_overflow = true;
		}
		if(n > 3){
			cout << "Buffer overflow not activated with real overflow" << endl;
			return;
		}
	}
	cout << "Test successful" << endl << endl;
 
	/////////////////////////////////////////
	// Test buffer count features
	/////////////////////////////////////////
 
	resetx = false;
	for(int n = 0; n <3; n++) wait();
	resetx = true;
 
	/////////////////////////////////////////
	// Test clearing buffer status in retry mode
	/////////////////////////////////////////
 
	/////////////////////////////////////////
	// Test disabling reordering
	/////////////////////////////////////////
 
	//not done
 
	/////////////////////////////////////////
	// Test io and memory space enable
	/////////////////////////////////////////
 
	//not done
 
	/////////////////////////////////////////
	// Send the three types (p,np,r)
	/////////////////////////////////////////
 
	//not done
 
}
 
void reordering_l2_tb::consume_data(){
	csr_ack_ro = ro_available_csr.read() && read_csr.read();
	ui_ack_ro = ro_available_ui.read() && read_ui.read();	
	fwd_ack_ro = ro_available_fwd.read() && read_fwd.read();
}
 
 
void reordering_l2_tb::generate_random_posted_pkt(ReorderTBPacket &tb_pkt,
												 PostedType posted_type){
	tb_pkt.csr = false;
 
	switch(posted_type){
	case POSTED_ACCEPTED:
		tb_pkt.csr = generate_random_accepted_posted_pkt(tb_pkt.pkt.packet,false);
		tb_pkt.accepted = true;
		tb_pkt.forward = false;
		tb_pkt.pkt.error64BitExtension = false;
		break;
	case POSTED_FORWARD:
		generate_random_forward_posted_pkt(tb_pkt.pkt.packet,false);
		tb_pkt.accepted = false;
		tb_pkt.forward = true;
		tb_pkt.pkt.error64BitExtension = rand() % 2;
		break;
	default:
		int type = rand()%3;
		if(type == 0){
			tb_pkt.csr = generate_random_accepted_posted_pkt(tb_pkt.pkt.packet,false);
			tb_pkt.accepted = true;
			tb_pkt.forward = false;
			tb_pkt.pkt.error64BitExtension = false;
		}
		else if(type == 1){
			generate_random_forward_posted_pkt(tb_pkt.pkt.packet,false);
			tb_pkt.accepted = false;
			tb_pkt.forward = true;
			tb_pkt.pkt.error64BitExtension = rand() % 2;
		}
		else{
			generate_random_broadcast_posted_pkt(tb_pkt.pkt.packet);
			tb_pkt.accepted = true;
			tb_pkt.forward = true;
			tb_pkt.pkt.error64BitExtension = false;
		}
	}
 
	tb_pkt.pkt.isPartOfChain = false;
	tb_pkt.pkt.data_address = sc_uint<32>(rand()).range(BUFFERS_ADDRESS_WIDTH-1,0);
}
 
bool reordering_l2_tb::generate_random_accepted_posted_pkt(sc_bv<64> &pkt, 
														  bool chain){
	//Randomly generate a 64-bit packet
	generate_random_64b_vector(pkt);
	//Now, we'll choose where the packet goes and set some of the bits accordingly
	//Choose a type randomly :
	// 0 : goes to CSR
	// 1 : goes to user (normal traffic)
	// 2 : goes to user (device message)
	int type = rand() % 3;
 
	//If in the middle of the chain
	if(curently_sending_chain){
		//Set the new value depending on if a chain packet is selected
		curently_sending_chain = chain;
		//Set same type as before
		if(chain_destination = POSTED_DESTINATION_CSR) type = 0;
		else if(chain_destination = POSTED_DESTINATION_USER) type = 1;
		else type = 2;
	}
	else if(chain){
		if(type == 0) chain_destination = POSTED_DESTINATION_CSR;
		else if(type == 1) chain_destination = POSTED_DESTINATION_USER;
		else chain_destination = POSTED_DESTINATION_USER_DEVICE_MSG;
	}
 
	//Go to CSR if the type is 0
	int csr = type == 0;
 
	pkt.range(5,3) = "101";
	if(type == 0){
		//CSR write
		pkt.range(63,48) = 
			"1111110111111110";
		pkt.range(39,35) = csr_unit_id.read();
	}
	else if(type == 1 || chain){
		//Write to bar address
		int bar = rand() % NbRegsBars;
		pkt.range(63,63-Header_BarLength[bar] + 1) = 
			csr_bar[bar].read().range(39,Header_BarSlotSize[bar]);
 
	}
	else{
		//Device message
		pkt.range(63,52) = 
			"111111100000";
		pkt.range(39,35) = csr_unit_id.read();
		pkt[2] = true;//always byte
	}
	//Don't want compat on
	pkt[21] = 0;
	//make it downstream
	pkt.range(12,8) = 0;
	//adjust if chain
	pkt[19] = chain;
	return csr;
}
 
void reordering_l2_tb::generate_random_forward_posted_pkt(sc_bv<64> &pkt, bool chain){
	generate_random_64b_vector(pkt);
	int type = rand()%2;
	if(type || chain){
		//Posted write, not configured in BARs
		pkt.range(5,3) = "101";
 
		sc_bv<40> addr;
		generate_random_not_bar_address(addr);
		pkt.range(63,25) = addr.range(39,2);
 
	}
	else{
		//Posted fence
		pkt.range(5,0) = "111100";
	}
	pkt[19] = chain;
}
 
void reordering_l2_tb::generate_random_broadcast_posted_pkt(sc_bv<64> &pkt){
	generate_random_64b_vector(pkt);
	pkt.range(5,0) = "111010";
}
 
void reordering_l2_tb::generate_random_64b_vector(sc_bv<64> &pkt){
	sc_uint<32> r;
	for(int n = 0; n < 4;n++){
		r = rand();
		pkt(15*(n+1)-1,15*n) = sc_uint<32>(rand()).range(14,0);
	}
	r = rand();
	pkt(63,60) = sc_uint<32>(rand()).range(3,0);
}
 
bool reordering_l2_tb::generate_random_accepted_nposted_pkt(sc_bv<64> &pkt){
	generate_random_64b_vector(pkt);
	int type = rand() % 3;
	int csr = rand() % 2;
 
	if(type == 0){
		//Non posted write
		pkt.range(5,3) = "001";
	}
	else if(type == 1){
		//Read
		pkt.range(5,4) = "01";
	}
	else{
		//Atomic
		pkt.range(5,0) = "0111101";
	}
	//Don't want compat on
	pkt[21] = 0;
	//make it downstream
	pkt.range(12,8) = 0;
 
	//If CSR, adjust address
	if(csr){
		pkt.range(63,48) = 
			"1111110111111110";
		pkt.range(39,35) = csr_unit_id.read();
	}
	else{
		int bar = rand() % NbRegsBars;
		pkt.range(63,63-Header_BarLength[bar] + 1) = 
			csr_bar[bar].read().range(39,Header_BarSlotSize[bar]);
	}
	return csr;
}
 
void reordering_l2_tb::generate_random_nposted_pkt(ReorderTBPacket &tb_pkt,
												 NPostedType nposted_type){
	tb_pkt.csr = false;
 
	switch(nposted_type){
	case NPOSTED_ACCEPTED:
		tb_pkt.csr = generate_random_accepted_nposted_pkt(tb_pkt.pkt.packet);
		tb_pkt.accepted = true;
		tb_pkt.forward = false;
		tb_pkt.pkt.error64BitExtension = false;
		break;
	case NPOSTED_FORWARD:
		generate_random_forward_nposted_pkt(tb_pkt.pkt.packet);
		tb_pkt.accepted = false;
		tb_pkt.forward = true;
		tb_pkt.pkt.error64BitExtension = rand() % 2;
		break;
	default:
		int type = rand()%2;
		if(type == 0){
			tb_pkt.csr = generate_random_accepted_nposted_pkt(tb_pkt.pkt.packet);
			tb_pkt.accepted = true;
			tb_pkt.forward = false;
			tb_pkt.pkt.error64BitExtension = false;
		}
		else{
			generate_random_forward_nposted_pkt(tb_pkt.pkt.packet);
			tb_pkt.accepted = false;
			tb_pkt.forward = true;
			tb_pkt.pkt.error64BitExtension = rand() % 2;
		}
	}
 
	tb_pkt.pkt.isPartOfChain = false;
	tb_pkt.pkt.data_address = sc_uint<32>(rand()).range(BUFFERS_ADDRESS_WIDTH-1,0);
}
 
void reordering_l2_tb::generate_random_forward_nposted_pkt(sc_bv<64> &pkt){
	generate_random_64b_vector(pkt);
	sc_bv<40> addr;
	generate_random_not_bar_address(addr);
 
	int type = rand()%4;
	switch(type){
	case 0:
		//flush
		pkt.range(5,0) = "000010";
		break;
	case 1:
		//Non posted write
		pkt.range(5,3) = "001";
		pkt.range(63,26) = addr.range(39,2);
		break;
	case 2:
		//Read
		pkt.range(5,4) = "01";
		pkt.range(63,26) = addr.range(39,2);
		break;
	default:
		//Atomic
		pkt.range(5,0) = "0111101";
		pkt.range(63,27) = addr.range(39,3);
	}
}
 
void reordering_l2_tb::generate_random_not_bar_address(sc_bv<40> &addr){
	//Generate random adresses until we find one not in bars
	/**
		Probably not the most efficient way of doing this!!!  But it's quick
		to code and it works.  Care must be taken that the majority of the address
		space is not used by BARs!
	*/
	bool in_bar;
	do{
		//Generate random address
		addr.range(9,0) = sc_uint<32>(rand()).range(9,0);
		addr.range(34,10) = sc_uint<32>(rand()).range(14,0);
		addr.range(39,35) = sc_uint<32>(rand()).range(14,0);
 
		//Check if it in bar
		in_bar = false;
		for(int n = 0; n < NbRegsBars; n++){
			if(		addr.range(39,Header_BarSlotSize[n]) == 
					csr_bar[n].read().range(39,Header_BarSlotSize[n])
				) in_bar = true;
		}
	//Repeat procedure until we have an address not in the bar
	}while(in_bar);
}
 
void reordering_l2_tb::generate_random_accepted_response_pkt(sc_bv<64> &pkt){
	generate_random_64b_vector(pkt);
	pkt.range(63,32) = 0;
	int type = rand() % 2;
	if(type){
		//Read response
		pkt.range(5,0) = "110000";
	}
	else{
		//Target done
		pkt.range(5,0) = "110011";
	}
	//bridge bit set
	pkt[14] = true;
	//unit_id owned by the node
	pkt.range(12,8) = csr_unit_id.read();
 
}
 
void reordering_l2_tb::generate_random_response_pkt(ReorderTBPacket &tb_pkt,
												 ResponseType response_type){
 
	switch(response_type){
	case RESPONSE_ACCEPTED:
		generate_random_accepted_response_pkt(tb_pkt.pkt.packet);
		tb_pkt.accepted = true;
		tb_pkt.forward = false;
		tb_pkt.pkt.error64BitExtension = false;
		break;
	case NPOSTED_FORWARD:
		generate_random_forward_response_pkt(tb_pkt.pkt.packet);
		tb_pkt.accepted = false;
		tb_pkt.forward = true;
		tb_pkt.pkt.error64BitExtension = rand() % 2;
		break;
	default:
		int type = rand()%2;
		if(type == 0){
			generate_random_accepted_response_pkt(tb_pkt.pkt.packet);
			tb_pkt.accepted = true;
			tb_pkt.forward = false;
			tb_pkt.pkt.error64BitExtension = false;
		}
		else{
			generate_random_forward_response_pkt(tb_pkt.pkt.packet);
			tb_pkt.accepted = false;
			tb_pkt.forward = true;
			tb_pkt.pkt.error64BitExtension = rand() % 2;
		}
	}
 
	tb_pkt.csr = false;
	tb_pkt.pkt.isPartOfChain = false;
	tb_pkt.pkt.data_address = sc_uint<32>(rand()).range(BUFFERS_ADDRESS_WIDTH-1,0);
 
}
 
void reordering_l2_tb::generate_random_forward_response_pkt(sc_bv<64> &pkt){
	generate_random_accepted_response_pkt(pkt);
	pkt.range(63,32) = 0;
 
	int forward_cause = rand() % 3;
	if(forward_cause == 0 || forward_cause == 2){
		//bridge bit unset
		pkt[14] = false;
	}
	if(forward_cause == 1 || forward_cause == 2){
	//unit_id owned by the node
	pkt.range(12,8) = ~csr_unit_id.read();
	}
}
 
void reordering_l2_tb::manage_memories(){
		////////////////////////////////////
		// CoommandBuffer Memories
		////////////////////////////////////
		for(int n = 0; n < 2; n++){
			command_packet_rd_data_ro[n] = 
				command_memory[ro_command_packet_rd_addr[n].read().to_int()];
		}
 
		if(ro_command_packet_write.read()) 
			command_memory[ro_command_packet_wr_addr.read().to_int()] = 
				ro_command_packet_wr_data.read();
}
 

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.