mirror of
https://github.com/SikongJueluo/Mini-Nav.git
synced 2026-07-12 20:15:31 +08:00
- Add cam_core_banked.sv with 8-lane banked CAM core - Add cam_write_noise.sv and cam_read_noise.sv for grouped noise injection - Add noise_mask_grouped.sv generating grouped flip masks from 128-bit PRNG - Add match_engine_pipeline.sv with multi-stage pipelined top-1 selection - Add popcount_pipeline.sv for pipelined popcount operations - Refactor test_cam_basic.py with parametrized DUT introspection helpers - Add Python ref_model match_top1_with_read_noise() for read noise verification - Update Makefile with separate WRITE_NOISE_* and READ_NOISE_* parameter groups - Add new testbenches: test_cam_core_banked, test_cam_read_noise, test_cam_write_noise, test_match_engine_pipeline, test_ref_model_noise breaking change hint: NUM_ROWS default changed from 512→4096, LANES from 16→8
67 lines
1.9 KiB
Python
67 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
import cocotb
|
|
from cocotb.clock import Clock
|
|
from cocotb.triggers import RisingEdge
|
|
|
|
|
|
async def reset_match(dut):
|
|
dut.rst_n.value = 0
|
|
dut.query_valid.value = 0
|
|
dut.query_hash.value = 0
|
|
dut.result_ready.value = 1
|
|
dut.rd_valid_i.value = 0
|
|
dut.rd_row_ids_i.value = 0
|
|
dut.rd_hashes_i.value = 0
|
|
dut.rd_lane_valid_i.value = 0
|
|
for _ in range(3):
|
|
await RisingEdge(dut.clk)
|
|
dut.rst_n.value = 1
|
|
for _ in range(2):
|
|
await RisingEdge(dut.clk)
|
|
|
|
|
|
@cocotb.test()
|
|
async def match_engine_returns_top1_after_pipeline_drain(dut):
|
|
cocotb.start_soon(Clock(dut.clk, 10, unit="ns").start())
|
|
await reset_match(dut)
|
|
|
|
LANES = 8
|
|
ROW_BITS = len(dut.rd_row_ids_i) // LANES
|
|
HASH_BITS = len(dut.rd_hashes_i) // LANES
|
|
NUM_ROWS = 1 << len(dut.rd_base_row_o)
|
|
TARGET_ROW = 9
|
|
|
|
query = (1 << HASH_BITS) - 1
|
|
dut.query_hash.value = query
|
|
dut.query_valid.value = 1
|
|
await RisingEdge(dut.clk)
|
|
dut.query_valid.value = 0
|
|
|
|
for base in range(0, NUM_ROWS, LANES):
|
|
while int(dut.rd_valid_o.value) == 0:
|
|
await RisingEdge(dut.clk)
|
|
assert int(dut.rd_base_row_o.value) == base
|
|
rows = 0
|
|
hashes = 0
|
|
for lane in range(LANES):
|
|
row_id = base + lane
|
|
rows |= row_id << (lane * ROW_BITS)
|
|
row_hash = query if row_id == TARGET_ROW else 0
|
|
hashes |= row_hash << (lane * HASH_BITS)
|
|
dut.rd_row_ids_i.value = rows
|
|
dut.rd_hashes_i.value = hashes
|
|
dut.rd_lane_valid_i.value = 0xFF
|
|
dut.rd_valid_i.value = 1
|
|
await RisingEdge(dut.clk)
|
|
dut.rd_valid_i.value = 0
|
|
|
|
for _ in range(20):
|
|
if int(dut.result_valid.value):
|
|
break
|
|
await RisingEdge(dut.clk)
|
|
|
|
assert int(dut.result_valid.value) == 1
|
|
assert int(dut.result_row.value) == TARGET_ROW
|
|
assert int(dut.result_score.value) == HASH_BITS
|