For this lab you will finally finish enhancing your PIPS computer by adding a keyboard input. You will then write three simple programs using the input and output devices.
It may be dangerous to proceed without having finished the previous portions of the lab. Please undertake completion of parts I–V before working on this lab.
Your datapath will ultimately be assessed by a test suite, and the final grade mostly determined by how many tests your datapath passes.
In addition to verifying circuit and program correctness, other elements of style will also be considered.
You added a terminal to your datapath in the previous lab, but most computers also give you the ability to provide input to your programs as well. We’ll use the same strategy of memory-mapped I/O to connect Logisim’s keyboard component to the datapath.
Add a keyboard device to your datapath somewhere near your memory controller. You can find this device in Logisim’s Input/Output section of components.
The keyboard device in Logisim has a short buffer. When you press a key (after selecting the keyboard with the hand tool) it places a character in the buffer. When the keyboard is enabled and its clock input rises, it deletes the first value from its buffer. The keyboard continuously outputs the value of the first character in the buffer to the $\text{Data}$ output, located on the lower right corner of the component.
Connect the keyboard’s clock input to a clock component. You should not use an inverted clock here; we do not want the keyboard buffer to change state at the same time its value is being written to a register.
As with the terminal, we need to choose a memory address that corresponds to the keyboard device.
We’ll use 0xff20, since this is the next available word in the upper memory region after the terminal device.
We want to allow the keyboard to advance to the next character in its buffer when we the program is reading from the address 0xff20.
Add a comparator and constant to check if the memory address is equal to 0xff20.
Remember that the memory controller’s $A$ input is connected to the ALU output.
We want to enable the keyboard only when the current instruction accesses memory at the address 0xff20, not just when its ALU output is 0xff20.
Use an AND gate to turn on the keyboard’s enable pin (located in the lower left corner) when the comparator’s $=$ output is true and the datapath is configured to read from memory.
Warning: Be careful not to connect to the keyboard’s $\text{clear}$ input!
Now, hook the keyboard’s $\text{Data}$ output to a bit extender the convert the 7-bit value to a 16-bit value.
This is the value we want to send back to the register file instead of the data value read from memory.
Most of the time we will pass the memory controller’s $R_d$ output to the register file, but when the program is loading from address 0xff20 it should send the keyboard buffer output back instead.
Add a multiplexor to choose between the memory controller’s $R_d$ output and the keyboard’s $\text{Data}$ output based on the result of the comparator you added earlier in this part of the lab.
Now that you have the keyboard connected, save and assemble this simple PIPS program that echoes keyboard input to the TTY output:
# Echo characters typed to the terminal until a newline is read
# Charlie Curtsinger
.constant HALT 0xff00
.constant TERM 0xff10
.constant KBD 0xff20
.constant STACK_TOP 0xf800
nop
main:
li $s0, TERM # Address of the terminal output for memory-mapped I/O
li $s1, KBD # Address of the keyboard input for memory-mapped I/O
li $sp, STACK_TOP # Predefined initial stack address
loop_top:
lb $t0, 0($s1) # Load a character from the keyboard
beq $t0, $zero, loop_top # If it is the null terminator, start over
sb $t0, 0($s0) # Write the character to the terminal
li $t1, '\n' # Load a newline constant
beq $t0, $t1, end # If the character was the newline, stop looping
j loop_top # Start over
end:
j HALT # Enable halt pin and stop the PC incrementing
Load the assembled program into instruction memory. If you haven’t already, select the fastest tick speed from the “Tick Frequency” section of the “Simulate” menu. Start this program by choosing “Ticks Enabled” from the “Simulate” menu.
Using the hand tool, click on the keyboard buffer and type. You should see the program transfer characters from the keyboard buffer to the terminal output. (Note your keyboard press will need to span a clock tick.) The program should halt once you hit enter. Once this simple test is working you can move on to the next part of the lab.
Warning: Running this program from the command line will result in slightly different behavior. Logisim waits for a newline character before passing inputs to a keyboard buffer in TTY mode, so you won’t see any output until you hit enter. If you type a line that is longer than the keyboard’s buffer it will discard trailing characters. Command line runs also seem to trigger a bug that causes Logisim to skip the first input character on some runs; it’s fine if this happens in the command line, but it should not happen when running the processor inside the Logisim window.
In this final part of the datapath lab sequence, you will write three interesting programs that use input and output.
Write a program that reads in a line of text and prints it out in reverse. The program should continue reading until it hits a newline, then print and halt.
Hint: You might be thinking you need to allocate memory to store the line you read.
While you could do this by choosing a reasonable address somewhere in the middle of data memory, there is a far simpler solution that uses recursion (i.e., without appealing to your procedure reverse from the lab on MIPS procedures).
Save your program in the file string_reverse.s.
Write a program that reads in a line of text and prints it out with all lowercase letters converted to uppercase. Your program should leave numbers, punctuation, and uppercase letters as-is.
Save your program in the file string_uppercase.s.
Write a program that allows the user to type in a one-digit number, a plus sign, and another one-digit number. After typing these inputs followed by a newline character, the calculator should convert the typed digits to numbers, add them, and print the result (also followed by a newline).
You are welcome to reuse the number printing code you wrote for the previous lab. Run the whole program in a loop so it will continue accepting and evaluating user input until the user hits enter without typing a command. Your program does not need to handle invalid inputs; type carefully!
Save your program in the file calculator.s
When you are finished, please create an archive of your entire datapath directory using the following command, starting from inside the datapath directory:
$ cd ..
$ tar cvzf datapath-vi.tar.gz datapath
This should create a datapath-vi.tar.gz file one directory up from your datapath.
Submit this archive to complete the lab.