Chisel芯片开发入门系列 -- 14. CPU芯片开发和解释4(Load/Store指令再探)

发布于:2025-08-02 ⋅ 阅读:(12) ⋅ 点赞:(0)

接本系列的上一篇,本文继续介绍CPU的指令译码后的执行并特定针对Load/Store执行,也就是代码位于ChipCamp/riscv-chisel-book项目的src/main/scala/目录下的04_sw子目录(03_lw是昨天介绍的内容)!

04_sw和03_lw看似是并列的实际上是包含的,04的代码是在03的代码基础上增加的!比较一下这两个子目录,左侧03右侧04,右侧的文件均比左侧大。

Top.scala文件内容一样,只是package lw改成了package sw。

Memory.scala部分除了package lw改为sw以外,增加了两处代码,一个是在DmemPortIo的定义中增加了wen和wdata两个IO信号线,其中的w表示write(也就是Store的内存写),en表示enable(表示使能),和w一起则表示写使能信号,只有在写使能信号置位使能的情况下才将数据从DmemPortIo读取下来写到内存中,这正是第二块增量代码所表示的意思。当然这个Memory.scala还将代码文件(指令文件)从lw.hex变为了sw.hex。

Core.scala的部分除了package lw改为sw以外,有多处代码增加。其中指令译码(Instruction Decode, ID)部分,增加了imm_s_sext(指令中包含的有符号立即数,带符号扩展至32bit)。指令为sw的时候(也就是inst ===SW的时候)对alu_out赋值和(inst===LW)的时候有所区分,io.dmem.wen写使能标记位则只在(inst===SW)的时候置位。rs2_data赋值给io.dmem.wdata则不区分LW/SW,但实际上的逻辑则是靠io.dmem.wen控制的。

剩下的增加的部分就是debug的部分增加了打印dmem.wen和dmem.wdata了,如下所示。其中的exit信号置位条件是0x00602823的指令,这就要求我们在src/hex/sw.hex中有0x00602823作为结束程序运行的指令。

src/hex/sw.hex文件的构造,我们使用如下思路进行构造,构造出的SW指令是0x33802323:

把这个LW指令、SW指令、以及结束程序的指令0x00602823都写到src/hex/sw.hex中,如下所示,蓝色红色绿色深红色分别是LW指令、SW指令、一个任意构造的指令、结束指令:

$ cat src/hex/sw.hex
03
23
80
00

23
23
80
33

22
22
22
22

23
28
60
00

运行结果如下,其中蓝色的是LW指令,红色的是SW指令,从中可以看出rs1_addr等各个字段均和上面预期的是一致的,包括那个0x326(十进制806)。有一个特殊的地方是rs2_data的值是0x20250730!这是在Core.scala中通过对regfile(24)赋值实现的,这个对regfile(24)进行赋值的测试在此前的系列文章中有“预告”的,可翻看。

$ sbt "testOnly sw.HexTest"
[info] welcome to sbt 1.10.11 (Oracle Corporation Java 24.0.2)
[info] loading settings for project chisel-template-build from plugins.sbt...
[info] loading project definition from D:\src\chipcamp\riscv-chisel-book\chisel-template\project
[info] loading settings for project chisel-template from build.sbt...
[info] set current project to chisel-template (in build file:/D:/src/chipcamp/riscv-chisel-book/chisel-template/)
[info] compiling 1 Scala source to D:\src\chipcamp\riscv-chisel-book\chisel-template\target\scala-2.13\classes ...
[warn] \src\main\scala\04_sw\Core.scala 37:39: [W002] Dynamic index with width 6 is too large for extractee of width 1
[warn]   val rs1_data = Mux((rs1_addr =/= 0.U(WORD_LEN.U)), regfile(rs1_addr), 0.U(WORD_LEN.W))
[warn]                                       ^
[warn] \src\main\scala\04_sw\Core.scala 38:39: [W002] Dynamic index with width 6 is too large for extractee of width 1
[warn]   val rs2_data = Mux((rs2_addr =/= 0.U(WORD_LEN.U)), regfile(rs2_addr), 0.U(WORD_LEN.W))
[warn]                                       ^
[warn] There were 2 warning(s) during hardware elaboration.
io.imem.addr=0x00000000,  io.imem.inst=0x00802303,  io.dmem.addr=0x00000008,  io.dmem.rdata=0x22222222.
pc_reg     : 0x00000000
inst       : 0x00802303
rs1_addr   :   0
rs2_addr   :   8
wb_addr    :   6
rs1_data   : 0x00000000
rs2_data   : 0x00000000
wb_data    : 0x22222222
dmem.addr  :           8
dmem.wen   :  0
dmem.wdata : 0x00000000

---------
io.imem.addr=0x00000004,  io.imem.inst=0x33802323,  io.dmem.addr=0x00000326,  io.dmem.rdata=0x00000000.
io.imem.dmem=0x00000326,  io.imem.wdata=0x20250730.
pc_reg     : 0x00000004
inst       : 0x33802323
rs1_addr   :   0
rs2_addr   :  24
wb_addr    :   6
rs1_data   : 0x00000000
rs2_data   : 0x20250730
wb_data    : 0x00000000
dmem.addr  :         806
dmem.wen   :  1
dmem.wdata : 0x20250730

---------
io.imem.addr=0x00000008,  io.imem.inst=0x22222222,  io.dmem.addr=0x00000000,  io.dmem.rdata=0x00802303.
pc_reg     : 0x00000008
inst       : 0x22222222
rs1_addr   :   4
rs2_addr   :   2
wb_addr    :   4
rs1_data   : 0x00000000
rs2_data   : 0x02ffff00
wb_data    : 0x00802303
dmem.addr  :           0
dmem.wen   :  0
dmem.wdata : 0x02ffff00
---------
[info] HexTest:
[info] mycpu
[info] - should work through hex
[info] Run completed in 1 second, 311 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 5 s, completed 2025骞?鏈?0鏃?09:51:57
[0J
 

附上本次测试的代码提交记录:

Commits详情 - riscv-chisel-book:fork riscv-chisel-book by ChipCamp for Tutorial 20250703 - GitCode

附本次提交代码的操作流水备忘(git操作备忘):

xxx@DESKTOP-ZZ4F56 MINGW64 /d/src/chipcamp/riscv-chisel-book/chisel-template (master)

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   src/hex/sw.hex
        modified:   src/main/scala/04_sw/Core.scala

no changes added to commit (use "git add" and/or "git commit -a")

xxx@DESKTOP-ZZ4F56 MINGW64 /d/src/chipcamp/riscv-chisel-book/chisel-template (master)
$ git diff
diff --git a/chisel-template/src/hex/sw.hex b/chisel-template/src/hex/sw.hex
index 5ee368a..a0de553 100644
--- a/chisel-template/src/hex/sw.hex
+++ b/chisel-template/src/hex/sw.hex
@@ -3,10 +3,14 @@
 80
 00
 23
-28
-60
-00
+23
+80
+33
 22
 22
 22
 22
+23
+28
+60
+00
diff --git a/chisel-template/src/main/scala/04_sw/Core.scala b/chisel-template/src/main/scala/04_sw/Core.scala
index 53d2c76..cb63e9f 100644
--- a/chisel-template/src/main/scala/04_sw/Core.scala
+++ b/chisel-template/src/main/scala/04_sw/Core.scala
@@ -13,6 +13,10 @@ class Core extends Module {
   })

   val regfile = Mem(32, UInt(WORD_LEN.W))
+  regfile(1) := 0x01ffff00.U(WORD_LEN.W)
+  regfile(2) := 0x02ffff00.U(WORD_LEN.W)
+  regfile(3) := 0x030f0f00.U(WORD_LEN.W)
+  regfile(24) := 0x20250730.U(WORD_LEN.W)


   //**********************************

xxx@DESKTOP-ZZ4F56 MINGW64 /d/src/chipcamp/riscv-chisel-book/chisel-template (master)
$ git add .

xxx@DESKTOP-ZZ4F56 MINGW64 /d/src/chipcamp/riscv-chisel-book/chisel-template (master)
$ git commit -m "20250730 update src/hex/sw.hex and src/main/scala/04_sw/Core.scala for Store instruction demo"
[master 4ca1115] 20250730 update src/hex/sw.hex and src/main/scala/04_sw/Core.scala for Store instruction demo
 2 files changed, 11 insertions(+), 3 deletions(-)

xxx@DESKTOP-ZZ4F56 MINGW64 /d/src/chipcamp/riscv-chisel-book/chisel-template (master)
$ git push
Enumerating objects: 19, done.
Counting objects: 100% (19/19), done.
Delta compression using up to 12 threads
Compressing objects: 100% (9/9), done.
Writing objects: 100% (10/10), 994 bytes | 994.00 KiB/s, done.
Total 10 (delta 5), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Start Git Hooks Checking                                        [PASSED]
To https://gitcode.com/ChipCamp/riscv-chisel-book.git
   f580d29..4ca1115  master -> master


网站公告

今日签到

点亮在社区的每一天
去签到