mirror of
https://github.com/SikongJueluo/Mini-Nav.git
synced 2026-07-12 20:15:31 +08:00
refactor(cam): remove read noise from noise architecture (Phase 2)
- Make cam_read_noise a pass-through module, removing all noise injection logic - Switch write noise to use noise_mask_bernoulli instead of noise_mask_grouped - Add state machine to cam_write_noise for mask generation timing - Remove noise_mask_grouped.sv (no longer needed) - Remove read noise parameters from cam_noisy and cam_top - Update simulation and benchmark code to reflect read noise removal - Sync documentation to reflect Phase 2 architecture
This commit is contained in:
@@ -10,6 +10,4 @@ HASH_BITS ?= 512
|
||||
WRITE_NOISE_EN ?= 1
|
||||
WRITE_NOISE_RATE_NUM ?= 1
|
||||
WRITE_NOISE_RATE_DEN ?= 100
|
||||
WRITE_NOISE_BITS ?= $(shell echo $$(( $(HASH_BITS) / 64 )))
|
||||
|
||||
include $(SIM_ROOT)/mk/cocotb-common.mk
|
||||
|
||||
@@ -2,8 +2,32 @@ from __future__ import annotations
|
||||
|
||||
import cocotb
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import RisingEdge
|
||||
from model.ref_model import generate_write_flip_mask
|
||||
from cocotb.triggers import RisingEdge, Timer
|
||||
|
||||
# Bernoulli: 1 PRIME + 16 RUN = 17 cycles internal
|
||||
# + 1 cycle for mask_start propagation + 1 cycle for core_wr_valid output = 19
|
||||
DEFAULT_WRITE_NOISE_LATENCY = 19
|
||||
|
||||
|
||||
async def pulse_write(dut, row: int, value: int):
|
||||
dut.wr_row.value = row
|
||||
dut.wr_hash.value = value
|
||||
dut.wr_valid.value = 1
|
||||
await Timer(1, unit="step")
|
||||
assert int(dut.wr_ready.value) == 1
|
||||
await RisingEdge(dut.clk)
|
||||
await Timer(1, unit="step")
|
||||
dut.wr_valid.value = 0
|
||||
|
||||
|
||||
async def wait_core_write(dut, max_cycles: int = 128) -> int:
|
||||
cycles = 0
|
||||
while int(dut.core_wr_valid.value) == 0:
|
||||
assert cycles < max_cycles, "timed out waiting for core_wr_valid"
|
||||
await RisingEdge(dut.clk)
|
||||
await Timer(1, unit="step")
|
||||
cycles += 1
|
||||
return cycles
|
||||
|
||||
|
||||
async def reset_write_noise(dut):
|
||||
@@ -19,23 +43,52 @@ async def reset_write_noise(dut):
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def write_noise_outputs_grouped_noisy_hash(dut):
|
||||
async def write_noise_enabled_applies_bernoulli_mask_after_generation(dut):
|
||||
"""Noise active: FSM enters WAIT_MASK, core_wr_hash deterministic across reset."""
|
||||
cocotb.start_soon(Clock(dut.clk, 10, unit="ns").start())
|
||||
await reset_write_noise(dut)
|
||||
|
||||
value = 0x123456789ABCDEF
|
||||
dut.wr_row.value = 3
|
||||
dut.wr_hash.value = value
|
||||
dut.wr_valid.value = 1
|
||||
value = (1 << 512) - 1 # all-ones: even low-rate Bernoulli may flip some bits
|
||||
await pulse_write(dut, row=3, value=value)
|
||||
await Timer(1, unit="step")
|
||||
assert int(dut.wr_ready.value) == 0
|
||||
|
||||
cycles = await wait_core_write(dut)
|
||||
assert cycles == DEFAULT_WRITE_NOISE_LATENCY
|
||||
|
||||
assert int(dut.core_wr_row.value) == 3
|
||||
hash_after_first = int(dut.core_wr_hash.value)
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await Timer(1, unit="step")
|
||||
assert int(dut.core_wr_valid.value) == 0
|
||||
assert int(dut.wr_ready.value) == 1
|
||||
|
||||
# Deterministic across reset: same seed → same mask → same noisy hash
|
||||
await reset_write_noise(dut)
|
||||
await pulse_write(dut, row=3, value=value)
|
||||
await wait_core_write(dut)
|
||||
assert int(dut.core_wr_hash.value) == hash_after_first
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def write_noise_backpressures_second_write_until_done(dut):
|
||||
cocotb.start_soon(Clock(dut.clk, 10, unit="ns").start())
|
||||
await reset_write_noise(dut)
|
||||
|
||||
await pulse_write(dut, row=1, value=0xAA55)
|
||||
|
||||
dut.wr_row.value = 2
|
||||
dut.wr_hash.value = 0x55AA
|
||||
dut.wr_valid.value = 1
|
||||
await Timer(1, unit="step")
|
||||
for _ in range(4):
|
||||
assert int(dut.wr_ready.value) == 0
|
||||
assert int(dut.core_wr_valid.value) == 0
|
||||
await RisingEdge(dut.clk)
|
||||
await Timer(1, unit="step")
|
||||
dut.wr_valid.value = 0
|
||||
|
||||
while int(dut.core_wr_valid.value) == 0:
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
seed = 0xB504_F32D_B504_F32D
|
||||
hash_bits = len(dut.wr_hash)
|
||||
noise_bits = hash_bits // 64
|
||||
flip, _ = generate_write_flip_mask((seed << 64) | seed, hash_bits, noise_bits, 1, 100)
|
||||
assert int(dut.core_wr_row.value) == 3
|
||||
assert int(dut.core_wr_hash.value) == (value ^ flip)
|
||||
cycles = await wait_core_write(dut)
|
||||
assert cycles == DEFAULT_WRITE_NOISE_LATENCY - 4 # 19 - 4 = 15
|
||||
assert int(dut.core_wr_row.value) == 1
|
||||
|
||||
Reference in New Issue
Block a user