This project implements an emulator for a custom processor architecture, adhering to principles of object-oriented programming (OOP), SOLID principles, and best practices for readable code. The correctness of all implemented features is tested using unit tests.
This emulator models a simple processor with the following components:
- Four 64-bit general-purpose registers
- Program Counter (PC)
- 64-bit address space, where each memory address holds 1 byte
The instruction set supports:
-
Arithmetic Operations:
ADDβ AdditionSUBβ SubtractionMULβ MultiplicationDIVβ Division
-
Bitwise Logical Operations:
AND,OR,NOT,XOR
-
Data Transfer Instructions:
MOVβ Supports both direct and indirect addressing
-
Control Flow Instructions (Unconditional & Conditional Branching):
JMP,JE,JNE,JGE,JL,CMP
-
I/O Instructions:
- Input from the keyboard into a register
- Output from a register to the screen
-
Processor Halt Instruction:
HALTβ Stops the emulator execution
-
Efficient Memory Usage
- Full access to the guest address space while minimizing host memory usage.
-
Cache Memory Simulation
- Configurable cache levels (e.g., L1, L2, L3).
- Set cache size, associativity, and line size per level.
- Track cache hit and miss rates for memory accesses.
- Support for cache replacement algorithms:
- LRU (Least Recently Used)
- Optimal (BΓ©lΓ‘dy) Algorithm
-
Unit Tests
- All core functionalities are tested with unit tests to ensure correctness.
Specifically tailored for a client using IntelliJ IDEA on any operating system:
First, download the project to your local machine:
git clone https://github.com/your-username/processor-emulator.git
cd processor-emulator- Launch IntelliJ IDEA.
- Navigate to
File > Openand select the project's root folder (processor-emulator). - Wait for IntelliJ to index the files and configure the project structure.
If you see red error lines in the code, you likely need to set your JDK:
- Go to
File > Project Structure > Project. - Ensure the SDK is set to Java 17 or newer (Java 21 is recommended).
- Under Libraries, if the tests are red, add JUnit 5 (Jupiter) by pressing
Alt+Enteron a red import in any test class and selecting "Add JUnit5 to classpath."
For the best experience, use the graphical interface:
- In the Project panel (left side), navigate to:
src/emulator/EmulatorGUI.java. - Right-click
EmulatorGUIand select Run 'EmulatorGUI.main()'. - Note: If you want a specific instruction file to load automatically on startup:
- Go to
Run > Edit Configurations. - In Program arguments, enter the path to your file (e.g.,
src/utility/Instructions.txt).
- Go to
- Load Program: Click the "Load fileβ¦" button in the top toolbar to select a
.txtfile containing your assembly instructions. - Simulation Controls:
- Step: Execute one instruction at a time to observe register and flag changes.
- Run: Start automatic execution (adjust the speed using the Speed slider).
- Reset: Clear the logs and return the CPU, Memory, and Cache to their initial states.
- Monitor State:
- Pipeline: Watch instructions flow through the different stages (IF β ID β EX β WB).
- Cache Hierarchy: Monitor hit rates and occupancy bars for the L1, L2, and L3 cache levels.
- Registers & Flags: View real-time updates for general-purpose registers and the status flags (Zero, Greater Than, Less Than).
CPU-Emulator/
β
βββ ARproject1/
β βββ src/ # Source code root
β βββ cache/ # Cache memory models and hierarchy
β βββ emulator/ # Emulator entry points (Console & GUI)
β β βββ Emulator.java # CLI version
β β βββ EmulatorGUI.java # Swing-based Graphical Interface
β βββ memory/ # Main memory simulation
β βββ processor/ # CPU core, registers, and opcode logic
β βββ test/ # JUnit 5 unit tests for all modules
β βββ utility/ # Helper classes and instruction loaders
β
βββ junit/ # External library dependencies
βββ out/ # Compiled bytecode (Build output)
βββ README.md # Project documentation
βββ .gitignore # Version control ignored files
- Cache Levels: Specify the number of cache levels (e.g., 1 to 3).
- Cache Size per Level: Set the size of each cache level in bytes.
- Cache Line Size: Define the size of a cache line.
- Associativity: Configure direct, set-associative, or fully associative caches.
- Replacement Algorithms:
- LRU β Evicts the least recently used line.
- Optimal β Uses the BΓ©lΓ‘dy algorithm for optimal line eviction.
Hereβs a simple example program that uses arithmetic and branching instructions:
MOV R1, 10 ; Load 10 into register R1
MOV R2, 20 ; Load 20 into register R2
ADD R3, R1, R2 ; Add R1 and R2, store result in R3
CMP R3, 30 ; Compare R3 with 30
JE END ; If R3 == 30, jump to END
HALT ; Stop the emulator
END: ; Label for the end of the program
MOV R4, 'H' ; Store character 'H' in R4
OUT R4 ; Print 'H' to the screen
The emulator provides detailed statistics on cache performance, including:
- Cache hit rate: Percentage of memory accesses served from the cache.
- Cache miss rate: Percentage of memory accesses that result in a cache miss.
Unit tests ensure the correctness of:
- Arithmetic and logic operations
- Data transfers and branching instructions
- Cache functionality and replacement algorithms
Run all unit tests using:
java -cp bin org.junit.runner.JUnitCore tests.ProcessorTest
A complete view of the dark-themed Java Swing GUI, including the code editor, status panels, and register displays.
Detailed view of the IF β ID β EX β WB pipeline stages and real-time Z / GT / LT flag indicators.
Visual breakdown of hit rates and occupancy bars for the L1, L2, and L3 cache levels during execution.
A close-up of the 4 general-purpose registers featuring decimal/hex values and change-highlighting.
The bottom panel showing the scrollable history of instructions and resulting values.
To demonstrate the functionality of the emulator:
- Load a sample program from the
examples/folder. - Configure the cache settings before execution.
- Observe the cache performance metrics and program output on the console.
Andrej TroΕΎiΔ Software Developer specializing in Backend Systems & Infrastructure
MIT License
Copyright (c) 2026 Andrej TroΕΎiΔ
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.