#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TRUE 1
#define FALSE 0
#define MAX_PROCESSES 4
#define MAX_REGISTERS 2
#define MAX_PAGES 64
#define PAGE_SIZE 32
#define TLB_SIZE 8

// Output file
FILE* output_file;

// TLB replacement strategy (FIFO or LRU)
char* strategy;

// Global timestamp for TLB entries
int global_timestamp = 0;

// State variables
int define_called = FALSE;
int current_pid = 0;
int registers[MAX_PROCESSES][MAX_REGISTERS];
int page_table[MAX_PROCESSES][MAX_PAGES];
int* memory = NULL; // Dynamically allocated based on define
int off_bits = 0;
int pfn_bits = 0;
int vpn_bits = 0;

// TLB structure
typedef struct {
    int pid;
    int vpn;
    int pfn;
    int valid;
    int timestamp;
} TLBEntry;

TLBEntry tlb[TLB_SIZE];
int global_tlb_index = 0; // For FIFO replacement

// Function to tokenize input
char** tokenize_input(char* input) {
    char** tokens = NULL;
    char* token = strtok(input, " ");
    int num_tokens = 0;

    while (token != NULL) {
        num_tokens++;
        tokens = realloc(tokens, num_tokens * sizeof(char*));
        if (tokens == NULL) {
            fprintf(stderr, "Error: Memory allocation failed during tokenization.\n");
            exit(1);
        }
        tokens[num_tokens - 1] = malloc(strlen(token) + 1);
        if (tokens[num_tokens - 1] == NULL) {
            fprintf(stderr, "Error: Memory allocation failed during tokenization.\n");
            exit(1);
        }
        strcpy(tokens[num_tokens - 1], token);
        token = strtok(NULL, " ");
    }

    num_tokens++;
    tokens = realloc(tokens, num_tokens * sizeof(char*));
    if (tokens == NULL) {
        fprintf(stderr, "Error: Memory allocation failed during tokenization.\n");
        exit(1);
    }
    tokens[num_tokens - 1] = NULL;

    return tokens;
}

// TLB lookup
int tlb_lookup(int pid, int vpn, int* pfn, int* tlb_entry) {
    for (int i = 0; i < TLB_SIZE; i++) {
        if (tlb[i].valid && tlb[i].pid == pid && tlb[i].vpn == vpn) {
            *pfn = tlb[i].pfn;
            *tlb_entry = i;
            fprintf(output_file, "Current PID: %d. Translating. Lookup for VPN %d hit in TLB entry %d. PFN is %d\n",
                    pid, vpn, i, *pfn);
            return TRUE;
        }
    }

    // On TLB miss, output miss message and do not update TLB here directly
    fprintf(output_file, "Current PID: %d. Translating. Lookup for VPN %d caused a TLB miss\n", pid, vpn);
    return FALSE;
}

// Per-process TLB update with FIFO replacement
void tlb_update(int pid, int vpn, int pfn) {
    int entry_index = global_tlb_index % TLB_SIZE;
    tlb[entry_index].pid = pid;
    tlb[entry_index].vpn = vpn;
    tlb[entry_index].pfn = pfn;
    tlb[entry_index].valid = TRUE;
    tlb[entry_index].timestamp = global_timestamp++;
    fprintf(output_file, "Current PID: %d. Mapped virtual page number %d to physical frame number %d\n", pid, vpn, pfn);
    global_tlb_index++;
}

// Function to handle loading an immediate into a register
void handle_load(char** tokens) {
    if (strcmp(tokens[1], "r1") == 0 || strcmp(tokens[1], "r2") == 0) {
        int reg_index = (strcmp(tokens[1], "r1") == 0) ? 0 : 1;
        int value = atoi(tokens[2] + 1); // Skip the '#' character
        registers[current_pid][reg_index] = value;
        fprintf(output_file, "Current PID: %d. Loaded immediate %d into register %s\n", current_pid, value, tokens[1]);
    } else {
        fprintf(output_file, "Current PID: %d. Error: invalid register operand %s\n", current_pid, tokens[1]);
    }
}

// Function to handle add operation
void handle_add() {
    int result = registers[current_pid][0] + registers[current_pid][1];
    fprintf(output_file, "Current PID: %d. Added contents of registers r1 (%d) and r2 (%d). Result: %d\n",
            current_pid, registers[current_pid][0], registers[current_pid][1], result);
    registers[current_pid][0] = result;
}

// Function to map a virtual page to a physical frame
void handle_map(char** tokens) {
    int vpn = atoi(tokens[1]);
    int pfn = atoi(tokens[2]);

    if (vpn < 0 || vpn >= MAX_PAGES) {
        fprintf(output_file, "Current PID: %d. Error: VPN %d out of range\n", current_pid, vpn);
        return;
    }

    if (pfn < 0 || pfn >= (1 << pfn_bits)) {
        fprintf(output_file, "Current PID: %d. Error: PFN %d out of range\n", current_pid, pfn);
        return;
    }

    // Update the page table
    page_table[current_pid][vpn] = pfn;

    // Update the TLB entry with the new mapping
    tlb_update(current_pid, vpn, pfn);
}

// Function to unmap a virtual page
void handle_unmap(char** tokens) {
    int vpn = atoi(tokens[1]);

    if (vpn < 0 || vpn >= MAX_PAGES) {
        fprintf(output_file, "Current PID: %d. Error: VPN %d out of range\n", current_pid, vpn);
        return;
    }

    // Invalidate any TLB entry for this PID and VPN
    for (int i = 0; i < TLB_SIZE; i++) {
        if (tlb[i].valid && tlb[i].pid == current_pid && tlb[i].vpn == vpn) {
            tlb[i].valid = FALSE;
            // Do not print per-entry unmap messages to match expected output
        }
    }

    // Invalidate in the page table
    page_table[current_pid][vpn] = -1;
    fprintf(output_file, "Current PID: %d. Unmapped virtual page number %d\n", current_pid, vpn);
}

// Function to handle store operation
void handle_store(char** tokens) {
    int addr = atoi(tokens[1]);
    int reg_value;
    if (tokens[2][0] == '#') {
        reg_value = atoi(tokens[2] + 1);
    } else if (strcmp(tokens[2], "r1") == 0 || strcmp(tokens[2], "r2") == 0) {
        int reg_index = (strcmp(tokens[2], "r1") == 0) ? 0 : 1;
        reg_value = registers[current_pid][reg_index];
    } else {
        fprintf(output_file, "Current PID: %d. Error: invalid register operand %s\n", current_pid, tokens[2]);
        return;
    }

    int vpn = addr >> off_bits; // Calculate VPN by shifting address right by off_bits
    int offset = addr & ((1 << off_bits) - 1); // Offset mask based on off_bits

    if (vpn < 0 || vpn >= MAX_PAGES) {
        fprintf(output_file, "Current PID: %d. Error: VPN %d out of range for address %d\n", current_pid, vpn, addr);
        return;
    }

    int pfn;
    int tlb_entry;
    if (!tlb_lookup(current_pid, vpn, &pfn, &tlb_entry)) {
        // If TLB miss, fall back to page table
        pfn = page_table[current_pid][vpn];
        if (pfn != -1) {
            tlb_update(current_pid, vpn, pfn); // Update TLB if mapping is in page table
            fprintf(output_file, "Current PID: %d. Translating. Successfully mapped VPN %d to PFN %d\n", current_pid, vpn, pfn);
        } else {
            fprintf(output_file, "Current PID: %d. Error: attempted to store to unmapped address %d\n", current_pid, addr);
            return;
        }
    }

    int phys_addr = (pfn << off_bits) | offset;
    if (phys_addr < 0 || phys_addr >= (1 << (pfn_bits + off_bits))) {
        fprintf(output_file, "Current PID: %d. Error: physical address %d out of range\n", current_pid, phys_addr);
        return;
    }
    memory[phys_addr] = reg_value;

    if (tokens[2][0] == '#') {
        fprintf(output_file, "Current PID: %d. Stored immediate %d into location %d\n", current_pid, reg_value, addr);
    } else {
        fprintf(output_file, "Current PID: %d. Stored value of register %s (%d) into location %d\n", current_pid, tokens[2], reg_value, addr);
    }
}

// handle_load_mem function
void handle_load_mem(char** tokens) {
    int addr = atoi(tokens[2]);
    int vpn = addr >> off_bits; // Calculate VPN by shifting address right by off_bits
    int offset = addr & ((1 << off_bits) - 1); // Offset mask based on off_bits

    if (vpn < 0 || vpn >= MAX_PAGES) {
        fprintf(output_file, "Current PID: %d. Error: VPN %d out of range for address %d\n", current_pid, vpn, addr);
        return;
    }

    int pfn;
    int tlb_entry;
    if (!tlb_lookup(current_pid, vpn, &pfn, &tlb_entry)) {
        // If TLB miss, fall back to page table
        pfn = page_table[current_pid][vpn];
        if (pfn != -1) {
            tlb_update(current_pid, vpn, pfn); // Update TLB if mapping is in page table
            fprintf(output_file, "Current PID: %d. Translating. Successfully mapped VPN %d to PFN %d\n", current_pid, vpn, pfn);
        } else {
            fprintf(output_file, "Current PID: %d. Translating. Translation for VPN %d not found in page table\n", current_pid, vpn);
            return;
        }
    }

    int phys_addr = (pfn << off_bits) | offset;
    if (phys_addr < 0 || phys_addr >= (1 << (pfn_bits + off_bits))) {
        fprintf(output_file, "Current PID: %d. Error: physical address %d out of range\n", current_pid, phys_addr);
        return;
    }

    if (strcmp(tokens[1], "r1") == 0 || strcmp(tokens[1], "r2") == 0) {
        int reg_index = (strcmp(tokens[1], "r1") == 0) ? 0 : 1;
        registers[current_pid][reg_index] = memory[phys_addr];
        fprintf(output_file, "Current PID: %d. Loaded value of location %d (%d) into register %s\n", current_pid, addr, memory[phys_addr], tokens[1]);
    } else {
        fprintf(output_file, "Current PID: %d. Error: invalid register operand %s\n", current_pid, tokens[1]);
    }
}

// Function to inspect page table entry
void handle_pinspect(char** tokens) {
    int vpn = atoi(tokens[1]);
    if (vpn < 0 || vpn >= MAX_PAGES) {
        fprintf(output_file, "Current PID: %d. Error: VPN %d out of range for inspection\n", current_pid, vpn);
        return;
    }
    int pfn = page_table[current_pid][vpn];
    
    // Translate internal PFN of -1 to 0 for reporting
    int display_pfn = (pfn == -1) ? 0 : pfn;
    int valid = (pfn != -1) ? 1 : 0;
    
    fprintf(output_file, "Current PID: %d. Inspected page table entry %d. Physical frame number: %d. Valid: %d\n",
            current_pid, vpn, display_pfn, valid);
}

// Function to inspect TLB entry
void handle_tinspect(char** tokens) {
    int tlbn = atoi(tokens[1]);
    if (tlbn >= 0 && tlbn < TLB_SIZE) {
        TLBEntry entry = tlb[tlbn];
        fprintf(output_file, "Current PID: %d. Inspected TLB entry %d. VPN: %d. PFN: %d. Valid: %d. PID: %d. Timestamp: %d\n",
                current_pid, tlbn, entry.vpn, entry.pfn, entry.valid, entry.pid, entry.timestamp);
    } else {
        fprintf(output_file, "Current PID: %d. Error: TLB number %d out of range\n", current_pid, tlbn);
    }
}

// Function to inspect physical memory location
void handle_linspect(char** tokens) {
    int pl = atoi(tokens[1]);
    if (pl >= 0 && pl < (1 << (pfn_bits + off_bits))) { // Dynamic memory size
        fprintf(output_file, "Current PID: %d. Inspected physical location %d. Value: %d\n",
                current_pid, pl, memory[pl]);
    } else {
        fprintf(output_file, "Current PID: %d. Error: physical location %d out of range\n", current_pid, pl);
    }
}

// Function to inspect register
void handle_rinspect(char** tokens) {
    if (strcmp(tokens[1], "r1") == 0 || strcmp(tokens[1], "r2") == 0) {
        int reg_index = (strcmp(tokens[1], "r1") == 0) ? 0 : 1;
        fprintf(output_file, "Current PID: %d. Inspected register %s. Content: %d\n",
                current_pid, tokens[1], registers[current_pid][reg_index]);
    } else {
        fprintf(output_file, "Current PID: %d. Error: invalid register operand %s\n", current_pid, tokens[1]);
    }
}

int main(int argc, char* argv[]) {
    const char usage[] = "Usage: memsym.out <strategy> <input trace> <output trace>\n";
    char* input_trace;
    char* output_trace;
    char buffer[2048]; // Increased buffer size for longer lines

    // Parse command line arguments
    if (argc != 4) {
        printf("%s", usage);
        return 1;
    }
    strategy = argv[1];
    input_trace = argv[2];
    output_trace = argv[3];

    // Initialize memory and page tables to NULL
    for (int i = 0; i < MAX_PROCESSES; i++) {
        for (int j = 0; j < MAX_PAGES; j++) {
            page_table[i][j] = -1;
        }
    }

    // Initialize TLB entries to invalid
    for(int i = 0; i < TLB_SIZE; i++) {
        tlb[i].valid = FALSE;
        tlb[i].pid = -1;
        tlb[i].vpn = -1;
        tlb[i].pfn = -1;
        tlb[i].timestamp = 0;
    }

    // Open input and output files
    FILE* input_file = fopen(input_trace, "r");
    if (!input_file) {
        fprintf(stderr, "Error: Cannot open input file %s\n", input_trace);
        return 1;
    }
    output_file = fopen(output_trace, "w");  
    if (!output_file) {
        fprintf(stderr, "Error: Cannot open output file %s\n", output_trace);
        fclose(input_file);
        return 1;
    }

    while (fgets(buffer, sizeof(buffer), input_file)) {
        // Remove the newline character if present
        size_t len = strlen(buffer);
        if (len > 0 && buffer[len - 1] == '\n') {
            buffer[len - 1] = '\0';
        }

        char** tokens = tokenize_input(buffer);

        // Ignore comments
        if (tokens[0] && tokens[0][0] == '%') {
            for (int i = 0; tokens[i] != NULL; i++)
                free(tokens[i]);
            free(tokens);
            continue;
        }

        // Implement the memory simulator
        if (tokens[0] != NULL) {
            if (strcmp(tokens[0], "define") == 0) {
                if (define_called) {
                    fprintf(output_file, "Current PID: 0. Error: multiple calls to define in the same trace\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                } else {
                    if (tokens[1] == NULL || tokens[2] == NULL || tokens[3] == NULL) { // Ensure there are enough tokens
                        fprintf(output_file, "Current PID: 0. Error: insufficient arguments for define\n");
                        // Clean up tokens before exiting
                        for (int i = 0; tokens[i] != NULL; i++)
                            free(tokens[i]);
                        free(tokens);
                        break;
                    }
                    define_called = TRUE;
                    off_bits = atoi(tokens[1]);
                    pfn_bits = atoi(tokens[2]);
                    vpn_bits = atoi(tokens[3]);

                    // Calculate memory size based on OFF and PFN bits
                    // Total physical addresses = (2^PFN_bits) * (2^OFF_bits)
                    // Each address holds an integer
                    unsigned long memory_size = ((unsigned long)(1) << (pfn_bits + off_bits));

                    // Allocate memory
                    memory = (int*)malloc(memory_size * sizeof(int));
                    if (memory == NULL) {
                        fprintf(stderr, "Error: Memory allocation failed.\n");
                        fclose(input_file);
                        fclose(output_file);
                        return 1;
                    }
                    memset(memory, 0, memory_size * sizeof(int));

                    fprintf(output_file, "Current PID: 0. Memory instantiation complete. OFF bits: %d. PFN bits: %d. VPN bits: %d\n", off_bits, pfn_bits, vpn_bits);
                }
            } 
            else if (strcmp(tokens[0], "ctxswitch") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[1] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for ctxswitch\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                int new_pid = atoi(tokens[1]);
                if (new_pid < 0 || new_pid >= MAX_PROCESSES) {
                    fprintf(output_file, "Current PID: %d. Invalid context switch to process %d\n", current_pid, new_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                } else {
                    current_pid = new_pid;
                    fprintf(output_file, "Current PID: %d. Switched execution context to process: %d\n", current_pid, new_pid);
                }
            } 
            else if (strcmp(tokens[0], "load") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[2] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for load\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[2][0] == '#') {
                    handle_load(tokens);
                } else {
                    handle_load_mem(tokens);
                }
            } 
            else if (strcmp(tokens[0], "add") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_add();
            } 
            else if (strcmp(tokens[0], "map") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_map(tokens);
            } 
            else if (strcmp(tokens[0], "unmap") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_unmap(tokens);
            } 
            else if (strcmp(tokens[0], "store") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[1] == NULL || tokens[2] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for store\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_store(tokens);
            } 
            else if (strcmp(tokens[0], "pinspect") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[1] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for pinspect\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_pinspect(tokens);
            } 
            else if (strcmp(tokens[0], "tinspect") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[1] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for tinspect\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_tinspect(tokens);
            } 
            else if (strcmp(tokens[0], "linspect") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[1] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for linspect\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_linspect(tokens);
            } 
            else if (strcmp(tokens[0], "rinspect") == 0) {
                if (!define_called) {
                    fprintf(output_file, "Current PID: 0. Error: attempt to execute instruction before define\n");
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                if (tokens[1] == NULL) {
                    fprintf(output_file, "Current PID: %d. Error: insufficient arguments for rininspect\n", current_pid);
                    // Clean up tokens before exiting
                    for (int i = 0; tokens[i] != NULL; i++)
                        free(tokens[i]);
                    free(tokens);
                    break;
                }
                handle_rinspect(tokens);
            } 
            else {
                fprintf(output_file, "Current PID: %d. Error: Unknown instruction %s\n", current_pid, tokens[0]);
                // Clean up tokens before exiting
                for (int i = 0; tokens[i] != NULL; i++)
                    free(tokens[i]);
                free(tokens);
                break;
            }
        }

        // Deallocate tokens
        for (int i = 0; tokens[i] != NULL; i++)
            free(tokens[i]);
        free(tokens);
    }

    // Close input and output files
    fclose(input_file);
    fclose(output_file);

    // Free dynamically allocated memory
    if (memory != NULL) {
        free(memory);
    }

    return 0;
}


what is wrong with my 4.4 test here is my output:

Current PID: 0. Memory instantiation complete. OFF bits: 3. PFN bits: 5. VPN bits: 4
Current PID: 2. Switched execution context to process: 2
Current PID: 2. Mapped virtual page number 0 to physical frame number 10
Current PID: 2. Mapped virtual page number 1 to physical frame number 11
Current PID: 2. Mapped virtual page number 2 to physical frame number 12
Current PID: 2. Mapped virtual page number 3 to physical frame number 13
Current PID: 2. Mapped virtual page number 4 to physical frame number 14
Current PID: 2. Mapped virtual page number 5 to physical frame number 15
Current PID: 2. Mapped virtual page number 6 to physical frame number 16
Current PID: 2. Mapped virtual page number 7 to physical frame number 17
Current PID: 2. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 10
Current PID: 2. Stored immediate 10 into location 0
Current PID: 2. Translating. Lookup for VPN 1 hit in TLB entry 1. PFN is 11
Current PID: 2. Stored immediate 11 into location 8
Current PID: 2. Translating. Lookup for VPN 2 hit in TLB entry 2. PFN is 12
Current PID: 2. Stored immediate 12 into location 16
Current PID: 2. Translating. Lookup for VPN 3 hit in TLB entry 3. PFN is 13
Current PID: 2. Stored immediate 13 into location 24
Current PID: 2. Translating. Lookup for VPN 4 hit in TLB entry 4. PFN is 14
Current PID: 2. Stored immediate 14 into location 32
Current PID: 2. Translating. Lookup for VPN 5 hit in TLB entry 5. PFN is 15
Current PID: 2. Stored immediate 15 into location 40
Current PID: 2. Translating. Lookup for VPN 6 hit in TLB entry 6. PFN is 16
Current PID: 2. Stored immediate 16 into location 48
Current PID: 2. Translating. Lookup for VPN 7 hit in TLB entry 7. PFN is 17
Current PID: 2. Stored immediate 17 into location 56
Current PID: 2. Inspected TLB entry 0. VPN: 0. PFN: 10. Valid: 1. PID: 2. Timestamp: 0
Current PID: 2. Inspected TLB entry 1. VPN: 1. PFN: 11. Valid: 1. PID: 2. Timestamp: 1
Current PID: 2. Inspected TLB entry 2. VPN: 2. PFN: 12. Valid: 1. PID: 2. Timestamp: 2
Current PID: 2. Inspected TLB entry 3. VPN: 3. PFN: 13. Valid: 1. PID: 2. Timestamp: 3
Current PID: 2. Inspected TLB entry 4. VPN: 4. PFN: 14. Valid: 1. PID: 2. Timestamp: 4
Current PID: 2. Inspected TLB entry 5. VPN: 5. PFN: 15. Valid: 1. PID: 2. Timestamp: 5
Current PID: 2. Inspected TLB entry 6. VPN: 6. PFN: 16. Valid: 1. PID: 2. Timestamp: 6
Current PID: 2. Inspected TLB entry 7. VPN: 7. PFN: 17. Valid: 1. PID: 2. Timestamp: 7
Current PID: 2. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 10
Current PID: 2. Stored immediate 11 into location 0
Current PID: 2. Mapped virtual page number 8 to physical frame number 18
Current PID: 2. Inspected TLB entry 0. VPN: 8. PFN: 18. Valid: 1. PID: 2. Timestamp: 8
Current PID: 2. Inspected TLB entry 1. VPN: 1. PFN: 11. Valid: 1. PID: 2. Timestamp: 1
Current PID: 2. Inspected TLB entry 2. VPN: 2. PFN: 12. Valid: 1. PID: 2. Timestamp: 2
Current PID: 2. Inspected TLB entry 3. VPN: 3. PFN: 13. Valid: 1. PID: 2. Timestamp: 3
Current PID: 2. Inspected TLB entry 4. VPN: 4. PFN: 14. Valid: 1. PID: 2. Timestamp: 4
Current PID: 2. Inspected TLB entry 5. VPN: 5. PFN: 15. Valid: 1. PID: 2. Timestamp: 5
Current PID: 2. Inspected TLB entry 6. VPN: 6. PFN: 16. Valid: 1. PID: 2. Timestamp: 6
Current PID: 2. Inspected TLB entry 7. VPN: 7. PFN: 17. Valid: 1. PID: 2. Timestamp: 7


when it should be this


Current PID: 0. Memory instantiation complete. OFF bits: 3. PFN bits: 5. VPN bits: 4
Current PID: 2. Switched execution context to process: 2
Current PID: 2. Mapped virtual page number 0 to physical frame number 10
Current PID: 2. Mapped virtual page number 1 to physical frame number 11
Current PID: 2. Mapped virtual page number 2 to physical frame number 12
Current PID: 2. Mapped virtual page number 3 to physical frame number 13
Current PID: 2. Mapped virtual page number 4 to physical frame number 14
Current PID: 2. Mapped virtual page number 5 to physical frame number 15
Current PID: 2. Mapped virtual page number 6 to physical frame number 16
Current PID: 2. Mapped virtual page number 7 to physical frame number 17
Current PID: 2. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 10
Current PID: 2. Stored immediate 10 into location 0
Current PID: 2. Translating. Lookup for VPN 1 hit in TLB entry 1. PFN is 11
Current PID: 2. Stored immediate 11 into location 8
Current PID: 2. Translating. Lookup for VPN 2 hit in TLB entry 2. PFN is 12
Current PID: 2. Stored immediate 12 into location 16
Current PID: 2. Translating. Lookup for VPN 3 hit in TLB entry 3. PFN is 13
Current PID: 2. Stored immediate 13 into location 24
Current PID: 2. Translating. Lookup for VPN 4 hit in TLB entry 4. PFN is 14
Current PID: 2. Stored immediate 14 into location 32
Current PID: 2. Translating. Lookup for VPN 5 hit in TLB entry 5. PFN is 15
Current PID: 2. Stored immediate 15 into location 40
Current PID: 2. Translating. Lookup for VPN 6 hit in TLB entry 6. PFN is 16
Current PID: 2. Stored immediate 16 into location 48
Current PID: 2. Translating. Lookup for VPN 7 hit in TLB entry 7. PFN is 17
Current PID: 2. Stored immediate 17 into location 56
Current PID: 2. Inspected TLB entry 0. VPN: 0. PFN: 10. Valid: 1. PID: 2. Timestamp: 3
Current PID: 2. Inspected TLB entry 1. VPN: 1. PFN: 11. Valid: 1. PID: 2. Timestamp: 4
Current PID: 2. Inspected TLB entry 2. VPN: 2. PFN: 12. Valid: 1. PID: 2. Timestamp: 5
Current PID: 2. Inspected TLB entry 3. VPN: 3. PFN: 13. Valid: 1. PID: 2. Timestamp: 6
Current PID: 2. Inspected TLB entry 4. VPN: 4. PFN: 14. Valid: 1. PID: 2. Timestamp: 7
Current PID: 2. Inspected TLB entry 5. VPN: 5. PFN: 15. Valid: 1. PID: 2. Timestamp: 8
Current PID: 2. Inspected TLB entry 6. VPN: 6. PFN: 16. Valid: 1. PID: 2. Timestamp: 9
Current PID: 2. Inspected TLB entry 7. VPN: 7. PFN: 17. Valid: 1. PID: 2. Timestamp: 10
Current PID: 2. Translating. Lookup for VPN 0 hit in TLB entry 0. PFN is 10
Current PID: 2. Stored immediate 11 into location 0
Current PID: 2. Mapped virtual page number 8 to physical frame number 18
Current PID: 2. Inspected TLB entry 0. VPN: 8. PFN: 18. Valid: 1. PID: 2. Timestamp: 28
Current PID: 2. Inspected TLB entry 1. VPN: 1. PFN: 11. Valid: 1. PID: 2. Timestamp: 4
Current PID: 2. Inspected TLB entry 2. VPN: 2. PFN: 12. Valid: 1. PID: 2. Timestamp: 5
Current PID: 2. Inspected TLB entry 3. VPN: 3. PFN: 13. Valid: 1. PID: 2. Timestamp: 6
Current PID: 2. Inspected TLB entry 4. VPN: 4. PFN: 14. Valid: 1. PID: 2. Timestamp: 7
Current PID: 2. Inspected TLB entry 5. VPN: 5. PFN: 15. Valid: 1. PID: 2. Timestamp: 8
Current PID: 2. Inspected TLB entry 6. VPN: 6. PFN: 16. Valid: 1. PID: 2. Timestamp: 9
Current PID: 2. Inspected TLB entry 7. VPN: 7. PFN: 17. Valid: 1. PID: 2. Timestamp: 10


it seems the issue is the timestamp but I dont understand why it doesnt do this right and the other tests were fine

Running test batch 1: basic tests
Running test Test 1.1: empty trace... PASSED
Running test Test 1.2: define... PASSED
Running test Test 1.3: double-defines... PASSED
Running test Test 1.4: context switching... PASSED
Running test Test 1.5: invalid context switch... PASSED
Done!
Running test batch 2: instructions tests
Running test Test 2.1: load immediate into register... PASSED
Running test Test 2.2: load immediate into invalid register... PASSED
Running test Test 2.3: instruction without define... PASSED
Running test Test 2.4: add... PASSED
Running test Test 2.5: add with context switch... PASSED
Done!
Running test batch 3: mapping tests
Running test Test 3.1: basic mapping... PASSED
Running test Test 3.2: basic unmapping... PASSED
Running test Test 3.3: store/load in mapped memory... PASSED
Running test Test 3.4: load from unmapped memory... PASSED
Running test Test 3.5: page shared between processes... PASSED
Done!
Running test batch 4: inspection tests
Running test Test 4.1: inspecting registers... PASSED
Running test Test 4.2: inspecting the page table... PASSED
Running test Test 4.3: Inspecting physical Memory... PASSED
Running test Test 4.4: FIFO TLB replacement strategy... FAILED
Done!
Running test batch 5: complex tests
Running test Test 5.1: mapping all the thingss... FAILED
Done!