Category:I600 Introduction to Computers and Informatics: Difference between revisions

From ICO wiki
Jump to navigationJump to search
Akerge (talk | contribs)
m Add git resources.
Lvosandi (talk | contribs)
Line 230: Line 230:


Topics: Computer history, Silicon Valley, standards
Topics: Computer history, Silicon Valley, standards
[https://echo360.e-ope.ee/ess/echo/presentation/584b21e6-4ead-4cb6-bc41-5c653bc5c3a2 Lecture recording]


[https://docs.google.com/presentation/d/1Ybld2ABpm9QJSLL-Bodr1a5XI5Hk_KM2q_nZVYu2L0c/edit?usp=sharing Lecture slides]
[https://docs.google.com/presentation/d/1Ybld2ABpm9QJSLL-Bodr1a5XI5Hk_KM2q_nZVYu2L0c/edit?usp=sharing Lecture slides]

Revision as of 15:30, 7 December 2015

In this course we'll give an introduction to variety of topics from hardware to software. The course will follow roughly the same structure as Computer Science 101 at Stanford University with more hands-on approach. This course substitutes Estonian courses I100 Sissejuhatus informaatikasse and I201 Arvutid.

Monday lectures will cover more theoretical stuff; Thursday workshops are for getting started with new topics; the homework assignments connect theoretical with practice and Tuesday sessions are for follow up, asking/answering questions and presenting homework. Attendance won't be tracked, the sessions are there if you need help. Bring your laptops for Tuesday and Thursday sessions.


Course credits: 6 ECTS

Lecturer: Lauri Võsandi

E-mail: lauri [donut] vosandi [plus] i600 [ät] gmail [dotchka] com


Grading

Grade mapping:

  • 0-50 points, fail
  • 51-60 points, pass 1
  • 61-70 points, satisfactory 2
  • 71-80 points, average 3
  • 81-90 points, good 4
  • 91-100 points, very good 5

Grading is split between theory and practice

  • Exam of 50 points, preparation in lectures and general discussion in workshops.
  • Assignments, see instructions and points below.
  • Extra points for improving quality of wiki articles, extracurricular work and also helping others, see points below.

Exam will be halfway between oral and written: You'll be given 30 minutes to prepare for several random questions and 15 minutes to discuss what you've answered. If you don't have prior experience with the topics, it's highly recommended to take part of the sessions in order to pass the exam.

Lecture: Computer hardware

Jargon: CPU, RAM, ROM, HDD, SSD, PCI, PCI Express, USB 2.0, USB 3.0, VGA, HDMI, DVI, LCD, TFT, LED, OLED, AMOLED, CRT, PWM

Lecture recording #1

Lecture recording #2 starting 12:30

Lecture slides Random access memory, permanent storage, buses, input devices, display technologies, networking

Potential exam questions:

Security section: Hacking SD cards

Assignments:

Lecture: Storage abstractions

In this lecture we'll talk about permanent storage abstractions: block device, disk, partition, file system, directory/folder, file, journaling, FAT32, NTFS, ext4, HFS+

Lecture slides

Lecture recording starts at 47:50.

Lecture: Bootloaders, kernels

In this lecture we'll discuss how a computer boots and how an operating system kernel is loaded.


Lecture recording #1, first half we'll discuss about first assignment about investigating PC hardware, slides start at 43:40.

Lecture recording #2, first 15 minutes we'll discuss about second assignment about investigating embedded hardware, last slides about kernels are discussed from 16:00 up to 27:30. I forgot to switch video input for lecture recording so you'll have to browse slides from the link below :/

Lecture slides: bootloaders, kernels.

Jargon: BIOS (basic input/output system), UEFI (Unified Extensible Firmware Interface), bootloader, kernel, process, context switch, x86 real/protected mode, paged virtual memory, swap/pagefile, kernelspace/supervisor mode, userspace, hypervisor mode (ring -1), system management mode aka (ring -2).

Potential exam questions:

  • What is the role of BIOS/UEFI in x86-based machines?
  • Explain step by step how operating system is booted up, see slides for flowchart.
  • Describe the functionality provided by general purpose operating system. See architecture of Windows NT, Android, OS X.
  • What are the main differences between real mode and protected mode of x86-based processor?
  • What happens during context switch?
  • What is the purpose of paged virtual memory?


Security section: DMA attack, editing GRUB entries to gain root shell without password prompt, 20 years old security exploit in x86 processors.

Lecture: Libraries, frameworks

Lecture recording #1, from 00:27:30 up to 1:04:00.

Lecture slides

Jargon: framework, library, ABI, API

Security section: HTTP.sys bug crashes IIS web servers, OpenSSL bug Heartbleed.

Lecture: Programming languages

In this lecture we'll talk about programming languages

Lecture recording: starting from 1:04:00

Lecture slides: programming languages, stack machine

Jargon: stack machine, lexer/lexeme, token, abstract syntax tree

Potential exam questions:

Assignments:

Lecture: Data encoding

Lecture recording

Lecture slides

In this lecture we'll talk about bits, bytes, integers, strings, pixels, audio encodings, video encoding etc.

Potential exam questions:

  • What is bit? Nibble? Byte? Word?
  • What is quantization in terms of signal processing?
  • How are integers stored in binary? What integer range can be described using n bits? How many bits are required to describe integer range from n .. m.
  • How are single precision and double precision floating point numbers stored in binary according to IEEE754 standard? Floating-point multiplication
  • What is the difference between CMYK and RGB color models? How are YUV, HSV and HSL colorspaces related to RGB? What are sRGB and YCbCr and where are they used?
  • How is data encoded on audio CD-s? What is the capacity of an audio CD?
  • What is sampling rate? What is bit depth? What is resolution?
  • What is bitrate?
  • What is lossy/lossless compression?
  • What is JPEG suitable for? Is JPEG lossy or lossless compression method?
  • What is PNG suitable for? Does PNG support compression?
  • How are time domain and frequency domain related in terms of signal processing? What is Fourier transform and where it is applied?

Jargon: 44.1kHz sampling rate, 16-bit audio, RGB565 pixel format, RGB888 pixel format

Relevant assignments:

Lecture: Code execution in processor

Lecture slides

Lecture recording #1

Lecture recording #2 up to 8:35, system calls

It's highly reccommended to play around with simulators here is one for MIPS processors.

In this lecture we'll talk about different processor architectures, instructions, pipelining, function calls, jumps, loops etc.

Assignments:

Lecture: Microcontrollers

Lecture slides

Lecture recording starts at 8:35

Jargon: microprocessor, microcontroller, coprocessor, floating-point unit (FPU), digital signal processor (DSP), field programmable grid array (FPGA), sensors, actuators, digital input/output, analog input, general purpose input/output (GPIO), interrupt, interrupt handler, timer/counter, pulse-width modulation (PWM), Hardvard architecture vs von Neumann architecture

Lecture: Introduction to Boole algebra

Lecture slides


Assignments:

Lecture: Hardware description languages

Lecture slides

Lecture recording starts at 05:00

Lecture: Publishing work

Lecture recording

Lecture slides


Lecture: Algorithms and data structures

Lecture recording unfortunately without audio :(

Lecture slides

Lecture: History

Topics: Computer history, Silicon Valley, standards

Lecture recording

Lecture slides

Potential example questions:

Assignment: Investigating PC hardware

Goal: Get familiar with your laptop hardware. Get out of the comfort zone of your primary operating system and try out other operating systems. Learn about hardware virtualization.

Deadline: 16. September

Credits: 5 points plus extra point for being extra thorough about interpreting what you see.

Use what you learned in Getting started with Ubuntu workshop:

  • Read the instructions before you act.
  • Place your preferred ISO image to a memory stick using dd or Win32 Disk Imager and boot it on your personal laptop. You do not need to install Ubuntu on your harddisk, simply click Try Ubuntu once the operating system boots off the memory stick and carry out following tasks.
  • Open up terminal by pressing Ctrl-Alt-T.
  • Use lsb_release -a to check what operating system distribution you're running.
  • Use uname -sr to check what operating system kernel you're running.
  • Use cat /proc/cpuinfo and check processor information. What CPU model and how many cores your computer has?
  • Use arch to check what CPU architecture is being used by the operating system. Is it 32-bit or 64-bit?
  • Use cat /proc/meminfo to check memory usage. How much RAM your computer has?
  • Use lspci -t -v -nn to enumerate PCI and PCI Express devices, attempt to identify what is what.
  • Use lsusb and lsusb -t to enumerate USB devices, again attempt to identify what is what.
  • Use fdisk -l to enumerate disks and partitions. How big is your harddisk? How many and how big partitions it has?
  • Use lsblk to enumerate block devices.
  • Use xrandr to enumerate display outputs. What video output resolutions are available and which one is currently used?
  • Use cat /proc/asound/cards to check which audio devices are available.
  • Use dmidecode to see even more information about your computer.
  • Use ifconfig -a or ip addr list to list all network interfaces.
  • Use iwconfig or iw list to list all wireless network interfaces. Is your wireless network interface detected? If not take a guess why?
  • Use hcitool dev to list bluetooth host controller. Is your bluetooth device detected?
  • Use glxinfo to check what 3D rendering capabilities are available, is it hardware accelerated? (hint: is direct rendering enabled?)
  • What audio card is your machine using? What bus is it using?
  • What graphics controller is your machine using? What bus is it using?
  • What webcam is your machine using? What bus is it using?
  • What wired network chipset your computer has? What bus is it using?
  • What wireless network chipset your computer has? What bus is it using?
  • What Bluetooth device your computer has? What bus is it using?
  • Is there a cellular modem connected and how it's connected?
  • Boot the ISO image in VirtualBox and follow the same steps as above, what are the differences and why?
  • Answer to questions above and send it as plain text e-mail to Lauri, make sure you use the address supplied above with the course code, otherwise your mail is not searchable in my mailbox. Attach collected command outputs as plain text file, do not send .odt, .doc files, these are not readable on my smartphone. When answering to questions phrase the text in a way that is understandable out of context, so I don't have to open up wiki to understand what you're talking about.

Note that I can't expect you to install Ubuntu on your physical machine, but I can help if you want to do that. You should have Ubuntu ready to go in a virtual machine at least for subsequent sessions. We're using Ubuntu because it's widely used on servers and in the cloud, so any Ubuntu skills will definitely come handy in future. If you're already familiar with Linux, it's suggested to take a look at other interesting operating systems such as FreeBSD or OpenBSD. Take a look at Kali Linux if you're interested in penetration testing.

Assignment: Investigating embedded hardware

Background: Most of the smartphones nowadays are using SoC built around ARM processor. Raspberry Pi is an excellent piece of hardware to for checking out how an ARM-based machine looks like.

Goal: Get familiar with hardware ARM-based hardware.

Deadline: 23. September

Points: 4 points

Use what you learned in Getting started with Ubuntu and Getting started with Raspberry Pi workshops:

  • Read the instructions before you get busy.
  • Boot Raspbian on Raspberry Pi.
  • Use the commands described in previous assignment to examine the environment of Raspbian on Raspberry Pi. What are the major differences compares to your laptop and virtual machine?
  • What buses is Raspberry Pi making use of?
  • What filesystems is Raspbian making use of?
  • Answer to questions above and send it as e-mail to Lauri, make sure you use the address supplied above with the course code, otherwise your mail is not searchable in my mailbox. Attach collected command outputs as plain text file, do not send .odt, .doc files, these are not readable on a phone. When answering to questions phrase the text in a way that is understandable out of context, so it is not necessary to open up wiki to understand what you're talking about.

Assignment: Investigating LAMP

LAMP software bundle is consists of Linux-based OS, Apache web server, PHP programming language runtime and MySQL database. Most of the web applications on the Internet including Facebook are built on top of LAMP-styled software stack. Use a Raspberry Pi or Ubuntu virtual machine to set up WordPress, ownCloud or any well-known web application that makes use of a database such as MySQL. To make your life easier also set up SSH public key authentication.

Goal: Get familiar with LAMP stack. Get comfortable with (SSH) public key authentication.

Deadline: 30. September

Points: 4 points

Tasks:

  • If you're using Ubuntu virtual machine approach, see Accessing a virtual machine via SSH connection
  • Use SSH to connect to your server over the network. If you're using Windows on your laptop use PuTTY to gain access to command line and WinSCP to copy files, otherwise simply boot Ubuntu in a virtual machine and use ssh username@hostname to invoke commands and sftp://username@hostname in the file browser to access filesystem.
  • Set up any of the web applications referenced above. You may be interested in reading also this and this.
  • Demonstrate that the web application you installed works in next Tuesday session, screenshots/photos with explanation sent to e-mail above also suffice.
  • Optional: Set up SSH public key authentication to enos.itcollege.ee.
  • Optional: Set up public key authentication to your Raspberry Pi. Windows users might want to take a look at PuTTYgen instructions.

Note: You don't have to necessarily use Raspberry Pi - Web application installed in Ubuntu VM is also accepted, also if you're maintaining similar installation of a production server that is accepted as well. WAMP on Windows is also accepted.

Assignment: Set up basic IoT scenario

Internet of Things is one of the emerging technologies (read: hype). IoT is essentially about getting everything online, including lightbulbs, switches, window shades etc. In this assignment LED symbolizes a light and the task is to implement code which allows user to switch the LED on and off over the network.

File:Raspberry-pi-gpio-18-led bb.png

Goal: Get familiar how Python code can be started up. Build basic IoT appliance, a light that can be turned on and off via the Internet.

Deadline: 7. October

Points: 4 points

  • Complete the Python track at CodeAcademy if you haven't done that yet.
  • Follow the wiki page Blinking LED section under Getting started with Raspberry Pi.
  • Get an LED blinking on command-line.
  • Get LED blinking from Python code.
  • Get basic HTTP server running in Python.
  • Combine all of the above, build an HTTP server that can be used to turn LED on and off from via web browser.
  • Optional: Take a peek at next assignment and upload working version to GitHub.
  • Optional: Smoothen the transitions using PWM.

Assignment: Collaborating using Git

Software development is usually done by several contributors, to facilitate efficient collaboration a distributed version control system is a must. In this assignment you'll upload your code to GitHub and modify fellow student's code to reflect changes in the Raspberry Pi setup:

Deadline: 14. October

Points: 5

Goal: Get familiar with distributed version control systems. Collaborate.

  • Create GitHub account if you haven't done so yet.
  • Create a Git repository, eg http://github.com/your-username/rpi-iot-example
  • Install Git on your Raspberry Pi by using apt-get install git.
  • Clone the repository to your Raspberry Pi using git clone http://github.com/your-username/rpi-iot-example.
  • Move the Python code created earlier to the Git repository directory.
  • Use git add to add the files.
  • Configure full name: git config --global user.name "Firstname Surname"
  • Configure e-mail: git config --global user.email first.last@domain.tld
  • Use git commit to create the initial commit.
  • Use git push to push the commits to GitHub server.
  • Set up public key authentication between your laptop and GitHub servers, verify that https://github.com/username.keys gives the expected result.
  • Use git clone to clone the repository to your laptop. Ubuntu should first apt-get install git, Windows and Mac users might want to take a look at Git homepage. If you're looking for graphical user interface take a look at GitHub Desktop or TortoiseGit.
  • Create README in the repository directory, populate it with relevant content - what is it about, who made it etc and commit the changes.
  • In your Raspberry Pi setup replace the single-color LED with RGB LED as shown above.
  • Clone fellow student's repository and adapt the code to reflect physical changes to the setup, the Python snippet should now permit changing the color of the light, have it blinking and turn it off. Other interesting modes are awarded with extra points.
  • Use either Atlassian Tutorials, git - the simple guide or Try Git as a reference if you get lost.
  • Document in the README what GPIO pins are used in the code for red, green and blue. Extra points for making the Python code configurable from command-line.
  • Late submissions will heavily lose points for failure to comply with decent commit messages.
  • Send Lauri the URL of your repository at GitHub.

Git resources: Pro Git Book (read the basics to get kickstarted) and Codecademy Git course.

Assignment: Disassembling Python

CPython is the default, most widely used implementation of the Python programming language. CPython is written in C. CPython compiles Python source into bytecode which is interpreted by a Python virtual (stack) machine. This is very similar to what is done with Java. Use dis to disassemble a Python function into stack machine instructions. Follow bytecode instructions to determine what each instruction does.

Deadline: 21. October


Example submission

Consider following Python function, which calculates the sum of squares. For example sum_of_powers(2, 3) == 14 (1**2 + 2**2 + 3**2):

def sum_of_powers(exponent, numbers):
    counter = 1
    return_value = 0
    while True:
        if counter > numbers:
            break
        return_value += counter ** exponent
        counter += 1
    return return_value

# Following two lines are the ones which produce the instructions shown below
from dis import dis
dis(sum_of_powers)

Corresponding Python stack machine instructions extracted with dis are following. Columns correspond to: line number in the source code, instruction offset (in bytes), instruction name as listed in dis documentation,

22           0 LOAD_CONST               1 (1)               # Constant of 1 is pushed to stack
             3 STORE_FAST               2 (counter)         # Pushed value is popped and stored in variable counter

23           6 LOAD_CONST               2 (0)               # Constant of 0 is pushed to stack
             9 STORE_FAST               3 (return_value)    # Pushed value is popped and stored in variable return_value

24          12 SETUP_LOOP              43 (to 58)           # Loop until instruction no 58 is set up

25     >>   15 LOAD_FAST                2 (counter)             # Value of variable <counter> is pushed to stack
            18 LOAD_FAST                1 (numbers)             # Value of variable <numbers> is pushed to stack
            21 COMPARE_OP               4 (>)                   # Two topmost values of stack are popped and compared,
                                                                # boolean result is pushed back to the top of stack
            24 POP_JUMP_IF_FALSE       31                       # If top of the stack if False,
                                                                # jump to instruction no 31 is performed.
                                                                # Top of the stack is popped

26          27 BREAK_LOOP                                       # Execution jumps out of the loop, the one
                                                                # that was set up at inst no 12
            28 JUMP_FORWARD             0 (to 31)               # Placeholder probably due to the way pipeline is handled

27     >>   31 LOAD_FAST                3 (return_value)        # Value of variable <return_value> is pushed to stack
            34 LOAD_FAST                2 (counter)             # Value of variable <counter> is pushed to stack
            37 LOAD_FAST                0 (exponent)            # Value of variable <exponent> is pushed to stack
            40 BINARY_POWER                                     # Exponentiation of two topmost values is performed and
                                                                # substituted with the result
            41 INPLACE_ADD                                      # Two topmost values are added and substituted with the sum
            42 STORE_FAST               3 (return_value)        # Sum of the addition is stored in variable <return_value>

28          45 LOAD_FAST                2 (counter)             # Value of variable <counter> is pushed to stack
            48 LOAD_CONST               1 (1)                   # Constant of 1 is pushed to stack
            51 INPLACE_ADD                                      # Two topmost values are added and substituted with the sum
            52 STORE_FAST               2 (counter)             # Sum is stored in the variable <counter>
            55 JUMP_ABSOLUTE           15                       # Code execution jumps to instruction no 15 (the beginning of the loop)

29     >>   58 LOAD_FAST                3 (return_value)    # The value of variable <return_value> is pushed to stack
            61 RETURN_VALUE                                 # Return top of the stack to the function caller


In the Python VM the state consists of:

  • Program counter (PC), the number of currently executed instruction
  • The stack and most importantly top of stack (TOS)
  • Constants extracted from source (co_consts)
  • Variables names (co_names)
  • Variables values (co_varnames)
  • There are *no* registers!


Executing the function with arguments exponent=2 and numbers=3 will result in return value of 14, the arguments are already placed in the co_varnames array by the calling function. Also the constants used in the code are present, so you may assume following state in the Python interpreter just before entering the function body:

   -1. stack = []; co_varnames = [2, 3]; co_consts[?, 1, 0]

The steps that Python VM takes to get to the results are following:

    0. LOAD_CONST 1: stack = [1]
    3. STORE_FAST 2: stack = []; co_varnames = [2, 3, 1]
    6. LOAD_CONST 2: stack = [0];
    9. STORE_FAST 3: stack = []; co_varnames = [2, 3, 1, 0]
   12. SETUP_LOOP 43: stack = []; loop is set up, counter is 1

   Here we enter loop body for the first time
   
   15. LOAD_FAST 2: stack = [1]
   18. LOAD_FAST 1: stack = [1, 3]
   21. COMPARE_OP 4: stack = [False]
   24. POP_JUMP_IF_FALSE 31: stack = []; jump to instruction 31
   31. LOAD_FAST 3: stack = [0];
   34. LOAD_FAST 2: stack = [0, 1];
   37. LOAD_FAST 0: stack = [0, 1, 2];
   40. BINARY_POWER: stack = [0, 1]
   41. INPLACE_ADD: stack = [1]
   42. STORE_FAST 3: stack = []; co_varnames = [2, 3, 1, 1]
   45. LOAD_FAST 3: stack = [1];
   48. LOAD_CONST 1: stack = [1, 1];
   51. INPLACE_ADD: stack = [2]
   52. STORE_FAST 2: stack = []; co_varnames = [2, 3, 2, 1]
   53. JUMP_ABSOLUTE 15: jump to instruction no 15, counter is 2

   Here we enter loop body for the second time
   
   15. LOAD_FAST 2: stack = [2]
   18. LOAD_FAST 1: stack = [2, 3]
   21. COMPARE_OP: stack = [False]
   24. POP_JUMP_IF_FALSE 31: stack = []; jump to instruction 31
   31. LOAD_FAST 3: stack = [1]; here we have only 1**1
   34. LOAD_FAST 2: stack = [1, 2];
   37. LOAD_FAST 0: stack = [1, 2, 2];
   40. BINARY_POWER: stack = [1, 4]
   41. INPLACE_ADD: stack = [5]; here we already have 1**2 + 2**2
   42. STORE_FAST 3: stack = []; co_varnames = [2, 3, 2, 5]
   45. LOAD_FAST 3: stack = [2];
   48. LOAD_CONST 1: stack = [2, 1];
   51. INPLACE_ADD: stack = [3]
   52. STORE_FAST 2: stack = []; co_varnames = [2, 3, 3, 5]
   53. JUMP_ABSOLUTE 15: jump to instruction no 15, counter is 3

   Here we enter the loop body third time
   
   15. LOAD_FAST 2: stack = [3]
   18. LOAD_FAST 1: stack = [3, 3]
   21. COMPARE_OP: stack = [False]
   24. POP_JUMP_IF_FALSE 31: stack = []; jump to instruction 31
   31. LOAD_FAST 3: stack = [5]
   34. LOAD_FAST 2: stack = [5, 3];
   37. LOAD_FAST 0: stack = [5, 3, 2];
   40. BINARY_POWER: stack = [5, 9]
   41. INPLACE_ADD: stack = [14]; here we have 1**2 + 2**2 + 3**2
   42. STORE_FAST: stack = []; co_varnames = [2, 3, 3, 14]
   45. LOAD_FAST 3: stack = [3];
   48. LOAD_CONST 1: stack = [3, 1];
   51. INPLACE_ADD: stack = [4]
   52. STORE_FAST 2: stack = []; co_varnames = [2, 3, 4, 14]
   53. JUMP_ABSOLUTE 15: jump to instruction no 15, counter is 4

   Here we enter the loop body fourth (!!!) time
   
   15. LOAD_FAST 2; stack = [4]
   18. LOAD_FAST 1; stack = [4, 3]
   21. COMPARE_OP 4; stack = [True]
   24. POP_JUMP_IF_FALSE 31; stack = []; but the condition does not hold anymore so we jump out of the loop
   27. BREAK_LOOP; break out of the loop
   58. LOAD_FAST 3; stack = [14]
   61. RETURN_VALUE; return 14 to caller

Assignment steps

  1. Select one of the Fibonacci code examples below.
  2. Use from dis import dis and dis(function_name_goes_here) to disassemble the function to opcodes.
  3. Comment the stack machine instructions as shown above (3p).
  4. Invoke the Fibonacci number calculation function with n=2, follow the instructions and elaborate after each instruction executed a) the stack contents b) co_varnames contents c) co_names contents d) what happened as shown above. Note that certain code blocks will be executed repeatedly, which means you'll have more than 30 instructions executed (2p).


Fibonacci with iterators:

def fib(n):
    a,b = 1,1
    for i in range(n-1):
        a,b = b,a+b
    return a

Fibonacci with recursion:

def fib(n):
    if n==1 or n==2:
        return 1
    return fib(n-1) + fib(n-2)

Fibonacci with infinite loop and breaks:

def fib3(n):
    a,b,i = 1,1,0
    while True:
        i += 1
        if i >= n: break
        b,a = a+b,b
    return a

Another variation:

def fib4(n):
    a = 1
    b = 1
    i = 0
    while True:
        i += 1
        if i >= n: break
        s = a + b
        a = b
        b = s
    return a

Assignment: Investigating compilers

Use what you learned in the Getting started with GCC session. See assignment steps below. Everything you need to understand ARM instructions should be here. Another good resource seems to be Introduction to ARM by David Thomas. See page 14 of Procedure Call Standard for the ARM® Architecture if you want to learn more about how function calls are implemented on ARM. See here for more information about branching instructions: B, BL, BX. <Insert extemely useful link here yourself>

Deadline: 4. November

Example

If you don't have Ubuntu installed on your machine skip next step and use SSH to perform these steps remotely at enos.itcollege.ee. Otherwise install ARM cross-compiler:

apt-get install gcc-arm-linux-gnueabi

Consider C snippet for calculating integer exponentiation, place it in a file power.c:

int power(long base, long exponent) {
    int counter;
    int result = 1;
    for (counter = 0; counter < exponent; counter++)
        result *= base;
    return result;
}

Generating assembly

Compile ARM assembly of the code snippet:

arm-linux-gnueabi-gcc -Os -S power.c -o power.s   # Cross-compile ARM assembly file power.s from C source code file power.c
cat power.s                                       # Dump the assembly file on terminal

The compiler should produce something similar to following:

	.arch armv5t
	.fpu softvfp
	.eabi_attribute 20, 1
	.eabi_attribute 21, 1
	.eabi_attribute 23, 3
	.eabi_attribute 24, 1
	.eabi_attribute 25, 1
	.eabi_attribute 26, 2
	.eabi_attribute 30, 2
	.eabi_attribute 34, 0
	.eabi_attribute 18, 4
	.file	"power.c"
	.text
	.align	2
	.global	power
	.type	power, %function
power:
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 0, uses_anonymous_args = 0
	@ link register save eliminated.
	cmp	r1, #0
	mov	r2, #1
	ble	.L2
	mov	r3, #0
.L3:
	add	r3, r3, #1
	cmp	r3, r1
	mul	r2, r0, r2
	bne	.L3
.L2:
	mov	r0, r2
	bx	lr
	.size	power, .-power
	.ident	"GCC: (Ubuntu/Linaro 4.7.3-12ubuntu1) 4.7.3"
	.section	.note.GNU-stack,"",%progbits

Commenting the assembly

You can safely ignore the lines starting with dot, these are simply hints for the next stage of the compilation process. Thus you're left only (!!!) 10 actual instructions. Here you can also see what kind of comments are expected from the submission:

power:
	cmp	r1, #0             /* Compare register r1 (second argument) contents against constant 0 */    
	mov	r2, #1             /* Copy the constant 1 to register r2 */
	ble	.L2                /* Jump to label .L2 if the comparison was false */
	mov	r3, #0             /* Copy the constant 0 to register r3 */
.L3:
	add	r3, r3, #1         /* Perform r3 = r3 + 1 */
	cmp	r3, r1             /* Compare register r3 and r1 (second argument) */
	mul	r2, r0, r2         /* Perform r2 = r0 (first argument) * r2 */
	bne	.L3                /* If r3 and r1 were different jump to label .L3
.L2:
	mov	r0, r2             /* Copy register r2 contents to register r0 */
	bx	lr                 /* Jump back to caller */


Analyzing the code

Code analysis reveals that registers are mapped as following:

  • r0 - argument base and eventually return value
  • r1 - argument exponent
  • r2 - variable result
  • r3 - variable counter


We can also see how the for loop gets translated into assembly:

power:
	cmp	r1, #0
	mov	r2, #1
	ble	.L2
	mov	r3, #0
.L3:
	add	r3, r3, #1 <---+
	cmp	r3, r1         | 4 instructions are executed repeatedly
	mul	r2, r0, r2     | if exponent is greater than 0
	bne	.L3 -----------+
.L2:
	mov	r0, r2
	bx	lr

Stepping through the instructions

When we execute the function with for example arguments base=5 and exponent=3 following happens in the processor. Note that this will essentially calculates 5 ^ 3 (5 to the power of 3) which is 125. Following has been done manually to illustrate how much time does it take to execute the the function.


/* When processor enters the function body the arguments are already placed in registers r0=5 (base), r1=3 (exponent) */
cmp r1, #0                        /* Compare exponent to 0 */
mov r2, #1                        /* Place constant 1 in register r2,
                                     this corresponds to result = 1 in C code */
ble .L2                           /* Exponent was not less than 0, so no jump to L2
mov r3, #0                        /* Place constant 0 in register r3,
                                     this corresponds to variable counter */

add r3, r3, #1                    /* Perform r3 = 0 + 1 which results in 1 being stored to r3
                                     this corresponds to first invocation of counter++ in C code */
cmp r3, r1                        /* Compare counter (1 in this case) to exponent (3), this will be used by bne instruction below */
mul r2, r0, r2                    /* Perform r2 = r0 * r2 which results in 1 * 5 = 5 being placed in r2
                                     this corresponds to first invocation of result *= base in C code */
bne .L3                           /* The comparison resulted in counter being not equal to exponent, so we jump back to L3
                                     this corresponds to first invocation of counter < exponent in C code */

add r3, r3, #1                    /* Perform r3 = 1 + 1 which results in 2 being stored to r3
                                     this corresponds to second invocation of counter++ in C code */
cmp r3, r1                        /* Compare counter (2 in this case) to exponent (3), this will be used by bne instruction below */
mul r2, r0, r2                    /* Perform r2 = r0 * r2 which results 5 * 5 = 25 being placed in r2
                                     this corresponds to second invocation of result *= base in C code */
bne .L3                           /* The comparison resulted in counter being not equal to exponent, so we jump back to L3
                                     this corresponds to second invocation of counter < exponent in C code */

add r3, r3, #1                    /* Perform r3 = 2 + 1 which results in 3 being stored to r3
                                     this corresponds to third invocation of counter++ in C code */
cmp r3, r1                        /* Compare counter (3 in this case) to exponent (3), this will be used by bne instruction below */
mul r2, r0, r2                    /* Perform r2 = r0 * r2 which results 25 * 5 = 125 being placed in r2
                                     this corresponds to third invocation of result *= base in C code */
bne .L3                           /* The comparison resulted in counter being equal to exponent, so we DO NOT jump back to L3 */

mov	r0, r2                     /* Copy register r2 contents (125) to register r0 */
bx	lr                         /* Jump back to caller */
/* Function returns with 125 placed in r0 this is where caller function should expect the return value */
/* The other registers will still hold whatever values were left there: r1 = 3, r2 = 125, r3 = 3 */

ARM registers

If you get lost with the ARM register naming conventions use following as a guide.

ARM7 has 16x 32-bit registers:

 r0 (a1) - Argument/result/scratch register, this is where first function argument is usually placed
 r1 (a2) - Argument/result/scratch register, this is where second function argument is placed
 r2 (a3) - Argument/scratch register 3
 r3 (a4) - Argument/scratch register 4
 r4 (v1) - Variable register 1
 r5 (v2) - Variable register 2
 r6 (v3) - Variable register 3
 r7 (v4) - Variable register 4
 r8 (v5) - Variable register 5
 r9 (v6) - Variable register 6
r10 (v7) - Variable register 7
r11 (fp) - Frame pointer, variable register 8 
r12 (ip) - Intra-procedure call scratch register
r13 (sp) - Stack pointer
r14 (lr) - Link register (to which memory address currently
                          executing function should return to?)
r15 (pc) - Program counter (what is the memory address of instruction
     ^                      that we are going to execute next?)
     |
     +- These are simply aliases for the numbered registers and
        can be used interchangeably.

Assignment steps

  1. Select one of the Fibonacci calculation examples below and use ARM cross compiler as shown above to generate the assembly corresponding to the C source code (1p).
  2. Remove the compiler hints (lines starting with dot), this should leave you less than 20 instructions. If it's more than that try different optimization flags. Analyze and comment the assembly as shown above (1p).
  3. Use n=3 as argument and follow the instructions, what values are left in the registers after the function finishes (2p)?
  4. Optional/extra: Elaborate step by step what happens in the processor: what instruction is being executed and what values are left in registers after instruction finishes? (1p)
  5. Optional/extra: Recompile with different optimization levels: -Os, -O0, -O1, -O2 and -O3. What differences did you notice? (1p)
  6. Optional/extra: Take a guess which one of the Fibonacci calculation functions below is the slowest? Which one is the fastest? Why? (1p)
  7. Send your conclusions as e-mail attachment to Lauri, attach the commented assembly, make sure you use the address supplied above with the course code, otherwise your mail is not searchable in my mailbox.


Fibonacci calculation using for-loop:

int fib(n) {
    int a = 1;
    int b = 1;
    int i;
    for (i = 0; i < n; i++) {
        int s = a + b;
        a = b;
        b = s;
    }
    return a;
}

Fibonacci calculation using recursion:

int fib2(n) {
    if (n == 1 || n== 2) {
        return 1;
    } else {
        return fib(n-1) + fib(n-2);
    }
}

Fibonacci calculation using while-loop:

int fib4(n) {
    int a = 1;
    int b = 1;
    int i = 0;
    while(1) {
        i += 1;
        if (i >= n) { break; }
        int s = a + b;
        a = b;
        b = s;
    }
    return a;
}

Assignment: Investigating microcontrollers

In this assignment we use Arduino to implement traffic lights for crossroads. If you don't care much about doing this assignment hands on, you can give a try online.

Assignment steps

  • Install Arduino IDE on your personal machine, on Windows/Mac check out Arduino homepage for instructions, on Ubuntu apt-get install arduino should suffice. You can also use school computers, Ubuntu has Arduino preinstalled.
  • From Arduino IDE menu open up File -> Examples -> 01. Basic -> Blink
  • In Arduino IDE menu Tools -> Board -> Arduino Mega2560
  • In Arduino IDE menu Tools -> Serial port -> Select what makes sense
  • On Ubuntu you may have to add yourself to the dialout group before you can access the serial ports. Use the command sudo gpasswd -a $USER dialout, log out and log in again to your PC.
  • Press the second button in the toolbar to upload the code, make sure the changes take effect on the board. You should see on-board LED blinking.
  • Connect some LED-s to the board. MAKE SURE YOU USE RESISTORS TO PROTECT LED-s AND THE BOARD
  • Implement traffic light cycle using digitalWrite and delay in the loop function (3p)
  • Use interrupts to read button presses, see example below. Pressing the button should toggle the LED now (1p)
  • Extra: Use PWM to implement smoother blinking (1p)
  • Extra: Use LCD1602 shield to display countdown (1p)
  • Use serial interface to send messages to your PC.
  • You can find useful code snippets for Robotics club equipment here

Code example: reading button press with interrupts

Set up a push button as shown below:

Insert following code to Arduino IDE and upload it to Arduino, verify that it works:

int led = 13;
int button  = 2;
int flag = LOW;

void setup() {
    pinMode(led, OUTPUT);         // Set up pin 13 as digital output
    pinMode(button, INPUT);       // Set up pin 9 as digital input
    digitalWrite(button, HIGH);   // Turn in pull-up resistor

    // Associate interrupt handler with an event
    attachInterrupt(digitalPinToInterrupt(button), onButtonPressed, FALLING);
}

void onButtonPressed() {
    // Keep this as short as possible
    flag = HIGH;
}

void loop() {
    // Do something useful or let processor sleep here
    if (flag) {
        digitalWrite(led, HIGH);
        delay(2000);
        flag = LOW;
    }

    digitalWrite(led, LOW);
    delay(50);
}

Code example: Cycling through different traffic light states

Add LED-s to the design:

Use following as hint to implement cycling through traffic light states:

// Define pin numbers
int car_green = 5;
int car_yellow = 6;
int car_red = 7;

// For LED-s we're sinking the 5V voltage, hence LED is turned on when voltage on the pin is LOW
int on = LOW;
int off = HIGH;

void setup() {
    pinMode(car_green, OUTPUT);
    pinMode(car_yellow, OUTPUT);
    pinMode(car_red, OUTPUT);
    digitalWrite(cars_yellow, off);
    Serial.begin(9600);
}

void loop() {
    Serial.println("Cars green, pedestrians red for 5 seconds");
    digitalWrite(cars_red, off);
    digitalWrite(cars_green, on);
    delay(5000);

    Serial.println("Green for cars is blinking 5 seconds");
    for(int j = 0; j < 10; j++) {
        digitalWrite(cars_green, j % 2 == 0);
        delay(500);
    }

    Serial.println("Cars red, pedestrians green for 5 seconds");
    digitalWrite(cars_green, off);
    digitalWrite(cars_red, on);
    delay(5000);
}


Skeleton of the final submission

The real traffic light has of course a little bit more states:

1. Cars green, pedestrians red for 10 seconds
2. Cars green **blinking**, pedestrians red for 2 seconds
3. Cars red, pedestrians green for 10 seconds
4. Cars red, pedestrians green **blinking** for 2 seconds
5. Cars yellow, pedestrians red for 2 seconds

So your final code will look something like this:

// Define pin numbers here

// Initially the flag is low
int pedestrian_requested_crossing = LOW;
 
void setup() {
    // Initialize necessary pins as digital outputs
    // Reset pins with digitalWrite

    // Initialize button pin as digital input
    // Enable pull-up resistor on button pin
    // Associate button interrupt handler function (onButtonPressed) below with the event on the button

}

void onButtonPressed() {
    // Here set pedestrian_requested_crossing flag to HIGH
    // Don't do anything else here!
}

void loop() {
    Serial.println("Cars green, pedestrians red for 5 seconds");
    digitalWrite(cars_red, off);
    digitalWrite(cars_green, on);
    // Set pedestrian lights here
    delay(5000);

    if (pedestrian_requested_crossing) {

        Serial.println("Green for cars is blinking 5 seconds");
        for(int j = 0; j < 10; j++) {
            digitalWrite(cars_green, j % 2 == 0);
            delay(500);
        }

        Serial.println("Cars red, pedestrians green for 5 seconds");
        digitalWrite(cars_green, off);
        digitalWrite(cars_red, on);
        // Set pedestrian lights here
        delay(5000);

        // Add another state here

        // And another state here

        // Reset flag here
    }
}

Assignment: Adders with NAND gates

In this assignment we use chips to build an adder. Get max points (4p) by wiring up half adder and double your points (8p) if you can make full adder work as well :)


Each SN74HC03N chip contains four NAND gates arranged like this, observe the pit on the left. VCC corresponds to 5V power supply and GND corresponds to ground or 0V.


Half adder

Each SN74HC03 contains 4 NAND gates. Use breadboard to wire up half adder with 7400 chips (4p):

File:Half-adder bb.png

The truth table for half adder:

  A  |  B  | Cout | Sum  | Human readable (how many bits are high?)
-----+-----+------+------+-------------------------------------------
  0  |  0  |  0   |  0   | 0
-----+-----+------+------+-------------------------------------------
  0  |  1  |  0   |  1   | 1
-----+-----+------+------+-------------------------------------------
  1  |  0  |  0   |  1   | 1
-----+-----+------+------+-------------------------------------------
  1  |  1  |  1   |  0   | 2

Full adder

You can double your points if you manage to wire up a full adder (+4p)

On a breadboard it looks a bit messy, but if you pay attention to gate numbering as shown above it should make your life significantly easier. The gates 1, 2, 3, 4 are placed in the leftmost chip; 5, 6, 7, 8 are placed in the middle one and gate 9 is the only one in the rightmost chip:



  A  |  B  | Cin | Cout | Sum  | Human readable (how many bits are high?)
-----+-----+-----+------+------+-------------------------------------------
  0  |  0  |  0  |  0   |  0   | 0
-----+-----+-----+------+------+-------------------------------------------
  0  |  0  |  1  |  0   |  1   | 1
-----+-----+-----+------+------+-------------------------------------------
  0  |  1  |  0  |  0   |  1   | 1
-----+-----+-----+------+------+-------------------------------------------
  0  |  1  |  1  |  1   |  0   | 2
-----+-----+-----+------+------+-------------------------------------------
  1  |  0  |  0  |  0   |  1   | 1
-----+-----+-----+------+------+-------------------------------------------
  1  |  0  |  1  |  1   |  0   | 2
-----+-----+-----+------+------+-------------------------------------------
  1  |  1  |  0  |  1   |  0   | 2
-----+-----+-----+------+------+-------------------------------------------
  1  |  1  |  1  |  1   |  1   | 3

Unittest

Use following code snippet on Arduino to test the circuit, it will shuffle through all the possible inputs and test whether the expected output is on the output pins. If you see sum or cout outputs giving 0 all the time it's likely you have resistors of too low resistance in the circuit which is draining all the voltage on the NAND gate output pins.

int PIN_A = 2;
int PIN_B = 3;
int PIN_CIN = 4;
int PIN_SUM = 5;
int PIN_COUT = 6;

void setup() {
    // Set up serial
    Serial.begin(9600);
    
    // Set up operands
    pinMode(PIN_A, OUTPUT);
    pinMode(PIN_B, OUTPUT);
    pinMode(PIN_CIN, OUTPUT);
    digitalWrite(PIN_A, HIGH);
    digitalWrite(PIN_B, HIGH);
    digitalWrite(PIN_CIN, HIGH);
    
    // Set up measurement pins
    pinMode(PIN_SUM, INPUT);
    pinMode(PIN_COUT, INPUT);
    digitalWrite(PIN_SUM, HIGH); // Enable pull-up resistor
    digitalWrite(PIN_COUT, HIGH); // Enable pull-up resistor
}

void test(int a, int b, int cin) {
    int cout = a && b || a && cin || b && cin;
    int sum = a ^ b ^ cin;
    
    digitalWrite(PIN_A, a);
    digitalWrite(PIN_B, b);
    digitalWrite(PIN_CIN, cin);
    
    Serial.print("Writing: a=");
    Serial.print(a);
    Serial.print(", b=");
    Serial.print(b);
    Serial.print(", cin=");
    Serial.print(cin);
    Serial.print("  Expecting: sum=");
    Serial.print(sum);
    Serial.print(", cout=");
    Serial.print(cout);
    
    int measured_sum = digitalRead(PIN_SUM);
    int measured_cout = digitalRead(PIN_COUT);

    Serial.print("  Got: sum=");
    Serial.print(measured_sum);
    Serial.print(" cout=");
    Serial.print(measured_cout);
    
    Serial.print("  Test:");
    if (measured_sum != sum || measured_cout != cout) {
        Serial.print("  FAIL");
    } else {
        Serial.print("  GOOD");
    }
    Serial.println();
    delay(500);
}

void loop() {
    Serial.println("Running test");
    test(0, 0, 0);
    test(0, 0, 1);
    test(0, 1, 0);
    test(0, 1, 1);
    test(1, 0, 0);
    test(1, 0, 1);
    test(1, 1, 0);
    test(1, 1, 1);
}

Assignment: Debugging ALU design

Bob had to ship the ALU design to the hardware manufacturer by yesterday. The project manager is angry about missed deadline. Bob still hasn't figured out why the ALU is not working properly. Help Bob by figuring out what's the problem.

If you're on Ubuntu install GHDL and GtkWave, otherwise simply use a school computer:

sudo add-apt-repository ppa:pgavin/ghdl
sudo apt-get update
sudo apt-get install ghdl gtkwave git

Clone the repository

git clone https://github.com/laurivosandi/vhdl-exercise

Use make to compile the components and run the testbench:

cd path/to/vhdl-exercise
make

Expected output of the testbench:

alu_testbench.vhd:77:9:@360ns:(report note): Finished testing addition operation of ALU
alu_testbench.vhd:106:9:@1us:(report note): Finished testing subtraction operation of ALU
alu_testbench.vhd:135:9:@1640ns:(report note): Finished testing NAND operation of ALU
alu_testbench.vhd:166:9:@2280ns:(report note): Finished testing NOR operation of ALU

However there are few bugs in alu.vhd, find the bugs and correct them.

Assignment: Publishing your work

Deadline: 25. November

  • Clean up your Git repositories and send the URL of a repository that you've actively worked on (for example the one from Java course) to Lauri, but before check the following:
    • The repository should show changes you've made over at least few days.
    • The repository has to contain only plaintext files unless there is a really good reason not to (eg. images).
    • There has to be authorship information in the files.
    • Add .gitignore file to your GitHub repositories to ignore temporary files, see Git docs for more details.
    • Add LICENSE file in the repository directory and commit the changes. LICENSE should answer to some important questions
      • Who is the copyright holder?
      • Under which conditions is redistribution permitted?
    • Add nicely formatted README file, see Markdown (online editor here) and reStructuredText for more details. README should answer to several silly questions:
      • What is the repository about?
      • Who made it?
      • How can the author be contacted? E-mail address, IRC chat channel on Freenode, Skype username?
      • How can the code be used? What hardware is necessary? How should the user wire the circuit to make it work? Add images if necessary.
      • What is the policy for including changes from third party developers?
  • There will be more details here

Extra points

Here you can claim extra credit points for various tasks, this is mostly to improve the quality of wiki.itcollege.ee. Once you have taken care of the task insert your name in the end of the line with corresponding date.

This category currently contains no pages or media.