docs: first steps document (intro)
[libreriscv.git] / docs / firststeps.mdwn
1 [[!toc ]]
2
3 ---
4
5 # Introduction
6
7 This tutorial intends to sched some light at the first steps for a newcomer.
8 Note that this tutorial is a work in progress; feel free to update it.
9 This tutorial assumes that the environment and and repositories are set.
10 The information on environment can be found at
11 [HDL workflow](https://libre-soc.org/HDL_workflow/) page.
12
13 In this tutorial, we will perform these steps:
14
15 0. Checking we're all ready and set.
16 1. Running the first test and observing its results.
17 2. Updating the test so that it enables/disables some functions.
18
19 Note that this tutorial is ISA-centric, since the idea of adding it
20 was born by the times there were several newcomer-oriented tasks around
21 the decoder. Many of key concepts, however, are not ISA-specific, so
22 there is a hope that this guide can be helpful for other tasks.
23
24 # Checking we're all ready and set
25
26 Once we established the environment and cloned openpower-isa repository,
27 we can run the first test we'll use as an example to observe.
28 Since we're starting from decoder, we will work with openpower-isa
29 repository. If you followed the HDL guidelines strictly, you can chroot
30 into libresoc environment and work with the repository immediately,
31 by changing the directory to `${HOME}/src/openpower-isa`.
32
33 schroot -c libresoc /bin/bash
34 cd "${HOME}/src/openpower-isa"
35
36 If for some reason `openpower-isa` repository is not yet in your `src`
37 subdirectory, you need to clone the relevant repository. The recommended
38 way to do it is to use
39 [hdl-dev-repos](https://git.libre-soc.org/?p=dev-env-setup.git;a=blob;f=hdl-dev-repos;hb=HEAD)
40 script.
41
42 The environment is quite newcomer-friendly: the test we intend to dissect
43 is implemented in pure Python, so there is no need to build anything before
44 running the test. All we need is a good ol' Python; however, before proceeding,
45 make sure that Python is at least of version 3.7.2.
46
47 python3 --version
48
49 If the version is less than 3.7.2, consider re-visiting the
50 [HDL workflow](https://libre-soc.org/HDL_workflow/) page and checking that all
51 preparations are done correctly. Again, the preferred way is using simple
52 scripts to keep the life easy. In this case, the script of interest is
53 [install-hdl-apt-reqs](https://git.libre-soc.org/?p=dev-env-setup.git;a=blob;f=install-hdl-apt-reqs;hb=HEAD).
54
55 # Running the very first test
56
57 Once we have the repository and the needed Python version, we can launch
58 our first test suite (assuming we're already inside openpower-isa
59 repository):
60
61 python3 src/openpower/decoder/isa/test_caller.py > /tmp/log
62
63 The test takes a while to complete; once it's ready, you should observe that
64 it exits with success, and all tests from suite report no errors. In case
65 some tests report failures, consider raising a question in #libre-soc on
66 irc.libera.chat, or in
67 [mailing list](https://lists.libre-soc.org/mailman/listinfo/libre-soc-dev).
68 If you choose the latter, again, consider visiting
69 [HDL workflow](https://libre-soc.org/HDL_workflow/) page, to be aware
70 of mailing lists etiquette and preferences. Note, however, that some tests
71 can be skipped; this is acceptable.
72
73 If everything works fine, that's a good sign; let's proceed to the first
74 routine we'd like to dissect.
75
76 # Dissecting the test of interest
77
78 The script we launched contained several tests; amongst others, it checks
79 that addition instruction works correctly. Since we're going to look through
80 this instruction, let's for this time disable other tests so that we would
81 run only test related to addition.
82 Let's edit the test_caller.py script and mark all tests except addition one
83 as those which must be skipped. This goal can be achieved by two ways.
84
85 1. The first option is to rename all methods in `DecoderTestCase` class
86 so that the names start with prefix other than `test_`.
87 2. Alternatively, and this is the recommended way, tests can be temporarily
88 disabled via @unittest.skip decorator applied to the method. This method
89 is mentioned in HDL workflow as well (section 10.4).
90
91 Regardless of the option considered, `test_add`, which we're looking at,
92 should be kept intact. Once all tests but `test_add` are renamed or skipped,
93 re-run the test:
94
95 python3 src/openpower/decoder/isa/test_caller.py > /tmp/log
96
97 This time the suite should complete much faster. Let's observe the log and
98 look for a line `call add add`. This line comes from
99 `src/openpower/decoder/isa/caller.py`, and gives us an important information:
100 we're calling an `add` instruction, and its assembly mnemonic is `add` as well.
101
102 So far so good; we dropped other tests, and now look at the test for `add`
103 instruction. Now we're ready to check how the instruction behaves.
104
105 # A quick look at ADD instruction test
106
107 Let's return to the test and the logs. What the test for `add` instruction does?
108 For reader's convenience, the overall `test_add` code is duplicated here:
109
110 ```
111 def test_add(self):
112 lst = ["add 1, 3, 2"]
113 initial_regs = [0] * 32
114 initial_regs[3] = 0x1234
115 initial_regs[2] = 0x4321
116 with Program(lst, bigendian=False) as program:
117 sim = self.run_tst_program(program, initial_regs)
118 self.assertEqual(sim.gpr(1), SelectableInt(0x5555, 64))
119 ```
120
121 What do we see here? First of all, we have an assembly listing, consisting of
122 exactly one command, `"add 1, 3, 2"`. Then we establish the initial values
123 for registers we're going to work with. After that, we instantiate the program
124 with the assembly listing, execute the program, and compare the state of the
125 first general-purpose register (aka GPR) with some predefined value (64-bit
126 integer with value 0x5555).
127
128 Now let's turn to logs to see how they correspond to what we see.
129 The lines of interest are `reading reg RA 3 0` and `reading reg RB 2 0`.
130 These, unsurprisingly, are two registers (`3` and `2`) which act as
131 input parameters to `add` instruction; the result is then placed as
132 an output into register `1`.
133
134 Note that the initial values for registers `3` and `2` are `0x1234` and `0x4321`
135 respectively, and this matches to the input parameters in the logs:
136 ```
137 inputs [SelectableInt(value=0x1234, bits=64), SelectableInt(value=0x4321, bits=64)]
138 ```
139
140 The simulator performs the actual computation, obtaining the result, and then
141 updates the general-purpose register we used as an output parameter:
142 ```
143 results (SelectableInt(value=0x5555, bits=64),)
144 writing gpr 1 SelectableInt(value=0x5555, bits=64) 0
145 ```
146
147 In the end, we see that our assertion indeed passes:
148 ```
149 __eq__ SelectableInt(value=0x5555, bits=64) SelectableInt(value=0x5555, bits=64)
150 ```
151
152 You can play around the test, e.g. modify the input/output registers (there are
153 32 GPRs, so there's a plethora of combinations possible). In the next chapter,
154 we're going to take a deeper look and cover some bits of implementation.