W05 — Pipeline Implementation in Java
As mentioned in my previous post, this week I will be working on source codes for the 5 classic stage of RISC (Reduced Instruction Set Computer) pipeline which includes fetch, decode, execute, memory access and writeback. But before I get my hand started on these, I was reminded by supervisor to generate documentation for my source code (basic processor class) so that outsider (or including I myself) could understand the code well int future by reading on the comments and then the codes is push to release using git flow. Eclipse itself has it’s own documentation format installed where you only need to type “/**” and enter, the documentation format is out.
The main purpose of pipelining of microprocessor is to process instructions set simultaneously at various stage execution. As we know computer only machine language and thus each instruction need to be “break up” across multiple clock cycles (in this case is 5). One complete pipeline process (5 clock cycle) only work on one instruction at a time. The 5 classical stage of RSC pipeline are:
FETCH (IF) — A 32 bits instruction is fetch from memory based on the program counter (PC). Program counter is a register where its function is to hold the address of the current instruction. While undergoing the fetching process, the PC will predict the address of next instruction by incrementing the PC by 4 as all instructions were in 4 bytes long.
DECODE (ID) — Once the instruction is fetched, it then will be shifted to the next pipeline stage that is decode stage. This stage basically is to translate opcode into control signals by determines the control signals for the rest of the pipeline stages and selects the proper immediate values from the instruction and read register files based on the instructions fetched.
EXECUTE (EX) — This is the stage where the actual computation occurs. It consists of Arithmetic and Logic unit, a bit of shifter, compute jump/branch target if necessary and may also include a multiple cycle multiplier and divider. Arithmetic and Logic Unit (ALU) responsible for performing boolean operations (AND/OR/NOT/NAND/NOR/XOR/XNOR) and also integer addition and subtraction. Bit shifter is responsible for shift and rotations. Based on the type of operation, we could later divide instruction into 3 latency classes: register-register operation; Memory reference and finally multi-cycle instructions.
MEMORY ACCESS (MEM)– This stage is optional. It will only be used if data memory needs to be access. During this stage, it read EX/MEM pipeline register to get values and control bits and later perform memory load and store if needed. Single cycle latency instructions simply have their results forwarded to the next stage. This forwarding will ensures that both single and two cycle instructions always write their results in the same stage of the pipeline (MEM/WB), so that just one write port to the register file can be used, and it is always available.
WRITEBACK (WB) — In this stage, it read MEM/WB pipeline register to get values and control bits so that both single and 2 cycle instructions write their result into register file and thus register file is updated.
Below diagram shows the pipelined implementation data path to give a clearer picture.
I have completed on fetch, decode and writeback stage source codes. Fetch and writeback stages are consider easy to structure whereas for decode stage I faced a little problem. When I am figuring out how to return multiples values in decode method, I found out that there is impossible to do so. To solve this, I am enlighten by supervisor to create another value holder class to “hold” the values of decode method and return back to it as an object. This method seems more approachable to return multiple values and thus after discussing with supervisor, it is better to encapsule all values need to be return to this value holder class and later call from this class. It actually acted like a “mini-bank”. The little tricky part of this decode stage is that I also need to separate the instructions into either type A or type B by identify its 2nd MSB. Thus masking technique is used. The different between these 2 type is that type A instructions have up to 2 source register operands (ra & rb) and 1 destination register operand (rd) whereas type B instructions have 1 source register (ra), single destination rgister (rd) and a 16 bits immediate operand ((imm)-which can be extends to 32 bits by preceding the type B instruction with an IMM instruction).
Currently I am working on Execute stage. It take more time to figure out on this stage as I need to differentiate and group the instruction sets base on their functional categories so that each instruction can be execute correctly. To avoid more self-confusion, the instruction sets that I need to process is actually the simplified version which consists around 90+ instruction types as provided in the MicroBlaze Processor Reference Guide attachment version 3.2. These are the basic of course and can add on more in future if necessary. Beside execute stage that is in the process, I still have one more stage need to be complete that is memory access which will be bringing forward to next week task.