WEBVTT 00:00.000 --> 00:22.760 All right, hi. I'm Barish from Intel. I will continue talking about the work. So, we have 00:22.760 --> 00:31.840 seen that the overall location expressions are important. They play a crucial role in debugging. 00:31.840 --> 00:37.160 So here I'm giving you, and I took this, this is a real example. I took this from a, from 00:37.160 --> 00:46.960 a GPU program. It's a location expression, a sequence of the law for operators. And you 00:46.960 --> 00:53.920 may be now a developer who is relatively new to this debugging world. And then you may 00:53.920 --> 00:59.760 be wondering, okay, what does this mean? I mean, I want to learn. So I want to evaluate 00:59.760 --> 01:07.080 this step by step, and I want to understand how the dwarf expressions semantics are. Or you 01:07.080 --> 01:14.080 may be a relatively seasoned developer in this world. But then maybe there's a bug here, 01:14.080 --> 01:17.760 and then you want to debug the expression. You want to understand the details. Or perhaps 01:17.760 --> 01:25.480 you want to optimize it. You want to find a better way of expressing the location. Or perhaps 01:25.480 --> 01:32.160 you are an expert, and you want to introduce a new operator with some other with new semantics 01:32.160 --> 01:39.600 in the dwarf spec. And then you want to define this. You want to experiment with some examples. 01:39.680 --> 01:46.800 You want to test. You want to show this to other people and so on. Well, for this, I present 01:46.800 --> 01:55.600 you to the dwarf evaluator. We can go to, let's see if this is going to work. 01:55.600 --> 02:19.680 Yeah. So this is the repository. And there's one file here, ML. That's, you don't, okay, let me 02:19.680 --> 02:27.680 quit this. Yeah. Yeah. So there's one, there's one ML file. This is written in OCaml. I will just 02:27.680 --> 02:33.040 quit this scroll down. There are some definitions, functions, et cetera, et cetera, et cetera, and 02:33.040 --> 02:43.920 then there are the functions that define the semantics. And then like about here, let's 02:43.920 --> 02:55.840 the end. So in less than, less than 700 lines of code, it's, it's done. The rest is just examples. 02:55.840 --> 03:00.320 So you can just take this, I mean, it's lightweight and concise. So you can just take this one, 03:00.320 --> 03:07.040 just copy and paste. There are some, some OCaml interpreters online. You can just put them 03:07.040 --> 03:11.680 there. You can evaluate inside the browser or you can install it in your terminal and then 03:11.760 --> 03:29.440 work with it. It's not a parser. I will show. I will show. Yeah. So it's implemented in OCaml, 03:29.440 --> 03:36.000 which I think is the second best choice for this purpose. The first one would have been 03:36.080 --> 03:45.280 algal-68, but I don't know how to program it. Yeah. There's also a web playground. I'm going 03:45.280 --> 03:56.880 to show this to you. These are the operators that are currently implemented. It's not the full set, 03:56.880 --> 04:02.720 but I think it's, it's pretty, pretty representative and you can, you can do useful stuff. 04:03.680 --> 04:10.800 So on the left-hand side, we see some snippets from the actual devolve spec version 6. 04:12.080 --> 04:16.480 I don't expect you to read this, of course, but I have highlighted some important places, 04:16.480 --> 04:22.320 and I will show some correspondence with implementation. For instance, here it says a location 04:22.320 --> 04:28.960 names a block of storage and an offset. Well, what this means is that location is a pair of storage 04:29.040 --> 04:34.640 and offset. Here it's, here is the definition. Location is a pair, storage and an integer. 04:35.200 --> 04:41.600 Or it says there are six kinds of storage, memory register, the one in the composite. So memory 04:41.600 --> 04:47.680 register composite. Composite storage consists of a possibly empty series of continues pieces. 04:47.680 --> 04:57.520 Well, composite storage has a list of pieces and so on. So with the spec, the verbal English version 04:57.600 --> 05:04.400 of the spec versus the code. I hope that there will, there will be a nice correspondence to, 05:06.080 --> 05:10.480 to show how, how this is defined. Some more examples, again from the spec, 05:12.480 --> 05:18.160 the expressions operate on a stack of entries. Each of which may be either a value or location. 05:18.160 --> 05:24.480 Now, a stack element is either a value or a location. And then there is this evolve function, 05:24.480 --> 05:30.800 which takes an operator, stack and the context. Okamol is valid, it's typed and types are 05:30.800 --> 05:36.560 inferred. It's not explicit written here, but the inferred type for this argument, 05:36.560 --> 05:44.320 stack argument is a list of stack elements, which is just a stack. Again, taking a look at the definition 05:44.320 --> 05:52.640 of DWOp Adder. It says, well, takes an Ad, takes an operant, which is address in the default 05:52.720 --> 05:58.720 address space. And the corresponding memory location is pushed onto the stack. Well, let's take 05:58.720 --> 06:09.200 a look at how it's defined. Default address space is map 0, 0 is the default index. And then with 06:09.200 --> 06:15.360 the given address, which happens now, happens to be the offset, we push a location onto the stack. 06:15.520 --> 06:23.760 Or for the REC operators, a location that names the storage associated with the designated 06:23.760 --> 06:28.800 register with an offset of 0 is formed and pushed on the stack. Exactly what's happening here, 06:28.800 --> 06:37.040 furnishes for REC one. We form a location for REC one with offset 0 and push it on top of the stack. 06:37.120 --> 06:45.920 A few more examples. Well, DWOp top duplicates the entry. Here, the pattern matching 06:46.960 --> 06:55.440 feature of a cable disiting excellent. So we do a pattern matching on the stack. We expect an 06:55.440 --> 07:01.040 element on the top with rest of the stack, which is now a stack prime. And then we duplicate it, 07:01.120 --> 07:06.880 E1, the element E1 followed by E1 again, followed by rest of the stack. Or for rotation, 07:06.880 --> 07:13.280 says there are three stack entries. Well, then the stack has to be E1, an element followed by another, 07:13.280 --> 07:21.200 followed by the rest. And then we rotate them and then give the give the new state of the stack. 07:22.080 --> 07:27.280 Relational operators, again, I don't expect you to read, but what it says is that, well, we push the 07:27.360 --> 07:32.960 constant value one or zero depending on the operation. Well, here is the definition, 07:33.840 --> 07:40.400 we expect E1 and E2 and then they have to be values, so that we can compare them. And then depending 07:40.400 --> 07:52.000 on the result of comparison, we either push value one or value zero. Here is how you can use it. 07:52.560 --> 08:04.800 Um, for this I want to give a demo. I start your camera, yeah, interpreter and then I load the file. 08:05.760 --> 08:16.560 And then I can say for instance, I want to evaluate the work list of the work operators. So let me push 08:17.440 --> 08:28.720 um, three, let me push four and then I'm going to multiply. I want to evaluate this in an in the 08:28.720 --> 08:36.400 empty stack initially and in an empty context. So I do that and I get the result. Okay, so this is how 08:37.040 --> 08:52.080 it's not a parser, this is how you can use it. This is an actual example, again from the spec, 08:52.080 --> 09:00.400 an example for for the pick operator. Well, here is what I did. I want to, I want a DW pick 09:00.400 --> 09:09.680 two evaluated in this initial stack, 17, 29, 1000 and then I get this as the result. 09:14.080 --> 09:18.640 Um, another example, again, actual example from the stack, this time it relates to a 09:19.200 --> 09:30.640 location. Um, so composite location is being formed with these operators. What I did is that 09:30.640 --> 09:36.640 well, frame frame base register, I mean it's ABI dependent, so I just said, okay, let's let's 09:36.640 --> 09:43.360 say register nine is frame base. And then I evaluate in a context where we need to define our 09:43.360 --> 09:48.000 register zero and register nine and then I get this composite with three pieces. Well, 09:49.440 --> 09:57.360 the first part is first four bytes reciting register zero, so byte zero until four registers zero. 09:58.000 --> 10:04.240 Middle four bytes are unavailable, unavailable and the last four bytes are in memory 12 bytes 10:04.240 --> 10:10.800 before the frame base. So last four bytes, they are in memory and the value 30 which is 12 bytes 10:11.760 --> 10:23.680 below the frame base. This is the text which gives which defines piece operators, which defines 10:23.680 --> 10:32.880 the piece operations and there is also definition of compatibility rules for the world version five. 10:32.880 --> 10:38.640 There are three rules. Now, if you look at the, look at the code well, we have three 10:38.720 --> 10:44.800 compatibility rules. The point I'm trying to make here is that for some people looking at this 10:45.520 --> 10:51.120 maybe easier to understand and the purpose is to help these people. 10:54.000 --> 11:00.480 There's a web playground. This was contributed by Scott Lindner from AMD, so full credits goes to him. 11:00.560 --> 11:07.840 And I thank him very much. In the web playground, you can do step by step. 11:07.840 --> 11:30.800 So here you type the context, you type the expression and then it evaluates. Here's an example. 11:31.760 --> 11:52.320 In the AMD context, I'm going to evaluate DWOP lit 5 DWOP lit 8 DWOP plus DWOP lit 3 and then let's say multiply. 11:52.960 --> 12:00.880 And then I evaluate. This shows you the state of step by step. So here's the state of the 12:00.880 --> 12:09.280 stack and then we evaluate this. We get this stack state and so on until and we end up with the value. 12:09.280 --> 12:30.640 In the web, let's try it again. So I should have opened this already. 12:30.960 --> 12:42.000 I'm going to show you another example. The same example from the actual spec, 12:42.000 --> 12:58.800 but done in the web playground. What we see, here's the same example. 13:01.200 --> 13:07.920 The expression there and when I evaluate again, it goes step by step and then we end up with a location on 13:07.920 --> 13:26.000 top of the stack. This is the result. I just cut it from there and then again you can see the 13:26.000 --> 13:32.720 correspondence between what the spec explains and what we end up with. This is a composite location. 13:33.680 --> 13:44.000 There's actually a DWOP issue where which defines a new operator. Overlay. 13:45.600 --> 13:56.880 I'm finishing and here there are some examples and here you would see links like this. 13:57.200 --> 14:04.320 You can just open it, evaluate it and you can see what the example is named. So this is another 14:04.320 --> 14:07.920 use case where such a tool could be useful. 14:07.920 --> 14:28.920 I present to you, I present to you the Wurf evaluator. To learn or teach, to understand the 14:28.920 --> 14:36.600 Wurf expressions, I think it's useful. I want to thank my managers for allowing me the time to work on this. 14:38.280 --> 14:44.440 There are some notices and disclaimers. Thank you for reading and with that I conclude. 14:45.080 --> 15:08.520 Why is not in GDP? So the goal here is that it's lightweight. You just take it and we're 15:08.520 --> 15:16.200 not having to go into the details of a full-fledged compiler or a debugger you can just run it and 15:16.200 --> 15:26.040 experiment with it easily. Thank you.