@ -1,8 +1,23 @@
@@ -1,8 +1,23 @@
# include <stdlib.h>
# include <stdio.h>
# include <getopt.h>
# include <stdint.h>
# include "cachelab.h"
int VERBOSE = 0 ;
# define mprintf(...) if (VERBOSE) printf(__VA_ARGS__)
/**
If VERBOSE is non - zero , mprintf will not print . Otherwise , it will .
Set in main ( ) .
*/
int8_t VERBOSE = 0 ;
/* As defined in conference. */
struct line_s {
int8_t validity ;
int tag ;
} ;
typedef struct line_s line ;
void print_usage ( )
{
@ -10,58 +25,86 @@ void print_usage()
@@ -10,58 +25,86 @@ void print_usage()
" Options: \n "
" -h Print this help. \n "
" -v Display trace info. \n "
" -s <number> The number of sets is the base-2 logarithm of this argument . \n "
" -E <number> Associativity (lines per set). \n "
" -b <number> Block size in bits is the base-2 logarithm of this argument . \n "
" -s <number> The number of set index bits. Must be a positive integer . \n "
" -E <number> Associativity (lines per set). Must be a positive integer. \n "
" -b <number> The number of block bits. Must be a positive integer . \n "
" -t <file> Name of the file to read a valgrind trace from. " ) ;
exit ( 0 ) ;
}
int parse_int_arg ( char * arg )
/* TODO: Move the exit call from parse_int_arg into the getopt cases. */
/**
Parses a string
@ param arg The string to parse .
@ param opt The option being parsed .
@ return The parsed integer if the argument was an integer .
@ note Exits if argument is invalid
*/
size_t parse_int_arg ( char * arg , char opt )
{
char * end ;
int i = strtol ( arg , & end , 0 ) ;
if ( ! i | | * end ! = ' \0 ' )
{
printf ( " Invalid argument \" %s \" \n " , arg ) ;
print_usage ( ) ;
long i = strtol ( arg , & end , 0 ) ;
if ( ! i | | * end ! = ' \0 ' ) {
printf ( " Invalid argument \" %s \" for option -%c \n " , arg , opt ) ;
printf ( " Usage: ./csim [-hv] -s <number> -E <number> -b <number> -t <file> \n " ) ;
exit ( 1 ) ;
}
else if ( i < 0 ) {
printf ( " Argument %ld for option %c too small (must be greater than 0) " , i , opt ) ;
exit ( 1 ) ;
}
else {
return ( size_t ) i ;
}
return i ;
}
int main ( int argc , char * argv [ ] )
{
int set_bits = 0 , lines = 0 , block_bits = 0 ;
char * filename ;
int ii ;
for ( ii = 0 ; ii < argc ; ii + + )
{
switch ( argv [ ii ] [ 1 ] )
{
case ' h ' :
//print_usage();
break ;
size_t index_bits = 1 , lines = ~ 0 , block_bits = 1 ; // Useful variables.
char * filename ;
int opt = 0 , argflags = 0 ;
while ( ( opt = getopt ( argc , argv , " hvs:E:b:t: " ) ) ! = - 1 ) {
switch ( opt ) {
/* TODO: maybe add checking for optarg swallowing actual arguments. */
case ' v ' :
VERBOSE = 1 ;
break ;
case ' s ' :
set_bits = parse_int_arg ( argv [ ii + 1 ] ) ;
case ' s ' : // 2^s = number of sets
index_bits = parse_int_arg ( optarg , ' s ' ) ;
argflags | = 8 ; // 0b1000
break ;
case ' E ' :
lines = parse_int_arg ( argv [ ii + 1 ] ) ;
case ' E ' : // associativity - lines per set
lines = parse_int_arg ( optarg , ' E ' ) ;
argflags | = 4 ; // 0b0100
break ;
case ' b ' :
block_bits = parse_int_arg ( argv [ ii + 1 ] ) ;
case ' b ' : // 2^b = block size
block_bits = parse_int_arg ( optarg , ' b ' ) ;
argflags | = 2 ; // 0b0010
break ;
case ' t ' :
filename = argv [ ii + 1 ] ;
filename = optarg ;
argflags | = 1 ; // 0b0001
break ;
case ' h ' :
print_usage ( ) ;
return 0 ;
default :
printf ( " Usage: ./csim [-hv] -s <number> -E <number> -b <number> -t <file> \n " ) ;
return 1 ;
}
}
/* If any required arguments were not provided. (argflags != 0b1111) */
if ( argflags ! = 15 ) {
printf ( " Usage: ./csim [-hv] -s <number> -E <number> -b <number> -t <file> \n " ) ;
return 1 ;
}
/* End of argument parsing. */
printf ( " Arguments: %d, %d, %d, %d, %s \n " , set_bits , lines , block_bits , VERBOSE , filename ) ;
if ( ! set_bits | | ! lines | | ! block_bits | | ! filename )
printf ( " Arguments: %z d, %z d, %z d, %h d, %s \n " , index _bits, lines , block_bits , VERBOSE , filename ) ;
if ( ! index_bits | | ! lines | | ! block_bits | | ! filename ) {
print_usage ( ) ;
}
printSummary ( 0 , 0 , 0 ) ;
return 0 ;