A python module for parsing, processing, and simulating gate-level circuits.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

2306 lines
87 KiB

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# KyuPy Introduction\n",
"\n",
"This notebook introduces KyuPy's basic data structures and built-in functions step-by-step.\n",
"\n",
"## Working With Gate-Level Circuit Structures\n",
"\n",
"KyuPy has two parser modules:\n",
"\n",
"* `kyupy.bench`: The [ISCAS'89 Benchmark Format](https://www.researchgate.net/profile/Franc-Brglez/publication/224723140_Combination_profiles_of_sequential_benchmark_circuits) \".bench\"\n",
"* `kyupy.verilog`: Non-hierarchical gate-level verilog\n",
"\n",
"Files can be loaded using `.load(file)`, strings can be parsed using `.parse(text)`."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from kyupy import bench, verilog\n",
"\n",
"# load a file\n",
"b15 = verilog.load('../tests/b15_2ig.v.gz')\n",
"\n",
"# ... or specify the circuit as string \n",
"adder = bench.parse('''\n",
"INPUT(a, b)\n",
"OUTPUT(s)\n",
"cin = DFF(cout)\n",
"axb = XOR(a, b)\n",
"s = XOR(axb, cin)\n",
"aab = AND(a, b)\n",
"axbacin = AND(axb, cin)\n",
"cout = OR(aab, axbacin)\n",
"''', name='adder')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"They return KyuPy's intermediate prepresentation of the circuit graph (objects of class `kyupy.circuit.Circuit`):"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"kyupy.circuit.Circuit"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(b15)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{name: \"b15\", cells: 10789, forks: 10749, lines: 32032, io_nodes: 111}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b15"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{name: \"adder\", cells: 6, forks: 8, lines: 17, io_nodes: 3}"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `.stats` property returns a dictionary with more detailed statistics on the elements in the circuit."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'__node__': 21538,\n",
" '__cell__': 10789,\n",
" '__fork__': 10749,\n",
" '__io__': 111,\n",
" '__line__': 32032,\n",
" 'TIEH_RVT': 1,\n",
" '__comb__': 10261,\n",
" 'NBUFFX4_RVT': 114,\n",
" 'NBUFFX2_RVT': 371,\n",
" 'INVX2_RVT': 27,\n",
" 'NBUFFX8_RVT': 40,\n",
" 'INVX0_RVT': 769,\n",
" 'AND2X1_RVT': 996,\n",
" 'OR2X1_RVT': 1087,\n",
" 'OR2X2_RVT': 8,\n",
" 'INVX8_RVT': 30,\n",
" 'NOR2X2_RVT': 20,\n",
" 'INVX4_RVT': 36,\n",
" 'AND2X2_RVT': 50,\n",
" 'SDFFARX1_RVT': 412,\n",
" '__dff__': 417,\n",
" 'NAND2X0_RVT': 6596,\n",
" 'NOR2X0_RVT': 74,\n",
" 'NOR2X1_RVT': 15,\n",
" 'NAND2X1_RVT': 3,\n",
" 'NOR2X4_RVT': 5,\n",
" 'NAND2X2_RVT': 9,\n",
" 'SDFFARX2_RVT': 5,\n",
" 'NAND2X4_RVT': 3,\n",
" 'AND2X4_RVT': 1,\n",
" 'INVX32_RVT': 4,\n",
" 'INVX16_RVT': 1,\n",
" 'NBUFFX32_RVT': 1,\n",
" 'output': 71,\n",
" 'input': 40,\n",
" '__latch__': 0,\n",
" '__seq__': 417}"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b15.stats"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'__node__': 14,\n",
" '__cell__': 6,\n",
" '__fork__': 8,\n",
" '__io__': 3,\n",
" '__line__': 17,\n",
" 'DFF': 1,\n",
" '__dff__': 1,\n",
" 'XOR': 2,\n",
" '__comb__': 5,\n",
" 'AND': 2,\n",
" 'OR': 1,\n",
" '__latch__': 0,\n",
" '__seq__': 1}"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.stats"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Circuits contain `cells`, `forks`, `lines`, and `io_nodes`. Let's explore these...\n",
"\n",
"### Cells and Forks\n",
"\n",
"`cells` and `forks` are dictionaries that map names to `Node`-objects."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'cin': 4:DFF\"cin\" <1 >0,\n",
" 'axb': 6:XOR\"axb\" <3 <4 >2,\n",
" 's': 8:XOR\"s\" <6 <7 >5,\n",
" 'aab': 9:AND\"aab\" <9 <10 >8,\n",
" 'axbacin': 11:AND\"axbacin\" <12 <13 >11,\n",
" 'cout': 13:OR\"cout\" <15 <16 >14}"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.cells"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'a': 0:__fork__\"a\" >3 >9,\n",
" 'b': 1:__fork__\"b\" >4 >10,\n",
" 's': 2:__fork__\"s\" <5,\n",
" 'cout': 3:__fork__\"cout\" <14 >1,\n",
" 'cin': 5:__fork__\"cin\" <0 >7 >13,\n",
" 'axb': 7:__fork__\"axb\" <2 >6 >12,\n",
" 'aab': 10:__fork__\"aab\" <8 >15,\n",
" 'axbacin': 12:__fork__\"axbacin\" <11 >16}"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.forks"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Access any cell or fork by name using a simple dictionary lookup:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6:XOR\"axb\" <3 <4 >2"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.cells['axb']"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"7:__fork__\"axb\" <2 >6 >12"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.forks['axb']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Cells and forks are instances of class `Node`, which represent *things* that are connected to one or more other *things* in the circuit.\n",
"\n",
"* A **cell** represents a gate or a standard cell.\n",
"* A **fork** represents a named signal or a fan-out point (connecting the output of one cell to multiple other cells or forks).\n",
"\n",
"`Node`-objects have an `index`, a `kind`, and a `name`."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(6, 'XOR', 'axb')"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.cells['axb'].index, adder.cells['axb'].kind, adder.cells['axb'].name"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*Forks* are `Node`-objects of the special kind `__fork__`.\n",
"\n",
"*Cells* are `Node`-objects of any other kind. A *kind* is just a string and can be anything.\n",
"\n",
"The namespaces of *forks* and *cells* are separate:\n",
"* A *cell* and a *fork* **can** have the same name.\n",
"* Two *cells* or two *forks* **cannot** have the same name."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(7, '__fork__', 'axb')"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.forks['axb'].index, adder.forks['axb'].kind, adder.forks['axb'].name"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `index` of a *node* in a circuit is a unique and consecutive integer.\n",
"\n",
"Although *Forks* and *cells* can have the same name, they all have separate indices.\n",
"\n",
"Nodes can be accessed by their index using the `nodes` list:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0:__fork__\"a\" >3 >9,\n",
" 1:__fork__\"b\" >4 >10,\n",
" 2:__fork__\"s\" <5,\n",
" 3:__fork__\"cout\" <14 >1,\n",
" 4:DFF\"cin\" <1 >0,\n",
" 5:__fork__\"cin\" <0 >7 >13,\n",
" 6:XOR\"axb\" <3 <4 >2,\n",
" 7:__fork__\"axb\" <2 >6 >12,\n",
" 8:XOR\"s\" <6 <7 >5,\n",
" 9:AND\"aab\" <9 <10 >8,\n",
" 10:__fork__\"aab\" <8 >15,\n",
" 11:AND\"axbacin\" <12 <13 >11,\n",
" 12:__fork__\"axbacin\" <11 >16,\n",
" 13:OR\"cout\" <15 <16 >14]"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.nodes"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(6:XOR\"axb\" <3 <4 >2, 7:__fork__\"axb\" <2 >6 >12)"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.nodes[6], adder.nodes[7]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A common use for the index is to store additional data for nodes. Since the index is positive, unique, and consecutive, it can be easily used with external arrays or lists.\n",
"\n",
"This is how you store an additional \"weight\" for each node in the circuit:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"weights = [0] * len(adder.nodes)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Use the node instance to index into the external list. This also works with numpy arrays, of course."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"weights[adder.cells['axb']] = 5"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0]"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"weights"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Lines\n",
"\n",
"A `Line` is a directional 1:1 connection between two Nodes.\n",
"\n",
"A line has a circuit-unique and consecutive `index` just like nodes.\n",
"\n",
"Line and node indices are different!\n",
"\n",
"There is a `lines` list. If a line is printed, it just outputs its index:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.lines"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A line one `driver`-node and one `reader`-node:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(6:XOR\"axb\" <3 <4 >2, 7:__fork__\"axb\" <2 >6 >12)"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.lines[2].driver, adder.lines[2].reader"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Nodes show their connections to the lines with direction (\"<\" for input, \">\" for output) and the line index.\n",
"\n",
"In the example above, line 2 connects the output of cell \"axb\" to the input of fork \"axb\".\n",
"\n",
"The input connections and output connections of a node are ordered lists of lines called `ins` and `outs`:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"([3, 4], [2])"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.cells['axb'].ins, adder.cells['axb'].outs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A line also stores its positions in the connection lists in `driver_pin` and `reader_pin`:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(0, 0, 1)"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.lines[2].driver_pin, adder.lines[2].reader_pin, adder.lines[4].reader_pin"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### IO_Nodes\n",
"\n",
"Any node in the circuit can be designated as a primary input or primary output by adding it to the `io_nodes` list:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0:__fork__\"a\" >3 >9, 1:__fork__\"b\" >4 >10, 2:__fork__\"s\" <5]"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.io_nodes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It is common that io_nodes either have only output connections (in a role as primary-input) or only input connections (in a role as primary-output).\n",
"\n",
"Inputs and outputs appear in the order they were defined in the loaded file. Inputs and outputs are often interspersed.\n",
"\n",
"A related list is `s_nodes`. It contains the io_nodes at the beginning and adds all sequential elements (flip-flops, latches)."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0:__fork__\"a\" >3 >9, 1:__fork__\"b\" >4 >10, 2:__fork__\"s\" <5, 4:DFF\"cin\" <1 >0]"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.s_nodes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Basic Circuit Navigation\n",
"\n",
"A circuit can be traversed easily using the properties of `Circuit`, `Node`, and `Line`."
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6:XOR\"axb\" <3 <4 >2"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.io_nodes[0].outs[0].reader"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6:XOR\"axb\" <3 <4 >2\n",
"9:AND\"aab\" <9 <10 >8\n"
]
}
],
"source": [
"for line in adder.io_nodes[0].outs:\n",
" print(line.reader)"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'cout'"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.cells['cin'].ins[0].driver.name"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's continue with `b15` loaded before. It has 111 io_nodes:"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"({name: \"b15\", cells: 10789, forks: 10749, lines: 32032, io_nodes: 111},\n",
" [21386:output\"BE_n[3]\" <31961,\n",
" 21387:output\"BE_n[2]\" <31962,\n",
" 21388:output\"BE_n[1]\" <31963,\n",
" 21389:output\"BE_n[0]\" <31964,\n",
" 21390:output\"Address[29]\" <31965,\n",
" 21391:output\"Address[28]\" <31966,\n",
" 21392:output\"Address[27]\" <31967,\n",
" 21393:output\"Address[26]\" <31968,\n",
" 21394:output\"Address[25]\" <31969,\n",
" 21395:output\"Address[24]\" <31970,\n",
" 21396:output\"Address[23]\" <31971,\n",
" 21397:output\"Address[22]\" <31972,\n",
" 21398:output\"Address[21]\" <31973,\n",
" 21399:output\"Address[20]\" <31974,\n",
" 21400:output\"Address[19]\" <31975,\n",
" 21401:output\"Address[18]\" <31976,\n",
" 21402:output\"Address[17]\" <31977,\n",
" 21403:output\"Address[16]\" <31978,\n",
" 21404:output\"Address[15]\" <31979,\n",
" 21405:output\"Address[14]\" <31980])"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b15, b15.io_nodes[:20]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"and even more sequential nodes:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"528"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(b15.s_nodes)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `.io_locs(prefix)` and `.s_locs(prefix)` methods return the locations of signals, busses and registers in `io_nodes` and `s_nodes`. :"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"107"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b15.io_locs('RESET')"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[33,\n",
" 32,\n",
" 31,\n",
" 30,\n",
" 29,\n",
" 28,\n",
" 27,\n",
" 26,\n",
" 25,\n",
" 24,\n",
" 23,\n",
" 22,\n",
" 21,\n",
" 20,\n",
" 19,\n",
" 18,\n",
" 17,\n",
" 16,\n",
" 15,\n",
" 14,\n",
" 13,\n",
" 12,\n",
" 11,\n",
" 10,\n",
" 9,\n",
" 8,\n",
" 7,\n",
" 6,\n",
" 5,\n",
" 4]"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b15.io_locs('Address')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Example of a two-dimensional register file (16 8-bit registers):"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[[349, 348, 350, 347, 351, 346, 352, 345],\n",
" [357, 356, 358, 355, 359, 354, 360, 353],\n",
" [365, 364, 366, 363, 367, 362, 368, 361],\n",
" [373, 372, 374, 371, 375, 370, 376, 369],\n",
" [381, 380, 382, 379, 383, 378, 384, 377],\n",
" [389, 388, 390, 387, 391, 386, 392, 385],\n",
" [397, 396, 398, 395, 399, 394, 400, 393],\n",
" [405, 404, 406, 403, 407, 402, 408, 401],\n",
" [413, 412, 414, 411, 415, 410, 416, 409],\n",
" [421, 420, 422, 419, 423, 418, 424, 417],\n",
" [429, 428, 430, 427, 431, 426, 432, 425],\n",
" [437, 436, 438, 435, 439, 434, 440, 433],\n",
" [445, 444, 446, 443, 447, 442, 448, 441],\n",
" [453, 452, 454, 451, 455, 450, 456, 449],\n",
" [461, 460, 462, 459, 463, 458, 464, 457],\n",
" [469, 468, 470, 467, 471, 466, 472, 465]]"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b15.s_locs('InstQueue_reg')"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"---------------\n",
"1385:SDFFARX1_RVT\"InstQueue_reg_0__0_\" <12704 <12706 <12705 <12707 <12708 >702\n",
"1383:SDFFARX1_RVT\"InstQueue_reg_0__1_\" <12699 <12701 <12700 <12702 <12703 >701\n",
"1387:SDFFARX1_RVT\"InstQueue_reg_0__2_\" <12709 <12711 <12710 <12712 <12713 >703\n",
"1381:SDFFARX1_RVT\"InstQueue_reg_0__3_\" <12694 <12696 <12695 <12697 <12698 >700\n",
"1389:SDFFARX1_RVT\"InstQueue_reg_0__4_\" <12714 <12716 <12715 <12717 <12718 >704\n",
"1379:SDFFARX1_RVT\"InstQueue_reg_0__5_\" <12689 <12691 <12690 <12692 <12693 >699\n",
"1391:SDFFARX1_RVT\"InstQueue_reg_0__6_\" <12719 <12721 <12720 <12722 <12723 >705\n",
"1377:SDFFARX1_RVT\"InstQueue_reg_0__7_\" <12684 <12686 <12685 <12687 <12688 >698\n",
"---------------\n",
"1401:SDFFARX1_RVT\"InstQueue_reg_1__0_\" <12744 <12746 <12745 <12747 <12748 >710\n",
"1399:SDFFARX1_RVT\"InstQueue_reg_1__1_\" <12739 <12741 <12740 <12742 <12743 >709\n",
"1403:SDFFARX1_RVT\"InstQueue_reg_1__2_\" <12749 <12751 <12750 <12752 <12753 >711\n",
"1397:SDFFARX1_RVT\"InstQueue_reg_1__3_\" <12734 <12736 <12735 <12737 <12738 >708\n",
"1405:SDFFARX1_RVT\"InstQueue_reg_1__4_\" <12754 <12756 <12755 <12757 <12758 >712\n",
"1395:SDFFARX1_RVT\"InstQueue_reg_1__5_\" <12729 <12731 <12730 <12732 <12733 >707\n",
"1407:SDFFARX1_RVT\"InstQueue_reg_1__6_\" <12759 <12761 <12760 <12762 <12763 >713\n",
"1393:SDFFARX1_RVT\"InstQueue_reg_1__7_\" <12724 <12726 <12725 <12727 <12728 >706\n",
"---------------\n",
"1417:SDFFARX1_RVT\"InstQueue_reg_2__0_\" <12784 <12786 <12785 <12787 <12788 >718\n",
"1415:SDFFARX1_RVT\"InstQueue_reg_2__1_\" <12779 <12781 <12780 <12782 <12783 >717\n",
"1419:SDFFARX1_RVT\"InstQueue_reg_2__2_\" <12789 <12791 <12790 <12792 <12793 >719\n",
"1413:SDFFARX1_RVT\"InstQueue_reg_2__3_\" <12774 <12776 <12775 <12777 <12778 >716\n",
"1421:SDFFARX1_RVT\"InstQueue_reg_2__4_\" <12794 <12796 <12795 <12797 <12798 >720\n",
"1411:SDFFARX1_RVT\"InstQueue_reg_2__5_\" <12769 <12771 <12770 <12772 <12773 >715\n",
"1423:SDFFARX1_RVT\"InstQueue_reg_2__6_\" <12799 <12801 <12800 <12802 <12803 >721\n",
"1409:SDFFARX1_RVT\"InstQueue_reg_2__7_\" <12764 <12766 <12765 <12767 <12768 >714\n",
"---------------\n",
"1433:SDFFARX1_RVT\"InstQueue_reg_3__0_\" <12824 <12826 <12825 <12827 <12828 >726\n",
"1431:SDFFARX1_RVT\"InstQueue_reg_3__1_\" <12819 <12821 <12820 <12822 <12823 >725\n",
"1435:SDFFARX1_RVT\"InstQueue_reg_3__2_\" <12829 <12831 <12830 <12832 <12833 >727\n",
"1429:SDFFARX1_RVT\"InstQueue_reg_3__3_\" <12814 <12816 <12815 <12817 <12818 >724\n",
"1437:SDFFARX1_RVT\"InstQueue_reg_3__4_\" <12834 <12836 <12835 <12837 <12838 >728\n",
"1427:SDFFARX1_RVT\"InstQueue_reg_3__5_\" <12809 <12811 <12810 <12812 <12813 >723\n",
"1439:SDFFARX1_RVT\"InstQueue_reg_3__6_\" <12839 <12841 <12840 <12842 <12843 >729\n",
"1425:SDFFARX1_RVT\"InstQueue_reg_3__7_\" <12804 <12806 <12805 <12807 <12808 >722\n",
"---------------\n",
"1449:SDFFARX1_RVT\"InstQueue_reg_4__0_\" <12864 <12866 <12865 <12867 <12868 >734\n",
"1447:SDFFARX1_RVT\"InstQueue_reg_4__1_\" <12859 <12861 <12860 <12862 <12863 >733\n",
"1451:SDFFARX1_RVT\"InstQueue_reg_4__2_\" <12869 <12871 <12870 <12872 <12873 >735\n",
"1445:SDFFARX1_RVT\"InstQueue_reg_4__3_\" <12854 <12856 <12855 <12857 <12858 >732\n",
"1453:SDFFARX1_RVT\"InstQueue_reg_4__4_\" <12874 <12876 <12875 <12877 <12878 >736\n",
"1443:SDFFARX1_RVT\"InstQueue_reg_4__5_\" <12849 <12851 <12850 <12852 <12853 >731\n",
"1455:SDFFARX1_RVT\"InstQueue_reg_4__6_\" <12879 <12881 <12880 <12882 <12883 >737\n",
"1441:SDFFARX1_RVT\"InstQueue_reg_4__7_\" <12844 <12846 <12845 <12847 <12848 >730\n",
"---------------\n",
"1465:SDFFARX1_RVT\"InstQueue_reg_5__0_\" <12904 <12906 <12905 <12907 <12908 >742\n",
"1463:SDFFARX1_RVT\"InstQueue_reg_5__1_\" <12899 <12901 <12900 <12902 <12903 >741\n",
"1467:SDFFARX1_RVT\"InstQueue_reg_5__2_\" <12909 <12911 <12910 <12912 <12913 >743\n",
"1461:SDFFARX1_RVT\"InstQueue_reg_5__3_\" <12894 <12896 <12895 <12897 <12898 >740\n",
"1469:SDFFARX1_RVT\"InstQueue_reg_5__4_\" <12914 <12916 <12915 <12917 <12918 >744\n",
"1459:SDFFARX1_RVT\"InstQueue_reg_5__5_\" <12889 <12891 <12890 <12892 <12893 >739\n",
"1471:SDFFARX1_RVT\"InstQueue_reg_5__6_\" <12919 <12921 <12920 <12922 <12923 >745\n",
"1457:SDFFARX1_RVT\"InstQueue_reg_5__7_\" <12884 <12886 <12885 <12887 <12888 >738\n",
"---------------\n",
"1481:SDFFARX1_RVT\"InstQueue_reg_6__0_\" <12944 <12946 <12945 <12947 <12948 >750\n",
"1479:SDFFARX1_RVT\"InstQueue_reg_6__1_\" <12939 <12941 <12940 <12942 <12943 >749\n",
"1483:SDFFARX1_RVT\"InstQueue_reg_6__2_\" <12949 <12951 <12950 <12952 <12953 >751\n",
"1477:SDFFARX1_RVT\"InstQueue_reg_6__3_\" <12934 <12936 <12935 <12937 <12938 >748\n",
"1485:SDFFARX1_RVT\"InstQueue_reg_6__4_\" <12954 <12956 <12955 <12957 <12958 >752\n",
"1475:SDFFARX1_RVT\"InstQueue_reg_6__5_\" <12929 <12931 <12930 <12932 <12933 >747\n",
"1487:SDFFARX1_RVT\"InstQueue_reg_6__6_\" <12959 <12961 <12960 <12962 <12963 >753\n",
"1473:SDFFARX1_RVT\"InstQueue_reg_6__7_\" <12924 <12926 <12925 <12927 <12928 >746\n",
"---------------\n",
"1497:SDFFARX1_RVT\"InstQueue_reg_7__0_\" <12984 <12986 <12985 <12987 <12988 >758\n",
"1495:SDFFARX1_RVT\"InstQueue_reg_7__1_\" <12979 <12981 <12980 <12982 <12983 >757\n",
"1499:SDFFARX1_RVT\"InstQueue_reg_7__2_\" <12989 <12991 <12990 <12992 <12993 >759\n",
"1493:SDFFARX1_RVT\"InstQueue_reg_7__3_\" <12974 <12976 <12975 <12977 <12978 >756\n",
"1501:SDFFARX1_RVT\"InstQueue_reg_7__4_\" <12994 <12996 <12995 <12997 <12998 >760\n",
"1491:SDFFARX1_RVT\"InstQueue_reg_7__5_\" <12969 <12971 <12970 <12972 <12973 >755\n",
"1503:SDFFARX1_RVT\"InstQueue_reg_7__6_\" <12999 <13001 <13000 <13002 <13003 >761\n",
"1489:SDFFARX1_RVT\"InstQueue_reg_7__7_\" <12964 <12966 <12965 <12967 <12968 >754\n",
"---------------\n",
"1513:SDFFARX1_RVT\"InstQueue_reg_8__0_\" <13024 <13026 <13025 <13027 <13028 >766\n",
"1511:SDFFARX1_RVT\"InstQueue_reg_8__1_\" <13019 <13021 <13020 <13022 <13023 >765\n",
"1515:SDFFARX1_RVT\"InstQueue_reg_8__2_\" <13029 <13031 <13030 <13032 <13033 >767 >768\n",
"1509:SDFFARX1_RVT\"InstQueue_reg_8__3_\" <13014 <13016 <13015 <13017 <13018 >764\n",
"1518:SDFFARX1_RVT\"InstQueue_reg_8__4_\" <13034 <13036 <13035 <13037 <13038 >769\n",
"1507:SDFFARX1_RVT\"InstQueue_reg_8__5_\" <13009 <13011 <13010 <13012 <13013 >763\n",
"1520:SDFFARX1_RVT\"InstQueue_reg_8__6_\" <13039 <13041 <13040 <13042 <13043 >770\n",
"1505:SDFFARX1_RVT\"InstQueue_reg_8__7_\" <13004 <13006 <13005 <13007 <13008 >762\n",
"---------------\n",
"1530:SDFFARX1_RVT\"InstQueue_reg_9__0_\" <13064 <13066 <13065 <13067 <13068 >775\n",
"1528:SDFFARX1_RVT\"InstQueue_reg_9__1_\" <13059 <13061 <13060 <13062 <13063 >774\n",
"1532:SDFFARX1_RVT\"InstQueue_reg_9__2_\" <13069 <13071 <13070 <13072 <13073 >776\n",
"1526:SDFFARX1_RVT\"InstQueue_reg_9__3_\" <13054 <13056 <13055 <13057 <13058 >773\n",
"1534:SDFFARX1_RVT\"InstQueue_reg_9__4_\" <13074 <13076 <13075 <13077 <13078 >777\n",
"1524:SDFFARX1_RVT\"InstQueue_reg_9__5_\" <13049 <13051 <13050 <13052 <13053 >772\n",
"1536:SDFFARX1_RVT\"InstQueue_reg_9__6_\" <13079 <13081 <13080 <13082 <13083 >778\n",
"1522:SDFFARX1_RVT\"InstQueue_reg_9__7_\" <13044 <13046 <13045 <13047 <13048 >771\n",
"---------------\n",
"1546:SDFFARX1_RVT\"InstQueue_reg_10__0_\" <13104 <13106 <13105 <13107 <13108 >783\n",
"1544:SDFFARX1_RVT\"InstQueue_reg_10__1_\" <13099 <13101 <13100 <13102 <13103 >782\n",
"1548:SDFFARX1_RVT\"InstQueue_reg_10__2_\" <13109 <13111 <13110 <13112 <13113 >784\n",
"1542:SDFFARX1_RVT\"InstQueue_reg_10__3_\" <13094 <13096 <13095 <13097 <13098 >781\n",
"1550:SDFFARX1_RVT\"InstQueue_reg_10__4_\" <13114 <13116 <13115 <13117 <13118 >785 >786\n",
"1540:SDFFARX1_RVT\"InstQueue_reg_10__5_\" <13089 <13091 <13090 <13092 <13093 >780\n",
"1553:SDFFARX1_RVT\"InstQueue_reg_10__6_\" <13119 <13121 <13120 <13122 <13123 >787\n",
"1538:SDFFARX1_RVT\"InstQueue_reg_10__7_\" <13084 <13086 <13085 <13087 <13088 >779\n",
"---------------\n",
"1563:SDFFARX1_RVT\"InstQueue_reg_11__0_\" <13144 <13146 <13145 <13147 <13148 >792\n",
"1561:SDFFARX1_RVT\"InstQueue_reg_11__1_\" <13139 <13141 <13140 <13142 <13143 >791\n",
"1565:SDFFARX1_RVT\"InstQueue_reg_11__2_\" <13149 <13151 <13150 <13152 <13153 >793\n",
"1559:SDFFARX1_RVT\"InstQueue_reg_11__3_\" <13134 <13136 <13135 <13137 <13138 >790\n",
"1567:SDFFARX1_RVT\"InstQueue_reg_11__4_\" <13154 <13156 <13155 <13157 <13158 >794\n",
"1557:SDFFARX1_RVT\"InstQueue_reg_11__5_\" <13129 <13131 <13130 <13132 <13133 >789\n",
"1569:SDFFARX1_RVT\"InstQueue_reg_11__6_\" <13159 <13161 <13160 <13162 <13163 >795\n",
"1555:SDFFARX1_RVT\"InstQueue_reg_11__7_\" <13124 <13126 <13125 <13127 <13128 >788\n",
"---------------\n",
"1579:SDFFARX1_RVT\"InstQueue_reg_12__0_\" <13184 <13186 <13185 <13187 <13188 >800\n",
"1577:SDFFARX1_RVT\"InstQueue_reg_12__1_\" <13179 <13181 <13180 <13182 <13183 >799\n",
"1581:SDFFARX1_RVT\"InstQueue_reg_12__2_\" <13189 <13191 <13190 <13192 <13193 >801\n",
"1575:SDFFARX1_RVT\"InstQueue_reg_12__3_\" <13174 <13176 <13175 <13177 <13178 >798\n",
"1583:SDFFARX1_RVT\"InstQueue_reg_12__4_\" <13194 <13196 <13195 <13197 <13198 >802\n",
"1573:SDFFARX1_RVT\"InstQueue_reg_12__5_\" <13169 <13171 <13170 <13172 <13173 >797\n",
"1585:SDFFARX1_RVT\"InstQueue_reg_12__6_\" <13199 <13201 <13200 <13202 <13203 >803\n",
"1571:SDFFARX1_RVT\"InstQueue_reg_12__7_\" <13164 <13166 <13165 <13167 <13168 >796\n",
"---------------\n",
"1595:SDFFARX1_RVT\"InstQueue_reg_13__0_\" <13224 <13226 <13225 <13227 <13228 >808\n",
"1593:SDFFARX1_RVT\"InstQueue_reg_13__1_\" <13219 <13221 <13220 <13222 <13223 >807\n",
"1597:SDFFARX1_RVT\"InstQueue_reg_13__2_\" <13229 <13231 <13230 <13232 <13233 >809\n",
"1591:SDFFARX1_RVT\"InstQueue_reg_13__3_\" <13214 <13216 <13215 <13217 <13218 >806\n",
"1599:SDFFARX1_RVT\"InstQueue_reg_13__4_\" <13234 <13236 <13235 <13237 <13238 >810\n",
"1589:SDFFARX1_RVT\"InstQueue_reg_13__5_\" <13209 <13211 <13210 <13212 <13213 >805\n",
"1601:SDFFARX1_RVT\"InstQueue_reg_13__6_\" <13239 <13241 <13240 <13242 <13243 >811\n",
"1587:SDFFARX1_RVT\"InstQueue_reg_13__7_\" <13204 <13206 <13205 <13207 <13208 >804\n",
"---------------\n",
"1611:SDFFARX1_RVT\"InstQueue_reg_14__0_\" <13264 <13266 <13265 <13267 <13268 >816\n",
"1609:SDFFARX1_RVT\"InstQueue_reg_14__1_\" <13259 <13261 <13260 <13262 <13263 >815\n",
"1613:SDFFARX1_RVT\"InstQueue_reg_14__2_\" <13269 <13271 <13270 <13272 <13273 >817\n",
"1607:SDFFARX1_RVT\"InstQueue_reg_14__3_\" <13254 <13256 <13255 <13257 <13258 >814\n",
"1615:SDFFARX1_RVT\"InstQueue_reg_14__4_\" <13274 <13276 <13275 <13277 <13278 >818\n",
"1605:SDFFARX1_RVT\"InstQueue_reg_14__5_\" <13249 <13251 <13250 <13252 <13253 >813\n",
"1617:SDFFARX1_RVT\"InstQueue_reg_14__6_\" <13279 <13281 <13280 <13282 <13283 >819\n",
"1603:SDFFARX1_RVT\"InstQueue_reg_14__7_\" <13244 <13246 <13245 <13247 <13248 >812\n",
"---------------\n",
"1627:SDFFARX1_RVT\"InstQueue_reg_15__0_\" <13304 <13306 <13305 <13307 <13308 >824\n",
"1625:SDFFARX1_RVT\"InstQueue_reg_15__1_\" <13299 <13301 <13300 <13302 <13303 >823\n",
"1629:SDFFARX1_RVT\"InstQueue_reg_15__2_\" <13309 <13311 <13310 <13312 <13313 >825\n",
"1623:SDFFARX1_RVT\"InstQueue_reg_15__3_\" <13294 <13296 <13295 <13297 <13298 >822\n",
"1631:SDFFARX1_RVT\"InstQueue_reg_15__4_\" <13314 <13316 <13315 <13317 <13318 >826\n",
"1621:SDFFARX1_RVT\"InstQueue_reg_15__5_\" <13289 <13291 <13290 <13292 <13293 >821\n",
"1633:SDFFARX1_RVT\"InstQueue_reg_15__6_\" <13319 <13321 <13320 <13322 <13323 >827\n",
"1619:SDFFARX1_RVT\"InstQueue_reg_15__7_\" <13284 <13286 <13285 <13287 <13288 >820\n"
]
}
],
"source": [
"for l in b15.s_locs('InstQueue_reg'):\n",
" print('---------------')\n",
" for i in l:\n",
" print(b15.s_nodes[i])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example: Tracing A Scan Chain\n",
"\n",
"We start at the output of the scan chain \"test_so000\", then go backwards through the circuit.\n",
"\n",
"When we encounter a scan cell \"SDFF\", we continue with the \"SI\" pin, which has index 2."
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"length (with forks): 1123\n",
"length (without forks): 562\n",
"length only SDFF: 417\n",
"output\"test_so000\" __fork__\"test_so000\" NBUFFX8_RVT\"ZBUF_15_inst_543\" __fork__\"aps_rename_15_\" SDFFARX1_RVT\"W_R_n_reg\" __fork__\"ZBUF_17_48\" NBUFFX2_RVT\"ZBUF_17_inst_981\" __fork__\"N3897\" SDFFARX1_RVT\"uWord_reg_14_\" __fork__\"N3896\" ... __fork__\"Address[0]\" NBUFFX2_RVT\"ZBUF_19_inst_438\" __fork__\"aps_rename_14_\" SDFFARX1_RVT\"Address_reg_0_\" __fork__\"ADS_n\" NBUFFX2_RVT\"ZBUF_34_inst_547\" __fork__\"aps_rename_18_\" SDFFARX1_RVT\"ADS_n_reg\" __fork__\"test_si000\" input\"test_si000\"\n"
]
}
],
"source": [
"chain = [cell := b15.cells['test_so000']]\n",
"while len(cell.ins) > 0:\n",
" chain.append(cell := cell.ins[2 if cell.kind.startswith('SDFF') else 0].driver)\n",
" \n",
"print(f'length (with forks): {len(chain)}')\n",
"print(f'length (without forks): {len(list(filter(lambda n: n.kind != \"__fork__\", chain)))}')\n",
"print(f'length only SDFF: {len(list(filter(lambda n: n.kind.startswith(\"SDFF\"), chain)))}')\n",
"\n",
"names = [f'{c.kind}\"{c.name}\"' for c in chain]\n",
"print(' '.join(names[:10]) + ' ... ' + ' '.join(names[-10:]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Traversing a Circuit in Topological Order\n",
"\n",
"There are several generators to traverse the circuit in various topological orderings.\n",
"\n",
"The following loop prints all nodes:\n",
"* starting with primary inputs (nodes that don't have any input connections) and sequential elements,\n",
"* and continuing with nodes who's inputs are connected only to already printed nodes."
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0:__fork__\"a\" >3 >9\n",
"1:__fork__\"b\" >4 >10\n",
"4:DFF\"cin\" <1 >0\n",
"6:XOR\"axb\" <3 <4 >2\n",
"9:AND\"aab\" <9 <10 >8\n",
"5:__fork__\"cin\" <0 >7 >13\n",
"7:__fork__\"axb\" <2 >6 >12\n",
"10:__fork__\"aab\" <8 >15\n",
"8:XOR\"s\" <6 <7 >5\n",
"11:AND\"axbacin\" <12 <13 >11\n",
"2:__fork__\"s\" <5\n",
"12:__fork__\"axbacin\" <11 >16\n",
"13:OR\"cout\" <15 <16 >14\n",
"3:__fork__\"cout\" <14 >1\n"
]
}
],
"source": [
"for n in adder.topological_order():\n",
" print(n)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Example: Determine Topological Level\n",
"\n",
"The topological (or logic level) of a node is its distance from inputs or sequential elements.\n",
"\n",
"Inputs and flip-flops themselves are level 0, *cells* driven by just inputs and flip-flops are level 1, and so on.\n",
"*Fork* nodes have the same level as their driver, because they do not increase the logic depth."
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Maximum logic depth: 44\n"
]
}
],
"source": [
"import numpy as np\n",
"\n",
"levels = np.zeros(len(b15.nodes), dtype=np.uint32) # array to store level for each node.\n",
"\n",
"for n in b15.topological_order():\n",
" if 'DFF' in n.kind or len(n.ins) == 0:\n",
" levels[n] = 0 # use the node n directly to index into the array.\n",
" elif n.kind == '__fork__':\n",
" levels[n] = levels[n.ins[0].driver] # forks only have exactly one driver\n",
" else:\n",
" levels[n] = max([levels[line.driver] for line in n.ins]) + 1\n",
" \n",
"print(f'Maximum logic depth: {np.max(levels)}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"List nodes with the highest depth and which nodes they are driving."
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"depth: 44 node: __fork__ n4587 driving: SDFFARX1_RVT EAX_reg_31_ \n",
"depth: 44 node: NAND2X0_RVT U737 driving: __fork__ n4587 \n",
"depth: 43 node: __fork__ n4478 driving: SDFFARX1_RVT Address_reg_29_\n",
"depth: 43 node: NAND2X0_RVT U738 driving: __fork__ n684 \n",
"depth: 43 node: __fork__ n4416 driving: SDFFARX1_RVT PhyAddrPointer_reg_29_\n",
"depth: 43 node: NAND2X0_RVT U220 driving: __fork__ n4416 \n",
"depth: 43 node: NAND2X0_RVT U214 driving: __fork__ n4414 \n",
"depth: 43 node: __fork__ n4414 driving: SDFFARX1_RVT PhyAddrPointer_reg_31_\n",
"depth: 43 node: __fork__ n684 driving: NAND2X0_RVT U737 \n",
"depth: 43 node: NAND2X0_RVT U408 driving: __fork__ n4478 \n",
"depth: 42 node: NAND2X0_RVT U216 driving: __fork__ n332 \n",
"depth: 42 node: __fork__ n4510 driving: SDFFARX1_RVT rEIP_reg_29_ \n",
"depth: 42 node: NAND2X0_RVT U595 driving: __fork__ n4540 \n",
"depth: 42 node: __fork__ n4540 driving: SDFFARX1_RVT EBX_reg_31_ \n",
"depth: 42 node: __fork__ n4588 driving: SDFFARX1_RVT EAX_reg_30_ \n",
"depth: 42 node: __fork__ n332 driving: NAND2X0_RVT U214 \n",
"depth: 42 node: NAND2X0_RVT U222 driving: __fork__ n337 \n",
"depth: 42 node: __fork__ n463 driving: NAND2X0_RVT U408 \n",
"depth: 42 node: __fork__ n4446 driving: SDFFARX1_RVT InstAddrPointer_reg_31_\n",
"depth: 42 node: NAND2X0_RVT U311 driving: __fork__ n4446 \n"
]
}
],
"source": [
"nodes_by_depth = np.argsort(levels)[::-1]\n",
"\n",
"for n_idx in nodes_by_depth[:20]:\n",
" n = b15.nodes[n_idx] # get the node itself by its index\n",
" readers = ', '.join([f'{l.reader.kind:12s} {l.reader.name:14s}' for l in n.outs])\n",
" print(f'depth: {levels[n_idx]} node: {n.kind:12s} {n.name:6s} driving: {readers}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Working With Logic Values\n",
"\n",
"Sequential states of circuits, signals, and test patterns contain logic values.\n",
"\n",
"KyuPy provides some useful tools to deal with 2-valued, 4-valued, and 8-valued logic data.\n",
"\n",
"All logic values are stored in numpy arrays of dtype `np.uint8`.\n",
"\n",
"There are two storage formats:\n",
"* `mv` (for \"multi-valued\"): Each logic value is stored as uint8\n",
"* `bp` (for \"bit-parallel\"): Groups of 8 logic values are stored as three uint8"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `mv` Arrays\n",
"\n",
"Suppose we want to simulate the adder circuit with 2 inputs, 1 output and 1 flip-flop."
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0:__fork__\"a\" >3 >9, 1:__fork__\"b\" >4 >10, 2:__fork__\"s\" <5, 4:DFF\"cin\" <1 >0]"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"adder.s_nodes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can construct a set of vectors using the `mvarray` helper function.\n",
"\n",
"Each vector has 4 elements, one for each io_node and sequential element.\n",
"\n",
"This would be an exhaustive vector set (the output in `s_nodes` remains unassigned (\"-\")):"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0, 3, 0, 3, 0, 3, 0, 3],\n",
" [0, 0, 3, 3, 0, 0, 3, 3],\n",
" [2, 2, 2, 2, 2, 2, 2, 2],\n",
" [0, 0, 0, 0, 3, 3, 3, 3]], dtype=uint8)"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from kyupy import logic\n",
"\n",
"inputs = logic.mvarray('00-0', '10-0', '01-0', '11-0', '00-1', '10-1', '01-1', '11-1')\n",
"inputs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The numeric values in this array are defined in `kyupy.logic`.\n",
"A logic-0 is stored as `0`, a logic-1 is stored as `3`, and 'unassigned' is stored as `2`.\n",
"\n",
"The **last** axis is always the number of vectors. It may be unintuitive at first, but it is more convenient for data-parallel simulations.\n",
"\n",
"The **second-to-last** axis corresponds to `s_nodes`. I.e., the first row is for input 'a', the second row for input 'b', and so on."
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(4, 8)"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"inputs.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Get a string representation of a vector set. Possible values are '0', '1', '-', 'X', 'R', 'F', 'P', and 'N'."
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"00-0\n",
"10-0\n",
"01-0\n",
"11-0\n",
"00-1\n",
"10-1\n",
"01-1\n",
"11-1\n"
]
}
],
"source": [
"print(logic.mv_str(inputs))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Load a stuck-at fault test pattern set and expected fault-free responses from a STIL file. It contains 678 test vectors."
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [],
"source": [
"from kyupy import stil\n",
"\n",
"s = stil.load('../tests/b15_2ig.sa_nf.stil.gz')\n",
"stuck_tests = s.tests(b15)\n",
"stuck_responses = s.responses(b15)"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"528"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(b15.s_nodes)"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(528, 678)"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stuck_tests.shape"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(528, 678)"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stuck_responses.shape"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"------------------------------------------------------------------------------------------------------0----00--000110110011010011101101001011010010110100101101001001100110011001100110011001100011001100110011001100110011001110011001100110011001100110011001011101001011010010110100101101001011010010110100101101001011101100110011001101100110000010010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011100110011001100110011001100110011111100001001011000100\n",
"--------------------------------------1100011011011111--------10111110--------------------------------P-00000--0101111000011010-01----110---110-110---110-11001100110-11101010011010-10-1010-1010101010-10-10-1010-10-10-10-101-10101010101010-10-10100-01010101011-01-11101110111011101-101-111011101-111011101-111010101000-10-1010-101010010-10011--0100-100110000111100001-111111-000011100000-101-01000011110-11-001000011111111-0001010100010001000----1----1-----1---11-----------00-101010101010-1010-1010101010101--10-1101010111111111\n",
"---------------------------------------1-1--1--1---1--1000100000000011--------------------------------P-10-00--11000001101111011---0--01-1111111111111111--1111110-111011111-111---11--11-1--1--------------------------------000000001---1----1--010-1-1---10010110011111110101001-0-0-0-1-0-1-0-011-0-1-000-1-001-1000101111111111111111111101111001101----1----------1-----------------------------------------------------1-11011100011111111-----111-----1-111-0-1-1----------------01------1------1-1-------------1--011-01011110011101111\n",
"------------------------------------------------------------------------------------------------------P111100--11011-0110000-10--0-----0--0-0-1-0-1-0-0-1---1-0-1-------0-01-11---0-0--00-0-00--------------------------------001100110000011000111110011000100--0011-------------1---------------------0-1-----1---1-1-1-1111111111111111101000100--001000011001-----1--111111--1--11--111--011---------------------------------0-------0-0---------------------------------------------00--------------------------------10-110-10010010-01010\n",
"--------------------------------------1011011111010000--------00101101--------------------------------P001100--10001010001111100-1-10101-1-1-1-1-1-1-1-1-101-1-1-100-000----0--00--1-0---------------------------------------------1--------------------------110-0--00001-0011001-001-0011001-0-0-010-001-1-0110101-1-1-0-100000000000011--1-11-1110-1----1--------------0--00---00-01---00-0----00-00---11-00--00000001011-0001-00-01---001001--11100---00-00---00-00---------1100-----01-------------0---------------0--11------0101000-10---\n"
]
}
],
"source": [
"print(logic.mv_str(stuck_tests[:,:5]))"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"11001100110011001100110011001100110000--------------------------------01001100110011001100110011001100--------0000110110011010011101101001011010010110100101101001001100110011001100110011001100011001100110011001100110011001110011001100110011001100110011001011101001011010010110100101101001011010010110100101101001011101100110011001101100110000010010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011100110011001100110011001100110011111100001001011000100\n",
"X0101010101010101X0101X01010101010XX11--------------------------------001X01X01X01X0101X01X01X01010101--------X0001010110000010X01XXXX110XXX110X110XXX110X11001100110X11101010011010X10X1010X1010101010X10X10X1010X10X10X10X101X10101010101010X10X10100X01010101110X00X01000100010001000X000X010001000X010001000X010000000000X10X1010X101010010X10001XX0100X100110000111100001X111111X000011100000X101X01000011110X11X001000011111111X00010101000100010001111011011110110110000011001110101X101010101010X1010X10101010101011X1001101010111111111\n",
"1X11XX1XXXXXXXXXXXXX1X1XXXXXX1XXXX1X1X--------------------------------0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX--------101010001101110010011111100000000000000000011000000110000000001000110000000001000XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX000000001XXX1XXXX1XX010X1X1XXX10110110011111110101001X0X0X0X1X0X1X0X011X0X1X000X1X001X1000101000000000000000000011111001010XXXX1XXXXXXXXXX1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1X11011100011111111XXXXX111XXXXX1X111X0X1X1XXXXXXXXXXXXXXXX0110000100100010100101001011011001100100101100001110101\n",
"0101XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0X0X--------------------------------0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX--------011011X11100000000X0XXXXX0XX0X0X1X0X1X0X0X1XXX1X0X1XXXXXXX0X01X11XXX0X0XX00X0X00XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX011100110000011000111110011000100XX0011XXXXXXXXXXXXX1XXXXXXXXXXXXXXXXXXXXX0X1XXXXX1XXX1X1X1X1111111111111111101000100XX001000011001XXXXX1XX111111XX1XX11XX111XX011XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0XXXXXXX0X0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX10X1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX101110010110110X01010\n",
"1XXXXX0XXXXXXXXXXXXXXX0XXXXXXXXXXX1XXX--------------------------------0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX--------100011001101001100X1X10101X1X1X1X1X1X1X1X1X101X1X1X100X000XXXX0XX00XX1X0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXXXXXXXXXXXXXXXXXXXXXXXX110X0XX00101X0011001X001X0011001X0X0X010X001X1X0110101X1X1X0X100000000000011XX1X11X1110X1XX1000101111100010X0XX00XXX00X01XXX00X0XXXX00X00XXX11X00XX00000001011X0001X00X01XXX001001XX11100XXX00X00XXX00X00XX01101100011011001011XXXXXXXXXXX0XXXXXXXXXXXXXXX0XX010X1X1X0101000X10XXX\n"
]
}
],
"source": [
"print(logic.mv_str(stuck_responses[:,:5]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The order of values in the vectors correspond to the circuit's `s_nodes`.\n",
"The test data can be used directly in the simulators as they use the same ordering convention.\n",
"\n",
"`stuck_tests` has values for all primary inputs and scan flip-flops, `stuck_responses` contains the expected values for all primary outputs and scan flip-flops.\n",
"\n",
"Since this is a static test, only '0', '1' and 'X' are used with the exception of the clock input, which has a positive pulse 'P'.\n",
"\n",
"A transition fault test is a dynamic test that also contains 'R' for rising transition and 'F' for falling transition:"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [],
"source": [
"s = stil.load('../tests/b15_2ig.tf_nf.stil.gz')\n",
"transition_tests = s.tests_loc(b15)\n",
"transition_responses = s.responses(b15)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"STIL files for delay tests usually only contain the initialization patterns.\n",
"When loading launch-on-capture transition fault tests, use `.tests_loc()`. This function performs a logic simulation of the launch cycle to calculate the transitions for the delay test itself."
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"------------------------------------------------------------------------------------------------------X----XX--000110110011010011101101001011010010110100101101001001100110011001100110011001100011001100110011001100110011001110011001100110011001100110011001011101001011010010110100101101001011010010110100101101001011101100110011001101100110000010010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011100110011001100110011001100110011111100001001011000100\n",
"--------------------------------------RFRRRRFRRFRRRR1R--------RXXRXRRR--------------------------------00F0F00--RR1RRXRF00011010XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX011X00XXX101X1X1X1X1X1X1X1X1X1X1X1X1X1X1X1X1X1X1X1X1X0XXXXXXX1XXXXXXXXXXXXXXXXXXXXXXXXRRXRXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX00000000000000000111111000001001RFXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX11XXXXX\n",
"--------------------------------------1X111XX11X1XX1X11XX11XX111X11X11--------------------------------0-XXR00--F1FF1X0110011X01XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXFXX1XFFX1XFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX0XFXFXFXF11110XX1XX1XXXXXXX1XXXX1XFR1F1XXXXXXXXXXXXXXXXX011101111000101101110111110001001000100010101011011001110111000X1XX11XXXXXXXX11XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX000X011111111111111111111111111111R0F1R0R001RR100FF1XXX\n",
"--------------------------------------------------------------XXXXXXXX--------------------------------0--FX00--F11F1XFRR00R01111XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0XX1XXXXXRX1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX111111111111111111111110X0XX10XXXXXXXXXRXXXRXRF1FFFRFRXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXXXXXXXXXXX0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX11X1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX011001010010111111111\n",
"--------------------------------------------------------------FFXFFFFF--------------------------------0XXRR00--RF01FXRF00001XX1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX010X010111111111X111111111111111X11100XX0101XXXXXX01XXXX01XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1X1111X110111111XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0RXRXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXXXX\n"
]
}
],
"source": [
"print(logic.mv_str(transition_tests[:,:5]))"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"11001100110011001100110011001100110000--------------------------------01001100110011001100110011001100--------0000110110011010011101101001011010010110100101101001001100110011001100110011001100011001100110011001100110011001110011001100110011001100110011001011101001011010010110100101101001011010010110100101101001011101100110011001101100110000010010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011100110011001100110011001100110011111100001001011000100\n",
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1--------------------------------0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX--------X01001X0110000010XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX011X00XXX000X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X1XXXXXXX1XXXXXXXXXXXXXXXXXXXXXXXX11X1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1111111111111111100000011111011010X1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0X0X0X1XXXXXXX11XXXXX\n",
"0100111111111111111111111111111110101X--------------------------------0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX--------101011X0110011001000X0X0X1X0X0X1X0X0X0X1X1X0X0X1X1X010110100110001XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0XX1X00X1X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X000001XX1XX1XXXXXXX1XXXX1X01000XXXXXXXXXXXXXXXXX011101111000101101110111110001001000100010101011011001110111000X1XX11XXXXXXXX11XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0010100000000000000000000000000000111011011000000010XXX\n",
"1011XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX01--------------------------------0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX--------X00101X01100100010XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0XX1XXXXX1X1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX000000000000000000000001X0XX11XXXXXXXX0100010101000101XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXXXXXXXXXXX0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX11101XXXXXXXXXXXXXXXXXXXXXXXXXXXXX001100000100001110100\n",
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1--------------------------------0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX--------X01000X1100101XX1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX000X0011000000000000000000000000000011XX1111XXXXXX11XXXX11XXXXXXXXXXXXXXXXXXXXXXXXXXXX11X1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0100000001000000XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX01X1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1X0X0X1XXXXXXXX0XXXXX\n"
]
}
],
"source": [
"print(logic.mv_str(transition_responses[:,:5]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Initialization patterns and launch patterns can be filtered by providing a call-back function. This can be used to fill in unassigned values."
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {},
"outputs": [],
"source": [
"def zero_fill(mva):\n",
" return np.choose(mva, logic.mvarray('0X01PRFN')) # maps '0X-1PRFN' -> '0X01PRFN'\n",
"\n",
"transition_tests_zf = s.tests_loc(b15, init_filter=zero_fill, launch_filter=zero_fill)"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110110011010011101101001011010010110100101101001001100110011001100110011001100011001100110011001100110011001110011001100110011001100110011001011101001011010010110100101101001011010010110100101101001011101100110011001101100110000010010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011100110011001100110011001100110011111100001001011000100\n",
"00000000000000000000000000000000000000RFRRRRFRRFRRRR1R00000000RRRRRRRR0000000000000000000000000000000000F0F0000RR1RR0RF00011010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000010101010101010101010101010101010101010101010000000001000000000000000000000000RR0R000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111000001001RF0R000000000000000000000000000000R00000R00000001100000\n",
"00000000000000000000000000000000000000101110011010010110011001110110110000000000000000000000000000000000R0R0000F1FF1001100110010RR0R0R000R0R000R0R0R00000R0R00000R0R00R0RR00RRR0000000000000000000000000000000000000000000000000000000000000000000000000000000F0010FF010F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F000F0F0F0F1111000100100000001000010FR1F1000000000000000000111011110001011011101111100010010001000101010110110011101110000100110000000011000000000000000000000000000000000000011111111111111111111111111111R0F1R0R001RR100FF1000\n",
"000000000000000000000000000000000000000000000000000000000000000FF00F0000000000000000000000000000000000000F00000F11F10FRR00R01111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000R010000000000000000000000000000000000000000000000000111111111111111111111110000010000000000R000R0RF1FFFRFR000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001101000000000000000000000000000000011001010010111111111\n",
"00000000000000000000000000000000000000000000000000000000000000FFRFFFFF00000000000000000000000000000000000RR0000RF01F0RF00001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000101111111110111111111111111011100000101000000010000010000000000000000000000000000RR0R0000000000000000000000000000000000000000000000000000000000000000000000000101111011011111100000000000000000000000000000000000000000R0R000000000000000000000000000000R0R000R00000001000000\n"
]
}
],
"source": [
"print(logic.mv_str(transition_tests_zf[:,:5]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `bp` Arrays\n",
"\n",
"The logic simulator uses bit-parallel storage of logic values, but our loaded test data uses one `uint8` per logic value.\n",
"\n",
"Use `mv_to_bp` to convert mv data to the bit-parallel storage layout.\n",
"Bit-parallel storage is more compact, but individual values cannot be easily accessed anymore."
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [],
"source": [
"stuck_tests_bp = logic.mv_to_bp(stuck_tests)"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(528, 3, 85)"
]
},
"execution_count": 53,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stuck_tests_bp.data.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Instead of 678 bytes per s_node, bit-parallel storage only uses 3*85=255 bytes.\n",
"\n",
"The reverse operation is `bp_to_mv`. Note that the number of vectors may be rounded up to the next multiple of 8:"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(528, 680)"
]
},
"execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"logic.bp_to_mv(stuck_tests_bp).shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Logic Simulation\n",
"\n",
"The following code performs a 8-valued logic simulation on all 678 vectors for one clock cycle."
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [],
"source": [
"from kyupy.logic_sim import LogicSim\n",
"\n",
"sim = LogicSim(b15, sims=stuck_tests.shape[-1]) # 678 simulations in parallel\n",
"sim.s[0] = stuck_tests_bp\n",
"sim.s_to_c()\n",
"sim.c_prop()\n",
"sim.c_to_s()\n",
"sim_responses = logic.bp_to_mv(sim.s[1])[...,:stuck_tests.shape[-1]] # trim from 680 -> 678"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"11001100110011001100110011001100110000--------------------------------01001100110011001100110011001100--------010X110XXX011010011101101001011010010110100101101001001100110011001100110011001100011001100110011001100110011001110011001100110011001100110011001011101001011010010110100101101001011010010110100101101001011101100110011001101100110000010010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011100110011001100110011001100110011111100001001011000100\n",
"-0101010101010101-0101-01010101010--11--------------------------------001-01-01X01-0101-01-01-01010101---------0001010110000010X01XXXX110XXX110X110XXX110X11001100110X11101010011010X10X1010X1010101010X10X10X1010X10X10X10X101X10101010101010X10X10100X01010101110X00X01000100010001000X000X010001000X010001000X010000000000X10X1010X101010010X10001XX0100X100110000111100001X111111X000011100000X101X01000011110X11X001000011111111X00010101000100010001111011011110110110000011001110101X101010101010X1010X10101010101011X1001101010111111111\n",
"1-11--1-------------1-1------1----1-1---------------------------------0--------X------------------------------101010001101110010011111100000000000000000011000000110000000001000110000000001000XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX000000001XXX1XXXX1XX010X1X1XXX10110110011111110101001X0X0X0X1X0X1X0X011X0X1X000X1X001X1000101000000000000000000011111001010XXXX1XXXXXXXXXX1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1X11011100011111111XXXXX111XXXXX1X111X0X1X1XXXXXXXXXXXXXXXX0110000100100010100101001011011001100100101100001110101\n",
"0101------------------------------0-0---------------------------------0--------X------------------------------011011X11100000000X0XXXXX0XX0X0X1X0X1X0X0X1XXX1X0X1XXXXXXX0X01X11XXX0X0XX00X0X00XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX011100110000011000111110011000100XX0011XXXXXXXXXXXXX1XXXXXXXXXXXXXXXXXXXXX0X1XXXXX1XXX1X1X1X1111111111111111101000100XX001000011001XXXXX1XX111111XX1XX11XX111XX011XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0XXXXXXX0X0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX10X1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX101110010110110X01010\n",
"1-----0---------------0-----------1-----------------------------------0--------X------------------------------100011001101001100X1X10101X1X1X1X1X1X1X1X1X101X1X1X100X000XXXX0XX00XX1X0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXXXXXXXXXXXXXXXXXXXXXXXX110X0XX00101X0011001X001X0011001X0X0X010X001X1X0110101X1X1X0X100000000000011XX1X11X1110X1XX1000101111100010X0XX00XXX00X01XXX00X0XXXX00X00XXX11X00XX00000001011X0001X00X01XXX001001XX11100XXX00X00XXX00X00XX01101100011011001011XXXXXXXXXXX0XXXXXXXXXXXXXXX0XX010X1X1X0101000X10XXX\n"
]
}
],
"source": [
"print(logic.mv_str(sim_responses[:,:5]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Compare simulation results to expected fault-free responses loaded from STIL.\n",
"\n",
"The first test fails, because it is a flush test while simulation implicitly assumes a standard test with a capture clock.\n",
"\n",
"The remaining 677 responses should be compatible.\n",
"\n",
"The following checks for compatibility (unknown/unassigned values in STIL always match)."
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"677"
]
},
"execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.sum(np.min((sim_responses == stuck_responses) | \n",
" (stuck_responses == logic.UNASSIGNED) | \n",
" (stuck_responses == logic.UNKNOWN), axis=0))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Same simulation for the transition-fault test set:"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [],
"source": [
"sim = LogicSim(b15, sims=transition_tests_zf.shape[-1]) # 1147 simulations in parallel\n",
"sim.s[0] = logic.mv_to_bp(transition_tests_zf)\n",
"sim.s_to_c()\n",
"sim.c_prop()\n",
"sim.c_to_s()\n",
"sim_responses = logic.bp_to_mv(sim.s[1])[...,:transition_tests_zf.shape[-1]] # trim to 1147"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"11001100110011001100110011001100110000--------------------------------01001100110011001100110011001100--------0100110001011010011101101001011010010110100101101001001100110011001100110011001100011001100110011001100110011001110011001100110011001100110011001011101001011010010110100101101001011010010110100101101001011101100110011001101100110000010010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011100110011001100110011001100110011111100001001011000100\n",
"0000000000000000000000000000000000000R--------------------------------00000000000000000000000000000000--------0FNFFNPFRR0PFF01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000NNP0PP00F0FPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPF0F0F0F0FPRP0P0P0PN000000000000000000000000NNPNP000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000RRRRRRRRRRRRRRRRRFFFFFFRRRRRFRRFNPPNP00000000000000000000000000000FPP000NP0000P0NN00000\n",
"01001111111111111111111111111111101010--------------------------------00000000000000000000000000000000--------1PNPRN0PNN0011001PFF0F0F0R0F0F0R0F0F0F0R0R0F0F0R0R0FRFRRFRFFRRFFFR000000000000000PP0PP0PPP00PP00P00000000000000000000000000000000000000000000000P00N0PP0N0P0P0P0P0P0P0P0P0P0P0P0P0P0P0P0P0P0P0P0P0P000P0P0P0PFFFFR00N00N0000000N0000N0PNFPF00000000000000000011101111000101101110111110001001000100010101011011001110111000010011000000001100000000000000000000000000000000PPRPRFFFFFFFFFFFFFFFFFFFFFFFFFFFFFNRRFNRFRRFFFFP0PRF000\n",
"10110000000000000000000000000000000001--------------------------------00000000000000000000000000000000--------0PFNP1PPNNPPNPFFNF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000PPPNP00PPNPNPPP0P0P0P0P0P0P0P0P0P0P0P0P0P0P000000000000000000FFFFFFFFFFFFFFFFFFFFFFFR0PPRNR000000000N000N0NPNPPPNPN0P000P0P0P000P0P0P000P0P0P000P0P0P000P0P0PN00P0P0000000000000000000000000000000000000000000000000000000011RFR000000000000000000000000000000F1R0F0F0RFPFFNNNFNFF\n",
"0000000000000000000000000000000000000R--------------------------------00000000000000000000000000000000--------0FRPFPPNRP0RPN00N00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F00PFRNFFFFFFFFPFFFFFFFFFFFFFFFPFFFRRP0RNRN000000RN0000RN000PP0PPPPPPP0P0000000000000NN0N0000000000000000000000000000000000000000000000000000000000000000000000000FRFFFFPFFRFFFFFFPPPPPPPPPPPPPPPP0000000000000000000000000N0N000000000000000000000000000000N0F000N00000PPF00PP00\n"
]
}
],
"source": [
"print(logic.mv_str(sim_responses[:,:5]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The simulator responses contain 'R' for rising transition, 'F' for falling transition, 'P' for possible positive pulse(s) (010) and 'N' for possible negative pulse(s) (101).\n",
"\n",
"We need to map each of these cases to the final logic values before we can compare:"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"11001100110011001100110011001100110000--------------------------------01001100110011001100110011001100--------0100110001011010011101101001011010010110100101101001001100110011001100110011001100011001100110011001100110011001110011001100110011001100110011001011101001011010010110100101101001011010010110100101101001011101100110011001101100110000010010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011100110011001100110011001100110011111100001001011000100\n",
"00000000000000000000000000000000000001--------------------------------00000000000000000000000000000000--------0010010011000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000010000000100000000000000000000000011010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111110000001111101101001000000000000000000000000000000000000100000001100000\n",
"01001111111111111111111111111111101010--------------------------------00000000000000000000000000000000--------1010110011001100100000000100000100000001010000010100101101001100010000000000000000000000000000000000000000000000000000000000000000000000000000000001000010000000000000000000000000000000000000000000000000000000010010010000000100001001000000000000000000000111011110001011011101111100010010001000101010110110011101110000100110000000011000000000000000000000000000000000010100000000000000000000000000000111011011000000010000\n",
"10110000000000000000000000000000000001--------------------------------00000000000000000000000000000000--------0001010011001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000001010000000000000000000000000000000000000000000000000000000000000000000000001000111000000000100010101000101000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001110100000000000000000000000000000001100000100001110100\n",
"00000000000000000000000000000000000001--------------------------------00000000000000000000000000000000--------0010000110010100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000001100111100000011000011000000000000000000000000000011010000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000000000000000000000101000000000000000000000000000000100000100000000000000\n"
]
}
],
"source": [
"sim_responses_final = np.choose(sim_responses, logic.mvarray('0X-10101')) # maps '0X-1PRFN' -> '0X-10101'\n",
"print(logic.mv_str(sim_responses_final[:,:5]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Again, first test is a flush test, so we expect 1146 matches.\n",
"\n",
"We simulated zero-filled patterns and therefore have more specified output bits.\n",
"\n",
"The following checks for compatability (unknown/unassigned values in STIL always match)."
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1146"
]
},
"execution_count": 61,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.sum(np.min((sim_responses_final == transition_responses) | \n",
" (transition_responses == logic.UNASSIGNED) | \n",
" (transition_responses == logic.UNKNOWN), axis=0))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Working With Delay Information and Timing Simulation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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": 62,
"metadata": {},
"outputs": [],
"source": [
"from kyupy import sdf\n",
"\n",
"df = sdf.load('../tests/b15_2ig.sdf.gz')\n",
"delays = df.iopaths(b15)[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The returned delay information is an `ndarray` with a set of delay values for each line in the circuit."
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(32032, 2, 2)"
]
},
"execution_count": 63,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"delays.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Number of non-0 values loaded:"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"79010"
]
},
"execution_count": 64,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(delays != 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",
"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": 65,
"metadata": {},
"outputs": [],
"source": [
"from kyupy.wave_sim import WaveSimCuda, TMAX\n",
"\n",
"wsim = WaveSimCuda(b15, delays, sims=32, c_caps=16)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"These are various memories allocated, with waveforms usually being the largest. "
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Waveforms : 64294.0 kiB\n",
"State Allocation Table : 129.3 kiB\n",
"Circuit Timing : 1034.1 kiB\n",
"Circuit Netlist : 1126.1 kiB\n",
"Sequential State : 726.0 kiB\n"
]
}
],
"source": [
"def print_mem(name, arr):\n",
" print(f'{name}: {arr.nbytes / 1024:.1f} kiB')\n",
" \n",
"print_mem('Waveforms ', wsim.c)\n",
"print_mem('State Allocation Table ', wsim.c_locs)\n",
"print_mem('Circuit Timing ', wsim.delays)\n",
"print_mem('Circuit Netlist ', wsim.ops)\n",
"print_mem('Sequential State ', wsim.s)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is a typical simulation loop where the number of patterns is larger than the number of simulators available.\n",
"We simulate `transition_tests_zf`.\n",
"The initial values, transition times and final values are loaded into `wsim.s` and the following three calls will update this array with simulation results. We collect all results in `wsim_results`."
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {},
"outputs": [],
"source": [
"from kyupy import batchrange\n",
"import numpy as np\n",
"\n",
"sims = 128 # transition_tests_zf.shape[-1] # Feel free to simulate all tests if CUDA is set up correctly.\n",
"\n",
"wsim_results = np.zeros((11, wsim.s_len, sims)) # space to store all simulation results\n",
"\n",
"for offset, size in batchrange(sims, wsim.sims):\n",
" wsim.s[0] = (transition_tests_zf[:,offset:offset+size] >> 1) & 1 # initial value\n",
" wsim.s[1] = 0.0 # transition time\n",
" wsim.s[2] = transition_tests_zf[:,offset:offset+size] & 1 # final value\n",
" wsim.s_to_c()\n",
" wsim.c_prop(sims=size)\n",
" wsim.c_to_s(time=1.5) # capture at time 1.5\n",
" wsim_results[:,:,offset:offset+size] = wsim.s[:,:,:size]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The arrays `wsim.s` and `wsim_results` contain various information for each PI, PO, and scan flip-flop (axis 1), and each test (axis 2):\n",
"* ``s[0]`` (P)PI initial value\n",
"* ``s[1]`` (P)PI transition time\n",
"* ``s[2]`` (P)PI final value\n",
"* ``s[3]`` (P)PO initial value\n",
"* ``s[4]`` (P)PO earliest arrival time (EAT): The time at which the output transitioned from its initial value.\n",
"* ``s[5]`` (P)PO latest stabilization time (LST): The time at which the output settled to its final value.\n",
"* ``s[6]`` (P)PO final value\n",
"* ``s[7]`` (P)PO capture value: probability of capturing a 1 at a given capture time\n",
"* ``s[8]`` (P)PO sampled capture value: decided by random sampling according to a given seed.\n",
"* ``s[9]`` (P)PO sampled capture slack: (capture time - LST) - decided by random sampling according to a given seed.\n",
"* ``s[10]`` Overflow indicator: If non-zero, some signals in the input cone of this output had more\n",
" transitions than specified in ``c_caps``. Some transitions have been discarded, the\n",
" final values in the waveforms are still valid."
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(11, 528, 128)"
]
},
"execution_count": 68,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wsim_results.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For validating against known logic values, convert the samples capture values `wsim_results[8]` into an mvarray like this:"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"110011001100110011001100110011001100000000000000000000000000000000000001001100110011001100110011001100000000000100110001011010011101101001011010010110100101101001001100110011001100110011001100011001100110011001100110011001110011001100110011001100110011001011101001011010010110100101101001011010010110100101101001011101100110011001101100110000010010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011100110011001100110011001100110011111100001001011000100\n",
"000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000010010011000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000010000000100000000000000000000000011010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111110000001111101101001000000000000000000000000000000000000100000001100000\n",
"010011111111111111111111111111111010100000000000000000000000000000000000000000000000000000000000000000000000001010110011001100100000000100000100000001010000010100101101001100010000000000000000000000000000000000000000000000000000000000000000000000000000000001000010000000000000000000000000000000000000000000000000000000010010010000000100001001000000000000000000000111011110001011011101111100010010001000101010110110011101110000100110000000011000000000000000000000000000000000010100000000000000000000000000000111011011000000010000\n",
"101100000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000001010011001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000001010000000000000000000000000000000000000000000000000000000000000000000000001000111000000000100010101000101000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001110100000000000000000000000000000001100000100001110100\n",
"000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000010000110010100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000001100111100000011000011000000000000000000000000000011010000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000000000000000000000101000000000000000000000000000000100000100000000000000\n"
]
}
],
"source": [
"wsim_responses_final = ((wsim_results[8] > 0.5) * logic.ONE).astype(np.uint8)\n",
"print(logic.mv_str(wsim_responses_final[:,:5]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We expect 127 matches here."
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"127"
]
},
"execution_count": 70,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.sum(np.min((wsim_responses_final == transition_responses[:,:sims]) | \n",
" (transition_responses[:,:sims] == logic.UNASSIGNED) | \n",
" (transition_responses[:,:sims] == logic.UNKNOWN), axis=0))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The circuit delay is the maximum among all latest stabilization times:"
]
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.0424000024795532"
]
},
"execution_count": 71,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wsim_results[5].max()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Check for overflows. If too many of them occur, increase `c_caps` during engine instanciation:"
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.0"
]
},
"execution_count": 72,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wsim_results[10].sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Check for capture failures by comparing the samples PPO capture value with the final PPO value:"
]
},
{
"cell_type": "code",
"execution_count": 73,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 73,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(wsim_results[6] != wsim_results[8]).sum()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.9"
},
"vscode": {
"interpreter": {
"hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
}
}
},
"nbformat": 4,
"nbformat_minor": 4
}