-
Notifications
You must be signed in to change notification settings - Fork 89
Add more tests for MemBlock and _MemIndexed #461
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## development #461 +/- ##
=============================================
+ Coverage 91.7% 91.9% +0.3%
=============================================
Files 24 24
Lines 6403 6413 +10
=============================================
+ Hits 5866 5888 +22
+ Misses 537 525 -12 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
fdxmw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for improving these tests! I have some minor comments
tests/test_memblock.py
Outdated
|
|
||
| def test_negative_bitwidth(self): | ||
| with self.assertRaises(pyrtl.PyrtlError): | ||
| pyrtl.MemBlock(-1, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines like these are a little easier to read with keyword arguments (pyrtl.MemBlock(bitwidth=-1, addrwidth=1)) as the reader may not remember whether bitwidth or addrwidth comes first.
If you agree and want to change this, please change it consistently throughout this commit
tests/test_memblock.py
Outdated
| with self.assertRaises(pyrtl.PyrtlError): | ||
| mem_out <<= mem[mem_in] | ||
|
|
||
| def test_memblock_write_data_larger_than_memory_bidwidth(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: bidwidth :)
tests/test_memblock.py
Outdated
|
|
||
| def test_memindex_bitwidth_more_than_addrwidth(self): | ||
| mem = pyrtl.MemBlock(1, 1) | ||
| mem_in = pyrtl.Input(2, 'mem_in') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name mem_in is confusing in this commit as it's sometimes the address, and sometimes the data to write. Seems clearer to always call the address mem_addr?
tests/test_memblock.py
Outdated
| with self.assertRaises(pyrtl.PyrtlError): | ||
| pyrtl.MemBlock(1, -1) | ||
|
|
||
| def test_memindex_bitwidth_more_than_addrwidth(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe call this greater_than instead of more_than ?
Regardless, the word choice here should be consistent with the next test (more vs larger)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the name to test_memindex_bitwidth_greater_than_addrwidth, but I left test_memblock_write_data_larger_than_memory_bitwidth as it is because I think when we talk about numbers it is better to say greater and less and when we talk about data it is better to say larger and smaller. But I can change it if you disagree.
tests/test_memblock.py
Outdated
| for i in range(8): | ||
| mem_out_array[i] <<= mem[mem_in][i] | ||
| mem_value_map = {mem: {0: 7, 1: 5}} | ||
| sim_trace = pyrtl.SimulationTrace() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a SimulationTrace shouldn't be needed here since Simulation should create a SimulationTrace for you if none is provided (happens again in the next two tests)
tests/test_memblock.py
Outdated
| mem_value_map = {mem: {0: 7, 1: 5}} | ||
| sim_trace = pyrtl.SimulationTrace() | ||
| sim = pyrtl.Simulation(tracer=sim_trace, memory_value_map=mem_value_map) | ||
| for i in range(len(mem_value_map[mem])): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't seem like we gain much by testing both addresses? Consider just checking the first address as loops like these make it harder to debug the test. When a test failure occurs, we won't know the values of i or j
tests/test_memblock.py
Outdated
| sim.step({mem_in: i}) | ||
| binary = bin(mem_value_map[mem][i])[2:].zfill(8) | ||
| for j in range(8): | ||
| self.assertEqual(sim.inspect(mem_out_array[j]), int(binary[7 - j])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, it's a little better to reassemble the inspected binary value, and then do one big assertEqual, rather than doing one assertEqual for each bit in the loop. With one big assertEqual, the test failure error message will be better, since we can more easily see which bits are wrong. With the single-bit assertEqual, the error message will just tell us that 0 is not equal to 1 or vice versa.
You can reassemble the inspected values with something like:
>>> def reassemble_bits(bits: list[int]):
... value = 0
... for bit in bits:
... value = (value << 1) | bit
... return value
>>> reassemble_bits([0, 0])
0
>>> reassemble_bits([0, 1])
1
>>> reassemble_bits([1, 0])
2
>>> reassemble_bits([1, 1])
3
If you want to keep things the way they are, consider moving this logic to check if the Nth bit is set to a helper function, as it's a bit complicated and it's repeated in the next two tests.
Also you can check this a little more easily with bitmasks and bitwise AND, something like
>>> def check_nth_bit(value: int, n: int):
... return bool(value & (1 << n))
>>> for n in range(8):
... print(n, check_nth_bit(27, n))
...
0 True
1 True
2 False
3 True
4 True
5 False
6 False
7 False
Classes
MemBlockand_MemIndexedare now fully covered by tests, except one exception that I don't think can happen (see #460)