UCSBarchlab / PyRTL

A collection of classes providing simple hardware specification, simulation, tracing, and testing suitable for teaching and research. Simplicity, usability, clarity, and extensibility are the overarching goals, rather than performance or optimization.
http://ucsbarchlab.github.io/PyRTL
BSD 3-Clause "New" or "Revised" License
257 stars 78 forks source link

Improve CompiledSimulation Iteration over Memory #320

Open mdko opened 3 years ago

mdko commented 3 years ago

The observed behavior of iterating over an inspected memory changes depending on whether it's a normal simulation (Simulation or FastSimulation) or a compiled simulation.

Observe the following program:

import pyrtl

m = pyrtl.MemBlock(32, 32, 'm')
addr = pyrtl.Input(32, 'addr')
out = pyrtl.Output(32, 'out')
w = m[addr]
out <<= w
m[addr] <<= pyrtl.as_wires(w + 10).truncate(32)

Normal Simulation

Given the above, if you simulate it via Simulation and then iterate over the inspected memory, it will only print the key-value pairs of memory addresses it touched during simulation (with the implication that all other memory locations are at their initial value, whatever that may be):

sim = pyrtl.Simulation()
sim.step_multiple({
    'addr': [0x0, 0x100, 0x102, 0x2345, 0x100, 0x102]
})
mv = sim.inspect_mem(m)
for addr, value in mv.items():
    print(f"{hex(addr)}: {value}")

Output:

> python ex1.py
0x0: 10
0x100: 20
0x102: 20
0x2345: 10

Compiled Simulation

sim = pyrtl.CompiledSimulation()
sim.step_multiple({
    'addr': [0x0, 0x100, 0x102, 0x2345, 0x100, 0x102]
})
mv = sim.inspect_mem(m)
for addr, value in mv.items():
    print(f"{hex(addr)}: {value}")

Output:

> python ex2.py
0x0: 10
0x1: 0
0x2: 0
0x3: 0
0x4: 0
0x5: 0
0x6: 0
0x7: 0
0x8: 0
0x9: 0
0xa: 0
0xb: 0
0xc: 0
0xd: 0
0xe: 0
0xf: 0
0x10: 0
0x11: 0
0x12: 0
0x13: 0
0x14: 0
....<etc. up to 2^32 address>

I think the first version makes much more sense, as it's easier to see through the noise. This means needing to update Compiled Simulation to be more judicious in what key-value pairs are returned during iteration. I've started adding another C function that can be called when the memory is being iterated, which will search for present elements in the hash map that currently represents memory in the C-made DLL.