// File: /workspace/github_c_makefile_star2_O2/YanjieZe[P]CacheLab/test-trans.c
// Function: eval_perf
void eval_perf(unsigned int s, unsigned int E, unsigned int b)
{
    int i,flag;
    unsigned int len, hits, misses, evictions;
    unsigned long long int marker_start, marker_end, addr;
    char buf[1000], cmd[255];
    char filename[128];

    registerFunctions(); 

    /* Open the complete trace file */
    FILE* full_trace_fp;  
    FILE* part_trace_fp; 

    /* Evaluate the performance of each registered transpose function */

    for (i=0; i<func_counter; i++) {
        if (strcmp(func_list[i].description, SUBMIT_DESCRIPTION) == 0 )
            results.funcid = i; /* remember which function is the submission */


        printf("\nFunction %d (%d total)\nStep 1: Validating and generating memory traces\n",i,func_counter);
        /* Use valgrind to generate the trace */

        sprintf(cmd, "valgrind --tool=lackey --trace-mem=yes --log-fd=1 -v ./tracegen -M %d -N %d -F %d  > trace.tmp", M, N,i);
        flag=WEXITSTATUS(system(cmd));
        if (0!=flag) {
            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);      
            continue;
        }

        /* Get the start and end marker addresses */
        FILE* marker_fp = fopen(".marker", "r");
        assert(marker_fp);
        fscanf(marker_fp, "%llx %llx", &marker_start, &marker_end);
        fclose(marker_fp);


        func_list[i].correct=1;

        /* Save the correctness of the transpose submission */
        if (results.funcid == i ) {
            results.correct = 1;
        }

        full_trace_fp = fopen("trace.tmp", "r");
        assert(full_trace_fp);


        /* Filtered trace for each transpose function goes in a separate file */
        sprintf(filename, "trace.f%d", i);
        part_trace_fp = fopen(filename, "w");
        assert(part_trace_fp);
    
        /* Locate trace corresponding to the trans function */
        flag = 0;
        while (fgets(buf, 1000, full_trace_fp) != NULL) {

            /* We are only interested in memory access instructions */
            if (buf[0]==' ' && buf[2]==' ' &&
                (buf[1]=='S' || buf[1]=='M' || buf[1]=='L' )) {
                sscanf(buf+3, "%llx,%u", &addr, &len);
        
                /* If start marker found, set flag */
                if (addr == marker_start)
                    flag = 1;

                /* Valgrind creates many spurious accesses to the
                   stack that have nothing to do with the students
                   code. At the moment, we are ignoring all stack
                   accesses by using the simple filter of recording
                   accesses to only the low 32-bit portion of the
                   address space. At some point it would be nice to
                   try to do more informed filtering so that would
                   eliminate the valgrind stack references while
                   include the student stack references. */
                if (flag && addr < 0xffffffff) {
                    fputs(buf, part_trace_fp);
                }

                /* if end marker found, close trace file */
                if (addr == marker_end) {
                    flag = 0;
                    fclose(part_trace_fp);
                    break;
                }
            }
        }
        fclose(full_trace_fp);

        /* Run the reference simulator */
        printf("Step 2: Evaluating performance (s=%d, E=%d, b=%d)\n", s, E, b);
        char cmd[255];
        sprintf(cmd, "./csim-ref -s %u -E %u -b %u -t trace.f%d > /dev/null", 
                s, E, b, i);
        system(cmd);
    
        /* Collect results from the reference simulator */
        FILE* in_fp = fopen(".csim_results","r");
        assert(in_fp);
        fscanf(in_fp, "%u %u %u", &hits, &misses, &evictions);
        fclose(in_fp);
        func_list[i].num_hits = hits;
        func_list[i].num_misses = misses;
        func_list[i].num_evictions = evictions;
        printf("func %u (%s): hits:%u, misses:%u, evictions:%u\n",
               i, func_list[i].description, hits, misses, evictions);
    
        /* If it is transpose_submit(), record number of misses */
        if (results.funcid == i) {
            results.misses = misses;
        }
    }
  
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x6b8, %rsp            # imm = 0x6B8
movl %edx, 0x14(%rsp)
movl %esi, 0x10(%rsp)
movl %edi, 0xc(%rsp)
xorl %eax, %eax
callq 0x5988
leaq 0x70f9(%rip), %r14      # 0x83c0
leaq 0x7102(%rip), %rbp      # 0x83d0
leaq 0x1c0(%rsp), %r15
xorl %r13d, %r13d
movslq (%r14), %rbx
cmpq %rbx, %r13
jge 0x15d2
movq %r13, %r12
shlq $0x5, %r12
movq 0x8(%rbp,%r12), %rdi
leaq 0x4d0c(%rip), %rsi      # 0x6004
callq 0x10d0
testl %eax, %eax
jne 0x1308
movl %r13d, 0x6de8(%rip)     # 0x80f0
leaq 0x4d0a(%rip), %rdi      # 0x6019
movl %r13d, %esi
movl %ebx, %edx
xorl %eax, %eax
callq 0x1070
movl 0x7097(%rip), %edx      # 0x83b8
movl 0x7095(%rip), %ecx      # 0x83bc
leaq 0x5b0(%rsp), %rbx
movq %rbx, %rdi
leaq 0x4d29(%rip), %rsi      # 0x6062
movl %r13d, %r8d
xorl %eax, %eax
callq 0x1160
movq %rbx, %rdi
callq 0x1060
shrl $0x8, %eax
andl $0xff, %eax
je 0x137b
decl %eax
movl 0x705b(%rip), %edx      # 0x83b8
movl 0x7059(%rip), %ecx      # 0x83bc
leaq 0x4d57(%rip), %rdi      # 0x60c1
movl %eax, %esi
movl %r13d, %r8d
xorl %eax, %eax
callq 0x1070
jmp 0x15ca
leaq 0x4dc2(%rip), %rdi      # 0x6144
leaq 0x4dc1(%rip), %rsi      # 0x614a
callq 0x1130
testq %rax, %rax
je 0x15e4
movq %rax, %rbx
addq %rbp, %r12
movq %rax, %rdi
leaq 0x4df5(%rip), %rsi      # 0x619c
leaq 0x30(%rsp), %rdx
leaq 0x28(%rsp), %rcx
xorl %eax, %eax
callq 0x1030
movq %rbx, %rdi
callq 0x1050
movb $0x1, 0x10(%r12)
movl 0x6d24(%rip), %eax      # 0x80f0
cmpq %rax, %r13
jne 0x13d8
movb $0x1, 0x6fdc(%rip)      # 0x83b4
leaq 0x4cd8(%rip), %rdi      # 0x60b7
leaq 0x4d64(%rip), %rsi      # 0x614a
callq 0x1130
testq %rax, %rax
je 0x15fd
movq %rax, %rbx
leaq 0x140(%rsp), %r14
movq %r14, %rdi
leaq 0x4dab(%rip), %rsi      # 0x61b4
movl %r13d, %edx
xorl %eax, %eax
callq 0x1160
movq %r14, %rdi
leaq 0x4da1(%rip), %rsi      # 0x61be
callq 0x1130
testq %rax, %rax
je 0x1616
movq %rax, %rbp
xorl %r14d, %r14d
movq %r15, %rdi
movl $0x3e8, %esi            # imm = 0x3E8
movq %rbx, %rdx
callq 0x10c0
testq %rax, %rax
je 0x14db
cmpb $0x20, 0x1c0(%rsp)
jne 0x1431
cmpb $0x20, 0x1c2(%rsp)
jne 0x1431
movzbl 0x1c1(%rsp), %eax
addl $-0x4c, %eax
cmpl $0x7, %eax
ja 0x1431
movl $0x83, %ecx
btl %eax, %ecx
jae 0x1431
leaq 0x1c3(%rsp), %rdi
leaq 0x4d47(%rip), %rsi      # 0x61ce
leaq 0x20(%rsp), %rdx
leaq 0x3c(%rsp), %rcx
xorl %eax, %eax
callq 0x1120
movq 0x20(%rsp), %rax
cmpq 0x30(%rsp), %rax
pushq $0x1
popq %rcx
cmovel %ecx, %r14d
movl $0xfffffffe, %ecx       # imm = 0xFFFFFFFE
cmpq %rcx, %rax
ja 0x14c8
testl %r14d, %r14d
je 0x14c8
movq %r15, %rdi
movq %rbp, %rsi
callq 0x1090
movq 0x20(%rsp), %rax
cmpq 0x28(%rsp), %rax
jne 0x1431
movq %rbp, %rdi
callq 0x1050
movq %rbx, %rdi
callq 0x1050
leaq 0x4cec(%rip), %rdi      # 0x61d6
movl 0xc(%rsp), %r14d
movl %r14d, %esi
movl 0x10(%rsp), %ebp
movl %ebp, %edx
movl 0x14(%rsp), %ebx
movl %ebx, %ecx
xorl %eax, %eax
callq 0x1070
leaq 0x40(%rsp), %rdi
leaq 0x4cf8(%rip), %rsi      # 0x6209
movl %r14d, %edx
movl %ebp, %ecx
movl %ebx, %r8d
movl %r13d, %r9d
xorl %eax, %eax
callq 0x1160
leaq 0x40(%rsp), %rdi
callq 0x1060
leaq 0x4d0b(%rip), %rdi      # 0x623f
leaq 0x4c0f(%rip), %rsi      # 0x614a
callq 0x1130
testq %rax, %rax
je 0x1633
movq %rax, %rbx
movq %rax, %rdi
leaq 0x4cfd(%rip), %rsi      # 0x6253
leaq 0x1c(%rsp), %rdx
leaq 0x8(%rsp), %rcx
leaq 0x18(%rsp), %r8
xorl %eax, %eax
callq 0x1030
movq %rbx, %rdi
callq 0x1050
movl 0x1c(%rsp), %ecx
movl %ecx, 0x14(%r12)
movl 0x8(%rsp), %r8d
movl %r8d, 0x18(%r12)
movl 0x18(%rsp), %r9d
movl %r9d, 0x1c(%r12)
movq 0x8(%r12), %rdx
leaq 0x4cbf(%rip), %rdi      # 0x625c
movl %r13d, %esi
xorl %eax, %eax
callq 0x1070
movl 0x6b43(%rip), %eax      # 0x80f0
cmpq %rax, %r13
leaq 0x6e09(%rip), %r14      # 0x83c0
leaq 0x6e12(%rip), %rbp      # 0x83d0
jne 0x15ca
movl 0x8(%rsp), %eax
movl %eax, 0x6b2a(%rip)      # 0x80f4
incq %r13
jmp 0x12d9
addq $0x6b8, %rsp            # imm = 0x6B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x4b61(%rip), %rdi      # 0x614c
leaq 0x4b64(%rip), %rsi      # 0x6156
leaq 0x4b6a(%rip), %rcx      # 0x6163
pushq $0x50
jmp 0x162d
leaq 0x4ba2(%rip), %rdi      # 0x61a6
leaq 0x4b4b(%rip), %rsi      # 0x6156
leaq 0x4b51(%rip), %rcx      # 0x6163
pushq $0x5d
jmp 0x162d
leaq 0x4ba3(%rip), %rdi      # 0x61c0
leaq 0x4b32(%rip), %rsi      # 0x6156
leaq 0x4b38(%rip), %rcx      # 0x6163
pushq $0x63
popq %rdx
callq 0x1080
leaq 0x4c13(%rip), %rdi      # 0x624d
leaq 0x4b15(%rip), %rsi      # 0x6156
leaq 0x4b1b(%rip), %rcx      # 0x6163
movl $0x92, %edx
callq 0x1080