~600行ANSI C代码实现RISC-V CPU核
今天在GitHub上看到一个C语言项目,用大约600行代码实现了一个RISC-V CPU核,甚为感叹,分享一下。不管是学习C,还是学习RISC-V,这个项目都有非常高的学习价值,开源万岁!
rv
用 ANSI C 编写的RISC-V CPU 内核。
特征:
- RV32IMC用户级实现
- 通过 riscv 测试中所有支持的测试
- ~600 行代码
- 不使用任何大于 32 位的整数类型,即使对于乘法也是如此
- 简单 API(两个函数,加上您提供的两个内存回调函数)
- 无内存分配
应用程序接口
/* Memory access callbacks: data is input/output, return RV_BAD on fault, 0 otherwise */
typedef rv_res (*rv_store_cb)(void *user, rv_u32 addr, rv_u8 data);
typedef rv_res (*rv_load_cb)(void *user, rv_u32 addr, rv_u8 *data);/* Initialize CPU. */
void rv_init(rv *cpu, void *user, rv_load_cb load_cb, rv_store_cb store_cb);/* Single-step CPU. Returns 0 on success, one of RV_E* on exception. */
rv_u32 rv_step(rv *cpu);
用法
#include <stdio.h>
#include <string.h>#include "rv.h"rv_res load_cb(void *user, rv_u32 addr, rv_u8 *data) {if (addr - 0x80000000 > 0x10000) /* Reset vector is 0x80000000 */return RV_BAD;*data = ((rv_u8 *)(user))[addr - 0x80000000];return RV_OK;
}rv_res store_cb(void *user, rv_u32 addr, rv_u8 data) {if (addr - 0x80000000 > 0x10000)return RV_BAD;((rv_u8 *)(user))[addr - 0x80000000] = data;return RV_OK;
}rv_u32 program[2] = {/* _start: */0x02A88893, /* add a7, a7, 42 */0x00000073 /* ecall */
};int main(void) {rv_u8 mem[0x10000];rv cpu;rv_init(&cpu, (void *)mem, &load_cb, &store_cb);memcpy((void *)mem, (void *)program, sizeof(program));while (rv_step(&cpu) != RV_EECALL) {}printf("Environment call @ %08X: %u\n", cpu.pc, cpu.r[17]);return 0;
}
为rv编译程序
使用 riscv-gnu-toolchain 工具链和 rv链接脚本。
建议使用gcc命令行:
riscv64-unknown-elf-gcc example.S -nostdlib -nostartfiles -Tlink.ld -march=rv32imc -mabi=ilp32 -o example.o -e _start -g -no-pie
然后用obj工具将0x80000000起始的二进制代码生成能被rv加载的二进制文件:
riscv64-unknown-elf-objcopy -g -O binary example.o example.bin
支持的指令列表
参见 支持指令列表。
公众号 | FunIO
微信搜一搜 “funio”,发现更多精彩内容。
个人博客 | blog.boringhex.top
相关文章:
~600行ANSI C代码实现RISC-V CPU核
今天在GitHub上看到一个C语言项目,用大约600行代码实现了一个RISC-V CPU核,甚为感叹,分享一下。不管是学习C,还是学习RISC-V,这个项目都有非常高的学习价值,开源万岁! rv 用 ANSI C 编写的RISC…...
【从零学习python 】55.Python中的序列化和反序列化,JSON与pickle模块的应用
文章目录 序列化和反序列化JSON模块pickle模块进阶案例 序列化和反序列化 通过文件操作,我们可以将字符串写入到一个本地文件。但是,如果是一个对象(例如列表、字典、元组等),就无法直接写入到一个文件里,需要对这个对象进行序列…...
【C++】详解内存中的堆和栈
2023年8月20日,周日早上 感觉很多东西还没吃透,很多疑问还没解决。 这篇文章可能会不定期更新。 还没解释为什么栈的空间有限,而堆的空间很大 还没解释栈和堆在内存中的位置 ...... 目录 怎么申请栈空间语法举例说明 怎么申请堆空间语法…...
QCustomPlot横坐标为毫秒级的时间轴数据展示的实时刷新数据功能
头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimer>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();int realtime…...
STM32/AT32 MCO管脚输出时钟配置
前言:最近在学以太网通讯,发现RMII接口配置的时钟管脚有MCU自己输出,想要看看是怎么输出的,对此进行记录 1、交接项目项目上使用的是PA8管脚来输出时钟50MHZ,提供给上面refclk。 先看手册 PA8的复用功能具备将MCU时钟…...
“SRP模型+”多技术融合在生态环境脆弱性评价模型构建、时空格局演变分析与RSEI 指数的生态质量评价
近年来,国内外学者在生态系统的敏感性、适应能力和潜在影响等方面开展了大量的生态脆弱性研究,他们普遍将生态脆弱性概念与农牧交错带、喀斯特地区、黄土高原区、流域、城市等相结合,评价不同类型研究区的生态脆弱特征,其研究内容…...
【大虾送书第六期】搞懂大模型的智能基因,RLHF系统设计关键问答
目录 ✨1、RLHF是什么? ✨2、RLHF适用于哪些任务? ✨3、RLHF和其他构建奖励模型的方法相比有何优劣? ✨4、什么样的人类反馈才是好的反馈 ✨5、RLHF算法有哪些类别,各有什么优缺点? ✨6、RLHF采用人类反馈会带来哪些局…...
超越函数界限:探索JavaScript函数的无限可能
🎬 岸边的风:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 📚 前言 📘 1. 函数的基本概念 📟 1.1 函数的定义和调用 📟 1.2 …...
PHP实现轻量级WEB服务器接收HTTP提交的RFID刷卡信息并回应驱动读卡器显示播报语音
本示例使用的读卡器:RFID网络WIFI无线TCP/UDP/HTTP可编程二次开发读卡器POE供电语音-淘宝网 (taobao.com) <?php mb_http_output(utf-8); $port88; $socket socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $bool socket_bind($socket, "0.0.0.0",…...
Neo4j之with基础
WITH 语句在 Cypher 查询中用于将之前的查询结果传递给后续的查询操作。它可以用来控制查询的流程,并且常常与其他语句如 MATCH、RETURN、CREATE、DELETE 等一起使用。以下是一些常用的示例和解释: 基本用法: MATCH (p:Person) WITH p RETU…...
60页数字政府智慧政务大数据资源平台项目可研方案PPT
导读:原文《60页数字政府智慧政务大数据资源平台项目可研方案PPT》(获取来源见文尾),本文精选其中精华及架构部分,逻辑清晰、内容完整,为快速形成售前方案提供参考。 项目需求分析 项目建设原则和基本策略…...
循环神经网络RNN完全解析:从基础理论到PyTorch实战
目录 一、循环神经网络全解1.1 什么是循环神经网络网络结构工作原理数学模型RNN的优缺点总结 1.2 循环神经网络的工作原理RNN的时间展开数学表述信息流动实现示例梯度问题:梯度消失和爆炸总结 1.3 循环神经网络的应用场景文本分析与生成1.3.1 自然语言处理1.3.2 机器…...
【SA8295P 源码分析】52 - 答疑之 QNX 创建镜像、Android修改CMDLINE
【SA8295P 源码分析】52 - 答疑之 QNX 创建镜像、Android修改CMDLINE 一、QNX 侧创建 img 镜像二、QNX 侧指定只编译某一个版本三、Android定制修改selinux权限,user版本采用enforcing,userdebug版本permissive系列文章汇总见:《【SA8295P 源码分析】00 - 系列文章链接汇总》…...
网络安全法律
立法的必要性:网络渗透,网络入侵,网络诈骗,网上钓鱼侵犯知识产权,宣传恐怖主义,极端主义等伤害共鸣利益的行为越发猖狂 信息系统运维安全管理规定(范文)| 资料 过程: 14-16 草案初…...
Redis缓存问题(穿透, 击穿, 雪崩, 污染, 一致性)
目录 1.什么是Redis缓存问题? 2.缓存穿透 3.缓存击穿 4.缓存雪崩 5.缓存污染(或满了) 5.1 最大缓存设置多大 5.2 缓存淘汰策略 6.数据库和缓存一致性 6.1 4种相关模式 6.2 方案:队列重试机制 6.3 方案:异步更新缓…...
网络时代拟态环境的复杂化
信息在网络上的制作、编码、传播机制和传统媒介有本质的区别,即传播者和 受传者的角色交叉,而且互联网本身可看作另一个有别于现实环境的虚拟世界,因 此网络媒介所营造出的拟态环境在一定程度上独立于传统大众传播的拟态环境。 一个是传统…...
湘潭大学 湘大 XTU OJ 1055 整数分类 题解(非常详细)
链接 整数分类 题目 Description 按照下面方法对整数x进行分类:如果x是一个个位数,则x属于x类;否则将x的各位上的数码累加,得到一个新的x,依次迭代,可以得到x的所属类。比如说24,246&#…...
什么是视频的编码和解码
这段描述中,视频解码能力和视频编码能力指的是不同的处理过程。视频解码是将压缩过的视频数据解开并还原为可播放的视频流,而视频编码是将原始视频数据压缩成更小的尺寸,以减少存储空间和传输带宽。在这个上下文中,解码能力和编码…...
LeetCode 2681. Power of Heroes【排序,数学,贡献法】2060
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
AVL树的讲解
算法拾遗三十八AVL树 AVL树AVL树平衡性AVL树加入节点AVL删除节点AVL树代码 AVL树 AVL树具有最严苛的平衡性,(增、删、改、查)时间复杂度为O(logN),AVL树任何一个节点,左树的高度和右树的高度差…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
