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