ECE 411


Spring 2018

FAQs for the Machine Problems

We'll try to keep a summary of questions that we've answered about MPs here. Please note that this page may lag behind Piazza, so if you can't find your answer here, check Piazza.

Questions are categorized by those which are specific to a certain MP, and those that are (possibly) relevant to all MPs.

General Questions

When simulation, the log shows an error like Reading /software/mentor/ModelSim-SE-10.1d/modeltech/tcl/vsim/pref.tcl Error in startup script: unmatched open brace in list while executing "GUIMAIN" invoked from within "if Unknown macro: {[batch_mode]} { BATCHMAIN } else { GUIMAIN }" invoked from within "ncFyP12 \-+" (file "/software/mentor/ModelSim-SE-10.1d/modeltech/linux/../tcl/vsim/vsim" line 1) \*\* Fatal: Read failure in vlm process (0,0) /software/mentor/ModelSim-SE-10.1d/modeltech/linux/vsim returned status 1

Try navigating to your home directory and deleting the .modelsim and .modelsim.bak files.

      rm -iv ~/.modelsim ~/.modelsim.bak

What is the difference between wire, reg, and logic in SystemVerilog?

In SystemVerilog, reg and logic describe the exact same type, so they can be used interchangeably. logic is an addition of SystemVerilog to Verilog introduced to clarify that if a signal is described as a reg, a register may or may not be synthesized.

The wire type describes a signal that can be continuously assigned, but can not store a value. The logic type describes a signal that can either be continuously assigned or can store a value (e.g., a register).

Practically, a logic type can be assigned inside an always block, but a wire type cannot. wire types can be assigned via an assign statement or used to connect ports between components.

Additional information: [1], [2], and [3]

My code passes Analysis and Synthesis in Quartus without any errors, but Modelsim throws an error similar to Error: /path/to/ (vlog-2110) Illegal reference to net "load_something".

This likely happens because you didn't declare a signal as a logic type, in which case the software will default it to a wire type. Subsequently, when you try to assign to the signal procedurally, e.g., in an always block, the error will be thrown.

You can fix this by declaring the signal as a logic type.

In general, pay attention to warnings/errors thrown by both Quartus and Modelsim, as one may warn about irregularities that the other doesn't.

How do I end an assembly program?

With an infinite loop. Something like: ENDLOOP: BRnzp ENDLOOP

How to make the assembler stop warning me that it is creating a default segment?

Add the line


to the beginning of your code (after ORIGIN).

The assembler is telling me "Error: ld index (blah) greater than 7 bits."

This means the data you are trying to load is too far from the beginning of a segment. Any data you wish to load must be within 64 words of the start of a segment. The best way to solve this is to make a new segment for whatever data you want your program to have. i.e.,

    -- ...Instructions...
    .SEGMENT DataSegment:
    MyData1: Data2 4x1234
    MyData2: data2 4x4567

You then need to use a base register for your load which contains the value of DataSegment. Something like this would work:

    LEA R1, DataSegment
    LD R2, R1, MyData1
Is it necessary to close and reopen Modelsim after loading the memory?

No, but you should restart the simulation using restart -f.

I noticed that RET and JMP have the same Opcode. Is this correct?

Yes. RET is just a special case of JMP. As a consequence of this, you should be able to use the same state in your control to implement both instructions.

Is the JMP instruction PC-relative?

No. The current value of the PC is irrelevant to the JMP instruction.

How is the condition code set for the LDB instruction?

LDB zero-extends the byte value that is loaded. The condition code is set based on the 16-bit value after zero-extension, so the resulting condition code should either be zero or positive.

The LC-3b reference mentions that certain values of trapvect8 are invalid. Do I need to check for these values in my design?

No. You don't need to check for valid values for the trapvect8 field.

How does LEA work with the assembler?

Currently, the parameter you provide to LEA is an absolute word address. The assembler calculates this parameter's distance from the current PC, and stores that distance in the instructions offset9 field. This sometimes confuses people who try to hardcode a value in the LEA instruction. You should always stick to using labels as the parameter for LEA.

How to use test-o-matic?

test-o-matic provides you the final registers values of an assemble code running in LC3-b. Here are the required steps to use it:

1- Copy the test-o-matic script file into your mp directory.

2- Grant execution permission to the file, by opening a terminal in the directory and entering this: chmod +x test-o-matic

3- Open the test-o-matic file in a text editor and make sure that the filenames and paths listed on lines 9, 11 and 13 are correct. Fix them if necessary.

4- Set the addressability figure on line 15 to to 1 if you're using a magic memory module, to 16 if you're using 128-bit line caches, or to 32 if you're using 256-bit line caches. This should match the addressability figure used in

5- You must do "module load altera" in the same terminal as the one in which you're about to run the script.

6- Try running the script now. As following: ./test-o-matic ~/path/to/testcode/testfilename.asm

7- If it doesn't work at this point, it might be because the test-o-matic script by default tries to find instances called regfile, which you likely don't have. So you must uncomment line 25, put the path to your register file there. Then comment out line 184, and uncomment line 185. This should make the script find your registerfile instance.

MP 0 Specific

In the LC-3B? ISA, how does the offset9 field in the BR instruction get shifted before addition to the PC?

It gets shifted left one bit.

In the wave output for ModelSim, where can I find the signals for the register contents?

Something like mp1_tb/dut/datapath/regfile/data

How are unaligned memory accesses handled?

The memory address specified by Base+offset will be treated as word-aligned.

MP 1 Specific

Does the LDB instruction set the condition code based on the 8-bit data or the 16-bit data after zero-extension?

LDB sets the condition code based on the 16-bit data. For LDB, the resulting condition code will be one of Z or P.

What should a test case for mp1 look like?

Here is an example test case for ADD immediate and AND immediate. There are also test cases for LDB, LDI, STB, STI, and TRAP, below. Remember to write your own test cases for the other instructions. Your test cases should cover all the ways that you can think of that an instruction could be mis-implemented. Remember to comment your test cases well to make it clear what is a correct result and what is an incorrect result.

ORIGIN 4x0000

;; This is a small test to test the ADD immediate and AND immediate
;; instructions. It assumes the following are working: BR, LDR
;; If the test passes, R6 will have the value 0x600D. If it fails, R6
;; will have a value from 0xBAD1 to 0xBAD4 or 0x600F. Each value
;; indicates a different type of failure, as described in the
;; comments.

SEGMENT CodeSegment:
	ADD R1,R1,1
	LDR R6,R0,Bad1 ; Immediate ADD does not work
	ADD R2,R1,-2
	LDR R6,R0,Bad2 ; Immediate ADD with a negative value does not work
	AND R3,R2,0
	LDR R6,R0,Bad3 ; Immediate AND does not work
	AND R4,R1,-1
	LDR R6,R0,Bad3 ; Immediate AND does not work
	AND R4,R2,-7
	LDR R6,R0,Bad4 ; Immediate AND with a neg. value does not work
	LDR R6,R0,Good
	AND R6,R6,-3 ; Change 0x600F to 0xG00D by ANDing it with 0xFFFD
	Bad1: DATA2 4xBAD1 ; Immediate ADD does not work
	Bad2: DATA2 4xBAD2 ; Immediate ADD with a neg. value does not work
	Bad3: DATA2 4xBAD3 ; Immediate AND does not work
	Bad4: DATA2 4xBAD4 ; Immediate AND with a neg. value does not work
	Good: DATA2 4x600F ; 0x600F is not correct, the code will change it.
I'm having trouble getting my LDB/STB or LDI/STI instructions working.

Here's some code you can use to test if your LDI/STI and LDB/STB instructions are working correctly. (Courtesy of Ash)

    ; Test LDI, STI
        ldi r7, r0, MyPointer     ;PC= 0
    ;First load should see
    ;MAR < 4
    ;MDR <(M[4] =6)
    ;Second load should see
    ;MAR < 6
    ;MDR < (M[6] = 4x600D)
    ;R7 < 4x600D
        sti r7, r0, MySPointer    ;PC= 2
    ;First load should see
    ;MAR < 8
    ;MDR < (M[8] = 4xA)
    ;Second store should see
    ;MAR < 4xA
    ;MDR < (R7 = 4x600D)
    ;M[10] < 4x600D
        MyPointer: DATA2 MyData   ;4
        MyData: DATA2 4x600D      ;6
        MySpointer: DATA2 MySData ;8
        MySData: DATA2 ?          ;10

These two bits of code should be in separate files!

    ; Test LDB, STB
        ldb r6, r0, LowByte       ;0
    ;MAR < 8
    ;MDR < (M[8] = 4x600D)
    ;R6 < 4x00 & 4x0D
        ldb r7, r0, HighByte      ;2
    ;MAR < 8 or 9
    ;MDR < (M[8] = 4x600D)
    ;R7 < 4x00 & 4x60
        stb r6, r0, LowSByte      ;4
    ;MAR < 10
    ;MDR < 4xXX & (R6(7:0) = 4x0D)
    ;*only* MWRITEL_L is active (=0).
    ;M[10] < 4x0D
        stb r7, r0, HighSByte    ;6
    ;MAR < 10 or 11
    ;MDR < (R7(7:0) = 4x60) & 4xXX
    ;*only* MWRITEH_L is active (=0).
    ;M[11] < 4x60
        LowByte:      DATA1 4x0D ;8
        HighByte:     DATA1 4x60 ;9
        LowSByte:     DATA1 ?    ;10
        HighSByte:    DATA1 ?    ;11
How do I test the trap instruction?

You can write test code something like this:

    -- ...
    TRAP cagey;
    -- ...
    cagey: DATA2 Weasel
    -- ...
    Weasel: ADD R2, R4, R3  -- Or whatever instruction you want.
    -- Whatever else you want to do in the trap routine here.
    RET   -- Go back to the instruction after TRAP.

Your processor should encounter the TRAP instruction, jump to the code labeled "Weasel", execute that (and following) code, and then return to the next instruction after the TRAP.

One of my registers becomes all X's after executing an instruction.

No clean easy answer here. Try to trace back to find out where the X's are coming from. (i.e. the Register file gets its values from regfilemux, which gets its values from ...) Sooner or later you'll trace the X's back to their source. Often it turns out that a mux has the wrong input selected.

Are we allowed to edit the source for the Memory block?

No. If you think otherwise, please ask on Piazza.

Does it matter if I send a non-word-aligned address to memory?

For MP 1, no, it doesn't matter. The memory ignores the least-significant bit of the addresses you send it. For MP 2, the memory is a little different. It has a wider bus, and it ignores the lowest four bits of all addresses you send it. (All accesses are aligned on 16-byte boundaries.)

MP 2 Specific

Does it matter if I send a non-word-aligned address to memory?

For MP 1, no, it doesn't matter. The memory ignores the least-significant bit of the addresses you send it. For MP 2, the memory is a little different. It has a wider bus, and it ignores the lowest four bits of all addresses you send it. (All accesses are aligned on 16-byte boundaries.)

MP 3 Specific

Can we use state machines for our MP 3 design?

Only in the cache hierarchy, nowhere else. A non-pipelined cache may use a state machine as its controller.

What does "no artifical stalls" mean?

A better phrasing would probably be "no unnecessary stalls". It means that non-dependent, non-memory instructions which follow a memory operation must not be stalled by the memory operation. This is true even if the memory instruction encounters a cache miss. (Note: For the purposes of this requirement, WAW (write after write) dependencies are considered valid dependencies.) Some examples might help clarify.

  • Example 1:

            LDI R1, R0, 5 # A
            ADD R4, R4, R3 # B

    In this example, instruction B is not dependent on instruction A. It should not be stalled by the fact that instruction A will be in the Mem stage for at least 2 cycles. Instruction B should "go around" the Mem stage and proceed down the pipeline.

  • Example 2:

            LDI R1, R0, 5 # A
            ADD R3, R1, R5 # B

    Here instruction B must stall because it is dependent on instruction A.

  • Example 3:

            LDI R1, R0, 5 # A
            LD R4, R2, label # Bi

    Instruction B must stall because it is a memory instruction.

  • Example 4:

            LDB R1, R0, 7 # A
            ADD R4, R4, R5 # B
            AND R3, R1, R6 # C
            LSHF R2, R2, 2 # D

    Instruction B should not stall (independent). Instruction C must stall. Instruction D is independent, but may stall because the instruction before it is stalling. This illustrates that you can stop letting instructions "go around" the mem stage once you encounter a dependent instruction.

  • Example 5:

            LDI R1, R0, 10 # A
            BRz label # B

    Instruction B is dependent on instruction A. (It needs the condition codes that will be set by A.) Instruction B must stall.

  • Example 6:

            LDB R4, R2, 10 # A
            ADD R5, R1, 4 # B
            BRz label # C

    Assume A misses in the cache. Instruction B is independent of A, and should continue on to writeback. C depends only on the condition codes set by B, and should also continue on to writeback.

How wide can the input to my control ROM be?

It should be no more than 4-7 bits wide.

How can I see how much space is left in my work directory?

At a terminal prompt, type uquota -s. This will report your use, as well as your quota(s), for your home and work directories. Note that if you approach your quota limit for your work directory, you may begin to see strange HDL Designer errors.