零基础入门硬件,我花 30 天设计了一套 RISC-V 风格极简指令集 MinimaArch
项目背景
个人背景
我是 Michael-Hardy-2026,在此之前,我完全没有接触过计算机硬件。在 2025 年,我了解了 RISC-V 的设计过程后,诞生了设计自己的指令集架构(ISA)的想法。于是我开始深入学习计算机的底层知识,为接下来的设计工作奠定基础。
在 2026 年 3 月 1 日,这个 ISA 项目正式启动,采用 Apache 2.0 开源协议,命名为 MinimaArch。目前只有我一个人在推进这个 ISA 的开发。
MinimaArch 这个词源于 Minimalist 和 Architecture 两个词,前者表示简洁,后者表示架构。项目的核心设计理念就是简洁,但这不意味着简单,我们需要让架构保持正交性和统一性。
学习背景
在真正动手设计 MinimaArch 之前,我其实是完全零基础的硬件小白,既没有写过 Verilog,也没有系统学过计算机组成原理,更没有接触过任何一款 CPU 的微架构。
最开始只是对 RISC‑V 产生了好奇,我从最基础的资料开始看:先搞懂什么是指令集架构,什么是寄存器、指令格式、加载 / 存储体系、分支跳转逻辑。那段时间几乎每天都会抽 1–2 小时,一点点啃指令编码、操作码分配、立即数扩展这些以前完全陌生的概念。
一开始最大的困难是理解 “正交性” 到底意味着什么。我反复对比 RISC‑V 的几种指令格式,思考为什么要分成 R、I、S、B 这类格式,为什么寄存器编号要统一放在固定位置,为什么立即数要拆分编码。为了真正消化,我甚至在纸上手绘了好几版指令格式布局,不断推翻重排,直到自己觉得逻辑通顺、没有冗余。
之后我开始尝试抽象出自己的设计原则:
- 指令数量不求多,但每条都必须有明确用途
- 寄存器布局统一,降低编译器实现难度
- 立即数编码尽量规整,减少特殊情况
- 控制状态寄存器(CSR)保持简单,不做过度扩展
从模糊理解,到画出第一版指令格式草案,再到整理成 YAML 规范文件,大概花了将近一个月的碎片化学习。整个过程没有老师带,也没有现成的项目可以照搬,很多设计决策都是在 “查资料→思考→推翻→重设计” 的循环里慢慢定型。
等到 2026 年 3 月,我感觉整体思路已经足够清晰,才正式建立仓库,启动 MinimaArch 项目,把之前零散的思考全部沉淀为规范文档。
项目特点
简洁设计
指令集设计遵循简洁原则,减少冗余和复杂性。每一条指令都经过精心设计,只保留最核心的功能,避免过度设计。
正交架构
指令设计保持正交性,提高代码生成效率。各指令功能独立,组合灵活,使得编译器能够更高效地生成优化代码。
统一风格
整个架构保持一致的设计风格,从指令格式到寄存器定义,都遵循统一的规范和命名约定。
开源协议
采用 Apache 2.0 开源协议,鼓励社区参与和贡献,任何人都可以自由使用、修改和分发项目代码。
技术规范
指令格式
MinimaArch 支持多种指令格式,满足不同场景的需求:
- R 格式:32位寄存器-寄存器操作
- R4 格式:32位四寄存器操作
- I 格式:32位立即数操作
- S 格式:32位存储操作
- B 格式:32位分支操作
- U 格式:32位高位立即数操作
- J 格式:32位跳转操作
- JALR 格式:32位跳转并链接寄存器操作
- CSRI 格式:32位CSR立即数操作
指令集
当前实现的指令集包括:
- MA32I:32位整数指令集,包含基本算术逻辑运算、加载存储、分支跳转等操作
寄存器规范
MinimaArch 定义了三类寄存器:
- 通用寄存器 (x_regs):32个,用于整数操作
- 浮点寄存器 (f_regs):32个,用于浮点操作
- 向量寄存器 (v_regs):32个,用于向量操作
项目结构
MinimaArch/
├── docs/ # 项目文档
│ ├── fmt_chart.png # 指令格式图表
│ └── why.md # 项目背景说明
├── spec/ # 规范文件
│ ├── inst_set/ # 指令集规范
│ │ ├── fmts.yaml # 指令格式定义
│ │ └── inst/ # 具体指令定义
│ │ └── ma32i.yaml # MA32I指令集
│ └── reg/ # 寄存器规范
│ └── x&f&v_abi.yaml # 寄存器ABI定义
├── license.txt # 许可证文件
└── readme.md # 项目说明文件
下一步
设计 MA32I 的伪指令,编写简单模拟器。
后续开始对内存模型的探究。
如何参与
- 查看 contributing.md 文件了解贡献指南
- 提交 Issue 报告 bug 或提出新功能建议
许可证
本项目采用 Apache 2.0 开源许可证,详情请查看 license.txt 文件。
联系方式
- 作者:Michael-Hardy-2026
- 邮箱:michael-hardy-2026@outlook.com
感谢阅读!如果你对 MinimaArch 项目感兴趣,欢迎关注和参与!
如果你现在就有建议或其他想法,可以直接发在评论区,你的评论是我学习并设计 MinimaArch 道路上的重要指引。
附件:MinimaArch 32 位指令的 9 种格式,以及绘制这张图的脚本(可复制)
'''
field_png_printer.py
绘制指令的位图
'''
import matplotlib.pyplot as plt
import matplotlib.patches as patches
color_alpha = 0.25
src_words = [
{
'name': 'R-fmt',
'words': [
('funct7', 31, 25, 'purple'),
('rs2', 24, 20, 'blue'),
('rs1', 19, 15, 'green'),
('funct3', 14, 12, 'purple'),
('rd', 11, 7, 'red'),
('opcode', 6, 0, 'orange')
]
},
{
'name': 'R4-fmt',
'words': [
('funct2', 31, 30, 'purple'),
('rs3', 29, 25, 'yellow'),
('rs2', 24, 20, 'blue'),
('rs1', 19, 15, 'green'),
('funct3', 14, 12, 'purple'),
('rd', 11, 7, 'red'),
('opcode', 6, 0, 'orange')
]
},
{
'name': 'I-fmt',
'words': [
('imm[11:0]', 31, 20, 'pink'),
('rs1', 19, 15, 'green'),
('funct3', 14, 12, 'purple'),
('rd', 11, 7, 'red'),
('opcode', 6, 0, 'orange')
]
},
{
'name': 'S-fmt',
'words': [
('imm[11:5]', 31, 25, 'pink'),
('rs2', 24, 20, 'blue'),
('rs1', 19, 15, 'green'),
('funct3', 14, 12, 'purple'),
('imm[4:0]', 11, 7, 'pink'),
('opcode', 6, 0, 'orange')
]
},
{
'name': 'B-fmt',
'words': [
('imm[12]', 31, 31, 'pink'),
('imm[10:5]', 30, 25, 'pink'),
('rs2', 24, 20, 'blue'),
('rs1', 19, 15, 'green'),
('funct3', 14, 12, 'purple'),
('imm[4:1]', 11, 8, 'pink'),
('imm[11]', 7, 7, 'pink'),
('opcode', 6, 0, 'orange')
]
},
{
'name': 'U-fmt',
'words': [
('imm[31:12]', 31, 12, 'pink'),
('rd', 11, 7, 'red'),
('opcode', 6, 0, 'orange')
]
},
{
'name': 'J-fmt',
'words': [
('imm[20]', 31, 31, 'pink'),
('imm[9:1]', 30, 21, 'pink'),
('imm[11]', 20, 20, 'pink'),
('imm[19:12]', 19, 12, 'pink'),
('rd', 11, 7, 'red'),
('opcode', 6, 0, 'orange')
]
},
{
'name': 'JALR-fmt',
'words': [
('imm[12]', 31, 31, 'pink'),
('imm[10:1]', 30, 21, 'pink'),
('imm[11]', 20, 20, 'pink'),
('rs1', 19, 15, 'green'),
('funct3', 14, 12, 'purple'),
('rd', 11, 7, 'red'),
('opcode', 6, 0, 'orange')
]
},
{
'name': 'CSRI-fmt',
'words': [
('csr[11:0]', 31, 20, 'purple'),
('imm[4:0]', 19, 15, 'pink'),
('funct3', 14, 12, 'purple'),
('rd', 11, 7, 'red'),
('opcode', 6, 0, 'orange')
]
}
]
def draw_field_chart(data):
# 计算子图数量和布局
n = len(data)
rows = n # 每行1个图
cols = 1
# 创建画布和子图,增加右侧空间
fig, axs = plt.subplots(rows, cols, figsize=(10, rows * 0.8))
axs = axs.flatten() if n > 1 else [axs]
# 遍历每个指令格式
for i, fmt in enumerate(data):
ax = axs[i]
# 收集所有字段边界
field_boundaries_start = set()
field_boundaries_end = set()
for field in fmt['words']:
_, start, end, _ = field
field_boundaries_start.add(start)
field_boundaries_end.add(end)
# 绘制字段
for field in fmt['words']:
name, start, end, color = field
width = start - end + 1
x = end
y = 0
height = 0.4
if name.startswith('imm'):
name = name[3:]
# 绘制矩形
rect = patches.Rectangle((x, y), width, height, facecolor=color, alpha=color_alpha, edgecolor='black')
ax.add_patch(rect)
# 添加字段名称
ax.text(x + width/2, y + height/2, name, ha='center', va='center', fontsize=8)
# 在字段首尾两端的位上方添加数字
ax.text(start+0.5, 0.5, str(start), ha='center', va='bottom', fontsize=8)
ax.text(end+0.5, 0.5, str(end), ha='center', va='bottom', fontsize=8)
# 绘制不是字段边界的位边界竖线
for bit in range(32):
if bit not in field_boundaries_end:
# 绘制上下各0.02高度的竖线
ax.plot([bit, bit], [0, 0.02], color='black', linewidth=1)
ax.plot([bit, bit], [0.4, 0.38], color='black', linewidth=1)
# 设置x轴范围和标签
ax.set_xlim(32, 0)
ax.set_ylim(0, 0.8)
ax.set_xticks([])
ax.set_yticks([])
# 在右侧添加总标签
ax.text(-0.5, 0.2, fmt['name'], ha='left', va='center', fontsize=10, fontweight='bold')
# 隐藏多余的子图
for i in range(n, len(axs)):
axs[i].set_visible(False)
# 调整布局
plt.tight_layout()
plt.savefig('temp/field_chart.png')
#plt.show()
if __name__=='__main__':
draw_field_chart(src_words)