In the previous unit, we learned how to implement the gate logic using HDL. However, nothing in what we did guarantees that the HDL code that we wrote is actually correct. We have no idea if this architecture that we put together delivers the intended results of the chip that we seek to design. So in this unit, we will close this gap and we will learn how we can take an HDL program and verify to the best of our ability that the program or the HDL file delivers the intended functionality of the underlying chip. Now here is the big picture of what we're going to do. Given that we have a particular HDL file and we want to test it, we can load it into a special program called hardware simulator. We have written such program and made it available to you, in our website. This program happens to to to be written in, in Java. And this program is designed to simulate and test HDL files. So we load it into this program. We interactively test all sorts of operations in this chip and we call this mode of testing interactive simulation. Alternatively we can write another file and using a special language that we designed, which we call the testing language, something that you can learn in a few minutes. We can put together a set of replicable tests that are predetermined. So we don't have to do things interactively. We can think ahead of how we can systematically test the underlying chip. We write in what is called a test script and then we load into the simulator two separate files. We load the HDL code. We load the test script and then we send the simulator to work. The simulator goes through every step in the test script and subjects the HDL code to the to the specified tests in this supplied script. We call this mode of operation script-based simulation. And finally, if we want, we can record the output of the simulation on something called an output file. And we can even compare the results of the simulation to a desired output, which is stored in, in yet another file called compare file. So as you see, there are many new concepts and techniques involved in this practice of hardware simulation. And the purpose of this unit is to make, you know, all this new information concrete by walking you through a step-by-step process of testing a working example that will accompany us throughout this unit. Now, throughout this unit, we are going to present several software tools. Actually only one software tool, the hardware simulator, and you are more than welcome to stop the video. Invoke this hardware simulator on your own computer and make sure that what we do can be done also on your machine. You can do all of this if you have downloaded the software suite at the beginning of the course and if so, the hardware simulator should be available on your computer. And everything that we do in the lecture can be done by by you as well. So we encourage you to kick tires as much as you please. So let's go on and and start with the with some concrete examples. So here's the example that I'm going to use throughout this unit. It's an HDL file describing the score chip that we talked about in the previous unit so the code itself should be familiar to you even though it's not terribly important for understanding this particular unit. All right. So once again the fact that we wrote this very nice piece of code does not imply in any way that the code is actually correct. In fact most likely it contains some errors, either syntax errors or logical errors or, or whatnot. So how do we test it? Well, here's what we can do. We can invoke the hardware simulator. Program starts running. We can load the HDL file into this simulator and we can then enter zeroes and ones into the a and b inputs and observe what is going on inside the chip. Now, how do we observe what is going on? Well, we have to tell the simulator to evaluate the chip's logic. The simulator will not do anything until we, we tell it to actually consider the new inputs that we entered and evaluate the chip's logic. And if we do this, the simulator will take these values, these zeroes and ones, or whatever we entered, and will kind of pipe them through the architecture. And at some point, something will come out from the from the output pin of the chip, so at that point, we can inspect what actually materialized. So we can observe the outputs of the chip and in this particular case, the value of the out pin and if we want, we can also inspect the values of the internal pins. Pins like not b, not a and so on, and the simulator gives us all these all these nice capabilities. In particular, here's an example or screenshot of the hardware simulator in action and the simulator contains features, several different panes. So, let's talk about each one of these panes in isolation. First of all, at the bottom-left of the screen, we see the HDL code that we have loaded into the simulator. This is a static view. We cannot manipulate or edit this code. If we want to edit anything, we have to use an external text editor, change the HDL code and reload it. So this pane you know, gives us an idea of what is it, what is it exactly that we loaded into the simulator. Here we can actually interact with the input panes of the simulator. We can click them and change the values. We have four different possibilities of zeroes and ones in, in this particular example. Now this is very simple chip. And once we do this, we can click this icon. Which looks like a calculator, and once we click it, we basically tell the simulator to evaluate the chip's logic on the supplied inputs. At this point the simulator will spin its wheels. It will take a fraction of a second and something will come out. We can then evaluate the output of the chip. In this particular case we have only one output called out. And once again if we want we can also inspect the the current values of the internal pins. So altogether this GUI gives us everything that we need. In order to carry out sort of hands on interactive simulation of of exalt chip or any other chip for this matter. All right, moving along I would like now to give you actually a hands on example of of the hardware simulator in action. So let's do that and then go back to the to the lecture. This is the hardware simulator. And, in order to use it, we have to first of all, load an HDL program into the simulator. And, we do it by clicking this icon here. So, let us do it. And, we see that we are in the nand2tetris folder, so within this folder, we're going to select Projects. And within Projects, we'll select Project 0. And we see that we have a single HDL file here, so let us select it. This is Xor file that we discussed before. And we loaded the chip into the simulator. [COUGH] Now the pane at the bottom left, right here gives me a display of the file that I just loaded. I can scroll back and forth. It's not separate, it's not terribly useful but this pane is actually just a read only display. There's no way to actually change the code when you are inside the simulator. If you want to change the code, you have to do it using an external text editor and then you have to reload, of course, the file that you changed and saved elsewhere. So, let us assume that we are happy with this file and I want to actually simulate the chip logic. Well I do this by first of all looking at the current input values and we see that the default values of the a and b inputs of Xor chip happen to be 0. So if I want, I can go ahead and change one of them, or both of them to some other values. So let us change A to 1 and let us change and let us also change b to one. And I noticed that nothing yet happened in order to, to see how the chip responds to these changes. I have to reevaluate the chip logic and I do it by. By clicking this icon here, the calculator icon. So let us do it and we see that once we click this icon, the output becomes 0. And [COUGH] indeed Xor of 1 and one is 1. If you want to see some other possibilities, we can once again manipulate one of the input panes. Click the calculator, and we see that Xor now emits, 1 instead of 0. Another thing that we can do is, inspect the values of the internal pins which gives us yet another level of scrutiny in particular when we, when we try to debug the chip and understand why it is misbehaving for some reason. So this has been a very brief description of the first thing that we do when you use a simulator, you load the chip, you play with the input panes, you inspect the outputs and the internal pins, and and this is the ABC of of chip debugging and testing. I wish to remind you in closing that if you want to change the chip logic,. You have to edit the HDL file using some external text editor. Save the new file, reload it into the simulator and rerun the tests in order to test the new chip design. Now, interactive simulation is, is very nice indeed, but at some point it can become rather tedious, especially if you have you know, lots of bugs in your design and and each time you have to, you know, go through the same set of tests and so on and so forth. So, with that in mind. We are fortunate that we also have the notion of a test script available to us. So here once again is the tested chip. And by the way, I allow myself to use the words chip and gate interchangeably for me, a gate is simply a, a simple chip. So this is the tested chip. And here is an example of a test script designed to test a Xor gate. Now let us go through the test script kind of line by line. The first command in the test script instruct the simulator to load the Xor.hdl file into the program. So even this step is, is taken care of. We don't have to do it ourselves. The test script will, will load the program for us. By the way, this is terribly important if you do repetitive debugging, because how do you debug a gate? You use an external text editor you know, to change the gate, and then you, you click Save, and you go back to the simulator. So, it's important to remember to reload the new version of the edited chips. So, that's why we added this command that to, to the test script. Now, once the test once the hdl is loaded into the simulator, the test grid begins a process of subjecting the chip to to four different tests. The semicolon represents you know, the ending of of one particular test if you will. And so, we set the input values of the chip to 0 and 0. We evaluate the chip logic and observe the results and then we go through the next test and and so on and so forth until we complete all the possible all, all the input possibilities for this particular chip. So this is how we carry out script ba, script-based testing. And it has many benefits. And far and foremost is the fact that we don't have to do anything laboriously, you know, using our own sort of intuition. Because everything is pre-determined. We have a set of rep, replicable tests and we just. Use the same tests over and over whenever we we debug the chip which can be you know, two weeks or two months from now. So it's good to know that you can always repeat the same set of tests. So, altogether, we will try to always use a test script. And the good news is that you don't really have to worry about how to write test scripts because we are going to supply to you all the test scripts that you need in order to test the the chips that, that you are going to design in hdl. So you worry about the hdl and we are going to worry about the the testing of of your work. Another thing that we can do is keep track of the outputs of the simulation. So in particular we can augment our basic test scripts with something like the following commands. We can at the beginning of the of the test when we initialize things, we can. Instruct the simulator to create an output file, which in this example, we happen to call Xor.out. And as we go through the through the testing. At the end of each test, we tell the simulator to output to the output file a set of values, which is determined in the preamble of the script. So, as you see the third line with script says, the output placed is a, b, and out. And so whenever the simulator would see the directive output, it will write to the output file, the current values of a, b and out. And at the end of the simulation, we can simply inspect the result of the output file and convince our self that the chip has actually behaved according to expectations. In fact, in this particular example, if you will inspect the output file that emerged from the simulation, you will notice that it is completely identical to the truth table of Xor gate. So it looks like the gate is well behaving. So here's a snapshot of the hardware simulation in action using a test script. And once again, we have the HDL code as, as we did before at the bottom left of, of the screen. But we, but we now have something new. We have a test script, which can be seen on the right pane. Which is some sort of a multipurpose GUI area, which we use for for different purposes. And after we load the script, we can instruct the simulator to actually execute the script. We do it by clicking this control and the simulator the simulator goes to work. And at the end, if we want, we can inspect the resulting output file. And here is also a demo of of the same thing with, with an actual how do simulations session. We will now show how to use the how to simulator in order to test an HDL program using a test script. So the first thing that we can do is load the HDL program into the simulator. So let us choose the same Xor.hdl chip that we used before and then instead of playing with the input pins interactively. We can use this icon here to open a test script and we see that in the project zero folder, we have one test script called Xor.tst. So let us load it into the simulator environment. Once we do it this pane in the interface shows us the contents of the currently loaded test script and we see that it begins with a few comments. And then following that, we see the actual testing commands. And the first command or the next command to be executed, is highlighted by a yellow bar, we can call it the cursor of the of the test script. Now we see that each command ends either with a comma or a semicolon and when we click the play icon, the simulator is going to execute all the testing commands until the next semicolon is encountered. Now the first four commands in this test strip set up the simulation so to speak. And so let us, let us execute them. So I click this icon here. And we see that the cursor moved to the next batch of commands. And this batch says, set a to 0, set b to 0. These are the input pins of this particular chip. And then evaluate the chip logic and output the result into the output file. So let us execute this batch of commands and we see that indeed, the a and b inputs are now 0 and the out of the chip happens to be 0, which seems to be right. Because as we know, Xor of and zero and zero should be zero. So let us execute the next batch of test script commands. This batch sets a to 0 and b to 1, evaluates the shapes and outputs the result and indeed, we see that Xor of 0 and 0 ended up being 1, which seems to be correct. So executing the next batch of commands sets a to 0, I'm sorry. Sets a to 1 and b to 0 giving the result 1, which also seems to be correct. And then moving along, we execute the next and final batch of commands, which set both a and b to one. And we see that the Xor response by emitting the value zero, which once again seems to be correct. Now the test script for Xor gate is relatively simple, because basically, it simply executes every possible input combination as stated by the chip truth table. In more complex shapes such an exhaustive testing is is less feasible. And therefore, the test, testing scripts will likely be more complex. Now, as we tested this script the script has also written the results of every test script batch into the output file. You know, this is the the result of saying output in, in the I'm sorry. This is the result of, of the output command. Now, if we want to inspect the output file, we can do so by going to this control here and selecting Output. So let's do that. And once we do it, we see that the output file, indeed looks exactly, like the truth table of Xor and this gives us yet another indication that the chip has operated to a specification. Before we go on with this step by step working example, I would like to stop for a minute or two and say some general things about the general concept of hardware simulators. So first of all, there are many of them. Some of them are free and open source. Others are proprietary and very sophisticated and very expensive. And in this course, we use a simple hardware simulator, which at the same time, gives you everything that you need in order to build the head computer and any other computer that you want to build using the techniques described in the course. So the supplied hardware simulator, which you have on your computer now is a, is a tool that once again, gives you everything you need. And if you want to learn how to use it, there are several places to consult with available documentation. If you go to the nand2tetris .org website you can find a full chapter, I think it's appendix a and appen, actually appendix and appendix b. In our book describe how to use the hardware simulator and these, these chapters are also available freely on the website and another thing that you should do is go for the hardware simulator tutorial, which is a stack of interacting slides that that explain how to use the simulator as well as all of the examples that you saw in this particular lecture. So that's the end of of the commercial break about hardware simulators and we return to our ongoing example. So let us revisit what we have done so far. We looked at a particular HDL file, which records the logic of Xor. We have supplied the simulator with a test script designed to test this particular code. And we also looked at the resulting output file and convinced ourself that the HDL file is actually correct. Now this privilege of looking at an output file and saying, yeah, it works is something which is rarely available in real life testing. Why? Because the chips that we normally build are far more complex than Xor gate. And there is no way to look at an output file of let's say an ALU or, or a CPU chip or something like that. And, and say, yeah, it works correctly. You know, it's we, we have to do it in, in a far more systematic and planned way. So is there a way to do it? Well, you bet. And that's, that's what we're going to do next. In particular, we can carry out the simulation with yet another tool which is called a compare file. So here's an example of a compare file. It looks exactly like an output file. And in fact, in its previous incarnation, the compare file was a, a, an output file of a well-behaving Xor chips. So someone, and we'll talk about this someone momentarily, someone has written an Xor chip correctly. Ran it thru the simulator, generated an output file. Renamed it compare file and gave it us. And said, now you go and build your chip and, and compare it to what I did. So basically, we can take the compare file and load it into the simulator and then start to do the simulator as the simulation as we did before. And now, in each step of the simulation, whenever we output a set of selected pin values, the simulator will compare the output set of values to the respective line in the compare file. And if the two lines will not agree with each other. The simulator will not throw a comparison error. So this gives us that ability to not only record the outputs of the chip, but also compare them to desired results. So you probably asked yourself once again, how do we generate these compare files to begin with? Right? Well, we, we could have left it as as a mystery, but there is no need to to leave anything unexplained. So here's how we do it. We do it using something called behavioral simulation. In particular, consider this Xor gate that we saw before. And let us assume, once again that this implementation is correct and we put it into the simulator along with the script. We run it, we generate results and then we simply rename it to be Xor.cmp and it becomes the official compare file of this shape. So what is special about this slide, didn't, didn't you say, everything that we said here before. Well, we did, but there's one detail which is, which is remarkably interesting in this in this notion of behavioral simulation. And, and the thing which is interesting is that the chip logic can be implemented in any way that the designer wishes. So we can write this chip logic in Java or some other high-level language. We can run the program. We can generate an output file and then once again, supply it as, as a compare file. So this technique of writing gate logic using or implementing gate logic using high-level language, gives you the ability to plan and test your hardware before you even write a single line of HDL code, which is, you know quite sophisticated way to do things. So we, you know, we can do everything in a high-level and only once the overall design of our machine works properly, we can begin to implement each chip at the time in in HDL. All right. So this has been the notion of behavioral simulation and I want to go on and talk about how we actually carry out hardware construction projects. So the cast of characters in any hardware construction project consists of several players of which, I would like talk about two. First, we have the system architect. Now the system architect is, is the person who is told, you know, go build a chip that supports a certain function of a digit, digital camera or something like that or go build a chip that monitors a certain medical device. So the architect has the exact sort of user-level specifications of the chip and and the other member in the team is a developer or, you know, more than one developer or more than one architects and together, they have to design this chip. So how do they do it? Well, the system architect looks at the overall desired operation of of the chip. And then he or she makes some decisions about how to break this overall behavior into a set of smaller chips if you will or sort of lower-level chips. And then for each one of these chips, the architect, the architect creates a chip API, which consists of the name of the chip, the names of its input and output pins. A test script and a compare file. Now, all these things are prepared by the system architect who, you know, may, may or may not have some people to help him or her in his work. And finally, given these resources, the developers can actually go out and build the chip. So the architecture can do behavioral simulation or they can do whatever they want in order to test that everything fits together nicely. And at some point, the developers actually build this thing using HDL. So, once again, that's, that's an example of well planned modular design and gives another example of divide and conquer. You know, taking something very complicated and breaking into something more, you know, a set of more manageable modules. Each of which can be created and tested in isolation. So for example, the HEC computer I could've told you something like go build yourself a computer and actually that's what we do in this course. But we split this job into the construction of something like 30, you know 30 different shapes that together comprise the HEC chip set. So we, Norm and I, the course instructors, we play the role of the system architects and you guys are playing the roles of the actual hardware developers. All right. So the developer's view, your view of a particular chip. You know, when we tell you to build a chip, here's what you get. You're going to get a stub file that contains the documentation of the chip that you have to build, along with its interface. You're also going to get a test script that we have written for you. You're going to get a compare file and then, you know, taken together, what you've basically got is everything that you need in order to number one, understand the interface. Understand what the chip is supposed to do, the compare file and we'll also tell you how we are going to test it. All right. So what do you do with all these resources? Well what you have to do is write the missing implementation. The missing implementation is the HDL code that should actually drive this entire show. So that's exactly what we're going to do in unit 1.7. But before we go onto this unit, we also have to say a few things about Multi-Bit Buses, which is a gap that we still have to close in in the general description of HDL programming.