"Tests and responses are instances of `PackedVectors`. Its length is the number of test vectors stored (`nvectors`), its `width` is the number of values in a vector, and its `vdim` is the number of bits used for storing one value. By default, the stil parser returns 4-valued test vectors (`vdim=2`)."
"The data is stored in a bit-parallel fashion. This internal storage (an `ndarray` of `uint8`) is accessible via `bits`. The first axis is the width, the second axis is `vdim`, the last axis goes along the test set. This last axis is about `nvectors / 8` in length. "
"The order of values in the vectors correspond to the circuit's interface followed by the scan flip-flops as they appear in `b14.cells`. The test data can be used directly in the simulators as they use the same ordering convention. The following code performs a 4-valued logic simulation and stores the results in a new instance of `PackedVectors`."
"Compare simulation results to expected fault-free responses loaded from STIL. The first test fails, because it is a flush test while simulation implicitly assumes a standard test with a capture clock."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"mismatch for test pattern 0\n",
"1080 of 1081 responses matched with simulator\n"
]
}
],
"source": [
"matches = 0\n",
"for i in range(len(responses)):\n",
" if responses[i] == stuck_responses[i]:\n",
" matches += 1\n",
" else:\n",
" print(f'mismatch for test pattern {i}')\n",
"print(f'{matches} of {len(responses)} responses matched with simulator')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Transition faults require test vector pairs for testing. These pairs are generated by `tests8v`, assuming a launch-on-capture scheme (two functional clock cycles after scan-in)."
"The responses loaded from STIL only contain the final logic values. Use simple character replacements before comparing these. First test is again a flush test."
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"mismatch for test pattern 0\n",
"1391 of 1392 responses matched with simulator\n"
]
}
],
"source": [
"matches = 0\n",
"for i in range(len(responses)):\n",
" if trans_responses[i] == responses[i].replace('P','0').replace('N','1').replace('R','1').replace('F','0'):\n",
" matches += 1\n",
" else:\n",
" print(f'mismatch for test pattern {i}')\n",
"print(f'{matches} of {len(responses)} responses matched with simulator')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Working With Delay Information and Timing Simulation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 32 Parallel Time Simulations with Waveform Capacity 16\n",
"Delay data for gates and interconnect can be loaded from SDF files. In kyupy's timing simulators, delays are associated with the lines between nodes, not with the nodes themselves. Each line in the circuit has a rising delay, a falling delay, a negative pulse threshold, and a positive pulse threshold. "
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [],
"source": [
"from kyupy import sdf\n",
"from kyupy.saed import pin_index\n",
"\n",
"This code will fall back to pure python if no CUDA card is available. This will be quite slow.\n",
"The returned delay information is an `ndarray` with a set of delay values for each line in the circuit."
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(46891, 2, 2)"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lt.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Number of non-0 values loaded:"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"119676"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(lt != 0).sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The available timing simulators are `WaveSim` and `WaveSimCuda`.\n",
"They work similarly to `LogicSim` in that they evaluate all cells in topological order.\n",
"Instead of propagating a logic value, however, they propagate waveforms.\n",
"\n",
"`WaveSim` uses the numba just-in-time compiler for acceleration on CPU.\n",
"It falls back to pure python if numba is not available. `WaveSimCuda` uses numba for GPU acceleration.\n",
"If no CUDA card is available, it will fall back to pure python (not jit-compiled for CPU!).\n",
"Pure python is too slow for most purposes.\n",
"\n",
"Instanciate simulator:"
"Both simulators operate data-parallel.\n",
"The following instanciates a new engine for 32 independent timing simulations and each signal line in the circuit can carry at most 16 transitions. All simulators share the same circuit and the same line delay specification."
]
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
@ -521,44 +889,90 @@
@@ -521,44 +889,90 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Main Simulation Loop"
"These are various memories allocated, with waveforms usually being the largest. "
" wsim.capture(time=2.5, cdata=cdata, offset=offset) # capture at time 2.5"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Output some captures data"
"The capture data contains for each PI, PO, and scan flip-flop (axis 0), and each test (axis 1) seven values:\n",
"0. Probability of capturing a 1 at the given capture time (same as next value, if no standard deviation given).\n",
"1. A capture value decided by random sampling according to above probability.\n",
"2. The final value (assume a very late capture time).\n",
"3. True, if there was a premature capture (capture error), i.e. final value is different from captured value.\n",
"4. Earliest arrival time. The time at which the output transitioned from its initial value.\n",
"5. Latest stabilization time. The time at which the output transitioned to its final value.\n",
"6. Overflow indicator. If non-zero, some signals in the input cone of this output had more transitions than specified in `wavecaps`. Some transitions have been discarded, the final values in the waveforms are still valid."
]
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(306, 32, 6)"
"(306, 128, 7)"
]
},
"execution_count": 20,
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
@ -567,46 +981,166 @@
@@ -567,46 +981,166 @@
"cdata.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For validating against known logic values, take `cdata[...,1]`."
]
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": 36,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"mismatch for test pattern 0\n",
"127 of 128 responses matched with simulator\n"
]
}
],
"source": [
"matches = 0\n",
"\n",
"for i in range(cdata.shape[1]):\n",
" response = ''.join('1' if x > 0.5 else '0' for x in cdata[..., i, 1])\n",
" if trans_responses[i].replace('-','0') == response:\n",
" matches += 1\n",
" else:\n",
" print(f'mismatch for test pattern {i}')\n",
"print(f'{matches} of {cdata.shape[1]} responses matched with simulator')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The circuit delay is the maximum among all latest stabilization times:"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0., 0., 0., ..., 0., 0., 0.],\n",
" [0., 0., 0., ..., 0., 0., 0.],\n",
" [0., 0., 0., ..., 0., 0., 0.],\n",
" ...,\n",
" [1., 1., 1., ..., 1., 1., 1.],\n",
" [0., 0., 0., ..., 0., 0., 0.],\n",
" [0., 0., 0., ..., 1., 1., 1.]], dtype=float32)"
"2.0610005855560303"
]
},
"execution_count": 21,
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cdata[...,5].max()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Check for overflows. If too many of them occur, increase `wavecaps` during engine instanciation:"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.0"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r"
"cdata[...,6].sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Check for CUDA Support\n",
"Check for capture failures:"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.0"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cdata[...,3].sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# CUDA Support Notes\n",
"\n",
"Try this code to check if CUDA is set up correctly."
"Try this code to check if CUDA is set up correctly.\n",
"\n",
"If there is an error related to `nvvm`, you probably need to set up some environment variables:\n",