这是一个本人学习 csapp 的 learning 库

261 řádky
7.9 KiB

  1. /*
  2. * test-trans.c - Checks the correctness and performance of all of the
  3. * student's transpose functions and records the results for their
  4. * official submitted version as well.
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <assert.h>
  9. #include <unistd.h>
  10. #include <string.h>
  11. #include <signal.h>
  12. #include <getopt.h>
  13. #include <sys/types.h>
  14. #include "cachelab.h"
  15. #include <sys/wait.h> // fir WEXITSTATUS
  16. #include <limits.h> // for INT_MAX
  17. /* Maximum array dimension */
  18. #define MAXN 256
  19. /* The description string for the transpose_submit() function that the
  20. student submits for credit */
  21. #define SUBMIT_DESCRIPTION "Transpose submission"
  22. /* External function defined in trans.c */
  23. extern void registerFunctions();
  24. /* External variables defined in cachelab-tools.c */
  25. extern trans_func_t func_list[MAX_TRANS_FUNCS];
  26. extern int func_counter;
  27. /* Globals set on the command line */
  28. static int M = 0;
  29. static int N = 0;
  30. /* The correctness and performance for the submitted transpose function */
  31. struct results {
  32. int funcid;
  33. int correct;
  34. int misses;
  35. };
  36. static struct results results = {-1, 0, INT_MAX};
  37. /*
  38. * eval_perf - Evaluate the performance of the registered transpose functions
  39. */
  40. void eval_perf(unsigned int s, unsigned int E, unsigned int b)
  41. {
  42. int i,flag;
  43. unsigned int len, hits, misses, evictions;
  44. unsigned long long int marker_start, marker_end, addr;
  45. char buf[1000], cmd[255];
  46. char filename[128];
  47. registerFunctions();
  48. /* Open the complete trace file */
  49. FILE* full_trace_fp;
  50. FILE* part_trace_fp;
  51. /* Evaluate the performance of each registered transpose function */
  52. for (i=0; i<func_counter; i++) {
  53. if (strcmp(func_list[i].description, SUBMIT_DESCRIPTION) == 0 )
  54. results.funcid = i; /* remember which function is the submission */
  55. printf("\nFunction %d (%d total)\nStep 1: Validating and generating memory traces\n",i,func_counter);
  56. /* Use valgrind to generate the trace */
  57. sprintf(cmd, "valgrind --tool=lackey --trace-mem=yes --log-fd=1 -v ./tracegen -M %d -N %d -F %d > trace.tmp", M, N,i);
  58. flag=WEXITSTATUS(system(cmd));
  59. if (0!=flag) {
  60. printf("Validation error at function %d! Run ./tracegen -M %d -N %d -F %d for details.\nSkipping performance evaluation for this function.\n",flag-1,M,N,i);
  61. continue;
  62. }
  63. /* Get the start and end marker addresses */
  64. FILE* marker_fp = fopen(".marker", "r");
  65. assert(marker_fp);
  66. fscanf(marker_fp, "%llx %llx", &marker_start, &marker_end);
  67. fclose(marker_fp);
  68. func_list[i].correct=1;
  69. /* Save the correctness of the transpose submission */
  70. if (results.funcid == i ) {
  71. results.correct = 1;
  72. }
  73. full_trace_fp = fopen("trace.tmp", "r");
  74. assert(full_trace_fp);
  75. /* Filtered trace for each transpose function goes in a separate file */
  76. sprintf(filename, "trace.f%d", i);
  77. part_trace_fp = fopen(filename, "w");
  78. assert(part_trace_fp);
  79. /* Locate trace corresponding to the trans function */
  80. flag = 0;
  81. while (fgets(buf, 1000, full_trace_fp) != NULL) {
  82. /* We are only interested in memory access instructions */
  83. if (buf[0]==' ' && buf[2]==' ' &&
  84. (buf[1]=='S' || buf[1]=='M' || buf[1]=='L' )) {
  85. sscanf(buf+3, "%llx,%u", &addr, &len);
  86. /* If start marker found, set flag */
  87. if (addr == marker_start)
  88. flag = 1;
  89. /* Valgrind creates many spurious accesses to the
  90. stack that have nothing to do with the students
  91. code. At the moment, we are ignoring all stack
  92. accesses by using the simple filter of recording
  93. accesses to only the low 32-bit portion of the
  94. address space. At some point it would be nice to
  95. try to do more informed filtering so that would
  96. eliminate the valgrind stack references while
  97. include the student stack references. */
  98. if (flag && addr < 0xffffffff) {
  99. fputs(buf, part_trace_fp);
  100. }
  101. /* if end marker found, close trace file */
  102. if (addr == marker_end) {
  103. flag = 0;
  104. fclose(part_trace_fp);
  105. break;
  106. }
  107. }
  108. }
  109. fclose(full_trace_fp);
  110. /* Run the reference simulator */
  111. printf("Step 2: Evaluating performance (s=%d, E=%d, b=%d)\n", s, E, b);
  112. char cmd[255];
  113. sprintf(cmd, "./csim-ref -s %u -E %u -b %u -t trace.f%d > /dev/null",
  114. s, E, b, i);
  115. system(cmd);
  116. /* Collect results from the reference simulator */
  117. FILE* in_fp = fopen(".csim_results","r");
  118. assert(in_fp);
  119. fscanf(in_fp, "%u %u %u", &hits, &misses, &evictions);
  120. fclose(in_fp);
  121. func_list[i].num_hits = hits;
  122. func_list[i].num_misses = misses;
  123. func_list[i].num_evictions = evictions;
  124. printf("func %u (%s): hits:%u, misses:%u, evictions:%u\n",
  125. i, func_list[i].description, hits, misses, evictions);
  126. /* If it is transpose_submit(), record number of misses */
  127. if (results.funcid == i) {
  128. results.misses = misses;
  129. }
  130. }
  131. }
  132. /*
  133. * usage - Print usage info
  134. */
  135. void usage(char *argv[]){
  136. printf("Usage: %s [-h] -M <rows> -N <cols>\n", argv[0]);
  137. printf("Options:\n");
  138. printf(" -h Print this help message.\n");
  139. printf(" -M <rows> Number of matrix rows (max %d)\n", MAXN);
  140. printf(" -N <cols> Number of matrix columns (max %d)\n", MAXN);
  141. printf("Example: %s -M 8 -N 8\n", argv[0]);
  142. }
  143. /*
  144. * sigsegv_handler - SIGSEGV handler
  145. */
  146. void sigsegv_handler(int signum){
  147. printf("Error: Segmentation Fault.\n");
  148. printf("TEST_TRANS_RESULTS=0:0\n");
  149. fflush(stdout);
  150. exit(1);
  151. }
  152. /*
  153. * sigalrm_handler - SIGALRM handler
  154. */
  155. void sigalrm_handler(int signum){
  156. printf("Error: Program timed out.\n");
  157. printf("TEST_TRANS_RESULTS=0:0\n");
  158. fflush(stdout);
  159. exit(1);
  160. }
  161. /*
  162. * main - Main routine
  163. */
  164. int main(int argc, char* argv[])
  165. {
  166. char c;
  167. while ((c = getopt(argc,argv,"M:N:h")) != -1) {
  168. switch(c) {
  169. case 'M':
  170. M = atoi(optarg);
  171. break;
  172. case 'N':
  173. N = atoi(optarg);
  174. break;
  175. case 'h':
  176. usage(argv);
  177. exit(0);
  178. default:
  179. usage(argv);
  180. exit(1);
  181. }
  182. }
  183. if (M == 0 || N == 0) {
  184. printf("Error: Missing required argument\n");
  185. usage(argv);
  186. exit(1);
  187. }
  188. if (M > MAXN || N > MAXN) {
  189. printf("Error: M or N exceeds %d\n", MAXN);
  190. usage(argv);
  191. exit(1);
  192. }
  193. /* Install SIGSEGV and SIGALRM handlers */
  194. if (signal(SIGSEGV, sigsegv_handler) == SIG_ERR) {
  195. fprintf(stderr, "Unable to install SIGALRM handler\n");
  196. exit(1);
  197. }
  198. if (signal(SIGALRM, sigalrm_handler) == SIG_ERR) {
  199. fprintf(stderr, "Unable to install SIGALRM handler\n");
  200. exit(1);
  201. }
  202. /* Time out and give up after a while */
  203. alarm(120);
  204. /* Check the performance of the student's transpose function */
  205. eval_perf(5, 1, 5);
  206. /* Emit the results for this particular test */
  207. if (results.funcid == -1) {
  208. printf("\nError: We could not find your transpose_submit() function\n");
  209. printf("Error: Please ensure that description field is exactly \"%s\"\n",
  210. SUBMIT_DESCRIPTION);
  211. printf("\nTEST_TRANS_RESULTS=0:0\n");
  212. }
  213. else {
  214. printf("\nSummary for official submission (func %d): correctness=%d misses=%d\n",
  215. results.funcid, results.correct, results.misses);
  216. printf("\nTEST_TRANS_RESULTS=%d:%d\n", results.correct, results.misses);
  217. }
  218. return 0;
  219. }