多周期处理器debug记录

news/2025/2/22 22:43:44/文章来源:https://www.cnblogs.com/namezhyp/p/18723115

这篇随笔记录的是从普通的多周期处理器到加入握手信号和axi-lite协议sram的处理器。

在之前的多周期处理器里,由于结构比较简单,所以我给ifu和exu的握手信号加入的是时序逻辑,idu由于只做解码,所以握手信号放在了组合逻辑里,差不多就和透传差不多。但是加入sram握手信号以后,很多地方都需要再调整。

一开始连接sram的时候,考虑到ifu这边只需要读取,所以写入相关全都空缺。由于读取需要先地址握手,再数据握手,所以ifu这边也增加一个ar_done,用来标记是否地址已握手。关于ifu_valid信号,这个信号应该在读到inst以后赋值为高,在和idu沟通,也就是ifu_valid && idu_ready后设置低。ifu和idu之间的握手我选择短时握手,握手时顺便传递inst,然后就断开。这里的idu_ready表示的就不是“我已经完成当前指令”,而是“我已准备好接收下一条指令”。和讲义稍微ie有点区别。

在实际运行的时候,发现load指令可以运行,但是write异常,提示地址错误,检查地址发现意外的小。起初我怀疑过是当前store指令处理的有问题,但是检查后发现不应该。问题应该出在别的指令上。打印寄存器,发现值意外的全是0. 和nemu逐条指令做对比,发现了问题:以前的指令严格遵守2/3周期,寄存器的写入会被推移到下条指令的首个周期开头,所以没有出问题。

但是升级握手以后,寄存器的写入也会发生在当前指令周期内,成功写入后指令还在运行,此时wdata已经被清除,但是写使能还开着,导致二次写入,寄存器又被置零。

80000000: 00000413 li s0,0
80000004: 0019a117 auipc sp,0x19a
80000008: ffc10113 addi sp,sp,-4 # 8019a000 <_end>
8000000c: 2ed5c0ef jal ra,8005caf8 <_trm_init>

 可以看到,上一个寄存器表里,sp寄存器是有值的(在更上一个周期准备好了值,这个周期被写入),但上面的wdata已经变成了0,在下一周期的寄存器表里就可以看到sp寄存器又变成0了。

此外还注意到如果程序有问题导致模拟器中途报错退出,那波形不会被记录。考虑到这一点,我让ebreak以外的退出点都改调用ebreak,然后在ebreak里增加退出时波形的保存,然后再exit,这样就可以保证cpu仿真内部报错也能记录下波形。

检查波形,发现十分奇怪,最后发现是因为addi指令处理有问题,之前保留的加法器的代码需要删除,但是修改以后,发现store指令仍然存在问题。

 调整完store以后发现load指令又出问题,一条条指令排查发现是因为下一条指令更新时旧指令还在,导致向sram发出握手请求,但是又不能提供正确地址导致报错。

 

做到这里,我的思路就完全改变了:单周期的时候基本只有组合逻辑。而现在,组合逻辑是时序逻辑的附属,时序逻辑负责控制,在某一个状态下才去执行自己对应的组合逻辑。idu这里原本不留周期给它,现在idu也使用时序逻辑,如果ifu_valid && !idu_valid,表示指令已经准备好并且idu不繁忙,那就设置idu_valid和idu_ready,一边ifu握手,一边给exu通知准备执行。

传递信号时的一个准则:记清楚valid表示master信息有效,ready表示slave已经接收到信号。不要多传

 idu_ready表示idu已经收到了ifu的内容,但exu里jal类指令会改变next pc。那么ifu用ifu_valid &&idu_ready为什么不会导致jal指令错误呢?因为idu_ready信号受ifu_valid和idu_valid两个信号控制,idu_valid受exu_ready控制,所以exu这边更新pc_next前,idu_ready不会更新,那ifu自然也不会更新。

调整以后exu的处理一直状态错乱,在控制台没意识到问题,查看wave时我才意识到,我的ifu也会给idu和exu发送inst信号用于一些特殊处理。idu修改后会缓存inst,exu也应该使用IDU缓存的inst,而不是直接连线ifu,错误连线导致处理一直有问题。修改以后该问题解决。

 

握手也是分“短时握手”和“持续握手”的,在ifu和idu之间,我用的是短时握手,成功握手确认数据传输后就断开,slave做自己的事。ifu idu之间是握手以后idu继续干自己的,握手同时传递信号,然后ifu就更新pc准备下一条指令(现在来看,我也可以把pc_next连到raddr上,也不是非的连接pc)。exu和idu之间则是长时握手,idu_valid有效以后会一直保持,exu收到信息后就取处理,处理完以后才会通知idu完成。目前来看这个逻辑是可用的。

 

还发现一个很奇怪的事:一开始sram的读地址连的reg是sram_raddr,每个周期开头清零,然后组合逻辑重新赋值,Pmem会报错地址为0, 但是gtkwave查看波形,却发现sram_raddr没有问题,思考了半天,怀疑可能是因为读到了跳变的0导致报错。于是决定直接把stored_addr连到sram的araddr上,结果不报错了。但是stored_addr在exu收到信息过一个周期才会启动,这样会不会还有问题呢?

在修改以后还是存在类似的问题,只不过换了个地方,我也在思考有没有可能是dpi-c机制的问题呢?但是以前没有出现这个问题。但是我和ai沟通后,决定给exu增加一个common_inst状态,exu平时处于空闲,exu_reaady为0.收到idu_valid以后,下一周期才转入common_inst状态并且exu_ready为1,这样处理指令,就不会紧巴巴地出现 “非load/store指令exu只有一个周期,导致exu无法正确处理自己状态,不能给lad/store指令沟通得到更多周期“ 的情况。问题暂时解决,可以跑起来th-thread。

不过,现在所有串口打印都是双倍打印,但现在能打印就说明程序握手方面应该是正常了。

 思路:串口打印只会来自putch函数,在源代码里找到putch或者串口地址,然后根据pc或者inst在波形里查看原因。

下图所示就是putch函数对应的store指令,可以看到,写入操作被执行了两次:

 检查sram 的写数据部分:

always @(posedge clk) beginif (!wready && wvalid) beginwready <= 1'b1;end else if (wready && wvalid) beginwready <= 1'b0;w_done <= 1'b1;if (aw_done) begin  
            pmem_write(awaddr, wdata, wstrb);endend else if (bvalid && bready) beginw_done <= 1'b0;end
end

发现写数据这里只要aw_done就会值执行写入,没有考虑到已经写入但是还在写sram周期的情况。所以增加条件,如果w_done,也就是已经写入过,那也不再写入,问题解决!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/888207.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

继承内存图--java进阶 day01

主方法进栈,有new进堆堆内存中先存自己类中有的变量又因为继承了父类,所以父类中的变量也要存入 即使被私有化,依旧可以继承,只是没有权限使用!创建对象时,会调用构造方法,所以走构造方法,实参传形参.....继续走到super,访问父类的构造方法,父类构造方法进栈,形参继…

离散化学习笔记

离散化学习笔记 OP:又是一如既往的周更。。。水死了 定义离散化:将数字映射为是第几小的数,其保证数据在Hash之后仍然保持原来的全/偏序关系,能够解决:通过元素相对大小即可解决的问题。 其实本质上就是哈希的一种特殊规则而已。(离散化简化了不止亿点)目标将一堆乱序且…

java知识面试day2

1.说出java和c++的区别java是一个纯粹的面向对象语言,所有的对象都继承于java. lang.Object,C++兼容C,不但支持面向对象也支持面向过程 java有着一次编译四处运行的跨平台特性。 java不具有指针,但具有垃圾回收。 java不支持多重继承,只能通过实现多个接口去达到相同目的2.…

继承中构造方法访问特点--java 进阶day01

1.子类不可以继承父类的构造方法构造方法的名称必须与类名一致,上图中类名是Zi,而构造方法名是Fu,肯定不行 2.子类在初始化之前,需要对父类初始化 子类在初始化的过程中,很有可能会调用到父类的数据,如果父类没有提前初始化,子类就无法调用这些数据3.通过在子类中访问父…

Mysql莫名其妙爆出拒绝访问问题的原因及解决方案

本文记录使用Mysql作为数据库时发生拒绝访问问题的解决方案Mysql出现拒绝连接问题 ⛄问题原因 : Mysql密码错误,本机上并不是只有一个Mysql服务,我们在开机时启动了并非以前使用的那个Mysql服务,所以造成了密码的错误🌟解决方案 :手动关闭当前正在启用的Mysql服务,尝试找…

Codes 开源 免费 研发项目管理平台 3.0.0 版本发布及创新的轻IPD实现

Codes 是国内首款重新定义 SaaS 模式的开源项目管理平台,支持云端认证、本地部署、全部功能开放,并且对 30 人以下团队免费。它通过创新的方式简化研发协同工作,使敏捷开发更易于实施。采用轻量化的 IPD 模式实现,且融合了敏捷 。轻 IPD 主要解决多项目交付的研发过程管理,…

2025/2/15课堂记录

数字转换,皇宫看守,树上dp,树的直径目录数字转换 皇宫看守数字转换这是一道树的直径题。 首先,树的直径定义是:树上两个结点之间的最短(加权)路中最长的一条路径(和二分答案没关) 但由于贪心思想,这个路径一定起点终点是两片叶子结点如图,这棵树的直径就是5,即节点…

基于CPS-SPWM链式STATCOM系统在电压不平衡环境下控制策略的simulink建模与仿真

1.课题概述基于CPS-SPWM链式STATCOM系统在电压不平衡环境下控制策略的simulink建模与仿真。利用电压外环PI调节器得到有功 电流指令值结合由负载侧电流检测 到 的无功 电流指令值 ,经由 状态解耦PI调节的电流内环控制器输出直接得到的是输出电压的指令值,用此信号作为采用控制…

【库】Coravel Schedule任务调度

Coravel 通过使高级应用程序功能(如任务/作业调度、排队、缓存、邮件(以及更多!))易于访问且易于使用,帮助开发人员快速启动并运行 .NET 应用程序。具有简单、富有表现力和直接的语法。   下面是简单的用法,通过注入Scheduler和在中间件中定义调度的实现,来完成简单的…

【库】用Rin透视Web请求

Rin 可以捕获对 ASP.NET Core 应用程序的 HTTP 请求,并为捕获的数据提供查看器。它是调试 Web 应用程序(例如,网站、API 应用)的有用工具。先看如下代码:var builder = WebApplication.CreateBuilder(args); builder.Logging.AddRinLogger(); builder.Services.AddRin(); …