CS 21 25.2 Laboratory Exercise 5
Single-Cycle Processor
Overview
As mentioned in the lectures, the RISC-V single-cycle processor is a sequential circuit made up of registers, memory, multiplexers, and other combinational components.
You will be using Logisim to modify an existing single-cycle processor implementation to support other kinds of instructions.
General Instructions
For this laboratory activity, you are to work on one HOPELEx Checkpoint Item that will aid in your understanding of the RISC-V single-cycle processor.
Important Reminder
You must finish and show your working checkpoint tasks to your lab handler before the end of the laboratory period. HOPELEx checkpoint items contribute 1% to your lab grade.
At the end of the HOPELEx Checkpoints are take-home exercises called TakeHOPE items. These are not graded and will not be submitted, but will help you prepare for the HOPE.
Relevant Links
- Ripes Fork: https://ripes.upd-dcs.work
- Google Classroom (slides, submission bin): https://classroom.google.com/u/2/c/ODQwNDkwODYxODg3
- RISC-V Green Card: https://drive.google.com/file/d/1xSll1ON5cSaOQhoGxpkvr4fKe7lGQFy3/view
- Lab 5 Logisim Template: https://drive.google.com/file/d/1pASP1ligoLcdXjPlcyACQCem6pdQRBQ6/view?usp=sharing
Guided Walkthrough
Overview
A Logisim-Evolution template for a RISC-V single-cycle processor can be downloaded via the link in the previous section. This processor implementation supports the following instructions:
lwswaddsubandorsltaddibeqjal
Your lab handler will run you through the template.
Note that the ALU is incomplete, causing R-type and I-type instructions not listed above to yield incorrect results.
Walkthrough #1: Running a single instruction
Suppose we want the processor to execute the following instruction:
To do this, its machine instruction equivalent should be loaded into instruction memory.
Do this now!
Convert addi x1, zero, 21 into its machine instruction equivalent in hexadecimal. You may use Ripes to do this quickly.
Select the hand tool (Ctrl-1 or ⌘-1) and click the instmem component laid out in the circuit once for a pink circle and magnifying glass icon to appear at the center of the component.
Next, double-click the magnifying glass icon to enter into the implementation of the instmem subcircuit. You may need to scroll up to find the ROM component.
Use the hand tool to click the first top-left 00000000 word (address 0) on the ROM component–this should have the component circled in pink with the word boxed in red.
Typing hexadecimal symbols here will change the value boxed in red. Type the hexadecimal representation of addi x1, zero, 21 to make address 0 contain the said instruction.
Tip: Alternative method
Copy-pasting values can be done by instead right-clicking the ROM component, selecting Edit Contents, selecting a box to fill up, then hitting Ctrl-v or ⌘-v.
Double-click main under either the Design or Simulate tab (or hit Ctrl-Left key or ⌘-Left key) to return to the main circuit.
Do this now!
Verify that the entered machine instruction is shown as the output of the instmem component and is shown as the value of the Instr probe.
Note that the instruction addi x1, zero, 21 under PC will only take effect after the next triggering edge. Use the State tab to verify that x1 still contains the value 0.
Trace the flow of bits across the circuit and verify that the value 21 will be written to x1 when the register file is triggered.
To make the clock signal tick (i.e., make one full cycle), hit Ctrl-T or ⌘-T twice (or run Simulate > Manual Tick Full Cycle once).
Make the clock tick once, then use the State tab to verify that x1 now contains the value 21 (0x15).
Look for the PC register laid out in the circuit and verify that its current value is now 4 with the current instruction being 00000000.
Hit Ctrl-r or ⌘-r (or run the Simulate > Reset Simulation menu item once) to reset all non-ROM data back to zero. Verify that PC is once again 0 and that all registers are zeroed out.
Reset Simulation
The Reset Simulation menu option of Logisim will zero-out all register and main memory values, but not ROM values (i.e., instruction memory).
This convenience allows you to perform multiple reruns of the same program with all registers and main memory values zeroed out without having to reload the same set of machine instructions into the ROM component over and over.
Walkthrough #2: Running an entire program
Do this now!
Use Ripes to assemble the instructions below into their hexadecimal equivalents.
.text
addi sp, zero, 0xff0
add gp, zero, zero
add t0, zero, zero
addi t1, zero, 10
addi sp, sp, -32
loop: beq t0, t1, done
lw t2, 4(sp)
addi t2, t2, 10
sw t2, 4(sp)
lw t3, 8(sp)
addi t3, t3, 100
sw t3, 8(sp)
addi t0, t0, 1
jal zero, loop
done: sub t4, sp, zero
not t4, t4
Ripes version
If the locally installed Ripes on your TL machine is unable to assemble addi sp, zero, 0xff0, kindly switch to https://ripes.upd-dcs.work.
To easily load several instructions into the instruction memory component, create a .txt file as follows:
v3.0 hex words
<eight-hex symbol instruction 1>
<eight-hex symbol instruction 2>
...
<eight-hex symbol instruction n>
Memory image format
The header line v3.0 hex words should be written as is while the instructions in hex should not have 0x.
Tip: Quick conversion shell script
Supposing the output of the Ripes assembly is in assembly.txt, the following command automatically transforms the said output into its Logisim-ready form in logisim.txt:
Open the instmem subcircuit, right-click the ROM component, select Load Image, then select the newly created .txt file.
After verifying that the ROM component indeed contains the correct sequence of instructions, head back to the main circuit.
While you could manually tick the clock until the execution of the last instruction to run the loaded program, it is likely more convenient to make the clock tick automatically by hitting Ctrl-g or ⌘-g (or ticking Simulate > Auto-Tick Enabled).
Clock rate
You may adjust the frequency of clock ticks via Simulate > Auto-Tick Frequency.
Using this approach, PC will eventually point to locations outside the scope of the loaded program which contains the instruction 00000000 by default–you may take this to mean that the program has finished execution.
Reset the simulation state, then run the program until its completion. Take note of the register values in particular.
Tip: State tab
You may use the State tab located at the left side of the Logisim window to examine register values without having to open up the register file.
Run the same program using Ripes and take note of its register values.
Verify that all but one register is consistent between the two sets of register values–this is because xori is not yet supported by the processor.
Self-check
xori does not appear in the assembly version of the program, but why is it present in the assembled version?
Walkthrough #3: Support for xori
Clear instruction memory and load xori x5, zero, -1 into address 0.
Clear instruction memory
You may select Clear Contents to zero-out the ROM component of instmem.
Notice that the ALUControl signal which controls the ALU does not have a valid value.
Do this now!
Zoom into the ALU component by double-clicking it with the hand tool, trace where exactly the ALU uses the ALUControl signal, and examine its purpose in the operation of the ALU.
Ensure you understand why ALUControl = 000 makes the ALU add, 001 makes it subtract, 010 makes it do AND, 011 makes it do OR, and 101 makes it do SLT.
The XOR operation is not yet supported by the ALU–there is no XOR gate in the ALU and it is not mapped to any ALUControl value.
Do this now!
Select a free ALUControl value, then modify the ALU to make it perform SrcA XOR SrcB for that particular ALUControl.
The computation for the ALUControl signal itself should also be fixed.
Do this now!
Return to the main circuit, trace where the ALUControl signal is being generated, and enter that subcircuit.
Ensure you know how priority encoders work before moving forward.
Using the ALUControl value you selected earlier, create an IsXor tunnel in the subcircuit and connect it to the correct input port of the priority encoder.
Create another IsXor tunnel, then connect it to a combinational circuit that:
- Outputs
1ifALUOp == 10(base 2) andfunct3 == 100(base 2) - Outputs
0otherwise
Verify that ALUControl now outputs a valid value for any xori instruction and that the resulting register values of the program loaded earlier are now consistent with those of the Ripes execution.
HOPELEx Checkpoint
Checkpoint Task: auipc
Modify the given Logisim circuit to support the U-type instruction auipc.
Ensure that all other instructions that were supported before by the template still work as intended.
You are allowed to use tunnels.
Save the resulting circuit as lab05.circ.
Demo
Show that the following code:
main:
auipc x31, 0xf0000
addi x1, x0, 10
loop:
auipc x30, 0x12345
add x31, x31, x30
addi x1, x1, -1
beq x1, x0, done
beq x0, x0, loop
done:
add x0, x0, x0
results in the following register values (with all unstated registers equal to 0x00000000):
TakeHOPE Problems
Item 1: R-type instructions
Add microarchitecture support for the following instructions:
subandorxorsllsrlsrasltsltu
Item 2: I-type instructions
Add microarchitecture support for the following instructions:
andiorixorisllisrlisraisltisltiu
Item 3: Branch instructions
Add microarchitecture support for the following instructions:
bnebgebltbgeubltu
Item 4: Other instructions
Add microarchitecture support for the following instructions:
luilblbulhlhusbsh
Item 5: Pseudoinstructions
Turn the following pseudoinstructions into basic instructions and add microarchitecture support for them:
notblebleubgtbgtubeqzbnezblezbgezbltzbgtz