/* Teaching model, not a reader of real hardware page tables.
 * Four virtual pages, 4 KiB/page, two-entry fully associative LRU TLB.
 * All mapped pages resident; successful accesses alone update TLB state.
 */
#include <stdio.h>
#include <stdbool.h>
#include <stddef.h>
#define PAGE_SIZE 4096u
struct pte { unsigned frame; bool mapped, writable; };
static const struct pte pt[] = {{3,true,true},{9,true,false},{0,false,false},{1,true,true}};
struct entry { unsigned page, frame, last; bool valid, writable; };
static struct entry tlb[2];
static unsigned tick;
static void access_address(unsigned address, char operation) {
    unsigned page = address / PAGE_SIZE, offset = address % PAGE_SIZE;
    printf("%c VA=0x%04X page=%u offset=%u ", operation, address, page, offset);
    if (page >= sizeof pt / sizeof pt[0] || !pt[page].mapped) { puts("UNMAPPED"); return; }
    int slot = -1;
    for (int i=0;i<2;i++) if (tlb[i].valid && tlb[i].page == page) slot=i;
    bool hit = slot >= 0;
    bool writable = hit ? tlb[slot].writable : pt[page].writable;
    if (operation == 'W' && !writable) { printf("TLB=%s PROTECTION\n",hit?"HIT":"MISS"); return; }
    if (!hit) {
        slot = !tlb[0].valid ? 0 : !tlb[1].valid ? 1 : tlb[0].last <= tlb[1].last ? 0 : 1;
        tlb[slot] = (struct entry){page,pt[page].frame,0,true,pt[page].writable};
    }
    tlb[slot].last=++tick;
    printf("TLB=%s frame=%u PA=0x%04X\n",hit?"HIT":"MISS",tlb[slot].frame,tlb[slot].frame*PAGE_SIZE+offset);
}
int main(void) {
    access_address(0x0FFF,'R'); access_address(0x1000,'R');
    access_address(0x0001,'R'); access_address(0x3000,'R');
    access_address(0x1234,'R'); access_address(0x1234,'W');
    access_address(0x2000,'R'); access_address(0x4000,'R');
    return 0;
}
