import java.util.Scanner; import java.io.FileNotFoundException; import java.io.FileInputStream; /** Driver.java for simple page table simulation. * Let's read a short input file that contains the following information: * size of RAM in MB (must be power of two from 1 to 2048) * size of page/frame in KB (must be power of two from 1 to 16) * Starting logical hex address of text (i.e. code) - assume this is * expressed in hex with the leading "0x" string. * List of logical data addresses accessed by a hypothetical program - * again, assume these are specified in hex prepended with "0x". * Let's assume that: * The text will only occupy one page. * The size of the logical address space is 4 GB (32 bit addressing). * We won't do error checking of the input parameters. * The program needs to do the following: * 1. Determine the number of bits of a logical address allocated to * logical page number and page offset. * 2. Determine the number of bits of a physical address allocated to * physical page number and page offset. * (Hint: the page offsets are the same) * 3. Determine the number of logical pages in our address space. * 4. Determine the number of physical pages in RAM. * 5. Create a page table. Initialize it with one page being the * page containing the text segment, which will go into physical * page 0. You may assume that every time you need to allocate a new * physical page, you can increment to the next sequential number. * 6. Now the fun part: for each of the logical data addresses in * the input, indicate whether each is a hit or miss in the page * table. Update the page table as needed. * 7. While reading logical data addresses, also detect if any address * lies in physical page 0. If so, announce this as a "segmentation * fault" but let the program continue. * 8. The program should terminate early if we run out of physical pages. * In other words, if you need to allocate a new physical page, but * no free page exists, halt the program with an error message. * 9. At the end of the program, print the page table. You can also * use this routine for debugging, and to print out just before exiting * on failure. * Functions implemented at the end of the program may be helpful. */ public class Driver { // Assume that the input file is specified at the command line. public static void main(String [] args) throws FileNotFoundException { if (args.length != 1) { System.out.printf("Usage: java Driver \n"); System.exit(1); } Scanner in = new Scanner(new FileInputStream(args[0])); // Read input file. First is RAM size, given after the '=' sign. String line = in.nextLine(); int loc = line.indexOf('='); int sizeRamMegabytes = Integer.parseInt(line.substring(loc+1).trim()); // Similarly read the page size. line = in.nextLine(); loc = line.indexOf('='); int sizePageKilobytes = Integer.parseInt(line.substring(loc+1).trim()); // Get the text segment start address. // Don't forget to chop off the 0x and interpret string as hex instead of dec. line = in.nextLine(); loc = line.indexOf('='); String hexString = line.substring(loc+1).trim().substring(2); int textStartAddress = Integer.parseInt(hexString, 16); ////////////////////////////////////////////////////////////////////////// // At this point, we have all the information we need to answer // simple questions about the memory system, before we read the logical // data addresses. ////////////////////////////////////////////////////////////////////////// // Echo the input. System.out.printf("Size of RAM = %d MB.\n", sizeRamMegabytes); System.out.printf("Size of a page = %d KB.\n", sizePageKilobytes); System.out.printf("We assume the logical address has 32 bits.\n"); // How is the logical address partitioned? There are a total of 32 bits. // It is split into 2 pieces: the logical page number, and page offset. // The page size immediately can tell us how many bits go to the page offset. int numBitsPageOffset = -123; int numBitsLogicalPageNumber = -123; // How is the physical address partitioned? // First, we need to determine the total number of bits in a physical // address. This is based directly on the size of RAM. // We will then already know the size of the page offset, because it's // the same as for the logical address! It will then be easy to find // the number of bits for the physical page number. int numBitsPhysicalAddress = -123; int numBitsPhysicalPageNumber = -123; // What are the number of logical pages and number of physical pages? // They are 2^logical page number and 2^physical page number. int numLogicalPages = -123; int numPhysicalPages = -123; // Print out data we just calculated. System.out.printf("The page offset has %d bits.\n", numBitsPageOffset); System.out.printf("The logical page number has %d bits.\n", numBitsLogicalPageNumber); System.out.printf("The physical address has %d bits.\n", numBitsPhysicalAddress); System.out.printf("The physical page number has %d bits.\n", numBitsPhysicalPageNumber); System.out.printf("There are %d logical pages.\n", numLogicalPages); System.out.printf("There are %d physical pages.\n", numPhysicalPages); // We're ready to create a page table. // The number of entries is the number of logical pages. // What does an entry consist of? The whole page table is an array, // so we index into the page table using a logical page number. // The number contained inside the page table is a physical page number. // Thus, in this bare-bones implementation, the page table just // needs to be a big array of integers. // Let's initialize the page table to be empty. // Store the number -1 in each cell to represent an unused or unmapped // logical page. // Next, we have to put the text of the hypothetical input program into // page 0 of physical memory. In other words, the number 0 is stored // in the page table at the index equal to the logical page containing // the starting text address. First, need to calculate this logical page #. int logicalPageNumber = -123; pageTable[logicalPageNumber] = 0; System.out.printf("Program text has logical page number %d.\n", logicalPageNumber); // Now ready for loop. // Read and process each data address. int nextAvailablePhysicalPage = 1; while (in.hasNextLine()) { line = in.nextLine(); loc = line.indexOf('='); hexString = line.substring(loc+1).trim().substring(2); int address = Integer.parseInt(hexString, 16); // Determine the logical page number for this logical address. // See if we have a page table hit or miss. // If a miss, update the page table. // Keep track of the next available physical page number. // Stop early if we run out of physical pages. // Also stop early if we reference physical page 0. logicalPageNumber = -123; System.out.printf("Address 0x%s has logical page number %d.\n", hexString, logicalPageNumber); // Use this logical page number as an index into the page table. // If the cell equals -1, this is a miss, and we need to "bring in" // a new physical page. If it was not -1, then it was a hit. // Also handle a segmentation fault and a full RAM. } // Print out the page table. System.out.printf("We're done.\n"); printPageTable(pageTable); } // Assuming that n is a power of 2, which power is it? public static int log2(int n) { for (int i = 0; i <= 31; ++i) if ((1 << i) == n) return i; // If we make it this far, n was not a power of 2. System.out.printf("Error: log2(n) called with bad argument %d.\n", n); System.exit(1); return -1; // Java compiler insists on a return statement. } // Given a logical address and the number of bits in the page offset, // determine its logical page number, public static int findLogicalPageNumber(int address, int pageOffsetBits) { return address >>> pageOffsetBits; } // Print the contents of the page table. Just the entries that are not // empty (i.e. not -1). public static void printPageTable(int [] pt) { System.out.printf("Page table:\n"); for (int i = 0; i < pt.length; ++i) if (pt[i] != -1) System.out.printf(" logical page %d mapped to physical page %d\n", i, pt[i]); } }