Browse by type
Interface-Driven OS Kernel for AI-Assisted Learning | Multi-Architecture: RISC-V 64, AArch64
🤖 Design Philosophy: Define clear kernel interfaces, let AI generate the implementation — a new paradigm for learning operating systems
SimpleKernel is a modern OS kernel project designed for AI-assisted learning. Written in C++23, it supports RISC-V 64 and AArch64 architectures.
Unlike traditional OS teaching projects, SimpleKernel adopts an Interface-Driven design:
.h/.hpp) containing class declarations, pure virtual interfaces, type definitions, and Doxygen documentation.cpp implementations from the interface docs| Feature | Description |
|---|---|
| 🤖 AI-First Design | Interface docs serve as prompts — AI can generate complete implementations directly from header files |
| 📐 Interface-Implementation Separation | Headers contain only declarations and contracts; implementations live in separate .cpp files |
| 🌐 Two-Architecture Support | RISC-V 64, AArch64 — one set of interfaces adapting to different hardware |
| 🧪 Test-Driven Verification | GoogleTest test suites verify whether AI-generated implementations conform to interface contracts |
| 📖 Complete Doxygen Documentation | Every interface has responsibility descriptions, preconditions, postconditions, and usage examples |
| 🏗️ Engineering Infrastructure | CMake build, Dev Container environment, CI/CD, clang-format/clang-tidy |
Traditional OS teaching projects follow: read code → understand principles → mimic and modify. This approach has several problems:
SimpleKernel proposes a new paradigm: read interface → understand contract → AI implements → test verifies
┌─────────────────────────────────────────────────────────┐
│ SimpleKernel Learning Flow │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 📐 Inter- │───▶│ 🤖 AI │───▶│ 🧪 Test │ │
│ │ face Hdrs │ │ Generates│ │ Verifies │ │
│ │ + Doxygen │ │ Impl │ │ Contract │ │
│ │ │ │ (.cpp) │ │ GoogleTest│ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │
│ │ ┌──────────┐ │ │
│ └────────▶│ 📚 Ref │◀─────────┘ │
│ │ Impl │ │
│ └──────────┘ │
└─────────────────────────────────────────────────────────┘
Each module's header file contains complete interface documentation:
/**
* @brief Interrupt subsystem abstract base class
*
* All architecture interrupt handlers must implement this interface.
*
* @pre Hardware interrupt controller has been initialized
* @post Can register interrupt handlers via RegisterInterruptFunc
*
* Known implementations: PLIC (RISC-V), GIC (AArch64)
*/
class InterruptBase {
public:
virtual ~InterruptBase() = default;
/// Execute interrupt handling
virtual void Do(uint64_t cause, cpu_io::TrapContext* context) = 0;
/// Register interrupt handler function
virtual void RegisterInterruptFunc(uint64_t cause, InterruptFunc func) = 0;
};
Provide the header file as context to an AI (e.g., GitHub Copilot, ChatGPT, Claude) and ask it to generate the .cpp implementation. The Doxygen comments in the interface are the best prompt.
Run the project's built-in test suite to verify the AI-generated implementation conforms to the interface contract:
cmake --preset build_riscv64
cd build_riscv64 && make unit-test
If tests fail, refer to the project's reference implementation for comparison and learning.
| Scenario | Usage |
|---|---|
| GitHub Copilot | Open the header file, let Copilot auto-complete the implementation in the corresponding .cpp |
| ChatGPT / Claude | Paste header file contents as context, request a complete .cpp implementation |
| Copilot Chat / Cursor | Select the interface in the IDE, ask AI to explain contract meaning or generate implementation |
| Self-Study | Think about the implementation first, then let AI generate it, and compare differences |
SimpleKernel's interfaces are organized into the following layers:
┌──────────────────────────────────────────┐
│ Application / Syscall Layer │
│ syscall.h · SyscallInit │
├──────────────────────────────────────────┤
│ Task Management Layer │
│ TaskManager · SchedulerBase · Mutex │
│ CfsScheduler · FifoScheduler · RR ... │
├──────────────────────────────────────────┤
│ Memory Management Layer │
│ VirtualMemory · PhysicalMemory │
│ MapPage · UnmapPage · AllocFrame │
├──────────────────────────────────────────┤
│ Interrupt / Exception Layer │
│ InterruptBase · RegisterInterruptFunc │
│ TimerInit · InterruptInit │
├──────────────────────────────────────────┤
│ Device Framework Layer │
│ DeviceManager · DriverRegistry │
│ PlatformBus · Ns16550aDriver · VirtioBlk │
├──────────────────────────────────────────┤
│ Architecture Abstraction (arch.h) │
│ ArchInit · InterruptInit · TimerInit │
│ EarlyConsole (auto-set during global │
│ construction phase) │
├──────────────────────────────────────────┤
│ Runtime Support Libraries │
│ libc (sk_stdio.h, sk_string.h, ...) │
│ libcxx (kstd_vector, __cxa_*, ...) │
├──────────────────────────────────────────┤
│ Hardware / QEMU │
│ RISC-V 64 · AArch64 │
└──────────────────────────────────────────┘
| Interface File | Responsibility | Implementation File |
|---|---|---|
src/arch/arch.h |
Architecture-independent unified entry | Each src/arch/{arch}/ directory |
src/include/interrupt_base.h |
Interrupt subsystem abstract base class | src/arch/{arch}/interrupt.cpp |
src/device/include/device_manager.hpp |
Device manager | header-only |
src/device/include/driver_registry.hpp |
Driver registry | header-only |
src/device/include/platform_bus.hpp |
Platform bus (FDT enumeration) | header-only |
src/device/include/driver/ns16550a_driver.hpp |
NS16550A UART driver | header-only (Probe/Remove pattern) |
src/include/virtual_memory.hpp |
Virtual memory management interface | src/virtual_memory.cpp |
src/include/kernel_fdt.hpp |
Device tree parsing interface | src/kernel_fdt.cpp |
src/include/kernel_elf.hpp |
ELF parsing interface | src/kernel_elf.cpp |
src/task/include/scheduler_base.hpp |
Scheduler abstract base class | cfs_scheduler.cpp etc. |
src/include/spinlock.hpp |
Spinlock interface | header-only (performance) |
src/include/mutex.hpp |
Mutex interface | src/task/mutex.cpp |
📋 See docs/TODO_interface_refactor.md for the complete interface refactoring plan.
| Architecture | Boot Chain | Serial | Interrupt Controller | Timer |
|---|---|---|---|---|
| RISC-V 64 | U-Boot + OpenSBI | SBI Call | Direct Mode | SBI Timer |
| AArch64 | U-Boot + ATF + OP-TEE | PL011 | GICv3 | Generic Timer |
Option 1: Using Dev Container (Recommended)
# 1. Clone the project
git clone https://github.com/simple-xx/SimpleKernel.git
cd SimpleKernel
# 2. Open in VS Code and reopen in container
# Install Dev Containers extension, click the >< icon at bottom-left
# Select "Reopen in Container"
# Or use CLI
npm install -g @devcontainers/cli
devcontainer up --workspace-folder .
devcontainer exec --workspace-folder . bash
Also supports GitHub Codespaces: Click Code → Codespaces → Create codespace on main
See Dev Container documentation for details.
Option 2: Local Environment
Refer to Toolchain Documentation for local development environment setup.
cd SimpleKernel
# Select target architecture (RISC-V 64 example)
cmake --preset build_riscv64
cd build_riscv64
# Build kernel
make SimpleKernel
# Run in QEMU emulator
make run
# Run unit tests (verify your implementation)
make unit-test
Supported Architecture Presets:
- build_riscv64 - RISC-V 64-bit architecture
- build_aarch64 - ARM 64-bit architecture
# 1. Open project in VS Code (GitHub Copilot extension recommended)
code ./SimpleKernel
# 2. Read interface definitions in header files (e.g., src/include/virtual_memory.hpp)
# 3. Create/edit the corresponding .cpp file, let AI generate implementation from the interface
# 4. Build and verify
cd build_riscv64 && make SimpleKernel
# 5. Run tests
make unit-test
# 6. Run in QEMU, observe behavior
make run
SimpleKernel/
├── src/ # Kernel source code
│ ├── include/ # 📐 Public interface headers (project core)
│ │ ├── virtual_memory.hpp # Virtual memory management interface
│ │ ├── kernel_fdt.hpp # Device tree parsing interface
│ │ ├── kernel_elf.hpp # ELF parsing interface
│ │ ├── spinlock.hpp # Spinlock interface
│ │ ├── mutex.hpp # Mutex interface
│ │ └── ...
│ ├── arch/ # Architecture-specific code
│ │ ├── arch.h # 📐 Architecture-independent unified interface
│ │ ├── aarch64/ # AArch64 implementation
│ │ └── riscv64/ # RISC-V 64 implementation
│ ├── device/ # Device management framework
│ │ ├── include/ # 📐 Device framework interfaces (DeviceManager, DriverRegistry, Bus, etc.)
│ │ │ └── driver/ # Concrete drivers (ns16550a_driver.hpp, virtio_blk_driver.hpp)
│ │ └── device.cpp # Device initialization entry (DeviceInit)
│ ├── task/ # Task management
│ │ ├── include/ # 📐 Scheduler interfaces (SchedulerBase, etc.)
│ │ └── ... # Scheduler implementations
│ ├── libc/ # Kernel C standard library
│ └── libcxx/ # Kernel C++ runtime
├── tests/ # 🧪 Test suite
│ ├── unit_test/ # Unit tests
│ ├── integration_test/ # Integration tests
│ └── system_test/ # System tests (QEMU-based)
├── docs/ # 📚 Documentation
│ ├── TODO_interface_refactor.md # Interface refactoring plan
│ └── ...
├── cmake/ # CMake build configuration
├── 3rd/ # Third-party dependencies (Git Submodule)
└── tools/ # Build tools and templates
Directories/files marked with 📐 are interface definitions — these are what you should focus on reading.
We recommend learning and implementing modules in the following order:
| Module | Interface File | Difficulty | Description |
|---|---|---|---|
| Early Console | src/arch/arch.h comments |
⭐ | Earliest output, understand global construction |
| Serial Driver | ns16550a_driver.hpp |
⭐⭐ |
$ claude mcp add SimpleKernel \
-- python -m otcore.mcp_server <graph>