Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cache Simulator

A configurable cache memory simulator written in Python, built for a Computer Architecture course at Universidade de Caxias do Sul. It replays a trace of memory accesses against a simulated cache and reports hit rates, main memory traffic, and average access time.

Cache size, block size, associativity, write policy, and replacement policy are all configurable, so the same trace can be run under different configurations to measure how each parameter affects performance.

Requirements

  • Python 3.8+
  • No external dependencies (standard library only)

Getting started

git clone https://github.com/YasmimAr/cache-simulator.git
cd cache-simulator

Usage

python3 cache_simulator.py <write> <block> <lines> <assoc> <hit> <repl> <t_read> [t_write]

The trace file is not passed as an argument. The program always reads oficial.cache from the same directory as the script.

Parameters

# Parameter Description
1 write Write policy: 0 = write-through, 1 = write-back
2 block Block/line size in bytes (power of 2)
3 lines Total number of cache lines (power of 2)
4 assoc Associativity (power of 2, must be ≤ number of lines)
5 hit Hit time, in ns
6 repl Replacement policy: LRU or RANDOM
7 t_read Main memory read time, in ns
8 t_write (optional) Main memory write time, in ns. Defaults to t_read

Total cache size is block × lines bytes. Setting assoc to 1 gives a direct-mapped cache; setting it equal to lines gives a fully associative cache. Every mapping scheme is therefore reachable from the same simulator by varying a single parameter.

Running with no arguments (or the wrong number of them) prints the usage text.

Input file

oficial.cache contains one memory access per line:

<hex_address> <operation>
  • hex_address — 32-bit address in hexadecimal
  • operationR for read, W for write

Blank lines are ignored. Malformed lines abort the run and report the offending line number. Example:

00003A1C R
00003A20 W
0000F004 R

Examples

Write-back, 8 KB cache (64 lines × 128 bytes), 4-way, 1 ns hit time, 10 ns main memory:

python3 cache_simulator.py 1 128 64 4 1 LRU 10

Write-through, 64-byte blocks, 4096 lines, 2-way, 10 ns hit time, 80 ns main memory:

python3 cache_simulator.py 0 64 4096 2 10 LRU 80

Output

The simulator echoes the configuration it ran with, then reports the results:

PASTE REAL OUTPUT HERE

Results

The simulator was used to run a series of experiments over a fixed 51,200-access trace, varying one parameter at a time. The full study, including the remaining experiments and complete result tables, is in the report linked below.

Associativity

Cache size fixed at 8 KB, 128-byte blocks, write-back, LRU:

Ways Hit rate Avg. access time MM reads MM writes
1 74.96% 19.03 ns 12,822 2,048
2 87.94% 11.24 ns 6,176 1,026
4 92.93% 8.24 ns 3,621 515
8 89.93% 10.04 ns 5,154 1,026
16 99.91% 4.05 ns 44 4
32 99.91% 4.05 ns 44 4
64 99.91% 4.05 ns 44 4

Conflict misses drop sharply as associativity grows, and the curve flattens completely at 16 ways, where the working set stops colliding. The dip at 8 ways is not a measurement error: set-associative LRU is not a stack algorithm, so adding ways can occasionally increase misses for a particular access pattern.

Block size

Cache size fixed at 8 KB, write-through, LRU, 2-way:

Block size Hit rate Avg. access time MM reads
8 B 84.83% 13.10 ns 1,621
16 B 84.83% 13.10 ns 1,621
64 B 80.90% 15.46 ns 3,633
256 B 74.97% 19.02 ns 6,673
1 KB 64.00% 25.60 ns 12,288
4 KB 56.00% 30.40 ns 16,384

Larger blocks exploit spatial locality, but with a fixed 8 KB capacity they also reduce the number of blocks resident at once. On this trace the second effect dominates throughout, and the smallest blocks win.

Memory traffic: write-through vs write-back

Same configurations run under both write policies, LRU replacement:

Cache Block Ways WT total WB total
8 KB 64 B 2 9,777 6,196
8 KB 64 B 4 8,755 3,641
8 KB 128 B 2 10,783 7,202
8 KB 128 B 4 9,250 4,136
16 KB 64 B 2 6,200 3,641
16 KB 64 B 4 6,200 3,130
16 KB 128 B 2 7,206 4,647
16 KB 128 B 4 6,184 3,114

Write-through propagates every write to main memory, so its write count is pinned at 6,144 — one per write in the trace — regardless of configuration. Write-back coalesces repeated writes to the same block into a single memory write when the line is evicted, averaging 771 writes across these runs, an 8× reduction in write traffic.

Best configuration found

8 KB cache, 128-byte blocks, 16-way, write-back, LRU: 99.91% hit rate at 4.05 ns average access time. This is the best result under a performance-first criterion; a design weighing hardware cost would not necessarily pick 16-way.

Report

The full technical report — methodology, all result tables, and discussion — is available in docs/report.pdf. It is written in Portuguese.

Simulation model

A few modeling decisions worth stating explicitly, since simulators differ on these and results are not comparable across tools otherwise:

  • Allocation policy is tied to write policy. Write-back uses write-allocate: a write miss fetches the block into the cache and marks it dirty. Write-through uses no-write-allocate: a write miss goes straight to main memory without allocating a line. This is the conventional pairing, but the two dimensions are independent in principle.
  • Write-backs are assumed to be buffered. Evicting a dirty line counts as main memory traffic, but adds no latency to the access being served.
  • Dirty lines are flushed at the end of the run. Every valid dirty line still resident when the trace finishes counts as one additional main memory write, so the reported write traffic accounts for all modified data rather than only what was evicted mid-run.
  • Addresses are treated as 32 bits wide.
  • RANDOM is not seeded, so runs using random replacement vary between executions. LRU is fully deterministic.

Scope

This was a university assignment, kept close to its original form. It simulates a single level of cache with a unified instruction/data path, and models timing as a simple sum of hit and main memory latencies — no pipelining, no prefetching, no multi-level hierarchy.

Authors

Yasmim Arsego and Eduardo Machado Lopes — Fundamentos de Arquitetura de Computadores, Universidade de Caxias do Sul, 2026.

About

trabalho de fundamentos de arquitetura de computadores

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages