Implement a Cache that meets the specifications below.
Cache Specifications
Parameter | Value |
CPU Address | 10 bits |
Cache Data Size | 24 Bytes |
Number of Sets | 2 |
Number of Ways (Blocks per Set) | 3 |
Block Size | 4 Bytes |
Write Policy | Write Back |
Eviction Policy | LRU |
Inputs
Input Pin | Size (bits) | Description |
CpuAddress | 10 bits | The address the CPU wants to read from or write to |
CpuRead | 1 bit | 1 If the CPU wants to Read and 0 otherwise |
CpuWrite | 1 bit | 1 if the CPU wants to Write and 0 otherwise |
CpuWriteValue | 8 bits | The value the CPU wants to Write. Will only have a meaningful value is CpuWrite = 1 |
LineFromMem | 32 bits | The contents of the block you requested to read from memory |
All of the inputs will only be valid during the SINGLE clock cycle that your Cache says it is Ready. This means that you will have to save your inputs if you need them beyond that first clock cycle.
The only exception to this is LineFromMem. It will be valid as long as you say you want to read from memory. If you arent reading from memory LineFromMem will be EEE and Red (an Error). Dont worry about this. It is normal behavior. As soon as your request to read from memory it will be the value at MemAddress.
Outputs
Output Pin | Size (in bits) | Description |
Ready | 1 bit | 1 if your Cache is ready to start a new request. If you are ready to start a new request it means you must have finished the old request. So at this point in time, your output will be checked. |
DidContain | 1 bit | 1 if your Cache contained the value the CPU asked for and 0 otherwise. Checked when Ready == 1 |
ByteRead | 8 bits | The value at the address the CPU requested to read. Checked when Ready == 1 and the last request the CPU made was a read. |
MemAddress | 8 bits | The address of the block you want to read from memory or the address of the block that you want to write Line2Memory back to. |
MemRead | 1 bit | 1 if you want to read the block at MemAddress and 0 otherwise. |
MemWrite | 1 bit | 1 if you want to write Line2Mem to MemAddress and 0 otherwise. |
Line2Mem | 32 bits | The block you want to write to MemAddress |
Why is MemAddress 8 bits instead of 10?
Our Memory is going to be Block Addressable instead of Byte Addressable. This means that each block has an address instead of each byte. This enables you to read a block from/write a block to memory in a single clock cycle which should help simplify your design a little. It should be pretty easy to figure out which bits to drop to form MemAddress. Hint: it is bits that help you pick out the byte within a block.
When are outputs checked?
- DidContain: At the end of every operation once your circuit becomes Ready.
- ByteRead: At the end of a read operation once your circuit becomes Ready.
- MemRead: Whenever you read from memory it increments the MissCounter.
Timing Restrictions
Your circuit must be able to complete a Read/Write request within 10 clock cycles. If you take longer than 10 clock cycles the tester will automatically advance to the next case. This will cause your Cache to start to desync from the tester and so will get everything wrong if you are taking too long. You can certainly finish in less than 10 clock cycles, I only took 7 but Ive seen students get as low as 2.
Testing
- Open the grading circuit
- Click on the Cache folder and select reload library
- Double-check that your updates are visible inside of the grader. If your changes dont show up, close your solution circuit and try reloading again. If the changes still fail to show up, close the grader and reopen it and then reload the library.
- Open the subcircuit named CheckerCirc and
- Right-click the ROM inside of it
- Select Load Image
- Select one of the provided files that ends in _sol.txt.
- Eample: seq_read1_seq_mem_sol.txt
- Open the subcircuit named InputGeneratorCirc and
- Right-click the ROM inside of it
- Select Load Image
- Select the corresponding input file that matches with the solution file. This will be the file that shares its name with the first part of the solution file.
- Example: seq_read1.txt
- Go back to the main subcircuit
- Right-click the RAM
- Select Load Image
- Select the corresponding memory file that matches with the solution file. This will be the file that shares its name with the second part of the solution file.
- Example: seq_mem.txt
Anytime your reset a test case you must RELOAD the RAM! The RAM is the only one that has to be reloaded. The ROMs will maintain the last value you put in them.
At the bottom of the the main circuit you will find probes that show your circuits inputs, outputs, answers, how many reads you got correct, how many times you said you hit, and how many misses(memory reads) you had. This is a good place to look when you are debugging to get a high level overview of what your cache is doing.
If you open the solution files in a text editor you will find what the correct values for all of the stats should be for that test case.
Testing Order
I recommend running the test cases in the following order
- seq_read1_seq_mem_sol.txt
- seq_write1_seq_mem_sol.txt
- set1_targeted_read_seq_mem_sol.txt
- set0_targeted_write_seq_mem_sol.txt
- random0_seq_mem_sol.txt
- final_test_rand_mem_mem_sol.txt.
User Created Tests
If you want to make your own test, you can use cache_test_maker.py to create your own tests. It should be fairly easy to follow the documentation inside if you feel like using it.
Reviews
There are no reviews yet.