YouTube2Text

W4 RISC V ISA II EN — Transcript

by Hasan Erdem Yantır · 14,512 words · 2,589 segments · language en · Watch on YouTube

Full transcript

  1. 0:11So, starting from this class, also
  2. 0:15in in this class also we'll continue to
  3. 0:17respect instruction set architecture and
  4. 0:19machine language.
  5. 0:20And after this
  6. 0:22class inshallah, we are going to start
  7. 0:24to see the actual hardware
  8. 0:26implementation of a RISC-V processor.
  9. 0:30So, in the last class we we said that
  10. 0:32binary representation of instructions
  11. 0:36is only in terms of ones and zeros. So,
  12. 0:39because computers only understand ones
  13. 0:41and zeros. And in RISC-V
  14. 0:44all instructions are 32-bit except for
  15. 0:48the compressed case. If your processor
  16. 0:50supports the compressed case, then
  17. 0:52instructions can be also 16-bit.
  18. 0:55The good point in here
  19. 0:58that RISC-V follow all of these
  20. 1:00principles, simplicity favors
  21. 1:02regularity.
  22. 1:04The
  23. 1:05For example, in Intel
  24. 1:07instructions are between 1 byte and 16
  25. 1:10byte. Maybe it changed because they are
  26. 1:12changing their ISA instruction set
  27. 1:14architecture a lot.
  28. 1:15But in Intel, for example, all
  29. 1:17instructions can be between 1 and 16
  30. 1:21byte in x86.
  31. 1:24But in RISC-V
  32. 1:26it is simple. All instructions are
  33. 1:2832-bit.
  34. 1:30And if there is a C extension, it is not
  35. 1:33mandatory
  36. 1:34then 16-bit instructions are also
  37. 1:36supported.
  38. 1:38And we saw the four types of instruction
  39. 1:40formats, R, I, S, U type.
  40. 1:43And in here, this figure shows the
  41. 1:46immediate encoding depending on the
  42. 1:49instruction type.
  43. 1:52And in here you can see that the
  44. 1:55immediate
  45. 1:56uh total immediate 31-bit
  46. 1:59and its organization immediate
  47. 2:02organization. For example, for B-type
  48. 2:04instructions, immediate zero is always
  49. 2:06zero because it is a jump instruction.
  50. 2:08And since we are jumping in terms of
  51. 2:1016-bits, its least significant bit is
  52. 2:13always zero.
  53. 2:17And other
  54. 2:19parts of the immediate, for example,
  55. 2:21designed in this way.
  56. 2:25And this immediate is important because
  57. 2:27we have some instructions that also has
  58. 2:30immediate field.
  59. 2:31Uh
  60. 2:32so, in here, there is a
  61. 2:35important point. For example, we have a
  62. 2:38add immediate instruction,
  63. 2:40but we don't have subtract immediate.
  64. 2:42Why?
  65. 2:45Because it is unnecessary.
  66. 2:47The difference between add immediate and
  67. 2:50sub immediate,
  68. 2:53for example, add immediate and sub
  69. 2:54immediate. So, instead of
  70. 2:59For example, you want to subtract minus
  71. 3:01X.
  72. 3:04For sorry, you want to subtract X, for
  73. 3:06example. So, instead of defining a sub
  74. 3:10sub immediate instruction, in add
  75. 3:12immediate, you can use minus X. So,
  76. 3:14adding with minus X is equal to
  77. 3:16subtracting
  78. 3:18it X.
  79. 3:19So, since compiler can do it very
  80. 3:22easily, RISC-V is not putting any
  81. 3:24instruction for it.
  82. 3:25Because compiler can do it. So, there is
  83. 3:27no need to put another instruction. In
  84. 3:30this way, our hardware becomes simpler.
  85. 3:32So, this is the very good point for
  86. 3:34RISC-V. If the instruction can be
  87. 3:39generated by the compiler, then RISC-V
  88. 3:41is not putting it in instruction set
  89. 3:43architecture.
  90. 3:45This is also another figure that shows
  91. 3:47the immediate encoding in RISC-V.
  92. 3:50So, immediate bits
  93. 3:52mostly occupy constant instruction bits.
  94. 3:55As you can see in here, for example, the
  95. 3:57place of RS1, depending on the
  96. 4:00uh
  97. 4:02this instruction types, the place of RS1
  98. 4:05is same, RS place of RS2 is same,
  99. 4:08function three is always same.
  100. 4:11For this reason, immediate is a little
  101. 4:13bit distributed. In the last class, we
  102. 4:16we mentioned about it, but we didn't
  103. 4:18mention why it is distributed. You can
  104. 4:21see the reasoning in here.
  105. 4:24And sign bit is always at 31 location.
  106. 4:27Location of 31 shows the sign bit.
  107. 4:30It's a most significant bit of
  108. 4:32instruction.
  109. 4:34So, this way, this immediate encoding
  110. 4:36simplifies the hardware to build the
  111. 4:38micro micro processor.
  112. 4:48So, this is figure also shows the
  113. 4:5132-bit immediate fields
  114. 4:53and type of instruction formats.
  115. 4:56Uh you can check it then.
  116. 4:59But, of course, you don't need to
  117. 5:00memorize them. No need for to memorize
  118. 5:03them.
  119. 5:06There is one exception in here.
  120. 5:09Previously, I mentioned that there are
  121. 5:11some instruction format RISC-V
  122. 5:14UJ.
  123. 5:15And
  124. 5:18in floating point, there are different
  125. 5:21There is a different format. It's named
  126. 5:23as R4 type. And this is important for
  127. 5:26you if you are implementing the floating
  128. 5:28point extension.
  129. 5:31So,
  130. 5:32in this R4 type, there are four RS uh
  131. 5:36There are three RS fields. And total,
  132. 5:40there are four registers.
  133. 5:43The difference is that in here, there is
  134. 5:45RS1, RS2, but there is also RS3. Because
  135. 5:48it is multiply and add instruction. What
  136. 5:49is a multiply and add instruction?
  137. 5:52RD is equal to RS1 * RS2 + RS3.
  138. 5:57So, this is
  139. 5:59a
  140. 5:59instruction specific to floating point
  141. 6:02floating point extension FD and Q
  142. 6:05extensions.
  143. 6:07And in this format,
  144. 6:08this is R4 type. R4 means that there are
  145. 6:11four registers in this format.
  146. 6:14But, this is not important for you. If
  147. 6:16you are not implementing floating point
  148. 6:17operations, then this is not a
  149. 6:19uh interest for you.
  150. 6:27This slide shows the compressed
  151. 6:29instruction formats. In the last class,
  152. 6:32I briefly mentioned that in compressed
  153. 6:34instruction formats, you can access only
  154. 6:36a limited set of registers.
  155. 6:39For example, in here, it says that if
  156. 6:41the instruction is compressed, then you
  157. 6:44can specify specify registers between X8
  158. 6:47and X15 only.
  159. 6:49We are using 3-bit register.
  160. 6:51And in this 3-bit, by using this 3-bit,
  161. 6:53you are
  162. 6:54encoding these eight registers between
  163. 6:56X8 and X15. And compressed instructions
  164. 7:01has different formats.
  165. 7:03They have different formats.
  166. 7:06Uh in here, immediates are changing
  167. 7:09between six and 11 bits. Opcode is two
  168. 7:11bits only. This opcode is only two bit.
  169. 7:16And these are the types.
  170. 7:18But, of course, you don't need to
  171. 7:19memorize them. Even we are developing
  172. 7:21lots of RISC-V processor, we are not
  173. 7:23memorizing them. We are just checking
  174. 7:25while developing.
  175. 7:26Uh we are checking them, applying them,
  176. 7:28then that's all.
  177. 7:30But, the good to good point in here is
  178. 7:32that RISC-V if there is an RS1 in an
  179. 7:36instruction, then it place is always
  180. 7:38same. This is a good thing for RISC-V.
  181. 7:41For example, in ARM, uh it is arm is not
  182. 7:44following this convention.
  183. 7:46The
  184. 7:46location of RS1 is changing in arm
  185. 7:49architecture.
  186. 7:51Since in RISC-V it is in the same
  187. 7:53location, when you implement a decoder
  188. 7:56in SystemVerilog, then your decoder
  189. 7:59works faster than arm's decoders. This
  190. 8:01is a good point for RISC-V.
  191. 8:05In here, there is a
  192. 8:07example about interpreting information
  193. 8:10language.
  194. 8:11You see, we have a instruction in here.
  195. 8:14It's 0x41.
  196. 8:17This instruction
  197. 8:19is hexadecimal format, and this is the
  198. 8:20binary format.
  199. 8:22For example, you want to disassemble
  200. 8:24this this
  201. 8:26binary code.
  202. 8:28Disassemble means that for example,
  203. 8:30assembly means that you are converting
  204. 8:33the instruction to assembly assembly
  205. 8:35version. Disassembly means that you are
  206. 8:37converting the binary to
  207. 8:40assembly version. Disassembly.
  208. 8:42So, assembly means that like converting
  209. 8:44the
  210. 8:46assembly instruction
  211. 8:48to binary version. Disassembly is the
  212. 8:50reverse of it.
  213. 8:51So, for example, if I want to do
  214. 8:54disassembly, get the disassembly version
  215. 8:56of this
  216. 8:57instruction,
  217. 8:59then in here, the first step is that to
  218. 9:01look at the op field and understand the
  219. 9:04operation type.
  220. 9:05For example, in here, it's op is 51.
  221. 9:09And function if op is 51, then it is
  222. 9:12related to an addition, subtraction, and
  223. 9:15or any operations between them.
  224. 9:18And then function is function three is
  225. 9:20the
  226. 9:21is the field that specifies the type
  227. 9:23type of the operation.
  228. 9:25So, in here, I'm taking function three,
  229. 9:26and it is zero. Then it is either
  230. 9:31add or sub instruction. So, in this
  231. 9:33case, I'm taking the function seven
  232. 9:35field,
  233. 9:36and then understand that this is a sub
  234. 9:38instruction.
  235. 9:39So, you need to first start with op
  236. 9:41and then depending on op
  237. 9:44you need to look at function three and
  238. 9:46function seven, but of course in in some
  239. 9:48instructions there is no function three,
  240. 9:50for example.
  241. 9:52Function seven itself is on is enough in
  242. 9:55this case.
  243. 9:57So, and this is also another instruction
  244. 9:59that corresponds to add immediate I type
  245. 10:01instruction. For example, in here there
  246. 10:03is no function seven, right? We are we
  247. 10:06can see that op is 19.
  248. 10:09So, 19 is add immediate immediately if
  249. 10:12its function three is 000 and we are not
  250. 10:14looking to function seven, for example,
  251. 10:16in here.
  252. 10:18Most likely you will not do this
  253. 10:20uh disassembly yourself. We are always
  254. 10:23using the
  255. 10:25tools to do disassembling,
  256. 10:28but this is the methodology to do it.
  257. 10:38And this is the machine code.
  258. 10:40It's It's field specific fields of these
  259. 10:42two two
  260. 10:44instructions.
  261. 10:48So, this is a summary for the
  262. 10:49instruction formats formats.
  263. 10:54Uh
  264. 10:55and in here SP and UG are near the same,
  265. 11:00but their immediate encoding is changing
  266. 11:02a little bit.
  267. 11:04For example, for S type
  268. 11:06immediate zero is important because in S
  269. 11:08type we are doing
  270. 11:10store, for example, uh memory operations
  271. 11:13actually by using S type.
  272. 11:15Uh but, for example, in B type we are
  273. 11:18jumping. This is jump and branch
  274. 11:20instructions, for example, in G type or
  275. 11:22B type. Then in this case immediate zero
  276. 11:24is always zero, for example, immediate
  277. 11:26starts from one in these instructions.
  278. 11:29Because it's always
  279. 11:30uh immediate zero, first bit of the
  280. 11:32immediate is zero in this in this
  281. 11:35instructions.
  282. 11:36implicitly
  283. 11:40Is there any questions until this point?
  284. 11:47Then we can switch to RISC-V programming
  285. 11:50section and we can inspect some RISC-V
  286. 11:53programming examples
  287. 11:56and then start the architecture. Because
  288. 11:58in order to build an architecture, you
  289. 12:00need to know how to program this
  290. 12:02architecture.
  291. 12:03Uh until now in the first four weeks
  292. 12:07uh we
  293. 12:09solved uh
  294. 12:11some System Verilog and then
  295. 12:14uh instruction set architecture specific
  296. 12:15topics. And starting from the next
  297. 12:17lecture, inshallah, we are going to see
  298. 12:19the
  299. 12:20hardware microarchitecture
  300. 12:22implementation. So in in we were
  301. 12:25starting with big A architecture
  302. 12:27architecture.
  303. 12:28Then we will switch to go down to one
  304. 12:30level below
  305. 12:32and look at the microarchitecture
  306. 12:34implementation.
  307. 12:37So this The first topic is the
  308. 12:39conditional statements, if statement,
  309. 12:41if-else statement, loops and loops,
  310. 12:43while and for loops.
  311. 12:48You see there is a C code in here.
  312. 12:51C code checks whether I is equal to G
  313. 12:54and if it is equal, then
  314. 12:56it does this computation.
  315. 12:58Otherwise
  316. 13:00it continues and does this computation.
  317. 13:03But in any case, this computation is
  318. 13:05done, but this condition this
  319. 13:07operation is conditional
  320. 13:10and depends on this condition.
  321. 13:13So how can we write a RISC-V assembly
  322. 13:15code for this specific C code?
  323. 13:19Normally, we are not writing
  324. 13:21writing RISC-V assembly codes. We are
  325. 13:24generally writing C code.
  326. 13:26But in here, since we are trying to be
  327. 13:28familiar with the instruction set
  328. 13:30architecture, we need to see how C code
  329. 13:33is converted to RISC-V assembly.
  330. 13:38In here,
  331. 13:39we can use branch equal or branch not
  332. 13:41equal instruction.
  333. 13:43In this example, when compiler converts,
  334. 13:48compiler used branch not equal
  335. 13:49instruction. And these are the initial
  336. 13:52location of these values. For example,
  337. 13:55S0 register keeps the value of F F, S1
  338. 13:59keeps the value of G G.
  339. 14:02And in the first
  340. 14:04instruction, it compares S3 with S4. S3
  341. 14:10is I and S4 is J. So, it does this
  342. 14:13comparison. But, it is doing the reverse
  343. 14:15of it, not equal.
  344. 14:17It is saying that if they are not equal,
  345. 14:20then jump to L1.
  346. 14:22L1 label.
  347. 14:24So, it is saying that if they are not
  348. 14:26equal, this I is not equal to G, then
  349. 14:30jump to here directly. It's the reverse
  350. 14:32of it.
  351. 14:35If they are equal,
  352. 14:37then it continues,
  353. 14:39and at then it also does this operation,
  354. 14:42sub operation.
  355. 14:43So, it it compares these two registers,
  356. 14:46and then
  357. 14:48does this operation. This is This
  358. 14:50corresponds to this F equal to G plus H
  359. 14:53operation corresponds to this add.
  360. 14:56And then it adds S0 and S1,
  361. 14:58which is G and H.
  362. 15:00And then it continues and does the sub
  363. 15:02operation. But, if they are not equal,
  364. 15:04then it jumps to L1. It doesn't run this
  365. 15:07It doesn't run this uh
  366. 15:09instruction, then jumps to L1 point
  367. 15:12immediately.
  368. 15:17In here, there is a if else one. If else
  369. 15:20is different, because in the previous
  370. 15:22version, we were running
  371. 15:24We are running this
  372. 15:27this instruction in any case, but in
  373. 15:29here
  374. 15:30we should either run this one or this
  375. 15:33one.
  376. 15:34And in if else version of it
  377. 15:38still we are looking to branch not
  378. 15:39equal.
  379. 15:41And if they are not equal, we are going
  380. 15:44we are switching to this else statement
  381. 15:47and running this else statement.
  382. 15:49But since
  383. 15:51either I should run this one or this one
  384. 15:55then
  385. 15:56after if they are not equal
  386. 15:59uh
  387. 16:00if they are equal, then
  388. 16:02we run this add instruction. We execute
  389. 16:05this
  390. 16:06add instruction.
  391. 16:07But after doing this instruction, I need
  392. 16:10to jump to this point because I
  393. 16:11shouldn't run
  394. 16:13this this instruction. For this reason,
  395. 16:15we are putting compiler puts a G done to
  396. 16:18here. G done means get jump jump done.
  397. 16:22So, it directly jumps after if they are
  398. 16:25equal
  399. 16:26then it runs this add instruction, then
  400. 16:29comes to here, then
  401. 16:31jumps to this done location without
  402. 16:33running this instruction.
  403. 16:35Is it clear, right?
  404. 16:43In here, there is also another example.
  405. 16:45It is for while loops.
  406. 16:48Our C code
  407. 16:53tries to compute two two to the X, two
  408. 16:55to the power of X.
  409. 16:57Uh actually, it determines the power of
  410. 17:00X such that two to the X is 128.
  411. 17:04So, it tries to find this X. What is
  412. 17:07this X value of X?
  413. 17:09So,
  414. 17:10in here, I have two variables in C code.
  415. 17:13One of them is pow. It starts with one
  416. 17:15and X
  417. 17:16is zero.
  418. 17:18And I'm always doing this computation
  419. 17:21both both times two and increasing to X
  420. 17:25each time by one.
  421. 17:27And trying to find
  422. 17:29trying to loop in here until both
  423. 17:32becomes 128, and then it exits this
  424. 17:35loop.
  425. 17:36So, in this case, I I can find that this
  426. 17:38X value.
  427. 17:40And what is the RISC-V assembly code in
  428. 17:42here?
  429. 17:43I am doing some initialization.
  430. 17:47S0 becomes one.
  431. 17:500 + 1 S0 S0
  432. 17:52becomes one.
  433. 17:54Uh it is X.
  434. 17:56Uh sorry, it is it is it is one. It is
  435. 17:58it is pow pow.
  436. 18:00Uh
  437. 18:01S1 is zero.
  438. 18:02Then it is it is X.
  439. 18:05And then
  440. 18:06for this constant, I am loading it to
  441. 18:08the T0 register.
  442. 18:10Uh in order to to load it, I'm just
  443. 18:13doing a basic addition. Add immediate. 0
  444. 18:15+ 128. Zero register is always zero. 0 +
  445. 18:18128. T0 keeps the 128.
  446. 18:22And then while loop starts here. This is
  447. 18:25a label for the while loop.
  448. 18:28I am doing a comparison in here. If S0
  449. 18:30is equal to T0,
  450. 18:32if it is
  451. 18:34equal, it means that S0 is equal to 128.
  452. 18:37If it is
  453. 18:39equal, we are
  454. 18:40going to we are jumping to this done
  455. 18:42location. Otherwise,
  456. 18:44we are doing multiplication operation in
  457. 18:46here. But for multiplication, we are not
  458. 18:49using multiplication instruction.
  459. 18:51Instead, we are doing one-bit shift.
  460. 18:54One-bit
  461. 18:55left shift means that multiply by two in
  462. 18:58binary. So, we are doing one-bit left
  463. 19:01shift
  464. 19:02immediate uh immediate shift. Immediate
  465. 19:05is one in here. And then doing addition
  466. 19:07instruction to increase this X counter.
  467. 19:11And after this operation, jumping to the
  468. 19:14beginning of the while. So,
  469. 19:16after some iterations,
  470. 19:20when
  471. 19:21power becomes 128 as a result of this
  472. 19:24comparison,
  473. 19:26we are jumping to done. And at that
  474. 19:27point, this S1
  475. 19:30register keeps the value of X that shows
  476. 19:32to this X.
  477. 19:36The value of X that
  478. 19:38it's
  479. 19:392 to the power of like X becomes 128.
  480. 19:46This was while loops. And in for loop,
  481. 19:50uh there are four parts in for loop.
  482. 19:53Uh one of them is initialization. One of
  483. 19:56them is condition, loop operation, and
  484. 19:58statement.
  485. 19:59So, you know for loop, right? In you you
  486. 20:02are familiar with the C programming or
  487. 20:03MATLAB or in any programming language,
  488. 20:06you know the for loops.
  489. 20:08So, in here, I have a C code. And this C
  490. 20:11code at the numbers from 0 to 9.
  491. 20:14And it computes
  492. 20:16the result in sum.
  493. 20:18And I is my
  494. 20:19counter in here, for loop counter.
  495. 20:22When you look at its respect assembly
  496. 20:24code,
  497. 20:26uh S1 corresponds to the sum. It starts
  498. 20:29with 0. And S0 starts with
  499. 20:33S0 is I.
  500. 20:35And this I starts with
  501. 20:370. It's initialized at 0 in for loops.
  502. 20:42And I have also a constant in here, 10.
  503. 20:45We
  504. 20:46We This is my limit.
  505. 20:48And at each time,
  506. 20:50uh
  507. 20:50I am comparing whether S0, which is my
  508. 20:54I counter, is equal to one or 10 or not.
  509. 20:58And if it is 10,
  510. 21:00then
  511. 21:01jumping to done location. Otherwise,
  512. 21:04I'm doing this computation. This
  513. 21:06computation and this computation is done
  514. 21:09in this in here.
  515. 21:11So, we are increasing the
  516. 21:14sum in here. Sum is
  517. 21:16increased by S0 each time and then S0 is
  518. 21:20increased by one also.
  519. 21:23And whenever this I becomes 10,
  520. 21:27it jumps to done and sum is
  521. 21:31resulted as a
  522. 21:33addition of the numbers from zero to
  523. 21:34nine.
  524. 21:43In here, there is also another
  525. 21:45C code example. It adds the power of two
  526. 21:47from one to 100.
  527. 21:55So, this is the corresponding code then.
  528. 21:59Sum starts with zero. I starts with from
  529. 22:02one. You can see the initialization in
  530. 22:04here.
  531. 22:05Here is initialization. And then in
  532. 22:08here, there's condition check.
  533. 22:11And this
  534. 22:14multiply by two operation done by shift
  535. 22:17left.
  536. 22:18And this is the summation operation done
  537. 22:21in here.
  538. 22:25Generally, by the way, we are not
  539. 22:27writing assembly code, but for example,
  540. 22:30if you design for example, you design
  541. 22:32the RISC-V processor and you want to
  542. 22:34test some specific cases, in this case,
  543. 22:36we are writing assembly code. But
  544. 22:37generally, nobody writes assembly code.
  545. 22:43We are all writing the C code or higher
  546. 22:46level C++, C# codes and then compiling
  547. 22:49them for RISC-V processor.
  548. 22:55And by the way, most people are not even
  549. 22:56writing code. They are just using the
  550. 22:58AI.
  551. 23:03This is an alternative version of this
  552. 23:05example.
  553. 23:09In here, I was using directly
  554. 23:12branch greater equal instruction.
  555. 23:15In here, I am using set less than
  556. 23:18operation. Set less than operation
  557. 23:20compares these two uh these S0 and T0
  558. 23:23registers.
  559. 23:24And if it is less than
  560. 23:26it makes T2 one.
  561. 23:30Otherwise, it makes T2 zero. Then in
  562. 23:33here, we can check whether T2 is zero or
  563. 23:36not
  564. 23:38by comparing it with the zero register.
  565. 23:40Because zero register X0 is all zero,
  566. 23:43always zero. Then we are comparing
  567. 23:45whether T2 is zero or not. It means that
  568. 23:48uh
  569. 23:49S0 is greater than Yeah, it checks the
  570. 23:51whether S0 greater than T0 or not.
  571. 23:57So, but this version is more preferable,
  572. 24:00right? Because it has less code.
  573. 24:02In here, I am executing one more code.
  574. 24:05Then one more code means that it it
  575. 24:07takes one more step, especially in the
  576. 24:09loop.
  577. 24:10Uh it takes one more instructions. So,
  578. 24:13this code, for example, if this loop
  579. 24:15runs 100 times,
  580. 24:17this code adds 100 cycle more because it
  581. 24:20has one more instructions. Since we are
  582. 24:22running the instruction cycle cycle, in
  583. 24:24each cycle I'm assume that in each cycle
  584. 24:27I am running one instruction.
  585. 24:29Then since there is a one more
  586. 24:30instruction in here, then it takes 100
  587. 24:33cycle more. So, for this reason, this is
  588. 24:36not good. If your code size is
  589. 24:38less than most likely,
  590. 24:41uh your
  591. 24:42program runs faster.
  592. 24:47But of course, there are some outlier
  593. 24:49cases for for it.
  594. 24:56RISC-V
  595. 24:57uh
  596. 24:58in for example in this five we are doing
  597. 25:00all addition operations in terms of
  598. 25:0332-bit if the processor is 32-bit.
  599. 25:08And in 32-bit operations generally the
  600. 25:11result can be 32-bit, right? Because
  601. 25:14if you are adding for example one one
  602. 25:17two one bit numbers, then result is two
  603. 25:19bit.
  604. 25:20It can for example if numbers is zero or
  605. 25:24one, then result can be two also and two
  606. 25:27can be represented by two bits.
  607. 25:30In a similar way, if you add two 32-bit
  608. 25:33numbers, generally result is normally
  609. 25:3533-bit because there must be a one
  610. 25:38overflow bit.
  611. 25:40Uh but RISC-V doesn't provide
  612. 25:42unsigned addition or instructions or
  613. 25:44overflow detection because it can be
  614. 25:46done with existing instructions.
  615. 25:49So for example in ARM architecture,
  616. 25:53assume there is a ARM 32-bit
  617. 25:55architecture,
  618. 25:56there is an addition operation
  619. 25:58and if this addition operation
  620. 26:02uh
  621. 26:03overflows, ARM has some flag bits and
  622. 26:06these flag bits are set so that you can
  623. 26:08check these flag bits and understand
  624. 26:10that this operation
  625. 26:12is overflowed.
  626. 26:14But in RISC-V, they don't need any
  627. 26:17necessity for it. So they didn't put any
  628. 26:19overflow checks and they are saying that
  629. 26:22if you want to check overflow, you only
  630. 26:25need to write your code in this way.
  631. 26:27In your code, you can explicitly check
  632. 26:30the overflow case. This is the RISC-V
  633. 26:32methodology. So instead of dealing it
  634. 26:34with in the hardware, they are saying
  635. 26:36that software software developers should
  636. 26:38should deal with them if they if they
  637. 26:41care. This is a good philosophy.
  638. 26:43For this reason, hardware becomes much
  639. 26:45simpler and simpler hardware means
  640. 26:47faster
  641. 26:49and it is also more efficient, more area
  642. 26:51efficient.
  643. 26:52And of course, you can detect the
  644. 26:54overflow very easily. For example, you
  645. 26:57can check, for example, detecting
  646. 26:59unsigned overflow, you can add two
  647. 27:01unsigned numbers
  648. 27:02and check
  649. 27:05in terms of, for example,
  650. 27:07uh you can say that branch less than
  651. 27:09unsigned comparison, you can do uh
  652. 27:11branch less than unsigned comparison and
  653. 27:13compare these two values.
  654. 27:15If then, for example, if you are adding
  655. 27:17two numbers and your result is less
  656. 27:20than, then it means that it overflowed.
  657. 27:24This is to detect unsigned overflow, and
  658. 27:27this is the way to detect signed
  659. 27:29overflow, for example. Signed overflow
  660. 27:31adds more
  661. 27:32instructions, for example. In here, in
  662. 27:35if you want to detect signed overflow,
  663. 27:37then you need to add, for example, three
  664. 27:39more instructions in
  665. 27:41unsigned overflow, you need to add one
  666. 27:43more instructions.
  667. 27:45But, most of the case, we don't care
  668. 27:47whether it is overflowed or not. For
  669. 27:49this reason, this is a good methodology
  670. 27:51to not
  671. 27:53check hardware hardware
  672. 27:56uh
  673. 27:57not put a mechanism
  674. 27:59that hardware checks this overflow. So,
  675. 28:01instead of that, software developers
  676. 28:03need to write this code explicitly.
  677. 28:08Is this point clear?
  678. 28:29Okay. So, we will start arrays.
  679. 28:42You know those C programming arrays?
  680. 28:44For example, in here, in memory, I have
  681. 28:47a five element array.
  682. 28:49And this five element array starts from
  683. 28:51this base address.
  684. 28:54Assume that it is five elements
  685. 28:57and each array element is 32-bit.
  686. 29:00And it starts from this base address.
  687. 29:03This one, this base address. So, in this
  688. 29:06base address, array zero corresponds to
  689. 29:08this, array one corresponds to this one,
  690. 29:10and you will see since this array is
  691. 29:1332-bit and this five element memory is
  692. 29:15byte addressable
  693. 29:16in
  694. 29:17each element
  695. 29:20our address is incremented by four 4-bit
  696. 29:24because it is byte addressable and each
  697. 29:25element is 32-bit. So, you will see it
  698. 29:29is 4-bit plus 4-bit plus 4-bit plus.
  699. 29:32So, this total array, if it is if there
  700. 29:35are five elements, then this total array
  701. 29:39is
  702. 29:4130 byte actually.
  703. 29:4320 byte, sorry.
  704. 29:455 * 4, it is 20 byte.
  705. 29:49So,
  706. 29:50in here, I have a C code and C code is
  707. 29:53defined an array and this array is in
  708. 29:56memory in this base address.
  709. 29:59And
  710. 30:00in this C code, we are doing this
  711. 30:02calculation.
  712. 30:03We are multiplying array zero with by
  713. 30:06two and array one by two and writing it
  714. 30:08back.
  715. 30:10So, since in here, in this example, in
  716. 30:12the previous examples, we were doing the
  717. 30:14computations all over registers, but now
  718. 30:17we are not using registers. We are using
  719. 30:19the memory addresses.
  720. 30:22First, in this case, we need to use load
  721. 30:24and store operations to access the
  722. 30:26memory locations. So, in order to get
  723. 30:28the data from memory, I need to use load
  724. 30:30operation. In order to store it back to
  725. 30:33memory, I need to use store operations.
  726. 30:38So, this is the RISC-V assembly code
  727. 30:41for this array operations.
  728. 30:44In here, you know, first I know that
  729. 30:48this array is stored in this address.
  730. 30:50The starting location of the array is in
  731. 30:53this address.
  732. 30:55And I know that compiler knows it
  733. 30:57because compiler is the tool that place
  734. 31:00the arrays while compiling the code
  735. 31:02because if this code has data also in
  736. 31:05it,
  737. 31:05then compiler knows its address and
  738. 31:08compiler assigns an address inside the
  739. 31:10memory region.
  740. 31:12And this is the assigned address for
  741. 31:14this array.
  742. 31:16So, in here,
  743. 31:18since this array address,
  744. 31:20this is 32-bit, address is also 32-bit.
  745. 31:23Since address is 32-bit, in order to
  746. 31:26load this array
  747. 31:27array address to S0 register,
  748. 31:30I cannot use I cannot do it in one
  749. 31:32instruction.
  750. 31:34I am using two instructions. In in the
  751. 31:37previous
  752. 31:39lecture, we we saw this concept. In this
  753. 31:42lecture, we are seeing the practical
  754. 31:44example of it. So, in here, I want to
  755. 31:46load the
  756. 31:48this base address of the array to S0
  757. 31:51register. So, how can do I do it? I need
  758. 31:54to run two instructions. One of them is
  759. 31:56load upper immediate. Load upper
  760. 31:58immediate takes this part
  761. 32:01of the instruction and load it to the
  762. 32:04upper 20 bits of S0 register.
  763. 32:08So, this is the 20-bit immediate.
  764. 32:11It gets 20-bit immediate and loads it to
  765. 32:15the upper bit portion of S0 register.
  766. 32:18And then for this remaining part, I am
  767. 32:21doing add immediate operation and this
  768. 32:23is the
  769. 32:2412-bit immediate.
  770. 32:26Then in this case, by running these two
  771. 32:28instructions, S0 becomes this address.
  772. 32:31So, I can get the address of the array
  773. 32:33in this way from S0.
  774. 32:37And then in order to access the first
  775. 32:39element of the array, then first element
  776. 32:42is in this location. By the way, this is
  777. 32:44the also first element means that the
  778. 32:46pointer of the array.
  779. 32:48Uh this is a concept belongs to the
  780. 32:50programming class.
  781. 32:52So, this array zero, which is the array
  782. 32:54pointer,
  783. 32:56uh
  784. 32:57this corresponds to the first element of
  785. 32:59the array.
  786. 33:00So, in order to load the first element
  787. 33:02of array, I am just running a load word
  788. 33:05command, and load word command in here
  789. 33:08takes the address of S0, adds S0 to it,
  790. 33:11so it points here.
  791. 33:14And loads this value to T1. This load
  792. 33:17word says that this is 32-bit load.
  793. 33:20And loads it to T1.
  794. 33:23Now, T1 keeps the first value of array,
  795. 33:26which is array zero.
  796. 33:28Then, in here, I am doing shift left by
  797. 33:31one bit. It means that in binary,
  798. 33:34multiply by two.
  799. 33:36I'm doing multiplication by two and
  800. 33:38storing the result to T1. Then,
  801. 33:41here,
  802. 33:42the turn is stored.
  803. 33:46This is the array address, array zero
  804. 33:50address. The C code says that
  805. 33:53I need to store it back to same
  806. 33:55location.
  807. 33:56So, I am running a store word operation
  808. 33:59in here.
  809. 34:00Then, store word address is S0 plus
  810. 34:03zero, which is this address still. And
  811. 34:07then,
  812. 34:08loads this T1 value to here. So, T1,
  813. 34:11which is the multiplied by two version
  814. 34:14of the
  815. 34:15of the initial value, then storing it
  816. 34:17back to the this location.
  817. 34:19And I'm doing it for the array one,
  818. 34:21also. In array one, doing the same
  819. 34:24operation, but this time, my index is
  820. 34:27four,
  821. 34:28because it's the array one.
  822. 34:30S0 plus four goes to this location, this
  823. 34:34one.
  824. 34:35Loading it, multiplying by two, and then
  825. 34:37writing it back to this location.
  826. 34:43I can do it in a for loop also, for all
  827. 34:45array elements also, right? I can write
  828. 34:48a for loop and in each
  829. 34:50for loop, I can multiply one element of
  830. 34:53array, for example, by two or do some
  831. 34:55operations on it. In here, there is an
  832. 34:57example code for it.
  833. 35:00Uh starting from zero to one 1,000,
  834. 35:04I'm loading the array.
  835. 35:06In here, this is the addressing.
  836. 35:09In here, for example, instead of using
  837. 35:11an immediate,
  838. 35:13compiler gives the code of or immediate,
  839. 35:15but doesn't matter. It's just immediate
  840. 35:18this
  841. 35:19with this one, so it means that I am
  842. 35:21keep I am placing this 12-bit value to
  843. 35:24here, so it forms 32-bit value still.
  844. 35:28It can use or immediate or add
  845. 35:30immediate, doesn't matter. It is It is
  846. 35:32giving the same value, which is the
  847. 35:34address of the array and storing it to
  848. 35:37the S0 location. So, S0 becomes this
  849. 35:39value.
  850. 35:40And then I have S1, which is the I
  851. 35:44value, and T2. T2 is the uh this
  852. 35:48constant value, 1,000 1,000.
  853. 35:51And then in the loop, I'm comparing
  854. 35:54whether I am
  855. 35:55greater equal to T2 value.
  856. 35:59If not,
  857. 36:00I am doing the multiplication in here.
  858. 36:02Uh not not multiplication.
  859. 36:05I am comparing the in I am computing the
  860. 36:08index in here. Since S1 is the byte
  861. 36:11offset,
  862. 36:13this this I,
  863. 36:15uh I am multiplying it by two to find
  864. 36:18the
  865. 36:19uh actual array index, because array is
  866. 36:2332-bit. Each element of the array is
  867. 36:2432-bit. In this case, in order to access
  868. 36:27the array actual location of the array,
  869. 36:30for example, if you want to access array
  870. 36:3210,
  871. 36:34you need to get base address of array
  872. 36:37plus 10 * 4 because each array element
  873. 36:41is 4 bytes. For this reason, you need to
  874. 36:44do this computation base address plus 10
  875. 36:46* 4. So, base address plus 40
  876. 36:50corresponds to array 10.
  877. 36:5210th element of two array.
  878. 36:54So, in here, I'm doing this computation.
  879. 36:57Then,
  880. 36:58I am finding the address of array. I'm
  881. 37:01adding it to the base address of the
  882. 37:02array, then loading array, then
  883. 37:06multiplying it by eight, then storing it
  884. 37:08back, and then increasing my I
  885. 37:11by one. Each time, I'm increasing the I
  886. 37:13by one.
  887. 37:15And then doing it for the array one,
  888. 37:17array two, until array 1,000.
  889. 37:20Is this example clear?
  890. 37:24Okay.
  891. 37:25For example, instead of int,
  892. 37:28this is same int. For example, assume
  893. 37:30that this is
  894. 37:32uh short.
  895. 37:35Short was 16-bit, right?
  896. 37:39Or in this case, instead of
  897. 37:42multiplying this index by two, I have to
  898. 37:46multiply
  899. 37:47So, sorry. Instead of multiplying it by
  900. 37:50four,
  901. 37:51it means that two shift left,
  902. 37:53I have to multiply it by two because
  903. 37:56each array element is two bytes. So, in
  904. 37:59here,
  905. 38:00we
  906. 38:02had to write one to here
  907. 38:04to multiply it by two. If this is byte,
  908. 38:08for example, assume that this is byte.
  909. 38:11There is no byte. It is char, for
  910. 38:13example. Char is 8-bit. If it is 8-bit,
  911. 38:17then there is no need to do any
  912. 38:18computation
  913. 38:19because each time my index is increased
  914. 38:22by one, so it it is increasing one byte
  915. 38:25each time.
  916. 38:26Is it clear?
  917. 38:32Okay.
  918. 38:37In there is also another concept RISC-V
  919. 38:40function calls.
  920. 38:43>> [clears throat]
  921. 38:44>> In a RISC-V there are two terminology,
  922. 38:46not in this not in RISC-V it in
  923. 38:49programming there are two terminology.
  924. 38:50One of them is caller and one one of
  925. 38:52them is callee.
  926. 38:54Uh caller is the calling function. If
  927. 38:56you are calling a function for example,
  928. 38:59for example you are calling a addition
  929. 39:00function, then you are the caller. You
  930. 39:02are running this function. For example,
  931. 39:04if main your main
  932. 39:07program calls the function of add, then
  933. 39:11main is the caller in here. So, the
  934. 39:15duty of the duties of the main is it
  935. 39:18passes the arguments to callee
  936. 39:21and jumps to callee. For example, in
  937. 39:23here main is
  938. 39:24calls this sum function, so it is the
  939. 39:26caller.
  940. 39:27And callee is the called function.
  941. 39:29In this case it is sum.
  942. 39:31Sum performs the function, it returns
  943. 39:34result to caller, returns the point of
  944. 39:36call. So, for example, after doing this
  945. 39:38computation,
  946. 39:40for example, I'm calling this sum
  947. 39:41function. After this after doing this
  948. 39:44computation, I'm returning back
  949. 39:46to the point of call, to this location
  950. 39:49to continue the program.
  951. 39:51And it has a
  952. 39:53duty that it must not overwrite
  953. 39:55registers or memory needed by the
  954. 39:57caller. For example, assume that this
  955. 39:59key code in here in main,
  956. 40:02this For example, in here I have also
  957. 40:04another variable
  958. 40:06named key for example.
  959. 40:08And this key is important and assume
  960. 40:10that this key is stored in X 4 for
  961. 40:13example.
  962. 40:16Whenever I call this sum function and
  963. 40:18inside this sum function during the
  964. 40:21computations while doing the
  965. 40:22computations, if I overwrite this X4,
  966. 40:26then when I
  967. 40:28go back to this main function again and
  968. 40:30assume that it this main function does
  969. 40:32some computation on this key in here.
  970. 40:36But since it is overwritten by this sum
  971. 40:38function, then this is a problem. For
  972. 40:40this reason, this function shouldn't
  973. 40:42change it.
  974. 40:43And there are some standards for RISC-V
  975. 40:46that the compiler needs to obey.
  976. 40:49Did you understand this problem? Is it
  977. 40:51clear?
  978. 41:00So, in here we did an introduction.
  979. 41:03Then in here
  980. 41:06there are function function call
  981. 41:08examples.
  982. 41:12In here I have a C code, and in C code I
  983. 41:15have a main function. This main inside
  984. 41:17this main function I am calling a
  985. 41:20function named simple.
  986. 41:22And then after returning from this
  987. 41:24function, I'm I'm calling this function,
  988. 41:26this simple function.
  989. 41:28And this simple simple function does not
  990. 41:30do anything meaningful. It just returns
  991. 41:33back to this point.
  992. 41:35I'm calling the simple, then inside this
  993. 41:38simple the first instruction that I
  994. 41:40encounter is return, so it just returns
  995. 41:42to here, back to here.
  996. 41:46So, when I compile this code,
  997. 41:49this is the resulted code.
  998. 41:52In here I have a main, and this main
  999. 41:55function, this is By the way, main is
  1000. 41:57the
  1001. 41:58introductory function for any program.
  1002. 42:01It any pro-
  1003. 42:03A- All programs starts with main, then
  1004. 42:06calls to other functions.
  1005. 42:09So, this main function calls the simple
  1006. 42:13directly. This simple function
  1007. 42:15So, this is call call routine. Jal
  1008. 42:19Jal means that jump to this simple
  1009. 42:22label, to this label.
  1010. 42:24But, at the same time
  1011. 42:26save the address of the return point.
  1012. 42:29So, return point is here. So, it saves
  1013. 42:31this address, this return point address
  1014. 42:34to RA register. So, this address 0x34304
  1015. 42:40is saved in register when I call this
  1016. 42:43function.
  1017. 42:44And then
  1018. 42:47in here, I'm running this function. I
  1019. 42:49jump this 15C location. And then in this
  1020. 42:5315C location
  1021. 42:55it is just returns. It is not doing
  1022. 42:57anything useful. It just returns to RA
  1023. 43:00location. Jump register RA means that
  1024. 43:04jump back to RA location. So, what is
  1025. 43:06the value of RA?
  1026. 43:080x 304.
  1027. 43:11So, 304 is here. So, it
  1028. 43:14just returns to here, this
  1029. 43:16at back.
  1030. 43:18Is it clear, right? This is If you
  1031. 43:19compile this C code
  1032. 43:21its corresponding RISC-V assembly code
  1033. 43:23is this one.
  1034. 43:26So, in here, there is a void in here.
  1035. 43:28This means that simple doesn't return a
  1036. 43:31value. We are not returning any value.
  1037. 43:33Sometimes in C you you want to return a
  1038. 43:36value. For example, in this main, we are
  1039. 43:37returning an integer.
  1040. 43:39And this integer corresponds to error
  1041. 43:43code of this program. If the this
  1042. 43:44program runs healthy in a healthy way
  1043. 43:46and finish in a healthy way, then this
  1044. 43:48integer return value becomes zero. But,
  1045. 43:51this this is specific to Windows, by the
  1046. 43:53way. You don't need to know it.
  1047. 43:56For example, this function returns a
  1048. 43:57value, but this doesn't return any
  1049. 43:59value.
  1050. 44:01So, in here, we have a two instruction.
  1051. 44:03We already see these so these functions,
  1052. 44:06these instructions. Jal, simple, it
  1053. 44:10jumps to simple label, but at the same
  1054. 44:12time, while jumping, it saves the return
  1055. 44:15address to RA register.
  1056. 44:18And return address address is the PC
  1057. 44:19plus four.
  1058. 44:21If the PC is here, the PC plus four is
  1059. 44:24here. So, it it saves this return
  1060. 44:26address to RA register.
  1061. 44:28And then jumps to the simple label.
  1062. 44:30And another one is that it corresponds
  1063. 44:34to this return instruction in C. It is
  1064. 44:37jump register RA. Jump register RA says
  1065. 44:40that just switch to RA.
  1066. 44:43So, jump register RA means that you need
  1067. 44:46to
  1068. 44:47just go back to this location, RA
  1069. 44:50location.
  1070. 44:51And it is useful while returning from
  1071. 44:53functions.
  1072. 44:56Okay?
  1073. 45:00In this slide, we will see the function
  1074. 45:03call convention in RISC-V.
  1075. 45:06Yeah. While calling a function, in here,
  1076. 45:09you see we are using jump and link.
  1077. 45:12Because jump means jumping, jumping to a
  1078. 45:15label, but at the same time, I need to
  1079. 45:16link. I need to know I need to register
  1080. 45:19the my
  1081. 45:21returning location
  1082. 45:23after finishing this function. Because
  1083. 45:25I'm going to a function, and when this
  1084. 45:27function finish, I need to go back to
  1085. 45:29main program, the color color function.
  1086. 45:32So, in order to know it, I need to save
  1087. 45:34my return address, and it means that
  1088. 45:36linking.
  1089. 45:38So, return from function, in order to
  1090. 45:40return a function from a function, I
  1091. 45:42need to jump register because this
  1092. 45:45return address is stored in register RA
  1093. 45:48during this jump and link.
  1094. 45:50So, I'm just returning back to this
  1095. 45:53location by using jump register.
  1096. 45:59Also, in in
  1097. 46:02RA has a specific meaning.
  1098. 46:04Which RA is you see it
  1099. 46:07register numbers. In RISC-V, we told
  1100. 46:09that there are 32 registers
  1101. 46:11and it has special meanings. You don't
  1102. 46:14have to know them. You don't
  1103. 46:16I'm not saying that you don't have to
  1104. 46:17memorize them. You don't need to know
  1105. 46:19them as a hardware developer, but it is
  1106. 46:21beneficial for you to know them.
  1107. 46:23For example, the important point for us
  1108. 46:26as the hardware developer is the
  1109. 46:28register number. X0 is always zero and
  1110. 46:31rest is doesn't matter. They can be any
  1111. 46:33value and there are 31 registers. But it
  1112. 46:36has a special naming, special purpose.
  1113. 46:40X0 is zero.
  1114. 46:42X1 is RA, for example. So, when I say RA
  1115. 46:45in here, it means that it is X1.
  1116. 46:48And it is the special purpose of this X1
  1117. 46:51register. The special purpose of this X1
  1118. 46:54register is return address.
  1119. 46:57But this is more This usage is more
  1120. 46:59related more related to software guys,
  1121. 47:03software developers, and compiler
  1122. 47:05developers. They are also software
  1123. 47:06developer, compiler developers. For us,
  1124. 47:09it's not much important. But of course,
  1125. 47:11in order to be familiar with the
  1126. 47:13instruction set architecture, we are
  1127. 47:14showing it in here.
  1128. 47:17RA, it which is X1, has a special name.
  1129. 47:21Also, arguments A0 and A7. What is A0
  1130. 47:24and what A7? A0
  1131. 47:27and A7, it is between X10 and X17.
  1132. 47:31These are the arguments. They are also
  1133. 47:33special meaning. If you are calling a
  1134. 47:36function, then you are storing the
  1135. 47:37arguments in A0, A1. You can use A0, A1,
  1136. 47:41A2 for arguments. I will show argument
  1137. 47:45example right now.
  1138. 47:46And return value is You can use A0 for
  1139. 47:50the return value. For example, you are
  1140. 47:52calling a function name, call it sum.
  1141. 47:55And this sum function gets two
  1142. 47:56arguments.
  1143. 47:58And in inside the sum function, you are
  1144. 48:00adding these two arguments and returning
  1145. 48:02a value. So, sum of these two values.
  1146. 48:05Then
  1147. 48:07arguments are A0 and A1. And return
  1148. 48:11value, the sum of these A0 and A1 is
  1149. 48:13stored in A0. This is a convention, by
  1150. 48:16the way. You You don't have to follow
  1151. 48:17this one. You can write
  1152. 48:19For example, you can write an assembly
  1153. 48:21code and you can return
  1154. 48:23from in X 31, no problem. But this is
  1155. 48:26the convention. The compilers generally
  1156. 48:29follow this convention.
  1157. 48:35So,
  1158. 48:37in here, for example,
  1159. 48:39I have a
  1160. 48:40main function. Main function doesn't get
  1161. 48:43any argument.
  1162. 48:45And in main function,
  1163. 48:47I have a Y variable. It is integer. And
  1164. 48:50this main function calls diff of sums
  1165. 48:53function. So, diff of sums function adds
  1166. 48:57gets four arguments. For example, 3 2 4
  1167. 49:005 in here.
  1168. 49:02And this is the diff of sums function.
  1169. 49:05It gets these four arguments and does
  1170. 49:07this computation.
  1171. 49:09It adds F to G and H to A and finds the
  1172. 49:13subtraction of them. And this is the
  1173. 49:15result and it returns this result.
  1174. 49:20So, in here, what you will see is that
  1175. 49:23these arguments are If you compile this
  1176. 49:26C code, these arguments are stored
  1177. 49:29stored in A0, A1, A2, and A3.
  1178. 49:34And then this result returns in A0.
  1179. 49:40Compiler follows this convention.
  1180. 49:44Uh let's see the compiled code. This is
  1181. 49:46the compiled code.
  1182. 49:48In here, I have a main function. The
  1183. 49:50program counter starts from here. It
  1184. 49:52runs.
  1185. 49:53At the beginning
  1186. 49:55since these are the values, I am
  1187. 49:58initializing this register as
  1188. 50:01This is the initialization. A0 becomes
  1189. 50:032, A1 becomes 3.
  1190. 50:05And A0, A1, A2, and A3 are initialized.
  1191. 50:10And then I am calling diff of sums
  1192. 50:12function. Diff of sums function is
  1193. 50:14called by jal. So, in here while calling
  1194. 50:18diff of sums, I am saving the return
  1195. 50:21address this address of this at to
  1196. 50:24array.
  1197. 50:25So, this
  1198. 50:27array keeps the address of this
  1199. 50:28instruction.
  1200. 50:32And jal diff of sums
  1201. 50:34I am calling to diff of sums.
  1202. 50:37And when I call the function
  1203. 50:39since in the convention I A0, A1, A2
  1204. 50:43until A7 keeps the input arguments, I
  1205. 50:47know that.
  1206. 50:48And
  1207. 50:49while writing this function, I know this
  1208. 50:52this convention.
  1209. 50:54So
  1210. 50:56the compiler uses this A0, A1, A2, and
  1211. 50:59A3 registers for the input arguments and
  1212. 51:02computes some intermediate results
  1213. 51:06and then computes the result and writes
  1214. 51:08the result to A0 register, then returns.
  1215. 51:13Return is
  1216. 51:15returns to this location. So, this
  1217. 51:17return
  1218. 51:19changes the PC to this value to this
  1219. 51:21instruction.
  1220. 51:23And whenever you reach to this
  1221. 51:25instruction, since in this convention I
  1222. 51:27told you that return value is written to
  1223. 51:29A0
  1224. 51:31then
  1225. 51:32I know that this A0 is
  1226. 51:34the result of this function is stored in
  1227. 51:37A0. So, starting from this location
  1228. 51:41I know that A0 keeps the return value
  1229. 51:44resulted value of diff of sums function
  1230. 51:46so that I can use this value.
  1231. 51:49But this is convention just
  1232. 51:51compilers knows the compa- while giving
  1233. 51:54can argument input argument to to a
  1234. 51:57function, they are using A0 A7 between
  1235. 52:01A0 and A7. For example, if they are
  1236. 52:03using two only two argument is enough,
  1237. 52:06then it only use A0 and A1. But this is
  1238. 52:09just a convention.
  1239. 52:10Yeah, so when you look at this code, it
  1240. 52:12is
  1241. 52:13reasonable.
  1242. 52:15Right?
  1243. 52:17Default sums, we I am jumping to this
  1244. 52:19here. I am doing some computations over
  1245. 52:22A0 A1 A2 and A3 and then writing the
  1246. 52:25result to A0 then returning back to yeah
  1247. 52:29here. And in here, I know that A0 keeps
  1248. 52:32the the result of this function.
  1249. 52:35Then I continue and use this value. This
  1250. 52:38is just a convention.
  1251. 52:42Yeah, you can inspect this
  1252. 52:44code at home in detail, but it is it is
  1253. 52:47very easy.
  1254. 52:50What we are doing is that we are writing
  1255. 52:52this C code
  1256. 52:53and this C code
  1257. 52:55translated to this binary.
  1258. 52:58Compiler actually places Compiler uses
  1259. 53:01this A0 A1 A2 and A3.
  1260. 53:08In here, for example, while calling this
  1261. 53:11function, I use A0 A1 A2 and A3 as the
  1262. 53:14input argument, but also inside of this
  1263. 53:16function, I overwrote these three
  1264. 53:18registers T0 T1 and S3.
  1265. 53:25And we can come to the previous our
  1266. 53:28previous discussion before the break
  1267. 53:30that what if in here, for example, I put
  1268. 53:33some value over T0
  1269. 53:36and this function overwrite this T0.
  1270. 53:40And after returning back from this
  1271. 53:42function to this point, this T0 is
  1272. 53:45changed by this function.
  1273. 53:47So, there is a problem right in here. If
  1274. 53:50T0 is important for main, for example,
  1275. 53:53and if diff of sums function changes
  1276. 53:55this T0, then this is a problem.
  1277. 53:59Because diff of sums I overwrote these
  1278. 54:01three registers, T0, T1, and S3, which
  1279. 54:04are What What is that? T0 is X5, T1 is
  1280. 54:08X6, and S0 for example. S A0 is X8 for
  1281. 54:12example in here. I changed these
  1282. 54:14registers.
  1283. 54:15This is the problem.
  1284. 54:22In here,
  1285. 54:28in here, I told you that there are
  1286. 54:31seven arguments. Not seven, eight
  1287. 54:34arguments between A0 and A7. What if,
  1288. 54:36for example,
  1289. 54:38a function would require more than seven
  1290. 54:40arguments?
  1291. 54:42For example, I am calling a function and
  1292. 54:44this function requires more than
  1293. 54:46seven arguments. Not seven, by the way,
  1294. 54:49eight arguments because A0 A7, more than
  1295. 54:53eight arguments. What What happens?
  1296. 54:55In this case, we can use a stack. Stack
  1297. 54:57means that a location in memory. So,
  1298. 55:00because register is not enough for us.
  1299. 55:03Register is There are 32 registers and
  1300. 55:0731 of them are in use because X0 is
  1301. 55:10always zero. So, our input arguments
  1302. 55:14doesn't cannot fit into the register
  1303. 55:16file because I need more than eight
  1304. 55:19registers to pass my input arguments to
  1305. 55:21function. Then, in this case, of course,
  1306. 55:24I can use the memory. So, in memory, I
  1307. 55:27can put two input arguments to memory,
  1308. 55:29call a function, and this function can
  1309. 55:31read the input arguments from memory.
  1310. 55:34So, the place inside the memory that we
  1311. 55:36use for this purpose is named as stack.
  1312. 55:39So, we can use stack to temporarily
  1313. 55:42store registers.
  1314. 55:44So, in here we will see the stack.
  1315. 55:52So, [clears throat] stack is the memory
  1316. 55:53used to temporarily save variables. It
  1317. 55:56is like stack of dishes, the last-in,
  1318. 55:58first-out queue.
  1319. 56:01So, in here for example, it is like
  1320. 56:03dishes. So, you are putting the dishes
  1321. 56:07top of each other, and while putting,
  1322. 56:09you are putting the top,
  1323. 56:11and while taking one, you are taking the
  1324. 56:14one at the top.
  1325. 56:16So, it's growing in this direction
  1326. 56:19and shrinks in this direction. It's like
  1327. 56:22these plates.
  1328. 56:24So, it is a last-in, first-out queue in
  1329. 56:27memory.
  1330. 56:28It expands, it means that uses more
  1331. 56:30memory when more space needed. It
  1332. 56:32contracts, uses less memory when the
  1333. 56:34space is no longer needed.
  1334. 56:37So, it grows down from higher to lower
  1335. 56:39memory address. So, while while going
  1336. 56:43down, for example, its address is 0x8,
  1337. 56:46for example.
  1338. 56:47While growing downside, it
  1339. 56:50decreases its address. I don't know why,
  1340. 56:52but it is the convention. While if stack
  1341. 56:55is growing,
  1342. 56:57then its address is decrements.
  1343. 57:03So, it grows down from higher to lower
  1344. 57:06memory addresses. Stack pointer is SP,
  1345. 57:10which points to the top of stack. By the
  1346. 57:12way, SP is also a special register. So,
  1347. 57:15SP corresponds to
  1348. 57:18here, for example. What is SP? SP is X2.
  1349. 57:22So, in compilers, generally compilers
  1350. 57:24when compilers compile the C code,
  1351. 57:28it uses X2 for SP, generally.
  1352. 57:32Because it has a special meaning of
  1353. 57:34stack stack pointer.
  1354. 57:35It's a memory location by the way,
  1355. 57:37memory address.
  1356. 57:41So, SP points to top of stack. So, for
  1357. 57:43example, assume that this is the top of
  1358. 57:46stack and in top of stack I I put
  1359. 57:49this value AB0001.
  1360. 57:52And this is the address.
  1361. 57:54Okay, SP is here.
  1362. 57:57So, I want to put two words more to this
  1363. 58:00stack. How I am putting it?
  1364. 58:03I am just
  1365. 58:04making room for two words. So, in the
  1366. 58:08stack pointer is decremented by
  1367. 58:12eight.
  1368. 58:13So, it comes to here.
  1369. 58:14To this point because it decrements by
  1370. 58:17eight.
  1371. 58:18So, if it is decremented by eight, it
  1372. 58:20means that we are
  1373. 58:22generating space for two words. And then
  1374. 58:25I'm writing these two words to here.
  1375. 58:30So, after decrementing here, the stack
  1376. 58:32pointer was in here and then I changed
  1377. 58:35it. It means that stack pointer is
  1378. 58:37changed in this way. Immediate stack
  1379. 58:39pointer stack pointer minus four minus
  1380. 58:42eight, for example. So, stack pointer
  1381. 58:44decremented by eight.
  1382. 58:46Then, for example, I am doing load word,
  1383. 58:50for example, sorry, store word.
  1384. 58:53And I am storing this value to stack
  1385. 58:56pointer
  1386. 58:57>> [clears throat]
  1387. 58:58>> four, for example, stack pointer four. I
  1388. 59:00am
  1389. 59:01storing this value, for example, to
  1390. 59:03stack pointer four. And another I'm
  1391. 59:06doing another store to stack pointer
  1392. 59:09to this location. So, if I run two store
  1393. 59:12word, then I can store two values to
  1394. 59:15here. One of them is stack pointer plus
  1395. 59:16four and other one is the stack pointer
  1396. 59:18itself.
  1397. 59:19Right? Is it clear?
  1398. 59:23Okay, let's [clears throat] see an
  1399. 59:23example for the stack pointer.
  1400. 59:28So, stack usage in functions
  1401. 59:32So, in here I have an example, the same
  1402. 59:34example, diff of sums. And diff of sums
  1403. 59:36uses this T0, T1, and S3 values because
  1404. 59:40in here diff of sums overrides three
  1405. 59:42registers, T0, T1, and S3.
  1406. 59:47And
  1407. 59:48>> [clears throat]
  1408. 59:52>> uh in here, for example,
  1409. 59:57this S3, T0, T1 diff of sums function
  1410. 1:00:01changes this S3, T0, and T1.
  1411. 1:00:05But assume that they are very important.
  1412. 1:00:07So, before changing it,
  1413. 1:00:09this this diff of sums function puts
  1414. 1:00:12this S3, T0, and T1 registers to a
  1415. 1:00:14stack. How it is putting? Assume that
  1416. 1:00:17there is a stack in here.
  1417. 1:00:20Yes, I can
  1418. 1:00:21show in this picture.
  1419. 1:00:23So, before this diff of sums function
  1420. 1:00:25call,
  1421. 1:00:28here is my stack pointer. The compiler
  1422. 1:00:30assigned this value. The compiler is the
  1423. 1:00:32stack corresponds shows the stack
  1424. 1:00:34pointer. Actually, compiler assigns a
  1425. 1:00:36pointer
  1426. 1:00:37uh
  1427. 1:00:38corresponds like the stack pointer.
  1428. 1:00:40In here, I am
  1429. 1:00:42decreasing the stack pointer by 12. So,
  1430. 1:00:45I'm making space on stack to store three
  1431. 1:00:48registers in here. So, stack pointer
  1432. 1:00:51comes to the here, right? After
  1433. 1:00:54minus
  1434. 1:00:5512,
  1435. 1:00:56the stack pointer comes to here.
  1436. 1:00:58So, during call, stack pointer comes to
  1437. 1:01:01here.
  1438. 1:01:02And in each stack pointer location,
  1439. 1:01:06this location, stack pointer, stack
  1440. 1:01:07pointer four is here, stack pointer
  1441. 1:01:10eight is here.
  1442. 1:01:12I am storing these values, S3, T0, and
  1443. 1:01:15T1, respectively in these locations. So,
  1444. 1:01:18these
  1445. 1:01:20registers are stored in here, okay?
  1446. 1:01:23Until here there is no problem, right?
  1447. 1:01:25It's just a RISC-V code.
  1448. 1:01:28And here it is a function body. We did
  1449. 1:01:32some computations in this function. It
  1450. 1:01:34was default sums function. It was doing
  1451. 1:01:38F plus G minus H plus I, this
  1452. 1:01:42computation. And it was storing the
  1453. 1:01:44result to S
  1454. 1:01:463 register. This was S3 is the register
  1455. 1:01:50that stores the result. And then I was
  1456. 1:01:53writing it to A0 register. This A0
  1457. 1:01:56register.
  1458. 1:01:57Because A0 register was also return
  1459. 1:01:59value.
  1460. 1:02:00And normally in the previous version of
  1461. 1:02:03the this code,
  1462. 1:02:06I was doing no stack assignment. I was
  1463. 1:02:08not writing these T0, T1, and S3 values
  1464. 1:02:11to stack. I was just starting the
  1465. 1:02:14computation and then returning the
  1466. 1:02:16result. But in here,
  1467. 1:02:20I am
  1468. 1:02:22keeping a copy of T0, T1, and S3 in
  1469. 1:02:25stack.
  1470. 1:02:27In here. And
  1471. 1:02:30since in here, during this function
  1472. 1:02:32operation, since I overwrote these T0,
  1473. 1:02:35T1, and S3 registers,
  1474. 1:02:39I am just restoring them before
  1475. 1:02:42returning to main.
  1476. 1:02:44Did you understand this why we are doing
  1477. 1:02:45it?
  1478. 1:02:49And while restoring,
  1479. 1:02:51in the same way
  1480. 1:02:54after call,
  1481. 1:02:56for example, in here, the stack in here,
  1482. 1:02:59I saved these variables to here in
  1483. 1:03:01stack. This is our stack. So, I stored
  1484. 1:03:04this S3, T0, and T1 and did the
  1485. 1:03:08computation in here. And while returning
  1486. 1:03:10back, before going back to this main
  1487. 1:03:13function,
  1488. 1:03:15I am restoring these registers
  1489. 1:03:17with the
  1490. 1:03:19uh
  1491. 1:03:20their original value. I am
  1492. 1:03:22writing their original value back to
  1493. 1:03:25register itself. So, I'm just getting
  1494. 1:03:27this stack pointer plus eight, this S3,
  1495. 1:03:30and
  1496. 1:03:31this this value
  1497. 1:03:33to it is a previous value of S3 and
  1498. 1:03:36putting it to the S3 again back. I'm
  1499. 1:03:39getting the previous value of T0 before
  1500. 1:03:41function call and writing it to T0 and
  1501. 1:03:45getting the previous value of T1 and
  1502. 1:03:47writing it to T1. So, in here I'm
  1503. 1:03:50restoring it.
  1504. 1:03:51And then, when I return back to main,
  1505. 1:03:55then
  1506. 1:03:56these S3, T0, and T1 keeps their
  1507. 1:03:59original values. It's like unchanged,
  1508. 1:04:02nothing changed.
  1509. 1:04:04Did you understand this point?
  1510. 1:04:13So, in here, this is the call function.
  1511. 1:04:15For example,
  1512. 1:04:18now the point in here, for example,
  1513. 1:04:23so
  1514. 1:04:25in for example, in this main function,
  1515. 1:04:29>> [clears throat]
  1516. 1:04:29>> there are
  1517. 1:04:3031 registers that can be used, right? X1
  1518. 1:04:33to X31.
  1519. 1:04:36And
  1520. 1:04:38in main, I am running this diff of sums
  1521. 1:04:41function and diff of sums function can
  1522. 1:04:43change any value.
  1523. 1:04:46Can use any register between X1 and X31.
  1524. 1:04:50And before and after returning back,
  1525. 1:04:53then any of these registers can be
  1526. 1:04:55changed. In this case, should I
  1527. 1:04:59uh
  1528. 1:05:00keep a copy of all registers before a
  1529. 1:05:02function call?
  1530. 1:05:04Because it can change any register, and
  1531. 1:05:06if I need this register, previous value
  1532. 1:05:08of this register, then I should keep a
  1533. 1:05:11copy of it. I should uh
  1534. 1:05:13back up it.
  1535. 1:05:16But in this case
  1536. 1:05:18for example, in a similar way to this
  1537. 1:05:20S3, T0, and T1 registers, should I for
  1538. 1:05:24example store word between X1 X31? So,
  1539. 1:05:29it means that running
  1540. 1:05:3131 store word then doing the
  1541. 1:05:33computation, and then restore all of
  1542. 1:05:36these registers. Is it required?
  1543. 1:05:39Because this function can use any of
  1544. 1:05:41these registers. And if these registers
  1545. 1:05:43are important for the caller
  1546. 1:05:45then I need to restore them. I need to
  1547. 1:05:47back up them and then restore them.
  1548. 1:05:51This is not much possible because in
  1549. 1:05:54every function called in this case, you
  1550. 1:05:55need to call 31 store and 31 load while
  1551. 1:05:59returning back.
  1552. 1:06:00So, RISC-V
  1553. 1:06:02puts a convention
  1554. 1:06:04puts a standard and says that
  1555. 1:06:08>> [clears throat]
  1556. 1:06:08>> caller, for example saves any register
  1557. 1:06:12any needed registers. For example, if
  1558. 1:06:15you are a caller and you are a calling a
  1559. 1:06:17function
  1560. 1:06:18you need to save any needed registers.
  1561. 1:06:21For example, RA,
  1562. 1:06:23T0, T6, A A0, and A7. If you are using
  1563. 1:06:28these one and these are important for
  1564. 1:06:30you
  1565. 1:06:31it says that caller needs to save it.
  1566. 1:06:33So, before calling the function I need
  1567. 1:06:36to save these registers. I need to do a
  1568. 1:06:38backup.
  1569. 1:06:39And I can I need to use the argument
  1570. 1:06:41register as A0 and A7 and call the
  1571. 1:06:45function and get the result return value
  1572. 1:06:48from A0 and if you save any registers,
  1573. 1:06:52any of these registers, for example,
  1574. 1:06:55these registers are important for us. If
  1575. 1:06:57and if I save any of them, I need to
  1576. 1:06:59restore them after returning back.
  1577. 1:07:02This is the
  1578. 1:07:04caller function. Caller needs to do it.
  1579. 1:07:06This is a standard. And what about the
  1580. 1:07:09Call called one?
  1581. 1:07:11Called one saves the registers that
  1582. 1:07:14might be disturbed. For example, if call
  1583. 1:07:17is
  1584. 1:07:18is changing S0
  1585. 1:07:20S1, this range, then it needs to save
  1586. 1:07:23it.
  1587. 1:07:24And while returning back, it has to
  1588. 1:07:26restore them.
  1589. 1:07:28But
  1590. 1:07:30for call it
  1591. 1:07:31it can change
  1592. 1:07:33T0 T6 A0 A0 and A7. It is
  1593. 1:07:38it is no problem to to change them.
  1594. 1:07:41So, in this case, for example, if as a
  1595. 1:07:43caller, for example, RA is important for
  1596. 1:07:46me
  1597. 1:07:46while calling a function, I need to back
  1598. 1:07:49up it.
  1599. 1:07:52The call saves the registers, this range
  1600. 1:07:55registers, if they are using.
  1601. 1:07:58Performs the function and put the
  1602. 1:07:59results to A0, restore the registers
  1603. 1:08:02that he saved. And then return this RA
  1604. 1:08:06RA position. So, this is the conversion,
  1605. 1:08:09actually.
  1606. 1:08:10As a caller, for example, this is the
  1607. 1:08:12non-preserved registers, T0 and T6, for
  1608. 1:08:15example. So,
  1609. 1:08:17if, for example,
  1610. 1:08:20as a function, if I am using T0 register
  1611. 1:08:23and T0 is important for the caller, then
  1612. 1:08:26caller needs to save it. For example,
  1613. 1:08:28this this specification conversion says
  1614. 1:08:30it.
  1615. 1:08:31But, for example, I am a call call. And
  1616. 1:08:35if I am using S0 and S11, then I need to
  1617. 1:08:39save it and restore it. This is a
  1618. 1:08:41conversion.
  1619. 1:08:44And the conversion is that you need I
  1620. 1:08:47need to save and restore it in the
  1621. 1:08:49memory region that is pointed by the
  1622. 1:08:52stack pointer.
  1623. 1:09:02Any question
  1624. 1:09:04related
  1625. 1:09:21>> [clears throat]
  1626. 1:09:22>> So, this is the optimized function call.
  1627. 1:09:25So, in here, for example,
  1628. 1:09:28there is no need to save
  1629. 1:09:30T0, T1.
  1630. 1:09:31T0, T1 is not non-preserved register.
  1631. 1:09:34So, if, for example, the caller function
  1632. 1:09:36uses them, it is the duty of this caller
  1633. 1:09:39function to save these registers.
  1634. 1:09:41And in any function, while writing, for
  1635. 1:09:43example, assembly code, you can use T0
  1636. 1:09:46and T1, T2, this T register. It is named
  1637. 1:09:49temp registers. You can use this temp
  1638. 1:09:52register without
  1639. 1:09:55backing up them or restoring them. No
  1640. 1:09:57need. So, this is a convention because
  1641. 1:09:59convention says that in a function,
  1642. 1:10:02you can use T registers freely. No need
  1643. 1:10:04to save them into the stack.
  1644. 1:10:07So,
  1645. 1:10:08the optimized function call, in this
  1646. 1:10:10case, just use the non-preserved
  1647. 1:10:12registers.
  1648. 1:10:14Because why?
  1649. 1:10:15If you are using non-preserved
  1650. 1:10:17registers, these T registers, for
  1651. 1:10:19example, then you don't need to save
  1652. 1:10:21them to the stack and then restoring
  1653. 1:10:23them to the stack. If the caller, for
  1654. 1:10:26example, in here, the main
  1655. 1:10:28uses them, then this is the duty of
  1656. 1:10:31caller, main function, to save them to
  1657. 1:10:33the stack.
  1658. 1:10:34So, this is the convention.
  1659. 1:10:36But generally, we don't pay much
  1660. 1:10:38attention to it. The compilers does this
  1661. 1:10:41job for us.
  1662. 1:10:45So, non-leaf function is the function
  1663. 1:10:47that calls another function.
  1664. 1:10:49What should we do in non-leaf functions?
  1665. 1:10:51For example, in here, I have a function
  1666. 1:10:53one.
  1667. 1:10:54And in this function one,
  1668. 1:10:57uh am calling another function which is
  1669. 1:10:59named as function two. So, I have a
  1670. 1:11:01function
  1671. 1:11:03and inside this function, I am calling
  1672. 1:11:05another
  1673. 1:11:07I am calling another function, G
  1674. 1:11:08function for example, and in this
  1675. 1:11:10function, I am returning back. So, it
  1676. 1:11:12returns back to this point and this
  1677. 1:11:14function returns back to the point that
  1678. 1:11:16calls this F.
  1679. 1:11:19Uh so, [clears throat]
  1680. 1:11:20in here, this F is non-leaf function
  1681. 1:11:22because it it return it calls another
  1682. 1:11:25function.
  1683. 1:11:27People say that it is non-leaf function.
  1684. 1:11:30So, in here uh
  1685. 1:11:33function one
  1686. 1:11:35calls function two but before
  1687. 1:11:38calling function two, there is an
  1688. 1:11:40important register which is named RA.
  1689. 1:11:45Actually, RA register keeps the value
  1690. 1:11:47that function one will return back.
  1691. 1:11:50So, this RA is important for us. So, in
  1692. 1:11:53function one, before
  1693. 1:11:55calling to function two register
  1694. 1:11:57I am storing to RA
  1695. 1:11:59to stack.
  1696. 1:12:02In stack, for example
  1697. 1:12:04for example, stack pointer is here. I am
  1698. 1:12:06just
  1699. 1:12:07making one
  1700. 1:12:09uh
  1701. 1:12:09one
  1702. 1:12:11uh
  1703. 1:12:12room in stack pointer
  1704. 1:12:14and I'm writing
  1705. 1:12:16to RA to here.
  1706. 1:12:18This RA this RA is function one RA,
  1707. 1:12:20okay?
  1708. 1:12:21I'm writing it to the stack pointer in
  1709. 1:12:23here.
  1710. 1:12:24And then I'm calling function two. So,
  1711. 1:12:26whenever I call function two
  1712. 1:12:30this location, the return location,
  1713. 1:12:32which is here, is written to RA.
  1714. 1:12:36So
  1715. 1:12:37in here, if I
  1716. 1:12:39uh didn't save this RA register, then in
  1717. 1:12:42this case, I would lose it. So, this is
  1718. 1:12:45why I'm saving to to stack pointer.
  1719. 1:12:48Because after some point, function one
  1720. 1:12:51function function one will finish and I
  1721. 1:12:53need to know to location where to where
  1722. 1:12:56to return back.
  1723. 1:12:58So, in here I'm calling function two and
  1724. 1:13:00whenever I call this function two with
  1725. 1:13:02jal instruction, then
  1726. 1:13:05>> [clears throat]
  1727. 1:13:06>> I am writing this return point inside
  1728. 1:13:08the function one. I am writing this
  1729. 1:13:11return point to the RA register. So, RA
  1730. 1:13:14register is overwritten.
  1731. 1:13:17And then
  1732. 1:13:19>> [clears throat]
  1733. 1:13:19>> for example,
  1734. 1:13:20uh
  1735. 1:13:23I'm assume that I call the function two
  1736. 1:13:26and function two is in here.
  1737. 1:13:29And while function two is returns,
  1738. 1:13:32return means the jump register RA. So,
  1739. 1:13:34I'm just returning back to this RA
  1740. 1:13:36location, which is here.
  1741. 1:13:38And then after returning here, I
  1742. 1:13:40continue my program. I come back to
  1743. 1:13:45jump function one and in function one,
  1744. 1:13:48before returning from function one, I am
  1745. 1:13:50restoring RA
  1746. 1:13:52from its stack pointer. So, what is the
  1747. 1:13:56RA? RA is the location that function one
  1748. 1:13:59needs to return. So, I am just restoring
  1749. 1:14:02RA value, then return to the point that
  1750. 1:14:04call that function one is called from.
  1751. 1:14:09Is it clear?
  1752. 1:14:13So, in here we must preserve RA before
  1753. 1:14:15function call.
  1754. 1:14:17>> [clears throat]
  1755. 1:14:19>> In here there is an example. I have a F1
  1756. 1:14:22function. This F1 function calls
  1757. 1:14:24function two. This is function two.
  1758. 1:14:27So, in here for example, before
  1759. 1:14:31before calling for this function two,
  1760. 1:14:34I am
  1761. 1:14:36opening a room.
  1762. 1:14:37I am actually registering four five
  1763. 1:14:39words in this stack. So, five words is
  1764. 1:14:4220 byte. So, I am
  1765. 1:14:46decreasing the stack pointer minus 20.
  1766. 1:14:49And I am putting A0, A1, RA, and S S4,
  1767. 1:14:54and S5 registers and keeping them into
  1768. 1:14:56the stack. So, in this is the stack.
  1769. 1:14:59Before call, this is the stack.
  1770. 1:15:01And I am
  1771. 1:15:03making a room of five words in stack and
  1772. 1:15:07storing A0, A1, RA, S4, and S5 in in in
  1773. 1:15:12in stack.
  1774. 1:15:14And calling function two.
  1775. 1:15:17This function two is called.
  1776. 1:15:19And in this function two, I am adding
  1777. 1:15:22another
  1778. 1:15:24register to stack. In while calling this
  1779. 1:15:27function two, my stack pointer
  1780. 1:15:29was here in here.
  1781. 1:15:31And also in here in this function two, I
  1782. 1:15:34am adding another word to this stack
  1783. 1:15:38stack. I'm keeping to S4 also. I I added
  1784. 1:15:41S4 in here.
  1785. 1:15:43And then while returning from F2
  1786. 1:15:46function, I am just restoring this S4
  1787. 1:15:49to here, then increasing the stack
  1788. 1:15:52pointer. So, stack pointer
  1789. 1:15:54just read this S4, then stack pointer
  1790. 1:15:57comes back to this here.
  1791. 1:15:59And jump return address.
  1792. 1:16:01So, returning back to here.
  1793. 1:16:05So, the the location that I called this
  1794. 1:16:07function two. So, I return to this
  1795. 1:16:09location. And after that in this
  1796. 1:16:12location,
  1797. 1:16:13>> [clears throat]
  1798. 1:16:14>> I am also returning return address from
  1799. 1:16:17stack pointer. So, it was in here. So,
  1800. 1:16:20my stack pointer is here.
  1801. 1:16:22Keeps here. So, RA is stack pointer plus
  1802. 1:16:25eight, right? So, for example, I am
  1803. 1:16:27loading stack pointer plus eight to RA.
  1804. 1:16:31And then while returning from this
  1805. 1:16:33function one, I can use this restored
  1806. 1:16:35value of RA also.
  1807. 1:16:39In here also while returning back in
  1808. 1:16:41each for example, in each function, if
  1809. 1:16:44you create a space in stack pointer, you
  1810. 1:16:47need to give it back to. So, in here I
  1811. 1:16:49am creating a space for five words.
  1812. 1:16:51While returning back from function, I
  1813. 1:16:53need to give this space back.
  1814. 1:16:56Okay?
  1815. 1:16:57And then jump to the return address.
  1816. 1:17:00In here, and this return address is
  1817. 1:17:02restored from the stack. Because you see
  1818. 1:17:05in in
  1819. 1:17:06while calling, because since I am
  1820. 1:17:08calling a function, then inside the
  1821. 1:17:10function, I am calling another function,
  1822. 1:17:12this array is always gets overwritten.
  1823. 1:17:15Whenever I call a function, I am
  1824. 1:17:16overwriting the array. For this reason,
  1825. 1:17:18I need to keep a copy of it in the
  1826. 1:17:21stack, and while returning back, I I
  1827. 1:17:24need to restore it back.
  1828. 1:17:28Actually, these [clears throat] are the
  1829. 1:17:28easy concepts. So, maybe in the in in
  1830. 1:17:32home, you can inspect the slides one
  1831. 1:17:34more time, and I think you can easily
  1832. 1:17:35understand. Because it is they are
  1833. 1:17:37trivial. They are very reasonable,
  1834. 1:17:39logical uh facts.
  1835. 1:17:49So, in here we can maybe give a break
  1836. 1:17:52around
  1837. 1:17:5312 minutes,
  1838. 1:17:55then continue
  1839. 1:17:57around
  1840. 1:17:5814
  1841. 1:18:0014
  1842. 1:18:0140.
  1843. 1:18:02We can continue at 14:40. We can give a
  1844. 1:18:05break. Okay?
  1845. 1:18:11So, we can continue with the recursive
  1846. 1:18:13functions.
  1847. 1:18:14The recursion means that the function
  1848. 1:18:15calls itself.
  1849. 1:18:18So, while converting to assembly code,
  1850. 1:18:22which is the duty of the compilers,
  1851. 1:18:28uh
  1852. 1:18:28it in the first pass treat recursive
  1853. 1:18:30calls as if it is calling a different
  1854. 1:18:33function, and ignore the overwritten
  1855. 1:18:35registers,
  1856. 1:18:36then save restore registers on stack as
  1857. 1:18:38needed.
  1858. 1:18:40Actually, this is not the duty of the
  1859. 1:18:41compiler while doing it.
  1860. 1:18:43While writing an assembly while in to
  1861. 1:18:47call recursively, you can follow this
  1862. 1:18:49convention, but most likely we will not
  1863. 1:18:50do it.
  1864. 1:18:51So, for example, in here I have a
  1865. 1:18:53recursive function func factorial n.
  1866. 1:18:56It is n
  1867. 1:18:59factorial. It means that n * n - 1 * n -
  1868. 1:19:032.
  1869. 1:19:04And
  1870. 1:19:05in here
  1871. 1:19:07if you write it as a recursive
  1872. 1:19:10this is the function.
  1873. 1:19:12So, I I have a
  1874. 1:19:13C code. It is int factorial int n. And
  1875. 1:19:17if n is less than one, less than or
  1876. 1:19:20equal to one, it returns one. Otherwise,
  1877. 1:19:23it returns n times factorial
  1878. 1:19:25calls itself in here. n times
  1879. 1:19:29the return value of this factorial and
  1880. 1:19:32each time this factorial is called with
  1881. 1:19:34n minus one.
  1882. 1:19:37So, in if for example, if if we call
  1883. 1:19:40factorial three, then it returns three
  1884. 1:19:42times factorial two. So,
  1885. 1:19:44factorial two returns two times
  1886. 1:19:46factorial one.
  1887. 1:19:48And then factorial one, this is the
  1888. 1:19:51last step, last case in if it goes into
  1889. 1:19:55this if statement and it returns one.
  1890. 1:19:58So,
  1891. 1:19:59in here factorial two one returns one,
  1892. 1:20:01factorial two returns two times one.
  1893. 1:20:04Because factorial two was two times
  1894. 1:20:06factorial one, and factorial one returns
  1895. 1:20:08one. Then factorial two returns two.
  1896. 1:20:11Then if factorial two returns two, then
  1897. 1:20:13factorial three returns three times two.
  1898. 1:20:15Then it is six. Actually, this is three
  1899. 1:20:17factorial.
  1900. 1:20:19This is six.
  1901. 1:20:20So, how
  1902. 1:20:22compiler writes such a code?
  1903. 1:20:24In this case, for example, in here I'm
  1904. 1:20:27calling the factorial function. And
  1905. 1:20:29factorial
  1906. 1:20:31factorial makes makes space
  1907. 1:20:34in stack pointer two words
  1908. 1:20:36or two words.
  1909. 1:20:38Minus eight means two words.
  1910. 1:20:40And then it places A0 and RA.
  1911. 1:20:43A0 is the input value input argument
  1912. 1:20:47and RA is the return value
  1913. 1:20:50in the stack pointer and then it does
  1914. 1:20:52the computation in here. It
  1915. 1:20:54compares this one with A0.
  1916. 1:20:59It does this comparison.
  1917. 1:21:01Branch greater than if it is greater
  1918. 1:21:03than one then it jumps to S.
  1919. 1:21:06So in S part it run it does this
  1920. 1:21:09computation.
  1921. 1:21:12It does [clears throat]
  1922. 1:21:13it decreases by one since N was input
  1923. 1:21:17value input value is stored in A0.
  1924. 1:21:20It decreases A0 by one then calls this
  1925. 1:21:23factorial again calls this function
  1926. 1:21:25again.
  1927. 1:21:27Okay?
  1928. 1:21:28Otherwise if it is in this
  1929. 1:21:31case if it is in here it just returns
  1930. 1:21:36uh
  1931. 1:21:37one. So A0 is becomes one in here and
  1932. 1:21:40returns just returns one in here.
  1933. 1:21:43It's jump returns to one directly.
  1934. 1:21:48So it means that
  1935. 1:21:49if it is in this condition it returns
  1936. 1:21:52one and returns back to the RA.
  1937. 1:21:55Because RA the return address.
  1938. 1:21:58Okay?
  1939. 1:22:01>> [clears throat]
  1940. 1:22:05>> In here the important point is that
  1941. 1:22:11each time
  1942. 1:22:14in here RA is input the A0 is input
  1943. 1:22:17input value.
  1944. 1:22:19Uh
  1945. 1:22:19when I call this factorial I am saving
  1946. 1:22:22this input value to stack and I am
  1947. 1:22:24saving the return address to this stack.
  1948. 1:22:27And while returning back from this
  1949. 1:22:30factorial in here in here it returns,
  1950. 1:22:34I need to restore them
  1951. 1:22:36here.
  1952. 1:22:38Because I'm calling this function and
  1953. 1:22:39this function has a array value. When I
  1954. 1:22:41call this function, this function has a
  1955. 1:22:44array value and when I call it again,
  1956. 1:22:49I have another array value. If I this
  1957. 1:22:51array writes to over this array, then I
  1958. 1:22:53lose this value. For this reason, at
  1959. 1:22:55each time I am storing this array values
  1960. 1:22:58to this the stack pointers and while
  1961. 1:23:00returning back from this factorial
  1962. 1:23:02function, I am restoring them. I need to
  1963. 1:23:04restore them.
  1964. 1:23:06This is the logic behind it.
  1965. 1:23:12So,
  1966. 1:23:14it means that and in here also while
  1967. 1:23:16returning back, you need to add stack
  1968. 1:23:19you need to restore the stock stack
  1969. 1:23:20pointer because in here when you call a
  1970. 1:23:22function, you are using two words in
  1971. 1:23:24stack pointer and you need to give it
  1972. 1:23:26back while returning back.
  1973. 1:23:36>> [clears throat]
  1974. 1:23:36>> So,
  1975. 1:23:39if you have a question, we can look at
  1976. 1:23:41here, but otherwise it is I advise you
  1977. 1:23:44to inspect this code at home.
  1978. 1:23:46Definitely you you have to look at it.
  1979. 1:23:49For example, look at these codes and run
  1980. 1:23:51it step by step at home and you can
  1981. 1:23:54understand the reasoning behind it.
  1982. 1:23:58By any questions, you can ask in Turkish
  1983. 1:24:00also we can we can look at it.
  1984. 1:24:10And this is an
  1985. 1:24:13uh call in here.
  1986. 1:24:15This is same factorial function. This is
  1987. 1:24:17the code. It has S and in here I have
  1988. 1:24:21now I give
  1989. 1:24:23memory addresses in here. This is the
  1990. 1:24:24address of the instructions. For
  1991. 1:24:26example, this factorial is stored at
  1992. 1:24:283,500, this location. This is the memory
  1993. 1:24:31location of factorial.
  1994. 1:24:33So, while returning,
  1995. 1:24:35while calling this jal factorial,
  1996. 1:24:39at that point, I am saving this return
  1997. 1:24:42address, which is the return address,
  1998. 1:24:44because I will call this factorial
  1999. 1:24:46again. And while this factorial returns
  2000. 1:24:48back, it needs to return back to here.
  2001. 1:24:51Okay? So, I'm saving this return address
  2002. 1:24:53to here, and this is the return address.
  2003. 1:24:550x 8528.
  2004. 1:25:05So, this is the return address when
  2005. 1:25:06factorial is called recursively.
  2006. 1:25:09So, this is the stack station while
  2007. 1:25:11calling the factorial. So, when I call
  2008. 1:25:14the factorial three,
  2009. 1:25:15then
  2010. 1:25:17first,
  2011. 1:25:20I am writing this a0 and ra
  2012. 1:25:24in after recursive call. I am saving the
  2013. 1:25:27ra also in here.
  2014. 1:25:29And then,
  2015. 1:25:32this is
  2016. 1:25:35No, factorial three is called, right?
  2017. 1:25:38Factorial three is called, so I am
  2018. 1:25:40saving this a0 and return address this
  2019. 1:25:43factorial three. This factorial three is
  2020. 1:25:45saved. Factorial three is called.
  2021. 1:25:48Okay?
  2022. 1:25:49I'm saving this input a,
  2023. 1:25:51which is a0, three, and return address
  2024. 1:25:54this factorial three. The the return
  2025. 1:25:56address
  2026. 1:25:57when I called this factorial three,
  2027. 1:25:59okay?
  2028. 1:26:02And this factorial three
  2029. 1:26:04does this operation, three times
  2030. 1:26:06factorial two, right?
  2031. 1:26:07And when I call this factorial two,
  2032. 1:26:10I have to save previous return address.
  2033. 1:26:13So, I am saving this previous return
  2034. 1:26:15address.
  2035. 1:26:16And at the same time, I am saving this
  2036. 1:26:18A02 in here. So, I am at each call
  2037. 1:26:22I am I am saving these
  2038. 1:26:25variables to the to inside the stack.
  2039. 1:26:27So, in factorial two, I am saving this
  2040. 1:26:30register, and this factorial two calls
  2041. 1:26:32factorial one, because factorial two is
  2042. 1:26:35two times factorial one.
  2043. 1:26:37And when I call this factorial one, I am
  2044. 1:26:40also saving these values.
  2045. 1:26:45And while returning back, this
  2046. 1:26:48For example, now I called factorial one.
  2047. 1:26:51So, factorial one returns back one. So,
  2048. 1:26:54RA is the location that I I will return
  2049. 1:26:57here. So, RA I am just returning back to
  2050. 1:27:00RA.
  2051. 1:27:01But at that point,
  2052. 1:27:03I need to restore the RA
  2053. 1:27:05from stack and return back to here. And
  2054. 1:27:08I need to restore it from stack and
  2055. 1:27:10return back to here. Because every time
  2056. 1:27:12when I call a function by using JAL, I
  2057. 1:27:15am overwriting RA. So, before
  2058. 1:27:18overwriting
  2059. 1:27:19over it before overwriting it, I need to
  2060. 1:27:23back up it in in the stack.
  2061. 1:27:26And then,
  2062. 1:27:28I need to restore it.
  2063. 1:27:30And this is the way to do it. While
  2064. 1:27:33while [clears throat] calling the
  2065. 1:27:34function,
  2066. 1:27:35I am writing this A0 and RA.
  2067. 1:27:38And in another call, I am writing it
  2068. 1:27:40back again in stack also in again.
  2069. 1:27:44And while returning back to stack, I am
  2070. 1:27:46reading them.
  2071. 1:27:48In the reverse order that I put.
  2072. 1:27:51It's like
  2073. 1:27:52first thing
  2074. 1:27:55Actually, it is a LIFO structure, last
  2075. 1:27:57in first out structure.
  2076. 1:28:00So, while calling, I am adding these
  2077. 1:28:01registers. And while returning back,
  2078. 1:28:03because it is recursive,
  2079. 1:28:05I am calling calling calling. And after
  2080. 1:28:08the end, I am returning back from the
  2081. 1:28:10recursive functions. Then, I am
  2082. 1:28:12returning back to here by by reading
  2083. 1:28:14them from the stack.
  2084. 1:28:19Is this concept clear? This This example
  2085. 1:28:21is long because for this reason I didn't
  2086. 1:28:24go step-by-step over the instructions.
  2087. 1:28:27Uh but this is a homework for you. You
  2088. 1:28:29need to follow.
  2089. 1:28:31It [clears throat] is a good practice
  2090. 1:28:32for
  2091. 1:28:33uh for
  2092. 1:28:35to understand the instruction set
  2093. 1:28:36architecture. But of course, this is
  2094. 1:28:38these concepts are not must for you. It
  2095. 1:28:40is just to be familiar with the
  2096. 1:28:42instruction set architecture.
  2097. 1:28:49So, there is also another concept named
  2098. 1:28:51pseudo instructions.
  2099. 1:28:54Ahem. Pseudo [clears throat]
  2100. 1:28:54instructions are not the actual RISC-V
  2101. 1:28:56instructions, but they are often
  2102. 1:28:59uh more convenient for the programmer.
  2103. 1:29:01So, you For example, you can compile a
  2104. 1:29:03program, and in the compiled uh assembly
  2105. 1:29:06code, you can see some instructions, but
  2106. 1:29:09these instructions are not real.
  2107. 1:29:11They don't exist.
  2108. 1:29:13Uh actually, they corresponds to another
  2109. 1:29:15instruction, actual instruction, but
  2110. 1:29:18people use them in assembly language to
  2111. 1:29:21make it assembly more readable. For this
  2112. 1:29:23reason, they are using the pseudo
  2113. 1:29:25instructions.
  2114. 1:29:27So, as in in that point, assemble
  2115. 1:29:30assembler converts them to real RISC-V
  2116. 1:29:32instructions. For example, RISC-V has
  2117. 1:29:34four jump pseudo instructions. For
  2118. 1:29:36example, jump immediate.
  2119. 1:29:39This jump immediate, for example, says
  2120. 1:29:41that jump to this immediate,
  2121. 1:29:43but normally, it uses jump instructions,
  2122. 1:29:48but jump instruction uh saves
  2123. 1:29:52the return address to X0. That saving
  2124. 1:29:55something to X0 means that nothing
  2125. 1:29:57saved.
  2126. 1:29:58Because in jump immediate says that jump
  2127. 1:30:01to a a location, but don't save
  2128. 1:30:03anything. Don't save the return address.
  2129. 1:30:06So,
  2130. 1:30:07return address is like saving to X0.
  2131. 1:30:09Save saved in X0, but X0 doesn't keep
  2132. 1:30:12anything because X0 is always
  2133. 1:30:14corresponds to zero.
  2134. 1:30:17So, this is [clears throat] the pseudo
  2135. 1:30:18instruction actually for jal X0
  2136. 1:30:21immediate. For example, jal immediate
  2137. 1:30:23jump and link. This time I have to save
  2138. 1:30:26the return address. So, this return
  2139. 1:30:28address saved at R R0 RA register.
  2140. 1:30:32So, this corresponds to this one. These
  2141. 1:30:34These are Look at it. These are two
  2142. 1:30:36different instructions, like two
  2143. 1:30:38different instructions, but they are all
  2144. 1:30:40jal instruction. These two are
  2145. 1:30:42corresponding to jal instruction, but it
  2146. 1:30:44is easier. For example, when you look at
  2147. 1:30:46the assembly code,
  2148. 1:30:47this is the ja ji je For example, je
  2149. 1:30:51immediate, you can read it, but its
  2150. 1:30:53actual corresponds to this one. But,
  2151. 1:30:55since this is more readable, more
  2152. 1:30:57friendly to understand, or compiler
  2153. 1:31:01pulls these codes. But, these are the
  2154. 1:31:02pseudo instructions, not real. It's
  2155. 1:31:04actual corresponds both jal.
  2156. 1:31:07For example, jump register ARF, it is
  2157. 1:31:10named as jump and link register X0 ARS0.
  2158. 1:31:14Since return address has no meaning, I'm
  2159. 1:31:17just storing it at to X0. It means that
  2160. 1:31:20we are not storing it because X0 is If
  2161. 1:31:23we are writing trying to write to X0, we
  2162. 1:31:25are not writing.
  2163. 1:31:26The
  2164. 1:31:27processor does not write to X0. X0 is
  2165. 1:31:30always zero.
  2166. 1:31:32But, it comes to ARS location. Return.
  2167. 1:31:35This is function return. It is jump
  2168. 1:31:37register RA.
  2169. 1:31:41So, [clears throat] return means that
  2170. 1:31:42jump register RA.
  2171. 1:31:44For example, in the compiled program, in
  2172. 1:31:46the compiled function, you can see just
  2173. 1:31:48a return, but this return means that
  2174. 1:31:51there is no return instruction in this
  2175. 1:31:52file. When you look at the instruction
  2176. 1:31:54set architecture manual, there is no
  2177. 1:31:56return instruction. This just
  2178. 1:31:58corresponds to jump register RA. It
  2179. 1:32:01means that jump register to array
  2180. 1:32:03register but does not store anything
  2181. 1:32:05this instruction.
  2182. 1:32:10So [clears throat] for example there is
  2183. 1:32:11a pseudo call instruction. Call
  2184. 1:32:13instruction says that go to this
  2185. 1:32:15location.
  2186. 1:32:17Go to this 32-bit location to this
  2187. 1:32:2032-bit address but in RISC-V it is
  2188. 1:32:22impossible to implement it in one
  2189. 1:32:24instruction because the maximum
  2190. 1:32:26immediate field is 20-bit. In this case
  2191. 1:32:30uh this call
  2192. 1:32:32function actually is
  2193. 1:32:34consists of two different functions.
  2194. 1:32:37One of them is add upper immediate to PC
  2195. 1:32:39and other one is the jump and link
  2196. 1:32:41register.
  2197. 1:32:42So this call
  2198. 1:32:44corresponds to two instructions
  2199. 1:32:46actually.
  2200. 1:32:48But this is pseudo instruction. If you
  2201. 1:32:49write it in assembly then your assembly
  2202. 1:32:52becomes more readable.
  2203. 1:32:55So in here there is a table. You can see
  2204. 1:32:58some pseudo instructions and it is
  2205. 1:33:00actually RISC-V correspondence. You can
  2206. 1:33:02check it.
  2207. 1:33:03Uh there is no need to memorize it.
  2208. 1:33:06For example there is no move instruction
  2209. 1:33:08in RISC-V. How can we do move
  2210. 1:33:11instruction? It is just add immediate
  2211. 1:33:13for example. If you want to move S3 to
  2212. 1:33:15T5 for example you can use
  2213. 1:33:17uh
  2214. 1:33:18add immediate T5 S3
  2215. 1:33:22for example zero. Or you can do it with
  2216. 1:33:25add instruction. Add T5 S3 X0. X0 is
  2217. 1:33:29always zero. You can do it with or for
  2218. 1:33:32example and or with X0 because if you
  2219. 1:33:36or the register with itself and then
  2220. 1:33:40write it back to another location then
  2221. 1:33:42it is just move move operation. Move
  2222. 1:33:44operation moves this S3 to T5.
  2223. 1:33:47There is not instruction for example but
  2224. 1:33:49in actual there is not instruction in
  2225. 1:33:51RISC-V in RISC-V. You can do it by using
  2226. 1:33:54XOR immediate.
  2227. 1:33:56So for example no instruction is writing
  2228. 1:33:59zero to zero plus zero, for example.
  2229. 1:34:01Because we cannot write zero, then this
  2230. 1:34:03is a no operation.
  2231. 1:34:07So, these are all actual
  2232. 1:34:08correspondences, but these are the
  2233. 1:34:10pseudo instructions. They are not
  2234. 1:34:12ex- They are not real not real, but
  2235. 1:34:15they are you can see them.
  2236. 1:34:18Uh this is the last concept.
  2237. 1:34:21Compiling, assembling, and loading
  2238. 1:34:22programs.
  2239. 1:34:27In
  2240. 1:34:28RISC-V, we told that instructions and
  2241. 1:34:32uh instructions are 32-bit, and
  2242. 1:34:34instructions and data are stored in
  2243. 1:34:36memory in RISC-V.
  2244. 1:34:38When we compiled it, uh
  2245. 1:34:41as a compiled
  2246. 1:34:43code,
  2247. 1:34:44there are instructions in it and data,
  2248. 1:34:46also. You can put data in it.
  2249. 1:34:50So,
  2250. 1:34:54for example, in here we have a assembly
  2251. 1:34:56code, compiled code, and it is machine
  2252. 1:34:57code correspondence. So, this
  2253. 1:35:00uh machine code is loaded to the main
  2254. 1:35:02memory, and then main memory
  2255. 1:35:05runs this code one by one. Assume it is
  2256. 1:35:09one by one. By the by time, we will see
  2257. 1:35:12architectures that runs the codes two by
  2258. 1:35:15two, four by four. Supers- They are
  2259. 1:35:17named as superscalar architectures.
  2260. 1:35:19For example, a machine can run four
  2261. 1:35:22instructions at a time immediately at
  2262. 1:35:23the same time.
  2263. 1:35:25But, assume that it increases the PC by
  2264. 1:35:27one by, and each time it runs an
  2265. 1:35:30instruction.
  2266. 1:35:32So, to run a new program, we simply
  2267. 1:35:34store the program in memory. So, we we
  2268. 1:35:36are writing a code in C, compiling it.
  2269. 1:35:39It's the assembly code. This assembly
  2270. 1:35:41code converted to machine machine code,
  2271. 1:35:44and this machine code is compiled
  2272. 1:35:46written to the main memory, and in main
  2273. 1:35:48memory, we have a program counter.
  2274. 1:35:50And each time, we are reading this main
  2275. 1:35:53memory region, this instruction from
  2276. 1:35:55main memory and
  2277. 1:35:57running it in the in the processor
  2278. 1:36:00and doing the computation.
  2279. 1:36:01So, in program execution pro- processor
  2280. 1:36:04fetches the list instruction from memory
  2281. 1:36:07in sequence
  2282. 1:36:08one by one.
  2283. 1:36:09And then we are performing the specified
  2284. 1:36:12operations.
  2285. 1:36:14So, for example, in here I put a example
  2286. 1:36:17for a more complex C code. In here I
  2287. 1:36:19have a main code and in this main I'm
  2288. 1:36:22calling function, this function, and it
  2289. 1:36:25has F and G arguments.
  2290. 1:36:27And this function does this operation
  2291. 1:36:31and calls itself again.
  2292. 1:36:34So, if for example in this function, if
  2293. 1:36:36B is less than zero,
  2294. 1:36:38then it returns A plus B, otherwise it
  2295. 1:36:41returns A plus
  2296. 1:36:43function A B minus one. So, it calls
  2297. 1:36:46itself again.
  2298. 1:36:47But at that time B is decreased by one.
  2299. 1:36:51So, when you look at here,
  2300. 1:36:54>> [cough and clears throat]
  2301. 1:36:54>> so
  2302. 1:36:59this is the main main.
  2303. 1:37:02So,
  2304. 1:37:03this is the function actually. This is
  2305. 1:37:05the function implementation. The
  2306. 1:37:06function first in This is the function
  2307. 1:37:08implementation. How function is
  2308. 1:37:10implemented in machine code in RISC-V
  2309. 1:37:12assembly.
  2310. 1:37:13At the beginning function makes room for
  2311. 1:37:16the forward
  2312. 1:37:17as stack pointer. Then it pulls these
  2313. 1:37:20values to stack pointer.
  2314. 1:37:22Does some move operations, for example,
  2315. 1:37:24it it moves A0 to S0. And does some
  2316. 1:37:27computations, you can inspect them at
  2317. 1:37:29home. I don't
  2318. 1:37:31go to the detail.
  2319. 1:37:32And in here there is a jump location,
  2320. 1:37:35branch greater equal zero, then it it
  2321. 1:37:38jumps back to this location.
  2322. 1:37:43So,
  2323. 1:37:45this is the location that called this
  2324. 1:37:48function by the way. This is most likely
  2325. 1:37:50main location main function because this
  2326. 1:37:52returns or this returns to main function
  2327. 1:37:56but otherwise it continues. In here
  2328. 1:37:58there is a return main function.
  2329. 1:38:03Otherwise by the way yeah no this is
  2330. 1:38:06this is not this is comparison this is
  2331. 1:38:08not return. This is comparison this
  2332. 1:38:10branch greater than equal this
  2333. 1:38:11comparison.
  2334. 1:38:13And if this comparison
  2335. 1:38:15branch greater than equal zero
  2336. 1:38:17if true then it does this operation and
  2337. 1:38:20returns. Does this A plus B operation
  2338. 1:38:22and returns. Otherwise it jumps to here.
  2339. 1:38:26This function plus zero X 28. This is
  2340. 1:38:29function address
  2341. 1:38:31and after zero 28
  2342. 1:38:34zero X 28 is most likely here and in
  2343. 1:38:36here it does this operation. And in this
  2344. 1:38:39operation we are calling this function
  2345. 1:38:41again in here.
  2346. 1:38:43We are calling this function again.
  2347. 1:38:47After calling this function again this
  2348. 1:38:50function is called again. I am putting
  2349. 1:38:51another set of variables in stack doing
  2350. 1:38:54this operation again and calling again
  2351. 1:38:57function and after some time
  2352. 1:39:00this function returns. Whenever this
  2353. 1:39:01function returns it continues from this
  2354. 1:39:03region here
  2355. 1:39:05and then jumps to back
  2356. 1:39:08to here actually the the
  2357. 1:39:10to here and then gets another return.
  2358. 1:39:14And then after that returns this value
  2359. 1:39:17and returns it to here.
  2360. 1:39:20So
  2361. 1:39:22maybe in here in in four five minutes it
  2362. 1:39:25is not
  2363. 1:39:26much
  2364. 1:39:29possible to understand this example but
  2365. 1:39:31definitely you you you need to inspect
  2366. 1:39:33it at home. You can inspect it one by
  2367. 1:39:35one running one by one.
  2368. 1:39:37So this is the main function. So this
  2369. 1:39:40main function is just also putting some
  2370. 1:39:42value to the store.
  2371. 1:39:46And then calls to the function, for
  2372. 1:39:47example, in here. And after that, it
  2373. 1:39:49returns and also main function returns
  2374. 1:39:52itself.
  2375. 1:39:53This is just compiled version of this C
  2376. 1:39:56and assembly code.
  2377. 1:40:01So, in here the there is another concept
  2378. 1:40:04of global pointer. We mentioned about
  2379. 1:40:06stack pointer.
  2380. 1:40:08Uh global pointer is also another
  2381. 1:40:11uh another region in memory. And in
  2382. 1:40:14global pointer, as name is global, it
  2383. 1:40:17keeps the global variables. For example,
  2384. 1:40:19in a C code,
  2385. 1:40:22if you write some variables like also
  2386. 1:40:25also outside of the main and these
  2387. 1:40:27functions inside file in in your C code
  2388. 1:40:30file, but outside of these functions,
  2389. 1:40:33main and function, they are the global
  2390. 1:40:35variables. And these global variables
  2391. 1:40:37are stored in
  2392. 1:40:39GP location.
  2393. 1:40:41So, compiler used this GP variable to
  2394. 1:40:44store the global variables. And global
  2395. 1:40:45variables are the variables stored
  2396. 1:40:47outside of the
  2397. 1:40:49functions in C code. This is a knowledge
  2398. 1:40:51from C, by the way, not related to this
  2399. 1:40:53class. This is a C C knowledge.
  2400. 1:40:56So, for example, in here, we are storing
  2401. 1:40:59F and G in this global pointer plus
  2402. 1:41:03minus 9 on 945, for example. And other
  2403. 1:41:06one is minus 940 in this global pointer
  2404. 1:41:09location. But,
  2405. 1:41:11you don't need to
  2406. 1:41:14yeah, know much about them because
  2407. 1:41:16compiler does this assignments, memory
  2408. 1:41:18assignments. You need to know the just
  2409. 1:41:20the meaning of GP. And GP is most likely
  2410. 1:41:23it was X3, most likely. I don't
  2411. 1:41:25remember, but it it might be X3. So, it
  2412. 1:41:28is a register and it has a special
  2413. 1:41:31meaning of global pointer in this file.
  2414. 1:41:38So, you can inspect these these examples
  2415. 1:41:40in detail at home.
  2416. 1:41:44So, when you compile a program, the
  2417. 1:41:46programs has some symbol tables.
  2418. 1:41:50Uh, most likely I have example in here.
  2419. 1:41:53Uh, no, we don't have example, but no
  2420. 1:41:56problem. Uh, text we previously
  2421. 1:41:59mentioned about it. Text means that code
  2422. 1:42:01instructions. Data means that if you if
  2423. 1:42:04I have data, for example, I have a array
  2424. 1:42:07and I define this array values as
  2425. 1:42:09constant in this C code, then this array
  2426. 1:42:12elements goes into the data segment.
  2427. 1:42:16For example, in here
  2428. 1:42:17uh, it says [clears throat] that
  2429. 1:42:19the instructions are placed at this
  2430. 1:42:21address 10074
  2431. 1:42:24in memory. And data is placed in 115E0
  2432. 1:42:28location in memory. It is not related
  2433. 1:42:31with us. Compiler does this job.
  2434. 1:42:33Compiler
  2435. 1:42:34knows to
  2436. 1:42:35CPU, its memory structure, and it places
  2437. 1:42:38the data and text section to there.
  2438. 1:42:41For example, text For example, function
  2439. 1:42:43three function, it is a function, it's a
  2440. 1:42:45instruction. So, instruction means that
  2441. 1:42:48text, for example.
  2442. 1:42:50So, compiler says that
  2443. 1:42:52the function is size of the function is
  2444. 1:42:543C. And it is placed at this location.
  2445. 1:42:58And there is also main function, and its
  2446. 1:43:00size is 34 34, and it's placed in this
  2447. 1:43:04uh, address. [clears throat]
  2448. 1:43:06And there is also BSS section. This is
  2449. 1:43:08also related with data. This is global
  2450. 1:43:10data, for example, FGY, and they are
  2451. 1:43:13stored in here.
  2452. 1:43:14But, this symbol table is generated by
  2453. 1:43:17the compiler. Also, you can say that,
  2454. 1:43:19for example, I want to put this text in
  2455. 1:43:22this memory region, you can also give
  2456. 1:43:23compiler a linker file, and you can do
  2457. 1:43:26it. But, compiler this this does this
  2458. 1:43:29job automatically.
  2459. 1:43:30And shows the where the data and
  2460. 1:43:33instructions are stored and global
  2461. 1:43:34variables are stored. And at the end
  2462. 1:43:37this
  2463. 1:43:39program, the program that you compile
  2464. 1:43:42are stored in memory in this way. And
  2465. 1:43:44this is the memory layout, for example.
  2466. 1:43:46In here, for example, I have
  2467. 1:43:48instructions.
  2468. 1:43:49This is the instruction region, for
  2469. 1:43:51example, text region, by the way.
  2470. 1:43:53This is the address, by the way. This is
  2471. 1:43:55the addresses for the text region.
  2472. 1:43:58And this corresponds to be here. And for
  2473. 1:44:00example, here is global pointer. So, you
  2474. 1:44:03all the compiler says that this address
  2475. 1:44:06keeps the global pointer stack. For
  2476. 1:44:09example, it C says that this is the
  2477. 1:44:11stack pointer. So, your stack addresses
  2478. 1:44:14in here. So, whenever while using stack,
  2479. 1:44:18you are using from here.
  2480. 1:44:19This is the region in memory that you
  2481. 1:44:21are using stack.
  2482. 1:44:23And this is the text, for example. The
  2483. 1:44:25And PC, for example, starts from here.
  2484. 1:44:27It says that PC needs to jump to here.
  2485. 1:44:30For example, operating system, whenever
  2486. 1:44:31you double click, for example,
  2487. 1:44:33PowerPoint, then operating system
  2488. 1:44:35changed the PC
  2489. 1:44:37as the first instruction of PowerPoint.
  2490. 1:44:41So, PC comes to here, for example, and
  2491. 1:44:43runs in here. And sometimes it jumps to
  2492. 1:44:46somewhere. And in some instructions, for
  2493. 1:44:48example, it loads data from this stock
  2494. 1:44:50pointer or loads this load any data from
  2495. 1:44:53global pointer. This is the way that how
  2496. 1:44:55programs run in a processor. It is not
  2497. 1:44:58specific to RISC-V. In all instruction
  2498. 1:45:00set architectures, it runs in this way.
  2499. 1:45:04And so, this is the last slides.
  2500. 1:45:07So, RISC-V design principles,
  2501. 1:45:09RISC-V follows the simplicity rules.
  2502. 1:45:12As you can see,
  2503. 1:45:14the location of RS1 is always same
  2504. 1:45:18irrespective of the instruction type.
  2505. 1:45:20The location of RS2, function 7,
  2506. 1:45:22function 3, all same. So, RISC-V follows
  2507. 1:45:26the simplicity. So, everything is
  2508. 1:45:28consistent. Same number of operands. So,
  2509. 1:45:31easier easier to encode and handle it on
  2510. 1:45:34hardware.
  2511. 1:45:36So, RISC-V also includes only simple and
  2512. 1:45:38commonly used instructions. For example,
  2513. 1:45:40I mentioned that RISC-V has no sub
  2514. 1:45:42immediate instruction because I can
  2515. 1:45:44implement sub immediate instructions
  2516. 1:45:46instruction by add immediate easily.
  2517. 1:45:48Just negating the immediate. So, RISC-V
  2518. 1:45:53doesn't have any sub immediate
  2519. 1:45:55instruction.
  2520. 1:45:56In this way also, since RISC-V is
  2521. 1:45:58simpler hardware to decode and execute
  2522. 1:46:00instructions can be simple, small, and
  2523. 1:46:02fast.
  2524. 1:46:03And more complex instructions performed
  2525. 1:46:06using multiple simple instructions. For
  2526. 1:46:08example, for overflow, we can put some
  2527. 1:46:11couple of instructions and
  2528. 1:46:13form this
  2529. 1:46:15overflow check
  2530. 1:46:17by using couple of instructions.
  2531. 1:46:20So, we can All instructions are simpler,
  2532. 1:46:22by the way.
  2533. 1:46:23So, since for this reason it's named as
  2534. 1:46:26reduced instruction set computer, RISC.
  2535. 1:46:30Other architectures such as Intel x86
  2536. 1:46:34are CISC, complex. Because in x86, I
  2537. 1:46:37told that instructions are variable. It
  2538. 1:46:39is between 1 or I think 17 bytes
  2539. 1:46:43between.
  2540. 1:46:44So, for example, one instruction is 1
  2541. 1:46:45byte. One instruction can be 4 byte. So,
  2542. 1:46:49their decoding all all are different.
  2543. 1:46:52So, this is complex. For this reason, it
  2544. 1:46:54is complex instruction set architecture.
  2545. 1:46:58So, for this reason, since RISC-V is
  2546. 1:47:01smaller, its decoding is simpler, it is
  2547. 1:47:03faster.
  2548. 1:47:05Always, for example, it has using either
  2549. 1:47:09three register or two register operands.
  2550. 1:47:11For example, in Intel, it changes. Maybe
  2551. 1:47:13it can use four, five registers.
  2552. 1:47:15Sometimes it is doing some For example,
  2553. 1:47:17it can do addition between a register
  2554. 1:47:19and a the
  2555. 1:47:20In RISC-V, if you want to do
  2556. 1:47:23uh addition between a memory region and
  2557. 1:47:25a register, you need to load this memory
  2558. 1:47:28to a register, and then you need to do
  2559. 1:47:30computation between the registers. You
  2560. 1:47:32cannot do a computation
  2561. 1:47:34in RISC-V, for example, there is no such
  2562. 1:47:36an instruction at
  2563. 1:47:38for example, X2, X3
  2564. 1:47:41uh address, for example, address
  2565. 1:47:440x FF8. For example, there is no such
  2566. 1:47:47instruction in RISC-V. But in, for
  2567. 1:47:49example, Intel, there is such
  2568. 1:47:51instructions. You are getting a register
  2569. 1:47:53and getting a getting a value from
  2570. 1:47:55memory and adding them, putting it to
  2571. 1:47:57the X2. In RISC-V, if you want to get a
  2572. 1:48:00if you want to access memory, the only
  2573. 1:48:03way is load or store
  2574. 1:48:05to access. So, for this reason, RISC-V
  2575. 1:48:08is simpler instructions.
  2576. 1:48:09And this simplicity at the end, in turn,
  2577. 1:48:13provides faster architectures. For this
  2578. 1:48:16reason, it is very good opportunity
  2579. 1:48:19uh
  2580. 1:48:20for right now to build processors in
  2581. 1:48:22RISC-V. And it is performance
  2582. 1:48:23increasing,
  2583. 1:48:25their performances are increasing by day
  2584. 1:48:27by day.
  2585. 1:48:30So, that's all for today.
  2586. 1:48:32Do you have any questions?
  2587. 1:48:36>> [clears throat]
  2588. 1:48:39>> So, if no questions, we can finish the
  2589. 1:48:41class.

About this transcript

This page contains the full transcript of W4 RISC V ISA II EN by Hasan Erdem Yantır, generated from the public captions YouTube serves with the video. The transcript has 14,512 words across 2,589 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.

What you can do with it

Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to translate the transcript into 100+ languages.

Free YouTube transcript tool

YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, translation to 100+ languages, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.