Skip to content

Im-Min/MIPS-simulator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

MIPS Simulator

A progressive series of MIPS processor simulators demonstrating the evolution from a simple instruction interpreter to a fully pipelined processor with hazard detection.

Overview

This repository contains three versions of MIPS simulators, each building upon the previous one to demonstrate increasingly sophisticated processor architectures:

  • HW1: Basic instruction-level simulator with text-based assembly input
  • HW2: Single-cycle processor simulator with binary instruction support
  • HW3: Pipelined processor with hazard detection and pipeline stalls

Key Learning Outcomes

This project demonstrates:

  1. Instruction Set Architecture (ISA): Understanding how instructions are encoded and decoded
  2. Processor Datapath: How data flows through different stages of execution
  3. Control Logic: Generation and use of control signals
  4. Pipelining: Parallel execution of instructions for performance improvement
  5. Hazard Detection: Identifying and resolving data and control hazards
  6. Performance Trade-offs: Comparing sequential vs. pipelined execution

Each version builds upon the previous, showing the evolution from a simple interpreter to a modern pipelined processor architecture.

Project Structure

MIPS-simulator/
├── HW1_[Min]/                               # Version 1: Basic Simulator
│   ├── CA HW1/
│   │   ├── HW1_[3223763]_[seok_min_Lim].c  # Simple instruction simulator
│   │   └── example.txt                      # Assembly input file
│   ├── HW1_[32213763]_[임석민]_document.pdf
│   └── MIPS_Green_Sheet.pdf
│
├── HW2_[Min]/                               # Version 2: Single-Cycle
│   ├── CA HW2/
│   │   ├── 소스.cpp                         # Single-cycle processor
│   │   ├── input1.bin                       # Binary test programs
│   │   └── input2.bin
│   └── HW2_32213763_임석민_document.pdf
│
└── HW3_[Min]/                               # Version 3: Pipelined
    ├── 소스.cpp                             # Pipelined processor with hazard detection
    ├── input1.bin                           # Binary test programs
    └── input2.bin

Version Comparison

HW1: Basic Instruction Simulator

Architecture: Sequential instruction execution

Key Features:

  • Text-based assembly language input
  • 10 general-purpose registers (r0-r9)
  • Simple instruction-by-instruction execution
  • Custom instruction format with line numbers
  • Direct register manipulation

Supported Instructions:

  • Arithmetic: ADD, SUB, MUL, DIV
  • Data Movement: MOV, LW, SW
  • Comparison: SLT
  • Control Flow: BEQ, BNE, JMP
  • Utility: RST (reset registers)

Input Format: Human-readable assembly (e.g., 1: ADD r0 r1 r2)

Use Case: Learning basic instruction set architecture concepts


HW2: Single-Cycle Processor

Architecture: Single-cycle datapath with five functional stages

Key Features:

  • Binary machine code execution (.bin files)
  • 32 MIPS registers (full MIPS register file)
  • Complete control unit with control signal generation
  • Five execution stages executed sequentially per instruction:
    • F1_If: Instruction Fetch
    • F2_Id: Instruction Decode & Register Read
    • F3_Ex: Execute/ALU Operation
    • F4_Mem: Memory Access
    • F5_Wb: Write Back
  • Big-endian memory organization
  • Proper ALU operations with multiplexers
  • Support for R-type, I-type, and J-type instructions

Additional Instructions:

  • Shift operations: SLL, SRL
  • Logical operations: AND, OR, NOR
  • Jump operations: J, JAL, JR
  • Signed/unsigned variants: ADDU, SUBU, SLTU

Input Format: MIPS binary machine code

Performance: CPI = 5 (5 stages per instruction, sequential execution)

Use Case: Understanding single-cycle processor design and control signals


HW3: Pipelined Processor with Hazard Detection

Architecture: 5-stage pipeline with hazard detection and stalling

Key Features:

  • True pipelined execution (multiple instructions in flight)
  • Pipeline registers between stages:
    • IF/ID: Instruction Fetch to Decode
    • ID/EX: Decode to Execute
    • EX/MEM: Execute to Memory
    • MEM/WB: Memory to Write Back
  • Data hazard detection and resolution:
    • Detects RAW (Read-After-Write) hazards
    • Automatic pipeline stalling when hazards detected
    • Bubble insertion for control hazards
  • Control hazard handling for branches
  • Pipeline forwarding logic
  • Separate pipeline stage execution per clock cycle

Pipeline Stages:

  1. F1_If (IF): Instruction fetch from memory
  2. F2_Id (ID): Decode instruction, read registers, detect hazards
  3. F3_Ex (EX): Execute ALU operations
  4. F4_Mem (MEM): Access data memory, handle branches
  5. F5_Wb (WB): Write results back to registers

Hazard Detection:

  • Load-use hazards: Automatic stall insertion
  • Branch hazards: 3-cycle stall for proper resolution
  • Data dependencies: Detection across pipeline stages
  • Register dependency tracking

Input Format: MIPS binary machine code (same as HW2)

Performance:

  • Ideal CPI ≈ 1 (with no hazards)
  • Actual CPI > 1 (due to pipeline stalls)
  • Much faster than HW2 for long instruction sequences

Use Case: Understanding modern pipelined processor design, hazard detection, and performance optimization


Comparison Table

Feature HW1 HW2 HW3
Execution Model Sequential Single-Cycle Pipelined
Input Format Text Assembly Binary Binary
Registers 10 custom 32 MIPS 32 MIPS
Pipeline Stages None 5 (sequential) 5 (parallel)
Hazard Detection N/A N/A Yes
CPI Variable 5 ~1-2
Memory Model Abstract Big-endian Big-endian
Control Unit Switch-case Full control signals Full + hazard logic
Performance Slowest Moderate Fastest
Complexity Low Medium High
Instructions Supported 12 basic 20+ MIPS 20+ MIPS
Branch Handling Immediate Immediate With stalls
Language C C++ C++

Evolution Summary

  1. HW1 → HW2: Transition from educational simulator to realistic processor

    • Added proper MIPS ISA support
    • Implemented control unit and datapath
    • Binary instruction execution
    • Full register file
  2. HW2 → HW3: Optimization through pipelining

    • Parallel instruction execution
    • Pipeline registers for stage separation
    • Hazard detection and resolution
    • Significant performance improvement
    • Closer to real processor design

Building

All three versions are configured as Visual Studio C/C++ projects.

HW1 (Basic Simulator)

Visual Studio:

  1. Open HW1_[Min]/CA HW1.sln
  2. Build the solution (F7)
  3. Executable: HW1_[Min]/x64/Debug/CA HW1.exe

Command Line:

gcc -o hw1_simulator "HW1_[Min]/CA HW1/HW1_[3223763]_[seok_min_Lim].c" -lm
./hw1_simulator

HW2 (Single-Cycle Processor)

Visual Studio:

  1. Open HW2_[Min]/CA HW2/CA HW2.vcxproj
  2. Build the solution (F7)
  3. Executable: HW2_[Min]/CA HW2/x64/Debug/CA HW2.exe

Command Line:

g++ -o hw2_simulator "HW2_[Min]/CA HW2/소스.cpp" -lm
./hw2_simulator

HW3 (Pipelined Processor)

Visual Studio:

  1. Open HW3_[Min]/CA HW3.vcxproj
  2. Build the solution (F7)
  3. Executable: HW3_[Min]/x64/Debug/CA HW3.exe

Command Line:

g++ -o hw3_simulator "HW3_[Min]/소스.cpp" -lm
./hw3_simulator

Usage

HW1: Basic Simulator

Input: Text file with assembly instructions

  1. Create or modify example.txt with assembly code
  2. Update filename in source code if needed (line 56):
    const char* filename = "example.txt";
  3. Run: ./hw1_simulator

Input Format: Line-numbered assembly instructions

line_number: OPCODE operand1 operand2 operand3

Example (example.txt):

1: LW r0 0x1
2: LW r1 0x2
3: ADD r2 r0 r1
4: SW r2 STDOUT

HW2 & HW3: Binary Simulators

Input: Binary machine code files (.bin)

  1. Prepare MIPS binary file (or use provided input1.bin, input2.bin)
  2. Update filename in source code if needed:
    fopen_s(&file, "input2.bin", "rb")
  3. Run: ./hw2_simulator or ./hw3_simulator

Input Format: MIPS 32-bit instructions in big-endian binary format

Note: HW2 and HW3 use the same input format but produce different execution traces due to pipelining

Output Examples

HW1 Output

The HW1 simulator prints each instruction as it executes, along with register value changes:

1: LW r0 0x1
LW r[0]: -1 -> 1

2: LW r1 0x2
LW r[1]: -1 -> 2

3: ADD r2 r0 r1
ADD r[2]: -1 -> 3

...

For branch instructions, it indicates whether the branch was taken:

BEQ         # Branch taken
skip BEQ    # Branch not taken

HW2 Output

HW2 shows detailed execution through each stage with control signals:

0
pc: 0       inst: 3c011001
addiu rs:0 rt:1 imm:4097
data1: 0     data2:1001
ALU Result: 1001
No memory access
reg[1] write data: 1001
Next Pc: 4
=====================================

Each cycle shows:

  • Program counter and fetched instruction
  • Decoded instruction with operands
  • ALU inputs and result
  • Memory operations (if any)
  • Register write-back
  • Next PC value

HW3 Output

HW3 displays pipeline stage execution with hazard detection:

Cycle[0]
 [IF]
  [IM] PC:0X0 -> 0X3C011001
  [PC Update] PC <- 0X4 = 0X0+4
 [ID]
 [EX]
 [MEM]
  None
 [WB]
  None
=====================================

Cycle[1]
 [IF]
  [IM] PC:0X4 -> 0X34210000
  [PC Update] PC <- 0X8 = 0X4+4
 [ID]
  type: I, opcode: 0XF (Addiu), rs: 0X0 (R[0]=0X0), rt: 0X1 (R[1]=0X0), imm: 0X1001
 [EX]
 [MEM]
  None
 [WB]
  None
=====================================

Cycle[2]
...
  [Data Hazard] Stall    # Pipeline stall detected
...

Shows:

  • Cycle-by-cycle pipeline progress
  • Each stage's operations
  • Data hazard detection and stalls
  • Register updates at write-back stage

Implementation Details

HW1: Data Structures

struct instruction {
    enum opcodes opcode;
    int jump;              // Target line number
    int present;           // Current line number
    int r[3];              // Register indices
    int registers[13];     // Register values (0-9 general, 10-12 temp)
};

Execution Flow:

  1. Read text instruction from file
  2. Parse instruction with buffer2Inst()
  3. Execute with process() using switch-case
  4. Update registers and jump counter
  5. Move to next instruction or jump target

HW2: Data Structures

typedef struct {
    // Control signals for datapath
    unsigned int RegDst, ALUSrc, MemtoReg;
    unsigned int RegWrite, MemRead, MemWrite;
    unsigned int Branch, Bcond, ALUOp, Jump;
} ControlSignals;

typedef struct {
    // Decoded instruction fields
    unsigned int opcode, rs, rt, rd;
    unsigned int shamt, funct, imm, addr;
} Operands;

Execution Flow (Sequential 5-stage):

  1. F1_If: Fetch 32-bit instruction from memory
  2. F2_Id: Decode opcode, extract operands, generate control signals
  3. F3_Ex: Execute ALU operation, evaluate branches
  4. F4_Mem: Load/store data in memory
  5. F5_Wb: Write result to register file, update PC

HW3: Data Structures

// Pipeline registers to pass data between stages
typedef struct {
    unsigned int in;       // Valid bit
    unsigned int savePC;   // Saved program counter
    unsigned int inst;     // Instruction
} IF_ID;

typedef struct {
    unsigned int in;
    ControlSignals* cs;
    unsigned int savePC, rt, rd, imm;
    unsigned int readData1, readData2;
    unsigned int shamt, funct, addr, opcode;
} ID_EX;

typedef struct {
    unsigned int in;
    ControlSignals* cs;
    unsigned int savePC, aluResult, zero;
    unsigned int writeData, writeRegister;
    unsigned int opcode, jumpAddr;
} EX_MEM;

typedef struct {
    unsigned int in;
    ControlSignals* cs;
    unsigned int readData, aluResult;
    unsigned int writeRegister, opcode;
} MEM_WB;

Pipelined Execution (Parallel 5-stage):

  1. F1_If: Fetch instruction, increment PC
  2. F2_Id: Decode, detect hazards, possibly stall
  3. F3_Ex: Execute ALU operation
  4. F4_Mem: Memory access, handle branches
  5. F5_Wb: Write back to registers

Hazard Detection Logic:

  • Compares source registers with destination registers in pipeline
  • Inserts stalls (bubbles) when hazards detected
  • Prevents incorrect data reads from pipeline registers

Notes

General

  • HW2 and HW3 use 4GB memory allocation (may require 64-bit system)
  • All versions support big-endian byte ordering for memory operations
  • Register 0 ($zero) is hardwired to 0 in HW2 and HW3
  • Register 31 ($ra) initialized to 0xFFFFFFFF for return address
  • Register 29 ($sp) initialized to 0x1000000 for stack pointer

HW1 Specific

  • All registers initialized to -1
  • Immediate values can be hexadecimal (0x prefix) or decimal
  • Division by zero not handled
  • Line numbers required in input file

HW2 & HW3 Specific

  • Requires binary machine code input
  • Supports sign extension for immediate values
  • Proper handling of signed/unsigned operations
  • Memory addresses must be word-aligned (4-byte boundaries)

Performance Considerations

  • HW1: Best for learning basic ISA concepts
  • HW2: Educational tool for understanding processor stages
  • HW3: Demonstrates real-world processor optimizations
  • HW3 significantly outperforms HW2 on large programs due to pipelining

License

This is an academic project for Computer Architecture coursework.

Author

Seok Min Lim (Student ID: 3223763)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •