DEV Community

Ando
Ando

Posted on

A 5th stage game

I Built a 5-Stage Pipeline Game in Python — And Finally Lost to My Own Branch Predictor

When I started CS101: Introduction to Programming on Codecademy, the portfolio project sounded simple: "Build a basic terminal game."
Everyone was making Blackjack and Tic-Tac-Toe. I wanted something that actually teaches how computers really think. So I remembered my previous project - building a CPU from scratch - and thought: what if I turn the CPU's biggest enemy into a game?

Introducing PIPELINE PANIC - CPU Hazard Defender. You're a Pipeline Engineer and your job is to keep a 5-stage pipeline alive while hazards try to kill it.

The Result (Proof it Works)
Here's my game running a real program with RAW hazards and branch
mispredictions: ![
 - Pipeline Panic running Cycle 5 with forwarding and stall detection]

This is actual terminal output from python main.py (Menu 2 - PLAY): It loads instructions from program.asm or from interactive input:

  1. It runs a full IF → ID → EX → MEM → WB simulation
  2. It shows Stalls, Flushes, Forwarding in real-time
  3. It tracks Branch Predictor Accuracy live - in this run, 75.0%!

Yes, I tied with a 2-bit saturating counter. That's humbling.

How My Python Code Works
I split the game into 5 core OOP modules to meet the Codecademy requirement for clean architecture - just like real hardware:

  1. AssemblyParser (The File Parser) A 3-pass parser pipeline - yes, a pipeline inside a pipeline simulator:
  • Pass 1: Collect all labels ( LOOP: , TARGET: )
  • Pass 2: Tokenize with strict Regex for R-type ( ADD R1,R2,R3 ), I-type ( LW R5,R2,100 ), B-type ( BEQ ), J-type
  • Pass 3: Resolve label → instruction index, with nice error reporting:

It supports # comments , empty lines, and both file and text input.

  1. HazardDetectionUnit + ForwardingUnit (The Brains) This is the part that makes decisions by itself - the "otak" I wanted: Two Big-O implementations for education: detect_naive() - O(n²) - checks every pair in the 3-instruction window detect_optimized() - O(n) - uses a last_write hashmap Benchmark in Menu 1 shows O(n) is ~40% faster even for 7 instructions. Imagine for 1000.

The ForwardingUnit automatically decides if it can forward EX→EX or MEM→EX or must insert a bubble.

  1. BranchPredictor (The One That Beat Me)
    This is the "nebak cabang" brain. It implements 3 strategies:
    always_taken
    always_not_taken
    2-bit - 4-state FSM: Strong NT (00) → Weak NT (01) → Weak T (10) → Strong T (11)
    It learns from history and tracks its own accuracy. In Battle Mode, you play against it.
    Spoiler: it's good.

  2. CPUPipeline (The 5-Stage Pipeline)
    Classic RISC pipeline:
    1 IF (Fetch) → ID (Decode) → EX (Execute) → MEM → WB
    Each step() moves pipeline registers. It handles stalls and flushes:

  1. GameEngine (The Terminal Game) Meets Codecademy's input() requirement with 5 modes:
  2. LEARN - Big-O demo + hazard visualization
  3. PLAY - Live pipeline visualization
  4. CHALLENGE - Compiler optimization puzzle: reorder instructions to minimize stalls (my favorite - you have ADD R1,R2,R3 / SUB R4,R1,R5 / ADD R6,R7,R8 and you must move the independent one up!)
  5. BATTLE - You vs 2-bit predictor
  6. PARSER - Load your own .asm file

Check Out The Code
All the code is open source and ready to run. I fixed the Git case from last time, but
this time I fought with program.asm not being found - classic Windows PowerShell
moment!
GitHub: https://github.com/ikaroshunt/pipeline_panic.git (create this repo!)

To run it yourself:

Files:
main.py - All-in-one game (OOP, Pipeline, Brains, Parser)
program.asm - Sample program with intentional hazards

Conclusion
My first CPU simulator taught me why cache exists. This one taught me why pipelines are hard. I finally understand:
Why a simple ADD can stall the whole CPU (RAW hazard)
Why branch prediction is 30% of CPU performance
Why O(n) vs O(n²) matters when you check hazards for thousands of
instructions
Why forwarding is cheaper than stalling

It was frustrating at first - ParseError: Undefined label LOOP (yes, I forgot to
define my own label!), fatal: pathspec did not match , and tying with my own
AI. But each error was a lesson.
If you're taking CS101, don't just make Blackjack. Make something that makes you
lose to your own code. There's no better feeling than seeing === Cycle 10 ===
Stalls=2 and knowing you built that logic.
This project was built as part of Codecademy's Computer Science Career Path
(CS101: Python Terminal Game Portfolio Project) - Level 2 of my CPU series.

Tools: Python 3, Git, VS Code, PowerShell, OOP, Big-O Analysis, 2-bit Branch
Prediction

Top comments (1)

Collapse
 
pepapepa profile image
pepapepa •

What does cara menjalankan mean?
How to run?