| # OTBN Random Instruction Generator |
| |
| This directory contains a random instruction generator for OTBN called |
| `otbn-rig`. This is intended to be run in multiple phases. If you just |
| want to generate some random binaries, it might be easier to call the |
| wrapper at `../uvm/gen-binaries.py`. |
| |
| At the moment, there are two sub-commands: `gen` and `asm`. In future, |
| we might add more (to do things like test case mutation or shrinking). |
| |
| ## The gen command |
| |
| The `gen` command is in charge of actually generating a random |
| program. This program is written to stdout in an JSON format. This |
| format may change over time, but it is understood by the `asm` |
| command. |
| |
| Example usage: |
| ``` |
| hw/ip/otbn/dv/rig/otbn-rig gen --seed 123 --size 1000 >foo.json |
| ``` |
| |
| To control random generation, there is a `--seed` parameter. The |
| output should be stable for a fixed seed. If not specified, the seed |
| is zero. |
| |
| ### The size parameter |
| |
| The `--size` parameter is used to control how big the program grows. A |
| snippet with a single unconditionally executed instruction has a size |
| of one. A snippet containing a sequence of `N` instructions has a size |
| of `N`. For a more interesting example, consider an if/else branch |
| that would look something like this in C: |
| |
| ```C |
| if (A) { |
| B; |
| } else { |
| C; |
| } |
| ``` |
| |
| If calculating `A` takes `a` cycles and `B` and `C` have a size of `b` |
| and `c` respectively, then the entire snippet has size `a + max(b, |
| c)`. The general idea is that the size taken by a snippet is an upper |
| bound on the number of instructions that it causes the processor to |
| execute. This might not be a strict upper bound: for example, it won't |
| be strict if `a != b` in the if/else snippet above. |
| |
| ### Snippets |
| |
| The random program is built from blocks called "snippets". The |
| simplest possible snippet is a sequence of straight-line instructions. |
| There are also more complicated snippets like conditional branches and |
| loops. The JSON output format represents this tree of snippets. |
| |
| ### Initialised data |
| |
| The generated program is designed never to trigger architecturally |
| unspecified behaviour. It might trigger errors, but its execution will |
| never depend on things like the initial contents of the register file |
| or uninitialised memories. |
| |
| To provide some data so that RIG can generate load instructions even |
| near the start of the run, the generated program also includes a few |
| words of (randomly) initialised data, scattered around dmem. |
| |
| ## The asm command |
| |
| Once a random program has been generated, the `asm` command can be |
| used to convert it to an assembly listing. This, in turn, can be |
| assembled and linked using the toolchain in `hw/ip/otbn/util`. |
| |
| Unlike the `gen` command, this step does no random generation: it's a |
| deterministic translation from the JSON input to assembly and linker |
| script output. |
| |
| Example usage: |
| ``` |
| hw/ip/otbn/dv/rig/otbn-rig asm --output foo foo.json |
| ``` |
| |
| When given the `--output` parameter, this command generates two output |
| files. With `--output foo`, it generates `foo.s` and `foo.ld`. These |
| are an assembly listing and a linker script, respectively. |
| |
| To assemble and link, use commands like: |
| ``` |
| hw/ip/otbn/util/otbn_as.py -o foo.o foo.s |
| hw/ip/otbn/util/otbn_ld.py -o foo.elf -T foo.ld foo.o |
| ``` |
| This is automated in the `gen-binaries.py` wrapper described above. |
| |
| Occasionally, it's helpful to just read the assembly listing for a |
| JSON file. To do this, run the command with no `--output` parameter to |
| see the assembly listing on stdout. The linker script will not be |
| generated. |