6. How do we study Computer Systems?#

6.1. Admin#

  • make sure you have a grading contract repo

  • you’ll track your progress in your

6.2. Studying Systems#

When we think of something as a system, we can study it different ways:

  • input/output behavior

  • components

  • abstraction layers

When we study a system we can do so in two main ways. We can look at the input/output behavior of the system as a whole and we can look at the individual components. For each component, we can look at its behavior or the subcomponents. We can take what we know from all fo the components and piece that together. However, for a complex system, we cannot match individual components up to the high level behavior. This is true in both computers and other complex systems. In the first computers in the 1940s, the only things they did was arithmetic and you could match from their components al the way up pretty easily. Modern computers connect to the internet, send signals, load complex graphics, play sounds and many other things that are harder to decompose all at once. Outside of computers, scientists have a pretty good idea of how neurons work and that appears to be the same across mammals and other species (eg squid) but we do not understand how the whole brain of a mammal works, not even smaller mammals with less complex social lives than humans. Understanding the parts is not always enough to understand all of the complex ways the parts can work together. Computers are much less complicated than brains. They were made by brains.

But that fact motivates another way to study a complex system, across levels of abstraction. You can abstract away details and focus on one representation. This can be tied literally to components, but it can also be conceptual. For example, in CSC211 you use a model of stack and heap for memory. It’s useful for understanding programming, but is not exactly what the hardware does. At times, it is even more useful though than understanding exactly what the hardware does. These abstractions also serve a social, practical purpose. In computing, and society at large really, we use standards these are sets of guidelines for how to build things. Like when you use a function, you need to know it’s API and what it is supposed to do in order to use it. The developers could change how it does that without impacting your program, as long as the API is not changed and the high level input/output behavior stays the same.

Let’s take those three pieces, behavior, components, and abstraction in turn.

6.2.1. Behavior#

This is probably how you first learned to use a computer. Maybe a parent showed you how to do a few things, but then you probably tried other things. For most of you, this may have been when you were very young and much less afraid of breaking things. Over time you learned how to do things and what behaviors to expect. You also learned categories of things. Like once you learned one social media app and that others were also social media you then looked for similar features. Maybe you learned one video game had the option to save and expected it in the next one.

Video games and social media are classes or categories of software and each game and app are instances. Similarly, an Integrated Development Environment (IDE) is a category of software and VS Code, … are instances. Also, version control is a category of software and git is an instance. A git host is also a category and GitHub is an instance. Just as before you were worried about details you transferred features from one instance to another within categories, I want you to think about what you know from one IDE and how that would help you learn another. We will study the actual features of IDE a=and what you might want to know about them so that you can choose your own. Becoming a more independent developer you’ll start to have your own opinions about which one is better. Think about about a person in your life who finds computers and technology overall intimidating or frustrating. They likely only use one social media app if at all, or maybe they only know to make documents in Microsoft word and they think that Google Docs is too much to learn, because they didn’t transfer ideas from one to the other.

We have focused on the behavior of individual applications to this point, but there is also the overall behavior of the system in broad terms, typing on the keyboard we expect the characters to show (and when they don’t for example in a shell password, we’re surprised and concerned it is not working).

6.2.2. Components#

We have the high level parts: keyboard, mouse, monitor/screen, tower/computer. Inside we also tend to know there is a power supply, a motherboard, graphics card, memory, etc.

We can study how each of these parts works while not worrying about the others but having them there. This is probably how you learned to use a mouse. You focused your attention on the mouse and saw what else happened.

Or we can take an individual component and isolate it to study it alone. For a mouse this would be hard. Without a computer attached its output is not very visible. To do this, we would need additional tools to interpret its output and examine it. Most computer components actually would need additional tools, to measure the electrical signals, but we could examine what happens at each part one at a time to then build up what they do.

This idea, however that we can use another tool to understand each component is an important one. This is also a way to again, take care and study each piece even within a software-alone system without worrying about the hardware.

6.2.3. Abstraction#

As we talked about the behavior and abstraction, we talked some about software and some about hardware. These are the two coarsest ways we can think about a computer system at different levels of abstraction. We can think about it only in physical terms and examine the patterns of electricity flow or we can think about only the software and not worry about the hardware, at a higher level of abstraction.

However, two levels is not really enough to understand how computer systems are designed.

layers

This diagram is mostly what computer scientists and engineers use to describe a computer system.

Application - the software you run.

Algorithm - the way that it is implemented, in mathematical level

Programming language - the way that it is implemented for a computer.

Let’s take a simple example, let’s say we are talking about a simple search program that we wrote that finds xx. We can say that you put in a part of a file name and it shows you all the ones with a similar name. That description is at the application level it gives the high level behavior, but not the step by step of how it does it. Let’s say we implemented it using bubble search then searches by … That’s the algorithm level, this is still abstract and could be implemented in different ways, but we know the steps and we can use this to know some things about how fast it will be, what types of result swill make it slower, etc. At the programming level language then we know which language it was done in and we see more details. At this level, we can see the specific data structures and controls structures. These implementation details can also impact performance in terms of space(memory) or time. Still at this level, we do not need to know how the actual hardware works, but we see it in increasing detail. At each level we have different types of operations. At the application we might have input, press enter, get results. At the algorithm we have check the value, compare. At the programming language level we need more specifics too, like assign or append.

After the Programming language level, there is assembly. The advantage to assembly is that it is hardware independent and human readable. It is low level and limited to what the hardware can do, but it is a version of that that can be run on different hardware. It is much lower level. When you compile a program, it is translated to assembly. At this level, programs written in different level become indistinguishable. This has much lower level operations. We can do various calculations, but not things like compare. Things that were one step before, like assign become two, choose a memory location, then write to memory. This level of abstraction is the level of detail we will think about most. We’ll look at the others, but spend much less time below here.

Machine code translates to binary from assembly.

The instruction set architecture is, notice, where the line between software and hardware lives. This is because these are specific to the actual hardware, this is the level where there are different instructions if you have an Intel chip vs an Apple chip. This level reduces down the instructions even more specifically to the specifics things that an individual piece of hardware does and how they dit.

The microarchitecture is the specific circuits: networks of smaller individual components. Again, we can treat the components as blocks and focus on how they work together. At this level we still have calculations like add, multiply, compare, negate, and we can store values and read them. That is all we have at this point though. At this level there are all binary numbers.

The actual gates (components that implement logical operations) and registers (components that hold values) break everything down to logical operations. Instead of adding, we have a series of and, nand, or, and xor put together over individual bits. Instead of numbers, we have registers that store individual zeros or ones. In a modern digital, electrical computer, at this level we have to actually watch the flow of electricity through the circuit and worry about things like the number of gates and whether or not the calculations finish at the same time or having other parts wait so that they are all working together. We will see later that when we try to allow multiple cores to work independently, we have to handle these timing issues at the higher levels as well. However, a register and gate can be implemented in different ways at the device level.

The device (or transistor in modern electrical digital computers) level, is where things transition between analog and digital. The world we live in is actually all analog. We just pay attention to lots of things at a time scale at which they appear to be be digital. Over time devices have changed from mechanical switches to electronic transistors. Material science innovations at the physics level have improved the transistors further over time, allowing them to be smaller and more heat efficient. Because of abstraction, these changes could be plugged into new hardware without having to make any changes at any software levels. However, they do enable improvements at the higher levels.

Note

For example, Bayesian statistics is a philosophy that treats probability as subjective uncertainty instead of as frequency. This has some interpretative differences, but most importantly it means that we always need an extra factor (multiplied term) in our calculations. This makes all of the math much more complex. For many decades Bayesian statistics was not practical for anything but the simplest models. However, with improvements to computers, that opened new options at the algorithm level. The first large scale application of this type of statistics was by Microsoft after their researchers built a Bayesian player model for player matching in Halo.

We are going to focus today on the Assembly level and use an abstraction of computers called the von Neumann model for today.

wikipedia von neumann

6.3. Using the simulator#

On MacOS:

cd path/nand2tetris/tools
bash CPUEmulator.sh

On Windows: Double click on the CPUEmulator.bat file

We’re going to use the test cases from the book’s project 5:

  1. Load Program

  2. Navigate to nand2tetris/projects/05

We’re not going to do project 5, which is to build a CPU, but instead to use the test.

For more on how the emulator works see the CPU Emulator Tutorial.

For much more detail about how this all works chapter 4 of the related text book has description of the machine code and assembly language.

6.4. How does the computer actually add constants?#

We’ll use add.hack first.

This program adds constants, 2+3.

It is a program, assembly code that we are loading to the simulator’s ROM, which is memory that gets read only by the CPU.

Run the simulator and watch what each line of the program does.

Notice the following:

  • to compute with a constant, that number only exists in ROM in the instructions

  • to write a value to memory the address register first has to be pointed to what where in the memory the value will go, then the value can be sent there

The simulator has a few key parts:

  • address register

  • program counter

If you prefer to read, see section 5.2.1- 5.2.6 of nan2tetris book

  • This program the first instruction puts 2 in the address register from the instructions in ROM.

  • Then it moves the 2 through the ALU to the data register (D)

  • then it puts 3 on the address register

  • then it adds the numbers at D and A

  • then it puts 0 on the address register

  • then it write the output from the ALU (D) to memory (at the location indicated by the A register)

Try if yourself

  • What line do you change to change where it outputs the data?

  • How could you add a third number?

  • How could you add two pairs, saving the intermediate numbers?

  • How could you do (4+4)*(3+2)?

6.5. Hardware Overview#

Important

Today is the first day outside of the grade free zone.

6.6. Review today’s class#

(required for a C or better)

  1. Review and update your listing of how data moves through a program in your abstraction.md. Answer reflection questions.

  2. practice with the hardware simulator, try to understand its assembly language enough to modify it and walk through what other steps happen.

  3. Update your KWL chart with the new items and any learned items

1. Did you initially get stuck anywhere?
1. How does what we saw with the hardware simulators differ from how you had thought about it before?
1. Are there cases where what you previously thought was functional for what you were doing but not totally correct? Describe them.

6.7. Prepare for Next Class#

(required for a C or better)

  1. Bring questions about git to class on Wednesday.

  2. Your grading contract proposal is due Thursday at 3pm.

  3. Make sure that the gh CLI tool works by using it to create an issue called test on your kwl repo with gh issue create

Warning

the template contracts in the repo have an error in them; use the ones on the course website.

6.8. More Practice#

(mostly required for a B or better)

  1. add a hardware term to your group repo. Remember to check other issues and then post an issue and self-assign it before you start working so that two people do not make the same one. Review one other PR.

  2. Expand on your update to abstraction.md: Can you reconcile different ways you have seen memory before?

  1. Try understanding the max.hack and rect.hack. Make notes and answer the questions below in assemblyexplore.md.

1. Explain how max.hack works in detail.
1. Write code in a high level language that would compile into this program. Try writing multiple different versions.
1. What does this max.hack assume has happened that it doesn't include in its body.
1. What does rect.hack do?  
1. What did you learn trying to figure out how it works?

6.9. Questions After Class#

6.9.1. Content#

6.9.1.1. More about the hardware architecture abstractions#

We will come back to this

6.9.1.2. how the CPU performs addition and stores the result in a memory location on the RAM#

We will study the components of a CPU including the ALU and the adder circuit in greater detail later. Today was a preview to introduce these terms so that we can use them as we go forward with learning more tools that will help us study the implications of hardware design choices better.

6.9.1.3. Explain more levels of abstraction and how they are connected#

I expanded some above and we will come back to these throughout the whole course.

6.9.2. Are there other simulators that we can play with?#

These are both CPU simulators with built in functions. For the first simulator, prewritten functions can be accessed by changing the drop down selection next to “Load Program” under the prewritten code. The functions for the second one can be chosen by changing the drop down menu labeled “SELECT”.

6.9.3. Logistics#

6.9.3.1. When requesting a review for a PR or something similar, would the only thing to do be tagging (@mention) the instructional team?#

Yes, tag @inrocompsys/instructors

6.9.3.2. With our collaborative repo, would we facilitate the merges and reviews or would you need to have the last review of the information?#

You all can merge on your own, but if you have questions, tag us.

6.9.3.3. Should we assume that when you ask to write a document, we should create a markdown file with a similar name (as opposed to an assignment with the description “add branches.md to your KWL repo”)#

Typically with a similar name is correct and never with any spaces in the file name. Mostly the instructions will say exactly what to add. If you have questions, you can (and should) always open an issue to ask for help.

6.9.3.4. for my grading contract if i choose to go for an A and stick with the A but don’t meet the requirements how much is my grade affected#

I will ask you to change your contract or take an incomplete. If you do not respond, I will put the lowest grade you completed.