OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [src_c/] [netrace-1.0/] [netrace.c] - Rev 48

Compare with Previous | Blame | View Log

/*
 * Copyright (c) 2010-2011 The University of Texas at Austin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
#include "netrace.h"
 
char*				nt_input_popencmd;
FILE*				nt_input_tracefile;
char*				nt_input_buffer;
nt_header_t*		nt_input_trheader;
int					nt_dependencies_off;
int					nt_self_throttling;
int					nt_primed_self_throttle;
int					nt_done_reading;
unsigned long long int nt_latest_active_packet_cycle;
nt_dep_ref_node_t** nt_dependency_array;
unsigned long long int nt_num_active_packets;
const char* nt_packet_types[] = { "InvalidCmd", "ReadReq", "ReadResp",
				"ReadRespWithInvalidate", "WriteReq", "WriteResp",
				"Writeback", "InvalidCmd", "InvalidCmd", "InvalidCmd",
				"InvalidCmd", "InvalidCmd", "InvalidCmd", "UpgradeReq",
				"UpgradeResp", "ReadExReq", "ReadExResp", "InvalidCmd",
				"InvalidCmd", "InvalidCmd", "InvalidCmd", "InvalidCmd",
				"InvalidCmd", "InvalidCmd", "InvalidCmd", "BadAddressError",
				"InvalidCmd", "InvalidateReq", "InvalidateResp",
				"DowngradeReq", "DowngradeResp" };
 
int nt_packet_sizes[] = { /*InvalidCmd*/ -1, /*ReadReq*/ 8, /*ReadResp*/ 72,
				/*ReadRespWithInvalidate*/ 72, /*WriteReq*/ 72, /*WriteResp*/ 8,
				/*Writeback*/ 72, /*InvalidCmd*/ -1, /*InvalidCmd*/ -1, /*InvalidCmd*/ -1,
				/*InvalidCmd*/ -1, /*InvalidCmd*/ -1, /*InvalidCmd*/ -1, /*UpgradeReq*/ 8,
				/*UpgradeResp*/ 8, /*ReadExReq*/ 8, /*ReadExResp*/ 72, /*InvalidCmd*/ -1,
				/*InvalidCmd*/ -1, /*InvalidCmd*/ -1, /*InvalidCmd*/ -1, /*InvalidCmd*/ -1,
				/*InvalidCmd*/ -1, /*InvalidCmd*/ -1, /*InvalidCmd*/ -1, /*BadAddressError*/ 8,
				/*InvalidCmd*/ -1, /*InvalidateReq*/ 8, /*InvalidateResp*/ 8,
				/*DowngradeReq*/ 8, /*DowngradeResp*/ 72 };
 
const char* nt_node_types[] = { "L1 Data Cache", "L1 Instruction Cache",
				"L2 Cache", "Memory Controller", "Invalid Node Type" };
 
nt_packet_list_t*	nt_cleared_packets_list;
nt_packet_list_t*	nt_cleared_packets_list_tail;
int nt_track_cleared_packets_list;
 
void nt_open_trfile(  char* trfilename ) {
	nt_close_trfile();
	int i;
	int length = 20;
	for( i = 0; trfilename[i] != 0; i++, length++ );
	nt_input_popencmd = (char*) nt_checked_malloc( length * sizeof(char) );
	sprintf( nt_input_popencmd, "bzip2 -dc %s", trfilename );
	nt_input_tracefile = popen( nt_input_popencmd, "r" );
	if( nt_input_tracefile == NULL ) {
		nt_error( "failed to open pipe to trace file" );
	}
	nt_input_trheader = nt_read_trheader();
	if( nt_dependency_array == NULL ) {
		nt_dependency_array = (nt_dep_ref_node_t**) nt_checked_malloc( sizeof(nt_dep_ref_node_t*) * NT_DEPENDENCY_ARRAY_SIZE );
		memset( nt_dependency_array, 0, sizeof(nt_dep_ref_node_t*) * NT_DEPENDENCY_ARRAY_SIZE );
		nt_num_active_packets = 0;
	} else {
		nt_error( "dependency array not NULL on file open" );
	}
}
 
nt_header_t* nt_read_trheader() {
 
	#pragma pack(push,1)
	struct nt_header_pack {
		unsigned int nt_magic;
		float version;
		char benchmark_name[NT_BMARK_NAME_LENGTH];
		unsigned char num_nodes;
		unsigned char pad;
		unsigned long long int num_cycles;
		unsigned long long int num_packets;
		unsigned int notes_length;  // Includes null-terminating char
		unsigned int num_regions;
		char padding[8];
	};
	#pragma pack(pop)
 
	int err = 0;
	char strerr[180];
 
	// Read Header
	struct nt_header_pack* in_header = (struct nt_header_pack*)nt_checked_malloc( sizeof(struct nt_header_pack) );
	fseek( nt_input_tracefile, 0, SEEK_SET );
	if( (err = fread( in_header, sizeof(struct nt_header_pack), 1, nt_input_tracefile )) < 0 ) {
		sprintf( strerr, "failed to read trace file header: err = %d", err );
		nt_error( strerr );
	}
 
	// Copy data from struct to header
	nt_header_t* to_return = (nt_header_t*) nt_checked_malloc( sizeof(nt_header_t) );
	memset( to_return, 0, sizeof(nt_header_t) );
	to_return->nt_magic = in_header->nt_magic;
	to_return->version = in_header->version;
	strcpy( to_return->benchmark_name, in_header->benchmark_name );
	to_return->num_nodes = in_header->num_nodes;
	to_return->num_cycles = in_header->num_cycles;
	to_return->num_packets = in_header->num_packets;
	to_return->notes_length = in_header->notes_length;
	to_return->num_regions = in_header->num_regions;
	free( in_header );
 
	// Error Checking
	if( to_return->nt_magic != NT_MAGIC ) {
		if( nt_little_endian() != 1 ) {
			nt_error( "only little endian architectures are currently supported" );
		} else {
			nt_error( "invalid trace file: bad magic" );
		}
	}
	if( to_return->version != 1.0f ) {
		sprintf( strerr, "trace file is unsupported version: %f", to_return->version );
		nt_error( strerr );
	}
	// Read Rest of Header
	if( to_return->notes_length > 0 && to_return->notes_length < 8192 ) {
		to_return->notes = (char*) nt_checked_malloc( to_return->notes_length * sizeof(char) );
		if( (err = fread( to_return->notes, sizeof(char), to_return->notes_length, nt_input_tracefile )) < 0 ) {
			sprintf( strerr, "failed to read trace file header notes: err = %d\n", err );
			nt_error( strerr );
		}
	} else {
		to_return->notes = NULL;
	}
	if( to_return->num_regions > 0 ) {
		if( to_return->num_regions <= 100 ) {
			to_return->regions = (nt_regionhead_t*) nt_checked_malloc( to_return->num_regions * sizeof(nt_regionhead_t) );
			if( (err = fread( to_return->regions, sizeof(nt_regionhead_t), to_return->num_regions, nt_input_tracefile )) < 0 ) {
				sprintf( strerr, "failed to read trace file header regions: error = %d\n", err );
				nt_error( strerr );
			}
		} else {
			nt_error( "lots of regions... is this correct?" );
		}
	} else {
		to_return->regions = NULL;
	}
	return to_return;
}
 
void nt_disable_dependencies() {
	if( nt_track_cleared_packets_list ) {
		nt_error( "Cannot turn off dependencies when tracking cleared packets list" );
	}
	nt_dependencies_off = 1;
}
 
void nt_seek_region( nt_regionhead_t* region ) {
	int err = 0;
	char strerr[180];
	if( nt_input_tracefile != NULL ) {
		if( region != NULL ) {
			// Clear all existing dependencies
			nt_delete_all_dependencies();
			// Reopen file to fast-forward to region
			// fseek doesn't work on compressed file
			pclose( nt_input_tracefile );
			nt_input_tracefile = popen( nt_input_popencmd, "r" );
            unsigned long long int seek_offset = nt_get_headersize() + region->seek_offset;
            unsigned long long int read_length = 4096;
			char* buffer = (char*) nt_checked_malloc( read_length );
			while( seek_offset > read_length ) {
				if( (err = fread( buffer, 1, read_length, nt_input_tracefile )) < 0 ) {
					sprintf( strerr, "failed to seek region: error = %d\n", err );
					nt_error( strerr );
				}
				seek_offset -= read_length;
			}
			if( (err = fread( buffer, 1, seek_offset, nt_input_tracefile )) < 0 ) {
				sprintf( strerr, "failed to seek region: error = %d\n", err );
				nt_error( strerr );
			}
			free( buffer );
			if( nt_self_throttling ) {
				// Prime the pump to read in self throttled packets
				nt_prime_self_throttle();
			}
		} else {
			nt_error( "invalid region passed: NULL" );
		}
	} else {
		nt_error( "must open trace file with nt_open_trfile before seeking" );
	}
}
 
nt_packet_t* nt_read_packet( void ) {
 
	#pragma pack(push,1)
	struct nt_packet_pack {
		unsigned long long int cycle;
		unsigned int id;
		unsigned int addr;
		unsigned char type;
		unsigned char src;
		unsigned char dst;
		unsigned char node_types;
		unsigned char num_deps;
	};
	#pragma pack(pop)
 
	int err = 0;
	unsigned int i;
	char strerr[180];
	nt_packet_t* to_return = NULL;
	if( nt_input_tracefile != NULL ) {
		to_return = nt_packet_malloc();
		if( (err = fread( to_return, 1, sizeof(struct nt_packet_pack), nt_input_tracefile )) < 0 ) {
			sprintf( strerr, "failed to read packet: err = %d", err );
			nt_error( strerr );
		}
		if( err > 0 && err < (int) sizeof(struct nt_packet_pack) ) {
			// Bad packet - end of file
			nt_error( "unexpectedly reached end of trace file - perhaps corrupt" );
		} else if( err == 0 ) {
			// End of file
			free( to_return );
			to_return = NULL;
			return to_return;
		}
 
		if( !nt_dependencies_off ) {
			// Track dependencies: add to_return to dependencies array
			nt_dep_ref_node_t* node_ptr = nt_get_dependency_node( to_return->id );
			if( node_ptr == NULL ) {
				node_ptr = nt_add_dependency_node( to_return->id );
			}
			node_ptr->node_packet = to_return;
		}
		nt_num_active_packets++;
		nt_latest_active_packet_cycle = to_return->cycle;
		if( to_return->num_deps == 0 ) {
			to_return->deps = NULL;
		} else {
			to_return->deps = nt_dependency_malloc( to_return->num_deps );
			if( (err = fread( to_return->deps, sizeof(nt_dependency_t), to_return->num_deps, nt_input_tracefile )) < 0 ) {
				sprintf( strerr, "failed to read dependencies: err = %d", err );
				nt_error( strerr );
			}
			if( !nt_dependencies_off ) {
				// Track dependencies: add to_return downward dependencies to array
				for( i = 0; i < to_return->num_deps; i++ ) {
					unsigned int dep_id = to_return->deps[i];
					nt_dep_ref_node_t* node_ptr = nt_get_dependency_node( dep_id );
					if( node_ptr == NULL ) {
						node_ptr = nt_add_dependency_node( dep_id );
					}
					node_ptr->ref_count++;
				}
			}
		}
	} else {
		nt_error( "must open trace file with nt_open_trfile before reading" );
	}
 
	return to_return;
}
 
nt_dep_ref_node_t* nt_add_dependency_node( unsigned int packet_id ) {
	if( nt_dependency_array != NULL ) {
		unsigned int index = packet_id % NT_DEPENDENCY_ARRAY_SIZE;
		nt_dep_ref_node_t* dep_ptr = nt_dependency_array[index];
		if( dep_ptr == NULL ) {
			nt_dependency_array[index] = (nt_dep_ref_node_t*) nt_checked_malloc( sizeof(nt_dep_ref_node_t) );
			dep_ptr = nt_dependency_array[index];
		} else {
			for( ; dep_ptr->next_node != NULL; dep_ptr = dep_ptr->next_node );
			dep_ptr->next_node =(nt_dep_ref_node_t*) nt_checked_malloc( sizeof(nt_dep_ref_node_t) );
			dep_ptr = dep_ptr->next_node;
		}
		dep_ptr->node_packet = NULL;
		dep_ptr->packet_id = packet_id;
		dep_ptr->ref_count = 0;
		dep_ptr->next_node = NULL;
		return dep_ptr;
	} else {
		nt_error( "dependency array NULL on node addition" );
	}
	return NULL;
}
 
void nt_read_ahead( unsigned long long int current_cycle ) {
	unsigned long long int read_to_cycle = current_cycle + NT_READ_AHEAD;
	if( read_to_cycle < current_cycle ) {
		nt_error( "trying to read too far ahead... overflowed :(" );
	}
	if( read_to_cycle > nt_latest_active_packet_cycle ) {
		nt_packet_t* packet;
		int d= ((end_sim_pck_num == 0 ) || (end_sim_pck_num > nt_tr_list_pck ));
		while( nt_latest_active_packet_cycle <= read_to_cycle && !nt_done_reading && (d==1) ) {
			packet = nt_read_packet();
			nt_tr_list_pck++;
			//printf("nt_tr_list_pck=%u\n",nt_tr_list_pck);
			if( packet == NULL ) {
				// This is the exit condition... how do we signal it to the
				// network simulator? We shouldn't need to... It is tracking
				// whether there are packets in flight.
				// Just in case, we'll provide this global indicator
				nt_done_reading = 1;
			} else if( nt_dependencies_cleared( packet ) ) {
				nt_add_cleared_packet_to_list( packet );
 
			//} else {
				// Ignore this packet, since the reader is already tracking it
			}
		}
	}
}
 
nt_packet_t* nt_remove_dependency_node( unsigned int packet_id ) {
	if( nt_dependency_array != NULL ) {
		unsigned int index = packet_id % NT_DEPENDENCY_ARRAY_SIZE;
		nt_dep_ref_node_t* dep_ptr = nt_dependency_array[index];
		if( dep_ptr == NULL ) {
			return NULL;
		} else {
			nt_dep_ref_node_t* prev_ptr = NULL;
			for( ; dep_ptr != NULL; prev_ptr = dep_ptr, dep_ptr = dep_ptr->next_node ) {
				if( dep_ptr->packet_id == packet_id ) break;
			}
			if( dep_ptr == NULL ) {
				return NULL;
			}
			if( prev_ptr == NULL ) {
				nt_dependency_array[index] = dep_ptr->next_node;
			} else {
				prev_ptr->next_node = dep_ptr->next_node;
			}
			nt_packet_t* packet = dep_ptr->node_packet;
			free( dep_ptr );
			return packet;
		}
	} else {
		nt_error( "dependency array NULL on node remove" );
	}
	return NULL;
}
 
nt_dep_ref_node_t* nt_get_dependency_node( unsigned int packet_id ) {
	if( nt_dependency_array != NULL ) {
		unsigned int index = packet_id % NT_DEPENDENCY_ARRAY_SIZE;
		nt_dep_ref_node_t* dep_ptr;
		for( dep_ptr = nt_dependency_array[index]; dep_ptr != NULL; dep_ptr = dep_ptr->next_node ) {
			if( dep_ptr->packet_id == packet_id ) break;
		}
		return dep_ptr;
	} else {
		nt_error( "dependency array not NULL on node search" );
	}
	return NULL;
}
 
int nt_dependencies_cleared( nt_packet_t* packet ) {
	if( nt_input_tracefile != NULL ) {
		nt_dep_ref_node_t* node_ptr = nt_get_dependency_node( packet->id );
		if( node_ptr == NULL || nt_dependencies_off ) {
			return 1;
		} else {
			return (node_ptr->ref_count == 0);
		}
	} else {
		nt_error( "must open trace file with nt_open_trfile before injecting" );
	}
	return 1;
}
 
void nt_clear_dependencies_free_packet( nt_packet_t* packet ) {
	unsigned int i;
	if( nt_input_tracefile != NULL ) {
		if( packet != NULL ) {
			// If self-throttling, read ahead in the trace file
			// to ensure that there are new packets ready to go
			if( nt_self_throttling ) {
				nt_read_ahead( packet->cycle );
			}
			for( i = 0; i < packet->num_deps; i++ ) {
				unsigned int dep_id = packet->deps[i];
				nt_dep_ref_node_t* node_ptr = nt_get_dependency_node( dep_id );
				if( node_ptr == NULL ) {
					if( !nt_dependencies_off ) {
						// TODO: check if this is a problem with short seeks
						nt_print_packet( packet );
						nt_error( "failed to find dependency node" );
					}
				} else {
					if( node_ptr->ref_count == 0 ) {
						nt_error( "invalid reference count on node while decrementing" );
					}
					node_ptr->ref_count--;
					if( nt_track_cleared_packets_list ) {
						if( node_ptr->ref_count == 0 ) {
							// This test alleviates the possibility of a packet
							// having ref_count zero before it has been read
							// from the trace (node_packet = NULL)
							if( node_ptr->node_packet ) {
								nt_add_cleared_packet_to_list( node_ptr->node_packet );
							}
						}
					}
				}
			}
			nt_remove_dependency_node( packet->id );
			nt_packet_free( packet );
			nt_num_active_packets--;
		}
	} else {
		nt_error( "must open trace file with nt_open_trfile before ejecting" );
	}
}
 
void nt_init_cleared_packets_list() {
	if( nt_dependencies_off ) {
		nt_error( "Cannot return cleared packets list when dependencies are turned off" );
	}
	nt_track_cleared_packets_list = 1;
	nt_cleared_packets_list = NULL;
	nt_cleared_packets_list_tail = NULL;
}
 
void nt_init_self_throttling() {
	if( nt_dependencies_off ) {
		nt_error( "Cannot self throttle packets when dependencies are turned off" );
	}
	nt_self_throttling = 1;
	nt_primed_self_throttle = 0;
	nt_init_cleared_packets_list();
}
 
nt_packet_list_t* nt_get_cleared_packets_list() {
	if( !nt_primed_self_throttle ) {
		nt_prime_self_throttle();
	}
	return nt_cleared_packets_list;
}
 
void nt_prime_self_throttle() {
	nt_packet_t* packet = nt_read_packet();
    nt_tr_list_pck++;
	if( nt_dependencies_cleared( packet ) ) {
		nt_add_cleared_packet_to_list( packet );
	}
	nt_primed_self_throttle = 1;
	nt_read_ahead( packet->cycle );
}
 
void nt_add_cleared_packet_to_list( nt_packet_t* packet ) {
	nt_packet_list_t* new_node = (nt_packet_list_t*) nt_checked_malloc( sizeof(nt_packet_list_t) );
	new_node->node_packet = packet;
	new_node->next = NULL;
	if( nt_cleared_packets_list == NULL ) {
		nt_cleared_packets_list = nt_cleared_packets_list_tail = new_node;
	} else {
		nt_cleared_packets_list_tail->next = new_node;
		nt_cleared_packets_list_tail = new_node;
	}
}
 
void nt_empty_cleared_packets_list() {
	while( nt_cleared_packets_list != NULL ) {
		nt_packet_list_t* temp = nt_cleared_packets_list;
		nt_cleared_packets_list = nt_cleared_packets_list->next;
		free( temp );
	}
	nt_cleared_packets_list = nt_cleared_packets_list_tail = NULL;
}
 
void nt_close_trfile() {
	if( nt_input_tracefile != NULL ) {
		pclose( nt_input_tracefile );
		nt_input_tracefile = NULL;
		nt_free_trheader( nt_input_trheader );
		if( nt_input_popencmd != NULL ) {
			free( nt_input_popencmd );
		}
		nt_input_popencmd = NULL;
		nt_delete_all_dependencies();
		free(nt_dependency_array);
		nt_dependency_array = NULL;
	}
}
 
void nt_delete_all_dependencies() {
	int i;
	for( i = 0; i < NT_DEPENDENCY_ARRAY_SIZE; i++ ) {
		while( nt_dependency_array[i] != NULL ) {
			nt_remove_dependency_node( nt_dependency_array[i]->packet_id );
		}
	}
}
 
void nt_print_header( nt_header_t* header ) {
	unsigned int i;
	if( header != NULL ) {
		printf( "NT_TRACEFILE---------------------\n" );
 
		printf( "  Benchmark: %s\n", header->benchmark_name );
		printf( "  Magic Correct? %s\n", (header->nt_magic == NT_MAGIC) ? "TRUE" : "FALSE" );
		printf( "  Tracefile Version: v%1.1f\n", header->version );
		printf( "  Number of Program Regions: %d\n", header->num_regions );
		printf( "  Number of Simulated Nodes: %d\n", header->num_nodes );
		printf( "  Simulated Cycles: %lld\n", header->num_cycles );
		printf( "  Simulated Packets: %lld\n", header->num_packets );
		printf( "  Average injection rate: %f\n", (double)header->num_packets / (double)header->num_cycles );
		if( header->notes_length > 0 ) {
			printf( "  Notes: %s\n", header->notes );
		}
 
		for( i = 0; i < header->num_regions; i++ ) {
			printf( "    Region %d:\n", i );
			printf( "      Seek Offset: %lld\n", header->regions[i].seek_offset );
			printf( "      Simulated Cycles: %lld\n", header->regions[i].num_cycles );
			printf( "      Simulated Packets: %lld\n", header->regions[i].num_packets );
			printf( "      Average injection rate: %f\n", (double)header->regions[i].num_packets / (double)header->regions[i].num_cycles );
			printf( "      Average injection rate per node: %f\n", (double)header->regions[i].num_packets / (double)header->regions[i].num_cycles / (double)header->num_nodes );
		}
		printf( "  Size of header (B): %u\n", nt_get_headersize() );
		printf( "NT_TRACEFILE---------------------\n" );
	} else {
		printf( "NULL header passed to nt_print_header\n" );
	}
}
 
void nt_print_trheader() {
	nt_print_header( nt_input_trheader );
}
 
nt_header_t* nt_get_trheader() {
	if( nt_input_tracefile != NULL ) {
		return nt_input_trheader;
	} else {
		nt_error( "must open trace file with nt_open_trfile before header is available" );
	}
	return NULL;
}
 
float nt_get_trversion() {
	if( nt_input_tracefile != NULL ) {
		return nt_input_trheader->version;
	} else {
		nt_error( "must open trace file with nt_open_trfile before version is available" );
	}
	return 0.0f;
}
 
nt_packet_t* nt_packet_malloc() {
	// TODO: v1.1?
	// Allocate large array (1+ pages) to reduce # system calls
	return (nt_packet_t*) nt_checked_malloc( sizeof(nt_packet_t) );
}
 
nt_dependency_t* nt_dependency_malloc( unsigned char num_deps ) {
	// TODO: v1.1?
	// Allocate large array (1+ pages) to reduce # system calls
	return (nt_dependency_t*) nt_checked_malloc( num_deps * sizeof(nt_dependency_t) );
}
 
int nt_get_src_type( nt_packet_t* packet ) {
	return (int) ( packet->node_types >> 4 );
}
 
int nt_get_dst_type( nt_packet_t* packet ) {
	return (int) ( 0xF & packet->node_types );
}
 
const char* nt_node_type_to_string( int type ) {
	if( type < NT_NUM_NODE_TYPES ) {
		return nt_node_types[type];
	} else {
		return nt_node_types[NT_NUM_NODE_TYPES];
	}
}
 
int nt_get_packet_size( nt_packet_t* packet ) {
	if( packet->type < NT_NUM_PACKET_TYPES ) {
		return nt_packet_sizes[packet->type];
	} else {
		return nt_packet_sizes[0];
	}
}
 
const char* nt_packet_type_to_string( nt_packet_t* packet ) {
	if( packet->type < NT_NUM_PACKET_TYPES ) {
		return nt_packet_types[packet->type];
	} else {
		return nt_packet_types[0];
	}
}
 
nt_packet_t* nt_packet_copy( nt_packet_t* packet ) {
	if( packet != NULL ) {
		nt_packet_t* to_return = nt_packet_malloc();
		memcpy( to_return, packet, sizeof(nt_packet_t) );
		if( packet->num_deps > 0 ) {
			to_return->deps = nt_dependency_malloc( to_return->num_deps );
			memcpy( to_return->deps, packet->deps, sizeof(nt_dependency_t) * to_return->num_deps );
		}
		return to_return;
	}
	return NULL;
}
 
void nt_packet_free( nt_packet_t* packet ) {
	if( packet != NULL ) {
		if( packet->num_deps > 0 ) {
			free( packet->deps );
		}
		free( packet );
	}
}
 
void nt_print_packet( nt_packet_t* packet ) {
	int i;
	if( packet != NULL ) {
		printf( "  ID:%u CYC:%llu SRC:%u DST:%u ADR:0x%08x TYP:%s NDEP:%u",
				packet->id, packet->cycle, packet->src,
				packet->dst, packet->addr, nt_packet_type_to_string( packet ),
				packet->num_deps );
		for( i = 0; i < packet->num_deps; i++ ) {
			printf( " %d", packet->deps[i] );
		}
		printf( "\n" );
	} else {
		printf( "WARNING: %s:%d: NULL packet printed!\n", __FILE__, __LINE__ );
	}
}
 
void nt_free_trheader( nt_header_t* header ) {
	if( header != NULL ) {
		if( header->regions != NULL ) {
			free( header->regions );
		}
		if( header->notes != NULL ) {
			free( header->notes );
		}
		free( header );
	}
}
 
int nt_get_headersize() {
 
	#pragma pack(push,1)
	struct nt_header_pack {
		unsigned int nt_magic;
		float version;
		char benchmark_name[NT_BMARK_NAME_LENGTH];
		unsigned char num_nodes;
		unsigned long long int num_cycles;
		unsigned long long int num_packets;
		unsigned int notes_length;  // Includes null-terminating char
		unsigned int num_regions;
		char padding[9];
	};
	#pragma pack(pop)
 
	if( nt_input_tracefile != NULL ) {
		int to_return = 0;
		to_return += sizeof(struct nt_header_pack);
		to_return += nt_input_trheader->notes_length;
		to_return += nt_input_trheader->num_regions * sizeof(nt_regionhead_t);
		return to_return;
	} else {
		nt_error( "must open trace file with nt_open_trfile before header is available" );
	}
	return -1;
}
 
void* _nt_checked_malloc( size_t n, const char* file, int line ) {
	void* ptr;
	ptr = malloc( n );
	if( ptr == NULL ) {
		fprintf( stderr, "ERROR: bad allocation at %s:%d\n", file, line );
		exit(0);
	}
	return ptr;
}
 
int nt_little_endian() {
	int to_return = 1;
	union {
		int number;
		char bytes[sizeof(int)];
	} u;
	unsigned int i;
	u.number = (int)0;
	for( i = 0; i < sizeof(int); i++ ) {
		u.number |= (int)(i + 1) << (8 * i);
	}
	for( i = 0; i < sizeof(int); i++ ) {
		if( (unsigned int)u.bytes[i] != i+1 ) {
			to_return = 0;
			break;
		}
	}
	return to_return;
}
 
void _nt_error( const char* str, const char* file, const int line ) {
#ifdef DEBUG_ON
	fprintf( stderr, "WARNING: In %s:%d: %s\n", file, line, str );
#else
	fprintf( stderr, "ERROR: In %s:%d: %s\n", file, line, str );
	exit(0);
#endif
}
 
// Backend functions for creating trace files
void nt_dump_header( nt_header_t* header, FILE* fp ) {
 
	#pragma pack(push,1)
	struct nt_header_pack {
		unsigned int nt_magic;
		float version;
		char benchmark_name[NT_BMARK_NAME_LENGTH];
		unsigned char num_nodes;
		unsigned char pad;
		unsigned long long int num_cycles;
		unsigned long long int num_packets;
		unsigned int notes_length;  // Includes null-terminating char
		unsigned int num_regions;
		char padding[8];
	};
	#pragma pack(pop)
 
	if( header != NULL ) {
		struct nt_header_pack* out_header = (struct nt_header_pack*) nt_checked_malloc( sizeof(struct nt_header_pack) );
		out_header->nt_magic = header->nt_magic;
		out_header->version = header->version;
		strcpy( out_header->benchmark_name, header->benchmark_name );
		out_header->num_nodes = header->num_nodes;
		out_header->num_cycles = header->num_cycles;
		out_header->num_packets = header->num_packets;
		out_header->notes_length = header->notes_length;
		out_header->num_regions = header->num_regions;
		fwrite( out_header, sizeof(struct nt_header_pack), 1, fp );
		fwrite( header->notes, sizeof(char), header->notes_length, fp );
		fwrite( header->regions, sizeof(nt_regionhead_t), header->num_regions, fp );
		free( out_header );
	} else {
		nt_error( "dumping NULL header" );
	}
}
 
void nt_dump_packet( nt_packet_t* packet, FILE* fp ) {
 
	#pragma pack(push,1)
	struct nt_read_pack {
		unsigned long long int cycle;
		unsigned int id;
		unsigned int addr;
		unsigned char type;
		unsigned char src;
		unsigned char dst;
		unsigned char node_types;
		unsigned char num_deps;
	};
	#pragma pack(pop)
 
	if( packet != NULL ) {
		fwrite( packet, sizeof(struct nt_read_pack), 1, fp );
		fwrite( packet->deps, sizeof(nt_dependency_t), packet->num_deps, fp );
	} else {
		nt_error( "dumping NULL packet" );
	}
}
 

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.