FA-89126 / Digital logic simulation / Open access
Negative address wraps to the top of memory · case 01
A write to address -1 lands in the last word.
ROOT CAUSE
The range check omits the lower bound, so Python negative indexing wraps.
VERIFIED REPAIR
Accept only 0 <= addr < depth.
Unsuccessful approach: Excluding address 0 makes the first word unreachable.
Case contract
Input [depth, mode, ops]; memory holds 16-bit words initialised to 0. Each op [we, addr, wdata, be, re]: be bit k enables byte lane k (bits 8k..8k+7). Addresses outside 0..depth-1 ignore writes and read 'x'. A read in the same cycle as a write returns the old word in mode 'read_first' and the merged new word in 'write_first'. re=0 yields None.
Why this case matters
RTL memory models must match the inferred RAM read-during-write and byte-enable behaviour or simulation diverges from silicon.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(*args):
depth, mode, ops = args
mem = [0] * depth
out = []
for we, addr, wdata, be, re in ops:
ok = addr < depth
old = mem[addr] if ok else None
new = old
if we and ok:
for lane in range(2):
if be >> lane & 1:
mask = 0xFF << (8 * lane)
new = (new & ~mask) | (wdata & mask)
mem[addr] = new
if re:
if not ok:
out.append('x')
else:
out.append(new if mode == 'write_first' else old)
else:
out.append(None)
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('full write then read-first read', [5, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [5, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [5, 'read_first', [[1, 3, 23041, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [5, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [5, 'read_first', [[1, -1, 30583, 3, 1], [0, 4, 0, 0, 1]]], ['x', 0]), ('out of range read', [5, 'read_first', [[0, 6, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [5, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 8738, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 8738])], [('full write then read-first read', [4, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [4, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [4, 'read_first', [[1, 3, 23042, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [4, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [4, 'read_first', [[1, -1, 30583, 3, 1], [0, 3, 0, 0, 1]]], ['x', 0]), ('out of range read', [4, 'read_first', [[0, 6, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [4, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 17476, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 17476])], [('full write then read-first read', [5, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [5, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [5, 'read_first', [[1, 3, 23043, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [5, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [5, 'read_first', [[1, -1, 30583, 3, 1], [0, 4, 0, 0, 1]]], ['x', 0]), ('out of range read', [5, 'read_first', [[0, 8, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [5, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 26214, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 26214])], [('full write then read-first read', [4, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [4, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [4, 'read_first', [[1, 3, 23044, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [4, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [4, 'read_first', [[1, -1, 30583, 3, 1], [0, 3, 0, 0, 1]]], ['x', 0]), ('out of range read', [4, 'read_first', [[0, 8, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [4, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 34952, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 34952])], [('full write then read-first read', [5, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [5, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [5, 'read_first', [[1, 3, 23045, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [5, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [5, 'read_first', [[1, -1, 30583, 3, 1], [0, 4, 0, 0, 1]]], ['x', 0]), ('out of range read', [5, 'read_first', [[0, 10, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [5, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 43690, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 43690])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| full write then read-first read | [0, 43981] | [0, 43981] | Passed |
| write-first partial write | [None, 4863, 4863] | [None, 4863, 4863] | Passed |
| high lane only | [None, 23040] | [None, 23040] | Passed |
| address zero | [3855, 3855] | [3855, 3855] | Passed |
| negative address rejected | [0, 30583] | ['x', 0] | Failed |
| out of range read | ['x', None] | ['x', None] | Passed |
| read-first returns old data | [None, 4369, 8738] | [None, 4369, 8738] | Passed |
SHA-256 / eeea070646d3f3df5352c804d11836fe49bc5f9f4805f40fd778962e15740787
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(*args):
depth, mode, ops = args
mem = [0] * depth
out = []
for we, addr, wdata, be, re in ops:
ok = 0 < addr < depth
old = mem[addr] if ok else None
new = old
if we and ok:
for lane in range(2):
if be >> lane & 1:
mask = 0xFF << (8 * lane)
new = (new & ~mask) | (wdata & mask)
mem[addr] = new
if re:
if not ok:
out.append('x')
else:
out.append(new if mode == 'write_first' else old)
else:
out.append(None)
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('full write then read-first read', [5, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [5, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [5, 'read_first', [[1, 3, 23041, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [5, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [5, 'read_first', [[1, -1, 30583, 3, 1], [0, 4, 0, 0, 1]]], ['x', 0]), ('out of range read', [5, 'read_first', [[0, 6, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [5, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 8738, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 8738])], [('full write then read-first read', [4, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [4, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [4, 'read_first', [[1, 3, 23042, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [4, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [4, 'read_first', [[1, -1, 30583, 3, 1], [0, 3, 0, 0, 1]]], ['x', 0]), ('out of range read', [4, 'read_first', [[0, 6, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [4, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 17476, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 17476])], [('full write then read-first read', [5, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [5, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [5, 'read_first', [[1, 3, 23043, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [5, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [5, 'read_first', [[1, -1, 30583, 3, 1], [0, 4, 0, 0, 1]]], ['x', 0]), ('out of range read', [5, 'read_first', [[0, 8, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [5, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 26214, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 26214])], [('full write then read-first read', [4, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [4, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [4, 'read_first', [[1, 3, 23044, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [4, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [4, 'read_first', [[1, -1, 30583, 3, 1], [0, 3, 0, 0, 1]]], ['x', 0]), ('out of range read', [4, 'read_first', [[0, 8, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [4, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 34952, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 34952])], [('full write then read-first read', [5, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [5, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [5, 'read_first', [[1, 3, 23045, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [5, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [5, 'read_first', [[1, -1, 30583, 3, 1], [0, 4, 0, 0, 1]]], ['x', 0]), ('out of range read', [5, 'read_first', [[0, 10, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [5, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 43690, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 43690])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| full write then read-first read | [0, 43981] | [0, 43981] | Passed |
| write-first partial write | [None, 4863, 4863] | [None, 4863, 4863] | Passed |
| high lane only | [None, 23040] | [None, 23040] | Passed |
| address zero | ['x', 'x'] | [3855, 3855] | Failed |
| negative address rejected | ['x', 0] | ['x', 0] | Passed |
| out of range read | ['x', None] | ['x', None] | Passed |
| read-first returns old data | [None, 4369, 8738] | [None, 4369, 8738] | Passed |
SHA-256 / d09855f92f6ebd70978dd927efed8862cfba35c3af5cf703413ad84373befc0d
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(*args):
depth, mode, ops = args
mem = [0] * depth
out = []
for we, addr, wdata, be, re in ops:
ok = 0 <= addr < depth
old = mem[addr] if ok else None
new = old
if we and ok:
for lane in range(2):
if be >> lane & 1:
mask = 0xFF << (8 * lane)
new = (new & ~mask) | (wdata & mask)
mem[addr] = new
if re:
if not ok:
out.append('x')
else:
out.append(new if mode == 'write_first' else old)
else:
out.append(None)
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('full write then read-first read', [5, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [5, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [5, 'read_first', [[1, 3, 23041, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [5, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [5, 'read_first', [[1, -1, 30583, 3, 1], [0, 4, 0, 0, 1]]], ['x', 0]), ('out of range read', [5, 'read_first', [[0, 6, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [5, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 8738, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 8738])], [('full write then read-first read', [4, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [4, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [4, 'read_first', [[1, 3, 23042, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [4, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [4, 'read_first', [[1, -1, 30583, 3, 1], [0, 3, 0, 0, 1]]], ['x', 0]), ('out of range read', [4, 'read_first', [[0, 6, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [4, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 17476, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 17476])], [('full write then read-first read', [5, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [5, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [5, 'read_first', [[1, 3, 23043, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [5, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [5, 'read_first', [[1, -1, 30583, 3, 1], [0, 4, 0, 0, 1]]], ['x', 0]), ('out of range read', [5, 'read_first', [[0, 8, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [5, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 26214, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 26214])], [('full write then read-first read', [4, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [4, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [4, 'read_first', [[1, 3, 23044, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [4, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [4, 'read_first', [[1, -1, 30583, 3, 1], [0, 3, 0, 0, 1]]], ['x', 0]), ('out of range read', [4, 'read_first', [[0, 8, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [4, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 34952, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 34952])], [('full write then read-first read', [5, 'read_first', [[1, 1, 43981, 3, 1], [0, 1, 0, 0, 1]]], [0, 43981]), ('write-first partial write', [5, 'write_first', [[1, 2, 4660, 3, 0], [1, 2, 65535, 1, 1], [0, 2, 0, 0, 1]]], [None, 4863, 4863]), ('high lane only', [5, 'read_first', [[1, 3, 23045, 2, 0], [0, 3, 0, 0, 1]]], [None, 23040]), ('address zero', [5, 'write_first', [[1, 0, 3855, 3, 1], [0, 0, 0, 0, 1]]], [3855, 3855]), ('negative address rejected', [5, 'read_first', [[1, -1, 30583, 3, 1], [0, 4, 0, 0, 1]]], ['x', 0]), ('out of range read', [5, 'read_first', [[0, 10, 0, 0, 1], [0, 1, 0, 0, 0]]], ['x', None]), ('read-first returns old data', [5, 'read_first', [[1, 1, 4369, 3, 0], [1, 1, 43690, 3, 1], [0, 1, 0, 0, 1]]], [None, 4369, 43690])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| full write then read-first read | [0, 43981] | [0, 43981] | Passed |
| write-first partial write | [None, 4863, 4863] | [None, 4863, 4863] | Passed |
| high lane only | [None, 23040] | [None, 23040] | Passed |
| address zero | [3855, 3855] | [3855, 3855] | Passed |
| negative address rejected | ['x', 0] | ['x', 0] | Passed |
| out of range read | ['x', None] | ['x', None] | Passed |
| read-first returns old data | [None, 4369, 8738] | [None, 4369, 8738] | Passed |
SHA-256 / f0d5972043ded25ba9c633bcf6086565978310e7987deaee77c932edf2717a0f
Verification & scope
A deterministic bounded teaching model of one simulator rule set; the contract is stipulated and is not a claim of conformance to any HDL standard or commercial simulator. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:51:14.602534+00:00.
Case digest / ca71fef491b5420f9ff2c5e1f4d709f8e0c6912a96d202cb3523e348c29626af