mirror of
https://github.com/SikongJueluo/Mini-Nav.git
synced 2026-07-12 20:15:31 +08:00
feat(cam): migrate noise generation from xorshift64 to xorshift128
- Replace NOISE_GEN_BITS/NOISE_SAMPLE_BITS parameters with unified NOISE_BITS
- Use xorshift128 (random128) instead of xorshift64 for PRNG
- Add flip_mask_next combinational helper for single-cycle mask computation
- Add random_enable signal to advance PRNG only on accepted noisy writes
- Simplify FSM by removing mask_group_idx counter
- Update parameter validation: GROUP_BITS (= HASH_BITS/NOISE_BITS) must equal 64
- Update ref_model.py and tests to match new seed convention: {seed, seed}
- Update Makefile and sweep_noise.py with renamed parameters
This commit is contained in:
@@ -53,50 +53,50 @@ def match_top1(
|
||||
)
|
||||
|
||||
|
||||
def xorshift64(state: int) -> int:
|
||||
"""64-bit XOR-shift PRNG, single step. Matches RTL behavior."""
|
||||
mask64 = (1 << 64) - 1
|
||||
s = state & mask64
|
||||
s ^= (s << 13) & mask64
|
||||
s ^= (s >> 7) & mask64
|
||||
s ^= (s << 17) & mask64
|
||||
return s
|
||||
def xorshift128(state: int) -> int:
|
||||
"""128-bit xorshift PRNG, single step. Matches random128.sv."""
|
||||
mask32 = (1 << 32) - 1
|
||||
mask128 = (1 << 128) - 1
|
||||
s = state & mask128
|
||||
x = (s >> 96) & mask32
|
||||
y = (s >> 64) & mask32
|
||||
z = (s >> 32) & mask32
|
||||
w = s & mask32
|
||||
t = (x ^ ((x << 11) & mask32)) & mask32
|
||||
next_x = y
|
||||
next_y = z
|
||||
next_z = w
|
||||
next_w = (w ^ (w >> 19) ^ t ^ (t >> 8)) & mask32
|
||||
return ((next_x << 96) | (next_y << 64) | (next_z << 32) | next_w) & mask128
|
||||
|
||||
|
||||
def generate_write_flip_mask(
|
||||
prng_state: int,
|
||||
hash_bits: int,
|
||||
noise_gen_bits: int,
|
||||
noise_sample_bits: int,
|
||||
noise_bits: int,
|
||||
rate_num: int,
|
||||
rate_den: int,
|
||||
) -> tuple[int, int]:
|
||||
"""
|
||||
Generate write-noise flip mask.
|
||||
Returns (flip_mask, next_prng_state).
|
||||
Matches RTL multi-cycle GEN_MASK behavior.
|
||||
"""Generate one write-noise flip mask using one xorshift128 step."""
|
||||
assert hash_bits % noise_bits == 0
|
||||
group_bits = hash_bits // noise_bits
|
||||
bit_index_bits = 6
|
||||
sample_bits = 8
|
||||
group_random_bits = bit_index_bits + sample_bits
|
||||
assert group_bits == 64
|
||||
assert noise_bits * group_random_bits <= 128
|
||||
|
||||
Each cycle processes noise_gen_bits bit decisions:
|
||||
- Advance xorshift64 → 64-bit output
|
||||
- Split into noise_gen_bits x noise_sample_bits-bit samples
|
||||
- Each sample < THRESHOLD → that bit flips
|
||||
"""
|
||||
assert hash_bits % noise_gen_bits == 0
|
||||
assert noise_gen_bits * noise_sample_bits == 64
|
||||
mask = 0
|
||||
state = prng_state
|
||||
sample_range = 1 << noise_sample_bits
|
||||
sample_range = 1 << sample_bits
|
||||
threshold = (rate_num * sample_range) // rate_den
|
||||
|
||||
for bit_offset in range(0, hash_bits, noise_gen_bits):
|
||||
# Advance PRNG
|
||||
state = xorshift64(state)
|
||||
|
||||
# Split into noise_gen_bits independent samples
|
||||
for b in range(noise_gen_bits):
|
||||
sample_b = (state >> (b * noise_sample_bits)) & (sample_range - 1)
|
||||
if sample_b < threshold:
|
||||
mask |= (1 << (bit_offset + b))
|
||||
state = xorshift128(prng_state)
|
||||
mask = 0
|
||||
for group_idx in range(noise_bits):
|
||||
group_rand = (state >> (group_idx * group_random_bits)) & ((1 << group_random_bits) - 1)
|
||||
bit_idx = group_rand & ((1 << bit_index_bits) - 1)
|
||||
sample = (group_rand >> bit_index_bits) & (sample_range - 1)
|
||||
if sample < threshold:
|
||||
mask |= 1 << (group_idx * group_bits + bit_idx)
|
||||
|
||||
return mask, state
|
||||
|
||||
|
||||
Reference in New Issue
Block a user