diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 00000000..44c89746 --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 15bcfc5e0d3550994f780fe622ea1282 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.doctrees/environment.pickle b/.doctrees/environment.pickle new file mode 100644 index 00000000..fb7ec9e7 Binary files /dev/null and b/.doctrees/environment.pickle differ diff --git a/.doctrees/index.doctree b/.doctrees/index.doctree new file mode 100644 index 00000000..765ae10e Binary files /dev/null and b/.doctrees/index.doctree differ diff --git a/.doctrees/switchboard.bitvector.doctree b/.doctrees/switchboard.bitvector.doctree new file mode 100644 index 00000000..ccbcb839 Binary files /dev/null and b/.doctrees/switchboard.bitvector.doctree differ diff --git a/.doctrees/switchboard.doctree b/.doctrees/switchboard.doctree new file mode 100644 index 00000000..63a66068 Binary files /dev/null and b/.doctrees/switchboard.doctree differ diff --git a/.doctrees/switchboard.icarus.doctree b/.doctrees/switchboard.icarus.doctree new file mode 100644 index 00000000..b47a353f Binary files /dev/null and b/.doctrees/switchboard.icarus.doctree differ diff --git a/.doctrees/switchboard.loopback.doctree b/.doctrees/switchboard.loopback.doctree new file mode 100644 index 00000000..91f772c0 Binary files /dev/null and b/.doctrees/switchboard.loopback.doctree differ diff --git a/.doctrees/switchboard.sbdut.doctree b/.doctrees/switchboard.sbdut.doctree new file mode 100644 index 00000000..0d836c43 Binary files /dev/null and b/.doctrees/switchboard.sbdut.doctree differ diff --git a/.doctrees/switchboard.sbtcp.doctree b/.doctrees/switchboard.sbtcp.doctree new file mode 100644 index 00000000..95a07ec4 Binary files /dev/null and b/.doctrees/switchboard.sbtcp.doctree differ diff --git a/.doctrees/switchboard.uart_xactor.doctree b/.doctrees/switchboard.uart_xactor.doctree new file mode 100644 index 00000000..0926bfc1 Binary files /dev/null and b/.doctrees/switchboard.uart_xactor.doctree differ diff --git a/.doctrees/switchboard.umi.doctree b/.doctrees/switchboard.umi.doctree new file mode 100644 index 00000000..d9960bb1 Binary files /dev/null and b/.doctrees/switchboard.umi.doctree differ diff --git a/.doctrees/switchboard.util.doctree b/.doctrees/switchboard.util.doctree new file mode 100644 index 00000000..4d49fc5e Binary files /dev/null and b/.doctrees/switchboard.util.doctree differ diff --git a/.doctrees/switchboard.verilator.doctree b/.doctrees/switchboard.verilator.doctree new file mode 100644 index 00000000..2d0a0c49 Binary files /dev/null and b/.doctrees/switchboard.verilator.doctree differ diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/_modules/index.html b/_modules/index.html new file mode 100644 index 00000000..eba14d1f --- /dev/null +++ b/_modules/index.html @@ -0,0 +1,112 @@ + + + + + + Overview: module code — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+ + +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/switchboard/bitvector.html b/_modules/switchboard/bitvector.html new file mode 100644 index 00000000..b587ed13 --- /dev/null +++ b/_modules/switchboard/bitvector.html @@ -0,0 +1,227 @@ + + + + + + switchboard.bitvector — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for switchboard.bitvector

+# Utilities for working with bit vectors using Verilog-style syntax, i.e. [MSB:LSB]
+
+# Copyright (c) 2024 Zero ASIC Corporation
+# This code is licensed under Apache License 2.0 (see LICENSE for details)
+
+import numpy as np
+
+
+
+[docs] +class BitVector: + def __init__(self, value: int = 0): + self.value = int(value) + + def __int__(self): + return int(self.value) + + def __str__(self): + return f'0x{self.value:x}' + + def __setitem__(self, key, value): + if isinstance(key, slice): + if (key.start is None) and (key.stop is None) and (key.step is None): + self.value = value + return + else: + msb, lsb = slice_to_msb_lsb(key.start, key.stop, key.step) + else: + msb, lsb = slice_to_msb_lsb(key, key) + + # generate mask with the right width + mask = (1 << (msb - lsb + 1)) - 1 + + # clear bit field using the mask + new_value = self.value & (~(mask << lsb)) + + # set bit field + new_value |= (value & mask) << lsb + + # set the new value (done here instead of through + # incremental updates, to prevent the value from + # being partially updated in case of an exception + self.value = new_value + + def __getitem__(self, key): + if isinstance(key, slice): + if (key.start is None) and (key.stop is None) and (key.step is None): + return self.value + else: + msb, lsb = slice_to_msb_lsb(key.start, key.stop, key.step) + else: + msb, lsb = slice_to_msb_lsb(key, key) + + # generate mask with the right width + mask = (1 << (msb - lsb + 1)) - 1 + + # extract the value + return (self.value >> lsb) & mask + +
+[docs] + def tobytes(self, n=None): + # convert to a numpy byte array. if "n" is provided, + # pad result to be "n" bytes. will error out if "n" + # is less than the number of bytes needed to represent + # the current value. + + value = self.value + bytes = [] + + while value != 0: + bytes.append(value & 0xff) + value >>= 8 + + if n is not None: + if len(bytes) < n: + bytes += [0] * (n - len(bytes)) + elif len(bytes) > n: + raise ValueError('Number of bytes needed to represent the current value' + f' ({self.value}) is {len(bytes)}, but the argument n={n} is smaller.') + + return np.array(bytes, dtype=np.uint8)
+ + +
+[docs] + @staticmethod + def frombytes(arr): + value = 0 + + for i, elem in enumerate(arr): + if not (0 <= elem <= 255): + raise ValueError(f'Non-byte value detected at index {i}: {elem}') + value |= (int(elem) & 0xff) << (i * 8) + + return BitVector(value)
+
+ + + +
+[docs] +def slice_to_msb_lsb(start=None, stop=None, step=None): + # set defaults + if start is None: + start = 0 + if stop is None: + stop = 0 + if step is None: + step = 1 + + if step != 1: + raise ValueError('Only step=1 allowed for slice indexing.') + + msb = start + lsb = stop + + if msb < lsb: + raise ValueError('MSB must be greater than or equal to LSB') + if lsb < 0: + raise ValueError('Negative LSB is not allowed.') + + return msb, lsb
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/switchboard/icarus.html b/_modules/switchboard/icarus.html new file mode 100644 index 00000000..cf9d811f --- /dev/null +++ b/_modules/switchboard/icarus.html @@ -0,0 +1,200 @@ + + + + + + switchboard.icarus — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for switchboard.icarus

+# Utilities for working with Icarus Verilog
+
+# Copyright (c) 2024 Zero ASIC Corporation
+# This code is licensed under Apache License 2.0 (see LICENSE for details)
+
+# TODO: replace with SiliconCompiler functionality
+
+from typing import Union, List
+from pathlib import Path
+
+from .util import plusargs_to_args, binary_run
+from .switchboard import path as sb_path
+from subprocess import check_output, STDOUT, CalledProcessError
+
+
+
+[docs] +def run(command: list, cwd: str = None) -> str: + return check_output(command, cwd=cwd, stderr=STDOUT).decode()
+ + + +
+[docs] +def icarus_build_vpi( + cwd: str = None, + name: str = 'switchboard', + cincludes: List[str] = None, + ldflags: List[str] = None +) -> str: + if cincludes is None: + cincludes = [] + + if ldflags is None: + ldflags = [] + + sbdir = sb_path() + incdirs = cincludes + [f'{sbdir}/cpp'] + + cmd = [] + cmd += ['iverilog-vpi'] + cmd += [f'-I{incdir}' for incdir in incdirs] + cmd += ldflags + cmd += [str(sbdir / 'vpi' / f'{name}_vpi.cc')] + + try: + run(cmd, cwd) + except CalledProcessError as e: + print(e.output) + raise
+ + + +
+[docs] +def icarus_find_vpi(cwd: Union[str, Path] = None, name: str = 'switchboard') -> Path: + path = Path(f'{name}_vpi.vpi') + + if cwd is not None: + path = Path(cwd) / path + + if path.exists(): + return path + else: + return None
+ + + +
+[docs] +def icarus_run(vvp, plusargs=None, modules=None, extra_args=None, **kwargs): + args = [] + + args += ['-n'] + + mdirs = set() + + if modules is not None: + if not isinstance(modules, list): + raise TypeError('modules must be a list') + for module in modules: + mdirs.add(str(Path(module.resolve().parent))) + args += ['-m', Path(module).stem] + + for mdir in mdirs: + args += [f'-M{mdir}'] + + args += [vvp] + args += plusargs_to_args(plusargs) + + if extra_args is not None: + if not isinstance(modules, list): + raise TypeError('extra_args must be a list') + args += extra_args + + return binary_run(bin='vvp', args=args, **kwargs)
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/switchboard/loopback.html b/_modules/switchboard/loopback.html new file mode 100644 index 00000000..3ce2cbb4 --- /dev/null +++ b/_modules/switchboard/loopback.html @@ -0,0 +1,263 @@ + + + + + + switchboard.loopback — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for switchboard.loopback

+# Loopback test to check the behavior of blocks that split/merge UMI packets
+
+# Copyright (c) 2024 Zero ASIC Corporation
+# This code is licensed under Apache License 2.0 (see LICENSE for details)
+
+from numbers import Integral
+from typing import Iterable, Iterator, Union
+
+try:
+    from tqdm import tqdm
+except ModuleNotFoundError:
+    tqdm = None
+
+from .umi import UmiTxRx, random_umi_packet
+
+
+
+[docs] +def umi_loopback( + umi: UmiTxRx, + packets: Union[Integral, Iterable, Iterator] = 10, + **kwargs +): + """ + Performs a loopback test by sending packets into a block and checking that + the packets received back are equivalent under the UMI split/merge rules. + + Parameters + ---------- + umi: UmiTxRx + packets: + Can be a number, a list of packets, or a generator. + + - If this is a number, it represents the number of packets to send, + which are generated with random_umi_packet. Any remaining arguments + are passed directly to random_umi_packet. + - If this is an iterable (list, tuple, etc.), then it represents a list + of packets to use for the test. This is helpful if you want to use a very + specific sequence of transactions. + - This can also be an iterator, which might be convenient if you want to + send a very large number of packets without having to store them + all in memory at once, e.g. (random_umi_packet() for _ in range(1000000)) + + Raises + ------ + ValueError + If the number of packets is not positive or if the `packets` argument is empty + Exception + If a received packet does not match the corresponding transmitted packet + + """ + + # input validation + + if isinstance(packets, Integral): + if packets <= 0: + raise ValueError(f'The number of packets must be positive (got packets={packets}).') + else: + total = packets + packets = (random_umi_packet(**kwargs) for _ in range(packets)) + elif isinstance(packets, Iterable): + if isinstance(packets, (list, tuple)): + total = len(packets) + else: + total = float('inf') + packets = iter(packets) + elif isinstance(packets, Iterator): + total = float('inf') + else: + raise TypeError(f'Unsupported type for packets: {type(packets)}') + + tx_sets = [] # kept for debug purposes + tx_hist = [] + + tx_set = None + tx_partial = None + + rx_set = None # kept for debug purposes + rx_partial = None + + if tqdm is not None: + pbar = tqdm(total=total) + else: + pbar = None + + # get the first element + try: + txp = next(packets) + if pbar is not None: + pbar.update(0) + except StopIteration: + raise ValueError('The argument "packets" is empty.') + + while (txp is not None) or (len(tx_hist) > 0): + # send data + if txp is not None: + if umi.send(txp, blocking=False): + if tx_partial is not None: + if not tx_partial.merge(txp): + tx_hist.append(tx_partial) + tx_sets.append(tx_set) + tx_start_new = True + else: + tx_set.append(txp) + tx_start_new = False + else: + tx_start_new = True + + if tx_start_new: + tx_partial = txp + tx_set = [txp] + + try: + txp = next(packets) + except StopIteration: + txp = None + + if txp is None: + # if this is the last packet, add it to the history + # even if the merge was successful + tx_hist.append(tx_partial) + tx_sets.append(tx_set) + + # receive data + if len(tx_hist) > 0: + rxp = umi.recv(blocking=False) + if rxp is not None: + # try to merge into an existing partial packet + if rx_partial is not None: + if not rx_partial.merge(rxp): + print('=== Mismatch detected ===') + for i, p in enumerate(tx_sets[0]): + print(f'* TX[{i}] *') + print(p) + print('---') + for i, p in enumerate(rx_set): + print(f'* RX[{i}] *') + print(p) + print('=========================') + raise Exception('Mismatch!') + else: + rx_set.append(rxp) + else: + rx_partial = rxp + rx_set = [rxp] + + # at this point it is guaranteed there is something in + # rx_partial, so compare it to the expected outbound packet + if rx_partial == tx_hist[0]: + tx_hist.pop(0) + tx_sets.pop(0) + rx_partial = None + rx_set = None + + if pbar is not None: + pbar.update() + + if pbar is not None: + pbar.close()
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/switchboard/sbdut.html b/_modules/switchboard/sbdut.html new file mode 100644 index 00000000..39adde1c --- /dev/null +++ b/_modules/switchboard/sbdut.html @@ -0,0 +1,964 @@ + + + + + + switchboard.sbdut — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for switchboard.sbdut

+# Build and simulation automation built on SiliconCompiler
+
+# Copyright (c) 2024 Zero ASIC Corporation
+# This code is licensed under Apache License 2.0 (see LICENSE for details)
+
+"""Class inheriting from the SiliconCompiler Chip class that can be used for building a
+Switchboard-based testbench.
+
+This class is meant to be interacted with like a regular Chip object, but it has some parameters
+automatically configured to abstract away setup of files that are required by all Switchboard
+testbenches.
+"""
+
+import importlib
+import subprocess
+
+from copy import deepcopy
+from pathlib import Path
+from typing import List, Dict, Any
+
+from .switchboard import path as sb_path
+from .verilator import verilator_run
+from .icarus import icarus_build_vpi, icarus_find_vpi, icarus_run
+from .util import plusargs_to_args, binary_run, ProcessCollection
+from .xyce import xyce_flags
+from .ams import make_ams_spice_wrapper, make_ams_verilog_wrapper, parse_spice_subckts
+from .autowrap import (normalize_clocks, normalize_interfaces, normalize_resets, normalize_tieoffs,
+    normalize_parameters, create_intf_objs)
+from .cmdline import get_cmdline_args
+
+import siliconcompiler
+
+SB_DIR = sb_path()
+
+
+
+[docs] +class SbDut(siliconcompiler.Chip): + def __init__( + self, + design: str = 'testbench', + tool: str = 'verilator', + default_main: bool = True, + trace: bool = True, + trace_type: str = 'vcd', + module: str = None, + fpga: bool = False, + xyce: bool = False, + frequency: float = 100e6, + period: float = None, + max_rate: float = -1, + start_delay: float = None, + timeunit: str = None, + timeprecision: str = None, + warnings: List[str] = None, + cmdline: bool = False, + fast: bool = False, + extra_args: dict = None, + autowrap: bool = False, + parameters=None, + interfaces=None, + clocks=None, + resets=None, + tieoffs=None, + buildroot=None, + builddir=None, + args=None, + subcomponent=False, + suffix=None, + threads=None + ): + """ + Parameters + ---------- + design: string + Name of the top level chip design module. + + tool: string, optional + Which tool to use to compile simulator. Options are "verilator" or + "icarus". + + default_main: bool, optional + If True, the default testbench.cc will be used and does not need to + be provided via the add() function + + trace: bool, optional + If true, a waveform dump file will be produced using the file type + specified by `trace_type`. + + trace_type: str, optional + File type for the waveform dump file. Defaults to vcd. + + module: str, optional + module containing the siliconcompiler driver for this object + + fpga: bool, optional + If True, compile using switchboard's library of modules for FPGA emulation, + rather than the modules for RTL simulation. + + xyce: bool, optional + If True, compile for xyce co-simulation. + + frequency: float, optional + If provided, the default frequency of the clock generated in the testbench, + in seconds. + + period: float, optional + If provided, the default period of the clock generated in the testbench, + in seconds. + + max_rate: float, optional + If provided, the maximum real-world rate that the simulation is allowed to run + at, in Hz. Can be useful to encourage time-sharing between many processes and + for performance modeling when latencies are large and/or variable. + + start_delay: float, optional + If provided, the real-world time to delay before the first clock tick in the + simulation. Can be useful to make sure that programs start at approximately + the same time and to prevent simulations from stepping on each other's toes + when starting up. + + warnings: List[str], optional + If provided, a list of tool-specific warnings to enable. If not provided, a default + set of warnings will be included. Warnings can be disabled by setting this argument + to an empty list. + + cmdline: bool, optional + If True, accept configuration settings from the command line, such as "--trace", + "--tool TOOL", and "--fast". + + fast: bool, optional + If True, the simulation binary will not be rebuilt if an existing one is found. + The setting here can be overridden when build() is called by setting its argument + with the same name. + + extra_args: dict, optional + If provided and cmdline=True, a dictionary of additional command line arguments + to be made available. The keys of the dictionary are the arguments ("-n", "--test", + etc.) and the values are themselves dictionaries that contain keyword arguments + accepted by argparse ("action": "store_true", "default": 42, etc.) + """ + + # call the super constructor + + if autowrap and (not subcomponent): + toplevel = 'testbench' + else: + toplevel = design + + super().__init__(toplevel) + + # parse command-line options if desired + + if cmdline: + self.args = get_cmdline_args(tool=tool, trace=trace, trace_type=trace_type, + frequency=frequency, period=period, fast=fast, max_rate=max_rate, + start_delay=start_delay, threads=threads, extra_args=extra_args) + elif args is not None: + self.args = args + else: + self.args = None + + if self.args is not None: + trace = self.args.trace + trace_type = self.args.trace_type + fast = self.args.fast + tool = self.args.tool + frequency = self.args.frequency + period = self.args.period + max_rate = self.args.max_rate + start_delay = self.args.start_delay + threads = self.args.threads + + # input validation + + if trace_type not in ('vcd', 'fst'): + raise ValueError('Invalid trace_type, expected one of "vcd" or "fst"') + + # save settings + + self.tool = tool + self.trace = trace + self.trace_type = trace_type + self.fpga = fpga + self.xyce = False # is set True by _configure_xyce + self.warnings = warnings + self.fast = fast + + if (period is None) and (frequency is not None): + period = 1 / frequency + self.period = period + self.max_rate = max_rate + self.start_delay = start_delay + + self.threads = threads + + self.timeunit = timeunit + self.timeprecision = timeprecision + + self.autowrap = autowrap + + if (suffix is None) and subcomponent: + suffix = f'_unq_{design}' + + self.suffix = suffix + + if suffix is not None: + self.dut = f'{design}{suffix}' + else: + self.dut = design + + self.parameters = normalize_parameters(parameters) + self.intf_defs = normalize_interfaces(interfaces) + self.clocks = normalize_clocks(clocks) + self.resets = normalize_resets(resets) + self.tieoffs = normalize_tieoffs(tieoffs) + + # initialization + + self.intfs = {} + + # keep track of processes started + self.process_collection = ProcessCollection() + + # simulator-agnostic settings + + if builddir is None: + if buildroot is None: + buildroot = 'build' + + buildroot = Path(buildroot).resolve() + + if subcomponent: + # the subcomponent build flow is tool-agnostic, producing a single Verilog + # file as output, as opposed to a simulator binary + builddir = buildroot / metadata_str(design=design, parameters=parameters) + else: + builddir = buildroot / metadata_str(design=design, parameters=parameters, + tool=tool, trace=trace, trace_type=trace_type, threads=threads) + + self.set('option', 'builddir', str(Path(builddir).resolve())) + + self.set('option', 'clean', True) # preserve old behavior + + if not subcomponent: + if fpga: + # library dirs + self.set('option', 'ydir', sb_path() / 'verilog' / 'fpga') + self.add('option', 'ydir', sb_path() / 'deps' / 'verilog-axi' / 'rtl') + + # include dirs + self.set('option', 'idir', sb_path() / 'verilog' / 'fpga' / 'include') + + for opt in ['ydir', 'idir']: + if not fpga: + self.set('option', opt, sb_path() / 'verilog' / 'sim') + self.add('option', opt, sb_path() / 'verilog' / 'common') + + if trace: + self.set('tool', 'verilator', 'task', 'compile', 'var', 'trace', True) + self.add('option', 'define', 'SB_TRACE') + + if self.trace_type == 'fst': + self.add('option', 'define', 'SB_TRACE_FST') + + if tool == 'icarus': + self._configure_icarus() + else: + if module is None: + if tool == 'verilator': + module = 'siliconcompiler' + else: + raise ValueError('Must specify the "module" argument,' + ' which is the name of the module containing the' + ' SiliconCompiler driver for this simulator.') + + self._configure_build( + module=module, + default_main=default_main, + fpga=fpga + ) + + if xyce: + self._configure_xyce() + else: + # special mode that produces a standalone Verilog netlist + # rather than building/running a simulation + + flowname = 'package' + + self.package_flow = siliconcompiler.Flow(flowname) + + from siliconcompiler.tools.surelog import parse + self.package_flow.node(flowname, 'parse', parse) + + from .sc.sed import remove + self.package_flow.node(flowname, 'remove', remove) + + from .sc.morty import uniquify + self.package_flow.node(flowname, 'uniquify', uniquify) + + self.package_flow.edge(flowname, 'parse', 'remove') + self.package_flow.edge(flowname, 'remove', 'uniquify') + + self.use(self.package_flow) + self.set('option', 'flow', flowname) + + def _configure_build( + self, + module: str, + default_main: bool = False, + fpga: bool = False + ): + if not fpga: + self.input(SB_DIR / 'dpi' / 'switchboard_dpi.cc') + + if default_main and (self.tool == 'verilator'): + self.input(SB_DIR / 'verilator' / 'testbench.cc') + + if fpga and (self.tool == 'verilator'): + self.set('tool', 'verilator', 'task', 'compile', 'file', 'config', + sb_path() / 'verilator' / 'config.vlt') + self.set('tool', 'verilator', 'task', 'compile', 'warningoff', 'TIMESCALEMOD') + + # enable specific warnings that aren't included by default + if self.tool == 'verilator': + if self.warnings is None: + warnings = ['BLKSEQ'] + else: + warnings = self.warnings + + for warning in warnings: + self.set('tool', 'verilator', 'task', 'compile', 'option', f'-Wwarn-{warning}') + + self.set('tool', self.tool, 'task', 'compile', 'var', 'cflags', + ['-Wno-unknown-warning-option']) + self.set('tool', self.tool, 'task', 'compile', 'dir', 'cincludes', [SB_DIR / 'cpp']) + self.set('tool', self.tool, 'task', 'compile', 'var', 'ldflags', ['-pthread']) + + if self.trace and (self.tool == 'verilator'): + self.set('tool', 'verilator', 'task', 'compile', 'var', 'trace_type', self.trace_type) + + if self.tool == 'verilator': + timeunit = self.timeunit + timeprecision = self.timeprecision + + if (timeunit is not None) or (timeprecision is not None): + if timeunit is None: + timeunit = '1ps' # default from Verilator documentation + + if timeprecision is None: + timeprecision = '1ps' # default from Verilator documentation + + timescale = f'{timeunit}/{timeprecision}' + self.add('tool', 'verilator', 'task', 'compile', 'option', '--timescale') + self.add('tool', 'verilator', 'task', 'compile', 'option', timescale) + + if (self.threads is not None) and (self.tool == 'verilator'): + self.add('tool', 'verilator', 'task', 'compile', 'option', '--threads') + self.add('tool', 'verilator', 'task', 'compile', 'option', str(self.threads)) + + self.set('option', 'libext', ['v', 'sv']) + + # Set up flow that compiles RTL + # TODO: this will be built into SC + self.set('option', 'flow', 'simflow') + + compile = importlib.import_module(f'{module}.tools.{self.tool}.compile') + self.node('simflow', 'compile', compile) + + def _configure_icarus(self): + self.add('option', 'libext', 'sv') + self.set('tool', 'icarus', 'task', 'compile', 'var', 'verilog_generation', '2012') + + # use dvflow to execute Icarus, but set steplist so we don't run sim + from siliconcompiler.flows import dvflow + self.use(dvflow) + + self.set('option', 'flow', 'dvflow') + self.set('option', 'to', 'compile') + + def _configure_xyce(self): + if self.xyce: + # already configured, so return early + return + + self.add('option', 'define', 'SB_XYCE') + + if self.tool != 'icarus': + self.input(SB_DIR / 'dpi' / 'xyce_dpi.cc') + + xyce_c_includes, xyce_ld_flags = xyce_flags() + + self.add('tool', self.tool, 'task', 'compile', 'dir', 'cincludes', xyce_c_includes) + self.add('tool', self.tool, 'task', 'compile', 'var', 'ldflags', xyce_ld_flags) + + # indicate that build is configured for Xyce. for Icarus simulation, this flag is used + # to determine whether a VPI object should be built for Xyce + self.xyce = True + +
+[docs] + def find_sim(self): + if self.tool == 'icarus': + result_kind = 'vvp' + else: + result_kind = 'vexe' + + return self.find_result(result_kind, step='compile')
+ + +
+[docs] + def build(self, cwd: str = None, fast: bool = None): + """ + Parameters + --------- + cwd: str, optional + Working directory for the simulation build + + fast: bool, optional + If True, the simulation binary will not be rebuilt if an existing one + is found. Defaults to the value provided to the SbDut constructor, + which in turn defaults to False. + """ + + if fast is None: + fast = self.fast + + if self.tool == 'icarus': + if (not fast) or (icarus_find_vpi(cwd, name='switchboard') is None): + icarus_build_vpi(cwd, name='switchboard') + if self.xyce and ((not fast) or (icarus_find_vpi(cwd, name='xyce') is None)): + cincludes, ldflags = xyce_flags() + icarus_build_vpi(cwd, name='xyce', cincludes=cincludes, ldflags=ldflags) + + # if "fast" is set, then we can return early if the + # simulation binary already exists + if fast: + sim = self.find_sim() + if sim is not None: + return sim + + # build the wrapper if needed + if self.autowrap: + from .autowrap import autowrap + + filename = Path(self.get('option', 'builddir')).resolve() / 'testbench.sv' + + filename.parent.mkdir(exist_ok=True, parents=True) + + instance = f'{self.dut}_i' + + autowrap( + instances={instance: self.dut}, + parameters={instance: self.parameters}, + interfaces={instance: self.intf_defs}, + clocks={instance: self.clocks}, + resets={instance: self.resets}, + tieoffs={instance: self.tieoffs}, + filename=filename + ) + + self.input(filename) + + # if we get to this point, then we need to rebuild + # the simulation binary + self.run() + + return self.find_sim()
+ + +
+[docs] + def simulate( + self, + plusargs=None, + args=None, + extra_args=None, + cwd: str = None, + trace: bool = None, + period: float = None, + frequency: float = None, + max_rate: float = None, + start_delay: float = None, + run: str = None, + intf_objs: bool = True + ) -> subprocess.Popen: + """ + Parameters + ---------- + plusargs: str or list or tuple, optional + additional arguments to pass to simulator that must be preceded + with a +. These are listed after `args`. + + args: str or list or tuple, optional + additional arguments to pass to simulator listed before `plusargs` and + `extra_args` + + extra_args: str or list or tuple, optional + additional arguments to pass to simulator listed after `args` and + `plusargs` + + cwd: str, optional + working directory where simulation binary is saved + + trace: bool, optional + If true, a waveform dump file will be produced + + period: float, optional + If provided, the period of the clock generated in the testbench, + in seconds. + """ + + # set up interfaces if needed + + if max_rate is None: + max_rate = self.max_rate + + if intf_objs: + self.intfs = create_intf_objs(self.intf_defs, max_rate=max_rate) + + # set defaults + + if plusargs is None: + plusargs = [] + else: + plusargs = deepcopy(plusargs) + + if args is None: + args = [] + + if extra_args is None: + extra_args = [] + + if trace is None: + trace = self.trace + + if (period is None) and (frequency is not None): + period = 1 / frequency + + if period is None: + period = self.period + + if start_delay is None: + start_delay = self.start_delay + + # build the simulation if necessary + + sim = self.build(cwd=cwd, fast=True) + + # enable tracing if desired. it's convenient to define +trace + # when running Icarus Verilog, even though it is not necessary, + # since logic in the testbench can use that flag to enable/disable + # waveform dumping in a simulator-agnostic manner. + + if trace: + carefully_add_plusarg(key='trace', args=args, plusargs=plusargs) + + if period is not None: + carefully_add_plusarg(key='period', value=period, args=args, plusargs=plusargs) + + if max_rate is not None: + carefully_add_plusarg(key='max-rate', value=max_rate, args=args, plusargs=plusargs) + + if start_delay is not None: + carefully_add_plusarg( + key='start-delay', value=start_delay, args=args, plusargs=plusargs) + + # add plusargs that define queue connections + + for name, value in self.intf_defs.items(): + wire = value.get('wire', None) + uri = value.get('uri', None) + + if (wire is not None) and (uri is not None): + plusargs += [(wire, uri)] + + # run-specific configurations (if running the same simulator build multiple times + # in parallel) + + if run is not None: + dumpfile = f'{run}.{self.trace_type}' + plusargs.append(('dumpfile', dumpfile)) + + # run the simulation + + p = None + + if self.tool == 'icarus': + names = ['switchboard'] + modules = [] + + if self.xyce: + names.append('xyce') + + for name in names: + vpi = icarus_find_vpi(cwd=cwd, name=name) + assert vpi is not None, f'Could not find VPI binary "{name}"' + modules.append(vpi) + + # set the trace format + if self.trace_type == 'fst' and ('-fst' not in extra_args): + extra_args.append('-fst') + + p = icarus_run( + sim, + plusargs=plusargs, + modules=modules, + extra_args=args + extra_args + ) + else: + # make sure that the simulator was built with tracing enabled + if trace and not self.trace: + raise ValueError('Simulator was built without tracing enabled.' + ' Please set trace=True in the SbDut and try again.') + + if self.tool == 'verilator': + p = verilator_run( + sim, + plusargs=plusargs, + args=args + ) + else: + p = binary_run( + sim, + args=plusargs_to_args(plusargs) + args + ) + + # Add newly created Popen object to subprocess list + self.process_collection.add(p) + + # return a Popen object that one can wait() on + + return p
+ + +
+[docs] + def terminate( + self, + stop_timeout=10, + use_sigint=False + ): + self.process_collection.terminate(stop_timeout=stop_timeout, use_sigint=use_sigint)
+ + +
+[docs] + def input_analog( + self, + filename: str, + pins: List[Dict[str, Any]] = None, + name: str = None, + check_name: bool = True, + dir: str = None + ): + """ + Specifies a SPICE subcircuit to be used in a mixed-signal simulation. This involves + providing the path to the SPICE file containing the subcircuit definition and describing + how real-valued outputs in the SPICE subcircuit should be converted to binary values in + the Verilog simulation (and vice versa for subcircuit inputs). + + Each of these conversions is specified as an entry in the "pins" argument, which is a + list of dictionaries, each representing a single pin of the SPICE subcircuit. Each + dictionary may have the following keys: + * "name": name of the pin. Bus notation may be used, e.g. "myBus[7:0]". In that case, + it is expected that the SPICE subcircuit has pins corresponding to each bit in the bus, + e.g. "myBus[0]", "myBus[1]", etc. + * "type": direction of the pin. May be "input", "output", or "constant". If "constant", + then this pin will not show up the Verilog module definition to be instantiated in user + code. Instead, the SPICE subcircuit pin with that name will be tied off to a fixed + voltage specified in the "value" field (below). + * "vil": low voltage threshold, below which a real-number voltage from the SPICE + simulation is considered to be a logical "0". + * "vih": high voltage threshold, above which a real-number voltage from the SPICE + simulation is considered to be a logical "1". + * "vol": real-number voltage to pass to a SPICE subcircuit input when the digital value + driven is "0". + * "voh": real-number voltage to pass to a SPICE subcircuit input when the digital value + driven is "1". + * "tr": time taken in the SPICE simulation to transition from a logic "0" value to a + logic "1" value. + * "tf": time taken in the SPICE simulation to transition from a logic "1" value to a + logic "0" value. + * "initial": initial value of a SPICE subcircuit pin. Currently only implemented for + subcircuit outputs. This is sometimes helpful, because there is a slight delay between + t=0 and the time when the SPICE simulation reports values for its outputs. Specifying + "initial" for subcircuit outputs prevents the corresponding digital signals from being + driven to "X" at t=0. + + Parameters + ---------- + filename: str + The path of the SPICE file containing the subcircuit definition. + pins: List[Dict[str, Any]] + List of dictionaries, each describing a pin of the subcircuit. + name: str + Name of the SPICE subcircuit that will be instantiated in the mixed-signal simulation. + If not provided, Switchboard guesses that the name is filename stem. For example, + if filename="myCircuit.cir", then Switchboard will guess that the subcircuit name + is "myCircuit" + check_name: bool + If True (default), Switchboard parses the provided file to make sure that there + is a subcircuit definition matching the given name. + dir: str + Running a mixed-signal simulation involves creating SPICE and Verilog wrappers. This + argument specifies the directory where those wrappers should be written. If not + provided, defaults to the directory where filename is located. + """ + + # automatically configures for Xyce co-simulation if not already configured + + self._configure_xyce() + + # set defaults + + if pins is None: + pins = [] + + if name is None: + # guess the name of the subcircuit from the filename + guessed = True + name = Path(filename).stem + else: + guessed = False + + if check_name: + # make sure that a subcircuit matching the provided or guessed + # name exists in the file provided. this is not foolproof, since + # the SPICE parser is minimal and won't consider things like + # .INCLUDE. hence, this feature can be disabled by setting + # check_name=False + + subckts = parse_spice_subckts(filename) + + for subckt in subckts: + if name.lower() == name.lower(): + break + else: + if guessed: + raise Exception(f'Inferred subckt named "{name}" from the filename,' + ' however a corresponding subckt definition was not found. Please' + ' specify a subckt name via the "name" argument.') + else: + raise Exception(f'Could not find a subckt definition for "{name}".') + + if dir is None: + dir = Path(filename).resolve().parent + + spice_wrapper = make_ams_spice_wrapper( + name=name, + filename=filename, + pins=pins, + dir=dir + ) + + verilog_wrapper = make_ams_verilog_wrapper( + name=name, + filename=spice_wrapper, + pins=pins, + dir=dir + ) + + self.input(verilog_wrapper)
+ + +
+[docs] + def package(self, suffix=None, fast=None): + # set defaults + + if suffix is None: + suffix = self.suffix + + if fast is None: + fast = self.fast + + # see if we can exit early + + if fast: + package = self.find_package(suffix=suffix) + + if package is not None: + return package + + # if not, parse with surelog and postprocess with morty + + if suffix: + self.set('tool', 'morty', 'task', 'uniquify', 'var', 'suffix', suffix) + + self.set('tool', 'sed', 'task', 'remove', 'var', 'to_remove', '`resetall') + + self.run() + + # return the path to the output + return self.find_package(suffix=suffix)
+ + +
+[docs] + def find_package(self, suffix=None): + if suffix is None: + return self.find_result('v', step='parse') + else: + return self.find_result('v', step='uniquify')
+
+ + + +
+[docs] +def metadata_str(design: str, tool: str = None, trace: bool = False, + trace_type: str = None, threads: int = None, parameters: dict = None) -> Path: + + opts = [] + + opts += [design] + + if parameters is not None: + for k, v in parameters.items(): + opts += [k, v] + + if tool is not None: + opts += [tool] + + if trace: + assert trace_type is not None + opts += [trace_type] + + if threads is not None: + opts += ['threads', threads] + + return '-'.join(str(opt) for opt in opts)
+ + + +
+[docs] +def carefully_add_plusarg(key, args, plusargs, value=None): + for plusarg in plusargs: + if isinstance(plusarg, (list, tuple)): + if (len(plusarg) >= 1) and (key == plusarg[0]): + return + elif key == plusarg: + return + + if f'+{key}' in args: + return + + if any(elem.startswith(f'+{key}+') for elem in args): + return + + if any(elem.startswith(f'+{key}=') for elem in args): + return + + if value is None: + plusargs.append(key) + else: + plusargs.append((key, value))
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/switchboard/sbtcp.html b/_modules/switchboard/sbtcp.html new file mode 100644 index 00000000..63daa210 --- /dev/null +++ b/_modules/switchboard/sbtcp.html @@ -0,0 +1,493 @@ + + + + + + switchboard.sbtcp — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for switchboard.sbtcp

+#!/usr/bin/env python3
+
+# Command-line tool that bridges Switchboard packets over TCP.
+
+# Copyright (c) 2024 Zero ASIC Corporation
+# This code is licensed under Apache License 2.0 (see LICENSE for details)
+
+# reference for setting up Python TCP connections:
+# https://realpython.com/python-sockets/#echo-client-and-server
+
+# reference for non-blocking socket programming:
+# https://stackoverflow.com/a/16745561
+
+import time
+import socket
+import argparse
+import numpy as np
+
+from switchboard import PySbRx, PySbTx, PySbPacket
+
+SB_PACKET_SIZE_BYTES = 60
+
+
+
+[docs] +def tcp2sb(outputs, conn): + while True: + # receive data from TCP + data_rx_from_tcp = bytes([]) + + while len(data_rx_from_tcp) < SB_PACKET_SIZE_BYTES: + b = conn.recv(SB_PACKET_SIZE_BYTES - len(data_rx_from_tcp)) + + if len(b) == 0: + # connection is not alive anymore + return + + data_rx_from_tcp += b + + # convert to a switchboard packet + p = bytes2sb(data_rx_from_tcp) + + # figure out which queue this packet is going to + for rule, output in outputs: + if rule_matches(rule, p.destination): + output.send(p) + break + else: + raise Exception(f"No rule for destination {p.destination}")
+ + + +
+[docs] +def sb2tcp(inputs, conn): + tcp_data_to_send = bytes([]) + + while True: + # get a switchboard packet + while True: + # select input and queue its next run as last + destination, sbrx = inputs.pop(0) + inputs.append((destination, sbrx)) + + # try to receive a packet from this input + p = sbrx.recv(blocking=False) + + if p is not None: + if destination is not None: + p.destination = destination + break + + # convert the switchboard packet to bytes + tcp_data_to_send = sb2bytes(p) + + # send the packet out over TCP + while len(tcp_data_to_send) > 0: + n = conn.send(tcp_data_to_send) + + if n == 0: + # connection is not alive anymore + return + + tcp_data_to_send = tcp_data_to_send[n:]
+ + + +
+[docs] +def run_client(host, port, quiet=False, max_rate=None, inputs=None, outputs=None, run_once=False): + """ + Connect to a server, retrying until a connection is made. + """ + + # initialize PySbRx/PySbTx objects if needed + + inputs, outputs = normalize_inputs_and_outputs( + inputs=inputs, outputs=outputs, max_rate=max_rate) + + # connect to the server in a loop + while True: + if not quiet: + print(f'Waiting for server (host={host}, port={port})') + while True: + try: + conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + conn.connect((host, port)) + break + except ConnectionRefusedError: + time.sleep(1) + if not quiet: + print(f'Connected to server (host={host}, port={port})') + + # communicate with the server + if outputs is not None: + tcp2sb(outputs=outputs, conn=conn) + elif inputs is not None: + sb2tcp(inputs=inputs, conn=conn) + + if run_once: + break
+ + + +
+[docs] +def run_server(host, port=0, quiet=False, max_rate=None, run_once=False, outputs=None, inputs=None): + """ + Accepts client connections in a loop until Ctrl-C is pressed. + """ + + # initialize PySbRx/PySbTx objects if needed + + inputs, outputs = normalize_inputs_and_outputs( + inputs=inputs, outputs=outputs, max_rate=max_rate) + + # create the server socket + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.setsockopt(socket.SOL_SOCKET, + socket.SO_REUSEADDR, 1) # allow port to be reused immediately + server_socket.bind((host, port)) + server_socket.listen() + + # accept client connections in a loop + while True: + # accept a client + if not quiet: + print(f'Waiting for client (host={host}, port={port})') + conn, _ = server_socket.accept() + if not quiet: + print(f'Connected to client (host={host}, port={port})') + + # communicate with the client + if outputs is not None: + tcp2sb(outputs=outputs, conn=conn) + elif inputs is not None: + sb2tcp(inputs=inputs, conn=conn) + + if run_once: + break
+ + + +
+[docs] +def normalize_inputs_and_outputs(inputs, outputs, max_rate): + if outputs is not None: + assert inputs is None, 'Cannot specify both inputs and outputs' + outputs = normalize_outputs(outputs, max_rate) + else: + assert inputs is not None, 'Must specify either inputs or outputs' + inputs = normalize_inputs(inputs, max_rate) + + return inputs, outputs
+ + + +
+[docs] +def normalize_outputs(outputs, max_rate): + retval = [] + + for rule, output in outputs: + output = convert_to_queue(q=output, cls=PySbTx, max_rate=max_rate) + retval.append((rule, output)) + + return retval
+ + + +
+[docs] +def normalize_inputs(inputs, max_rate): + retval = [] + + for input in inputs: + if not isinstance(input, (list, tuple)): + destination, input = None, input + else: + destination, input = input + + input = convert_to_queue(q=input, cls=PySbRx, max_rate=max_rate) + + retval.append((destination, input)) + + return retval
+ + + +
+[docs] +def sb2bytes(p): + # construct a bytes object from a Switchboard packet + arr = np.concatenate(( + np.array([p.destination, p.flags], dtype=np.uint32), + p.data.view(np.uint32) + )) + return arr.tobytes()
+ + + +
+[docs] +def bytes2sb(b): + # construct a Switchboard packet from a bytes object + arr = np.frombuffer(b, dtype=np.uint32) + return PySbPacket(arr[0], arr[1], arr[2:].view(np.uint8))
+ + + +
+[docs] +def convert_to_queue(q, cls, max_rate=None): + if isinstance(q, cls): + # note that None is passed through + return q + elif isinstance(q, str): + kwargs = {} + + if max_rate is not None: + kwargs['max_rate'] = max_rate + + return cls(q, **kwargs) + else: + raise TypeError(f'{q} must be a string or {cls.__name__}; got {type(q)}')
+ + + +
+[docs] +def rule_matches(rule, addr): + if rule == '*': + return True + elif isinstance(rule, int): + return addr == rule + elif isinstance(rule, range): + return rule.start <= addr < rule.stop + elif isinstance(rule, (list, tuple)): + # return True if any subrules match + for subrule in rule: + if rule_matches(subrule, addr): + return True + + # otherwise return False + return False + else: + raise Exception(f'Unsupported rule type: {type(rule)}')
+ + + +
+[docs] +def parse_rule(rule): + subrules = rule.split(',') + + retval = [] + + for subrule in subrules: + if subrule == '*': + retval.append('*') + elif '-' in subrule: + start, stop = subrule.split('-') + start = int(start) + stop = int(stop) + retval.append(range(start, stop + 1)) + else: + retval.append(int(subrule)) + + return retval
+ + + +
+[docs] +def start_tcp_bridge(inputs=None, outputs=None, host='localhost', port=5555, + quiet=True, max_rate=None, mode='auto', run_once=False): + + kwargs = dict( + host=host, + port=port, + quiet=quiet, + max_rate=max_rate, + run_once=run_once + ) + + target = None + + if mode == 'client': + target = run_client + elif mode == 'server': + target = run_server + + if outputs is not None: + kwargs['outputs'] = outputs + if mode == 'auto': + target = run_server + elif inputs is not None: + kwargs['inputs'] = inputs + if mode == 'auto': + target = run_client + else: + raise Exception('Must specify "outputs" or "inputs" argument.') + + assert target is not None, 'Could not determine whether to run the bridge as a client or server' + + import multiprocessing + + p = multiprocessing.Process(target=target, kwargs=kwargs, daemon=True) + p.start() + + return p
+ + + +
+[docs] +def get_parser(): + parser = argparse.ArgumentParser() + + parser.add_argument('--outputs', type=str, default=None, nargs='+', help="Space-separated" + " dictionary of queues to write to. For example, 0:a.q 1-2:b.q 3,5-7:c.q *:d.q means" + " that packets sent to destination 0 are routed to a.q, packets sent to destinations 1" + " or 2 are routed to b.q, packets sent to destinations 3, 5, 6, or 7 are routed to c.q," + " and all other packets are routed to d.q") + parser.add_argument('--inputs', type=str, default=None, nargs='+', help="Space-separated" + " list of queues to read from, for example a.q b.q c.q") + parser.add_argument('--port', type=int, default=5555, help="TCP port used for" + " sending and receiving packets.") + parser.add_argument('--host', type=str, default="localhost", help="IP address or hostname" + " used sending/receiving packets.") + parser.add_argument('-q', action='store_true', help="Quiet mode: doesn't print anything.") + parser.add_argument('--max-rate', type=float, default=None, help='Maximum rate at which' + ' queues are read or written.') + parser.add_argument('--run-once', action='store_true', help="Process only one connection" + " in server mode, then exit.") + + return parser
+ + + +
+[docs] +def main(): + # parse command-line arguments + + parser = get_parser() + args = parser.parse_args() + + # main logic + + if args.outputs is not None: + # parse the output mapping + outputs = [] + for output in args.outputs: + rule, output = output.split(':') + outputs.append((parse_rule(rule), output)) + + run_server(outputs=outputs, host=args.host, port=args.port, + quiet=args.q, max_rate=args.max_rate, run_once=args.run_once) + elif args.inputs is not None: + run_client(inputs=args.inputs, host=args.host, port=args.port, + quiet=args.q, max_rate=args.max_rate) + else: + raise ValueError("Must specify either --inputs or --outputs")
+ + + +if __name__ == "__main__": + main() +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/switchboard/uart_xactor.html b/_modules/switchboard/uart_xactor.html new file mode 100644 index 00000000..df6e2cf5 --- /dev/null +++ b/_modules/switchboard/uart_xactor.html @@ -0,0 +1,187 @@ + + + + + + switchboard.uart_xactor — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for switchboard.uart_xactor

+#!/usr/bin/env python3
+
+# Copyright (c) 2024 Zero ASIC Corporation
+# This code is licensed under Apache License 2.0 (see LICENSE for details)
+
+"""
+UMI/UART Transactor.
+"""
+
+import numpy as np
+
+
+
+[docs] +class uart_xactor: + REG_TX = 0 + REG_RX = 4 + REG_SR = 8 + + REGF_SR_RXEMPTY_MASK = 1 << 0 + REGF_SR_RXFULL_MASK = 1 << 1 + REGF_SR_TXEMPTY_MASK = 1 << 8 + REGF_SR_TXFULL_MASK = 1 << 9 + + def __init__(self, umi, encoding='ascii'): + self.encoding = encoding + self.umi = umi + +
+[docs] + def read_byte(self): + c8 = None + while True: + sr = self.umi.read(self.REG_SR, np.uint32) + if (sr & self.REGF_SR_RXEMPTY_MASK) == 0: + rx = self.umi.read(self.REG_RX, np.uint32) + c8 = rx & 0xff + break + return bytes([c8])
+ + +
+[docs] + def readline(self, size=-1, end='\n'): + line = "" + + while size < 0 or len(line) < size: + c8 = self.read_byte() + if c8 == end.encode(self.encoding): + break + line += c8.decode(self.encoding) + return line
+ + +
+[docs] + def write_byte(self, b): + while True: + sr = self.umi.read(self.REG_SR, np.uint32) + if (sr & self.REGF_SR_TXFULL_MASK) == 0: + self.umi.write(self.REG_TX, np.uint32(b)) + break
+ + + # File-like ops +
+[docs] + def write(self, string): + for b in string: + self.write_byte(b)
+ + + # On streaming UART, reading until EOF doesn't make sense + # So we default the size arg to 1 +
+[docs] + def read(self, size=1): + data = bytes(0) + while size < 0 or len(data) < size: + b = self.read_byte() + data += b + return data
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/switchboard/umi.html b/_modules/switchboard/umi.html new file mode 100644 index 00000000..7e935eb8 --- /dev/null +++ b/_modules/switchboard/umi.html @@ -0,0 +1,944 @@ + + + + + + switchboard.umi — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for switchboard.umi

+# Python interface for UMI reads, writes, and atomic operations
+
+# Copyright (c) 2024 Zero ASIC Corporation
+# This code is licensed under Apache License 2.0 (see LICENSE for details)
+
+import random
+import numpy as np
+
+from numbers import Integral
+from typing import Iterable, Union, Dict
+
+from _switchboard import (PyUmi, PyUmiPacket, umi_pack, UmiCmd, UmiAtomic)
+from .gpio import UmiGpio
+
+# note: it was convenient to implement some of this in Python, rather
+# than have everything in C++, because it was easier to provide
+# flexibility with numpy types
+
+
+
+[docs] +class UmiTxRx: + def __init__(self, tx_uri: str = None, rx_uri: str = None, + srcaddr: Union[int, Dict[str, int]] = 0, posted: bool = False, + max_bytes: int = None, fresh: bool = False, error: bool = True, + max_rate: float = -1): + """ + Parameters + ---------- + tx_uri: str, optional + Name of the switchboard queue that + write() and send() will send UMI packets to. Defaults to + None, meaning "unused". + rx_uri: str, optional + Name of the switchboard queue that + read() and recv() will receive UMI packets from. Defaults + to None, meaning "unused". + srcaddr: int, optional + Default srcaddr to use for reads, + ack'd writes, and atomics. Defaults to 0. Can also be + provided as a dictionary with separate defaults for each + type of transaction: srcaddr={'read': 0x1234, 'write': + 0x2345, 'atomic': 0x3456}. When the defaults are provided + with a dictionary, all keys are optional. Transactions + that are not specified in the dictionary will default + to a srcaddr of 0. + posted: bool, optional + If True, default to using posted + (i.e., non-ack'd) writes. This can be overridden on a + transaction-by-transaction basis. Defaults to False. + max_bytes: int, optional + Default maximum number of bytes + to use in each UMI transaction. Can be overridden on a + transaction-by-transaction basis. Defaults to 32 bytes. + fresh: bool, optional + If True, the queue specified by the uri parameter will get + cleared before executing the simulation. + error: bool, optional + If True, error out upon receiving an unexpected UMI response. + """ + + if tx_uri is None: + tx_uri = "" + + if rx_uri is None: + rx_uri = "" + + self.umi = PyUmi(tx_uri, rx_uri, fresh, max_rate=max_rate) + + if srcaddr is not None: + # convert srcaddr default to a dictionary if necessary + if isinstance(srcaddr, int): + srcaddr = { + 'read': srcaddr, + 'write': srcaddr, + 'atomic': srcaddr + } + + if isinstance(srcaddr, dict): + self.def_read_srcaddr = int(srcaddr.get('read', 0)) + self.def_write_srcaddr = int(srcaddr.get('write', 0)) + self.def_atomic_srcaddr = int(srcaddr.get('atomic', 0)) + else: + raise ValueError(f'Unsupported default srcaddr specification: {srcaddr}') + else: + raise ValueError('Default value of "srcaddr" cannot be None.') + + if posted is not None: + self.default_posted = bool(posted) + else: + raise ValueError('Default value of "posted" cannot be None.') + + if max_bytes is None: + max_bytes = 32 + + self.default_max_bytes = max_bytes + self.default_error = error + +
+[docs] + def gpio( + self, + iwidth: int = 32, + owidth: int = 32, + init: int = 0, + dstaddr: int = 0, + srcaddr: int = 0, + posted: bool = False, + max_bytes: int = 32 + ) -> UmiGpio: + """ + Returns an object for communicating with umi_gpio modules. + + Parameters + ---------- + iwidth: int + Width of GPIO input (bits). Defaults to 32. + owidth: int + Width of GPIO output (bits). Defaults to 32. + init: int + Default value of GPIO output. Defaults to 0. + dstaddr: int + Base address of the GPIO device. Defaults to 0. + srcaddr: int + Source address to which responses should be routed. Defaults to 0. + posted: bool + Whether writes should be sent as posted. Defaults to False. + max_bytes: int + Maximum number of bytes in a single transaction to umi_gpio. + + Returns + ------- + UmiGpio + UmiGpio object with .i (input) and .o (output) attributes + """ + + return UmiGpio( + iwidth=iwidth, + owidth=owidth, + init=init, + dstaddr=dstaddr, + srcaddr=srcaddr, + posted=posted, + max_bytes=max_bytes, + umi=self + )
+ + +
+[docs] + def init_queues(self, tx_uri: str = None, rx_uri: str = None, fresh: bool = False): + """ + Parameters + ---------- + tx_uri: str, optional + Name of the switchboard queue that + write() and send() will send UMI packets to. Defaults to + None, meaning "unused". + rx_uri: str, optional + Name of the switchboard queue that + read() and recv() will receive UMI packets from. Defaults + to None, meaning "unused". + fresh: bool, optional + If True, the queue specified by the uri parameter will get + cleared before executing the simulation. + """ + + if tx_uri is None: + tx_uri = "" + + if rx_uri is None: + rx_uri = "" + + self.umi.init(tx_uri, rx_uri, fresh)
+ + +
+[docs] + def send(self, p, blocking=True) -> bool: + """ + Sends (or tries to send if burst=False) a UMI transaction (PyUmiPacket) + Returns True if the packet was sent successfully, else False. + + Parameters + ---------- + p: PyUmiPacket + The UMI packet that will be sent + blocking: bool, optional + If True, the program will pause execution until a response to the write request + is received. + + Returns + ------- + bool + Returns true if the `p` was sent successfully + """ + + return self.umi.send(p, blocking)
+ + +
+[docs] + def recv(self, blocking=True) -> PyUmiPacket: + """ + Wait for and return a UMI packet if blocking=True, otherwise return a + UMI packet if one can be read immediately, and None otherwise. + + Parameters + ---------- + blocking: bool, optional + If True, the function will wait until a UMI packet can be read. + If False, a None type will be returned if no UMI packet can be read + immediately. + + Returns + ------- + PyUmiPacket + If `blocking` is True, a PyUmiPacket is always returned. If `blocking` is + False, a PyUmiPacket object will be returned if one can be read immediately. + Otherwise, a None type will be returned. + """ + + return self.umi.recv(blocking)
+ + +
+[docs] + def write(self, addr, data, srcaddr=None, max_bytes=None, + posted=None, qos=0, prot=0, progressbar=False, check_alignment=True, + error=None): + """ + Writes the provided data to the given 64-bit address. + + Parameters + ---------- + addr: int + 64-bit address that will be written to + + data: np.uint8, np.uint16, np.uint32, np.uint64, or np.array + Can be either a numpy integer type (e.g., np.uint32) or an numpy + array of integer types (np.uint8, np.uin16, np.uint32, np.uint64, etc.). + The `data` input may contain more than "max_bytes", in which case + the write will automatically be split into multiple transactions. + + srcaddr: int, optional + UMI source address used for the write transaction. This is sometimes needed to make + the write response gets routed to the right place. + + max_bytes: int, optional + Indicates the maximum number of bytes that can be used for any individual UMI + transaction. If not specified, this defaults to the value of `max_bytes` + provided in the UmiTxRx constructor, which in turn defaults to 32. + + posted: bool, optional + If True, a write response will be received. + + qos: int, optional + 4-bit Quality of Service field in UMI Command + + prot: int, optional + 2-bit protection mode field in UMI command + + progressbar: bool, optional + If True, the number of packets written will be displayed via a progressbar + in the terminal. + + check_alignment: bool, optional + If true, an exception will be raised if the `addr` parameter cannot be aligned based + on the size of the `data` parameter + + error: bool, optional + If True, error out upon receiving an unexpected UMI response. + """ + + # set defaults + + if max_bytes is None: + max_bytes = self.default_max_bytes + + max_bytes = int(max_bytes) + + if srcaddr is None: + srcaddr = self.def_write_srcaddr + + srcaddr = int(srcaddr) + + if posted is None: + posted = self.default_posted + + posted = bool(posted) + + if error is None: + error = self.default_error + + error = bool(error) + + # format the data to be written + + if isinstance(data, np.ndarray): + if data.ndim == 0: + write_data = np.atleast_1d(data) + elif data.ndim == 1: + write_data = data + else: + raise ValueError(f'Can only write 1D arrays (got ndim={data.ndim})') + + if not np.issubdtype(write_data.dtype, np.integer): + raise ValueError('Can only write integer dtypes such as uint8, uint16, etc.' + f' (got dtype "{data.dtype}")') + elif isinstance(data, np.integer): + write_data = np.array(data, ndmin=1) + else: + raise TypeError(f"Unknown data type: {type(data)}") + + if check_alignment: + size = dtype2size(write_data.dtype) + if not addr_aligned(addr=addr, align=size): + raise ValueError(f'addr=0x{addr:x} misaligned for size={size}') + + # perform write + self.umi.write(addr, write_data, srcaddr, max_bytes, + posted, qos, prot, progressbar, error)
+ + +
+[docs] + def write_readback(self, addr, value, mask=None, srcaddr=None, dtype=None, + posted=True, write_srcaddr=None, check_alignment=True, error=None): + """ + Writes the provided value to the given 64-bit address, and blocks + until that value is read back from the provided address. + + Parameters + ---------- + addr: int + The destination address to write to and read from + + value: int, np.uint8, np.uint16, np.uint32, or np.uint64 + The data written to `addr` + + mask: int, optional + argument (optional) allows the user to mask off some bits + in the comparison of the data written vs. data read back. For example, + if a user only cares that bit "5" is written to "1", and does not care + about the value of other bits read back, they could use mask=1<<5. + + srcaddr: int, optional + The UMI source address used for the read transaction. This is + sometimes needed to make sure that reads get routed to the right place. + + dtype: np.uint8, np.uint16, np.uint32, or np.uint64, optional + If `value` is specified as plain integer, then dtype must be specified, + indicating a particular numpy integer type. This is so that the size of + the UMI transaction can be set appropriately. + + posted: bool, optional + By default, the write is performed as a posted write, however it is + is possible to use an ack'd write by setting posted=False. + + write_srcaddr: int, optional + If `posted`=True, write_srcaddr specifies the srcaddr used for that + transaction. If write_srcaddr is None, the default srcaddr for writes + will be used. + + check_alignment: bool, optional + If true, an exception will be raised if the `addr` parameter cannot be aligned based + on the size of the `data` parameter + + error: bool, optional + If True, error out upon receiving an unexpected UMI response. + + Raises + ------ + TypeError + If `value` is not an integer type, if `mask` is not an integer type + """ + + # set defaults + + if srcaddr is None: + srcaddr = self.def_read_srcaddr + + srcaddr = int(srcaddr) + + if write_srcaddr is None: + write_srcaddr = self.def_write_srcaddr + + write_srcaddr = int(write_srcaddr) + + # convert value to a numpy datatype if it is not already + if not isinstance(value, np.integer): + if dtype is not None: + value = dtype(value) + else: + raise TypeError("Must provide value as a numpy integer type, or specify dtype.") + + # set the mask to all ones if it is None + if mask is None: + nbits = (np.dtype(value.dtype).itemsize * 8) + mask = (1 << nbits) - 1 + + # convert mask to a numpy datatype if it is not already + if not isinstance(mask, np.integer): + if dtype is not None: + mask = dtype(mask) + else: + raise TypeError("Must provide mask as a numpy integer type, or specify dtype.") + + # write, then read repeatedly until the value written is observed + self.write(addr, value, srcaddr=write_srcaddr, posted=posted, + check_alignment=check_alignment, error=error) + rdval = self.read(addr, value.dtype, srcaddr=srcaddr, + check_alignment=check_alignment, error=error) + while ((rdval & mask) != (value & mask)): + rdval = self.read(addr, value.dtype, srcaddr=srcaddr, + check_alignment=check_alignment, error=error)
+ + +
+[docs] + def read(self, addr, num_or_dtype, dtype=np.uint8, srcaddr=None, + max_bytes=None, qos=0, prot=0, check_alignment=True, error=None): + """ + Parameters + ---------- + addr: int + The 64-bit address read from + + num_or_dtype: int or numpy integer datatype + If a plain int, `num_or_datatype` specifies the number of bytes to be read. + If a numpy integer datatype (np.uint8, np.uint16, etc.), num_or_datatype + specifies the data type to be returned. + + dtype: numpy integer datatype, optional + If num_or_dtype is a plain integer, the value returned by this function + will be a numpy array of type "dtype". On the other hand, if num_or_dtype + is a numpy datatype, the value returned will be a scalar of that datatype. + + srcaddr: int, optional + The UMI source address used for the read transaction. This + is sometimes needed to make sure that reads get routed to the right place. + + max_bytes: int, optional + Indicates the maximum number of bytes that can be used for any individual UMI + transaction. If not specified, this defaults to the value of `max_bytes` + provided in the UmiTxRx constructor, which in turn defaults to 32. + + qos: int, optional + 4-bit Quality of Service field used in the UMI command + + prot: int, optional + 2-bit Protection mode field used in the UMI command + + error: bool, optional + If True, error out upon receiving an unexpected UMI response. + + Returns + ------- + numpy integer array + An array of `num_or_dtype` bytes read from `addr`. The array will have the type + specified by `dtype` or `num_or_dtype` + """ + + # set defaults + + if max_bytes is None: + max_bytes = self.default_max_bytes + + max_bytes = int(max_bytes) + + if srcaddr is None: + srcaddr = self.def_read_srcaddr + + srcaddr = int(srcaddr) + + if error is None: + error = self.default_error + + error = bool(error) + + if isinstance(num_or_dtype, (type, np.dtype)): + num = 1 + bytes_per_elem = np.dtype(num_or_dtype).itemsize + else: + num = num_or_dtype + bytes_per_elem = np.dtype(dtype).itemsize + + if check_alignment: + size = nbytes2size(bytes_per_elem) + if not addr_aligned(addr=addr, align=size): + raise ValueError(f'addr=0x{addr:x} misaligned for size={size}') + + result = self.umi.read(addr, num, bytes_per_elem, srcaddr, max_bytes, + qos, prot, error) + + if isinstance(num_or_dtype, (type, np.dtype)): + return result.view(num_or_dtype)[0] + else: + return result
+ + +
+[docs] + def atomic(self, addr, data, opcode, srcaddr=None, qos=0, prot=0, error=None): + """ + Parameters + ---------- + addr: int + 64-bit address atomic operation will be applied to. + + data: np.uint8, np.uint16, np.uint32, np.uint64 + must so that the size of the atomic operation can be determined. + + opcode: str or switchboard.UmiAtomic value + Supported string values are 'add', 'and', 'or', 'xor', 'max', 'min', + 'minu', 'maxu', and 'swap' (case-insensitive). + + srcaddr: int, optional + The UMI source address used for the atomic transaction. This + is sometimes needed to make sure the response get routed to the right place. + + qos: int, optional + 4-bit Quality of Service field used in the UMI command + + prot: int, optional + 2-bit Protection mode field used in the UMI command + + error: bool, optional + If True, error out upon receiving an unexpected UMI response. + + Raises + ------ + TypeError + If `value` is not a numpy integer datatype + + Returns + ------- + np.uint8, np.uint16, np.uint32, np.uint64 + The value returned by this function is the original value at addr, + immediately before the atomic operation is applied. The numpy dtype of the + returned value will be the same as for "data". + """ + + # set defaults + + if srcaddr is None: + srcaddr = self.def_atomic_srcaddr + + srcaddr = int(srcaddr) + + if error is None: + error = self.default_error + + error = bool(error) + + # resolve the opcode to an enum if needed + if isinstance(opcode, str): + opcode = getattr(UmiAtomic, f'UMI_REQ_ATOMIC{opcode.upper()}') + + # format the data for sending + if isinstance(data, np.integer): + atomic_data = np.array(data, ndmin=1).view(np.uint8) + result = self.umi.atomic(addr, atomic_data, opcode, srcaddr, qos, prot, error) + return result.view(data.dtype)[0] + else: + raise TypeError("The data provided to atomic should be of a numpy integer type" + " so that the transaction size can be determined")
+
+ + + +
+[docs] +def size2dtype(size: int, signed: bool = False, float: bool = False): + if float: + dtypes = [None, np.float16, np.float32, np.float64, np.float128] + elif signed: + dtypes = [np.int8, np.int16, np.int32, np.int64] + else: + dtypes = [np.uint8, np.uint16, np.uint32, np.uint64] + + dtype = None + + if size < len(dtypes): + dtype = dtypes[size] + + if dtype is None: + raise ValueError(f'Size {size} unsupported with signed={signed} and float={float}') + + return dtype
+ + + +
+[docs] +def nbytes2size(nbytes: Integral): + if not isinstance(nbytes, Integral): + raise ValueError(f'Number of bytes must be an integer (got {nbytes})') + elif nbytes <= 0: + raise ValueError(f'Number of bytes must be positive (got {nbytes})') + + nbytes = int(nbytes) + + if bin(nbytes).count('1') != 1: + raise ValueError(f'Number of bytes must be a power of two (got {nbytes})') + + size = nbytes.bit_length() - 1 + + if size < 0: + raise ValueError(f'size cannot be negative (got {size})') + + return size
+ + + +
+[docs] +def dtype2size(dtype: np.dtype): + if isinstance(dtype, np.dtype): + return nbytes2size(dtype.itemsize) + else: + raise ValueError(f'dtype must be of type np.dtype (got {type(dtype)})')
+ + + +
+[docs] +def addr_aligned(addr: Integral, align: Integral) -> bool: + return ((addr >> align) << align) == addr
+ + + +
+[docs] +def random_int_value(name, value, min, max, align=None): + # determine the length of the transaction + + if isinstance(value, range) or (value is None): + if isinstance(value, range): + a = value.start + b = value.stop - 1 + else: + a = min + b = max + + value = random.randint(a, b) + + if align is not None: + value >>= align + value <<= align + elif isinstance(value, (list, tuple, np.ndarray)): + value = random.choice(value) + + if isinstance(value, (range, list, tuple)): + # if we happen to pick a range object from the list/tuple, then run this + # function on the range object. this allows users to specify a collection + # of values and ranges to efficiently represent a discontinuous space + # of options. it is also possible to have lists of lists of ranges, to + # adjust the probabilities of drawing from each range + return random_int_value(name=name, value=value, min=min, max=max, align=align) + + # validate result + + check_int_in_range(name, value, min=min, max=max) + + value = int(value) + + if align is not None: + if not addr_aligned(addr=value, align=align): + raise ValueError(f'misaligned {name}: 0x{value:x}') + + # return result + + return value
+ + + +
+[docs] +def check_int_in_range(name, value, min=None, max=None): + if not np.issubdtype(type(value), np.integer): + raise ValueError(f'{name} is not an integer') + + if (min is not None) and (value < min): + raise ValueError(f'{name} is less than {min}') + + if (max is not None) and (value > max): + raise ValueError(f'{name} is greater than {max}')
+ + + +
+[docs] +def random_umi_packet( + opcode=None, + len=None, + size=None, + dstaddr=None, + srcaddr=None, + data=None, + qos=0, + prot=0, + ex=0, + atype=0, + eom=1, + eof=1, + max_bytes=32 +): + """ + Generates a Random UMI packet. All parameters are optional. Parameters that + are not explicitly specified will be assigned randomly. + + For more information on the meanings of each parameter, reference + `the UMI specification <https://github.com/zeroasiccorp/umi/blob/main/README.md>`_ + + Parameters + ---------- + opcode: int, optional + Command opcode + + len: int, optional + Word transfers per message. (`len`-1 words will be transferred + per message) + + size: int, optional + Word size ((2^size)-1 bits per word) + + dstaddr: int, optional + 64-bit destination address used in the UMI packet + + srcaddr: int, optional + 64-bit source address used in the UMI packet + + data: numpy integer array, optional + Values used in the Data field for the UMI packet + + qos: int, optional + 4-bit Quality of Service field used in the UMI command + + prot: int, optional + 2-bit Protection mode field used in the UMI command + + ex: int, optional + 1-bit Exclusive access indicator in the UMI command + + atype: int, optional + 8-bit field specifying the type of atomic transaction used + in the UMI command for an atomic operation + + eom: int, optional + 1-bit End of Message indicator in UMI command, used to track + the transfer of the last word in a message + + eof: int, optional + 1-bit End of Frame bit in UMI command, used to indicate the + last message in a sequence of related UMI transactions + + max_bytes: int, optional + The maximum number of bytes included in each UMI packet + + Returns + ------- + """ + + # input validation + + check_int_in_range("max_bytes", max_bytes, min=0, max=32) + + # TODO: make these parameters flexible, or more centrally-defined + + MAX_SUMI_SIZE = 3 + AW = 64 + + # determine the opcode + + if opcode is None: + opcode = random.choice([ + UmiCmd.UMI_REQ_WRITE, + UmiCmd.UMI_REQ_POSTED, + UmiCmd.UMI_REQ_READ, + UmiCmd.UMI_RESP_WRITE, + UmiCmd.UMI_RESP_READ, + UmiCmd.UMI_REQ_ATOMIC + ]) + elif isinstance(opcode, Iterable): + opcode = random.choice(opcode) + + # determine the size of the transaction + + if (size is None) and (data is not None): + size = dtype2size(data.dtype) + + size = random_int_value('size', size, 0, MAX_SUMI_SIZE) + + # determine the length of the transaction + + if (len is None) and (data is not None): + len = data.size - 1 + + len = random_int_value('len', len, 0, (max_bytes >> size) - 1) + + # generate other fields + + atype = random_int_value('atype', atype, 0x00, 0x08) + qos = random_int_value('qos', qos, 0b0000, 0b1111) + prot = random_int_value('prot', prot, 0b00, 0b11) + eom = random_int_value('eom', eom, 0b0, 0b1) + eof = random_int_value('eof', eof, 0b0, 0b1) + ex = random_int_value('ex', ex, 0b0, 0b1) + + # construct the command field + + cmd = umi_pack(opcode, atype, size, len, eom, eof, qos, prot, ex) + + # generate destination address + + dstaddr = random_int_value('dstaddr', dstaddr, 0, (1 << AW) - 1, align=size) + srcaddr = random_int_value('srcaddr', srcaddr, 0, (1 << AW) - 1, align=size) + + # generate data if needed + + if opcode in [ + UmiCmd.UMI_REQ_WRITE, + UmiCmd.UMI_REQ_POSTED, + UmiCmd.UMI_RESP_READ, + UmiCmd.UMI_REQ_ATOMIC + ]: + if data is None: + dtype = size2dtype(size) + iinfo = np.iinfo(dtype) + if opcode != UmiCmd.UMI_REQ_ATOMIC: + nelem = len + 1 + else: + nelem = 1 + data = np.random.randint(iinfo.min, iinfo.max - 1, + size=nelem, dtype=dtype) + + # return the packet + + return PyUmiPacket(cmd=cmd, dstaddr=dstaddr, srcaddr=srcaddr, data=data)
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/switchboard/util.html b/_modules/switchboard/util.html new file mode 100644 index 00000000..31138b34 --- /dev/null +++ b/_modules/switchboard/util.html @@ -0,0 +1,252 @@ + + + + + + switchboard.util — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for switchboard.util

+# General utilities for working with switchboard
+
+# Copyright (c) 2024 Zero ASIC Corporation
+# This code is licensed under Apache License 2.0 (see LICENSE for details)
+
+import atexit
+import signal
+import subprocess
+import shlex
+
+
+
+[docs] +def plusargs_to_args(plusargs): + args = [] + if plusargs is not None: + if not isinstance(plusargs, list): + raise TypeError('plusargs must be a list') + for plusarg in plusargs: + if isinstance(plusarg, (list, tuple)): + if len(plusarg) != 2: + raise ValueError('Only lists/tuples of length 2 allowed') + args += [f'+{plusarg[0]}={plusarg[1]}'] + else: + args += [f'+{plusarg}'] + return args
+ + + +
+[docs] +def binary_run(bin, args=None, stop_timeout=10, use_sigint=False, + quiet=False, print_command=False, cwd=None, env=None): + + cmd = [] + + cmd += [bin] + + if args is not None: + if not isinstance(args, list): + raise TypeError('args must be a list') + cmd += args + + cmd = [str(elem) for elem in cmd] + if print_command: + print(' '.join([shlex.quote(elem) for elem in cmd])) + + kwargs = {} + if quiet: + kwargs['stdout'] = subprocess.DEVNULL + kwargs['stderr'] = subprocess.DEVNULL + + p = subprocess.Popen(cmd, cwd=cwd, env=env, **kwargs) + + def stop_bin(p=p, stop_timeout=stop_timeout, use_sigint=use_sigint): + poll = p.poll() + if poll is not None: + # process has stopped + return + + if use_sigint: + try: + p.send_signal(signal.SIGINT) + p.wait(stop_timeout) + return + except: # noqa: E722 + # if there is an exception for any reason, including + # Ctrl-C during the wait() call, want to make sure + # that the process is actually terminated + pass + + # if we get to this point, the process is still running + # and sigint didn't work (or we didn't try it) + p.terminate() + + # note: tried combining all process terminations into a single + # function registered with atexit, but it didn't appear to make + # a difference when running with a few hundred verilator sim + # processes - still took a few dozen milliseconds to stop each + # simulator. + + atexit.register(stop_bin) + + return p
+ + + +
+[docs] +class ProcessCollection: + def __init__(self): + self.processes = [] + +
+[docs] + def add(self, process): + self.processes.append(process)
+ + +
+[docs] + def wait(self): + import subprocess + import multiprocessing + + for process in self.processes: + if isinstance(process, subprocess.Popen): + process.wait() + elif isinstance(process, multiprocessing.Process): + process.join() + else: + raise Exception(f'Unknown process type: {type(process)}')
+ + +
+[docs] + def terminate( + self, + stop_timeout=10, + use_sigint=False + ): + if not self.processes: + return + + for p in self.processes: + if isinstance(p, ProcessCollection): + p.terminate(stop_timeout=stop_timeout, use_sigint=use_sigint) + else: + poll = p.poll() + if poll is not None: + # process has stopped + return + + if use_sigint: + try: + p.send_signal(signal.SIGINT) + p.wait(stop_timeout) + return + except: # noqa: E722 + # if there is an exception for any reason, including + # Ctrl-C during the wait() call, want to make sure + # that the process is actually terminated + pass + + # if we get to this point, the process is still running + # and sigint didn't work (or we didn't try it) + p.terminate()
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/switchboard/verilator.html b/_modules/switchboard/verilator.html new file mode 100644 index 00000000..5a3a2446 --- /dev/null +++ b/_modules/switchboard/verilator.html @@ -0,0 +1,137 @@ + + + + + + switchboard.verilator — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for switchboard.verilator

+# Utilities for working with Verilator
+
+# Copyright (c) 2024 Zero ASIC Corporation
+# This code is licensed under Apache License 2.0 (see LICENSE for details)
+
+# TODO: replace with SiliconCompiler functionality
+
+from .util import plusargs_to_args, binary_run
+
+
+
+[docs] +def verilator_run(bin, plusargs=None, args=None, use_sigint=True, **kwargs): + if args is None: + extra_args = [] + elif isinstance(args, (list, tuple)): + # even if args is already a list, make a copy to + # ensure that changes don't propagate back to the + # value that the user provided for args + extra_args = list(args) + else: + # if the user provided a single value for args, + # wrap it in a list rather than erroring out + extra_args = [args] + + # build up the argument list + args = [] + args += plusargs_to_args(plusargs) + + # append any extra arguments user provided by the user + args += extra_args + + return binary_run(bin=bin, args=args, use_sigint=use_sigint, **kwargs)
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_sources/index.rst.txt b/_sources/index.rst.txt new file mode 100644 index 00000000..da2b9136 --- /dev/null +++ b/_sources/index.rst.txt @@ -0,0 +1,18 @@ +Welcome to Switchboard's documentation! +======================================= + +This page is meant to serve as a reference manual for the various python classes and functions contained in the switchboard package. To get started, reference some of the `examples `_ included in the repository. + +.. toctree:: + :maxdepth: 3 + :caption: Contents: + + index + switchboard + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/_sources/switchboard.bitvector.rst.txt b/_sources/switchboard.bitvector.rst.txt new file mode 100644 index 00000000..6f94e569 --- /dev/null +++ b/_sources/switchboard.bitvector.rst.txt @@ -0,0 +1,9 @@ +switchboard.bitvector module +============================ + +.. automodule:: switchboard.bitvector + :autosummary: + :autosummary-no-nesting: + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/switchboard.icarus.rst.txt b/_sources/switchboard.icarus.rst.txt new file mode 100644 index 00000000..16796c90 --- /dev/null +++ b/_sources/switchboard.icarus.rst.txt @@ -0,0 +1,9 @@ +switchboard.icarus module +========================= + +.. automodule:: switchboard.icarus + :autosummary: + :autosummary-no-nesting: + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/switchboard.loopback.rst.txt b/_sources/switchboard.loopback.rst.txt new file mode 100644 index 00000000..74fa9986 --- /dev/null +++ b/_sources/switchboard.loopback.rst.txt @@ -0,0 +1,9 @@ +switchboard.loopback module +=========================== + +.. automodule:: switchboard.loopback + :autosummary: + :autosummary-no-nesting: + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/switchboard.rst.txt b/_sources/switchboard.rst.txt new file mode 100644 index 00000000..946aaad8 --- /dev/null +++ b/_sources/switchboard.rst.txt @@ -0,0 +1,24 @@ +switchboard package +=================== + +.. automodule:: _switchboard + :autosummary: + :autosummary-no-nesting: + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- +.. toctree:: + :maxdepth: 4 + + switchboard.umi + switchboard.util + switchboard.verilator + switchboard.icarus + switchboard.sbdut + switchboard.loopback + switchboard.bitvector + switchboard.uart_xactor + switchboard.sbtcp diff --git a/_sources/switchboard.sbdut.rst.txt b/_sources/switchboard.sbdut.rst.txt new file mode 100644 index 00000000..84fdb8f4 --- /dev/null +++ b/_sources/switchboard.sbdut.rst.txt @@ -0,0 +1,11 @@ +switchboard.sbdut module +======================== + +Note that the `sbdut` module inherits functions from `siliconcompiler.Chips`, such as `input()` used to add rtl files to the simulation and `add()` used to add include directories to the simulation. These functions are important for specifying the RTL files used in a simulation, but they are not covered in the documentation here. For a complete list of the the inherited functions, checkout the `siliconcompiler documentation `_. + +.. automodule:: switchboard.sbdut + :autosummary: + :autosummary-no-nesting: + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/switchboard.sbtcp.rst.txt b/_sources/switchboard.sbtcp.rst.txt new file mode 100644 index 00000000..75248bc6 --- /dev/null +++ b/_sources/switchboard.sbtcp.rst.txt @@ -0,0 +1,9 @@ +switchboard.sbtcp module +======================== + +.. automodule:: switchboard.sbtcp + :autosummary: + :autosummary-no-nesting: + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/switchboard.uart_xactor.rst.txt b/_sources/switchboard.uart_xactor.rst.txt new file mode 100644 index 00000000..120bded4 --- /dev/null +++ b/_sources/switchboard.uart_xactor.rst.txt @@ -0,0 +1,9 @@ +switchboard.uart_xactor module +============================== + +.. automodule:: switchboard.uart_xactor + :autosummary: + :autosummary-no-nesting: + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/switchboard.umi.rst.txt b/_sources/switchboard.umi.rst.txt new file mode 100644 index 00000000..a46e35e4 --- /dev/null +++ b/_sources/switchboard.umi.rst.txt @@ -0,0 +1,9 @@ +switchboard.umi module +====================== + +.. automodule:: switchboard.umi + :autosummary: + :autosummary-no-nesting: + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/switchboard.util.rst.txt b/_sources/switchboard.util.rst.txt new file mode 100644 index 00000000..f978e673 --- /dev/null +++ b/_sources/switchboard.util.rst.txt @@ -0,0 +1,9 @@ +switchboard.util module +======================= + +.. automodule:: switchboard.util + :autosummary: + :autosummary-no-nesting: + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/switchboard.verilator.rst.txt b/_sources/switchboard.verilator.rst.txt new file mode 100644 index 00000000..3888eef9 --- /dev/null +++ b/_sources/switchboard.verilator.rst.txt @@ -0,0 +1,9 @@ +switchboard.verilator module +============================ + +.. automodule:: switchboard.verilator + :autosummary: + :autosummary-no-nesting: + :members: + :undoc-members: + :show-inheritance: diff --git a/_static/_sphinx_javascript_frameworks_compat.js b/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 00000000..81415803 --- /dev/null +++ b/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,123 @@ +/* Compatability shim for jQuery and underscores.js. + * + * Copyright Sphinx contributors + * Released under the two clause BSD licence + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 00000000..f316efcb --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,925 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/_static/css/badge_only.css b/_static/css/badge_only.css new file mode 100644 index 00000000..c718cee4 --- /dev/null +++ b/_static/css/badge_only.css @@ -0,0 +1 @@ +.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} \ No newline at end of file diff --git a/_static/css/fonts/Roboto-Slab-Bold.woff b/_static/css/fonts/Roboto-Slab-Bold.woff new file mode 100644 index 00000000..6cb60000 Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Bold.woff differ diff --git a/_static/css/fonts/Roboto-Slab-Bold.woff2 b/_static/css/fonts/Roboto-Slab-Bold.woff2 new file mode 100644 index 00000000..7059e231 Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Bold.woff2 differ diff --git a/_static/css/fonts/Roboto-Slab-Regular.woff b/_static/css/fonts/Roboto-Slab-Regular.woff new file mode 100644 index 00000000..f815f63f Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Regular.woff differ diff --git a/_static/css/fonts/Roboto-Slab-Regular.woff2 b/_static/css/fonts/Roboto-Slab-Regular.woff2 new file mode 100644 index 00000000..f2c76e5b Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Regular.woff2 differ diff --git a/_static/css/fonts/fontawesome-webfont.eot b/_static/css/fonts/fontawesome-webfont.eot new file mode 100644 index 00000000..e9f60ca9 Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.eot differ diff --git a/_static/css/fonts/fontawesome-webfont.svg b/_static/css/fonts/fontawesome-webfont.svg new file mode 100644 index 00000000..855c845e --- /dev/null +++ b/_static/css/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_static/css/fonts/fontawesome-webfont.ttf b/_static/css/fonts/fontawesome-webfont.ttf new file mode 100644 index 00000000..35acda2f Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.ttf differ diff --git a/_static/css/fonts/fontawesome-webfont.woff b/_static/css/fonts/fontawesome-webfont.woff new file mode 100644 index 00000000..400014a4 Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.woff differ diff --git a/_static/css/fonts/fontawesome-webfont.woff2 b/_static/css/fonts/fontawesome-webfont.woff2 new file mode 100644 index 00000000..4d13fc60 Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.woff2 differ diff --git a/_static/css/fonts/lato-bold-italic.woff b/_static/css/fonts/lato-bold-italic.woff new file mode 100644 index 00000000..88ad05b9 Binary files /dev/null and b/_static/css/fonts/lato-bold-italic.woff differ diff --git a/_static/css/fonts/lato-bold-italic.woff2 b/_static/css/fonts/lato-bold-italic.woff2 new file mode 100644 index 00000000..c4e3d804 Binary files /dev/null and b/_static/css/fonts/lato-bold-italic.woff2 differ diff --git a/_static/css/fonts/lato-bold.woff b/_static/css/fonts/lato-bold.woff new file mode 100644 index 00000000..c6dff51f Binary files /dev/null and b/_static/css/fonts/lato-bold.woff differ diff --git a/_static/css/fonts/lato-bold.woff2 b/_static/css/fonts/lato-bold.woff2 new file mode 100644 index 00000000..bb195043 Binary files /dev/null and b/_static/css/fonts/lato-bold.woff2 differ diff --git a/_static/css/fonts/lato-normal-italic.woff b/_static/css/fonts/lato-normal-italic.woff new file mode 100644 index 00000000..76114bc0 Binary files /dev/null and b/_static/css/fonts/lato-normal-italic.woff differ diff --git a/_static/css/fonts/lato-normal-italic.woff2 b/_static/css/fonts/lato-normal-italic.woff2 new file mode 100644 index 00000000..3404f37e Binary files /dev/null and b/_static/css/fonts/lato-normal-italic.woff2 differ diff --git a/_static/css/fonts/lato-normal.woff b/_static/css/fonts/lato-normal.woff new file mode 100644 index 00000000..ae1307ff Binary files /dev/null and b/_static/css/fonts/lato-normal.woff differ diff --git a/_static/css/fonts/lato-normal.woff2 b/_static/css/fonts/lato-normal.woff2 new file mode 100644 index 00000000..3bf98433 Binary files /dev/null and b/_static/css/fonts/lato-normal.woff2 differ diff --git a/_static/css/theme.css b/_static/css/theme.css new file mode 100644 index 00000000..19a446a0 --- /dev/null +++ b/_static/css/theme.css @@ -0,0 +1,4 @@ +html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel,.rst-content .menuselection{font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .guilabel,.rst-content .menuselection{border:1px solid #7fbbe3;background:#e7f2fa}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 00000000..4d67807d --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/_static/documentation_options.js b/_static/documentation_options.js new file mode 100644 index 00000000..df66cc5e --- /dev/null +++ b/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '0.0.29', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 00000000..a858a410 Binary files /dev/null and b/_static/file.png differ diff --git a/_static/jquery.js b/_static/jquery.js new file mode 100644 index 00000000..c4c6022f --- /dev/null +++ b/_static/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document); \ No newline at end of file diff --git a/_static/js/html5shiv.min.js b/_static/js/html5shiv.min.js new file mode 100644 index 00000000..cd1c674f --- /dev/null +++ b/_static/js/html5shiv.min.js @@ -0,0 +1,4 @@ +/** +* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed +*/ +!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); \ No newline at end of file diff --git a/_static/js/theme.js b/_static/js/theme.js new file mode 100644 index 00000000..1fddb6ee --- /dev/null +++ b/_static/js/theme.js @@ -0,0 +1 @@ +!function(n){var e={};function t(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return n[i].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,i){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var i=Object.create(null);if(t.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(i,o,function(e){return n[e]}.bind(null,o));return i},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){t(1),n.exports=t(3)},function(n,e,t){(function(){var e="undefined"!=typeof window?window.jQuery:t(2);n.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(n){var t=this;void 0===n&&(n=!0),t.isRunning||(t.isRunning=!0,e((function(e){t.init(e),t.reset(),t.win.on("hashchange",t.reset),n&&t.win.on("scroll",(function(){t.linkScroll||t.winScroll||(t.winScroll=!0,requestAnimationFrame((function(){t.onScroll()})))})),t.win.on("resize",(function(){t.winResize||(t.winResize=!0,requestAnimationFrame((function(){t.onResize()})))})),t.onResize()})))},enableSticky:function(){this.enable(!0)},init:function(n){n(document);var e=this;this.navBar=n("div.wy-side-scroll:first"),this.win=n(window),n(document).on("click","[data-toggle='wy-nav-top']",(function(){n("[data-toggle='wy-nav-shift']").toggleClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift")})).on("click",".wy-menu-vertical .current ul li a",(function(){var t=n(this);n("[data-toggle='wy-nav-shift']").removeClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift"),e.toggleCurrent(t),e.hashChange()})).on("click","[data-toggle='rst-current-version']",(function(){n("[data-toggle='rst-versions']").toggleClass("shift-up")})),n("table.docutils:not(.field-list,.footnote,.citation)").wrap("
"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/_static/minus.png b/_static/minus.png new file mode 100644 index 00000000..d96755fd Binary files /dev/null and b/_static/minus.png differ diff --git a/_static/plus.png b/_static/plus.png new file mode 100644 index 00000000..7107cec9 Binary files /dev/null and b/_static/plus.png differ diff --git a/_static/pygments.css b/_static/pygments.css new file mode 100644 index 00000000..84ab3030 --- /dev/null +++ b/_static/pygments.css @@ -0,0 +1,75 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #008000; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #9C6500 } /* Comment.Preproc */ +.highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +.highlight .gr { color: #E40000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #008400 } /* Generic.Inserted */ +.highlight .go { color: #717171 } /* Generic.Output */ +.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #008000 } /* Keyword.Pseudo */ +.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #B00040 } /* Keyword.Type */ +.highlight .m { color: #666666 } /* Literal.Number */ +.highlight .s { color: #BA2121 } /* Literal.String */ +.highlight .na { color: #687822 } /* Name.Attribute */ +.highlight .nb { color: #008000 } /* Name.Builtin */ +.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.highlight .no { color: #880000 } /* Name.Constant */ +.highlight .nd { color: #AA22FF } /* Name.Decorator */ +.highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #0000FF } /* Name.Function */ +.highlight .nl { color: #767600 } /* Name.Label */ +.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #19177C } /* Name.Variable */ +.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mb { color: #666666 } /* Literal.Number.Bin */ +.highlight .mf { color: #666666 } /* Literal.Number.Float */ +.highlight .mh { color: #666666 } /* Literal.Number.Hex */ +.highlight .mi { color: #666666 } /* Literal.Number.Integer */ +.highlight .mo { color: #666666 } /* Literal.Number.Oct */ +.highlight .sa { color: #BA2121 } /* Literal.String.Affix */ +.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ +.highlight .sc { color: #BA2121 } /* Literal.String.Char */ +.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */ +.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ +.highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */ +.highlight .sx { color: #008000 } /* Literal.String.Other */ +.highlight .sr { color: #A45A77 } /* Literal.String.Regex */ +.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ +.highlight .ss { color: #19177C } /* Literal.String.Symbol */ +.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #0000FF } /* Name.Function.Magic */ +.highlight .vc { color: #19177C } /* Name.Variable.Class */ +.highlight .vg { color: #19177C } /* Name.Variable.Global */ +.highlight .vi { color: #19177C } /* Name.Variable.Instance */ +.highlight .vm { color: #19177C } /* Name.Variable.Magic */ +.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/_static/searchtools.js b/_static/searchtools.js new file mode 100644 index 00000000..b08d58c9 --- /dev/null +++ b/_static/searchtools.js @@ -0,0 +1,620 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + } + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms, anchor) + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + "Search finished, found ${resultCount} page(s) matching the search query." + ).replace('${resultCount}', resultCount); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString, anchor) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + for (const removalQuery of [".headerlink", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` + ); + } + + // if anchor not specified or not found, fall back to main content + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent) return docContent.textContent; + + console.warn( + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + _parseQuery: (query) => { + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename]. + const normalResults = []; + const nonMainIndexResults = []; + + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase().trim(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + const score = Math.round(Scorer.title * queryLower.length / title.length); + const boost = titles[file] === title ? 1 : 0; // add a boost for document titles + normalResults.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score + boost, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id, isMain] of foundEntries) { + const score = Math.round(100 * queryLower.length / entry.length); + const result = [ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } + } + } + } + + // lookup as object + objectTerms.forEach((term) => + normalResults.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + return results.reverse(); + }, + + query: (query) => { + const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); + const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/_static/sphinx_highlight.js b/_static/sphinx_highlight.js new file mode 100644 index 00000000..8a96c69a --- /dev/null +++ b/_static/sphinx_highlight.js @@ -0,0 +1,154 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore( + span, + parent.insertBefore( + rest, + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/genindex.html b/genindex.html new file mode 100644 index 00000000..fe9ddb18 --- /dev/null +++ b/genindex.html @@ -0,0 +1,655 @@ + + + + + + Index — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Index

+ +
+ _ + | A + | B + | C + | D + | F + | G + | I + | M + | N + | P + | R + | S + | T + | U + | V + | W + +
+

_

+ + +
    +
  • + _switchboard + +
  • +
+ +

A

+ + + +
+ +

B

+ + + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

F

+ + + +
+ +

G

+ + + +
+ +

I

+ + + +
+ +

M

+ + +
+ +

N

+ + + +
+ +

P

+ + + +
+ +

R

+ + + +
+ +

S

+ + + +
    +
  • + switchboard.loopback + +
  • +
  • + switchboard.sbdut + +
  • +
  • + switchboard.sbtcp + +
  • +
  • + switchboard.uart_xactor + +
  • +
  • + switchboard.umi + +
  • +
  • + switchboard.util + +
  • +
  • + switchboard.verilator + +
  • +
+ +

T

+ + + +
+ +

U

+ + + +
+ +

V

+ + + +
+ +

W

+ + + +
+ + + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..2dbd61a4 --- /dev/null +++ b/index.html @@ -0,0 +1,228 @@ + + + + + + + Welcome to Switchboard’s documentation! — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Welcome to Switchboard’s documentation!

+

This page is meant to serve as a reference manual for the various python classes and functions contained in the switchboard package. To get started, reference some of the examples included in the repository.

+
+

Contents:

+ +
+
+
+

Indices and tables

+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/objects.inv b/objects.inv new file mode 100644 index 00000000..6939dd18 Binary files /dev/null and b/objects.inv differ diff --git a/py-modindex.html b/py-modindex.html new file mode 100644 index 00000000..da26c385 --- /dev/null +++ b/py-modindex.html @@ -0,0 +1,176 @@ + + + + + + Python Module Index — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Python Module Index

+ +
+ _ | + s +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ _
+ _switchboard +
 
+ s
+ switchboard +
    + switchboard.bitvector +
    + switchboard.icarus +
    + switchboard.loopback +
    + switchboard.sbdut +
    + switchboard.sbtcp +
    + switchboard.uart_xactor +
    + switchboard.umi +
    + switchboard.util +
    + switchboard.verilator +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/search.html b/search.html new file mode 100644 index 00000000..0629326b --- /dev/null +++ b/search.html @@ -0,0 +1,122 @@ + + + + + + Search — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + + + +
+ +
+ +
+
+ +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/searchindex.js b/searchindex.js new file mode 100644 index 00000000..59789fb5 --- /dev/null +++ b/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"alltitles": {"Contents:": [[0, null]], "Indices and tables": [[0, "indices-and-tables"]], "Submodules": [[1, "submodules"]], "Welcome to Switchboard\u2019s documentation!": [[0, null]], "switchboard package": [[1, null]], "switchboard.bitvector module": [[2, null]], "switchboard.icarus module": [[3, null]], "switchboard.loopback module": [[4, null]], "switchboard.sbdut module": [[5, null]], "switchboard.sbtcp module": [[6, null]], "switchboard.uart_xactor module": [[7, null]], "switchboard.umi module": [[8, null]], "switchboard.util module": [[9, null]], "switchboard.verilator module": [[10, null]]}, "docnames": ["index", "switchboard", "switchboard.bitvector", "switchboard.icarus", "switchboard.loopback", "switchboard.sbdut", "switchboard.sbtcp", "switchboard.uart_xactor", "switchboard.umi", "switchboard.util", "switchboard.verilator"], "envversion": {"sphinx": 62, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1}, "filenames": ["index.rst", "switchboard.rst", "switchboard.bitvector.rst", "switchboard.icarus.rst", "switchboard.loopback.rst", "switchboard.sbdut.rst", "switchboard.sbtcp.rst", "switchboard.uart_xactor.rst", "switchboard.umi.rst", "switchboard.util.rst", "switchboard.verilator.rst"], "indexentries": {"_switchboard": [[1, "module-_switchboard", false]], "add() (switchboard.util.processcollection method)": [[9, "switchboard.util.ProcessCollection.add", false]], "addr_aligned() (in module switchboard.umi)": [[8, "switchboard.umi.addr_aligned", false]], "atomic() (_switchboard.pyumi method)": [[1, "switchboard.PyUmi.atomic", false]], "atomic() (switchboard.umi.umitxrx method)": [[8, "switchboard.umi.UmiTxRx.atomic", false]], "binary_run() (in module switchboard.util)": [[9, "switchboard.util.binary_run", false]], "bitvector (class in switchboard.bitvector)": [[2, "switchboard.bitvector.BitVector", false]], "build() (switchboard.sbdut.sbdut method)": [[5, "switchboard.sbdut.SbDut.build", false]], "bytes2sb() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.bytes2sb", false]], "carefully_add_plusarg() (in module switchboard.sbdut)": [[5, "switchboard.sbdut.carefully_add_plusarg", false]], "check_int_in_range() (in module switchboard.umi)": [[8, "switchboard.umi.check_int_in_range", false]], "cmd (_switchboard.pyumipacket property)": [[1, "switchboard.PyUmiPacket.cmd", false]], "convert_to_queue() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.convert_to_queue", false]], "data (_switchboard.pysbpacket property)": [[1, "switchboard.PySbPacket.data", false]], "data (_switchboard.pyumipacket property)": [[1, "switchboard.PyUmiPacket.data", false]], "delete_queue() (in module _switchboard)": [[1, "switchboard.delete_queue", false]], "delete_queues() (in module _switchboard)": [[1, "switchboard.delete_queues", false]], "destination (_switchboard.pysbpacket property)": [[1, "switchboard.PySbPacket.destination", false]], "dstaddr (_switchboard.pyumipacket property)": [[1, "switchboard.PyUmiPacket.dstaddr", false]], "dtype2size() (in module switchboard.umi)": [[8, "switchboard.umi.dtype2size", false]], "find_package() (switchboard.sbdut.sbdut method)": [[5, "switchboard.sbdut.SbDut.find_package", false]], "find_sim() (switchboard.sbdut.sbdut method)": [[5, "switchboard.sbdut.SbDut.find_sim", false]], "flags (_switchboard.pysbpacket property)": [[1, "switchboard.PySbPacket.flags", false]], "frombytes() (switchboard.bitvector.bitvector static method)": [[2, "switchboard.bitvector.BitVector.frombytes", false]], "get_parser() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.get_parser", false]], "gpio() (switchboard.umi.umitxrx method)": [[8, "switchboard.umi.UmiTxRx.gpio", false]], "icarus_build_vpi() (in module switchboard.icarus)": [[3, "switchboard.icarus.icarus_build_vpi", false]], "icarus_find_vpi() (in module switchboard.icarus)": [[3, "switchboard.icarus.icarus_find_vpi", false]], "icarus_run() (in module switchboard.icarus)": [[3, "switchboard.icarus.icarus_run", false]], "init() (_switchboard.pysbrx method)": [[1, "switchboard.PySbRx.init", false]], "init() (_switchboard.pysbrxpcie method)": [[1, "switchboard.PySbRxPcie.init", false]], "init() (_switchboard.pysbtx method)": [[1, "switchboard.PySbTx.init", false]], "init() (_switchboard.pysbtxpcie method)": [[1, "switchboard.PySbTxPcie.init", false]], "init() (_switchboard.pyumi method)": [[1, "switchboard.PyUmi.init", false]], "init_queues() (switchboard.umi.umitxrx method)": [[8, "switchboard.umi.UmiTxRx.init_queues", false]], "input_analog() (switchboard.sbdut.sbdut method)": [[5, "switchboard.sbdut.SbDut.input_analog", false]], "main() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.main", false]], "merge() (_switchboard.pyumipacket method)": [[1, "switchboard.PyUmiPacket.merge", false]], "metadata_str() (in module switchboard.sbdut)": [[5, "switchboard.sbdut.metadata_str", false]], "module": [[1, "module-_switchboard", false], [2, "module-switchboard.bitvector", false], [3, "module-switchboard.icarus", false], [4, "module-switchboard.loopback", false], [5, "module-switchboard.sbdut", false], [6, "module-switchboard.sbtcp", false], [7, "module-switchboard.uart_xactor", false], [8, "module-switchboard.umi", false], [9, "module-switchboard.util", false], [10, "module-switchboard.verilator", false]], "name (_switchboard.umiatomic property)": [[1, "switchboard.UmiAtomic.name", false]], "name (_switchboard.umicmd property)": [[1, "switchboard.UmiCmd.name", false]], "nbytes2size() (in module switchboard.umi)": [[8, "switchboard.umi.nbytes2size", false]], "normalize_inputs() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.normalize_inputs", false]], "normalize_inputs_and_outputs() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.normalize_inputs_and_outputs", false]], "normalize_outputs() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.normalize_outputs", false]], "package() (switchboard.sbdut.sbdut method)": [[5, "switchboard.sbdut.SbDut.package", false]], "parse_rule() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.parse_rule", false]], "plusargs_to_args() (in module switchboard.util)": [[9, "switchboard.util.plusargs_to_args", false]], "processcollection (class in switchboard.util)": [[9, "switchboard.util.ProcessCollection", false]], "pysbpacket (class in _switchboard)": [[1, "switchboard.PySbPacket", false]], "pysbrx (class in _switchboard)": [[1, "switchboard.PySbRx", false]], "pysbrxpcie (class in _switchboard)": [[1, "switchboard.PySbRxPcie", false]], "pysbtx (class in _switchboard)": [[1, "switchboard.PySbTx", false]], "pysbtxpcie (class in _switchboard)": [[1, "switchboard.PySbTxPcie", false]], "pyumi (class in _switchboard)": [[1, "switchboard.PyUmi", false]], "pyumipacket (class in _switchboard)": [[1, "switchboard.PyUmiPacket", false]], "random_int_value() (in module switchboard.umi)": [[8, "switchboard.umi.random_int_value", false]], "random_umi_packet() (in module switchboard.umi)": [[8, "switchboard.umi.random_umi_packet", false]], "read() (_switchboard.pyumi method)": [[1, "switchboard.PyUmi.read", false]], "read() (switchboard.uart_xactor.uart_xactor method)": [[7, "switchboard.uart_xactor.uart_xactor.read", false]], "read() (switchboard.umi.umitxrx method)": [[8, "switchboard.umi.UmiTxRx.read", false]], "read_byte() (switchboard.uart_xactor.uart_xactor method)": [[7, "switchboard.uart_xactor.uart_xactor.read_byte", false]], "readline() (switchboard.uart_xactor.uart_xactor method)": [[7, "switchboard.uart_xactor.uart_xactor.readline", false]], "recv() (_switchboard.pysbrx method)": [[1, "switchboard.PySbRx.recv", false]], "recv() (_switchboard.pyumi method)": [[1, "switchboard.PyUmi.recv", false]], "recv() (switchboard.umi.umitxrx method)": [[8, "switchboard.umi.UmiTxRx.recv", false]], "reg_rx (switchboard.uart_xactor.uart_xactor attribute)": [[7, "switchboard.uart_xactor.uart_xactor.REG_RX", false]], "reg_sr (switchboard.uart_xactor.uart_xactor attribute)": [[7, "switchboard.uart_xactor.uart_xactor.REG_SR", false]], "reg_tx (switchboard.uart_xactor.uart_xactor attribute)": [[7, "switchboard.uart_xactor.uart_xactor.REG_TX", false]], "regf_sr_rxempty_mask (switchboard.uart_xactor.uart_xactor attribute)": [[7, "switchboard.uart_xactor.uart_xactor.REGF_SR_RXEMPTY_MASK", false]], "regf_sr_rxfull_mask (switchboard.uart_xactor.uart_xactor attribute)": [[7, "switchboard.uart_xactor.uart_xactor.REGF_SR_RXFULL_MASK", false]], "regf_sr_txempty_mask (switchboard.uart_xactor.uart_xactor attribute)": [[7, "switchboard.uart_xactor.uart_xactor.REGF_SR_TXEMPTY_MASK", false]], "regf_sr_txfull_mask (switchboard.uart_xactor.uart_xactor attribute)": [[7, "switchboard.uart_xactor.uart_xactor.REGF_SR_TXFULL_MASK", false]], "rule_matches() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.rule_matches", false]], "run() (in module switchboard.icarus)": [[3, "switchboard.icarus.run", false]], "run_client() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.run_client", false]], "run_server() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.run_server", false]], "sb2bytes() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.sb2bytes", false]], "sb2tcp() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.sb2tcp", false]], "sbdut (class in switchboard.sbdut)": [[5, "switchboard.sbdut.SbDut", false]], "send() (_switchboard.pysbtx method)": [[1, "switchboard.PySbTx.send", false]], "send() (_switchboard.pyumi method)": [[1, "switchboard.PyUmi.send", false]], "send() (switchboard.umi.umitxrx method)": [[8, "switchboard.umi.UmiTxRx.send", false]], "simulate() (switchboard.sbdut.sbdut method)": [[5, "switchboard.sbdut.SbDut.simulate", false]], "size2dtype() (in module switchboard.umi)": [[8, "switchboard.umi.size2dtype", false]], "slice_to_msb_lsb() (in module switchboard.bitvector)": [[2, "switchboard.bitvector.slice_to_msb_lsb", false]], "srcaddr (_switchboard.pyumipacket property)": [[1, "switchboard.PyUmiPacket.srcaddr", false]], "start_tcp_bridge() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.start_tcp_bridge", false]], "switchboard.bitvector": [[2, "module-switchboard.bitvector", false]], "switchboard.icarus": [[3, "module-switchboard.icarus", false]], "switchboard.loopback": [[4, "module-switchboard.loopback", false]], "switchboard.sbdut": [[5, "module-switchboard.sbdut", false]], "switchboard.sbtcp": [[6, "module-switchboard.sbtcp", false]], "switchboard.uart_xactor": [[7, "module-switchboard.uart_xactor", false]], "switchboard.umi": [[8, "module-switchboard.umi", false]], "switchboard.util": [[9, "module-switchboard.util", false]], "switchboard.verilator": [[10, "module-switchboard.verilator", false]], "tcp2sb() (in module switchboard.sbtcp)": [[6, "switchboard.sbtcp.tcp2sb", false]], "terminate() (switchboard.sbdut.sbdut method)": [[5, "switchboard.sbdut.SbDut.terminate", false]], "terminate() (switchboard.util.processcollection method)": [[9, "switchboard.util.ProcessCollection.terminate", false]], "tobytes() (switchboard.bitvector.bitvector method)": [[2, "switchboard.bitvector.BitVector.tobytes", false]], "uart_xactor (class in switchboard.uart_xactor)": [[7, "switchboard.uart_xactor.uart_xactor", false]], "umi_atype() (in module _switchboard)": [[1, "switchboard.umi_atype", false]], "umi_eof() (in module _switchboard)": [[1, "switchboard.umi_eof", false]], "umi_eom() (in module _switchboard)": [[1, "switchboard.umi_eom", false]], "umi_ex() (in module _switchboard)": [[1, "switchboard.umi_ex", false]], "umi_invalid (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_INVALID", false]], "umi_len() (in module _switchboard)": [[1, "switchboard.umi_len", false]], "umi_loopback() (in module switchboard.loopback)": [[4, "switchboard.loopback.umi_loopback", false]], "umi_opcode() (in module _switchboard)": [[1, "switchboard.umi_opcode", false]], "umi_opcode_to_str() (in module _switchboard)": [[1, "switchboard.umi_opcode_to_str", false]], "umi_pack() (in module _switchboard)": [[1, "switchboard.umi_pack", false]], "umi_prot() (in module _switchboard)": [[1, "switchboard.umi_prot", false]], "umi_qos() (in module _switchboard)": [[1, "switchboard.umi_qos", false]], "umi_req_atomic (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_REQ_ATOMIC", false]], "umi_req_atomicadd (_switchboard.umiatomic attribute)": [[1, "switchboard.UmiAtomic.UMI_REQ_ATOMICADD", false]], "umi_req_atomicand (_switchboard.umiatomic attribute)": [[1, "switchboard.UmiAtomic.UMI_REQ_ATOMICAND", false]], "umi_req_atomicmax (_switchboard.umiatomic attribute)": [[1, "switchboard.UmiAtomic.UMI_REQ_ATOMICMAX", false]], "umi_req_atomicmaxu (_switchboard.umiatomic attribute)": [[1, "switchboard.UmiAtomic.UMI_REQ_ATOMICMAXU", false]], "umi_req_atomicmin (_switchboard.umiatomic attribute)": [[1, "switchboard.UmiAtomic.UMI_REQ_ATOMICMIN", false]], "umi_req_atomicminu (_switchboard.umiatomic attribute)": [[1, "switchboard.UmiAtomic.UMI_REQ_ATOMICMINU", false]], "umi_req_atomicor (_switchboard.umiatomic attribute)": [[1, "switchboard.UmiAtomic.UMI_REQ_ATOMICOR", false]], "umi_req_atomicswap (_switchboard.umiatomic attribute)": [[1, "switchboard.UmiAtomic.UMI_REQ_ATOMICSWAP", false]], "umi_req_atomicxor (_switchboard.umiatomic attribute)": [[1, "switchboard.UmiAtomic.UMI_REQ_ATOMICXOR", false]], "umi_req_error (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_REQ_ERROR", false]], "umi_req_future0 (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_REQ_FUTURE0", false]], "umi_req_link (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_REQ_LINK", false]], "umi_req_posted (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_REQ_POSTED", false]], "umi_req_rdma (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_REQ_RDMA", false]], "umi_req_read (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_REQ_READ", false]], "umi_req_user0 (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_REQ_USER0", false]], "umi_req_write (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_REQ_WRITE", false]], "umi_resp_future0 (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_RESP_FUTURE0", false]], "umi_resp_future1 (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_RESP_FUTURE1", false]], "umi_resp_link (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_RESP_LINK", false]], "umi_resp_read (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_RESP_READ", false]], "umi_resp_user0 (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_RESP_USER0", false]], "umi_resp_user1 (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_RESP_USER1", false]], "umi_resp_write (_switchboard.umicmd attribute)": [[1, "switchboard.UmiCmd.UMI_RESP_WRITE", false]], "umi_size() (in module _switchboard)": [[1, "switchboard.umi_size", false]], "umiatomic (class in _switchboard)": [[1, "switchboard.UmiAtomic", false]], "umicmd (class in _switchboard)": [[1, "switchboard.UmiCmd", false]], "umitxrx (class in switchboard.umi)": [[8, "switchboard.umi.UmiTxRx", false]], "value (_switchboard.umiatomic property)": [[1, "switchboard.UmiAtomic.value", false]], "value (_switchboard.umicmd property)": [[1, "switchboard.UmiCmd.value", false]], "verilator_run() (in module switchboard.verilator)": [[10, "switchboard.verilator.verilator_run", false]], "wait() (switchboard.util.processcollection method)": [[9, "switchboard.util.ProcessCollection.wait", false]], "write() (_switchboard.pyumi method)": [[1, "switchboard.PyUmi.write", false]], "write() (switchboard.uart_xactor.uart_xactor method)": [[7, "switchboard.uart_xactor.uart_xactor.write", false]], "write() (switchboard.umi.umitxrx method)": [[8, "switchboard.umi.UmiTxRx.write", false]], "write_byte() (switchboard.uart_xactor.uart_xactor method)": [[7, "switchboard.uart_xactor.uart_xactor.write_byte", false]], "write_readback() (switchboard.umi.umitxrx method)": [[8, "switchboard.umi.UmiTxRx.write_readback", false]]}, "objects": {"": [[1, 0, 0, "-", "_switchboard"]], "_switchboard": [[1, 1, 1, "switchboard.PySbPacket", "PySbPacket"], [1, 1, 1, "switchboard.PySbRx", "PySbRx"], [1, 1, 1, "switchboard.PySbRxPcie", "PySbRxPcie"], [1, 1, 1, "switchboard.PySbTx", "PySbTx"], [1, 1, 1, "switchboard.PySbTxPcie", "PySbTxPcie"], [1, 1, 1, "switchboard.PyUmi", "PyUmi"], [1, 1, 1, "switchboard.PyUmiPacket", "PyUmiPacket"], [1, 1, 1, "switchboard.UmiAtomic", "UmiAtomic"], [1, 1, 1, "switchboard.UmiCmd", "UmiCmd"], [1, 5, 1, "switchboard.delete_queue", "delete_queue"], [1, 5, 1, "switchboard.delete_queues", "delete_queues"], [1, 5, 1, "switchboard.umi_atype", "umi_atype"], [1, 5, 1, "switchboard.umi_eof", "umi_eof"], [1, 5, 1, "switchboard.umi_eom", "umi_eom"], [1, 5, 1, "switchboard.umi_ex", "umi_ex"], [1, 5, 1, "switchboard.umi_len", "umi_len"], [1, 5, 1, "switchboard.umi_opcode", "umi_opcode"], [1, 5, 1, "switchboard.umi_opcode_to_str", "umi_opcode_to_str"], [1, 5, 1, "switchboard.umi_pack", "umi_pack"], [1, 5, 1, "switchboard.umi_prot", "umi_prot"], [1, 5, 1, "switchboard.umi_qos", "umi_qos"], [1, 5, 1, "switchboard.umi_size", "umi_size"]], "_switchboard.PySbPacket": [[1, 2, 1, "switchboard.PySbPacket.data", "data"], [1, 2, 1, "switchboard.PySbPacket.destination", "destination"], [1, 2, 1, "switchboard.PySbPacket.flags", "flags"]], "_switchboard.PySbRx": [[1, 3, 1, "switchboard.PySbRx.init", "init"], [1, 3, 1, "switchboard.PySbRx.recv", "recv"]], "_switchboard.PySbRxPcie": [[1, 3, 1, "switchboard.PySbRxPcie.init", "init"]], "_switchboard.PySbTx": [[1, 3, 1, "switchboard.PySbTx.init", "init"], [1, 3, 1, "switchboard.PySbTx.send", "send"]], "_switchboard.PySbTxPcie": [[1, 3, 1, "switchboard.PySbTxPcie.init", "init"]], "_switchboard.PyUmi": [[1, 3, 1, "switchboard.PyUmi.atomic", "atomic"], [1, 3, 1, "switchboard.PyUmi.init", "init"], [1, 3, 1, "switchboard.PyUmi.read", "read"], [1, 3, 1, "switchboard.PyUmi.recv", "recv"], [1, 3, 1, "switchboard.PyUmi.send", "send"], [1, 3, 1, "switchboard.PyUmi.write", "write"]], "_switchboard.PyUmiPacket": [[1, 2, 1, "switchboard.PyUmiPacket.cmd", "cmd"], [1, 2, 1, "switchboard.PyUmiPacket.data", "data"], [1, 2, 1, "switchboard.PyUmiPacket.dstaddr", "dstaddr"], [1, 3, 1, "switchboard.PyUmiPacket.merge", "merge"], [1, 2, 1, "switchboard.PyUmiPacket.srcaddr", "srcaddr"]], "_switchboard.UmiAtomic": [[1, 4, 1, "switchboard.UmiAtomic.UMI_REQ_ATOMICADD", "UMI_REQ_ATOMICADD"], [1, 4, 1, "switchboard.UmiAtomic.UMI_REQ_ATOMICAND", "UMI_REQ_ATOMICAND"], [1, 4, 1, "switchboard.UmiAtomic.UMI_REQ_ATOMICMAX", "UMI_REQ_ATOMICMAX"], [1, 4, 1, "switchboard.UmiAtomic.UMI_REQ_ATOMICMAXU", "UMI_REQ_ATOMICMAXU"], [1, 4, 1, "switchboard.UmiAtomic.UMI_REQ_ATOMICMIN", "UMI_REQ_ATOMICMIN"], [1, 4, 1, "switchboard.UmiAtomic.UMI_REQ_ATOMICMINU", "UMI_REQ_ATOMICMINU"], [1, 4, 1, "switchboard.UmiAtomic.UMI_REQ_ATOMICOR", "UMI_REQ_ATOMICOR"], [1, 4, 1, "switchboard.UmiAtomic.UMI_REQ_ATOMICSWAP", "UMI_REQ_ATOMICSWAP"], [1, 4, 1, "switchboard.UmiAtomic.UMI_REQ_ATOMICXOR", "UMI_REQ_ATOMICXOR"], [1, 2, 1, "switchboard.UmiAtomic.name", "name"], [1, 2, 1, "switchboard.UmiAtomic.value", "value"]], "_switchboard.UmiCmd": [[1, 4, 1, "switchboard.UmiCmd.UMI_INVALID", "UMI_INVALID"], [1, 4, 1, "switchboard.UmiCmd.UMI_REQ_ATOMIC", "UMI_REQ_ATOMIC"], [1, 4, 1, "switchboard.UmiCmd.UMI_REQ_ERROR", "UMI_REQ_ERROR"], [1, 4, 1, "switchboard.UmiCmd.UMI_REQ_FUTURE0", "UMI_REQ_FUTURE0"], [1, 4, 1, "switchboard.UmiCmd.UMI_REQ_LINK", "UMI_REQ_LINK"], [1, 4, 1, "switchboard.UmiCmd.UMI_REQ_POSTED", "UMI_REQ_POSTED"], [1, 4, 1, "switchboard.UmiCmd.UMI_REQ_RDMA", "UMI_REQ_RDMA"], [1, 4, 1, "switchboard.UmiCmd.UMI_REQ_READ", "UMI_REQ_READ"], [1, 4, 1, "switchboard.UmiCmd.UMI_REQ_USER0", "UMI_REQ_USER0"], [1, 4, 1, "switchboard.UmiCmd.UMI_REQ_WRITE", "UMI_REQ_WRITE"], [1, 4, 1, "switchboard.UmiCmd.UMI_RESP_FUTURE0", "UMI_RESP_FUTURE0"], [1, 4, 1, "switchboard.UmiCmd.UMI_RESP_FUTURE1", "UMI_RESP_FUTURE1"], [1, 4, 1, "switchboard.UmiCmd.UMI_RESP_LINK", "UMI_RESP_LINK"], [1, 4, 1, "switchboard.UmiCmd.UMI_RESP_READ", "UMI_RESP_READ"], [1, 4, 1, "switchboard.UmiCmd.UMI_RESP_USER0", "UMI_RESP_USER0"], [1, 4, 1, "switchboard.UmiCmd.UMI_RESP_USER1", "UMI_RESP_USER1"], [1, 4, 1, "switchboard.UmiCmd.UMI_RESP_WRITE", "UMI_RESP_WRITE"], [1, 2, 1, "switchboard.UmiCmd.name", "name"], [1, 2, 1, "switchboard.UmiCmd.value", "value"]], "switchboard": [[2, 0, 0, "-", "bitvector"], [3, 0, 0, "-", "icarus"], [4, 0, 0, "-", "loopback"], [5, 0, 0, "-", "sbdut"], [6, 0, 0, "-", "sbtcp"], [7, 0, 0, "-", "uart_xactor"], [8, 0, 0, "-", "umi"], [9, 0, 0, "-", "util"], [10, 0, 0, "-", "verilator"]], "switchboard.bitvector": [[2, 1, 1, "", "BitVector"], [2, 5, 1, "", "slice_to_msb_lsb"]], "switchboard.bitvector.BitVector": [[2, 3, 1, "", "frombytes"], [2, 3, 1, "", "tobytes"]], "switchboard.icarus": [[3, 5, 1, "", "icarus_build_vpi"], [3, 5, 1, "", "icarus_find_vpi"], [3, 5, 1, "", "icarus_run"], [3, 5, 1, "", "run"]], "switchboard.loopback": [[4, 5, 1, "", "umi_loopback"]], "switchboard.sbdut": [[5, 1, 1, "", "SbDut"], [5, 5, 1, "", "carefully_add_plusarg"], [5, 5, 1, "", "metadata_str"]], "switchboard.sbdut.SbDut": [[5, 3, 1, "", "build"], [5, 3, 1, "", "find_package"], [5, 3, 1, "", "find_sim"], [5, 3, 1, "", "input_analog"], [5, 3, 1, "", "package"], [5, 3, 1, "", "simulate"], [5, 3, 1, "", "terminate"]], "switchboard.sbtcp": [[6, 5, 1, "", "bytes2sb"], [6, 5, 1, "", "convert_to_queue"], [6, 5, 1, "", "get_parser"], [6, 5, 1, "", "main"], [6, 5, 1, "", "normalize_inputs"], [6, 5, 1, "", "normalize_inputs_and_outputs"], [6, 5, 1, "", "normalize_outputs"], [6, 5, 1, "", "parse_rule"], [6, 5, 1, "", "rule_matches"], [6, 5, 1, "", "run_client"], [6, 5, 1, "", "run_server"], [6, 5, 1, "", "sb2bytes"], [6, 5, 1, "", "sb2tcp"], [6, 5, 1, "", "start_tcp_bridge"], [6, 5, 1, "", "tcp2sb"]], "switchboard.uart_xactor": [[7, 1, 1, "", "uart_xactor"]], "switchboard.uart_xactor.uart_xactor": [[7, 4, 1, "", "REGF_SR_RXEMPTY_MASK"], [7, 4, 1, "", "REGF_SR_RXFULL_MASK"], [7, 4, 1, "", "REGF_SR_TXEMPTY_MASK"], [7, 4, 1, "", "REGF_SR_TXFULL_MASK"], [7, 4, 1, "", "REG_RX"], [7, 4, 1, "", "REG_SR"], [7, 4, 1, "", "REG_TX"], [7, 3, 1, "", "read"], [7, 3, 1, "", "read_byte"], [7, 3, 1, "", "readline"], [7, 3, 1, "", "write"], [7, 3, 1, "", "write_byte"]], "switchboard.umi": [[8, 1, 1, "", "UmiTxRx"], [8, 5, 1, "", "addr_aligned"], [8, 5, 1, "", "check_int_in_range"], [8, 5, 1, "", "dtype2size"], [8, 5, 1, "", "nbytes2size"], [8, 5, 1, "", "random_int_value"], [8, 5, 1, "", "random_umi_packet"], [8, 5, 1, "", "size2dtype"]], "switchboard.umi.UmiTxRx": [[8, 3, 1, "", "atomic"], [8, 3, 1, "", "gpio"], [8, 3, 1, "", "init_queues"], [8, 3, 1, "", "read"], [8, 3, 1, "", "recv"], [8, 3, 1, "", "send"], [8, 3, 1, "", "write"], [8, 3, 1, "", "write_readback"]], "switchboard.util": [[9, 1, 1, "", "ProcessCollection"], [9, 5, 1, "", "binary_run"], [9, 5, 1, "", "plusargs_to_args"]], "switchboard.util.ProcessCollection": [[9, 3, 1, "", "add"], [9, 3, 1, "", "terminate"], [9, 3, 1, "", "wait"]], "switchboard.verilator": [[10, 5, 1, "", "verilator_run"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "property", "Python property"], "3": ["py", "method", "Python method"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "function", "Python function"]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:property", "3": "py:method", "4": "py:attribute", "5": "py:function"}, "terms": {"": 5, "0": [1, 2, 5, 6, 7, 8], "0x1234": 8, "0x2345": 8, "0x3456": 8, "1": [1, 5, 7, 8], "10": [1, 4, 5, 9], "1000000": 4, "100000000": 5, "11": 1, "12": 1, "13": 1, "14": 1, "15": 1, "2": [1, 7, 8], "256": 7, "3": 1, "32": [1, 8], "4": [1, 7, 8], "42": 5, "47": 1, "5": [1, 8], "512": 7, "5555": 6, "6": 1, "64": [1, 8], "7": [1, 5], "8": [1, 7, 8], "9": 1, "By": 8, "For": [5, 8], "If": [1, 4, 5, 8], "In": 5, "On": [1, 8], "The": [1, 5, 8], "These": 5, "To": 0, "_": 4, "_switchboard": 1, "about": 8, "abov": 5, "abstract": 5, "accept": [5, 6], "access": 8, "ack": 8, "action": 5, "add": [1, 5, 8, 9], "addit": 5, "addr": [1, 6, 8], "addr_align": [1, 8], "address": [1, 8], "after": 5, "align": 8, "all": [4, 5, 8], "allow": [5, 8], "also": [4, 8], "alwai": 8, "an": [1, 4, 5, 8], "ani": [1, 4, 5, 8], "appli": [1, 8], "appropri": 8, "approxim": 5, "ar": [1, 4, 5, 8], "arg": [5, 9, 10], "arg0": 1, "argpars": 5, "argument": [4, 5, 8], "arr": 2, "arrai": [1, 8], "ascii": 7, "assign": 8, "atom": [0, 1, 8], "attribut": 8, "atyp": [1, 8], "auto": 6, "automat": [1, 5, 8], "autowrap": 5, "avail": 5, "awai": 5, "b": [6, 7], "back": [4, 8], "bar_num": 1, "base": [1, 2, 5, 7, 8, 9], "basi": 8, "bdf": 1, "becaus": 5, "been": 1, "befor": [1, 5, 8], "being": 5, "below": 5, "between": 5, "bin": [9, 10], "binari": 5, "binary_run": [1, 9], "bit": [1, 5, 8], "bitvector": [0, 1], "block": [1, 4, 8], "bool": [1, 5, 8], "bu": 5, "build": [1, 5], "builddir": 5, "buildroot": 5, "burst": 8, "byte": [1, 8], "bytes2sb": [1, 6], "bytes_per_elem": 1, "bytesthat": 1, "c": 6, "call": 5, "can": [1, 4, 5, 8], "cannot": [1, 8], "care": 8, "carefully_add_plusarg": [1, 5], "case": [1, 5, 8], "cc": 5, "check": 4, "check_align": 8, "check_int_in_rang": [1, 8], "check_nam": 5, "checkout": 5, "chip": 5, "cinclud": 3, "cir": 5, "cl": 6, "class": [0, 1, 2, 5, 7, 8, 9], "clear": [1, 8], "client": 6, "clock": 5, "cmd": [0, 1], "cmdline": 5, "co": 5, "code": 5, "command": [1, 3, 5, 8], "commun": 8, "comparison": 8, "compil": 5, "complet": 5, "configur": 5, "conn": 6, "connect": 6, "consid": 5, "constant": 5, "constructor": [5, 8], "contain": [0, 1, 5, 8], "conveni": 4, "convers": 5, "convert": 5, "convert_to_queu": [1, 6], "correspond": [4, 5], "could": 8, "cover": 5, "creat": 5, "ctrl": 6, "current": [1, 5], "cwd": [3, 5, 9], "d": 8, "data": [0, 1, 8], "datatyp": [1, 8], "default": [1, 5, 8], "default_main": 5, "definit": 5, "delai": 5, "delet": 1, "delete_queu": [0, 1], "describ": 5, "design": 5, "destin": [0, 1, 8], "determin": [1, 8], "devic": 8, "dict": 5, "dictionari": [5, 8], "digit": 5, "dir": 5, "direct": 5, "directli": 4, "directori": 5, "disabl": 5, "displai": [1, 8], "document": 5, "doe": [4, 5, 8], "driven": 5, "driver": 5, "dstaddr": [0, 1, 8], "dtype": [1, 8], "dtype2s": [1, 8], "dump": 5, "e": [1, 4, 5, 8], "each": [5, 8], "either": [1, 8], "els": 8, "empti": [4, 5], "emul": 5, "enabl": 5, "encod": 7, "encourag": 5, "end": [7, 8], "entri": 5, "env": 9, "eof": [1, 8], "eom": [1, 8], "equival": 4, "error": [1, 8], "etc": [1, 4, 5, 8], "ex": [1, 8], "exampl": [0, 5, 8], "except": [4, 8], "exclus": 8, "execut": [1, 8], "exist": 5, "expect": 5, "explicitli": 8, "extra_arg": [3, 5], "fals": [1, 5, 6, 8, 9], "fast": 5, "field": [1, 5, 8], "file": 5, "filenam": 5, "find_packag": [1, 5], "find_sim": [1, 5], "first": 5, "fix": 5, "flag": [0, 1], "float": [1, 5, 8], "follow": 5, "found": 5, "fpga": 5, "frame": 8, "frequenc": 5, "fresh": [1, 8], "from": [1, 5, 8], "frombyt": [1, 2], "function": [0, 1, 2, 3, 4, 5, 6, 8, 9, 10], "functionwil": 1, "g": [1, 4, 5, 8], "gener": [4, 5, 8], "get": [0, 1, 8], "get_pars": [1, 6], "given": [1, 5, 8], "gpio": [1, 8], "guess": 5, "ha": [1, 5], "hand": [1, 8], "have": [4, 5, 8], "help": [4, 5], "here": 5, "high": 5, "host": 6, "how": 5, "howev": 8, "hz": 5, "i": [0, 1, 4, 5, 6, 8], "icaru": [0, 1, 5], "icarus_build_vpi": [1, 3], "icarus_find_vpi": [1, 3], "icarus_run": [1, 3], "idx": 1, "immedi": [1, 8], "implement": 5, "import": 5, "includ": [0, 5, 8], "index": 0, "indic": [1, 8], "individu": [1, 8], "individualumi": 1, "inform": 8, "inherit": 5, "init": [0, 1, 8], "init_queu": [1, 8], "initi": 5, "input": [1, 5, 6, 8], "input_analog": [1, 5], "insensit": [1, 8], "instanti": 5, "instead": 5, "int": [1, 2, 5, 8], "integ": [1, 8], "integr": [4, 8], "interact": 5, "interfac": 5, "intf_obj": 5, "involv": 5, "iter": 4, "its": 5, "iwidth": 8, "kei": [5, 8], "keyword": 5, "kwarg": [3, 4, 10], "larg": [4, 5], "larger": 1, "last": 8, "latenc": 5, "ldflag": 3, "len": [1, 8], "level": 5, "librari": 5, "like": 5, "line": 5, "list": [1, 3, 4, 5], "localhost": 6, "locat": 5, "logic": 5, "loop": 6, "loopback": [0, 1], "low": 5, "made": [5, 6], "mai": [1, 5, 8], "main": [1, 6], "make": [1, 5, 8], "mani": 5, "manual": 0, "mask": 8, "match": [4, 5], "max": [1, 8], "max_byt": [1, 8], "max_rat": [1, 5, 6, 8], "maximum": [1, 5, 8], "maxu": [1, 8], "mean": [1, 8], "meant": [0, 5], "member": 1, "memori": 4, "merg": [0, 1, 4], "messag": 8, "metadata_str": [1, 5], "might": 4, "min": [1, 8], "minu": [1, 8], "mix": 5, "mode": [1, 6, 8], "model": 5, "modul": [0, 1], "more": [1, 8], "multipl": [1, 8], "must": [1, 5, 8], "mybu": 5, "mycircuit": 5, "n": [2, 5, 7], "name": [0, 1, 3, 5, 8], "nbyte": 8, "nbytes2s": [1, 8], "ndarrai": 1, "need": [1, 5, 8], "non": 8, "none": [1, 2, 3, 5, 6, 8, 9, 10], "normalize_input": [1, 6], "normalize_inputs_and_output": [1, 6], "normalize_output": [1, 6], "notat": 5, "note": 5, "np": [1, 8], "num": 1, "num_or_datatyp": [1, 8], "num_or_datatypespecifi": 1, "num_or_dtyp": [1, 8], "num_or_dtypei": 1, "number": [1, 4, 5, 8], "numpi": [1, 8], "o": 8, "object": [1, 2, 5, 7, 8, 9], "off": [5, 8], "old": 1, "onc": 4, "one": [5, 8], "onli": [5, 8], "opcod": [1, 8], "oper": [1, 8], "option": [1, 5, 8], "origin": [1, 8], "other": [1, 5, 8], "otherwis": 8, "out": [1, 8], "output": [5, 6, 8], "overridden": [5, 8], "owidth": 8, "p": [6, 8], "packag": [0, 5], "packet": [1, 4, 8], "packetcan": 1, "packetcannot": 1, "page": 0, "paramet": [1, 2, 3, 4, 5, 8], "pars": 5, "parse_rul": [1, 6], "particular": 8, "pass": [4, 5], "path": [3, 5], "paus": [1, 8], "payload": 1, "per": 8, "perform": [4, 5, 8], "period": 5, "pin": 5, "place": [1, 8], "plain": [1, 8], "plugin": 1, "plusarg": [3, 5, 9, 10], "plusargs_to_arg": [1, 9], "popen": 5, "port": 6, "posit": 4, "possibl": 8, "post": [1, 8], "preced": 5, "press": 6, "prevent": 5, "print_command": 9, "prior": 1, "process": [5, 9], "processcollect": [1, 9], "produc": 5, "program": [5, 8], "progressbar": [1, 8], "progressbarin": 1, "properti": 1, "prot": [1, 8], "protect": [1, 8], "provid": [5, 8], "py_packet": 1, "pybind11": 1, "pybind11_object": 1, "pysbpacket": [0, 1], "pysbrx": [0, 1], "pysbrxpci": [0, 1], "pysbtx": [0, 1], "pysbtxpci": [0, 1], "python": 0, "pyumi": [0, 1], "pyumipacket": [0, 1, 8], "q": 6, "qo": [1, 8], "qualiti": [1, 8], "queue": [1, 8], "quiet": [6, 9], "rais": [4, 8], "random": 8, "random_int_valu": [1, 8], "random_umi_packet": [1, 4, 8], "randomli": 8, "rang": 4, "rate": 5, "rather": 5, "read": [0, 1, 7, 8], "read_byt": [1, 7], "readlin": [1, 7], "real": 5, "rebuilt": 5, "receiv": [1, 4, 8], "recv": [0, 1, 8], "refer": [0, 8], "reflect": 1, "reg_rx": [1, 7], "reg_sr": [1, 7], "reg_tx": [1, 7], "regf_sr_rxempty_mask": [1, 7], "regf_sr_rxfull_mask": [1, 7], "regf_sr_txempty_mask": [1, 7], "regf_sr_txfull_mask": [1, 7], "regular": 5, "relat": 8, "remain": 4, "report": 5, "repositori": 0, "repres": [4, 5], "represent": 1, "request": 8, "requir": 5, "reset": 5, "respons": [1, 8], "retri": 6, "return": [1, 3, 5, 8], "right": [1, 8], "rout": [1, 8], "rtl": 5, "rule": [4, 6], "rule_match": [1, 6], "run": [1, 3, 5], "run_client": [1, 6], "run_onc": 6, "run_serv": [1, 6], "rx": 1, "rx_uri": [1, 8], "same": [1, 5, 8], "save": 5, "sb2byte": [1, 6], "sb2tcp": [1, 6], "sbdut": [0, 1], "sbtcp": [0, 1], "scalar": [1, 8], "search": 0, "second": 5, "self": 1, "send": [0, 1, 4, 8], "sent": [1, 8], "separ": 8, "sequenc": [4, 8], "serv": 0, "server": 6, "servic": [1, 8], "set": [5, 8], "setup": 5, "share": 5, "should": [5, 8], "show": 5, "sign": 8, "signal": 5, "siliconcompil": 5, "simul": [1, 5, 8], "singl": [5, 8], "size": [1, 7, 8], "size2dtyp": [1, 8], "slice_to_msb_lsb": [1, 2], "slight": 5, "so": [1, 8], "some": [0, 5, 8], "sometim": [1, 5, 8], "sourc": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "specif": [4, 5, 8], "specifi": [1, 5, 8], "spice": 5, "split": [1, 4, 8], "srcaddr": [0, 1, 8], "start": [0, 2, 5], "start_delai": 5, "start_tcp_bridg": [1, 6], "static": 2, "stem": 5, "step": [2, 5], "stop": 2, "stop_timeout": [5, 9], "store": 4, "store_tru": 5, "str": [1, 3, 5, 8], "string": [1, 5, 7, 8], "subcircuit": 5, "subcompon": 5, "submodul": 0, "successfulli": [1, 8], "suffix": 5, "support": [1, 8], "sure": [1, 5, 8], "swap": [1, 8], "t": 5, "taken": 5, "tcp2sb": [1, 6], "termin": [1, 5, 8, 9], "test": [4, 5], "testbench": 5, "tf": 5, "than": [1, 5, 8], "thedefault": 1, "thei": [5, 8], "them": 4, "themselv": 5, "thi": [0, 1, 4, 5, 8], "thisi": 1, "those": 5, "thread": 5, "threshold": 5, "ti": 5, "tick": 5, "tieoff": 5, "time": 5, "timeprecis": 5, "timeunit": 5, "tobyt": [1, 2], "toe": 5, "tool": 5, "top": 5, "tr": 5, "trace": 5, "trace_typ": 5, "track": 8, "transact": [1, 4, 8], "transactor": 7, "transfer": 8, "transit": 5, "transmit": 4, "tri": 8, "true": [1, 5, 6, 8, 10], "tupl": [4, 5], "turn": [5, 8], "tx": 1, "tx_uri": [1, 8], "type": [1, 3, 5, 8], "typeerror": 8, "uart": 7, "uart_xactor": [0, 1], "uin16": [1, 8], "uint16": [1, 8], "uint32": [1, 8], "uint64": [1, 8], "uint8": [1, 8], "umi": [0, 1, 4, 7], "umi_atyp": [0, 1], "umi_eof": [0, 1], "umi_eom": [0, 1], "umi_ex": [0, 1], "umi_gpio": 8, "umi_invalid": [0, 1], "umi_len": [0, 1], "umi_loopback": [1, 4], "umi_opcod": [0, 1], "umi_opcode_to_str": [0, 1], "umi_pack": [0, 1], "umi_prot": [0, 1], "umi_qo": [0, 1], "umi_req_atom": [0, 1], "umi_req_atomicadd": [0, 1], "umi_req_atomicand": [0, 1], "umi_req_atomicmax": [0, 1], "umi_req_atomicmaxu": [0, 1], "umi_req_atomicmin": [0, 1], "umi_req_atomicminu": [0, 1], "umi_req_atomicor": [0, 1], "umi_req_atomicswap": [0, 1], "umi_req_atomicxor": [0, 1], "umi_req_error": [0, 1], "umi_req_future0": [0, 1], "umi_req_link": [0, 1], "umi_req_post": [0, 1], "umi_req_rdma": [0, 1], "umi_req_read": [0, 1], "umi_req_user0": [0, 1], "umi_req_writ": [0, 1], "umi_resp_future0": [0, 1], "umi_resp_future1": [0, 1], "umi_resp_link": [0, 1], "umi_resp_read": [0, 1], "umi_resp_user0": [0, 1], "umi_resp_user1": [0, 1], "umi_resp_writ": [0, 1], "umi_s": [0, 1], "umiatom": [0, 1, 8], "umicmd": [0, 1], "umigpio": 8, "umitxrx": [1, 4, 8], "under": 4, "unexpect": [1, 8], "until": [1, 6, 8], "unus": [1, 8], "up": 5, "upon": [1, 8], "uri": [1, 8], "us": [1, 4, 5, 8], "use_sigint": [5, 9, 10], "user": [5, 8], "util": [0, 1], "v": 8, "valu": [0, 1, 2, 5, 8], "valueerror": 4, "variabl": 5, "variou": 0, "vcd": 5, "veri": 4, "veril": [0, 1, 5], "verilator_run": [1, 10], "verilog": 5, "versa": 5, "via": [1, 5, 8], "vice": 5, "vih": 5, "vil": 5, "voh": 5, "vol": 5, "voltag": 5, "vvp": 3, "wa": 8, "wait": [1, 8, 9], "want": 4, "warn": 5, "waveform": 5, "when": [5, 8], "where": 5, "whether": 8, "which": [1, 4, 5, 8], "whichcas": 1, "width": 8, "without": 4, "word": 8, "work": 5, "world": 5, "wrapper": 5, "write": [0, 1, 7, 8], "write_byt": [1, 7], "write_readback": [1, 8], "write_srcaddr": 8, "written": [1, 5, 8], "x": 5, "xor": [1, 8], "xyce": 5, "you": 4}, "titles": ["Welcome to Switchboard\u2019s documentation!", "switchboard package", "switchboard.bitvector module", "switchboard.icarus module", "switchboard.loopback module", "switchboard.sbdut module", "switchboard.sbtcp module", "switchboard.uart_xactor module", "switchboard.umi module", "switchboard.util module", "switchboard.verilator module"], "titleterms": {"": 0, "bitvector": 2, "content": 0, "document": 0, "icaru": 3, "indic": 0, "loopback": 4, "modul": [2, 3, 4, 5, 6, 7, 8, 9, 10], "packag": 1, "sbdut": 5, "sbtcp": 6, "submodul": 1, "switchboard": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "tabl": 0, "uart_xactor": 7, "umi": 8, "util": 9, "veril": 10, "welcom": 0}}) \ No newline at end of file diff --git a/switchboard.bitvector.html b/switchboard.bitvector.html new file mode 100644 index 00000000..4029b4a6 --- /dev/null +++ b/switchboard.bitvector.html @@ -0,0 +1,194 @@ + + + + + + + switchboard.bitvector module — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

switchboard.bitvector module

+

Classes:

+ + + + + + +

BitVector([value])

+

Functions:

+ + + + + + +

slice_to_msb_lsb([start, stop, step])

+
+
+class switchboard.bitvector.BitVector(value=0)[source]
+

Bases: object

+
+
Parameters:
+

value (int)

+
+
+
+
+static frombytes(arr)[source]
+
+ +
+
+tobytes(n=None)[source]
+
+ +
+ +
+
+switchboard.bitvector.slice_to_msb_lsb(start=None, stop=None, step=None)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/switchboard.html b/switchboard.html new file mode 100644 index 00000000..207e2519 --- /dev/null +++ b/switchboard.html @@ -0,0 +1,918 @@ + + + + + + + switchboard package — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

switchboard package

+

switchboard pybind11 plugin

+

Classes:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

PySbPacket(self[, destination, flags, data])

PySbRx(self[, uri, fresh, max_rate])

PySbRxPcie(self[, uri, idx, bar_num, bdf])

PySbTx(self[, uri, fresh, max_rate])

PySbTxPcie(self[, uri, idx, bar_num, bdf])

PyUmi(self[, tx_uri, rx_uri, fresh, max_rate])

PyUmiPacket(self[, cmd, dstaddr, srcaddr, data])

UmiAtomic(self, value)

Members:

UmiCmd(self, value)

Members:

+

Functions:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

delete_queue(arg0)

Deletes an old queue.

delete_queues(arg0)

Deletes a old queues specified in a list.

umi_atype(arg0)

umi_eof(arg0)

umi_eom(arg0)

umi_ex(arg0)

umi_len(arg0)

umi_opcode(arg0)

umi_opcode_to_str(arg0)

Returns a string representation of a UMI opcode

umi_pack([opcode, atype, size, len, eom, ...])

Returns a UMI command with the given parameters.

umi_prot(arg0)

umi_qos(arg0)

umi_size(arg0)

+
+
+class _switchboard.PySbPacket(self: _switchboard.PySbPacket, destination: int = 0, flags: int = 0, data: numpy.ndarray[numpy.uint8] | None = None)
+

Bases: pybind11_object

+
+
+property data
+
+ +
+
+property destination
+
+ +
+
+property flags
+
+ +
+ +
+
+class _switchboard.PySbRx(self: _switchboard.PySbRx, uri: str = '', fresh: bool = False, max_rate: float = -1)
+

Bases: pybind11_object

+
+
+init(self: _switchboard.PySbRx, uri: str = '', fresh: bool = False, max_rate: float = -1) None
+
+
Parameters:
+
    +
  • uri (str Name of the queue for the Rx object)

  • +
  • fresh (bool, optional) – If True, the queue specified by the uri parameter will get cleared before executing the simulation.

  • +
+
+
+
+ +
+
+recv(self: _switchboard.PySbRx, blocking: bool = True) _switchboard.PySbPacket
+
+
Parameters:
+

blocking (bool, optional) – If true, the function will pause execution until a packetcan be read. If false, the function will return None if a packetcannot be read immediately

+
+
Returns:
+

Returns a UMI packet. If blocking is false, None will be returned If a packet cannot be read immediately.

+
+
Return type:
+

PySbPacket

+
+
+
+ +
+ +
+
+class _switchboard.PySbRxPcie(self: _switchboard.PySbRxPcie, uri: str = '', idx: int = 0, bar_num: int = 0, bdf: str = '')
+

Bases: pybind11_object

+
+
+init(self: _switchboard.PySbRxPcie, uri: str = '', idx: int = 0, bar_num: int = 0, bdf: str = '') None
+
+ +
+ +
+
+class _switchboard.PySbTx(self: _switchboard.PySbTx, uri: str = '', fresh: bool = False, max_rate: float = -1)
+

Bases: pybind11_object

+
+
+init(self: _switchboard.PySbTx, uri: str = '', fresh: bool = False, max_rate: float = -1) None
+
+
Parameters:
+
    +
  • uri (str) – Name of the queue for the Tx object

  • +
  • fresh (bool, optional) – If True, the queue specified by the uri parameter will get cleared before executing the simulation.

  • +
+
+
+
+ +
+
+send(self: _switchboard.PySbTx, py_packet: _switchboard.PySbPacket, blocking: bool = True) bool
+
+
Parameters:
+
    +
  • py_packet (PySbPacket) – UMI packet to send

  • +
  • blocking (bool, optional) – If true, the function will pause execution until the packet has been successfully sent.

  • +
+
+
+
+ +
+ +
+
+class _switchboard.PySbTxPcie(self: _switchboard.PySbTxPcie, uri: str = '', idx: int = 0, bar_num: int = 0, bdf: str = '')
+

Bases: pybind11_object

+
+
+init(self: _switchboard.PySbTxPcie, uri: str = '', idx: int = 0, bar_num: int = 0, bdf: str = '') None
+
+ +
+ +
+
+class _switchboard.PyUmi(self: _switchboard.PyUmi, tx_uri: str = '', rx_uri: str = '', fresh: bool = False, max_rate: float = -1)
+

Bases: pybind11_object

+
+
+atomic(self: _switchboard.PyUmi, addr: int, data: numpy.ndarray[numpy.uint8], opcode: int, srcaddr: int = 0, qos: int = 0, prot: int = 0, error: bool = True) numpy.ndarray
+
+
Parameters:
+
    +
  • addr (int) – 64-bit address atomic operation will be applied to.

  • +
  • data (np.uint8, np.uint16, np.uint32, np.uint64) – must so that the size of the atomic operation can be determined.

  • +
  • opcode (str or switchboard.UmiAtomic value) – Supported string values are ‘add’, ‘and’, ‘or’, ‘xor’, ‘max’, ‘min’, ‘minu’, ‘maxu’, and ‘swap’ (case-insensitive).

  • +
  • srcaddr (int, optional) – The UMI source address used for the atomic transaction. This is sometimes needed to make sure the response get routed to the right place.

  • +
  • qos (int, optional) – 4-bit Quality of Service field in UMI Command

  • +
  • prot (int, optional) – 2-bit protection mode field in UMI command

  • +
  • error (bool, optional) – If true, error out upon receiving an unexpected UMI response.

  • +
+
+
Returns:
+

The value returned by this function is the original value at addr, immediately before the atomic operation is applied. The numpy dtype of the returned value will be the same as for data.

+
+
Return type:
+

np.uint8, np.uint16, np.uint32, np.uint64

+
+
+
+ +
+
+init(self: _switchboard.PyUmi, tx_uri: str = '', rx_uri: str = '', fresh: bool = False, max_rate: float = -1) None
+
+
Parameters:
+
    +
  • tx_uri (str, optional) – Name of the switchboard queue that write() and send() will send UMI packets to. Defaults to None, meaning “unused”.

  • +
  • rx_uri (str, optional) – Name of the switchboard queue that read() and recv() will receive UMI packets from. Defaults to None, meaning “unused”.

  • +
  • fresh (bool, optional) – If true, the tx_uri and rx_uri will be cleared prior to running

  • +
+
+
+
+ +
+
+read(self: _switchboard.PyUmi, addr: int, num: int, bytes_per_elem: int = 1, srcaddr: int = 0, max_bytes: int = 32, qos: int = 0, prot: int = 0, error: bool = True) numpy.ndarray
+
+
Parameters:
+
    +
  • addr (int) – The 64-bit address read from

  • +
  • num_or_dtype (int or numpy integer datatype) – If a plain int, num_or_datatype specifies the number of bytes to be read.If a numpy integer datatype (np.uint8, np.uint16, etc.), num_or_datatypespecifies the data type to be returned.

  • +
  • dtype (numpy integer datatype, optional) – If num_or_dtype is a plain integer, the value returned by this functionwill be a numpy array of type dtype. On the other hand, if num_or_dtypeis a numpy datatype, the value returned will be a scalar of that datatype.

  • +
  • srcaddr (int, optional) – The UMI source address used for the read transaction. Thisis sometimes needed to make sure that reads get routed to the right place.

  • +
  • max_bytes (int, optional) – Indicates the maximum number of bytes that can be used for any individualUMI transaction. num_or_dtype can be larger than max_bytes, in whichcase the read will automatically be split into multiple transactions. Currently,the data payload size used by switchboard is 32 bytes, which is reflected in thedefault value of max_bytes.

  • +
  • qos (int, optional) – 4-bit Quality of Service field in UMI Command

  • +
  • prot (int, optional) – 2-bit protection mode field in UMI command

  • +
  • error (bool, optional) – If true, error out upon receiving an unexpected UMI response.

  • +
+
+
+
+ +
+
+recv(self: _switchboard.PyUmi, blocking: bool = True) _switchboard.PyUmiPacket
+
+
Parameters:
+

blocking (bool, optional) – If true, the function will pause execution until a packetcan be read. If false, the function will return None if a packetcannot be read immediately

+
+
Returns:
+

Returns a UMI packet. If blocking is false, None will be returned If a packet cannot be read immediately.

+
+
Return type:
+

PySbPacket

+
+
+
+ +
+
+send(self: _switchboard.PyUmi, py_packet: _switchboard.PyUmiPacket, blocking: bool = True) bool
+
+
Parameters:
+
    +
  • py_packet (PySbPacket) – UMI packet to send

  • +
  • blocking (bool, optional) – If true, the function will pause execution until the packet has been successfully sent.

  • +
+
+
+
+ +
+
+write(self: _switchboard.PyUmi, addr: int, data: numpy.ndarray, srcaddr: int = 0, max_bytes: int = 32, posted: bool = False, qos: int = 0, prot: int = 0, progressbar: bool = False, error: bool = True) None
+
+
Parameters:
+
    +
  • addr (int) – 64-bit address that will be written to

  • +
  • data (np.uint8, np.uint16, np.uint32, np.uint64, or np.array) – Can be either a numpy integer type (e.g., np.uint32) or an numpy array of integer types (np.uint8, np.uin16, np.uint32, np.uint64, etc.). The data input may contain more than max_bytes, in which case the write will automatically be split into multiple transactions.

  • +
  • srcaddr (int, optional) – UMI source address used for the write transaction. This is sometimes needed to make the write response gets routed to the right place.

  • +
  • max_bytes (int, optional) – Indicates the maximum number of bytesthat can be used for any individual UMI transaction in bytes. Currently, the data payload size used by switchboard is 32 bytes, which is reflected in the default value of max_bytes.

  • +
  • posted (bool, optional) – If True, a write response will be received.

  • +
  • qos (int, optional) – 4-bit Quality of Service field in UMI Command

  • +
  • prot (int, optional) – 2-bit protection mode field in UMI command

  • +
  • progressbar (bool, optional) – If True, the number of packets written will be displayed via a progressbarin the terminal.

  • +
  • error (bool, optional) – If true, error out upon receiving an unexpected UMI response.

  • +
+
+
+
+ +
+ +
+
+class _switchboard.PyUmiPacket(self: _switchboard.PyUmiPacket, cmd: int = 0, dstaddr: int = 0, srcaddr: int = 0, data: numpy.ndarray | None = None)
+

Bases: pybind11_object

+
+
+property cmd
+
+ +
+
+property data
+
+ +
+
+property dstaddr
+
+ +
+
+merge(self: _switchboard.PyUmiPacket, arg0: _switchboard.PyUmiPacket) bool
+
+ +
+
+property srcaddr
+
+ +
+ +
+
+class _switchboard.UmiAtomic(self: _switchboard.UmiAtomic, value: int)
+

Bases: pybind11_object

+

Members:

+

UMI_REQ_ATOMICADD

+

UMI_REQ_ATOMICAND

+

UMI_REQ_ATOMICOR

+

UMI_REQ_ATOMICXOR

+

UMI_REQ_ATOMICMAX

+

UMI_REQ_ATOMICMIN

+

UMI_REQ_ATOMICMAXU

+

UMI_REQ_ATOMICMINU

+

UMI_REQ_ATOMICSWAP

+
+
+UMI_REQ_ATOMICADD = <UmiAtomic.UMI_REQ_ATOMICADD: 0>
+
+ +
+
+UMI_REQ_ATOMICAND = <UmiAtomic.UMI_REQ_ATOMICAND: 1>
+
+ +
+
+UMI_REQ_ATOMICMAX = <UmiAtomic.UMI_REQ_ATOMICMAX: 4>
+
+ +
+
+UMI_REQ_ATOMICMAXU = <UmiAtomic.UMI_REQ_ATOMICMAXU: 6>
+
+ +
+
+UMI_REQ_ATOMICMIN = <UmiAtomic.UMI_REQ_ATOMICMIN: 5>
+
+ +
+
+UMI_REQ_ATOMICMINU = <UmiAtomic.UMI_REQ_ATOMICMINU: 7>
+
+ +
+
+UMI_REQ_ATOMICOR = <UmiAtomic.UMI_REQ_ATOMICOR: 2>
+
+ +
+
+UMI_REQ_ATOMICSWAP = <UmiAtomic.UMI_REQ_ATOMICSWAP: 8>
+
+ +
+
+UMI_REQ_ATOMICXOR = <UmiAtomic.UMI_REQ_ATOMICXOR: 3>
+
+ +
+
+property name
+
+ +
+
+property value
+
+ +
+ +
+
+class _switchboard.UmiCmd(self: _switchboard.UmiCmd, value: int)
+

Bases: pybind11_object

+

Members:

+

UMI_INVALID

+

UMI_REQ_READ

+

UMI_REQ_WRITE

+

UMI_REQ_POSTED

+

UMI_REQ_RDMA

+

UMI_REQ_ATOMIC

+

UMI_REQ_USER0

+

UMI_REQ_FUTURE0

+

UMI_REQ_ERROR

+

UMI_REQ_LINK

+

UMI_RESP_READ

+

UMI_RESP_WRITE

+

UMI_RESP_USER0

+

UMI_RESP_USER1

+

UMI_RESP_FUTURE0

+

UMI_RESP_FUTURE1

+

UMI_RESP_LINK

+
+
+UMI_INVALID = <UmiCmd.UMI_INVALID: 0>
+
+ +
+
+UMI_REQ_ATOMIC = <UmiCmd.UMI_REQ_ATOMIC: 9>
+
+ +
+
+UMI_REQ_ERROR = <UmiCmd.UMI_REQ_ERROR: 15>
+
+ +
+
+UMI_REQ_FUTURE0 = <UmiCmd.UMI_REQ_FUTURE0: 13>
+
+ +
+ +
+ +
+
+UMI_REQ_POSTED = <UmiCmd.UMI_REQ_POSTED: 5>
+
+ +
+
+UMI_REQ_RDMA = <UmiCmd.UMI_REQ_RDMA: 7>
+
+ +
+
+UMI_REQ_READ = <UmiCmd.UMI_REQ_READ: 1>
+
+ +
+
+UMI_REQ_USER0 = <UmiCmd.UMI_REQ_USER0: 11>
+
+ +
+
+UMI_REQ_WRITE = <UmiCmd.UMI_REQ_WRITE: 3>
+
+ +
+
+UMI_RESP_FUTURE0 = <UmiCmd.UMI_RESP_FUTURE0: 10>
+
+ +
+
+UMI_RESP_FUTURE1 = <UmiCmd.UMI_RESP_FUTURE1: 12>
+
+ +
+ +
+ +
+
+UMI_RESP_READ = <UmiCmd.UMI_RESP_READ: 2>
+
+ +
+
+UMI_RESP_USER0 = <UmiCmd.UMI_RESP_USER0: 6>
+
+ +
+
+UMI_RESP_USER1 = <UmiCmd.UMI_RESP_USER1: 8>
+
+ +
+
+UMI_RESP_WRITE = <UmiCmd.UMI_RESP_WRITE: 4>
+
+ +
+
+property name
+
+ +
+
+property value
+
+ +
+ +
+
+_switchboard.delete_queue(arg0: str) None
+

Deletes an old queue.

+
+ +
+
+_switchboard.delete_queues(arg0: list[str]) None
+

Deletes a old queues specified in a list.

+
+ +
+
+_switchboard.umi_atype(arg0: int) int
+
+ +
+
+_switchboard.umi_eof(arg0: int) int
+
+ +
+
+_switchboard.umi_eom(arg0: int) int
+
+ +
+
+_switchboard.umi_ex(arg0: int) int
+
+ +
+
+_switchboard.umi_len(arg0: int) int
+
+ +
+
+_switchboard.umi_opcode(arg0: int) int
+
+ +
+
+_switchboard.umi_opcode_to_str(arg0: int) str
+

Returns a string representation of a UMI opcode

+
+ +
+
+_switchboard.umi_pack(opcode: int = 0, atype: int = 0, size: int = 0, len: int = 0, eom: int = 1, eof: int = 1, qos: int = 0, prot: int = 0, ex: int = 0) int
+

Returns a UMI command with the given parameters.

+
+ +
+
+_switchboard.umi_prot(arg0: int) int
+
+ +
+
+_switchboard.umi_qos(arg0: int) int
+
+ +
+
+_switchboard.umi_size(arg0: int) int
+
+ +
+

Submodules

+
+ +
+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/switchboard.icarus.html b/switchboard.icarus.html new file mode 100644 index 00000000..168afdac --- /dev/null +++ b/switchboard.icarus.html @@ -0,0 +1,226 @@ + + + + + + + switchboard.icarus module — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

switchboard.icarus module

+

Functions:

+ + + + + + + + + + + + + + + +

icarus_build_vpi([cwd, name, cincludes, ldflags])

icarus_find_vpi([cwd, name])

icarus_run(vvp[, plusargs, modules, extra_args])

run(command[, cwd])

+
+
+switchboard.icarus.icarus_build_vpi(cwd=None, name='switchboard', cincludes=None, ldflags=None)[source]
+
+
Parameters:
+
    +
  • cwd (str)

  • +
  • name (str)

  • +
  • cincludes (List[str])

  • +
  • ldflags (List[str])

  • +
+
+
Return type:
+

str

+
+
+
+ +
+
+switchboard.icarus.icarus_find_vpi(cwd=None, name='switchboard')[source]
+
+
Parameters:
+
    +
  • cwd (str | Path)

  • +
  • name (str)

  • +
+
+
Return type:
+

Path

+
+
+
+ +
+
+switchboard.icarus.icarus_run(vvp, plusargs=None, modules=None, extra_args=None, **kwargs)[source]
+
+ +
+
+switchboard.icarus.run(command, cwd=None)[source]
+
+
Parameters:
+
    +
  • command (list)

  • +
  • cwd (str)

  • +
+
+
Return type:
+

str

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/switchboard.loopback.html b/switchboard.loopback.html new file mode 100644 index 00000000..8a4c3819 --- /dev/null +++ b/switchboard.loopback.html @@ -0,0 +1,192 @@ + + + + + + + switchboard.loopback module — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

switchboard.loopback module

+

Functions:

+ + + + + + +

umi_loopback(umi[, packets])

Performs a loopback test by sending packets into a block and checking that the packets received back are equivalent under the UMI split/merge rules.

+
+
+switchboard.loopback.umi_loopback(umi, packets=10, **kwargs)[source]
+

Performs a loopback test by sending packets into a block and checking that +the packets received back are equivalent under the UMI split/merge rules.

+
+
Parameters:
+
    +
  • umi (UmiTxRx)

  • +
  • packets (Integral | Iterable | Iterator) –

    Can be a number, a list of packets, or a generator.

    +
      +
    • If this is a number, it represents the number of packets to send, +which are generated with random_umi_packet. Any remaining arguments +are passed directly to random_umi_packet.

    • +
    • If this is an iterable (list, tuple, etc.), then it represents a list +of packets to use for the test. This is helpful if you want to use a very +specific sequence of transactions.

    • +
    • This can also be an iterator, which might be convenient if you want to +send a very large number of packets without having to store them +all in memory at once, e.g. (random_umi_packet() for _ in range(1000000))

    • +
    +

  • +
+
+
Raises:
+
    +
  • ValueError – If the number of packets is not positive or if the packets argument is empty

  • +
  • Exception – If a received packet does not match the corresponding transmitted packet

  • +
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/switchboard.sbdut.html b/switchboard.sbdut.html new file mode 100644 index 00000000..0406fd41 --- /dev/null +++ b/switchboard.sbdut.html @@ -0,0 +1,370 @@ + + + + + + + switchboard.sbdut module — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

switchboard.sbdut module

+

Note that the sbdut module inherits functions from siliconcompiler.Chips, such as input() used to add rtl files to the simulation and add() used to add include directories to the simulation. These functions are important for specifying the RTL files used in a simulation, but they are not covered in the documentation here. For a complete list of the the inherited functions, checkout the siliconcompiler documentation.

+

Class inheriting from the SiliconCompiler Chip class that can be used for building a +Switchboard-based testbench.

+

This class is meant to be interacted with like a regular Chip object, but it has some parameters +automatically configured to abstract away setup of files that are required by all Switchboard +testbenches.

+

Classes:

+ + + + + + +

SbDut([design, tool, default_main, trace, ...])

+

Functions:

+ + + + + + + + + +

carefully_add_plusarg(key, args, plusargs[, ...])

metadata_str(design[, tool, trace, ...])

+
+
+class switchboard.sbdut.SbDut(design='testbench', tool='verilator', default_main=True, trace=True, trace_type='vcd', module=None, fpga=False, xyce=False, frequency=100000000.0, period=None, max_rate=-1, start_delay=None, timeunit=None, timeprecision=None, warnings=None, cmdline=False, fast=False, extra_args=None, autowrap=False, parameters=None, interfaces=None, clocks=None, resets=None, tieoffs=None, buildroot=None, builddir=None, args=None, subcomponent=False, suffix=None, threads=None)[source]
+

Bases: Chip

+
+
Parameters:
+
    +
  • design (string) – Name of the top level chip design module.

  • +
  • tool (string, optional) – Which tool to use to compile simulator. Options are “verilator” or +“icarus”.

  • +
  • default_main (bool, optional) – If True, the default testbench.cc will be used and does not need to +be provided via the add() function

  • +
  • trace (bool, optional) – If true, a waveform dump file will be produced using the file type +specified by trace_type.

  • +
  • trace_type (str, optional) – File type for the waveform dump file. Defaults to vcd.

  • +
  • module (str, optional) – module containing the siliconcompiler driver for this object

  • +
  • fpga (bool, optional) – If True, compile using switchboard’s library of modules for FPGA emulation, +rather than the modules for RTL simulation.

  • +
  • xyce (bool, optional) – If True, compile for xyce co-simulation.

  • +
  • frequency (float, optional) – If provided, the default frequency of the clock generated in the testbench, +in seconds.

  • +
  • period (float, optional) – If provided, the default period of the clock generated in the testbench, +in seconds.

  • +
  • max_rate (float, optional) – If provided, the maximum real-world rate that the simulation is allowed to run +at, in Hz. Can be useful to encourage time-sharing between many processes and +for performance modeling when latencies are large and/or variable.

  • +
  • start_delay (float, optional) – If provided, the real-world time to delay before the first clock tick in the +simulation. Can be useful to make sure that programs start at approximately +the same time and to prevent simulations from stepping on each other’s toes +when starting up.

  • +
  • warnings (List[str], optional) – If provided, a list of tool-specific warnings to enable. If not provided, a default +set of warnings will be included. Warnings can be disabled by setting this argument +to an empty list.

  • +
  • cmdline (bool, optional) – If True, accept configuration settings from the command line, such as “–trace”, +“–tool TOOL”, and “–fast”.

  • +
  • fast (bool, optional) – If True, the simulation binary will not be rebuilt if an existing one is found. +The setting here can be overridden when build() is called by setting its argument +with the same name.

  • +
  • extra_args (dict, optional) – If provided and cmdline=True, a dictionary of additional command line arguments +to be made available. The keys of the dictionary are the arguments (“-n”, “–test”, +etc.) and the values are themselves dictionaries that contain keyword arguments +accepted by argparse (“action”: “store_true”, “default”: 42, etc.)

  • +
  • timeunit (str)

  • +
  • timeprecision (str)

  • +
  • autowrap (bool)

  • +
+
+
+
+
+build(cwd=None, fast=None)[source]
+
+
Parameters:
+
    +
  • cwd (str, optional) – Working directory for the simulation build

  • +
  • fast (bool, optional) – If True, the simulation binary will not be rebuilt if an existing one +is found. Defaults to the value provided to the SbDut constructor, +which in turn defaults to False.

  • +
+
+
+
+ +
+
+find_package(suffix=None)[source]
+
+ +
+
+find_sim()[source]
+
+ +
+
+input_analog(filename, pins=None, name=None, check_name=True, dir=None)[source]
+

Specifies a SPICE subcircuit to be used in a mixed-signal simulation. This involves +providing the path to the SPICE file containing the subcircuit definition and describing +how real-valued outputs in the SPICE subcircuit should be converted to binary values in +the Verilog simulation (and vice versa for subcircuit inputs).

+

Each of these conversions is specified as an entry in the “pins” argument, which is a +list of dictionaries, each representing a single pin of the SPICE subcircuit. Each +dictionary may have the following keys: +* “name”: name of the pin. Bus notation may be used, e.g. “myBus[7:0]”. In that case, +it is expected that the SPICE subcircuit has pins corresponding to each bit in the bus, +e.g. “myBus[0]”, “myBus[1]”, etc. +* “type”: direction of the pin. May be “input”, “output”, or “constant”. If “constant”, +then this pin will not show up the Verilog module definition to be instantiated in user +code. Instead, the SPICE subcircuit pin with that name will be tied off to a fixed +voltage specified in the “value” field (below). +* “vil”: low voltage threshold, below which a real-number voltage from the SPICE +simulation is considered to be a logical “0”. +* “vih”: high voltage threshold, above which a real-number voltage from the SPICE +simulation is considered to be a logical “1”. +* “vol”: real-number voltage to pass to a SPICE subcircuit input when the digital value +driven is “0”. +* “voh”: real-number voltage to pass to a SPICE subcircuit input when the digital value +driven is “1”. +* “tr”: time taken in the SPICE simulation to transition from a logic “0” value to a +logic “1” value. +* “tf”: time taken in the SPICE simulation to transition from a logic “1” value to a +logic “0” value. +* “initial”: initial value of a SPICE subcircuit pin. Currently only implemented for +subcircuit outputs. This is sometimes helpful, because there is a slight delay between +t=0 and the time when the SPICE simulation reports values for its outputs. Specifying +“initial” for subcircuit outputs prevents the corresponding digital signals from being +driven to “X” at t=0.

+
+
Parameters:
+
    +
  • filename (str) – The path of the SPICE file containing the subcircuit definition.

  • +
  • pins (List[Dict[str, Any]]) – List of dictionaries, each describing a pin of the subcircuit.

  • +
  • name (str) – Name of the SPICE subcircuit that will be instantiated in the mixed-signal simulation. +If not provided, Switchboard guesses that the name is filename stem. For example, +if filename=”myCircuit.cir”, then Switchboard will guess that the subcircuit name +is “myCircuit”

  • +
  • check_name (bool) – If True (default), Switchboard parses the provided file to make sure that there +is a subcircuit definition matching the given name.

  • +
  • dir (str) – Running a mixed-signal simulation involves creating SPICE and Verilog wrappers. This +argument specifies the directory where those wrappers should be written. If not +provided, defaults to the directory where filename is located.

  • +
+
+
+
+ +
+
+package(suffix=None, fast=None)[source]
+
+ +
+
+simulate(plusargs=None, args=None, extra_args=None, cwd=None, trace=None, period=None, frequency=None, max_rate=None, start_delay=None, run=None, intf_objs=True)[source]
+
+
Parameters:
+
    +
  • plusargs (str or list or tuple, optional) – additional arguments to pass to simulator that must be preceded +with a +. These are listed after args.

  • +
  • args (str or list or tuple, optional) – additional arguments to pass to simulator listed before plusargs and +extra_args

  • +
  • extra_args (str or list or tuple, optional) – additional arguments to pass to simulator listed after args and +plusargs

  • +
  • cwd (str, optional) – working directory where simulation binary is saved

  • +
  • trace (bool, optional) – If true, a waveform dump file will be produced

  • +
  • period (float, optional) – If provided, the period of the clock generated in the testbench, +in seconds.

  • +
  • frequency (float)

  • +
  • max_rate (float)

  • +
  • start_delay (float)

  • +
  • run (str)

  • +
  • intf_objs (bool)

  • +
+
+
Return type:
+

Popen

+
+
+
+ +
+
+terminate(stop_timeout=10, use_sigint=False)[source]
+
+ +
+ +
+
+switchboard.sbdut.carefully_add_plusarg(key, args, plusargs, value=None)[source]
+
+ +
+
+switchboard.sbdut.metadata_str(design, tool=None, trace=False, trace_type=None, threads=None, parameters=None)[source]
+
+
Parameters:
+
    +
  • design (str)

  • +
  • tool (str)

  • +
  • trace (bool)

  • +
  • trace_type (str)

  • +
  • threads (int)

  • +
  • parameters (dict)

  • +
+
+
Return type:
+

Path

+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/switchboard.sbtcp.html b/switchboard.sbtcp.html new file mode 100644 index 00000000..ab2846c4 --- /dev/null +++ b/switchboard.sbtcp.html @@ -0,0 +1,290 @@ + + + + + + + switchboard.sbtcp module — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

switchboard.sbtcp module

+

Functions:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

bytes2sb(b)

convert_to_queue(q, cls[, max_rate])

get_parser()

main()

normalize_inputs(inputs, max_rate)

normalize_inputs_and_outputs(inputs, ...)

normalize_outputs(outputs, max_rate)

parse_rule(rule)

rule_matches(rule, addr)

run_client(host, port[, quiet, max_rate, ...])

Connect to a server, retrying until a connection is made.

run_server(host[, port, quiet, max_rate, ...])

Accepts client connections in a loop until Ctrl-C is pressed.

sb2bytes(p)

sb2tcp(inputs, conn)

start_tcp_bridge([inputs, outputs, host, ...])

tcp2sb(outputs, conn)

+
+
+switchboard.sbtcp.bytes2sb(b)[source]
+
+ +
+
+switchboard.sbtcp.convert_to_queue(q, cls, max_rate=None)[source]
+
+ +
+
+switchboard.sbtcp.get_parser()[source]
+
+ +
+
+switchboard.sbtcp.main()[source]
+
+ +
+
+switchboard.sbtcp.normalize_inputs(inputs, max_rate)[source]
+
+ +
+
+switchboard.sbtcp.normalize_inputs_and_outputs(inputs, outputs, max_rate)[source]
+
+ +
+
+switchboard.sbtcp.normalize_outputs(outputs, max_rate)[source]
+
+ +
+
+switchboard.sbtcp.parse_rule(rule)[source]
+
+ +
+
+switchboard.sbtcp.rule_matches(rule, addr)[source]
+
+ +
+
+switchboard.sbtcp.run_client(host, port, quiet=False, max_rate=None, inputs=None, outputs=None, run_once=False)[source]
+

Connect to a server, retrying until a connection is made.

+
+ +
+
+switchboard.sbtcp.run_server(host, port=0, quiet=False, max_rate=None, run_once=False, outputs=None, inputs=None)[source]
+

Accepts client connections in a loop until Ctrl-C is pressed.

+
+ +
+
+switchboard.sbtcp.sb2bytes(p)[source]
+
+ +
+
+switchboard.sbtcp.sb2tcp(inputs, conn)[source]
+
+ +
+
+switchboard.sbtcp.start_tcp_bridge(inputs=None, outputs=None, host='localhost', port=5555, quiet=True, max_rate=None, mode='auto', run_once=False)[source]
+
+ +
+
+switchboard.sbtcp.tcp2sb(outputs, conn)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/switchboard.uart_xactor.html b/switchboard.uart_xactor.html new file mode 100644 index 00000000..1c33f4d2 --- /dev/null +++ b/switchboard.uart_xactor.html @@ -0,0 +1,226 @@ + + + + + + + switchboard.uart_xactor module — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

switchboard.uart_xactor module

+

UMI/UART Transactor.

+

Classes:

+ + + + + + +

uart_xactor(umi[, encoding])

+
+
+class switchboard.uart_xactor.uart_xactor(umi, encoding='ascii')[source]
+

Bases: object

+
+
+REGF_SR_RXEMPTY_MASK = 1
+
+ +
+
+REGF_SR_RXFULL_MASK = 2
+
+ +
+
+REGF_SR_TXEMPTY_MASK = 256
+
+ +
+
+REGF_SR_TXFULL_MASK = 512
+
+ +
+
+REG_RX = 4
+
+ +
+
+REG_SR = 8
+
+ +
+
+REG_TX = 0
+
+ +
+
+read(size=1)[source]
+
+ +
+
+read_byte()[source]
+
+ +
+
+readline(size=-1, end='\n')[source]
+
+ +
+
+write(string)[source]
+
+ +
+
+write_byte(b)[source]
+
+ +
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/switchboard.umi.html b/switchboard.umi.html new file mode 100644 index 00000000..dad68e04 --- /dev/null +++ b/switchboard.umi.html @@ -0,0 +1,537 @@ + + + + + + + switchboard.umi module — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

switchboard.umi module

+

Classes:

+ + + + + + +

UmiTxRx([tx_uri, rx_uri, srcaddr, posted, ...])

+

Functions:

+ + + + + + + + + + + + + + + + + + + + + + + + +

addr_aligned(addr, align)

check_int_in_range(name, value[, min, max])

dtype2size(dtype)

nbytes2size(nbytes)

random_int_value(name, value, min, max[, align])

random_umi_packet([opcode, len, size, ...])

Generates a Random UMI packet.

size2dtype(size[, signed, float])

+
+
+class switchboard.umi.UmiTxRx(tx_uri=None, rx_uri=None, srcaddr=0, posted=False, max_bytes=None, fresh=False, error=True, max_rate=-1)[source]
+

Bases: object

+
+
Parameters:
+
    +
  • tx_uri (str, optional) – Name of the switchboard queue that +write() and send() will send UMI packets to. Defaults to +None, meaning “unused”.

  • +
  • rx_uri (str, optional) – Name of the switchboard queue that +read() and recv() will receive UMI packets from. Defaults +to None, meaning “unused”.

  • +
  • srcaddr (int, optional) – Default srcaddr to use for reads, +ack’d writes, and atomics. Defaults to 0. Can also be +provided as a dictionary with separate defaults for each +type of transaction: srcaddr={‘read’: 0x1234, ‘write’: +0x2345, ‘atomic’: 0x3456}. When the defaults are provided +with a dictionary, all keys are optional. Transactions +that are not specified in the dictionary will default +to a srcaddr of 0.

  • +
  • posted (bool, optional) – If True, default to using posted +(i.e., non-ack’d) writes. This can be overridden on a +transaction-by-transaction basis. Defaults to False.

  • +
  • max_bytes (int, optional) – Default maximum number of bytes +to use in each UMI transaction. Can be overridden on a +transaction-by-transaction basis. Defaults to 32 bytes.

  • +
  • fresh (bool, optional) – If True, the queue specified by the uri parameter will get +cleared before executing the simulation.

  • +
  • error (bool, optional) – If True, error out upon receiving an unexpected UMI response.

  • +
  • max_rate (float)

  • +
+
+
+
+
+atomic(addr, data, opcode, srcaddr=None, qos=0, prot=0, error=None)[source]
+
+
Parameters:
+
    +
  • addr (int) – 64-bit address atomic operation will be applied to.

  • +
  • data (np.uint8, np.uint16, np.uint32, np.uint64) – must so that the size of the atomic operation can be determined.

  • +
  • opcode (str or switchboard.UmiAtomic value) – Supported string values are ‘add’, ‘and’, ‘or’, ‘xor’, ‘max’, ‘min’, +‘minu’, ‘maxu’, and ‘swap’ (case-insensitive).

  • +
  • srcaddr (int, optional) – The UMI source address used for the atomic transaction. This +is sometimes needed to make sure the response get routed to the right place.

  • +
  • qos (int, optional) – 4-bit Quality of Service field used in the UMI command

  • +
  • prot (int, optional) – 2-bit Protection mode field used in the UMI command

  • +
  • error (bool, optional) – If True, error out upon receiving an unexpected UMI response.

  • +
+
+
Raises:
+

TypeError – If value is not a numpy integer datatype

+
+
Returns:
+

The value returned by this function is the original value at addr, +immediately before the atomic operation is applied. The numpy dtype of the +returned value will be the same as for “data”.

+
+
Return type:
+

np.uint8, np.uint16, np.uint32, np.uint64

+
+
+
+ +
+
+gpio(iwidth=32, owidth=32, init=0, dstaddr=0, srcaddr=0, posted=False, max_bytes=32)[source]
+

Returns an object for communicating with umi_gpio modules.

+
+
Parameters:
+
    +
  • iwidth (int) – Width of GPIO input (bits). Defaults to 32.

  • +
  • owidth (int) – Width of GPIO output (bits). Defaults to 32.

  • +
  • init (int) – Default value of GPIO output. Defaults to 0.

  • +
  • dstaddr (int) – Base address of the GPIO device. Defaults to 0.

  • +
  • srcaddr (int) – Source address to which responses should be routed. Defaults to 0.

  • +
  • posted (bool) – Whether writes should be sent as posted. Defaults to False.

  • +
  • max_bytes (int) – Maximum number of bytes in a single transaction to umi_gpio.

  • +
+
+
Returns:
+

UmiGpio object with .i (input) and .o (output) attributes

+
+
Return type:
+

UmiGpio

+
+
+
+ +
+
+init_queues(tx_uri=None, rx_uri=None, fresh=False)[source]
+
+
Parameters:
+
    +
  • tx_uri (str, optional) – Name of the switchboard queue that +write() and send() will send UMI packets to. Defaults to +None, meaning “unused”.

  • +
  • rx_uri (str, optional) – Name of the switchboard queue that +read() and recv() will receive UMI packets from. Defaults +to None, meaning “unused”.

  • +
  • fresh (bool, optional) – If True, the queue specified by the uri parameter will get +cleared before executing the simulation.

  • +
+
+
+
+ +
+
+read(addr, num_or_dtype, dtype=<class 'numpy.uint8'>, srcaddr=None, max_bytes=None, qos=0, prot=0, check_alignment=True, error=None)[source]
+
+
Parameters:
+
    +
  • addr (int) – The 64-bit address read from

  • +
  • num_or_dtype (int or numpy integer datatype) – If a plain int, num_or_datatype specifies the number of bytes to be read. +If a numpy integer datatype (np.uint8, np.uint16, etc.), num_or_datatype +specifies the data type to be returned.

  • +
  • dtype (numpy integer datatype, optional) – If num_or_dtype is a plain integer, the value returned by this function +will be a numpy array of type “dtype”. On the other hand, if num_or_dtype +is a numpy datatype, the value returned will be a scalar of that datatype.

  • +
  • srcaddr (int, optional) – The UMI source address used for the read transaction. This +is sometimes needed to make sure that reads get routed to the right place.

  • +
  • max_bytes (int, optional) – Indicates the maximum number of bytes that can be used for any individual UMI +transaction. If not specified, this defaults to the value of max_bytes +provided in the UmiTxRx constructor, which in turn defaults to 32.

  • +
  • qos (int, optional) – 4-bit Quality of Service field used in the UMI command

  • +
  • prot (int, optional) – 2-bit Protection mode field used in the UMI command

  • +
  • error (bool, optional) – If True, error out upon receiving an unexpected UMI response.

  • +
+
+
Returns:
+

An array of num_or_dtype bytes read from addr. The array will have the type +specified by dtype or num_or_dtype

+
+
Return type:
+

numpy integer array

+
+
+
+ +
+
+recv(blocking=True)[source]
+

Wait for and return a UMI packet if blocking=True, otherwise return a +UMI packet if one can be read immediately, and None otherwise.

+
+
Parameters:
+

blocking (bool, optional) – If True, the function will wait until a UMI packet can be read. +If False, a None type will be returned if no UMI packet can be read +immediately.

+
+
Returns:
+

If blocking is True, a PyUmiPacket is always returned. If blocking is +False, a PyUmiPacket object will be returned if one can be read immediately. +Otherwise, a None type will be returned.

+
+
Return type:
+

PyUmiPacket

+
+
+
+ +
+
+send(p, blocking=True)[source]
+

Sends (or tries to send if burst=False) a UMI transaction (PyUmiPacket) +Returns True if the packet was sent successfully, else False.

+
+
Parameters:
+
    +
  • p (PyUmiPacket) – The UMI packet that will be sent

  • +
  • blocking (bool, optional) – If True, the program will pause execution until a response to the write request +is received.

  • +
+
+
Returns:
+

Returns true if the p was sent successfully

+
+
Return type:
+

bool

+
+
+
+ +
+
+write(addr, data, srcaddr=None, max_bytes=None, posted=None, qos=0, prot=0, progressbar=False, check_alignment=True, error=None)[source]
+

Writes the provided data to the given 64-bit address.

+
+
Parameters:
+
    +
  • addr (int) – 64-bit address that will be written to

  • +
  • data (np.uint8, np.uint16, np.uint32, np.uint64, or np.array) – Can be either a numpy integer type (e.g., np.uint32) or an numpy +array of integer types (np.uint8, np.uin16, np.uint32, np.uint64, etc.). +The data input may contain more than “max_bytes”, in which case +the write will automatically be split into multiple transactions.

  • +
  • srcaddr (int, optional) – UMI source address used for the write transaction. This is sometimes needed to make +the write response gets routed to the right place.

  • +
  • max_bytes (int, optional) – Indicates the maximum number of bytes that can be used for any individual UMI +transaction. If not specified, this defaults to the value of max_bytes +provided in the UmiTxRx constructor, which in turn defaults to 32.

  • +
  • posted (bool, optional) – If True, a write response will be received.

  • +
  • qos (int, optional) – 4-bit Quality of Service field in UMI Command

  • +
  • prot (int, optional) – 2-bit protection mode field in UMI command

  • +
  • progressbar (bool, optional) – If True, the number of packets written will be displayed via a progressbar +in the terminal.

  • +
  • check_alignment (bool, optional) – If true, an exception will be raised if the addr parameter cannot be aligned based +on the size of the data parameter

  • +
  • error (bool, optional) – If True, error out upon receiving an unexpected UMI response.

  • +
+
+
+
+ +
+
+write_readback(addr, value, mask=None, srcaddr=None, dtype=None, posted=True, write_srcaddr=None, check_alignment=True, error=None)[source]
+

Writes the provided value to the given 64-bit address, and blocks +until that value is read back from the provided address.

+
+
Parameters:
+
    +
  • addr (int) – The destination address to write to and read from

  • +
  • value (int, np.uint8, np.uint16, np.uint32, or np.uint64) – The data written to addr

  • +
  • mask (int, optional) – argument (optional) allows the user to mask off some bits +in the comparison of the data written vs. data read back. For example, +if a user only cares that bit “5” is written to “1”, and does not care +about the value of other bits read back, they could use mask=1<<5.

  • +
  • srcaddr (int, optional) – The UMI source address used for the read transaction. This is +sometimes needed to make sure that reads get routed to the right place.

  • +
  • dtype (np.uint8, np.uint16, np.uint32, or np.uint64, optional) – If value is specified as plain integer, then dtype must be specified, +indicating a particular numpy integer type. This is so that the size of +the UMI transaction can be set appropriately.

  • +
  • posted (bool, optional) – By default, the write is performed as a posted write, however it is +is possible to use an ack’d write by setting posted=False.

  • +
  • write_srcaddr (int, optional) – If `posted`=True, write_srcaddr specifies the srcaddr used for that +transaction. If write_srcaddr is None, the default srcaddr for writes +will be used.

  • +
  • check_alignment (bool, optional) – If true, an exception will be raised if the addr parameter cannot be aligned based +on the size of the data parameter

  • +
  • error (bool, optional) – If True, error out upon receiving an unexpected UMI response.

  • +
+
+
Raises:
+

TypeError – If value is not an integer type, if mask is not an integer type

+
+
+
+ +
+ +
+
+switchboard.umi.addr_aligned(addr, align)[source]
+
+
Parameters:
+
    +
  • addr (Integral)

  • +
  • align (Integral)

  • +
+
+
Return type:
+

bool

+
+
+
+ +
+
+switchboard.umi.check_int_in_range(name, value, min=None, max=None)[source]
+
+ +
+
+switchboard.umi.dtype2size(dtype)[source]
+
+
Parameters:
+

dtype (dtype)

+
+
+
+ +
+
+switchboard.umi.nbytes2size(nbytes)[source]
+
+
Parameters:
+

nbytes (Integral)

+
+
+
+ +
+
+switchboard.umi.random_int_value(name, value, min, max, align=None)[source]
+
+ +
+
+switchboard.umi.random_umi_packet(opcode=None, len=None, size=None, dstaddr=None, srcaddr=None, data=None, qos=0, prot=0, ex=0, atype=0, eom=1, eof=1, max_bytes=32)[source]
+

Generates a Random UMI packet. All parameters are optional. Parameters that +are not explicitly specified will be assigned randomly.

+

For more information on the meanings of each parameter, reference +the UMI specification

+
+
Parameters:
+
    +
  • opcode (int, optional) – Command opcode

  • +
  • len (int, optional) – Word transfers per message. (len-1 words will be transferred +per message)

  • +
  • size (int, optional) – Word size ((2^size)-1 bits per word)

  • +
  • dstaddr (int, optional) – 64-bit destination address used in the UMI packet

  • +
  • srcaddr (int, optional) – 64-bit source address used in the UMI packet

  • +
  • data (numpy integer array, optional) – Values used in the Data field for the UMI packet

  • +
  • qos (int, optional) – 4-bit Quality of Service field used in the UMI command

  • +
  • prot (int, optional) – 2-bit Protection mode field used in the UMI command

  • +
  • ex (int, optional) – 1-bit Exclusive access indicator in the UMI command

  • +
  • atype (int, optional) – 8-bit field specifying the type of atomic transaction used +in the UMI command for an atomic operation

  • +
  • eom (int, optional) – 1-bit End of Message indicator in UMI command, used to track +the transfer of the last word in a message

  • +
  • eof (int, optional) – 1-bit End of Frame bit in UMI command, used to indicate the +last message in a sequence of related UMI transactions

  • +
  • max_bytes (int, optional) – The maximum number of bytes included in each UMI packet

  • +
+
+
+
+ +
+
+switchboard.umi.size2dtype(size, signed=False, float=False)[source]
+
+
Parameters:
+
    +
  • size (int)

  • +
  • signed (bool)

  • +
  • float (bool)

  • +
+
+
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/switchboard.util.html b/switchboard.util.html new file mode 100644 index 00000000..371cf24e --- /dev/null +++ b/switchboard.util.html @@ -0,0 +1,203 @@ + + + + + + + switchboard.util module — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

switchboard.util module

+

Classes:

+ + + + + + +

ProcessCollection()

+

Functions:

+ + + + + + + + + +

binary_run(bin[, args, stop_timeout, ...])

plusargs_to_args(plusargs)

+
+
+class switchboard.util.ProcessCollection[source]
+

Bases: object

+
+
+add(process)[source]
+
+ +
+
+terminate(stop_timeout=10, use_sigint=False)[source]
+
+ +
+
+wait()[source]
+
+ +
+ +
+
+switchboard.util.binary_run(bin, args=None, stop_timeout=10, use_sigint=False, quiet=False, print_command=False, cwd=None, env=None)[source]
+
+ +
+
+switchboard.util.plusargs_to_args(plusargs)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/switchboard.verilator.html b/switchboard.verilator.html new file mode 100644 index 00000000..6c5325b7 --- /dev/null +++ b/switchboard.verilator.html @@ -0,0 +1,164 @@ + + + + + + + switchboard.verilator module — Switchboard 0.0.29 documentation + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

switchboard.verilator module

+

Functions:

+ + + + + + +

verilator_run(bin[, plusargs, args, use_sigint])

+
+
+switchboard.verilator.verilator_run(bin, plusargs=None, args=None, use_sigint=True, **kwargs)[source]
+
+ +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file