Get it to ACTUALLY compile :)
This commit is contained in:
@@ -1,493 +0,0 @@
|
|||||||
import cocotb
|
|
||||||
from cocotb.handle import Immediate, LogicArray
|
|
||||||
|
|
||||||
from cocotb.simulator import get_sim_time
|
|
||||||
|
|
||||||
from cocotb.clock import Clock
|
|
||||||
from cocotb.triggers import Timer, RisingEdge, FallingEdge, with_timeout
|
|
||||||
|
|
||||||
from enum import IntEnum
|
|
||||||
|
|
||||||
from collections import defaultdict
|
|
||||||
from collections.abc import Mapping
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
|
||||||
|
|
||||||
logger.setLevel(logging.INFO)
|
|
||||||
|
|
||||||
CLK_PERIOD = 5
|
|
||||||
|
|
||||||
reference_cache_data = defaultdict(bytearray)
|
|
||||||
|
|
||||||
higher_cache_data = defaultdict(bytearray)
|
|
||||||
|
|
||||||
async def cpu_sequencer(dut, sequence: Mapping[int, int, bool, bool]):
|
|
||||||
|
|
||||||
|
|
||||||
addr, do, we, sync = sequence[0]
|
|
||||||
|
|
||||||
dut.i_addr.value = addr
|
|
||||||
dut.i_data.value = do
|
|
||||||
dut.i_we.value = we
|
|
||||||
dut.i_sync.value = sync
|
|
||||||
|
|
||||||
await FallingEdge(dut.i_rst)
|
|
||||||
|
|
||||||
index = 1
|
|
||||||
|
|
||||||
while index < len(sequence):
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
if not dut.o_rdy.value:
|
|
||||||
continue
|
|
||||||
|
|
||||||
addr, do, we, sync = sequence[index]
|
|
||||||
|
|
||||||
dut.i_addr.value = addr
|
|
||||||
dut.i_data.value = do
|
|
||||||
dut.i_we.value = we
|
|
||||||
dut.i_sync.value = sync
|
|
||||||
|
|
||||||
index += 1
|
|
||||||
|
|
||||||
await Timer(150, "ns")
|
|
||||||
|
|
||||||
async def cpu_data_monitor(dut):
|
|
||||||
previous_address = 0
|
|
||||||
address = 0
|
|
||||||
|
|
||||||
we = 0
|
|
||||||
previous_we = 0
|
|
||||||
|
|
||||||
i_data = 0
|
|
||||||
previous_i_data = 0
|
|
||||||
|
|
||||||
await FallingEdge(dut.i_rst)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
if not dut.o_rdy.value:
|
|
||||||
continue
|
|
||||||
|
|
||||||
previous_address = address
|
|
||||||
previous_we = we
|
|
||||||
address = int(dut.i_addr.value)
|
|
||||||
we = int(dut.i_we.value)
|
|
||||||
|
|
||||||
previous_i_data = i_data
|
|
||||||
i_data = int(dut.i_data.value)
|
|
||||||
|
|
||||||
data = int(dut.o_data.value)
|
|
||||||
|
|
||||||
if previous_address == 0:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# don't care if it was a write
|
|
||||||
if previous_we:
|
|
||||||
|
|
||||||
index = (previous_address // 64) % 64
|
|
||||||
offset = previous_address % 64
|
|
||||||
|
|
||||||
cacheline = reference_cache_data[index]
|
|
||||||
|
|
||||||
cacheline[offset] = previous_i_data
|
|
||||||
logger.debug(f"We saw a write here {index=} {offset=} previous_data={previous_i_data:x}")
|
|
||||||
else:
|
|
||||||
index = (previous_address // 64) % 64
|
|
||||||
offset = previous_address % 64
|
|
||||||
|
|
||||||
cacheline = reference_cache_data[index]
|
|
||||||
|
|
||||||
expected_data = cacheline[offset]
|
|
||||||
|
|
||||||
if (data != expected_data):
|
|
||||||
logger.error(f"{get_sim_time()} {address=:x} {previous_address=:x} {data=:x} {expected_data=:x}")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def mmu_sequencer(dut):
|
|
||||||
while True:
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
dut.i_phys_address.value = dut.i_addr.value
|
|
||||||
|
|
||||||
async def handle_higher_level_cache(dut):
|
|
||||||
dut.i_cache_rdy.value = 0
|
|
||||||
|
|
||||||
class CacheCmd(IntEnum):
|
|
||||||
CACHE_NONE = 0
|
|
||||||
CACHE_READ = 1
|
|
||||||
CACHE_WRITE = 2
|
|
||||||
|
|
||||||
while True:
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
dut.i_cache_rdy.value = 0
|
|
||||||
|
|
||||||
if not dut.o_cache_valid.value:
|
|
||||||
continue
|
|
||||||
|
|
||||||
cmd = CacheCmd(dut.o_cache_cmd.value)
|
|
||||||
addr = int(dut.o_cache_addr.value)
|
|
||||||
|
|
||||||
logger.debug(f"{cmd=} {addr=}")
|
|
||||||
|
|
||||||
|
|
||||||
if cmd == CacheCmd.CACHE_READ:
|
|
||||||
|
|
||||||
if addr not in higher_cache_data:
|
|
||||||
data = bytearray(random.randbytes(64))
|
|
||||||
higher_cache_data[addr] = data
|
|
||||||
|
|
||||||
dut.i_cache_data.value = LogicArray.from_bytes(higher_cache_data[addr] , byteorder="little")
|
|
||||||
|
|
||||||
dut.i_cache_rdy.value = 1
|
|
||||||
|
|
||||||
reference_cache_data[int(dut.read_index.value)] = higher_cache_data[addr]
|
|
||||||
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
|
|
||||||
dut.i_cache_rdy.value = 0
|
|
||||||
|
|
||||||
elif cmd == CacheCmd.CACHE_WRITE:
|
|
||||||
|
|
||||||
dut.i_cache_rdy.value = 1
|
|
||||||
|
|
||||||
data = dut.o_cache_data.value.to_bytes(byteorder="little")
|
|
||||||
|
|
||||||
higher_cache_data[addr] = bytearray(data)
|
|
||||||
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
|
|
||||||
dut.i_cache_rdy.value = 0
|
|
||||||
|
|
||||||
@cocotb.test
|
|
||||||
async def sanity_test(dut):
|
|
||||||
expected_cache_misses = 0
|
|
||||||
expected_evictions = 0
|
|
||||||
|
|
||||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
|
||||||
cocotb.start_soon(mmu_sequencer(dut))
|
|
||||||
cocotb.start_soon(handle_higher_level_cache(dut))
|
|
||||||
cocotb.start_soon(cpu_data_monitor(dut))
|
|
||||||
|
|
||||||
cpu_sequence = [
|
|
||||||
(0x100, 0xaa, True, False),
|
|
||||||
(0x101, 0xbb, True, False),
|
|
||||||
(0x100, 0x00, False, False),
|
|
||||||
(0x101, 0x00, False, False),
|
|
||||||
(0x200, 0xcc, True, False),
|
|
||||||
(0x201, 0xdd, True, False),
|
|
||||||
(0x100, 0x00, False, False),
|
|
||||||
(0x101, 0x00, False, False),
|
|
||||||
(0x200, 0x00, False, False),
|
|
||||||
(0x201, 0x00, False, False),
|
|
||||||
(0x100, 0x11, True, False),
|
|
||||||
(0x101, 0x22, True, False),
|
|
||||||
(0x100, 0x00, False, False),
|
|
||||||
(0x200, 0x33, True, False),
|
|
||||||
(0x101, 0x00, False, False),
|
|
||||||
(0x201, 0x44, True, False),
|
|
||||||
(0x100, 0x00, False, False),
|
|
||||||
(0x200, 0x00, False, False),
|
|
||||||
(0x101, 0x00, False, False),
|
|
||||||
(0x201, 0x00, False, False),
|
|
||||||
]
|
|
||||||
|
|
||||||
dut.i_rst.value = Immediate(1)
|
|
||||||
for _ in range(10):
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
dut.i_rst.value = 0
|
|
||||||
|
|
||||||
await cpu_sequencer(dut, cpu_sequence)
|
|
||||||
|
|
||||||
|
|
||||||
expected_cache_misses = 2
|
|
||||||
expected_evictions = 0
|
|
||||||
|
|
||||||
dut_evictions = int(dut.eviction_count.value)
|
|
||||||
dut_misses = int(dut.cache_miss_count.value)
|
|
||||||
|
|
||||||
if dut_evictions != expected_evictions:
|
|
||||||
logger.error(f"Eviction count mismatch! Expected {expected_evictions}, saw {dut_evictions}")
|
|
||||||
|
|
||||||
if dut_misses != expected_cache_misses:
|
|
||||||
logger.error(f"Miss count mismatch! Expected {expected_cache_misses}, saw {dut_misses}")
|
|
||||||
|
|
||||||
|
|
||||||
@cocotb.test
|
|
||||||
async def clean_evict_test(dut):
|
|
||||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
|
||||||
cocotb.start_soon(mmu_sequencer(dut))
|
|
||||||
cocotb.start_soon(handle_higher_level_cache(dut))
|
|
||||||
cocotb.start_soon(cpu_data_monitor(dut))
|
|
||||||
|
|
||||||
# Read from one cacheline, then read from an aliased cacheline without writing.
|
|
||||||
# cacheline should be overwritten without evicting
|
|
||||||
cpu_sequence = [
|
|
||||||
(0x100, 0x00, False, False),
|
|
||||||
(0x1100, 0x00, False, False),
|
|
||||||
]
|
|
||||||
|
|
||||||
dut.i_rst.value = Immediate(1)
|
|
||||||
for _ in range(10):
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
dut.i_rst.value = 0
|
|
||||||
|
|
||||||
await cpu_sequencer(dut, cpu_sequence)
|
|
||||||
|
|
||||||
expected_cache_misses = 2
|
|
||||||
expected_evictions = 0
|
|
||||||
|
|
||||||
dut_evictions = int(dut.eviction_count.value)
|
|
||||||
dut_misses = int(dut.cache_miss_count.value)
|
|
||||||
|
|
||||||
if dut_evictions != expected_evictions:
|
|
||||||
logger.error(f"Eviction count mismatch! Expected {expected_evictions}, saw {dut_evictions}")
|
|
||||||
|
|
||||||
if dut_misses != expected_cache_misses:
|
|
||||||
logger.error(f"Miss count mismatch! Expected {expected_cache_misses}, saw {dut_misses}")
|
|
||||||
|
|
||||||
@cocotb.test
|
|
||||||
async def dirty_evict_test(dut):
|
|
||||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
|
||||||
cocotb.start_soon(mmu_sequencer(dut))
|
|
||||||
cocotb.start_soon(handle_higher_level_cache(dut))
|
|
||||||
cocotb.start_soon(cpu_data_monitor(dut))
|
|
||||||
|
|
||||||
# Read from one cacheline, then read from an aliased cacheline without writing.
|
|
||||||
# cacheline should be overwritten without evicting
|
|
||||||
cpu_sequence = [
|
|
||||||
(0x100, 0x41, True, False),
|
|
||||||
(0x101, 0x42, True, False),
|
|
||||||
(0x1100, 0x00, False, False),
|
|
||||||
(0x1100, 0xaa, True, False),
|
|
||||||
(0x100, 0x00, False, False)
|
|
||||||
]
|
|
||||||
|
|
||||||
dut.i_rst.value = Immediate(1)
|
|
||||||
for _ in range(10):
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
dut.i_rst.value = 0
|
|
||||||
|
|
||||||
await cpu_sequencer(dut, cpu_sequence)
|
|
||||||
|
|
||||||
expected_cache_misses = 3
|
|
||||||
expected_evictions = 2
|
|
||||||
|
|
||||||
dut_evictions = int(dut.eviction_count.value)
|
|
||||||
dut_misses = int(dut.cache_miss_count.value)
|
|
||||||
|
|
||||||
if dut_evictions != expected_evictions:
|
|
||||||
logger.error(f"Eviction count mismatch! Expected {expected_evictions}, saw {dut_evictions}")
|
|
||||||
|
|
||||||
if dut_misses != expected_cache_misses:
|
|
||||||
logger.error(f"Miss count mismatch! Expected {expected_cache_misses}, saw {dut_misses}")
|
|
||||||
|
|
||||||
|
|
||||||
@cocotb.test
|
|
||||||
async def long_write_thrash_test(dut):
|
|
||||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
|
||||||
cocotb.start_soon(mmu_sequencer(dut))
|
|
||||||
cocotb.start_soon(handle_higher_level_cache(dut))
|
|
||||||
cocotb.start_soon(cpu_data_monitor(dut))
|
|
||||||
|
|
||||||
num_lines_read = 2**20//64
|
|
||||||
|
|
||||||
cpu_sequence = [
|
|
||||||
(i*64, i % 256, True, False)
|
|
||||||
for i in range(num_lines_read)]
|
|
||||||
|
|
||||||
dut.i_rst.value = Immediate(1)
|
|
||||||
for _ in range(10):
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
dut.i_rst.value = 0
|
|
||||||
|
|
||||||
await cpu_sequencer(dut, cpu_sequence)
|
|
||||||
|
|
||||||
# The last 64 lines aren't evicted
|
|
||||||
expected_cache_misses = num_lines_read
|
|
||||||
expected_evictions = num_lines_read - 64
|
|
||||||
|
|
||||||
dut_evictions = int(dut.eviction_count.value)
|
|
||||||
dut_misses = int(dut.cache_miss_count.value)
|
|
||||||
|
|
||||||
if dut_evictions != expected_evictions:
|
|
||||||
logger.error(f"Eviction count mismatch! Expected {expected_evictions}, saw {dut_evictions}")
|
|
||||||
|
|
||||||
if dut_misses != expected_cache_misses:
|
|
||||||
logger.error(f"Miss count mismatch! Expected {expected_cache_misses}, saw {dut_misses}")
|
|
||||||
|
|
||||||
|
|
||||||
@cocotb.test
|
|
||||||
async def long_write_read_thrash_test(dut):
|
|
||||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
|
||||||
cocotb.start_soon(mmu_sequencer(dut))
|
|
||||||
cocotb.start_soon(handle_higher_level_cache(dut))
|
|
||||||
cocotb.start_soon(cpu_data_monitor(dut))
|
|
||||||
|
|
||||||
num_lines_read = 2**20//64
|
|
||||||
|
|
||||||
|
|
||||||
cpu_sequence = [
|
|
||||||
(i*64, i % 256, True, False)
|
|
||||||
for i in range(num_lines_read)]
|
|
||||||
|
|
||||||
cpu_sequence.extend([
|
|
||||||
(i*64, 0, False, False)
|
|
||||||
for i in range(num_lines_read)])
|
|
||||||
|
|
||||||
dut.i_rst.value = Immediate(1)
|
|
||||||
for _ in range(10):
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
dut.i_rst.value = 0
|
|
||||||
|
|
||||||
await cpu_sequencer(dut, cpu_sequence)
|
|
||||||
|
|
||||||
expected_cache_misses = num_lines_read * 2
|
|
||||||
expected_evictions = num_lines_read
|
|
||||||
|
|
||||||
dut_evictions = int(dut.eviction_count.value)
|
|
||||||
dut_misses = int(dut.cache_miss_count.value)
|
|
||||||
|
|
||||||
if dut_evictions != expected_evictions:
|
|
||||||
logger.error(f"Eviction count mismatch! Expected {expected_evictions}, saw {dut_evictions}")
|
|
||||||
|
|
||||||
if dut_misses != expected_cache_misses:
|
|
||||||
logger.error(f"Miss count mismatch! Expected {expected_cache_misses}, saw {dut_misses}")
|
|
||||||
|
|
||||||
|
|
||||||
@cocotb.test
|
|
||||||
async def long_write_linear_test(dut):
|
|
||||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
|
||||||
cocotb.start_soon(mmu_sequencer(dut))
|
|
||||||
cocotb.start_soon(handle_higher_level_cache(dut))
|
|
||||||
cocotb.start_soon(cpu_data_monitor(dut))
|
|
||||||
|
|
||||||
num_bytes_read = 2**16
|
|
||||||
|
|
||||||
cpu_sequence = [
|
|
||||||
(i, i % 256, True, False)
|
|
||||||
for i in range(num_bytes_read)]
|
|
||||||
|
|
||||||
dut.i_rst.value = Immediate(1)
|
|
||||||
for _ in range(10):
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
dut.i_rst.value = 0
|
|
||||||
|
|
||||||
await cpu_sequencer(dut, cpu_sequence)
|
|
||||||
|
|
||||||
expected_cache_misses = num_bytes_read // 64
|
|
||||||
expected_evictions = num_bytes_read//64 - 64
|
|
||||||
|
|
||||||
dut_evictions = int(dut.eviction_count.value)
|
|
||||||
dut_misses = int(dut.cache_miss_count.value)
|
|
||||||
|
|
||||||
if dut_evictions != expected_evictions:
|
|
||||||
logger.error(f"Eviction count mismatch! Expected {expected_evictions}, saw {dut_evictions}")
|
|
||||||
|
|
||||||
if dut_misses != expected_cache_misses:
|
|
||||||
logger.error(f"Miss count mismatch! Expected {expected_cache_misses}, saw {dut_misses}")
|
|
||||||
|
|
||||||
|
|
||||||
@cocotb.test
|
|
||||||
async def long_write_read_linear_test(dut):
|
|
||||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
|
||||||
cocotb.start_soon(mmu_sequencer(dut))
|
|
||||||
cocotb.start_soon(handle_higher_level_cache(dut))
|
|
||||||
cocotb.start_soon(cpu_data_monitor(dut))
|
|
||||||
|
|
||||||
num_bytes_read = 2**16
|
|
||||||
|
|
||||||
|
|
||||||
cpu_sequence = [
|
|
||||||
(i, i % 256, True, False)
|
|
||||||
for i in range(num_bytes_read)]
|
|
||||||
|
|
||||||
cpu_sequence.extend([
|
|
||||||
(i, 0, False, False)
|
|
||||||
for i in range(num_bytes_read)])
|
|
||||||
|
|
||||||
dut.i_rst.value = Immediate(1)
|
|
||||||
for _ in range(10):
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
dut.i_rst.value = 0
|
|
||||||
|
|
||||||
await cpu_sequencer(dut, cpu_sequence)
|
|
||||||
|
|
||||||
expected_cache_misses = (num_bytes_read // 64) * 2
|
|
||||||
expected_evictions = num_bytes_read // 64
|
|
||||||
|
|
||||||
dut_evictions = int(dut.eviction_count.value)
|
|
||||||
dut_misses = int(dut.cache_miss_count.value)
|
|
||||||
|
|
||||||
if dut_evictions != expected_evictions:
|
|
||||||
logger.error(f"Eviction count mismatch! Expected {expected_evictions}, saw {dut_evictions}")
|
|
||||||
|
|
||||||
if dut_misses != expected_cache_misses:
|
|
||||||
logger.error(f"Miss count mismatch! Expected {expected_cache_misses}, saw {dut_misses}")
|
|
||||||
|
|
||||||
@cocotb.test
|
|
||||||
async def short_write_read_linear_test(dut):
|
|
||||||
# What makes this test "short" is that we read 64 cachelines,
|
|
||||||
# so we shouldn't have to make any evictions
|
|
||||||
# TODO add number of evictions and cachlines loaded as performance counteres
|
|
||||||
|
|
||||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
|
||||||
cocotb.start_soon(mmu_sequencer(dut))
|
|
||||||
cocotb.start_soon(handle_higher_level_cache(dut))
|
|
||||||
cocotb.start_soon(cpu_data_monitor(dut))
|
|
||||||
|
|
||||||
num_bytes_read = 64*64
|
|
||||||
|
|
||||||
cpu_sequence = [
|
|
||||||
(i, i % 256, True, False)
|
|
||||||
for i in range(num_bytes_read)] # 64 bytes times 64 cachelines
|
|
||||||
|
|
||||||
cpu_sequence.extend([
|
|
||||||
(i, i % 256, False, False)
|
|
||||||
for i in range(num_bytes_read)]) # 64 bytes times 64 cachelines
|
|
||||||
|
|
||||||
dut.i_rst.value = Immediate(1)
|
|
||||||
for _ in range(10):
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
dut.i_rst.value = 0
|
|
||||||
|
|
||||||
await cpu_sequencer(dut, cpu_sequence)
|
|
||||||
|
|
||||||
expected_cache_misses = num_bytes_read//64
|
|
||||||
expected_evictions = num_bytes_read//64 - 64
|
|
||||||
|
|
||||||
dut_evictions = int(dut.eviction_count.value)
|
|
||||||
dut_misses = int(dut.cache_miss_count.value)
|
|
||||||
|
|
||||||
if dut_evictions != expected_evictions:
|
|
||||||
logger.error(f"Eviction count mismatch! Expected {expected_evictions}, saw {dut_evictions}")
|
|
||||||
|
|
||||||
if dut_misses != expected_cache_misses:
|
|
||||||
logger.error(f"Miss count mismatch! Expected {expected_cache_misses}, saw {dut_misses}")
|
|
||||||
|
|
||||||
@cocotb.test
|
|
||||||
async def random_access_test(dut):
|
|
||||||
# Just fully random accesses
|
|
||||||
# This is also kind of a thrash test since this is not realistic
|
|
||||||
|
|
||||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
|
||||||
cocotb.start_soon(mmu_sequencer(dut))
|
|
||||||
cocotb.start_soon(handle_higher_level_cache(dut))
|
|
||||||
cocotb.start_soon(cpu_data_monitor(dut))
|
|
||||||
|
|
||||||
num_bytes_read = 2**18
|
|
||||||
|
|
||||||
cpu_sequence = [
|
|
||||||
(random.randint(0, 2**32), random.randint(0, 255), random.randint(0,1), random.randint(0,1))
|
|
||||||
for _ in range(num_bytes_read)] # 64 bytes times 64 cachelines
|
|
||||||
|
|
||||||
dut.i_rst.value = Immediate(1)
|
|
||||||
for _ in range(10):
|
|
||||||
await RisingEdge(dut.i_clk)
|
|
||||||
dut.i_rst.value = 0
|
|
||||||
|
|
||||||
await cpu_sequencer(dut, cpu_sequence)
|
|
||||||
34
sim/application_wrapper/cache/application_wrapper_cache_top_test.py
vendored
Normal file
34
sim/application_wrapper/cache/application_wrapper_cache_top_test.py
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import cocotb
|
||||||
|
from cocotb.handle import Immediate
|
||||||
|
|
||||||
|
|
||||||
|
from cocotb.clock import Clock
|
||||||
|
from cocotb.triggers import Timer, RisingEdge
|
||||||
|
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
CLK_PERIOD = 5
|
||||||
|
|
||||||
|
@cocotb.test
|
||||||
|
async def test_sanity(dut):
|
||||||
|
# Request a read from the cache, then request a write to the cache
|
||||||
|
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
||||||
|
|
||||||
|
dut.i_cpu_we.value = 0
|
||||||
|
|
||||||
|
dut.i_rst.value = Immediate(1)
|
||||||
|
for _ in range(10):
|
||||||
|
await RisingEdge(dut.i_clk)
|
||||||
|
dut.i_rst.value = 0
|
||||||
|
|
||||||
|
await RisingEdge(dut.o_cpu_rdy)
|
||||||
|
|
||||||
|
await Timer(10, "us")
|
||||||
8
sim/application_wrapper/cache/cache.yaml
vendored
8
sim/application_wrapper/cache/cache.yaml
vendored
@@ -5,9 +5,17 @@ tests:
|
|||||||
- "application_wrapper_cache_arrays_test"
|
- "application_wrapper_cache_arrays_test"
|
||||||
sources: "sources.list"
|
sources: "sources.list"
|
||||||
waves: True
|
waves: True
|
||||||
|
|
||||||
- name: "application_wrapper_cache_miss_handler_test"
|
- name: "application_wrapper_cache_miss_handler_test"
|
||||||
toplevel: "application_wrapper_cache_miss_handler"
|
toplevel: "application_wrapper_cache_miss_handler"
|
||||||
modules:
|
modules:
|
||||||
- "application_wrapper_cache_miss_handler_test"
|
- "application_wrapper_cache_miss_handler_test"
|
||||||
sources: "sources.list"
|
sources: "sources.list"
|
||||||
waves: True
|
waves: True
|
||||||
|
|
||||||
|
- name: "application_wrapper_cache_top_test"
|
||||||
|
toplevel: "application_wrapper_cache_top"
|
||||||
|
modules:
|
||||||
|
- "application_wrapper_cache_top_test"
|
||||||
|
sources: "sources.list"
|
||||||
|
waves: True
|
||||||
@@ -1,7 +1,13 @@
|
|||||||
import application_wrapper_cache_pkg::*;
|
import application_wrapper_cache_pkg::*;
|
||||||
|
|
||||||
module application_wrapper_cache_bus_interface #(
|
module application_wrapper_cache_bus_interface #(
|
||||||
parameter DATA_W = 64*8
|
parameter DATA_W = 64*8,
|
||||||
|
|
||||||
|
// these are all wip
|
||||||
|
localparam REQ_W = 32,
|
||||||
|
localparam RSP_W = 32,
|
||||||
|
localparam DAT_W = 512+64,
|
||||||
|
localparam SNP_W = 32
|
||||||
) (
|
) (
|
||||||
input logic i_clk,
|
input logic i_clk,
|
||||||
input logic i_rst,
|
input logic i_rst,
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
module application_wrapper_cache_lru #(
|
module application_wrapper_cache_lru #(
|
||||||
// This should be NUM_WAYS - 1
|
// This should be NUM_WAYS - 1
|
||||||
parameter LRU_W = 3,
|
parameter LRU_W = 3,
|
||||||
parameter NUM_SETS = 64
|
parameter NUM_SETS = 64,
|
||||||
|
|
||||||
|
localparam INDEX_W = $clog2(NUM_SETS)
|
||||||
) (
|
) (
|
||||||
|
input logic i_clk,
|
||||||
|
|
||||||
input logic [INDEX_W-1:0] i_read_index,
|
input logic [INDEX_W-1:0] i_read_index,
|
||||||
input logic i_read_valid,
|
input logic i_read_valid,
|
||||||
output logic [LRU_W-1:0] o_read_data,
|
output logic [LRU_W-1:0] o_read_data,
|
||||||
|
|
||||||
input logic [INDEX_W-1:0] i_write_index,
|
input logic [INDEX_W-1:0] i_write_index,
|
||||||
input logic i_write_valid,
|
input logic i_write_valid,
|
||||||
|
|||||||
@@ -10,14 +10,19 @@ module application_wrapper_cache_top #(
|
|||||||
localparam TAG_W = 32 - INDEX_W - OFFSET_W,
|
localparam TAG_W = 32 - INDEX_W - OFFSET_W,
|
||||||
localparam LRU_W = NUM_WAYS-1,
|
localparam LRU_W = NUM_WAYS-1,
|
||||||
|
|
||||||
localparam META_W = TAG_W + 2
|
localparam META_W = TAG_W + 2,
|
||||||
|
|
||||||
|
localparam REQ_W = 32,
|
||||||
|
localparam RSP_W = 32,
|
||||||
|
localparam DAT_W = 512+64,
|
||||||
|
localparam SNP_W = 32
|
||||||
) (
|
) (
|
||||||
input logic i_clk,
|
input logic i_clk,
|
||||||
input logic i_rst,
|
input logic i_rst,
|
||||||
|
|
||||||
// CPU Interface
|
// CPU Interface
|
||||||
input logic [31:0] i_cpu_addr,
|
input logic [31:0] i_cpu_addr,
|
||||||
input logic i_we,
|
input logic i_cpu_we,
|
||||||
input logic i_cpu_sync,
|
input logic i_cpu_sync,
|
||||||
input logic [7:0] i_cpu_data,
|
input logic [7:0] i_cpu_data,
|
||||||
output logic [7:0] o_cpu_data,
|
output logic [7:0] o_cpu_data,
|
||||||
@@ -140,6 +145,11 @@ logic [31:0] snoop_writeback_addr;
|
|||||||
logic snoop_writeback_valid;
|
logic snoop_writeback_valid;
|
||||||
logic snoop_writeback_done;
|
logic snoop_writeback_done;
|
||||||
|
|
||||||
|
logic [DATA_W-1:0] bus_writeback_data;
|
||||||
|
logic [31:0] bus_writeback_addr;
|
||||||
|
logic bus_writeback_valid;
|
||||||
|
logic bus_writeback_done;
|
||||||
|
|
||||||
logic [31:0] cpu_memory_addr;
|
logic [31:0] cpu_memory_addr;
|
||||||
logic cpu_memory_valid;
|
logic cpu_memory_valid;
|
||||||
cache_cmd_e cpu_memory_cmd;
|
cache_cmd_e cpu_memory_cmd;
|
||||||
@@ -148,6 +158,11 @@ logic [DATA_W-1:0] cpu_memory_data;
|
|||||||
logic cpu_memory_done;
|
logic cpu_memory_done;
|
||||||
cache_resp_e cpu_memory_resp;
|
cache_resp_e cpu_memory_resp;
|
||||||
|
|
||||||
|
|
||||||
|
logic [31:0] snoop_addr;
|
||||||
|
snoop_cmd_e snoop_cmd;
|
||||||
|
logic snoop_valid;
|
||||||
|
|
||||||
logic [31:0] snoop_memory_addr;
|
logic [31:0] snoop_memory_addr;
|
||||||
logic snoop_memory_valid;
|
logic snoop_memory_valid;
|
||||||
cache_cmd_e snoop_memory_cmd;
|
cache_cmd_e snoop_memory_cmd;
|
||||||
@@ -164,6 +179,8 @@ assign cpu_tag = mmu_phys_address[31:INDEX_W+OFFSET_W];
|
|||||||
assign cpu_index = i_cpu_addr[INDEX_W+OFFSET_W-1:OFFSET_W];
|
assign cpu_index = i_cpu_addr[INDEX_W+OFFSET_W-1:OFFSET_W];
|
||||||
assign cpu_offset = i_cpu_addr[OFFSET_W-1:0];
|
assign cpu_offset = i_cpu_addr[OFFSET_W-1:0];
|
||||||
|
|
||||||
|
assign o_cpu_rdy = miss_handler_rdy;
|
||||||
|
|
||||||
application_wrapper_cache_miss_handler #(
|
application_wrapper_cache_miss_handler #(
|
||||||
.NUM_WAYS (NUM_WAYS),
|
.NUM_WAYS (NUM_WAYS),
|
||||||
.NUM_SETS (NUM_SETS)
|
.NUM_SETS (NUM_SETS)
|
||||||
@@ -250,6 +267,8 @@ application_wrapper_cache_lru #(
|
|||||||
.LRU_W (LRU_W),
|
.LRU_W (LRU_W),
|
||||||
.NUM_SETS (NUM_SETS)
|
.NUM_SETS (NUM_SETS)
|
||||||
) u_lru (
|
) u_lru (
|
||||||
|
.i_clk (i_clk),
|
||||||
|
|
||||||
.i_read_index (cpu_lru_read_index),
|
.i_read_index (cpu_lru_read_index),
|
||||||
.i_read_valid (cpu_lru_read_valid),
|
.i_read_valid (cpu_lru_read_valid),
|
||||||
.o_read_data (cpu_lru_read_data),
|
.o_read_data (cpu_lru_read_data),
|
||||||
|
|||||||
Reference in New Issue
Block a user