forked from wandwramp/manual
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathintro.tex
832 lines (691 loc) · 32.5 KB
/
intro.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
\section{Introducing the Basys3 and WRAMP}
This manual is intended as an introduction to WRAMPSys, which essentially
comprises the Basys 3 boards with the FPGA programmed to perform as a WRAMP
processor. The manual includes information on programming for WRAMP and using
the physical capabilities of the Basys boards. It covers the basics of the WRAMP
assembly language, the WRAMP tools, and the I/O devices implemented on the
Basys3 boards. Only the Basys3 itself is required for most of the
functionality, but the second serial port requires a Micro-USB PMOD expansion.
WRAMPsys can be used without this attached, but the second serial port will not function.
WRAMP is designed to be a simple architecture which can help you gain a practical
understanding of the internal workings of a computer. The initial implementation
on REX boards was developed at the University of Waikato by Dean Armstrong, as
part of an undergraduate degree. The implementation for Basys3 FPGAs was developed
by Daniel Oosterwijk and Tyler Marriner at the University of Waikato.
\subsection{The WRAMP CPU}
The \BI{Central Processing Unit} (\BI{CPU}) is responsible for carrying out
instructions.
CPUs have developed at an astounding rate. From the humble Z80 to the 386, and
beyond the GHz barrier. But as the speed increases, so does
the complexity. Due to this complexity, it is difficult to learn to program
at a low level.
The WRAMP CPU was designed to solve this problem. It is much easier to
understand because it does not have the quirks of performance orientated CPUs.
Some features of the WRAMP CPU are:
\begin{itemize}
\item An easy to understand instruction set. All instructions conform
to a clear and consistent structure.
\item All operations are carried out on 32-bit words.
\item Only a single instruction is executed at a time.
\item Memory addressing is easy to understand.
\end{itemize}
\subsection{The Basys board}
For a CPU to be usable, a motherboard is needed. Originally, the REX board was
developed to host the WRAMP CPU. However, the Basys FPGA can be reprogrammed
to take the form of both the WRAMP CPU and its peripheral components.
It should be connected via the Micro-USB port on the top-left to a Linux machine
with the \texttt{remote} tool installed.
The Basys board includes the following components:
\begin{description}
\item[CPU] The WRAMP processor is the brain of the Basys board.
%
\item[RAM] Capable of storing 16K words, the RAM resides at addresses 0x00000
to 0x03FFF. The last 2K words are reserved for use by the monitor program. The rest
of the RAM is used to store and execute your programs, which, by default, are
loaded starting from address 0x00000.
%
\item[ROM] Capable of storing 32K words, the ROM resides at addresses
0x80000 to 0x87FFF. It is used to store the \WRAMPmon\ monitor program.
%
\item[Serial Interface] Allows the WRAMP processor to interface with two serial
ports. One is connected to a Linux machine via the Micro-USB port on the top-left
of the Basys board, which can also provide power. The other connects to the Micro-USB
port of a PMOD expansion, which should be connected to the bottom half of the
top-left PMOD port.
%
\item[Parallel Interface] Allows the WRAMP processor to interface with:
\begin{itemize}
\item a set of sixteen switches from which the CPU can read
\item three pushbuttons from which the CPU can read
\item four seven segment displays to which the CPU can write
\item a set of sixteen LEDs to which the CPU can write
\end{itemize}
\item[Timer] Counts down from a certain value and can interrupt the CPU when
finished.
%
\end{description}
Use of these I/O devices will be covered in chapter \ref{chapter:io}.
\subsection{WRAMPmon}
The Basys board has installed on it monitor software known as \WRAMPmon.
It communicates with the user through the Linux machine connected to
the first serial port. \WRAMPmon\ is used to upload your programs to the
board and to debug them. This will be covered in more detail in
section \ref{intro:wrampmon}.
%
%
% SECTION - Assembly
%
\section{The WRAMP Assembly Language}
%
To help you get started we will begin by analysing, assembling,
executing and debugging a simple WRAMP assembly language program.
Using \program{emacs} (or your preferred text editor) enter the
program listed in Figure \ref{simple_prog}. Save it as \filename{intro.s}.
A digital copy is also bundled with this manual, named \filename{intro.s}.
You can simply use this to avoid retyping the program.
%%%
%
% Example Code
%
%%%
\begin{figure}[btp]
\begin{center}
%\begin{footnotesize}
\begin{tabular}{|p{15cm}|}
\hline
\begin{verbatim}
.text
.global main
main:
# Get the address of the welcome message
la $2, welcome_msg
# Display the message
jal putstr
# Clear our sum register
add $4, $0, $0
# Initialise the loop counter
addi $5, $0, 1
loop:
# Read a number from the user
jal readnum
# Add it to our running total
add $4, $4, $1
# Increment our loop counter
addi $5, $5, 1
# Test to see if we have done all 4 numbers
slti $1, $5, 4
# Keep looping until 4 numbers have been entered
bnez $1, loop
# Get the output message
la $2, output_msg
# Print it
jal putstr
# Move our sum into register $2 to display it
add $2, $0, $4
# Print out the number
jal writenum
# Return to the monitor
j exit
.data
# This is our welcome message
welcome_msg:
.asciiz "Welcome to the world of WRAMP!!!\n\nPlease
type four numbers, pressing enter after each:\n"
# This is the output message
output_msg:
.asciiz "The sum of the numbers is : "
\end{verbatim}%$
\\
\hline
\end{tabular}
%\end{footnotesize}
\end{center}
\caption{WRAMP Assembly Language Program (\filename{intro.s})}
\label{simple_prog}
\end{figure}
%%%%
%%%
%%
%
This program first displays a message asking you to enter four numbers. It
is then meant to input four numbers, add them up and display the result.
If you have noticed the bug in it, don't worry as we will correct this later.
As you read through the source file look for the following:
\begin{description}
\item[comments] are lines beginning with a hash (\src{\#}). These work in
the same way as \src{//} comments in C and are ignored by the assembler.
%
\item[labels] such as \src{main:} are used to refer to a location in the
memory. This may be used to move execution to a different area of code or
to refer to data in the memory.
%
\item[directives] are commands beginning with a period (\src{.}). They
pass information to the assembler.
%
\item[subroutine calls] are used in this program to perform hardware
operations such as reading from the serial port. For example the
lines \src{jal putstr} and \src{jal readnum} are subroutine calls.
%
\item[WRAMP instructions] such as \src{add \reg{4}, \reg{0}, \reg{0}} get
converted to machine code by the assembler. They can then be executed by the
WRAMP CPU.
%
\end{description}
\subsection{Labels}
A label is a means of referencing a location in memory. Rather than
specifying absolute addresses when accessing data in memory, a label
can be used. This makes it much easier for the programmer to write
and understand the code. Labels can also be declared within the
code. They can then be used as a destination for branch and jump
instructions.
A label declaration consists of a name (containing no spaces) followed
by a colon (\src{:}). A label name can include alphanumeric characters,
underscores (\src{\_}), and periods (\src{.}).
The example code in figure \ref{simple_prog} has labels \src{main},
\src{loop}, \src{welcome\_msg}, \src{output\_msg}. The labels
\src{main} and \src{loop} refer to locations within the code. The
labels \src{welcome\_msg} and \src{output\_msg} refer to data.
In addition to any labels declared by the user, three special labels
can be used: \src{text\_size}, \src{data\_size}, and \src{bss\_size}.
These labels will resolve to the size of each section of the program:
for example, \src{text\_size} will be the number of instructions
in the \src{.text} section. These sections are discussed below.
\subsection{Directives}
Directives (commands preceded by a \src{.}) do not become part of the
final executable. They are used to pass information to the assembler,
like \src{\#} directives do in C.
\subsubsection{\text, \data and \bss}
A program written in WRAMP assembly can be split into three sections.
These are used to separate executable code, initialised data, and
uninitialised data. The directives \text, \data and \bss are used to
do this. When the assembler encounters one of these directives it
knows that all the code following it belongs in the given section.
The \text section contains WRAMP assembly instructions which will be
converted to machine language which can be executed on the WRAMP CPU.
%The \data section is used for initialised data.
Within the \data section, space in the memory can be reserved and
initialised. This is useful for strings, constants, and variables
which have an initial value.
The \bss section allows memory space to be reserved but not initialised.
The advantage of this is that space can be reserved in chunks using a single
command. This feature makes the \bss section useful for arrays.
\subsubsection{Assigning Space}
Within the \data and \bss sections, memory space is assigned using directives.
To be able to access this you need to place a label before the assigning
directive. In the example code, the label \src{welcome\_msg:} refers to the
memory reserved by the \asciiz directive.
\begin{verbatim}
welcome_msg:
.asciiz "Welcome to the world of WRAMP!!!\n\n"
\end{verbatim}
The following is a list of the available memory assigning directives
and how they can be used.
\begin{description}
\item[\word \src{n}] assigns one word of memory space and initialises it to
the number \src{n}.
If a character is provided instead of a number, like \src{\word `a'}, the space
will be initialised to the ASCII value of that character.
If the name of a label is provided, like \src{\word main}, the space will be
initialised to the address of that label.
\item[\asciiz \src{"str"}] reserves and initialises space
for a NULL terminated ASCII string (\src{"str"}).
This means that the string is followed immediately by a NULL
character (\src{0}). The NULL character can then be used
to identify the end of the string.
\item[\ascii \src{"str"}] reserves and initialises space for
the ASCII string \src{"str"} without NULL terminating.
\item[\Space \src{n}] is used to allocate a chunk of space
of size \src{n} in the \bss section.
\end{description}
The \ascii and \asciiz directives cannot be used in the \bss section
as they initialise the space they reserve. The \word directive may be
used as long as it is not provided with an argument.
\subsubsection{Escape Characters}
Any string or character literal can include some special characters which
are otherwise difficult to type. The following is a list of the valid
escape sequences and their uses.
\begin{description}
\item[\src{\textbackslash r}] is the `carriage return' character, which moves
the cursor back to the start of the current row.
\item[\src{\textbackslash n}] represents the `newline' character, which moves the
cursor down one row. If combined with a carriage return, like
\src{"\textbackslash r\textbackslash n"}, the cursor moves to the beginning of the next line.
\item[\src{\textbackslash t}] is a tab character. When this is printed directly to
the serial port, the cursor will move to the next point in the current
row whose index is a multiple of 8. This is similar to setting the
tab width to 8 in any common text editor.
\item[\src{\textbackslash a}] is the bell character. Printing this character
will cause your terminal's bell to ring, which may be audible or visual
depending on your settings.
\item [\src{\textbackslash\textbackslash}, \src{\textbackslash'},] and
\src{\textbackslash"} will produce a literal \src{\textbackslash},
\src{\char13}, and \src{"} respectively.
\item[\src{\textbackslash 0}] allows you to enter arbitrary escape sequences.
Any numeric characters immediately following this are read as an octal value,
and the ASCII character code they represent is placed in the string. Note that
the result will be truncated to the least significant 8 bits, and that any 8s
or 9s in the sequence may produce unexpected behaviour. Many ASCII reference
tables, such as \src{man 7 ascii}, show octal representations to make writing
these easier.
A particularly useful escape sequence is \src{\textbackslash 033}. Printing
the control sequence \src{"\textbackslash 033[yy;xxH"} will cause the cursor
to move to the location referenced by \src{yy} and \src{xx} (yy being row
count, and xx being column count). These numbers are 1-indexed and decimal.
For example, the following text is printed at the top-left corner of the
screen:
\begin{verbatim}
Hello world!
\end{verbatim}
To change this to \src{Hello WRAMP!} without reprinting the parts of the string
which do not need changing, the following sequence could be printed:
\begin{verbatim}
\033[01;07HWRAMP
\end{verbatim}
A selection of other standard VT100 terminal control codes are supported by
\program{remote}. There is no full list of which of these control codes
\program{remote} supports, but the list of standard control codes can be found
online.
\end{description}
\subsubsection{The \Global Directive}
When linking multiple files, we need to share functions and data.
However, we do not want to expose all the labels in a file.
Only labels declared as global (using the \Global directive) are
accessible outside the current file.
In the example program, we have declared the `entry point' \src{main}
as global. To do this we used the following directive:
\begin{verbatim}
.global main
\end{verbatim}
\subsubsection{The \equ Directive}
When writing large programs, it can be useful to declare a number of
constants to avoid the use of magic numbers. The \equ directive will
create a named constant, which is simply an alias to a number. It is
similar to a \src{\#define} directive in C. It will not define an
area in memory, nor will it exist in a compiled program aside from
where it is used. The directive can be used as follows:
\begin{verbatim}
.global main
.text
main:
lw $1, switches($0)
sw $1, leds($0)
j main
.equ switches, 0x73000
.equ leds, 0x7300A
\end{verbatim}
This creates a program which will continually read from the switches
and save their value to the LEDs. It has no reserved memory.
\subsection{Registers}
Registers are the CPU's equivalent of variables. There are 16 general
purpose registers numbered 0 to 15. They can be used for temporarily
storing data while it is used in operations. Registers are generally
referred to by a \$-sign followed by a number. For example \reg{0}
refers to register zero. The contents of registers can be transferred
to and from main memory. This done using load and store instructions,
which are covered in a later section.
Some of the general purpose registers have special uses:
Register \reg{0} is always zero. Any attempts to write to it are
ignored. This provides a constant source of zero that can be used for
comparing and initialising registers.
Register fourteen is denoted \reg{sp}. This register is defined by
convention to be the stack pointer. While the hardware imposes no
special conditions on this register, failure to follow this convention
may affect the ability of code to interoperate with other software.
Register fifteen is denoted \reg{ra}. It is defined by convention to
be the subroutine return address register. When a jump and link
instruction is executed, this register is loaded with the address of
the next instruction after the jump and link. We will discuss stacks
and this register in a later chapter.
In addition to these general purpose registers is a set of special
purpose registers. The use of these is covered in chapter
\ref{chapter:exceptions}.
Various types of instructions are introduced below.
\subsection{Instructions}
Executable machine code is created by assembling WRAMP instructions.
Instructions tell the WRAMP CPU what to do. For example an \src{add}
instruction will add the contents of two registers and place the result
in another.
\subsubsection{Arithmetic}
Arithmetic instructions come in four forms, which are listed
below, using \src{add} as an example:
\src{add \regd, \regs, \regt} \\*
Simply performs the specified operation
on \regs\ and \regt, placing the result in \regd. For example,
\mbox{\src{add \reg{1}, \reg{2}, \reg{0}}} will add the contents of registers
\reg{2} and \reg{0} then place the result in \reg{1}.
\\
\src{addi \regd, \regs, Immediate} \\*
This is known as immediate form.
The argument \src{Immediate} is a constant. Thus the specified
operation is performed on \regs\ and \src{Immediate}, and the result
placed in \regd. For example \mbox{\src{addi \reg{1}, \reg{2}, 4}} will add
\src{4}\ to the contents of \reg{2}\ and place the result in \reg{1}.
Keep in mind that \src{Immediate} is a sign extended 16-bit twos compliment integer,
meaning the range of numbers is \src{-32,768} to \src{32,767}.
\\
\src{addu \regd, \regs, \regd} \\*
The \emph{u}\ tells the CPU that this is an unsigned instruction.
Both operands will be treated as positive, which is important when
we consider the two's complement representation of negative numbers.
For example, \mbox{\src{1111 1111 1111 1111 1111 1111 1111 1111}}
represents \src{-1} when treated as signed, and 0xFFFFFFFF, a very
large positive number, when treated as unsigned.
\\
\src{addui \regd, \regs, Immediate} \\*
This is the combination of the two forms above. It performs an unsigned
operation on \regs\ and the \src{Immediate} value.
\\
For a full listing of arithmetic instructions see Appendix
\ref{appendix:instr}.
\subsubsection{Memory I/O}
The WRAMP CPU has a 20-bit memory space. Of this, the memory locations
0x00000 to 0x03FFF are RAM.
Unlike other CPUs, WRAMP has only a single method of referencing
external memory. It consists of a base address added to an offset.
The base address is specified as a constant in the instruction. The
offset is the contents of a specified register.
The notation for this is \src{base(\regs)}. The \src{base} can either
be a label or an integer. To load from the memory location specified
by a label, \reg{0} can be used for \regs. We will mostly use this method
of accessing memory. Figure \ref{memio} shows an example.
It loads a word of data from memory into a register, adds 1 to it,
then stores it back into the memory.
\src{lw \regd, base(\regs)}\\*
Used to get the contents of the specified memory location and place it
in the register \regd.
\src{sw \regd, base(\regs)}\\*
Will place the contents of \regd\ into the specified memory location.
As well as the \src{base}, a constant offset can also be provided to
\src{lw} and \src{sw} instructions:
\src{lw \regd, base+1(\regs)}\\*
This will load from the address directly after the one pointed to by
\src{base}. A negative offset can also be provided, such as \src{base-1}.
This allows a user to do things like indexing directly to a constant
offset in an array. Care must be taken to not provide an offset that
points to an unexpected memory location, especially when using negative
offsets.
\begin{figure}[btp]
\begin{center}
%\begin{footnotesize}
\begin{tabular}{|p{15cm}|}
\hline
\begin{verbatim}
.text
. . .
#Read from the memory location `counter' into $4
lw $4, counter($0)
#Add 1 to $4
addi $4, $4, 1
#Store the contents of $4 into the memory location `counter'
sw $4, counter($0)
. . .
.data
# This is our counter
counter:
.word 0
\end{verbatim}%$
\\
\hline
\end{tabular}
%\end{footnotesize}
\end{center}
\caption{Memory I/O Example}
\label{memio}
\end{figure}
Sometimes you will need to know the address of a variable. The
instruction `load address' ( \src{la} ) is used for this. It has the
structure:
\src{la \regd, label} \\*
Load the address that \src{label} refers to into register \regd.
This instruction also allows loading of a 20 bit immediate to a register.
This instruction is also the method used to use the special labels
\src{text\_size}, \src{bss\_size}, and \src{data\_size}.
\subsubsection{Test Instructions}
These instructions are used to compare either two registers, or a
register and an immediate value. They take the same form as
arithmetic instructions. If the test passes the destination register
is set to \src{1}, otherwise, it is cleared to \src{0}.
For example, to test if registers \reg{2} and \reg{3} were equal and store the
result in \reg{1} we would use the `set if equal' instruction:
\src{seq \reg{1}, \reg{2}, \reg{3}}.
A full listing of test instructions can be found in the instruction set reference, Appendix \ref{appendix:instr}.
\subsubsection{Program Control}
We can move execution to a different part of the program using two types
of instruction: the unconditional jump, and the conditional branch.
\textbf{Jump Instructions}\\*
The jump instructions simply move execution to a different line of
code. They are unconditional and so do not perform any tests first.
There are four different varieties:
\src{j label} - Jump\\*
Jumps to the specified label.
\src{jal label} - Jump and link\\*
Stores the address of the next instruction into the return address register
\reg{ra}. It then jumps to the specified label. This is used when calling
subroutines.
\src{jr \regs} - Jump Register\\*
Jumps to the location specified by the contents of the register \regs.
Because the WRAMP CPU has only a 20-bit address space the upper 12 bits
of the register are ignored. Jump register is typically used to
return from a subroutine using \src{jr \reg{ra}}
\src{jalr \regs} - Jump and Link Register\\*
A combination of \src{jal} and \src{jr}.
It works in the same way as \src{jr}, but it stores the address of the
next instruction into the return address register before jumping.
\textbf{Branch Instructions}\\*
Branching instructions are conditional. They look at whether a
register is zero or not and act on that information. There are two
varieties: `branch if equal to zero' \src{beqz} and `branch if not
equal to zero' \src{bnez}. Both of these instructions take a single
register and a label as arguments.
For example the `branch if not equal to zero' command
\src{bnez \reg{1}, loop} will branch to label \src{loop} if
\reg{1} is non-zero.
\subsection{Assembling and Linking}
Before we can execute our program on the Basys board we need to
translate it into machine code, so that the WRAMP CPU can understand it.
This is a two-step process.
Please see Appendix \ref{appendix:toolchain} for additional details
on the usage of these tools, as well as some supplementary tools.
\subsubsection{Assembly}
First, we have to \BI{assemble} the source code using a program
called an \filename{assembler}. This involves checking that all the
directives and instructions within the program make sense (are
syntactically correct). The program is then translated into a file
called an \BI{object file}. This contains portions of machine code
along with other information about the program.
To assemble our file we use the WRAMP \BI{assembler}, \program{wasm}:
\begin{verbatim}
wasm intro.s
\end{verbatim}
There should now exist a file called \filename{intro.o}. This is the
\BI{object file}. You can manually specify a filename by providing the
\src{-o} flag, but the default name is usually the clearest: the
object file created from the source file with the same name.
\begin{verbatim}
wasm -o intro.o intro.s
\end{verbatim}
\subsubsection{Linking}
Next we must \BI{link} the \BI{object file}. A program may be
comprised of many separate parts. Even our example program contains
functions (subroutines) contained in a separate \BI{library}. Linking
involves joining all these parts together to create a final program.
The WRAMP \BI{linker} is called \program{wlink}. We will use it to
link our object file to the library object file bundled with this manual.
Issue the command:
\begin{verbatim}
wlink -o intro.srec intro.o lib_manual.o
\end{verbatim}
This command links together the object files to create a file called
\filename{intro.srec}. This file is in a form known as S-Record, which
is suitable to be uploaded to WRAMPmon and executed.
%
%
% SECTION - WRAMPmon
%
\section{Introduction to WRAMPmon}
\label{intro:wrampmon}
The \WRAMPmon\ monitor is a program which runs on the Basys boards. It
provides you with basic facilities for interacting with the board.
It is important for hardware and software development, debugging,
testing and troubleshooting. It uses a command line interface to
perform these functions.
\WRAMPmon\ communicates through the first serial port, which is usually
connected to a Linux machine.
By running a terminal emulator on the Linux machine, we can talk to the board.
\subsection{WRAMPmon commands}
A set of commands is provided for the user to interact with \WRAMPmon\
including:
\begin{itemize}
\item a help command (\src{help}, or \src{?})
\item commands to view and alter the memory and register contents
\item a command to upload your programs
\item commands to execute programs in the memory
\item commands for debugging
\end{itemize}
For a listing of these commands see Appendix \ref{appendix:wrampmon}.
\subsection{Getting started}
The Basys board uses serial ports as its primary form of communication.
The first serial port on the board should be connected to a Linux
machine. The Linux machine runs a terminal program, called
\filename{remote}, which transmits anything typed on the keyboard
directly to the board, and displays any text received from WRAMP.
To execute the terminal program type \src{remote} from a console.
Once you have \src{remote} running you will need to reset the
board by pressing the \src{RESET} button, the \src{RESET} button is the
top button in the group of 5.
You should see something like Figure \ref{wrampmon}.
\begin{figure}[h]
\begin{center}
\begin{tabular}{|p{15cm}|}
\hline
\begin{verbatim}
+------------------------------------------------+
| WRAMPmon 0.7 |
| Copyright 2002, 2003 The University of Waikato |
| |
| Written by Dean Armstrong |
| Ported to the Basys3 in 2018 by |
| Daniel Oosterwijk and Tyler Marriner |
+------------------------------------------------+
Type ? and press enter for available commands.
>
\end{verbatim}
\\
\hline
\end{tabular}
\end{center}
\caption{\WRAMPmon}
\label{wrampmon}
\end{figure}
Type \src{?} to obtain a list of commands available within \WRAMPmon.
Help on individual commands can be obtained by typing the command and then a
question mark, eg:
\begin{verbatim}
load ?
\end{verbatim}
Each command gives the required format and available options.
An item enclosed in square brackets, \src{[}~and~\src{]},
indicates an optional item. An item enclosed in angled brackets,
\src{<}~and~\src{>}, indicates a compulsory item.
If you have any problems with the monitor not responding at any stage you
should always be able to get back to the board's initial state with the
start-up message displayed by pressing the \src{RESET} button.
\subsection{Uploading and Executing your Program}
Before you can run your program on the Basys board it must first be loaded
into the board's memory. This can be done by setting the board into \src{load}
mode and using the upload option within the \program{remote} program to send
the S-Record file from the Linux machine to the board. To place the board
into load mode, type the following command (then press enter) at the
\WRAMPmon\ prompt:
\begin{verbatim}
load
\end{verbatim}
After hitting return there should be a reminder response from the board
indicating how to send an executable file. To send the executable type:
\verb| <ctrl>-a| and then \verb|s|
Where \verb|<ctrl>-a| means press and hold the \src{control} key, hit
the \src{a} key and then release both keys.
The \program{remote} program does not pass this key sequence on to the Basys
board but instead enters a command mode. When you press \src{s}, remote will
switch into upload mode. A dialogue box appears which asks you to enter the name
of the file you wish to upload. Type in the following file name:
\begin{verbatim}
intro.srec
\end{verbatim}
After the file name has been entered a series of dots should appear on the
screen indicating that the file is being uploaded, followed by a message which
tells you that is has completed. You should then press the enter key to
leave the upload mode of \src{remote} at which stage the \WRAMPmon\ prompt
should reappear.
If any characters which are not dots appear, it means that \WRAMPmon\ did not
correctly receive the program data. \program{remote} will try again until it
reaches ten failures. If this happens, you should check the connection between
the Linux machine and the Basys board, and recompile the S-Record file.
Now that the program has been uploaded, you can run it by typing the command:
\begin{verbatim}
go
\end{verbatim}
This will start executing your program from the entry point defined by the
\src{main} label. The program will prompt you to enter four numbers. You
should continue to type a number and hit enter until the program outputs the
resulting sum. The output of your program should appear on your screen. When
the \WRAMPmon\ prompt appears again it indicates that your program has finished
executing.
\subsection{Debugging your Program}
\label{intro:debugging}
The program that you have just run on the Basys board should have read four
numbers from the keyboard and output their sum to the terminal. However, when
run, only three numbers are read before their sum is output.
In this section of the exercise, you are going to use the debugging
features of \WRAMPmon\ to locate the bug that causes this problem.
The debugging commands within \WRAMPmon\ allow you to trace the execution
of a program (i.e. follow the path of execution) by inserting breakpoints.
If a breakpoint is set at a certain instruction, then when the program
is running, and that instruction is about to be executed, control will
be returned to the monitor. From here, you can view register and
memory contents, and maybe resume execution, or step through the
program one instruction at a time to try and identify bugs. The
commands for setting, removing and viewing breakpoints are \src{sb},
\src{rb}, and \src{vb} respectively. The help functions in \WRAMPmon\
fully describe the operation of these commands. For example, to find
out more about the set breakpoint command type
\begin{verbatim}
sb ?
\end{verbatim}
Insert a breakpoint at the beginning of the loop in the above program
(ie. at memory location \src{0x00004}), and execute the program using
the \src{go} command.
When a break does occur, use the view registers command to find out
the contents of the registers. You should also notice that the breakpoint
register dump contains identical information to the \src{vr} command.
To continue execution type:
\begin{verbatim}
cont
\end{verbatim}
This will cause the program to continue execution until either the
breakpoint is encountered again or the program completes execution.
Remember that the program will now wait for you to enter a number
before it will break again.
Another feature of the monitor that can be used to help debug your programs
is the single-step command \src{s}. This command causes only the
immediately next instruction to be executed, then returns back to
\WRAMPmon.
To demonstrate the use of the single step command, you should reset the
board and reload the program. Create a new breakpoint at memory location
\src{0x00005}. Once this is done run the program using the \src{go}
command.
Once you have encountered the breakpoint, try single stepping through
the program using the \verb|s| command. Pay careful attention to the
loop counter in \reg{5} and the instructions that increment and test
that register. As we are only interested in the loop counter at this
stage we will skip the \src{readnum} subroutine. We can do this using
the `step over' \src{so} command. When you reach the instruction \src{jal
readnum} type `\src{so}' instead of `\src{s}'.
At some point, you may wish to remove the breakpoint using the
\src{rb} command and then use \src{cont} to make the program run to
completion.
As you may have noticed, the program is designed with a bug. Although
it is intended to add 4 numbers, it will only add 3. You should now use
the debugging methods we have just covered to determine the cause of the
bug. Correct it then and assemble, link, and load the program to confirm
it now operates correctly.