Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/env python3
      2 
      3 # Copyright 2016, VIXL authors
      4 # All rights reserved.
      5 #
      6 # Redistribution and use in source and binary forms, with or without
      7 # modification, are permitted provided that the following conditions are met:
      8 #
      9 #   * Redistributions of source code must retain the above copyright notice,
     10 #     this list of conditions and the following disclaimer.
     11 #   * Redistributions in binary form must reproduce the above copyright notice,
     12 #     this list of conditions and the following disclaimer in the documentation
     13 #     and/or other materials provided with the distribution.
     14 #   * Neither the name of ARM Limited nor the names of its contributors may be
     15 #     used to endorse or promote products derived from this software without
     16 #     specific prior written permission.
     17 #
     18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
     19 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     21 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
     22 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     23 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     24 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     25 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     26 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 
     29 """
     30 Generating tests
     31 ================
     32 
     33 From the VIXL toplevel directory run:
     34 
     35     $ ./tools/generate_tests.py
     36 
     37 The script assumes that `clang-format-3.6` is in the current path. If it isn't,
     38 you can provide your own:
     39 
     40     $ ./tools/generate_tests.py --clang-format /patch/to/clang-format
     41 
     42 Once the script has finished, it will have generated test files, as many as
     43 present in the `default_config_files` list. For example:
     44 
     45 - test/aarch32/test-assembler-cond-rd-rn-immediate-a32.cc
     46 - test/aarch32/test-assembler-cond-rd-rn-rm-a32.cc
     47 - test/aarch32/test-assembler-cond-rd-rn-rm-q-a32.cc
     48 - test/aarch32/test-assembler-cond-rd-rn-rm-ge-a32.cc
     49 
     50 Because these test cases need traces in order to build, the script will have
     51 generated dummy trace files in `test/aarch32/traces/`. If you look at them
     52 you'll see they are basically empty:
     53 
     54     $ cat test/aarch32/traces/sim-cond-rd-rn-immediate-adc-a32.h
     55     static const TestResult *kReferenceAdc = NULL;
     56 
     57 So of course, we can now build the test cases but running them will crash. We
     58 need to re-generate traces with real hardware; the test cases do not support
     59 running in the simulator just yet.
     60 
     61 Generating traces
     62 =================
     63 
     64 You need to have either compiled natively for ARM, or cross-compiled
     65 `test-runner`. The traces can then be generated in the same way as with VIXL64.
     66 Note that it takes a few minutes to generate everything.
     67 
     68     ./tools/generate_simulator_traces.py --runner /path/to/test-runner \
     69       --aarch32-only
     70 
     71 You can now rebuild everything. If it all goes well, running the new tests
     72 should pass.
     73 
     74 Test configuration format
     75 =========================
     76 
     77 TODO: Write a simple and well documented complete example configuration file and
     78       mention it here.
     79 
     80 The underlying `test_generator` framework reads JSON description files and
     81 generates tests according to them. These files live in `test/aarch32/config` by
     82 default, but you may provide your own files with the `--config-files FILE ...`
     83 flag. The JSON format was extended to support C++ like one-line comments.
     84 
     85 Each configuration file will serve to generate one or more test files,
     86 we even use its file name to choose the name of the test:
     87 
     88     test/aarch32/config/cond-rd-rn-immediate-a32.json
     89     `-> test/aarch32/test-simulator-cond-rd-rn-immediate-a32.cc
     90     `-> test/aarch32/test-assembler-cond-rd-rn-immediate-a32.cc
     91 
     92 In addition to these test configuration files, we also provide a JSON
     93 description with shared information. This information represents data types that
     94 instructions use and lives in `test/aarch32/config/data-types.json`.
     95 
     96 Data types description
     97 ----------------------
     98 
     99 We refer to two kinds of data types: `operand` and `input`.
    100 
    101 An `operand` represents an argument passed to the macro-assembler to generate an
    102 instruction. For example, a register or an immediate are operands. We can think
    103 of it as "assemble-time" data.
    104 
    105 As opposed to `operands`, an `input` represents data passed to an instruction at
    106 runtime. For example, it will be the value you write to a register before
    107 executing the instruction under test.
    108 
    109 The `data-types.json` file has the following structure:
    110 
    111 ~~~
    112 {
    113   "operands": [
    114     // List of operand types.
    115   ],
    116   "inputs": [
    117     // List of input types.
    118   ]
    119 }
    120 ~~~
    121 
    122 Each operand is described with the following structure:
    123 
    124 ~~~
    125 {
    126   // Unique name for this operand type.
    127   "name": "AllRegistersButPC",
    128   // C++ type used by VIXL to represent this operand.
    129   "type": "Register",
    130   // List of possible variants.
    131   "variants": [
    132     "r0",
    133     "r1",
    134     "r2",
    135     "r3",
    136     "r4",
    137     "r5",
    138     "r6",
    139     "r7",
    140     "r8",
    141     "r9",
    142     "r10",
    143     "r11",
    144     "r12",
    145     "r13",
    146     "r14"
    147   ],
    148   // Default variant to use.
    149   "default": "r0"
    150 }
    151 ~~~
    152 
    153 The "name" field of the operand will be used by test configuration files in
    154 order to specify what kind of operands an instruction takes. The "type" field
    155 simply tells the generator what C++ type should be generated, e.g. "Condition",
    156 "Register", "uint32_t", "ShiftType", ...etc.
    157 
    158 Inputs are described in a very similar way:
    159 
    160 ~~~
    161 {
    162   // Unique name for this input type.
    163   "name": "Register",
    164   // Python type from `test_generator.data_types` to use to generate C++ code
    165   // for this input.
    166   "type": "Register",
    167   // List of possible values.
    168   "values": [
    169     "0x00000000",
    170     "0xffffffff",
    171     "0xabababab",
    172     "0x5a5a5a5a"
    173   ],
    174   // Default value.
    175   "default": "0xabababab"
    176 }
    177 ~~~
    178 
    179 The "name" field has the same purpose as for operands. The "type" field however,
    180 is the name of a Python class in `test_generator.data_types`. The type will
    181 specify what C++ code to generate in order to load and record the input value,
    182 e.g. how to load a value into a register, how to read and record it.
    183 
    184 When adding more tests, one may have to create new data types in this file. For
    185 example, when we want to test an instruction with a different set of registers.
    186 If adding new input types which need different C++ code to load and record them,
    187 one will have to add it to `test_generator.data_types` and override the
    188 `Epilogue` and `Prologue` methods.
    189 
    190 Test configuration
    191 ------------------
    192 
    193 Once we have all the data types we need described, we need test configuration
    194 files to describe what instructions to test and with what `inputs` and
    195 `operands` they take.
    196 
    197 These files have the following structure:
    198 
    199 ~~~
    200 {
    201   "mnemonics": [
    202     // List of instruction mnemonics to use. These must correspond to
    203     // `MacroAssembler` methods.
    204   ],
    205   "description": {
    206     "operands": [
    207       // List of operands the instruction takes.
    208     ],
    209     "inputs: [
    210       // List of inputs the instruction can be affected by.
    211     ]
    212   },
    213   // List of files to generate.
    214   "test-files": [
    215     {
    216       "type": "assembler",
    217       "mnemonics": [
    218         // Optional list of instruction mnemonics to use, overriding the
    219         // top-level list.
    220       ],
    221       "test-cases": [
    222         // List of test cases for "assembler" tests, see below for
    223         // details.
    224       ]
    225     },
    226     {
    227       "type": "simulator",
    228       "test-cases": [
    229         // List of test cases for "simulator" tests, see below for
    230         // details.
    231       ]
    232     }
    233   ]
    234 }
    235 ~~~
    236 
    237 - List of operands:
    238 
    239 The operand list describes the actual argument to the `MacroAssembler` method.
    240 For example, if we take instruction in the form
    241 "XXX.cond rd rn rm shift #amount":
    242 
    243 We want to generate C++ code as such:
    244 
    245 ~~~
    246 Condition cond = ...;
    247 Register rd = ...;
    248 Register rn = ...;
    249 Register rm = ...;
    250 ShiftType type = ...;
    251 uint32_t amount = ...;
    252 Operand op(rm, type, amount);
    253 
    254 __ Xxx(cond, rd, rn, op);
    255 ~~~
    256 
    257 We will have the following operand list:
    258 
    259 ~~~
    260 "operands": [
    261   {
    262     "name": "cond",
    263     "type": "Condition"
    264   },
    265   {
    266     "name": "rd",
    267     "type": "AllRegistersButPC"
    268   },
    269   {
    270     "name": "rn",
    271     "type": "AllRegistersButPC"
    272   },
    273   {
    274     "name": "op",
    275     "wrapper": "Operand",
    276     "operands": [
    277       {
    278         "name": "rm",
    279         "operand": "AllRegistersButPC"
    280       },
    281       {
    282         "name": "type",
    283         "operand": "Shift"
    284       },
    285       {
    286         "name": "amount",
    287         "operand": "ImmediateShiftAmount"
    288       }
    289     ]
    290   }
    291 ]
    292 ~~~
    293 
    294 The "name" field represents the identifier of the operand and will be used as a
    295 variable name in the generated code. The "type" field corresponds to an operand
    296 type described in the `data-types.json` file as described above.
    297 
    298 We can see that we've wrapped the last three operands into an "op"
    299 wrapper object. This allows us to tell the generator to wrap these
    300 operands into a `Operand` C++ object.
    301 
    302 - List of inputs:
    303 
    304 This structure is similar to the operand list, but this time it describes what
    305 input data the instructions may be affected by at runtime. If we take the same
    306 example as above, we will have the following list:
    307 
    308 ~~~
    309 "inputs": [
    310   {
    311     "name": "apsr",
    312     "type": "NZCV"
    313   },
    314   {
    315     "name": "rd",
    316     "type": "Register"
    317   },
    318   {
    319     "name": "rn",
    320     "type": "Register"
    321   },
    322   {
    323     "name": "rm",
    324     "type": "Register"
    325   }
    326 ]
    327 ~~~
    328 
    329 This will specify what C++ code to generate before and after emitting the
    330 instruction under test. The C++ code will set and record register values for
    331 example. See `test_generator.data_types` for more details.
    332 
    333 - Test files and test cases:
    334 
    335 Up until now, we've only just described the environment in which instructions
    336 can operate. We need to express what files we want generating, what instructions
    337 we want to test and what we want them to do.
    338 
    339 As previously mentioned, a configuration file can control the generation of
    340 several test files. We will generate one file per element in the "test-files"
    341 array:
    342 
    343 ~~~
    344 "test-files": [
    345   {
    346     "type": "assembler",
    347     "test-cases": [
    348       // List of test cases for "assembler" tests, see below for
    349       // details.
    350     ]
    351   },
    352   {
    353     "type": "assembler",
    354     "name": "special-case",
    355     "mnemonics": [
    356       // Override the top-level list with a subset of instructions concerned
    357       // with this special case.
    358     ],
    359     "test-cases": [
    360       // List of test cases for "assembler" tests, see below for
    361       // details.
    362     ]
    363   },
    364   {
    365     "type": "simulator",
    366     "test-cases": [
    367       // List of test cases for "simulator" tests, see below for
    368       // details.
    369     ]
    370   }
    371 ]
    372 ~~~
    373 
    374 Above, we've decided to generate three tests: a "simulator" test and two
    375 "assembler" tests. The resulting files will have names with the following
    376 pattern.
    377 
    378   - "test/aarch32/test-assembler-{configuration name}-a32.cc"
    379   - "test/aarch32/test-assembler-{configuration name}-special-case-a32.cc"
    380   - "test/aarch32/test-simulator-{configuration name}-a32.cc"
    381 
    382 The "type" field describes the kind of testing we want to do, these types are
    383 recognized by the generator and, at the moment, can be one of "simulator",
    384 "assembler" and "macro-assembler". Simulator tests will run each instruction and
    385 record the changes while assembler tests will only record the code buffer and
    386 never execute anything. MacroAssembler tests currently only generate code to
    387 check that the MacroAssembler does not crash; the output itself is not yet
    388 tested. Because you may want to generate more than one test of the same type, as
    389 we are doing in the example, we need a way to differentiate them. You may use
    390 the optional "name" field for this.
    391 
    392 Finally, we describe how to test the instruction by declaring a list of test
    393 cases with the "test-cases" field.
    394 
    395 Here is an example of what we can express:
    396 ~~~
    397 [
    398   // Generate all combinations of instructions where "rd" an "rn" are the same
    399   // register and "cond" and "rm" are just the default.
    400   // For example:
    401   //   __ Xxx(al, r0, r0, r0);
    402   //   __ Xxx(al, r1, r1, r0);
    403   //   __ Xxx(al, r2, r2, r0);
    404   //   ...
    405   //   __ Xxx(al, r12, r12, r0);
    406   //   __ Xxx(al, r13, r13, r0);
    407   //   __ Xxx(al, r14, r14, r0);
    408   //
    409   // For each of the instructions above, run them with a different value in "rd"
    410   // and "rn".
    411   {
    412     "name": "RdIsRn",
    413     "operands": [
    414       "rd", "rn"
    415     ],
    416     "operand-filter": "rd == rn",
    417     "inputs": [
    418       "rd", "rn"
    419     ],
    420     "input-filter": "rd == rn"
    421   },
    422   // Generate all combinations of instructions with different condition codes.
    423   // For example:
    424   //   __ Xxx(eq, r0, r0, r0);
    425   //   __ Xxx(ne, r0, r0, r0);
    426   //   __ Xxx(cs, r0, r0, r0);
    427   //   ...
    428   //   __ Xxx(gt, r0, r0, r0);
    429   //   __ Xxx(le, r0, r0, r0);
    430   //   __ Xxx(al, r0, r0, r0);
    431   //
    432   // For each of the instructions above, run them against all combinations of
    433   // NZCV bits.
    434   {
    435     "name": "ConditionVersusNZCV",
    436     "operands": [
    437       "cond"
    438     ],
    439     "inputs": [
    440       "apsr"
    441     ]
    442   },
    443   // We are interested in testing that the Q bit gets set and cleared, so we've
    444   // limited the instruction generation to a single instruction and instead have
    445   // stressed the values put in "rn" and "rm".
    446   //
    447   // So for this instruction, we choose to run it will all combinations of
    448   // values in "rn" and "rm". Additionally, we include "qbit" in the inputs,
    449   // which will make the test set or clear it before executing the instruction.
    450   // Note that "qbit" needs to be declared as an input in the instruction
    451   // description (see "List of inputs" section).
    452   {
    453     "name": "Qbit",
    454     "operands": [
    455       "rn", "rm"
    456     ],
    457     "inputs": [
    458       "qbit", "rn", "rm"
    459     ],
    460     "operand-filter": "rn != rm'",
    461     "operand-limit": 1
    462   },
    463   // Generate 10 random instructions with all different registers but use the
    464   // default condition.
    465   // For example:
    466   //   __ Xxx(al, r5, r1, r0);
    467   //   __ Xxx(al, r8, r9, r7);
    468   //   __ Xxx(al, r9, r1, r2);
    469   //   __ Xxx(al, r0, r6, r2);
    470   //   __ Xxx(al, r11, r9, r11);
    471   //   __ Xxx(al, r14, r2, r11);
    472   //   __ Xxx(al, r8, r2, r5);
    473   //   __ Xxx(al, r10, r0, r1);
    474   //   __ Xxx(al, r11, r2, r7);
    475   //   __ Xxx(al, r2, r6, r1);
    476   //
    477   // For each instruction, feed it 200 different combination of values in the
    478   // three registers.
    479   {
    480     "name": "RegisterSimulatorTest",
    481     "operands": [
    482       "rd", "rn", "rm"
    483     ],
    484     "inputs": [
    485       "rd", "rn", "rm"
    486     ],
    487     "operand-limit": 10,
    488     "input-limit": 200
    489   }
    490 ]
    491 ~~~
    492 
    493 Assembler test cases are much simpler, here are some examples:
    494 ~~~
    495 // Generate 2000 random instructions out of all possible operand combinations.
    496 {
    497   "name": "LotsOfRandomInstructions",
    498   "operands": [
    499     "cond", "rd", "rn", "rm"
    500   ],
    501   "operand-limit": 2000
    502 },
    503 // Same as above but limit the test to 200 instructions where rd == rn.
    504 {
    505   "name": "RdIsRn",
    506   "operands": [
    507     "cond", "rd", "rn", "rm"
    508   ],
    509   "operand-filter": "rd == rn",
    510   "operand-limit": 200
    511 }
    512 ~~~
    513 
    514 As can be expected, assembler test do not have the notion of "inputs".
    515 
    516 Here are details about each field. Note that all of them except for "name" are
    517 optional.
    518 
    519   * "name":
    520 
    521     A unique name should be given to the test case, it will be used to give the
    522     generated C++ `const Input[]` array a name.
    523 
    524   * "operands":
    525 
    526     List of operand names that we are interested in testing. The generator will
    527     lookup the list of variants for each operand and build the product of all of
    528     them. It will then choose the default variant for the operands not specified
    529     here.
    530 
    531   * "operand-filter":
    532 
    533     As you would expect, the product of all operand variants may be huge. To
    534     prevent this, you may specify a Python expression to filter the list.
    535 
    536   * "operand-limit":
    537 
    538     We can potentially obtain a *massive* set of variants of instructions, as we
    539     are computing a product of operand variants in "operands". This field allows
    540     us to limit this by choosing a random sample from the computed variants.
    541     Note that this is a seeded pseudo-random sample, and the seed corresponds to
    542     the test case description. The same test case description will always
    543     generate the same code.
    544 
    545   * "inputs":
    546 
    547     This is exactly the same as "operands" but for inputs.
    548 
    549   * "input-filter":
    550 
    551     Ditto.
    552 
    553   * "input-limit":
    554 
    555     Ditto.
    556 
    557 Here is an example of the C++ code that will be generated for a given test case.
    558 For simplicity, let's generate tests for an instruction with only `NZCV` and two
    559 registers as inputs.
    560 
    561 For the following test case, which will target encodings where `rd` and `rn` are
    562 the same registers:
    563 
    564 ~~~
    565 {
    566   "name": "RdIsRn",
    567   "operands": [
    568     "rd", "rn"
    569   ],
    570   "operand-filter": "rd == rn",
    571   "inputs": [
    572     "rd", "rn"
    573   ],
    574   "input-filter": "rd == rn"
    575 },
    576 ~~~
    577 
    578 It will generate the following input array.
    579 
    580 ~~~
    581 //                                apsr,        rd,         rn
    582 static const Inputs kRdIsRn[] = {{NoFlag, 0x00000000, 0x00000000},
    583                                  {NoFlag, 0xffffffff, 0xffffffff},
    584                                  {NoFlag, 0xabababab, 0xabababab},
    585                                  {NoFlag, 0x5a5a5a5a, 0x5a5a5a5a}};
    586 ~~~
    587 
    588 We can see that the default apsr value was chosen (NoFlag), as apsr is not in
    589 the list of "inputs".
    590 
    591 It will also generate a list of instructions to test:
    592 
    593 ~~~
    594 static const TestLoopData kTests[] = {
    595     {{al, r1, r1, 0x000000ab}, ARRAY_SIZE(kRdIsRn), kRdIsRn, "RdIsRn"},
    596     {{al, r2, r2, 0x000000ab}, ARRAY_SIZE(kRdIsRn), kRdIsRn, "RdIsRn"},
    597     {{al, r8, r8, 0x000000ab}, ARRAY_SIZE(kRdIsRn), kRdIsRn, "RdIsRn"},
    598     {{al, r9, r9, 0x000000ab}, ARRAY_SIZE(kRdIsRn), kRdIsRn, "RdIsRn"},
    599 };
    600 ~~~
    601 
    602 As a result, the new test we will assemble each instructions in "mnemonics" with
    603 all of the operands described in `kTests` above. And each instruction will be
    604 executed and passed all inputs in `kRdIsRn`.
    605 """
    606 
    607 import subprocess
    608 import argparse
    609 import string
    610 import re
    611 import multiprocessing
    612 import functools
    613 
    614 import test_generator.parser
    615 
    616 
    617 default_config_files = [
    618     'test/aarch32/config/rd-rn-rm-a32.json',
    619     'test/aarch32/config/cond-rd-rn-operand-const-a32.json',
    620     'test/aarch32/config/cond-rd-rn-operand-rm-a32.json',
    621     'test/aarch32/config/cond-rd-rn-operand-rm-shift-amount-1to31-a32.json',
    622     'test/aarch32/config/cond-rd-rn-operand-rm-shift-amount-1to32-a32.json',
    623     'test/aarch32/config/cond-rd-rn-operand-rm-shift-rs-a32.json',
    624     'test/aarch32/config/cond-rd-rn-operand-rm-ror-amount-a32.json',
    625     'test/aarch32/config/cond-rd-rn-a32.json',
    626     'test/aarch32/config/cond-rd-rn-pc-a32.json',
    627     'test/aarch32/config/cond-rd-rn-rm-a32.json',
    628     'test/aarch32/config/cond-rd-operand-const-a32.json',
    629     'test/aarch32/config/cond-rd-operand-rn-a32.json',
    630     'test/aarch32/config/cond-rd-operand-rn-shift-amount-1to31-a32.json',
    631     'test/aarch32/config/cond-rd-operand-rn-shift-amount-1to32-a32.json',
    632     'test/aarch32/config/cond-rd-operand-rn-shift-rs-a32.json',
    633     'test/aarch32/config/cond-rd-operand-rn-ror-amount-a32.json',
    634     'test/aarch32/config/cond-rd-memop-immediate-512-a32.json',
    635     'test/aarch32/config/cond-rd-memop-immediate-8192-a32.json',
    636     'test/aarch32/config/cond-rd-memop-rs-a32.json',
    637     'test/aarch32/config/cond-rd-memop-rs-shift-amount-1to31-a32.json',
    638     'test/aarch32/config/cond-rd-memop-rs-shift-amount-1to32-a32.json',
    639 
    640     'test/aarch32/config/cond-rd-rn-t32.json',
    641     'test/aarch32/config/cond-rd-rn-rm-t32.json',
    642     'test/aarch32/config/cond-rdlow-rnlow-rmlow-t32.json',
    643     'test/aarch32/config/cond-rd-rn-operand-const-t32.json',
    644     'test/aarch32/config/cond-rd-pc-operand-imm12-t32.json',
    645     'test/aarch32/config/cond-rd-rn-operand-imm12-t32.json',
    646     'test/aarch32/config/cond-rd-pc-operand-imm8-t32.json',
    647     'test/aarch32/config/cond-rd-sp-operand-imm8-t32.json',
    648     'test/aarch32/config/cond-rdlow-rnlow-operand-immediate-t32.json',
    649     'test/aarch32/config/cond-sp-sp-operand-imm7-t32.json',
    650     'test/aarch32/config/cond-rd-rn-operand-rm-t32.json',
    651     'test/aarch32/config/cond-rd-rn-operand-rm-shift-amount-1to31-t32.json',
    652     'test/aarch32/config/cond-rd-rn-operand-rm-shift-amount-1to32-t32.json',
    653     'test/aarch32/config/cond-rd-rn-operand-rm-ror-amount-t32.json',
    654     'test/aarch32/config/cond-rd-operand-const-t32.json',
    655     'test/aarch32/config/cond-rd-operand-imm16-t32.json',
    656     'test/aarch32/config/cond-rdlow-operand-imm8-t32.json',
    657     'test/aarch32/config/cond-rd-operand-rn-shift-amount-1to31-t32.json',
    658     'test/aarch32/config/cond-rd-operand-rn-shift-amount-1to32-t32.json',
    659     'test/aarch32/config/cond-rd-operand-rn-shift-rs-t32.json',
    660     'test/aarch32/config/cond-rd-operand-rn-ror-amount-t32.json',
    661     'test/aarch32/config/cond-rd-operand-rn-t32.json',
    662     'test/aarch32/config/rd-rn-rm-t32.json',
    663 ]
    664 
    665 
    666 # Link a test type with a template file.
    667 template_files = {
    668     'simulator': "test/aarch32/config/template-simulator-aarch32.cc.in",
    669     'assembler': "test/aarch32/config/template-assembler-aarch32.cc.in",
    670     'macro-assembler': "test/aarch32/config/template-macro-assembler-aarch32.cc.in",
    671 }
    672 
    673 
    674 def BuildOptions():
    675   result = argparse.ArgumentParser(
    676       description = 'Test generator for AArch32.',
    677       formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    678   result.add_argument('--config-files', nargs='+',
    679                       default=default_config_files,
    680                       metavar='FILE',
    681                       help='Configuration files, each will generate a test file.')
    682   result.add_argument('--clang-format',
    683                       default='clang-format-3.6', help='Path to clang-format.')
    684   result.add_argument('--jobs', '-j', type=int, metavar='N',
    685                       default=multiprocessing.cpu_count(),
    686                       help='Allow N jobs at once')
    687   result.add_argument('--skip-traces', action='store_true',
    688                       help='Skip generation of dummy traces.')
    689   return result.parse_args()
    690 
    691 
    692 def DoNotEditComment(template_file):
    693   # We rely on `clang-format` to wrap this comment to 80 characters.
    694   return """
    695 // -----------------------------------------------------------------------------
    696 // This file is auto generated from the {} template file using tools/generate_tests.py.
    697 //
    698 // PLEASE DO NOT EDIT.
    699 // -----------------------------------------------------------------------------
    700     """.format(template_file)
    701 
    702 def GenerateTest(generator, clang_format, skip_traces):
    703   template_file = template_files[generator.test_type]
    704   generated_file = ""
    705   with open(template_file, "r") as f:
    706     # Strip out comments starting with three forward slashes before creating the
    707     # string.Template object.
    708     template = string.Template(re.sub("\/\/\/.*", "", f.read()))
    709 
    710     # The `generator` object has methods generating strings to fill the template.
    711     generated_file = template.substitute({
    712       # Add a top comment stating this file is auto-generated.
    713       'do_not_edit_comment': DoNotEditComment(template_file),
    714 
    715       # List of mnemonics.
    716       'instruction_list_declaration': generator.InstructionListDeclaration(),
    717 
    718       # Declarations.
    719       'operand_list_declaration': generator.OperandDeclarations(),
    720       'input_declarations': generator.InputDeclarations(),
    721 
    722       # Definitions.
    723       'input_definitions': generator.InputDefinitions(),
    724       'test_case_definitions': generator.TestCaseDefinitions(),
    725 
    726       # Include traces.
    727       'include_trace_files': generator.IncludeTraceFiles(),
    728 
    729       # Define a typedef for the MacroAssembler method.
    730       'macroassembler_method_args': generator.MacroAssemblerMethodArgs(),
    731 
    732       # Generate code to switch instruction set.
    733       'macroassembler_set_isa': generator.MacroAssemblerSetISA(),
    734 
    735       # Generate code to emit instructions.
    736       'code_instantiate_operands': generator.CodeInstantiateOperands(),
    737       'code_prologue': generator.CodePrologue(),
    738       'code_epilogue': generator.CodeEpilogue(),
    739       'code_parameter_list': generator.CodeParameterList(),
    740 
    741       # Generate code to trace the execution and print C++.
    742       'trace_print_outputs': generator.TracePrintOutputs(),
    743 
    744       # Generate code to compare the results against a trace.
    745       'check_instantiate_results': generator.CheckInstantiateResults(),
    746       'check_instantiate_inputs': generator.CheckInstantiateInputs(),
    747       'check_instantiate_references': generator.CheckInstantiateReferences(),
    748       'check_results_against_references':
    749           generator.CheckResultsAgainstReferences(),
    750       'check_print_input': generator.CheckPrintInput(),
    751       'check_print_expected': generator.CheckPrintExpected(),
    752       'check_print_found': generator.CheckPrintFound(),
    753 
    754       'test_name': generator.TestName(),
    755       'isa_guard': generator.GetIsaGuard()
    756     })
    757   # Create the test case and pipe it through `clang-format` before writing it.
    758   with open(
    759       "test/aarch32/test-{}-{}.cc".format(generator.test_type, generator.test_name),
    760       "w") as f:
    761     proc = subprocess.Popen([clang_format], stdin=subprocess.PIPE,
    762                             stdout=subprocess.PIPE)
    763     out, _ = proc.communicate(generated_file.encode())
    764     f.write(out.decode())
    765   if not skip_traces:
    766     # Write dummy trace files into 'test/aarch32/traces/'.
    767     generator.WriteEmptyTraces("test/aarch32/traces/")
    768   print("Generated {} test for \"{}\".".format(generator.test_type, generator.test_name))
    769 
    770 
    771 if __name__ == '__main__':
    772   args = BuildOptions()
    773 
    774   # Each file in `args.config_files` populates a `Generator` object.
    775   generators = test_generator.parser.Parse('test/aarch32/config/data-types.json',
    776                                            args.config_files)
    777 
    778   # Call the `GenerateTest` function for each generator object in parallel. This
    779   # will use as many processes as defined by `-jN`, which defaults to 1.
    780   with multiprocessing.Pool(processes=args.jobs) as pool:
    781     pool.map(functools.partial(GenerateTest, clang_format=args.clang_format,
    782                                              skip_traces=args.skip_traces),
    783              generators)
    784