Skip to content

Standalone Injection

This page demonstrates how to use the standalone mode of the RTL injector. In the following, we assume the current directory is the root directory of this RTL injector.

Usage

The injector can be run as a standalone script with:

./src/stand_alone.py -c <config> -i <input value file> [-o <output file name> -d <debug flag>]

With the config file, you can control the type of fault, cell library, target circuit, etc. An example config is in ./stand_alone/add_64b.yaml and the corresponding input file in ./stand_alone/add_64b_inputs.

See explantion below for the optinal output flag and debug flag.

Example

The first example in ./stand_alone performs two injection to x+y=z (64-bit integer addition) with two sets of inputs: x=y=1 and x=y=2. You can run it with:

./src/stand_alone.py -c ./stand_alone/add_64b.yaml -i ./stand_alone/add_64b_inputs.csv

The second example named mult_64b_3_stages.yaml demonstrates how to selectively inject particular modules. Note the additional targets field in fault. It specifies that the target modules to inject belonging to the LATCHES group, which is defined in the group mapping file NangateOpenCellLibrary.yaml within ./rtl_components/libs. Check the cell_libs part of the config file to see how the group mapping file is specified. Essentially, the targets field's value must be a list. For instance, the example specifies a list with single element, LATCHES. Elements in the list can be either groups such as LATCHES or module names (e.g., DFF_X1, a type of flip-flop). However, there is an issue of using such selective injection (see below).


Input

The input value file specifies the inputs to the circuit with the following format. The first row should be the input port names of the circuit. The following rows are the corresponding input values. Note that the acceptable input value format depends on the data type (see below). If no input value file is provided, random inputs will be used.

Data types

The input values must be eventually converted to bits for RTL simulation. In this injector, we store the input values as 64-bit unsigned integer to save memory. The input values specified in the input file should conform to the following rules depending on the data type.

  • Integer: Use the human-readable format (i.e., if the input value is 3, just put 3 in the input file)
  • Floating-point: Use the integer representation of the raw bits.
    • For example, the 32-bit raw bits of 0.12 in hex is 0x3DF5C28F, which equals to 1039516303 if we treat it as a 64-bit unsigned integer. One can verify it using this and this converter online.
    • We provide a script (./stand_alone/util/fp_convert.py) to achieve this conversion. User must refer to it before injecting with floating-point circuits.

Output

  • Output info:
    • Iterations: number of iterations taken to generate a unmasked fault
    • Correct outupts: fault-free output for each output port
    • Erroneous outputs: corrupted output due to the fault
    • Difference in Hexadecimal: bitwise difference between correct and errorneous outputs
  • Output Format: Output file format depends on the specified output file name. If it ends with .csv, CSV format will be rendered. If .json, JSON format will be printed. Note that the postfixes are case-sensitive.
    • CSV (default): Each row includes the result for an error. The number of output fields specifies the number of cells in the Correct, Error, Diff fields. The default output file is stand_alone_out.csv.
    • JSON: a dict with correct outputs and a list of errors.

Other circuits

If you wants to use circuits other than integer adder, we also provide a script that automatically generate the config of other circuits we provide (see ./stand_alone/config_gen.py).

Debugging

If debug flag is set to nonzero value, it enables verbose logging and intermediate files will be kept for debug purpose.

Issues:

  1. Although you can do injection in batch with different input values (by specifying multiple rows). There is a memory management bug in this tool. You would run into something like OSError: Cannot allocate memory if you put too many rows in the input value file (in our case, the issue appears when you put more than 600 rows but varies across circuits).
  2. To speed up injection, we cache intermediate results to a path specified by the user. Note that when selective injection is used and the targets are changed, the user also has to specify another path for caching. This is because different targets result in different verilog code and error mapping. For now, the user is responsible for managing this multi-cache issue. In summary, make sure you specify the right cache path when using this selective injection feature.