Created
March 23, 2015 05:22
-
-
Save korydondzila/c78d3e25b26c45fefab7 to your computer and use it in GitHub Desktop.
Computer Organization project to simulate direct cache mapping
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* File: project1_dondzila.java | |
* Package: virtual_cache | |
* Project: COMP_222 | |
* Date: Mar 20, 2015, 9:30:11 PM | |
* Purpose: To simulate direct cache mapping | |
* @author Kory Dondzila | |
* @version "%I%, %G%" | |
* Copyright: 2015 | |
*/ | |
package virtual_cache; | |
import java.util.Scanner; | |
/** | |
* Simulates cache memory | |
*/ | |
public class project1_dondzila | |
{ | |
public static void main( String[] args ) | |
{ | |
Scanner input = new Scanner(System.in); | |
int choice = -1; | |
VirtualMemory VMem = new VirtualMemory(); | |
while ( choice != 0 ) | |
{ | |
try | |
{ | |
choice = Integer.parseInt( menu(input) ); | |
} | |
catch ( NumberFormatException e ) | |
{ | |
System.out.println( "Option must be an integer." ); | |
e.printStackTrace(); | |
choice = -1; | |
} | |
switch ( choice ) | |
{ | |
case 1: | |
VMem = parameters( input ); | |
break; | |
case 2: | |
VMem = read( input, VMem ); | |
break; | |
case 3: | |
VMem = write( input, VMem ); | |
break; | |
default: | |
break; | |
} | |
} | |
input.close(); | |
} | |
// Menu display | |
private static String menu( Scanner input ) | |
{ | |
System.out.printf( "\n%s\n", "-----------------------------------" ); | |
System.out.printf( "%2d | %s\n", 1, "Set Perameters" ); | |
System.out.printf( "%2d | %s\n", 2, "Read Cache" ); | |
System.out.printf( "%2d | %s\n", 3, "Write to Cache" ); | |
System.out.printf( "%2d | %s\n", 0, "Exit" ); | |
System.out.printf( "%s\n", "-----------------------------------" ); | |
System.out.print( "Choose an option: " ); | |
return input.nextLine(); | |
} | |
// Get parameters and initialize new virtual memory | |
private static VirtualMemory parameters( Scanner input ) | |
{ | |
int memSize = 0, cacheSize = 0, blockSize = 0; | |
memSize = getSize( input, memSize, cacheSize, 3 ); | |
cacheSize = getSize( input, memSize, cacheSize, 2 ); | |
blockSize = getSize( input, memSize, cacheSize, 1 ); | |
return new VirtualMemory( memSize, cacheSize, blockSize ); | |
} | |
// Get the size for main memory, cache and block. | |
private static int getSize( Scanner input, int memSize, int cacheSize, int whichSize ) | |
{ | |
boolean good = false; | |
double size = 0; | |
while ( !good ) | |
{ | |
if ( whichSize == 1 ) | |
System.out.print( "Enter block size(words/block): " ); | |
else if ( whichSize == 2 ) | |
System.out.print( "Enter cache size(words): " ); | |
else | |
System.out.print( "Enter main memory size(words): " ); | |
try | |
{ | |
good = true; | |
size = Math.log( Integer.parseInt( input.nextLine() ) ) / Math.log( 2 ); | |
// Makes checks based on which size is called | |
if ( size != (int)size || size < whichSize || ( whichSize > 1 ? ( whichSize > 2 ? false : size > memSize ) : size > cacheSize ) ) | |
{ | |
good = false; | |
if ( whichSize == 1 ) | |
System.out.println( "Must be a power of 2, at least 2 but less than " + Math.pow( 2, cacheSize ) ); | |
else if ( whichSize == 2 ) | |
System.out.println( "Must be a power of 2, at least 4 but less than " + Math.pow( 2, memSize ) ); | |
else | |
System.out.println( "Must be a power of 2, at least 8" ); | |
} | |
} | |
catch ( NumberFormatException e) | |
{ | |
System.out.println( "Must be an integer" ); | |
e.printStackTrace(); | |
good = false; | |
} | |
} | |
return (int)size; | |
} | |
// Read from virtual memory | |
private static VirtualMemory read( Scanner input, VirtualMemory VMem ) | |
{ | |
VMem.readCache( getAddress( input, VMem, false ) ); | |
return VMem; | |
} | |
// Write to virtual memory | |
private static VirtualMemory write( Scanner input, VirtualMemory VMem ) | |
{ | |
boolean good = false; | |
int value = 0; | |
int address = getAddress( input, VMem, true ); | |
while ( !good ) | |
{ | |
System.out.print( "Enter value to write: " ); | |
try | |
{ | |
good = true; | |
value = Integer.parseInt( input.nextLine() ); | |
} | |
catch ( NumberFormatException e ) | |
{ | |
System.out.println( "Must be an integer" ); | |
e.printStackTrace(); | |
good = false; | |
} | |
} | |
VMem.writeCache( address, value ); | |
return VMem; | |
} | |
// Get the address to read from or write to | |
private static int getAddress( Scanner input, VirtualMemory VMem, boolean write ) | |
{ | |
boolean good = false; | |
int address = 0; | |
while ( !good ) | |
{ | |
if ( write ) | |
System.out.print( "Enter main memory address to write to: " ); | |
else | |
System.out.print( "Enter main memory address to read from: " ); | |
try | |
{ | |
good = true; | |
address = Integer.parseInt( input.nextLine() ); | |
if ( address < 0 || address >= VMem.getMemSize() ) | |
{ | |
good = false; | |
System.out.println( "Address must be between 0 and " + (VMem.getMemSize() - 1) ); | |
} | |
} | |
catch ( NumberFormatException e ) | |
{ | |
System.out.println( "Must be an integer" ); | |
e.printStackTrace(); | |
good = false; | |
} | |
} | |
return address; | |
} | |
} | |
/** | |
* The virtual memory | |
*/ | |
class VirtualMemory | |
{ | |
/** | |
* The main memory | |
*/ | |
private int[] mainMemory; | |
/** | |
* The cache | |
*/ | |
private CacheBlock[] cache; | |
/** | |
* Byte size of memory, cache and block | |
*/ | |
private int memSize, cacheSize, blockSize; | |
/** | |
* Default constructor | |
*/ | |
public VirtualMemory() {} | |
/** | |
* @param memSize the power of 2 for memory | |
* @param cacheSize the power of 2 for cache | |
* @param blockSize the power of 2 for block size | |
*/ | |
public VirtualMemory( int memSize, int cacheSize, int blockSize ) | |
{ | |
// Convert to byte amount | |
this.memSize = (int)Math.pow( 2, memSize ); | |
this.cacheSize = (int)Math.pow( 2, cacheSize ); | |
this.blockSize = (int)Math.pow( 2, blockSize ); | |
// Initialize main memory | |
mainMemory = new int[this.memSize]; | |
for ( int i = 0; i < mainMemory.length; i++ ) | |
{ | |
mainMemory[i] = mainMemory.length - i; | |
} | |
// Initialize cache | |
cache = new CacheBlock[this.cacheSize / this.blockSize]; | |
for ( int i = 0; i < cache.length; i++ ) | |
{ | |
cache[i] = new CacheBlock( this.blockSize ); | |
} | |
} | |
/** | |
* @return the memSize | |
*/ | |
public int getMemSize() | |
{ | |
return this.memSize; | |
} | |
/** | |
* @return the cacheSize | |
*/ | |
public int getCacheSize() | |
{ | |
return this.cacheSize; | |
} | |
/** | |
* @return the blockSize | |
*/ | |
public int getBlockSize() | |
{ | |
return this.blockSize; | |
} | |
/** | |
* @param address the address to read | |
*/ | |
public void readCache( int address ) | |
{ | |
readWriteCache( address, 0, false ); | |
} | |
/** | |
* @param address the address to write to | |
* @param value the value to write | |
*/ | |
public void writeCache( int address, int value ) | |
{ | |
mainMemory[address] = value; | |
readWriteCache( address, value, true ); | |
} | |
// Read from or write to cache | |
private void readWriteCache( int address, int value, boolean write ) | |
{ | |
int tag = address / cacheSize; | |
int line = address / blockSize % ( cacheSize / blockSize ); | |
int word = address % blockSize; | |
// Cache miss on read/write, get values from main memory | |
if ( tag != cache[line].getTag() ) | |
{ | |
if ( write ) | |
System.out.println( "Write miss!" ); | |
else | |
System.out.println( "Read miss!" ); | |
address -= word; | |
int[] block = new int[blockSize]; | |
for ( int i = 0; i < blockSize; i++ ) | |
{ | |
block[i] = mainMemory[address + i]; | |
} | |
cache[line].setTag( tag ); | |
cache[line].setBlock( block ); | |
} | |
else if ( write ) // Hit on write, write value to cache | |
{ | |
cache[line].setWord( word, value ); | |
} | |
System.out.println( "Word " + word + " of block " + line + " with tag " + tag + " contains value " + cache[line].getWord( word ) ); | |
} | |
} | |
/** | |
* The cache block/line element | |
*/ | |
class CacheBlock | |
{ | |
/** | |
* Cache block/line tag | |
*/ | |
private int tag; | |
/** | |
* Cache block/line | |
*/ | |
private int[] block; | |
/** | |
* Cache block constructor | |
* @param size The size of the cache block in bytes | |
*/ | |
public CacheBlock( int size ) | |
{ | |
tag = -1; | |
block = new int[ size ]; | |
} | |
/** | |
* @return the tag | |
*/ | |
public int getTag() | |
{ | |
return this.tag; | |
} | |
/** | |
* @param tag the tag to set | |
*/ | |
public void setTag( int tag ) | |
{ | |
this.tag = tag; | |
} | |
/** | |
* @param block the block to set | |
*/ | |
public void setBlock( int[] block ) | |
{ | |
this.block = block; | |
} | |
/** | |
* @param word the word to get | |
* @return the word | |
*/ | |
public int getWord( int word ) | |
{ | |
return block[word]; | |
} | |
/** | |
* @param word the word to set | |
* @param value the value to set word to | |
*/ | |
public void setWord( int word, int value ) | |
{ | |
block[word] = value; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment