CSE 141L Homepage | Lab Overview | Lab Description
| Deadline: |
|
| Changes: |
|
In order to make the work more manageable, there will be two due dates for this part of the lab. A preliminary progress report with the work from steps 1-3 will be due on Sunday, May 15. A full progress report, including all of the steps will be due on Sunday, May 22.
Jump to: Control Logic | Finalize Fetch Unit | Instruction Set Test | IO Test | Write a Simple Loader | VirtualMachine Test | Evaulation
Complete your backend by implementing its control logic. In your report write a state transition diagram for your processor showing the states, their transitions and the control signals causing the transitions. Include the source files in an appendix at the end of your progress report.
if (UUT.fifo_enqueue)
begin
$fwrite(filedes,"Enque %9.9x %5.5x\n", UUT.pc_prev_r, UUT.ram_data);
end
To run your program, you will need to use your assembler to generate COE files for your instruction and data memories. Because Altera uses a different (HEX) format than you generate with your assembler, you will need to convert these files to the appropriate format. We have provided you with a Java class, hex_converter.java, which automatically converts COE files to HEX format. (Check out this script using SVN: svn co svn://parallel.ucsd.edu/asm-sim-framework/trunk/coe-to-hex ) Run the program with the "-h" option for instructions on how to use it. You may also want to incorporate this code directly into your assembler so that your assembly output is in HEX instead of COE format.
After you have generated the HEX files, use them to create new instruction and data memory modules. You can follow the same steps to create memory modules with MegaWizard as you did in Lab 3A but you will additionally need to specify the HEX file that should be used to initialize memory, as shown in this image. Having generated the new memory modules, you can now perform behavioral and timing simulations to verify that your instructions are working correctly. Include the assembly file for your test program in your progress report.
Before you try timing simulation you should verify that behavioral simulation works.
Synthesis for timing simulation, you will only be synthesizing your core.v with Quartus; top.v and io_device.v will be added to your modelsim project afterwards and will be unsynthesized. Timing simulation can be challenging to debug; both for synthesis and for simulation. For synthesis, the safest thing is to stick to the synthesizable Verilog constructs that we have used in class. Behavioral verilog, using negedge of clock, initial statements, assignments to registers, etc, are all red flags for synthesis problems.
Debugging timing simulation In timing simulation, much of the internals of your core are obfuscated
by the optimization process. This makes things very challenging. In many cases, register names are preserved; as long as they were not optimized away.
One approach to guarantee you can see certain values is to create a system verilog struct that you route all the way to the top-level of your design. Then you can add and remove wires for debugging without writing code to route them through your module hierarchy. See this file for
some tips on System Verilog structs. If wires are part of the interface of your top-level module in synthesis, then they will not be optimized away
since they are legitimate outputs.
It often pays to identify "risky" elements of your design from a timing simulation point of view. Then write smaller unit tests
that just test those particular components (e.g. 12 ported register file) or constructs (e.g. structs; unfamiliar syntax.) Testing smaller
portions of your design that present risk of not synthesizing correctly, is often a time-saver even if you don't find a bug, because now
you know with much more certainty where the bug is not located.
| Q1 | What was your strategy for testing all your instructions? Is there a way to quickly verify that all of the instructions executed correctly? |
| Q2 | Include screen captures from at least 3 points in your behavioral simulation. One of these must be for the end of your program but the rest of the points are of your choosing. Be sure to explain what each of the screen captures is showing. Also, make sure the captures are zoomed in enough to see actual values and that the labels for the signals are visible in the capture. |
| Q3 | Include screen captures for atleast 3 points in your timing simulation. They can be from the same points where you captured for behavioral simulation in Q2. |
You also have access to top.v which is a top level module that includes your processor core and the IO devices. Note that you will need to modify top.v if you did not use the exact core interface given in part 1 of this lab.
We recommend that you extend your simulator to support this interface, so that you can generate reference traces to aid in the debugging of your RTL.
The interface of the io_devices module is given below:
module io_devices#(parameter D_WIDTH = 34, PA_WIDTH = 4) ( input reset_i, input clk, input read_req_i, input write_req_i, input [PA_WIDTH-1 : 0] read_addr_i, input [PA_WIDTH-1 : 0] write_addr_i, input [D_WIDTH-1 : 0] din_i, output [D_WIDTH-1 : 0] dout_o, output read_ack_o, output write_ack_o );
The io_devices module provides the following services via I/O channels:
Input Channels:
Now that you have an IO device to interact with, you should write a small assembly program to test your in and out instructions. Include this assembly program as part of the appendices of your progress report.
| Q4 | Explain how the setup of your IO test. Get a screen capture of the behavioral simulation of this test and explain the results. |
To run a SuperGarbage program using your VM, your processor first needs to properly load the application into the data memory. The following figure shows the format of the SuperGarbage binary file and how a loader works. After selecting the application to load, the loader requests the selected SuperGarbage binary file via input channel #1, word-by- word. The odd-numbered words contain the address where the following word will be stored. For example, in the figure below, 'Data 0' will be loaded into address 3 in your data memory. The loader continues loading data until it encounters the address -1 (0x3FFFFFFFF), which means the end of the file. The word following address -1 is the starting PC for the SuperGarbage program. After the loader is finished, it should call the VirtualMachine function you have written.

The following Java-esque pseudo-code shows how to load a program from the io_devices module and run the VirtualMachine. We have provided several SuperGarbage applications for you to test on. Changing the num_app variable in the pseudo-code will change which of these applications you load. You should write the loader in your assembly language, build the COE files, convert them to HEX, and generate a memory module. Be sure to include the assembly code for your loader in an appendix of your progress report. Note that get_instr_count is a macro that translates into whatever assembly instructions are needed to access a counter that counts the number of instructions executed in your processor since reset (you will add this functionality to your processor; see below).
// SuperGarbage Loader
// num _app
// 0: app0.bin
// 1: app1.bin
// 2: app2.bin
final int num_app = 0;
word mem[4096];
word startPC;
// basic code stub
set $SP;
set $GP;
// select an app
out( num_app, 1);
// load data from an external device while(addr != -1)
do {
word addr, data;
addr = in(0x1);
data = in(0x1);
if (addr == 0x3FFFFFFFFL) {
startPC = data;
break;
} else {
mem[addr] = data;
}
} while(true);
// Finally, call the virtual machine
start = get_instr_count();
VirtualMachine(startPC, mem);
end = get_instr_count();
out (0x3,end - start);
| Benchmark | Assembly File | Binary File | Input File | Counter Input File |
|---|---|---|---|---|
You should now run your loaded with the app0 (Compare) to make sure your loader is working correct.
| Q5 | Perform a behavioral simulation of your loader using the app0. Get a screencapture of the integer that is returned from the VirtualMemory function. What was this integer? |
The following files comprise the SuperGarbage simulator. After downloading and compiling them, you can start the simulator by running the command 'java SuperGarbageSim'.
Here are a few examples of SuperGarbageSim commands:
prompt> load test1.bin // load 'test1.bin' file prompt> disasm // disassembles 10 instructions from PC prompt> disasm 0x10 15 // disassembles 15 instructions from 0x10 prompt> set_mem 14 0x0 // set the memory location 14(0xe) to 0x0
| Q6 | With the aid of SuperGarbageSim, figure out what the final PC of app0 should be. Explain how you got this number. How does it compare to the integer that was returned in your screen capture as part of Q4? |
In order to count the number of instructions executed on your processor, you should add an instruction counter to your processor (this was briefly referred to in step 5). It should be initialized to zero when your processor is reset and incremented after every successful execution of an instruction. Make sure to only count instructions that have committed; i.e. since some instructions may be squashed after fetch.
Note: dmem.v occassionally refuses a request to the memory (for debugging purposes). However, for testing of the applications, we do not want this to happen. We have therefore provided dmem_no_refuse.v, which does not refuse requests. When doing performance analysis, use dmem_no_refuse.v rather than the old dmem.v.
| Q7 | Run all the benchmark applications and gather the following information for each benchmark:
|
| Q8 | Why does CPI vary across applications? |
| Q9 | What is the maximum achievable frequency of your processor? Include a screen capture on the post-route simulation result at that frequency in your hardcopy report. Using this frequency, calculate the execution time for all three benchmarks. |
| Q10 | What is the critical path of your processor? Draw the critical path on the datapath schematic you made in part 1 of this lab. |
| Q11 | Propose one idea for increasing the performance of your processor. Why do you think it is an effective way to boost the performance? |