Skip to content

Instantly share code, notes, and snippets.

@korydondzila
Created March 23, 2015 05:22
Show Gist options
  • Save korydondzila/c78d3e25b26c45fefab7 to your computer and use it in GitHub Desktop.
Save korydondzila/c78d3e25b26c45fefab7 to your computer and use it in GitHub Desktop.
Computer Organization project to simulate direct cache mapping
/**
* 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