|
|
|
@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
|
|
|
|
|
"""High-Throughput combinational logic timing simulators. |
|
|
|
|
|
|
|
|
|
These simulators work similarly to :py:class:`kyupy.logic_sim.LogicSim`. |
|
|
|
|
These simulators work similarly to :py:class:`~kyupy.logic_sim.LogicSim`. |
|
|
|
|
They propagate values through the combinational circuit from (pseudo) primary inputs to (pseudo) primary outputs. |
|
|
|
|
Instead of propagating logic values, these simulators propagate signal histories (waveforms). |
|
|
|
|
They are designed to run many simulations in parallel and while their latencies are quite high, they achieve |
|
|
|
@ -17,8 +17,7 @@ from bisect import bisect, insort_left
@@ -17,8 +17,7 @@ from bisect import bisect, insort_left
|
|
|
|
|
|
|
|
|
|
import numpy as np |
|
|
|
|
|
|
|
|
|
from . import numba |
|
|
|
|
from . import cuda |
|
|
|
|
from . import numba, cuda, hr_bytes |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TMAX = np.float32(2 ** 127) # almost np.PINF for 32-bit floating point values |
|
|
|
@ -253,6 +252,12 @@ class WaveSim:
@@ -253,6 +252,12 @@ class WaveSim:
|
|
|
|
|
m0 = ~m1 |
|
|
|
|
self.mask = np.rollaxis(np.vstack((m0, m1)), 1) |
|
|
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
|
total_mem = self.state.nbytes + self.sat.nbytes + self.ops.nbytes + self.cdata.nbytes |
|
|
|
|
return f'<WaveSim {self.circuit.name} sims={self.sims} ops={len(self.ops)} ' + \ |
|
|
|
|
f'levels={len(self.level_starts)} state_mem={hr_bytes(self.state.nbytes)} ' + \ |
|
|
|
|
f'total_mem={hr_bytes(total_mem)}>' |
|
|
|
|
|
|
|
|
|
def get_line_delay(self, line, polarity): |
|
|
|
|
return self.timing[line, 0, polarity] |
|
|
|
|
|
|
|
|
@ -283,10 +288,7 @@ class WaveSim:
@@ -283,10 +288,7 @@ class WaveSim:
|
|
|
|
|
self.state[ppi_loc + toggle, p] = TMAX |
|
|
|
|
|
|
|
|
|
def propagate(self, sims=None, sd=0.0, seed=1): |
|
|
|
|
if sims is None: |
|
|
|
|
sims = self.sims |
|
|
|
|
else: |
|
|
|
|
sims = min(sims, self.sims) |
|
|
|
|
sims = min(sims or self.sims, self.sims) |
|
|
|
|
for op_start, op_stop in zip(self.level_starts, self.level_stops): |
|
|
|
|
self.overflows += level_eval(self.ops, op_start, op_stop, self.state, self.sat, 0, sims, |
|
|
|
|
self.timing, sd, seed) |
|
|
|
@ -559,6 +561,13 @@ class WaveSimCuda(WaveSim):
@@ -559,6 +561,13 @@ class WaveSimCuda(WaveSim):
|
|
|
|
|
|
|
|
|
|
self._block_dim = (32, 16) |
|
|
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
|
total_mem = self.state.nbytes + self.sat.nbytes + self.ops.nbytes + self.timing.nbytes + \ |
|
|
|
|
self.tdata.nbytes + self.cdata.nbytes |
|
|
|
|
return f'<WaveSimCuda {self.circuit.name} sims={self.sims} ops={len(self.ops)} ' + \ |
|
|
|
|
f'levels={len(self.level_starts)} state_mem={hr_bytes(self.state.nbytes)} ' + \ |
|
|
|
|
f'total_mem={hr_bytes(total_mem)}>' |
|
|
|
|
|
|
|
|
|
def get_line_delay(self, line, polarity): |
|
|
|
|
return self.d_timing[line, 0, polarity] |
|
|
|
|
|
|
|
|
@ -586,10 +595,7 @@ class WaveSimCuda(WaveSim):
@@ -586,10 +595,7 @@ class WaveSimCuda(WaveSim):
|
|
|
|
|
return gx, gy |
|
|
|
|
|
|
|
|
|
def propagate(self, sims=None, sd=0.0, seed=1): |
|
|
|
|
if sims is None: |
|
|
|
|
sims = self.sims |
|
|
|
|
else: |
|
|
|
|
sims = min(sims, self.sims) |
|
|
|
|
sims = min(sims or self.sims, self.sims) |
|
|
|
|
for op_start, op_stop in zip(self.level_starts, self.level_stops): |
|
|
|
|
grid_dim = self._grid_dim(sims, op_stop - op_start) |
|
|
|
|
wave_kernel[grid_dim, self._block_dim](self.d_ops, op_start, op_stop, self.d_state, self.sat, int(0), |
|
|
|
|