I'd really need a hand or two with this Assembly Mips CPU Excercise.
I have to determine input and output from: ALU(s), Jump-related MUX and from the Register File.
PC is 0x01D0 and the instruction I have to simulate is: beq $3, $7, -120
Regarding the ALU(s) I've no problem on those, I've got issues on MUX and RG.
As you can see on the image on the second jump-related MUX I don't know what to write regarding jump address [31-0].
The other problem I've got is within the Register File, I don't know what to write as input.(Instruction should be: 0x1067FFE2)
Related
So, I know how an lw instruction is supposed to work on a single-cycle datapath, but how would I implement something like:
lwr reg1, reg2(reg3)
Which uses a register as the distance.
Can someone give me a hint of how to implement something like this? What needs to be changed?
Single-cycle datapath
There are a multitude of different instructions in MIPS. I'm currently learning about data and instruction cache.
Instruction cache simply takes what it can so to say, depending on the block size it might utilize spatial locality and fetch multiple instructions. But for data cache I have a harder time understanding when it fetches things from main memory and when it doesn't.
For example, the instruction lw $t0, 0x4C($0) will fetch a word of data stored in address 0x4C and depending on data cache capacity, sets, block size and so forth it will temporarily store in in a block in the cache if for that adress the valid bit or tag doesn't exist there.
In my litterature, an addi instruction does not fetch from memory, why? The only times it seems to need to fetch data from memory is when using the lw instruction, why?
I also have a question regarding registers in MIPS. If we're simply doing the instructions over the registers, then there will be no access to any main memory, correct? It will not even go to the data cache, correct? Are the registers the highest level in the memory heirarchy?
The reason addi doesn't "fetch from memory" is that it's using an immediate operand, as in, the program counter has already fetched the value that's going to be loaded. (Technically it is fetching from memory, since all code resides in some form of memory, but when literature refers to "memory" typically it's referring to a range of memory outside the program counter. When MIPS uses something like lw to load from memory, the CPU has no idea what value the destination register will have until the load is finished.
Just to illustrate this concept further, the original MIPS I architecture (which was used by the PlayStation 1) actually wouldn't finish loading from memory before the next instruction was already being worked on!
lw $t0,0($a0) ;load from the address pointed to by $a0
addi $t0,$t0,5 ;the value in $t0 hasn't been updated yet so this won't have the desired result.
The easiest solution to this was to put a nop after every lw. Chances are the version of MIPS you're using doesn't have this problem, so don't worry about it.
I'm learning MIPS so I wrote a simple C program and generated MIPS assembly with gcc and inside it there is this part
lui $28,%hi(__gnu_local_gp)
addiu $28,$28,%lo(__gnu_local_gp)
I know that lui means load upper immediate but I don't know what %hi(__gnu_local_gp) and %lo(__gnu_local_gp) mean; addiu means add immediate unsigned.
Are lo and hi registers?
If so what does % mean?
The instructions load the address of the symbol __gnu_local_gp into register 28.
__gnu_local_gp is a memory location that is used to store the Global Pointer, and register 28 is typically used to hold the Global Pointer.
'%hi' and '%lo' are builtin functions of the GNU assembler, and have nothing to do with the hi and lo registers in the MIPS architecture.
I'm working with PIC32 MCUs (MIPS M4K core), I'm trying to understand how do interrupts work in MIPS; I'm armed with "See MIPS Run" book, official MIPS reference and Google. No one of them can help me understand the following:
I have interrupt declared like this:
void __ISR(_CORE_TIMER_VECTOR) my_int_handler(void)
I look at disassembly, and I see that RDPGPR SP, SP is called in the ISR prologue (first instruction, actually); and balancing WRPGPR SR, SR instruction is called in the ISR epilogue (before writing previously-saved Status register to CP0 and calling ERET).
I see that these instruction purposes are to read from and save to previous shadow register set, so, RDPGPR SP, SP reads $sp from shadow register set and WRPGPR SR, SR writes it back, but I can't understand the reason for this. This ISR intended not to use shadow register set, and actually in disassembly I see that context is saved to the stack. But, for some reason, $sp is read from and written to shadow $sp. Why is this?
And, related question: is there some really comprehensive resource (book, or something) on MIPS assembly language? "See MIPS Run" seems really good, it's great starting point for me to dig into MIPS architecture, but it does not cover several topics good enough, several things off the top of my head:
Very little information about EIC (external interrupt controller) mode: it has the diagram with Cause register that shows that in EIC mode we have RIPL instead of IP7-2, but there is nothing about how does it work (say, that interrupt is caused if only Cause->RIPL is more than Status->IPL. There's even no explanation what RIPL does mean ("Requested Interrupt Priority Level", well, Google helped). I understand that EIC is implementation-dependent, but the things I just mentioned are generic.
Assembly language is covered not completely enough: say, nothing about macro (.macro, .endm directives), I couldn't find anything about some assembler directives I've seen in the existing code, say, .set mips32r2, and so on.
I cant find anything about using rdpgpr/wrpgpr in the ISR, it covers these instructions (and shadow register sets in general) very briefly
Official MIPS reference doesn't help much in these topics as well. Is there really good book that covers all possible assembly directives, and so on?
When the MIPS core enters an ISR it can swap the interrupted code's active register set with a new one (there can be several different shadow register sets), specific for that interrupt priority.
Usually the interrupt routines don't have a stack of their own, and because the just switched-in shadow register set certainly have its sp register with a different value than the interrupted code's, the ISR copies the sp value from the just switched-out shadow register set to its own, to be able to use the interrupted code's stack.
If you wish, you could set your ISR's stack to a previously allocated stack of its own, but that is usually not useful.
How many stalls do I need to execute the following instructions properly. I am a little confused with what I did, so I am here to see experts answers.
lw $1,0($2);
beq $1,$2,Label;
Note that the check whether the branch will occur or not will be done in decoding stage. But the source register rs of beq which is $1 in this case will be updated after writeback stage of lw instruction. So do we need to forward new data from Memory in memory stage to Decoding stage of beq instruction.
Here is the data path diagram:
The value that is fetched from the memory, is written to the register file in the write-back stage of the pipeline. Writes to the register file happen in the first half of the clock cycle, while reads from the register file happen in the second half of the clock cycle.
The value that is written to the register file can thus be read in the same clock cycle as it is written to the register file. Thus forwarding is not effective here.
As for the number of stalls needed, you need to insert two bubbles into the pipeline, as the lw instruction should be in the write back stage when the beq instruction is in the decode stage.
I hope this answers your question.