当前位置: 首页 > news >正文

QtRVSim(二)一个 RISC-V 程序的解码流程

继上一篇文章简单代码分析后,本文主要调研如何实现对指令的解析运行。

调试配置

使用 gdb 工具跟踪调试运行。

image-20240124233037109

c_cpp_properties.json 项目配置:

{"name": "QtRvSim","includePath": ["${workspaceFolder}/**"],"defines": [],"compilerPath": "/usr/bin/clang","cStandard": "c11","cppStandard": "c++17","intelliSenseMode": "gcc-x64","configurationProvider": "ms-vscode.cmake-tools"}

launch.json:

{// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。`                                                          // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387"version": "0.2.0","configurations": [{"name": "(gdb) Launch","type": "cppdbg","request": "launch",// "program": "${fileDirname}/${fileBasenameNoExtension}","program": "${command:cmake.launchTargetPath}","args": ["/home/jingqing3948/Develop/qtrvsim-test/sum2vars-riscv"],"stopAtEntry": false,"cwd": "${workspaceFolder}","environment": [{"name": "PATH","value":"${env:PATH):${command:cmake.getLaunchTargetDirectory]"}],"externalConsole": true,"MIMode": "gdb","setupCommands": [{"description": "Enable pretty-printing for gdb","text": "-enable-pretty-printing","ignoreFailures": true}],//"preLaunchTask": "Tutorial",  "miDebuggerPath": "/usr/bin/gdb"}]
}

程序解析流程

由于我的毕设任务主要是实现 F 扩展,因此我集中精力于对于指令集的解码、执行、写回过程,对于取指过程不同扩展区别不大暂不过多关注。

程序执行流程跟踪分析:

//main.cppint main(int argc, char *argv[]) {//省略一系列预配置,在 machine.play() 函数中执行程序machine.play();}
void Machine::play() {//set status//start execute each instructionsstep_internal(true);
}void Machine::step_internal(bool skip_break) {//set statustry {QTime start_time = QTime::currentTime();do {//execute one step cr->step(skip_break);} while (time_chunk != 0 && stat == ST_BUSY && !skip_break&& start_time.msecsTo(QTime::currentTime()) < (int)time_chunk);} catch (SimulatorException &e) {//set trapped status}if (regs->read_pc() >= program_end) {//set exit status} else {//set status as the previous status}
}
//core.cpp//step(): wrapper of do_step() function
void Core::step(bool skip_break) {//pcstate.cycle_count++;do_step(skip_break);emit step_done(state);
}void CoreSingle::do_step(bool skip_break) {Pipeline &p = state.pipeline;p.fetch = fetch(pc_if, skip_break);p.decode = decode(p.fetch.final);p.execute = execute(p.decode.final);p.memory = memory(p.execute.final);p.writeback = writeback(p.memory.final);regs->write_pc(mem_wb.computed_next_inst_addr);if (mem_wb.excause != EXCAUSE_NONE) {handle_exception(mem_wb.excause, mem_wb.inst, mem_wb.inst_addr, regs->read_pc(), prev_inst_addr,mem_wb.mem_addr);return;}prev_inst_addr = mem_wb.inst_addr;
}

由此可见,对于F扩展的实现,除去新硬件的实现,主要需要补充的就是 Pipeline.decode() , Pipeline.execute() , Pipeline.memory() , Pipeline.writeback() 以上内容。

首先我需要先实现 F 指令集的 decode。单条指令解码由

//core.cppDecodeState Core::decode(const FetchInterstage &dt) {InstructionFlags flags;bool w_operation = this->xlen != Xlen::_64;AluCombinedOp alu_op {};AccessControl mem_ctl;ExceptionCause excause = dt.excause;// decode后把结果存在flags alu_op mem_ctl结构体里,也就是说指令解码具体实现由 instructions.cpp 的 flags_alu_op_mem_ctl 函数实现dt.inst.flags_alu_op_mem_ctl(flags, alu_op, mem_ctl);//flags结构体通过位域操作识别rs rd op等信息,并返回
}
//instructions.cppvoid Instruction::flags_alu_op_mem_ctl(InstructionFlags &flags,AluCombinedOp &alu_op,AccessControl &mem_ctl) const {//通过 InstructionMapFind 函数查找指令表const struct InstructionMap &im = InstructionMapFind(dt);flags = (enum InstructionFlags)im.flags;alu_op = im.alu;mem_ctl = im.mem_ctl;
}static inline const struct InstructionMap &InstructionMapFind(uint32_t code) {const struct InstructionMap *im = &C_inst_map[instruction_map_opcode_field.decode(code)];//递归解码,和指令集在程序中的存储方式有关while (im->subclass != nullptr) {im = &im->subclass[im->subfield.decode(code)];}if ((code ^ im->code) & im->mask) {return C_inst_unknown;}return *im;
}

也就是说对于一条指令,首先需要根据 instruction_map_opcode_field.decode(code) 判断其操作码类型,然后用对应操作码的解码表 C_inst_map 元素进行解码。并且解码是递归进行的,因为解码表的存储方式是递归存储(先大类后小类,比如 I_inst_map 下的 load 指令全部属于 LOAD_map ,包括 lb lh lw 等。)

C_inst_map 解码表目前只包含了 i 扩展的指令集,对于 F 扩展实现从 C_inst_map 开始参照 I 扩展逐层实现。

static const struct InstructionMap C_inst_map[] = {IM_UNKNOWN,IM_UNKNOWN,IM_UNKNOWN,{"i", IT_UNKNOWN, NOALU, NOMEM, I_inst_map, {}, 0x3, 0x3, { .subfield = {5, 2} }, nullptr},
};static const struct InstructionMap I_inst_map[] = {{"load", IT_I, NOALU, NOMEM, LOAD_map, {}, 0x03, 0x7f, { .subfield = {3, 12} }, nullptr}, // LOADIM_UNKNOWN, // LOAD-FPIM_UNKNOWN, // custom-0{"misc-mem", IT_I, NOALU, NOMEM, MISC_MEM_map, {}, 0x0f, 0x7f, { .subfield = {3, 12} }, nullptr}, // MISC-MEM{"op-imm", IT_I, NOALU, NOMEM, OP_IMM_map, {}, 0x13, 0x7f, { .subfield = {3, 12} }, nullptr}, // OP-IMM{"auipc", IT_U, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"d", "u"}, 0x17, 0x7f, { .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE | IMF_PC_TO_ALU }, nullptr}, // AUIPC{"op-imm-32", IT_I, NOALU, NOMEM, OP_IMM_32_map, {}, 0x1b, 0x7f, { .subfield = {3, 12} }, nullptr}, // OP-IMM-32    IM_UNKNOWN, // OP-IMM-32IM_UNKNOWN, // 48b{"store", IT_I, NOALU, NOMEM, STORE_map, {}, 0x23, 0x7f, { .subfield = {3, 12} }, nullptr}, // STOREIM_UNKNOWN, // STORE-FPIM_UNKNOWN, // custom-1{"amo", IT_R, NOALU, NOMEM, AMO_map, {}, 0x2f, 0x7f, { .subfield = {3, 12} }, nullptr}, // OP-32{"op", IT_R, NOALU, NOMEM, OP_map, {}, 0x33, 0x7f, { .subfield = {1, 25} }, nullptr}, // OP{"lui", IT_U, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"d", "u"}, 0x37, 0x7f, { .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE }, nullptr}, // LUI{"op-32", IT_R, NOALU, NOMEM, OP_32_map, {}, 0x3b, 0x7f, { .subfield = {1, 25} }, nullptr}, // OP-32IM_UNKNOWN, // 64bIM_UNKNOWN, // MADDIM_UNKNOWN, // MSUBIM_UNKNOWN, // NMSUBIM_UNKNOWN, // NMADDIM_UNKNOWN, // OP-FPIM_UNKNOWN, // reservedIM_UNKNOWN, // custom-2/rv128IM_UNKNOWN, // 48b{"branch", IT_B, NOALU, NOMEM, BRANCH_map, {}, 0x63, 0x7f, { .subfield = {3, 12} }, nullptr}, // BRANCH{"jalr", IT_I, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"d", "o(s)"}, 0x67, 0x7f, { .flags =
IMF_SUPPORTED | IMF_REGWRITE | IMF_BRANCH_JALR | IMF_ALUSRC | IMF_ALU_REQ_RS }, inst_aliases_jalr}, // JALRIM_UNKNOWN, // reserved{"jal", IT_J, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"d", "a"}, 0x6f, 0x7f, { .flags =
IMF_SUPPORTED |
IMF_REGWRITE | IMF_JUMP | IMF_PC_TO_ALU | IMF_ALUSRC }, inst_aliases_jal}, // JAL{"system", IT_I, NOALU, NOMEM, SYSTEM_map, {}, 0x73, 0x7f, { .subfield = {3, 12} }, nullptr}, // SYSTEMIM_UNKNOWN, // reservedIM_UNKNOWN, // custom-3/rv128IM_UNKNOWN, // >= 80b
};

下一步目标:从最基础的 F load, F store 指令开始实现。先达成能成功识别指令的目标。

相关文章:

QtRVSim(二)一个 RISC-V 程序的解码流程

继上一篇文章简单代码分析后&#xff0c;本文主要调研如何实现对指令的解析运行。 调试配置 使用 gdb 工具跟踪调试运行。 c_cpp_properties.json 项目配置&#xff1a; {"name": "QtRvSim","includePath": ["${workspaceFolder}/**&quo…...

x-cmd pkg | httpx - 为 Python 设计的下一代 HTTP 客户端库

目录 简介首次用户功能特点进一步探索 简介 HTTPX 是一个为 Python 设计的下一代 HTTP 客户端库&#xff0c;由 Tom Christie 创建。它提供了同步和异步的 API&#xff0c;并支持 HTTP/1.1 和 HTTP/2 协议。与 Requests 库类似&#xff0c;但增加了对异步请求的支持和 HTTP/2 …...

代码随想录算法训练营第四十二天(动态规划篇)|62. 不同路径

62. 不同路径 题目链接&#xff1a;62. 不同路径 - 力扣&#xff08;LeetCode&#xff09; 思路 dp[i][j]: 从0到位置[i, j]共有dp[i][j]条路径。 dp[i][j] dp[i-1][j] dp[i][j-1] 到位置[i,j]&#xff0c;可以从它的上面或者左边来&#xff0c;所以路径和为这两个方向的路…...

YOLO 全面回顾:从最初的YOLOv1到最新的YOLOv8、YOLO-NAS,以及整合了 Transformers 的 YOLO

YOLO 全面回顾 综述评估指标YOLO v1YOLO v2YOLO v3YOLO v4YOLOv5 与 Scaled-YOLOv4 YOLORYOLOXYOLOv6YOLOv7DAMO-YOLOYOLOv8PP-YOLO, PP-YOLOv2, and PP-YOLOEYOLO-NASYOLO with Transformers 综述 论文&#xff1a;https://arxiv.org/pdf/2304.00501.pdf 代码&#xff1a;gi…...

Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心,Kotlin(2)

Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心&#xff0c;Kotlin&#xff08;2&#xff09; 在 Android ScaleGestureDetector检测双指缩放Bitmap基于Matrix动画移动到双指捏合中心点ImageView区域中心&#xff0c;Kotlin-CSDN博客 …...

同为科技(TOWE)自动控制循环定时插座

随着科技的发展&#xff0c;智能化家居已成为我们生活的重要组成部分。作为国内领先的智能家居品牌&#xff0c;同为科技&#xff08;TOWE&#xff09;推出的自动控制循环定时插座&#xff0c;无疑将科技与生活完美地结合在一起。 1.外观设计 同为科技&#xff08;TOWE&#x…...

游戏设计模式

单列模式 概念 单例模式是一种创建型设计模式&#xff0c;可以保证一个类只有一个实例&#xff0c;并提供一个访问该实例的全局节点。 优点 可以派生&#xff1a;在单例类的实例构造函数中可以设置以允许子类派生。受控访问&#xff1a;因为单例类封装他的唯一实例&#xf…...

CUBEMX与FreeRTOS在Arm Compiler 6下的配置方法

在嵌入式开发中&#xff0c;STM32是一种广泛使用的微控制器。为了提高开发效率&#xff0c;我们通常会利用ST公司提供的STM32CubeMX工具来配置硬件&#xff0c;并结合FreeRTOS这一实时操作系统来进行多任务处理。本文将深入探讨如何在这一框架下&#xff0c;使用Arm Compiler 6…...

Android Studio 提示Use app:drawableStartCompat instead of android:drawableStart

每次提交代码时&#xff0c;AS这个老妈子总爱唠叨一堆warning&#xff0c;这些Warning都在讲什么&#xff1f; 1.Use app:drawableStartCompat instead of android:drawableStart 在Android开发中&#xff0c;android:drawableStart和app:drawableStartCompat是两个用于设置…...

C# wpf 实现任意控件(包括窗口)更多调整大小功能

WPF拖动改变大小系列 第一节 Grid内控件拖动调整大小 第二节 Canvas内控件拖动调整大小 第三节 窗口拖动调整大小 第四节 附加属性实现拖动调整大小 第五章 拓展更多调整大小功能&#xff08;本章&#xff09; 文章目录 WPF拖动改变大小系列前言一、添加的功能1、任意控件Drag…...

Vue+OpenLayers7入门到实战:快速搭建Vue+OpenLayers7地图脚手架项目。从零开始构建Vue项目并整合OpenLayers7.5.2

返回《Vue+OpenLayers7》专栏目录:Vue+OpenLayers7 前言 本章针对Vue初学者,对Vue不熟悉,甚至还不会Vue的入门学生读者。 本章会详细讲解从NodeJS环境到npm环境的各个步骤,再到使用vue-cli脚手架快速生成项目,以及添加OpenLayers7地图库依赖,编写简单的xyz高德地图显示…...

mysql-线上常用运维sql

1.表备份 INSERT INTO table1 SELECT * FROM table2; 2.用一个表中的字段更新另一张表中的字段 UPDATE table2 JOIN table1 ON table2.id table1.id SET table2.column2 table1.column1; 3.在MySQL中&#xff0c;查询一个表的列字段值是否包含另一个表的字段&#xff0c;…...

Linux之进程间通信(system V 共享内存)

目录 一、共享内存 1、基本原理 2、共享内存的创建 3、共享内存的释放 4、共享内存的关联 5、共享内存的去关联 6、查看IPC资源 二、完整通信代码 三、共享内存的特点 四、信号量 1、相关概念 2、信号量概念 进程间通信的本质就是让不同的进程看到同一个资源。而前…...

数据库 sql select *from account where name=‘张三‘ 执行过程

select *from account where name张三分析上面语句的执行过程 用到了索引 由于是根据 1.name字段进行查询&#xff0c;所以先根据name张三’到name字段的二级索引中进行匹配查 找。但是在二级索引中只能查找到 Arm 对应的主键值 10。 2.由于查询返回的数据是*&#xff0c…...

力扣日记1.27-【回溯算法篇】131. 分割回文串

力扣日记&#xff1a;【回溯算法篇】131. 分割回文串 日期&#xff1a;2023.1.27 参考&#xff1a;代码随想录、力扣 131. 分割回文串 题目描述 难度&#xff1a;中等 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可…...

如何用web界面打开华为防火墙

目录 1.创建一个虚拟网卡 2.cloud操作 3.防火墙上操作 4. 登录 1.创建一个虚拟网卡 2.cloud操作 3.防火墙上操作 4. 登录...

力扣20、有效的括号(简单)

1 题目描述 图1 题目描述 2 题目解读 给定的字符串只包含括号&#xff0c;判断这个字符串中的括号是否按照正确顺序出现&#xff0c;即这个字符串是否有效。 3 解法一&#xff1a;栈 C的STL中的stack&#xff0c;在解题时非常好用。 3.1 解题思路 使用栈stk&#xff0c;并枚举…...

Android 系统启动过程

当按下电源时&#xff0c;引导芯片代码会从预定义的地方(固化在ROM) 开始执行,加载引导程序BootLoader到RAM,然后执行。 启动内核的第一个进程idle(pid0),idle进程是Linux系统第一个进程&#xff0c;是init进程和kthreadd进程的父进程。 idle的主要作用 初始化进程以及内存管…...

基于STM32的智能手环设计与实现

需要原理图工程&#xff0c;源码&#xff0c;PCB工程的朋友收藏&#xff0c;这篇文章关注我&#xff0c;私我吧&#xff01;&#xff01;&#xff01; 基于STM32的智能手环设计与实现 摘要一、研究背景及意义二、实现功能三、系统方案设计系统方案设计框图3.1 单片机芯片选择3…...

[BJDCTF2020]The mystery of ip

hint 猜测ip和XFF有关 加一个XFF 下面这一步是看了wp出来的&#xff1a;存在ssti 这里尝试用jinja的注入方法&#xff0c;页面回显了是php的smarty框架 查了一下smarty的注入方法&#xff0c;发现可以直接执行php命令 在根目录找到flag...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...