├── .gitignore
├── .gitmodules
├── README.assets
├── Snipaste_2023-09-27_23-38-29.png
├── cpu.png
└── wechat_screenshot.jpg
├── README.md
├── doc
└── RISCV-CPU-doc
│ ├── .gitmodules
│ ├── README.md
│ ├── doc
│ ├── 2021-README.md
│ ├── ChangeFreq.pdf
│ ├── Comments on hci.v.md
│ ├── FPGA debug by LED.md
│ ├── HowToCompileTestCases.md
│ ├── Vivado_license_to2037.lic
│ ├── Yet Another FPGA Debug.md
│ ├── attach
│ │ ├── fig1.png
│ │ ├── fig2.png
│ │ └── fig3.png
│ ├── qweryy-Vivado-wsl2.md
│ ├── simulation debug method.md
│ ├── src
│ │ ├── constrs
│ │ │ └── Basys-3-Master.xdc
│ │ ├── sim
│ │ │ └── testbench.v
│ │ └── src
│ │ │ ├── display_ctrl.v
│ │ │ └── riscv_top.v
│ ├── vivadoDemo.pdf
│ ├── 体系结构I 环境配置参考.md
│ └── 支持中断.pdf
│ └── riscv
│ ├── FPGA_test.py
│ ├── autorun_fpga.sh
│ ├── build_test.sh
│ ├── ctrl
│ ├── build.sh
│ ├── controller.cpp
│ ├── listener.h
│ └── run.sh
│ ├── pd.tcl
│ ├── run_test.sh
│ ├── run_test_fpga.sh
│ ├── sim
│ └── testbench.v
│ ├── src
│ ├── Basys-3-Master.xdc
│ ├── common
│ │ ├── block_ram
│ │ │ └── block_ram.v
│ │ ├── fifo
│ │ │ └── fifo.v
│ │ └── uart
│ │ │ ├── uart.v
│ │ │ ├── uart_baud_clk.v
│ │ │ ├── uart_rx.v
│ │ │ └── uart_tx.v
│ ├── cpu.v
│ ├── hci.v
│ ├── ram.v
│ └── riscv_top.v
│ ├── sys
│ ├── io.h
│ ├── memory.ld
│ └── rom.s
│ └── testcase
│ ├── array_test1.ans
│ ├── array_test1.c
│ ├── array_test1.in
│ ├── array_test2.ans
│ ├── array_test2.c
│ ├── array_test2.in
│ ├── basicopt1.ans
│ ├── basicopt1.c
│ ├── bulgarian.ans
│ ├── bulgarian.c
│ ├── expr.ans
│ ├── expr.c
│ ├── gcd.ans
│ ├── gcd.c
│ ├── hanoi.ans
│ ├── hanoi.c
│ ├── hanoi.in
│ ├── heart.ans
│ ├── heart.c
│ ├── looper.c
│ ├── lvalue2.ans
│ ├── lvalue2.c
│ ├── magic.ans
│ ├── magic.c
│ ├── manyarguments.ans
│ ├── manyarguments.c
│ ├── multiarray.ans
│ ├── multiarray.c
│ ├── pi.ans
│ ├── pi.c
│ ├── qsort.ans
│ ├── qsort.c
│ ├── queens.ans
│ ├── queens.c
│ ├── statement_test.ans
│ ├── statement_test.c
│ ├── statement_test.in
│ ├── superloop.ans
│ ├── superloop.c
│ ├── superloop.in
│ ├── tak.ans
│ ├── tak.c
│ ├── tak.in
│ ├── testsleep.c
│ ├── uartboom.ans
│ └── uartboom.c
└── riscv
├── Makefile
├── fpga
├── build.sh
├── controller.cpp
├── listener.h
├── pd.tcl
└── run.sh
├── script
├── FPGA_test.py
├── autorun_fpga.sh
├── build_test.sh
├── run_test.sh
└── run_test_fpga.sh
├── sim
└── testbench.v
├── src
├── Basys-3-Master.xdc
├── common
│ ├── block_ram
│ │ └── block_ram.v
│ ├── fifo
│ │ └── fifo.v
│ └── uart
│ │ ├── uart.v
│ │ ├── uart_baud_clk.v
│ │ ├── uart_rx.v
│ │ └── uart_tx.v
├── cpu.v
├── hci.v
├── ram.v
└── riscv_top.v
├── sys
├── io.h
├── memory.ld
└── rom.s
├── testcase
├── fpga
│ ├── array_test1.ans
│ ├── array_test1.c
│ ├── array_test1.in
│ ├── array_test2.ans
│ ├── array_test2.c
│ ├── array_test2.in
│ ├── basicopt1.ans
│ ├── basicopt1.c
│ ├── bulgarian.ans
│ ├── bulgarian.c
│ ├── expr.ans
│ ├── expr.c
│ ├── gcd.ans
│ ├── gcd.c
│ ├── hanoi.ans
│ ├── hanoi.c
│ ├── hanoi.in
│ ├── heart.ans
│ ├── heart.c
│ ├── looper.c
│ ├── lvalue2.ans
│ ├── lvalue2.c
│ ├── magic.ans
│ ├── magic.c
│ ├── manyarguments.ans
│ ├── manyarguments.c
│ ├── multiarray.ans
│ ├── multiarray.c
│ ├── pi.ans
│ ├── pi.c
│ ├── qsort.ans
│ ├── qsort.c
│ ├── queens.ans
│ ├── queens.c
│ ├── statement_test.ans
│ ├── statement_test.c
│ ├── statement_test.in
│ ├── superloop.ans
│ ├── superloop.c
│ ├── superloop.in
│ ├── tak.ans
│ ├── tak.c
│ ├── tak.in
│ ├── testsleep.c
│ ├── uartboom.ans
│ └── uartboom.c
└── sim
│ ├── 000_array_test1.ans
│ ├── 000_array_test1.c
│ ├── 001_array_test2.ans
│ ├── 001_array_test2.c
│ ├── 002_expr.ans
│ ├── 002_expr.c
│ ├── 003_looper.c
│ ├── 004_gcd.ans
│ ├── 004_gcd.c
│ ├── 005_lvalue2.ans
│ ├── 005_lvalue2.c
│ ├── 006_multiarray.ans
│ ├── 006_multiarray.c
│ ├── 007_hanoi.ans
│ ├── 007_hanoi.c
│ ├── 100_magic.ans
│ ├── 100_magic.c
│ ├── 101_queens.ans
│ ├── 101_queens.c
│ ├── 102_qsort.ans
│ ├── 102_qsort.c
│ ├── 103_bulgarian.ans
│ ├── 103_bulgarian.c
│ ├── basicopt1.ans
│ ├── basicopt1.c
│ ├── manyarguments.ans
│ ├── manyarguments.c
│ ├── statement_test.ans
│ ├── statement_test.c
│ ├── superloop.ans
│ ├── superloop.c
│ ├── uartboom.ans
│ └── uartboom.c
└── testspace
└── .keep
/.gitignore:
--------------------------------------------------------------------------------
1 | riscv/testspace/*
2 |
3 | *.o
4 | *.vcd
5 |
6 | !.keep
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "riscv-gnu-toolchain"]
2 | path = riscv-gnu-toolchain
3 | url = https://github.com/riscv-collab/riscv-gnu-toolchain.git
4 |
--------------------------------------------------------------------------------
/README.assets/Snipaste_2023-09-27_23-38-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACMClassCourse-2022/RISC-V-CPU-2023/ec253f029a987405359ee679ae397be53938d47a/README.assets/Snipaste_2023-09-27_23-38-29.png
--------------------------------------------------------------------------------
/README.assets/cpu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACMClassCourse-2022/RISC-V-CPU-2023/ec253f029a987405359ee679ae397be53938d47a/README.assets/cpu.png
--------------------------------------------------------------------------------
/README.assets/wechat_screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACMClassCourse-2022/RISC-V-CPU-2023/ec253f029a987405359ee679ae397be53938d47a/README.assets/wechat_screenshot.jpg
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #
RISCV-CPU 2023
2 |
3 | ## 引言
4 |
5 | 
6 |
7 |
8 | ## 项目说明
9 |
10 | 在本项目中,你需要使用 Verilog 语言完成一个简单的 RISC-V CPU 电路设计。Verilog 代码会以软件仿真和 FPGA 板两种方式运行。你设计的电路将运行若干测试程序并可能有输入数据,执行得到的输出数据将与期望结果比较,从而判定你的 Verilog 代码的正确性。**你需要实现 CPU 的运算器与控制器,而内存等部件题面已提供代码**。要求最终你的CPU需要能够正确**完成RISC-V指令集中的部分指令,支持tomasulo算法的乱序执行,并且能够在FPGA上运行所有测试点**。具体项目要求和项目阶段划分见下文。
11 |
12 |
13 |
14 | ### 项目阶段
15 |
16 | - 环境配置
17 | - 完成 `cpu.v` 的所有模块, 根据 `riscv/src/cpu.v` 提供的接口自顶向下完成代码,其余题面代码尽量不要改动
18 | - 使用 iVerilog 进行本地仿真测试(结果为 `.vcd` 文件)通过可执行的测试
19 | - 将 Verilog 代码烧录至 FPGA 板上,在 FPGA 上通过所有测试
20 |
21 |
22 | ### 时间安排
23 |
24 | > 时间以上海交通大学 2023-2024 学年校历为准,Week 4 周一为 2023.10.02
25 |
26 | 每 2 周一次检查,检查时间为每周日 22:00 后,下表为检查形式与标准:
27 | 鉴于去年的情况,助教选择中间预留更长时间并且多多push,以保证大家的代码能够在期末前的时间里有一个不错的进度。
28 | 另外,由于主体部分工作很多,助教大概率会在期中安排code review保证进度,具体时间会考虑同学们期中的work load。
29 |
30 | | 时间 | 检查内容 |
31 | | ----------- | --------------------------------------------------------------- |
32 | | **Week 4** | 仓库创建 |
33 | | **Week 6** | 完成电路设计草稿 / 各个 CPU 模块文件创建 |
34 | | **Week 8** | 开始完善部分模块代码,checkpoint 1 |
35 | | **Week 10** | 完善部分模块代码,尝试连线,checkpoint 2 |
36 | | **Week 12** | 各个 CPU 模块文件基本完成,完成 `cpu.v` 连线,checkpoint 3 |
37 | | **Week 14** | Simulation 初步debug 通过 `gcd` |
38 | | **Week 16** | Simulation 完成debug 通过除 `tak`,`heart`,`pi` 之外的所有样例 |
39 | | **Week 18** | FPGA 通过所有样例 |
40 |
41 | ### 分数构成
42 |
43 | 本作业满分为 100%。
44 |
45 | | 评分项目 | 分数 | 说明 |
46 | | --------------- | ------ | ---------------------------------------- |
47 | | **仿真测试** | 75% | 在 OJ 通过所有仿真测试点 |
48 | | **FPGA 测试** | 10% | 在 OJ 通过所有 FPGA 测试点 |
49 | | **Code Review** | 5%+10% | 以面谈形式考察 CPU 原理与 HDL 的理解掌握 |
50 |
51 | Code Review 将会有两次,分别在期中和期末,分别占 5%、10%。期中的 Code Review 会考察 CPU 原理的设计和工程进度,期末的 Code Review 会考察整个项目的理解掌握。Code Review 会以面谈形式进行,面谈时间、地点将会在课程群内通知。
52 |
53 |
54 | ### 仓库文件结构
55 |
56 | ```C++
57 | 📦RISCV-CPU
58 | ┣ 📂riscv // 项目根目录
59 | ┃ ┣ 📂fpga // FPGA 开发板相关
60 | ┃ ┣ 📂script // 编译测试相关参考脚本
61 | ┃ ┣ 📂sim // 仿真运行 Testbench
62 | ┃ ┣ 📂src // HDL 源代码
63 | ┃ ┃ ┣ 📂common // 题面提供部件源代码
64 | ┃ ┃ ┣ 📜cpu.v // CPU 核心代码
65 | ┃ ┣ 📂sys // 编译 C 语言测试点所需文件
66 | ┃ ┣ 📂testcase // 测试点
67 | ┃ ┃ ┣ 📂fpga // 全部测试点 (全集)
68 | ┃ ┃ ┗ 📂sim // 仿真运行测试点 (子集)
69 | ┃ ┣ 📂testspace // 编译运行结果
70 | ┃ ┗ 📜Makefile // 编译及测试脚本
71 | ┣ 📂serial // 用于访问 FPGA 串口的第三方库
72 | ┣ 📂doc // **题面补充文档,包括环境配置、频率修改、vivado配置教程和文件**
73 | ┗ 📜README.md // 题面文档
74 | ```
75 |
76 | ### 指令集
77 |
78 | > 可参考资料见 [RISC-V 指令集](#RISC-V-指令集)
79 |
80 | 本项目使用 **RV32I 指令集**
81 |
82 | 基础测试内容不包括 Doubleword 和 Word 相关指令、Environment 相关指令和 CSR 相关等指令。
83 |
84 | 必须要实现的指令为以下 37 个:`LUI`, `AUIPC`, `JAL`, `JALR`, `BEQ`, `BNE`, `BLT`, `BGE`, `BLTU`, `BGEU`, `LB`, `LH`, `LW`, `LBU`, `LHU`, `SB`, `SH`, `SW`, `ADDI`, `SLLI`, `SLTI`, `SLTIU`, `XORI`, `SRLI`, `SRAI`, `ORI`, `ANDI`, `ADD`, `SUB`, `SLL`, `SLT`, `SLTU`, `XOR`, `SRL`, `SRA`, `OR`, `AND`
85 |
86 |
87 | 如果需要额外参考信息,以下内容可能对你有帮助:
88 | - RISC-V官网 https://riscv.org/
89 | - [官方文档下载页面](https://riscv.org/technical/specifications/)
90 | - 基础内容见 Volume 1, Unprivileged Spec
91 | - 特权指令集见 Volume 2, Privileged Spec
92 | - 非官方 [Read the Docs 文档](https://msyksphinz-self.github.io/riscv-isadoc/html/index.html)
93 | - 非官方 Green Card,[PDF 下载链接](https://inst.eecs.berkeley.edu/~cs61c/fa17/img/riscvcard.pdf)
94 |
95 | ### Simulation测试
96 |
97 | - 在本地 Simulation 时,部分样例运行时间可能会非常非常长,如 `heart.c` 与 `pi.c`。这些样例不会被算入 Simulation 的测试范围,但会在 FPGA 检查阶段纳入测试范围。
98 | - 为了让一些不用 `sleep` 函数的本地 simulation 跑得更快,本地测评版本中的 `riscv/sys/io.h` 并没有 `#define SIM`,导致一些需要 `sleep` 函数的测试点无法本地正确测试,比如 `qsort` 测试点会因为`sleep`没执行导致时钟始终为$0$而执行异常,如果需要本地测评这类测试点记得在 `riscv/sys/io.h` 中加上`#define SIM`。
99 | 
100 |
101 | ### Vivado配置和FPGA
102 |
103 | - **Vivado**
104 |
105 | - 你需要该软件将 Verilog 代码编译为可以烧录至 FPGA 板的二进制文件
106 |
107 | - Vivado 安装后软件整体大小达 30G 左右,请准备足够硬盘空间
108 |
109 | - **Serial Communication Library**
110 |
111 | - 程序与 FPGA 板通过 USB 通讯过程中使用该库
112 | - 安装方式参见本仓库 `doc` 分支,2023-10-03 update:范老师关于WSL2上板指引 `RISC-V-CPU-2023/doc/RISCV-CPU-doc/doc/qweryy-Vivado-wsl2.md`
113 |
114 | - Vivado 不支持 MacOS 系统,故如果使用 Mac 则必须使用虚拟机,推荐 Ubuntu Desktop。此外对于使用 Windows 电脑的同学,RISC-V Toolchain 也推荐在 Linux 系统上安装。
115 | - FPGA 开发板比较脆弱,使用时请注意爱护,除垫脚外不要有磕碰或硬物接触;不要让导电物品(注意人体是导电的)接触到板上按钮除外的金属部分。
116 |
117 | ### Bonus
118 |
119 | #### 1. 作业概述
120 |
121 | 在这个 bonus 作业中,你的任务是通过实现特权指令来拓展 CPU 可模拟的功能。
122 |
123 | ##### 必须实现的功能:
124 |
125 | - **特权级别切换:** 允许在不同的特权级别之间切换
126 | - **中断和异常处理:** 管理中断和异常
127 |
128 | #### 2. 推荐实现的指令
129 |
130 | 以下是十个推荐的特权指令,这些指令涵盖了特权级别切换、中断和异常处理,以及控制和状态寄存器的操作。你可以将这些指令作为起点,同时也鼓励你尝试实现其他指令以增强 CPU 的功能。
131 |
132 | 1. **ECALL / EBREAK**
133 | 2. **MRET**
134 | 3. **CSRRW / CSRRS / CSRRC**
135 | 4. **CSRRWI / CSRRSI / CSRRCI**
136 | 5. **WFI**
137 | 6. **SRET**
138 | 7. **URET**
139 | 8. **FENCE.I**
140 | 9. **SFENCE.VMA**
141 | 10. **FENCE**
142 |
143 |
144 | ### Q & A (**这可能对你来说非常重要。**)
145 |
146 | 1. **我的 CPU 会从哪里读取指令并执行?**
147 |
148 | 从 `0x0000000` 地址处开始执行。
149 |
150 | 2. **我的 CPU 如何停机?**
151 |
152 | 见 `cpu.v` 中 `Specification` 部分。
153 |
154 | 3. **我的寄存器堆(Register File)需要多少个寄存器?**
155 |
156 | Unprivileged CPU: 32;
157 |
158 | Privileged CPU: 32 + 8 (CSR)。
159 |
160 | 4. **托马斯洛算法并没有硬件实现的公认唯一标准,那么本项目有什么特殊要求吗?**
161 |
162 | 托马斯洛的要求可参考 [Wikipedia](https://en.wikipedia.org/wiki/Tomasulo%27s_algorithm#Instruction_lifecycle),即执行一条指令需要涉及 *Issue*、*Execute*、*Write Result* 三步骤。此外,**必须要实现 *Instruction Cache*** 以确保程序运行过程中会出现多条指令的 lifecycle 重叠的情况。
163 |
164 | 5. **我该如何开始运行代码?**
165 |
166 | 在 `riscv/` 路径下运行 `make test_sim name=000` 指令即可自动编译并运行第一个仿真测试点,测试文件均在 `riscv/testspace/` 文件夹中。
167 |
168 | 6. **`io_buffer_full`?**
169 |
170 | 用于指示当前 ram 的 io buffer 是否已满。若已满,可能会出现 overwrite / loss。在FPGA debug阶段注意正确响应此信号。
171 |
172 | 注意:此信号在 simulation 部分始终为 low (false),但在 FPGA 上会有高低变化。所以在 simulation 中,你可以忽略此信号。
173 |
174 | 7. **`in_rdy`?**
175 |
176 | 用于指示当前hci总线是否为active (可工作),若否,则cpu应当pause。
177 |
178 | 8. **运行测试过程中 build 报错?**
179 |
180 | 请考虑以下几点:
181 |
182 | - 目录错误
183 |
184 | 脚本运行目录应当为 `riscv/` 文件夹
185 |
186 | - 环境缺失,如 `cannot find module -lgcc ...`
187 |
188 | **在配置了riscv-toolchains 的环境下,应当可以正常 build。**
189 |
190 | **请检查连接了 FPGA 的系统是否配置了 riscv-toolchains,若没有,你也可以使用现成的编译结果。**
191 |
192 | 9. **vivado如何debug?**
193 | 在vivado上入手过程是首先跑一遍synthesis和implementation,然后确保消除所有latch和multi-driven两种会影响程序正确性的warning,它们一般来自于simulation过程中没有考虑到的物理电路的特性。一般bug在保证了simulation的正确性,再加上适应电路的特性之后能得到解决。
194 |
195 | 10. to be continued...
196 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "serial"]
2 | path = serial
3 | url = https://github.com/wjwwood/serial
4 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/ChangeFreq.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACMClassCourse-2022/RISC-V-CPU-2023/ec253f029a987405359ee679ae397be53938d47a/doc/RISCV-CPU-doc/doc/ChangeFreq.pdf
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/Comments on hci.v.md:
--------------------------------------------------------------------------------
1 | #### hci.v
2 | `hci` 模块:该模块是主机通信接口,它使得能和调试的目标(FPGA硬件)和运行的主机进行串口通信,实现了与主机的数据交换和控制,其中:
3 | - 主机(Host)你的电脑,与FPGA板相连接;
4 | - 调试目标(Debug Target)硬件系统中被调试的目标设备,包含你的烧录到FPGA板的CPU、内存等组件;
5 |
6 | 这两个设备通过`hci`模块进行交互:`hci`接收主机发送的数据(Rx 输入端口),并向主机发送数据(Tx 输出端口)。hci在主机和调试目标之间进行双向的数据交流,比如主机可以将终端输入的数据发送到IO设备的输出总线(`io_dout`),并且将CPU的结果显示回主机屏幕。
7 | #### io_buffer_full
8 | `io_buffer_full`:我们的程序在串口通信中使用了通用非同步收发传输器(UART),由于接收和发送速率可能不同,为了保证数据的可靠传输,常常使用 FIFO(First-In-First-Out)缓冲区,称为UART buffer。这个缓冲区用于临时存储接收和发送的数据,并提供适当的流量控制机制,由于buffer的大小受到限制,所以主机和调试目标之间的通信也会受到限制,在buffer中没有空间时,就会将`io_buffer_full`信号拉至高电平,**此时如果继续通过缓冲区在主机和硬件之间通信会发生信息丢失错误,需要及时stall相应的程序操作**。
9 | 并且`io_buffer_full`的**信号是有延迟的**,写入一个byte后只有在**下一个时钟周期才能知道buffer的状态**,所以如果有连续的操作要向UART buffer写入数据请注意周期的判断和处理。
10 | #### 0x30000, 0x30004
11 | `0x30000`, `0x30004`: 向UART buffer读写从而实现正确通信在你的CPU中是通过物理地址重映射实现的
12 | - 写到地址`0x30000`的数据相当于被UART放入buffer中,发送给外部系统显示在终端屏幕;外部系统的终端输入通过uart串口通信放入`0x30000`从而可以被你的CPU读取
13 | - `0x30004`则用于向外部系统发送输出数据或指示程序停止的信号,同样是通过UART的CPU物理地址重映射作为buffer进行的
14 |
15 | 这些地址的重映射使得CPU能**通过类似内存读写的方式与外部的主机进行数据交换和控制**,但是需要注意上文提到的buffer限制了向这些特殊的内存读写的速率。
16 | #### riscv_top.v
17 | `riscv_top` 模块:这是顶层模块,将上述模块连接在一起。它接收输入信号,如时钟 (`EXCLK`)、按钮信号 (`btnC`) 和串口信号 (`Rx`)。然后,它使用这些信号来控制各个模块的工作,并从 `Tx` 输出串口信号和 `led` 输出 LED 控制信号。
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/FPGA debug by LED.md:
--------------------------------------------------------------------------------
1 | This is a tutorial about how to debug your design on FPGA using LED:
2 |
3 | First see `/riscv/src/Basys-3-Master.xdc`. You can find lines as:
4 |
5 | ```
6 | #set_property PACKAGE_PIN E19 [get_ports {led[1]}]
7 | #set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
8 | ```
9 |
10 | The meaning of the two line is to associate `led[1]`(as a wire) with LED no.1(which is named as `E19`) on FPGA. Uncomment the two lines to put them to use.
11 |
12 | Feel free to modify the name of the wire, you do not need to keep the name `led[1]`.
13 |
14 | The second step is to add the wire in your output of your top module. As an example, if I use:
15 |
16 | ```
17 | set_property PACKAGE_PIN E19 [get_ports {cpu_led_dbg}]
18 | set_property IOSTANDARD LVCMOS33 [get_ports {cpu_led_dbg}]
19 | ```
20 |
21 | Then I need to modify the `riscv_top.v` as:
22 |
23 | ```verilog
24 | module riscv_top
25 | #(
26 | parameter SIM = 0
27 | )
28 | (
29 | input wire EXCLK,
30 | input wire btnC,
31 | output wire Tx,
32 | input wire Rx,
33 | output wire led,
34 | output wire cpu_led_dbg // I add this line
35 | );
36 | ```
37 |
38 | Now as soon as `cpu_led_dbg=1` , the LED is turned on. Otherwise it is off.
39 |
40 | Mention that, you are not advised to associate a bit of an address with an LED, since this may result in a flicker: the address is modified every cycle(10ns), you need very good eyesight to catch the light.
41 |
42 | Connecting to other ports has nothing different. You can refer to Basys3 manual to get the id of each port.
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/HowToCompileTestCases.md:
--------------------------------------------------------------------------------
1 | # 如何编译测试点
2 | ## Step1. 安装riscv-gnu-toolchain
3 | > 为保证你实际使用的测试点与助教用于测试的测试点一致,你应该按照此教程配置正确版本的riscv-gnu-toolchain
4 |
5 | 在当前的仓库中, `riscv-gnu-toolchain` 已经以 submodule 的形式引入,你需要首先将其下载至本地。
6 |
7 | 在仓库根目录执行以下指令:(仓库较大,可能需要花费较长的时间下载)
8 | ``` bash
9 | git submodule update --init --recursive
10 | ```
11 |
12 | 接下来, 你需要编译并安装 `riscv-gnu-toolchain`,具体方法可见[此README](https://github.com/riscv-collab/riscv-gnu-toolchain/blob/b86b2b37d0acc607156ff56ff17ee105a9b48897/README.md),这里我们只做基本的介绍
13 |
14 | 在上一步之后,执行以下指令
15 |
16 | ``` bash
17 | cd riscv-gnu-toolchain
18 | ./configure --prefix=/opt/riscv --with-arch=rv32i --with-abi=ilp32
19 | sudo make
20 | ```
21 |
22 | 其中,第二条指令中的 `/opt/riscv` 为 `riscv-gnu-toolchain` 的安装路径,可自行修改,但同时需要修改仓库中 `riscv/Makefile` 中的 `riscv_toolchain` 和 `riscv/script/build_test.sh` 中的 `prefix` 与其一致。
23 |
24 | 安装完成后,可执行
25 |
26 | ``` bash
27 | /opt/riscv/bin/riscv32-unknown-elf-gcc --version
28 | ```
29 | 确认安装成功
30 |
31 | ## Step2. 编译测试点
32 | > 这里推荐使用编写好的 Makefile 进行编译
33 |
34 | 在 `riscv` 目录下执行
35 | ``` bash
36 | make build_sim_test name=000_array_test1
37 | ```
38 |
39 | 其中 `000_array_test1` 可以替换为你需要编译的测试点名称。
40 | 编译的结果为 `riscv/testspace` 中的 `test.data` `test.bin` 文件,另外 `test.dump` 文件展示了具体的汇编指令,可以在调试时作为参考。
41 |
42 | ## Tips
43 | 1. 在simulation阶段,编译测试点前需要确认 `riscv/sys/io.h` 中 `#define SIM` 生效,否则会导致某些测试点无法正确执行。
44 | 2. To be continue
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/Vivado_license_to2037.lic:
--------------------------------------------------------------------------------
1 | INCREMENT VIVADO_HLS xilinxd 2037.05 permanent uncounted AF3E86892AA2 \
2 | VENDOR_STRING=License_Type:Bought HOSTID=ANY ISSUER="Xilinx \
3 | Inc" START=18-May-2016 TS_OK
4 | INCREMENT Vivado_System_Edition xilinxd 2037.05 permanent uncounted \
5 | A1074C37F742 VENDOR_STRING=License_Type:Bought HOSTID=ANY \
6 | ISSUER="Xilinx Inc" START=19-May-2016 TS_OK
7 | PACKAGE Vivado_System_Edition xilinxd 2037.05 DFF4A65E0A68 \
8 | COMPONENTS="ISIM ChipScopePro_SIOTK PlanAhead ChipscopePro XPS \
9 | ISE HLS_Synthesis AccelDSP Vivado Rodin_Synthesis \
10 | Rodin_Implementation Rodin_SystemBuilder \
11 | PartialReconfiguration AUTOESL_FLOW AUTOESL_CC AUTOESL_OPT \
12 | AUTOESL_SC AUTOESL_XILINX petalinux_arch_ppc \
13 | petalinux_arch_microblaze petalinux_arch_zynq ap_sdsoc SDK \
14 | SysGen Simulation Implementation Analyzer HLS Synthesis \
15 | VIVADO_HLS" OPTIONS=SUITE
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/Yet Another FPGA Debug.md:
--------------------------------------------------------------------------------
1 | # Yet Another (useless) Debug Method
2 |
3 | 1. Use the `risc_top.v`, `Basys-3-Master.xdc`, `testbench.v`, `display_ctrl.v` in the folder.
4 | 2. Bind the wanted output to the `dbgreg_dout` of the `cpu` module.
5 | 3. Turn on `SW1` to turn on the display.
6 | 4. Turn on `SW0` to turn on manual control of `rdy`.
7 | 5. With `SW0` on, press `btnU` to step forward to the next `clk` period.
8 | 6. Set `DBG` in `testbench.v` to use in simulation.
9 |
10 | It's just what I did last year and may shed a light on what `Basys-3-Master.xdc` is used for. You may try modifying the control logic to realize breakpoints and more functions.
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/attach/fig1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACMClassCourse-2022/RISC-V-CPU-2023/ec253f029a987405359ee679ae397be53938d47a/doc/RISCV-CPU-doc/doc/attach/fig1.png
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/attach/fig2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACMClassCourse-2022/RISC-V-CPU-2023/ec253f029a987405359ee679ae397be53938d47a/doc/RISCV-CPU-doc/doc/attach/fig2.png
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/attach/fig3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACMClassCourse-2022/RISC-V-CPU-2023/ec253f029a987405359ee679ae397be53938d47a/doc/RISCV-CPU-doc/doc/attach/fig3.png
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/qweryy-Vivado-wsl2.md:
--------------------------------------------------------------------------------
1 | # Toy CPU 2022
2 |
3 | 基于 RV32I 指令集。
4 |
5 | ## 实现框架
6 |
7 | - Memory Controller
8 | - Instruction Cache
9 | - Instruction Fetcher
10 | - With Branch Predictor
11 | - Issue Module
12 | - Reservation Station
13 | - Reorder Buffer
14 | - Load and Store Buffer
15 | - Register File
16 |
17 | > To Do
18 |
19 | ## 运行效率
20 |
21 | 目前版本问题:`testsleep.c` 睡的时长偏小,且 `sleep(2000)` 时实际睡眠 clk 不足 1.9 s。
22 |
23 | 上一版本问题:睡眠正常但运行时间过慢(`heart.c` 1968 s)。经严格控制变量后发现问题不在 Branch Predictor 而在于以下 Warning:
24 |
25 | ```
26 | WARNING: [Synth 8-4767] Trying to implement RAM 'valid_reg' in registers. Block RAM or DRAM implementation is not possible; see log for reasons.
27 | Reason is one or more of the following :
28 | 1: Invalid write to RAM.
29 | 2: Unable to determine number of words or word size in RAM.
30 | 3: No valid read/write found for RAM.
31 | RAM "valid_reg" dissolved into registers
32 | ```
33 |
34 | 产生该 Warning 是因为某种不规范的初始化方式。
35 |
36 | ------
37 |
38 | 上板频率 100 MHz,WNS = -0.721 ns。
39 |
40 | | 测试点名称 | 运行时间(s) |
41 | | -------------- | ------------ |
42 | | array_test1 | 0.018041 |
43 | | array_test2 | 0.007438 |
44 | | basicopt1 | 0.018451 |
45 | | bulgarian | 1.731970 |
46 | | expr | 0.009880 |
47 | | gcd | 0.006399 |
48 | | hanoi | 3.545234 |
49 | | heart | 586.205736 |
50 | | looper | 2.008588 |
51 | | lvalue2 | 0.014634 |
52 | | magic | 0.033122 |
53 | | manyarguments | 0.016577 |
54 | | multiarray | 0.017369 |
55 | | pi | 1.608805 |
56 | | qsort | 6.536273 |
57 | | queens | 3.126208 |
58 | | statement_test | 0.004048 |
59 | | superloop | 0.014961 |
60 | | tak | 0.072251 |
61 | | testsleep | 10.008813 |
62 | | uartboom | 0.784658 |
63 |
64 | ## 难调的 bug
65 |
66 | 懒得整理了,见[草稿](attach/cpu_draft.pdf)。
67 |
68 | ## WSL2 上板指引
69 |
70 | > Microsoft 官方文档:https://learn.microsoft.com/zh-cn/windows/wsl/connect-usb
71 |
72 | ### 预备
73 |
74 | 根据官方文档先完成 [USBIPD-WIN](https://learn.microsoft.com/en-us/windows/wsl/connect-usb#install-the-usbipd-win-project) 与 [USBIP tools and hardware database in Linux](https://learn.microsoft.com/en-us/windows/wsl/connect-usb#install-the-usbipd-win-project) 的安装。
75 |
76 | ### 将 `.bit` 文件写入板中
77 |
78 | 在使用数据线连接好 FPGA 板后根据助教的文档操作即可。
79 |
80 | ### 连接 FPGA 板至 WSL2
81 |
82 | 注:接下来需要注意命令的运行环境(以**粗体**注明)。
83 |
84 | 1. 以管理员模式打开 **PowerShell**,输入以下命令列出所有连接到 Windows 的 USB 设备。
85 |
86 | ```powershell
87 | usbipd wsl list
88 | ```
89 |
90 | 
91 |
92 | 2. 找到 FPGA 板(设备名称应该是 `USB Serial Converter A, USB Serial Converter B`)的 bus ID,然后执行
93 |
94 | ```powershell
95 | usbipd wsl attach --busid
96 | ```
97 |
98 | 
99 |
100 | 3. 在 **WSL** 中,可以使用以下命令确认是否连接成功。
101 |
102 | ```bash
103 | lsusb
104 | ```
105 |
106 | 
107 |
108 | ### 修改 `run_test_fpga.sh` 的端口
109 |
110 | 与 WSL1 不同,应为 `/dev/ttyUSB1`(或者可能为其它数字,可以通过 attach 前后 `ls /dev/` 大致辨别)。
111 |
112 | ### 访问权限
113 |
114 | 通常情况下 attach 至 WSL2 的设备是不允许非 root 用户访问的。有几种方案:
115 |
116 | 1. 配置 udev 规则。~~我不会()~~
117 | 2. 使用你喜欢的方式直接修改设备文件权限,例如
118 |
119 | ```bash
120 | sudo chmod 777 /dev/ttyUSB1
121 | ```
122 |
123 | 不过在该种方法下,每次重新连接设备时都要执行一遍。
124 |
125 | 之后理论上便可成功执行 `./run_test_fpga.sh` 来测试你的硬件代码。
126 |
127 | ### 断开连接(或需要 reprogram 时)
128 |
129 | 当你需要对 FPGA 板重新编程时,需将板重新连回 Windows 中。在 **PowerShell** 下执行
130 |
131 | ```powershell
132 | usbipd wsl detach --busid
133 | ```
134 |
135 | 以断开该设备与 WSL 的连接,然后你可以使用 Vivado 对其重新编程。当你准备好再次测试时,重复上述连接步骤即可。
136 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/simulation debug method.md:
--------------------------------------------------------------------------------
1 | In this note, we proffer some naïve methods to debug.
2 |
3 | ##### Use testcases
4 |
5 | The first is to compile a testcase and use the compiled `test.data` to debug. Here are some typical testcases:
6 |
7 | 1. gcd. This is very easy and short.
8 | 2. expr, a bit larger.
9 | 3. heart, pi. Only simulating some steps is enough.
10 | 4. Bulgarian, especially for FPGA test.
11 |
12 | ##### Hand-writing test.data
13 |
14 | Write your own `test.data`. It is nothing but a sequence of RISCV instructions. For example, if the file is:
15 |
16 | ```
17 | @00000000
18 | 83 20 00 00
19 | ```
20 |
21 | Since the instruction is `8h'00002083=32b'000000000000 00000 010 00001 0000011`, which means `ld r1, r0(0)`, it loads a word from address `0x00000000` to register 1, after executing this file, the value in register 1 should be 0x2083.
22 |
23 | ##### Testbench
24 |
25 | Writing a testbench can be a good idea when you want to test a single module. What you need is a testbench like `/riscv/sim/testbench`. Here we provide a testbench file of the Verilog practice homework `diff8r`:
26 |
27 | ```
28 | module test_bench;
29 | reg clk = 0;
30 | always #5 clk = ~clk; // Create clock with period=10
31 | reg [7:0] d;
32 | wire [7:0] q, ans;
33 |
34 | integer i = 0;
35 | reg wrong = 0, wrong2 = 0, rst = 1;
36 |
37 | top_module ff0( .clk(clk), .reset(rst), .d(d), .q(q));
38 | std ff1( .clk(clk), .reset(rst), .d(d), .q(ans));
39 |
40 | initial begin
41 | #10;
42 | if (d != q) wrong = 1;
43 | rst = 0;
44 | #200;
45 | if (wrong | wrong2) begin
46 | $display("Wrong Answer");
47 | end else begin
48 | $display("Accepted");
49 | end
50 | $finish;
51 | end
52 | always @(posedge clk) begin
53 | if (rst) begin
54 | d <= 0;
55 | end else begin
56 | $display("%d", d);
57 | d <= d - 1;
58 | end
59 | end
60 |
61 | always @(*) begin
62 | if (rst) begin
63 | wrong2 = 0;
64 | end else begin
65 | wrong2 |= q != ans;
66 | end
67 | end
68 | endmodule
69 | ```
70 |
71 | You can read `/riscv/sim/testbench.v` for more. In all, a testbench has:
72 |
73 | 1. connection with tested module. In this file, it is the `top_module`.
74 | 2. simulated clock. In this file, it is `always #5 clk=~clk;`. In `/riscv/sim/testbench.v` it is the `forever(10) #1 clk=!clk;`
75 | 3. `$finish` in correct time.
76 | 4. A sophisticated designed input, which can be more flexible than a `test.data`.
77 | 5. Optional, `$display` as a hint.
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/src/sim/testbench.v:
--------------------------------------------------------------------------------
1 | // testbench top module file
2 | // for simulation only
3 |
4 | //`timescale 1ns/1ps
5 | module testbench;
6 |
7 | localparam DBG = 1'b0;
8 |
9 | reg clk;
10 | reg rst;
11 | reg manual_clk;
12 |
13 | riscv_top #(.SIM(1)) top(
14 | .EXCLK(clk),
15 | .btnC(rst),
16 | .btnU(manual_clk),
17 | .sw(DBG),
18 | .Tx(),
19 | .Rx(),
20 | .led(),
21 | .seg(),
22 | .dp(),
23 | .an()
24 | );
25 |
26 | initial begin
27 | clk=0;
28 | manual_clk=0;
29 | rst=1;
30 | repeat(50) #1 clk=!clk;
31 | rst=0;
32 | forever begin
33 | #1 clk=!clk;
34 | #1 clk=!clk;
35 | #1 clk=!clk;
36 | #1 clk=!clk;
37 | #1 clk=!clk;
38 | #1 clk=!clk;
39 | manual_clk=!manual_clk;
40 | end
41 |
42 | $finish;
43 | end
44 |
45 | endmodule
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/src/src/display_ctrl.v:
--------------------------------------------------------------------------------
1 | module display_ctrl
2 | #(
3 | parameter SYS_CLK_FREQ = 100000000,
4 | parameter DISPLAY_REFRESH_RATE = 5000000
5 | )
6 | (
7 | input wire clk,
8 | input wire rst,
9 | input wire en,
10 | input wire [15:0] val,
11 | output reg [ 6:0] seg,
12 | output reg dp,
13 | output reg [ 3:0] an
14 | );
15 |
16 | reg [19:0] cnt;
17 |
18 | always @(posedge clk or posedge rst) begin
19 | if(rst)
20 | cnt <= 0;
21 | else
22 | cnt <= cnt + 1;
23 | end
24 |
25 | reg [3:0] digit;
26 | wire [1:0] d_num;
27 | assign d_num[1:0] = cnt[19:18];
28 |
29 | always @(*) begin
30 | if (rst || !en) begin
31 | digit = 4'b0;
32 | end else begin
33 | case (d_num)
34 | 2'b00: digit = val[ 3: 0];
35 | 2'b01: digit = val[ 7: 4];
36 | 2'b10: digit = val[11: 8];
37 | 2'b11: digit = val[15:12];
38 | endcase
39 | end
40 | end
41 |
42 | always @(*) begin
43 | if (rst || !en) begin
44 | an = 4'b1111;
45 | end else begin
46 | case (d_num)
47 | 2'b00: an = 4'b1110;
48 | 2'b01: an = 4'b1101;
49 | 2'b10: an = 4'b1011;
50 | 2'b11: an = 4'b0111;
51 | endcase
52 | end
53 | end
54 |
55 | always @(*) begin
56 | if (rst || !en) begin
57 | {seg, dp} = 8'b11111111;
58 | end else begin
59 | case (digit)
60 | 4'h0: {seg, dp} = 8'b10000001;
61 | 4'h1: {seg, dp} = 8'b11110011;
62 | 4'h2: {seg, dp} = 8'b01001001;
63 | 4'h3: {seg, dp} = 8'b01100001;
64 | 4'h4: {seg, dp} = 8'b00110011;
65 | 4'h5: {seg, dp} = 8'b00100101;
66 | 4'h6: {seg, dp} = 8'b00000101;
67 | 4'h7: {seg, dp} = 8'b11110001;
68 | 4'h8: {seg, dp} = 8'b00000001;
69 | 4'h9: {seg, dp} = 8'b00100001;
70 | 4'ha: {seg, dp} = 8'b00010001;
71 | 4'hb: {seg, dp} = 8'b00000111;
72 | 4'hc: {seg, dp} = 8'b10001101;
73 | 4'hd: {seg, dp} = 8'b01000011;
74 | 4'he: {seg, dp} = 8'b00001101;
75 | 4'hf: {seg, dp} = 8'b00011101;
76 | endcase
77 | end
78 | end
79 |
80 | endmodule : display_ctrl
81 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/src/src/riscv_top.v:
--------------------------------------------------------------------------------
1 | // riscv top module file
2 | // modification allowed for debugging purposes
3 |
4 | module riscv_top
5 | #(
6 | parameter SIM = 0 // whether in simulation
7 | )
8 | (
9 | input wire EXCLK,
10 | input wire btnC,
11 | input wire btnU,
12 | input wire [1:0] sw,
13 | output wire Tx,
14 | input wire Rx,
15 | output wire [3:0] led,
16 | output wire [6:0] seg,
17 | output wire dp,
18 | output wire [3:0] an
19 | );
20 |
21 | localparam SYS_CLK_FREQ = 100000000;
22 | localparam UART_BAUD_RATE = 115200;
23 | localparam RAM_ADDR_WIDTH = 17; // 128KiB ram, should not be modified
24 |
25 | localparam DISPLAY_REFRESH_RATE = 500000;
26 |
27 | localparam OPT_DBG = 0;
28 |
29 | reg rst;
30 | reg rst_delay;
31 |
32 | wire clk;
33 |
34 | // assign EXCLK (or your own clock module) to clk
35 | assign clk = EXCLK;
36 | // wire locked;
37 | // clk_wiz_0 NEW_CLK(
38 | // .reset(btnC),
39 | // .clk_in1(EXCLK),
40 | // .clk_out1(clk),
41 | // .locked(locked)
42 | // );
43 |
44 | always @(posedge clk or posedge btnC)
45 | begin
46 | if (btnC)
47 | begin
48 | rst <= 1'b1;
49 | rst_delay <= 1'b1;
50 | end
51 | else
52 | begin
53 | rst_delay <= 1'b0;
54 | rst <= rst_delay;
55 | end
56 | end
57 |
58 | //
59 | // System Memory Buses
60 | //
61 | wire [ 7:0] cpumc_din;
62 | wire [31:0] cpumc_a;
63 | wire cpumc_wr;
64 |
65 | //
66 | // RAM: internal ram
67 | //
68 | wire ram_en;
69 | wire [RAM_ADDR_WIDTH-1:0] ram_a;
70 | wire [ 7:0] ram_dout;
71 |
72 | ram #(.ADDR_WIDTH(RAM_ADDR_WIDTH))ram0(
73 | .clk_in(clk),
74 | .en_in(ram_en && (sw[0] ? manual_clk : 1'b1)),
75 | .r_nw_in(~cpumc_wr),
76 | .a_in(ram_a),
77 | .d_in(cpumc_din),
78 | .d_out(ram_dout)
79 | );
80 |
81 | assign ram_en = (cpumc_a[RAM_ADDR_WIDTH:RAM_ADDR_WIDTH-1] == 2'b11) ? 1'b0 : 1'b1;
82 | assign ram_a = cpumc_a[RAM_ADDR_WIDTH-1:0];
83 |
84 | //
85 | // CPU: CPU that implements RISC-V 32b integer base user-level real-mode ISA
86 | //
87 | wire [31:0] cpu_ram_a;
88 | wire cpu_ram_wr;
89 | wire [ 7:0] cpu_ram_din;
90 | wire [ 7:0] cpu_ram_dout;
91 | wire cpu_rdy;
92 |
93 | wire [31:0] cpu_dbgreg_dout;
94 |
95 |
96 | //
97 | // HCI: host communication interface block. Use controller to interact.
98 | //
99 | wire hci_active_out;
100 | wire [ 7:0] hci_ram_din;
101 | wire [ 7:0] hci_ram_dout;
102 | wire [RAM_ADDR_WIDTH-1:0] hci_ram_a;
103 | wire hci_ram_wr;
104 |
105 | wire hci_io_en;
106 | wire [ 2:0] hci_io_sel;
107 | wire [ 7:0] hci_io_din;
108 | wire [ 7:0] hci_io_dout;
109 | wire hci_io_wr;
110 | wire hci_io_full;
111 |
112 | reg q_hci_io_en;
113 |
114 | cpu #(.DBG(OPT_DBG)) cpu0
115 | (
116 | .clk_in(clk),
117 | .rst_in(rst),
118 | .rdy_in(cpu_rdy),
119 |
120 | .mem_din(cpu_ram_din),
121 | .mem_dout(cpu_ram_dout),
122 | .mem_a(cpu_ram_a),
123 | .mem_wr(cpu_ram_wr),
124 |
125 | .io_buffer_full(hci_io_full),
126 |
127 | .dbgreg_dout(cpu_dbgreg_dout)
128 | );
129 |
130 | hci #(.SYS_CLK_FREQ(SYS_CLK_FREQ),
131 | .RAM_ADDR_WIDTH(RAM_ADDR_WIDTH),
132 | .BAUD_RATE(UART_BAUD_RATE),
133 | .DBG(OPT_DBG)) hci0
134 | (
135 | .clk(clk),
136 | .rst(rst),
137 | .tx(Tx),
138 | .rx(Rx),
139 | .active(hci_active_out),
140 | .ram_din(hci_ram_din),
141 | .ram_dout(hci_ram_dout),
142 | .ram_a(hci_ram_a),
143 | .ram_wr(hci_ram_wr),
144 | .io_sel(hci_io_sel),
145 | .io_en(hci_io_en),
146 | .io_din(hci_io_din),
147 | .io_dout(hci_io_dout),
148 | .io_wr(hci_io_wr),
149 | .io_full(hci_io_full),
150 |
151 | .cpu_dbgreg_din(cpu_dbgreg_dout) // demo
152 | );
153 |
154 | assign hci_io_sel = cpumc_a[2:0];
155 | assign hci_io_en = (cpumc_a[RAM_ADDR_WIDTH:RAM_ADDR_WIDTH-1] == 2'b11) ? 1'b1 : 1'b0;
156 | assign hci_io_wr = cpumc_wr;
157 | assign hci_io_din = cpumc_din;
158 |
159 | // hci is always disabled in simulation
160 | wire hci_active;
161 | assign hci_active = hci_active_out & ~SIM;
162 |
163 | // seven segment display pc
164 | display_ctrl #(.SYS_CLK_FREQ(SYS_CLK_FREQ),
165 | .DISPLAY_REFRESH_RATE(DISPLAY_REFRESH_RATE)) display_ctrl0
166 | (
167 | .clk(clk),
168 | .rst(rst),
169 | .en(sw[1] & !SIM),
170 | .val(cpu_dbgreg_dout[15:0]),
171 | .seg(seg),
172 | .dp(dp),
173 | .an(an)
174 | );
175 |
176 | // manual clk
177 | reg r1, r2, r3;
178 |
179 | always @(posedge clk) begin
180 | r1 <= btnU;
181 | r2 <= r1;
182 | r3 <= r2;
183 | end
184 |
185 | assign manual_clk = ~r3 & r2;
186 |
187 | // indicates debug break
188 | assign led = {cpu_dbgreg_dout[16], sw[1], sw[0], hci_active};
189 |
190 | // pause cpu on hci active
191 | assign cpu_rdy = (hci_active) ? 1'b0 : sw[0] ? manual_clk : 1'b1;
192 |
193 | // Mux cpumc signals from cpu or hci blk, depending on debug break state (hci_active).
194 | assign cpumc_a = (hci_active) ? hci_ram_a : cpu_ram_a;
195 | assign cpumc_wr = (hci_active) ? hci_ram_wr : cpu_ram_wr;
196 | assign cpumc_din = (hci_active) ? hci_ram_dout : cpu_ram_dout;
197 |
198 | // Fixed 2020-10-06: Inconsisitency of return value with I/O state
199 | always @ (posedge clk) begin
200 | q_hci_io_en <= hci_io_en;
201 | end
202 |
203 | assign cpu_ram_din = (q_hci_io_en) ? hci_io_dout : ram_dout;
204 |
205 | assign hci_ram_din = ram_dout;
206 |
207 | endmodule
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/vivadoDemo.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACMClassCourse-2022/RISC-V-CPU-2023/ec253f029a987405359ee679ae397be53938d47a/doc/RISCV-CPU-doc/doc/vivadoDemo.pdf
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/体系结构I 环境配置参考.md:
--------------------------------------------------------------------------------
1 | # 体系结构I 环境配置参考
2 |
3 | ## Vivado 安装指引
4 |
5 | (以下操作基于kubuntu 20.04 LTS)
6 |
7 | 1. 获取安装包(2018.2: https://jbox.sjtu.edu.cn/l/noXqCD )
8 |
9 | 2. 对于2018.2,使用gui安装即可;对于2020.1,执行以下命令
10 |
11 | ```
12 | sudo ./xsetup -b ConfigGen
13 | ```
14 |
15 | ```
16 | sudo ./xsetup --agree XilinxEULA,3rdPartyEULA,WebTalkTerms --batch Install --config /root/.Xilinx/install_config.txt
17 | ```
18 |
19 | (第一条命令生成config,根据环境不同第二行命令中config路径可能不同,请参考第一行命令输出)
20 |
21 | 一般通过执行/tools/Xilinx/Vivado/2020.1/bin/vivado来打开vivado
22 |
23 | 3. (Optional) 创建快捷方式:在~/Desktop/(桌面)或/usr/share/applications/(快捷启动)下建立`vivido.desktop`文件,内容为(以下为2020.1示例,2018.2自行对照,2018.2安装目录通常为/opt/而非/tools/)
24 |
25 | ```
26 | [Desktop Entry]
27 | Encoding=UTF-8
28 | Type=Application
29 | Name=Vivado 2020.1
30 | Comment=Vivado 2020.1
31 | Icon=/tools/Xilinx/Vivado/2020.1/doc/images/vivado_logo.png
32 | Exec={path to your launch script/exectuable}
33 | ```
34 |
35 | (kde/gnome方法,不保证xfce下可用,若不可用建议自己查询对应方法)
36 |
37 | ### 可能问题
38 |
39 | 1. 出现如下错误
40 |
41 | ```
42 | terminate called after throwing an instance of 'std::runtime_error'
43 | what(): locale::facet::_S_create_c_locale name not valid
44 | /opt/Xilinx/Vivado/2016.4/bin/loader: line 179: 2309 Aborted (core dumped) "$RDI_PROG" "$@"
45 | ```
46 |
47 | 解决方法:将环境改变至en_US
48 |
49 | 在终端执行以下代码以改变环境变量
50 |
51 | ```
52 | export LC_ALL="en_US.UTF-8"
53 | ```
54 |
55 | 若需要这样解决,通常需要创建launch script,并在script里执行export命令后再启动vivado
56 |
57 |
58 |
59 | 2. ```
60 | application-specific initialization failed: couldn't load file "librdi_commontasks.so": libtinfo.so.5: cannot open shared object file: No such file or directory
61 | ```
62 |
63 | 解决方法:安装libtinfo-dev,再执行
64 |
65 | ```
66 | sudo ln -s /lib/x86_64-linux-gnu/libtinfo.so.6 /lib/x86_64-linux-gnu/libtinfo.so.5
67 | ```
68 |
69 | 3. 激活:使用vivado2037.llc
70 |
71 | 使用方法见https://www.cnblogs.com/maskerk/p/7350182.html
72 |
73 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/doc/支持中断.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACMClassCourse-2022/RISC-V-CPU-2023/ec253f029a987405359ee679ae397be53938d47a/doc/RISCV-CPU-doc/doc/支持中断.pdf
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/FPGA_test.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 |
4 | isWin = sys.platform[:3] == 'win'
5 | wslPrefix = 'ubuntu.exe run ' if isWin else ''
6 |
7 | test_cases_dir = './testcase'
8 | path_of_bit = 'C:/a.bit' # A Windows-style path is ok if you runs on Windows
9 | excluded_test_cases = []
10 |
11 | color_red = "\033[0;31m"
12 | color_green = "\033[0;32m"
13 | color_none = "\033[0m"
14 |
15 |
16 | def program_device():
17 | os.system('vivado -nolog -nojournal -notrace -mode batch -source pd.tcl -tclarg ' + path_of_bit + ' > ' + ('NUL' if isWin else '/dev/null'))
18 |
19 | def collect_test_cases():
20 | test_cases = []
21 | for f in os.listdir(test_cases_dir):
22 | if os.path.splitext(f)[1] == '.ans':
23 | test_cases.append(os.path.splitext(os.path.split(f)[1])[0])
24 | for s in excluded_test_cases:
25 | if s in test_cases: test_cases.remove(s)
26 | test_cases.sort()
27 | return test_cases
28 |
29 | def main():
30 | program_device()
31 | test_cases = collect_test_cases()
32 |
33 | print('Build controller...')
34 | if os.system(wslPrefix + './ctrl/build.sh'):
35 | print(color_red + 'Build Failed' + color_none)
36 | return
37 | print(color_green + 'Success' + color_none)
38 |
39 | for t in test_cases:
40 | print('Testing ' + t + ': ')
41 | if os.system(wslPrefix + './autorun_fpga.sh ' + t):
42 | print(color_red + 'Test Failed' + color_none)
43 | continue
44 | if os.system(wslPrefix + 'diff ./test/test.ans ./test/test.out > diff.out'):
45 | print(color_red + 'Wrong Answer' + color_none)
46 | continue
47 | print(color_green + 'Accepted' + color_none)
48 |
49 | if __name__ == '__main__':
50 | main()
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/autorun_fpga.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # build testcase
3 | ./build_test.sh $@
4 | # copy test input
5 | if [ -f ./testcase/$@.in ]; then cp ./testcase/$@.in ./test/test.in; fi
6 | # copy test output
7 | if [ -f ./testcase/$@.ans ]; then cp ./testcase/$@.ans ./test/test.ans; fi
8 | # add your own test script here
9 | # Example: assuming serial port on /dev/ttyUSB1
10 | # ./ctrl/build.sh
11 | # ./ctrl/run.sh ./test/test.bin ./test/test.in /dev/ttyUSB1 -I
12 | ./ctrl/run.sh ./test/test.bin ./test/test.in /dev/ttyUSB1 -T > ./test/test.out
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/build_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 | prefix='/opt/riscv'
4 | rpath=$prefix/bin/
5 | # clearing test dir
6 | rm -rf ./test
7 | mkdir ./test
8 | # compiling rom
9 | ${rpath}riscv32-unknown-elf-as -o ./sys/rom.o -march=rv32i ./sys/rom.s
10 | # compiling testcase
11 | cp ./testcase/${1%.*}.c ./test/test.c
12 | ${rpath}riscv32-unknown-elf-gcc -o ./test/test.o -I ./sys -c ./test/test.c -O2 -march=rv32i -mabi=ilp32 -Wall
13 | # linking
14 | ${rpath}riscv32-unknown-elf-ld -T ./sys/memory.ld ./sys/rom.o ./test/test.o -L $prefix/riscv32-unknown-elf/lib/ -L $prefix/lib/gcc/riscv32-unknown-elf/8.2.0/ -lc -lgcc -lm -lnosys -o ./test/test.om
15 | # converting to verilog format
16 | ${rpath}riscv32-unknown-elf-objcopy -O verilog ./test/test.om ./test/test.data
17 | # converting to binary format(for ram uploading)
18 | ${rpath}riscv32-unknown-elf-objcopy -O binary ./test/test.om ./test/test.bin
19 | # decompile (for debugging)
20 | ${rpath}riscv32-unknown-elf-objdump -D ./test/test.om > ./test/test.dump
21 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/ctrl/build.sh:
--------------------------------------------------------------------------------
1 | set -e
2 | dir=`dirname $0`
3 | g++ $dir/controller.cpp -std=c++14 -I /tmp/usr/local/include/ -L /tmp/usr/local/lib/ -lserial -lpthread -o $dir/ctrl
4 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/ctrl/controller.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | int run_mode;
9 |
10 | #define error(msg...) printf(msg)
11 | #define info(msg...) do{if(run_mode) printf(msg);}while(0)
12 |
13 | typedef std::uint8_t byte;
14 | typedef std::uint16_t word;
15 | typedef std::uint32_t dword;
16 |
17 | serial::Serial serPort;
18 |
19 | void uart_send(const byte *data, int send_count, byte* recv, int return_count) {
20 | serPort.write(data,send_count);
21 | if (!return_count) return;
22 | try {
23 | serPort.read(recv,return_count);
24 | } catch (std::exception &e) {
25 | error("recv error: %s\n",e.what());
26 | }
27 | }
28 | void uart_send(const std::vector data, byte* recv, int return_count) {
29 | uart_send(data.data(),data.size(),recv,return_count);
30 | }
31 | void uart_send(const std::string &data) { serPort.write(data); }
32 | void uart_send(const byte *data, int size) { serPort.write(data,size); }
33 | void uart_send(const std::vector &data) { serPort.write(data); }
34 | void uart_read(byte *data, int size) { serPort.read(data, size); }
35 |
36 | #include "listener.h"
37 |
38 | int init_port(char* port) {
39 | serPort.setPort(port);
40 | serPort.setBaudrate(baud_rate);
41 | serPort.setBytesize(byte_size);
42 | serPort.setParity(parity);
43 | serPort.setStopbits(stopbits);
44 | serPort.setTimeout(
45 | inter_byte_timeout,
46 | read_timeout_constant,
47 | read_timeout_multiplier,
48 | write_timeout_constant,
49 | write_timeout_multiplier
50 | );
51 | try {
52 | serPort.open();
53 | } catch (std::exception &e) {
54 | error("failed to open port: %s\n",e.what());
55 | return 1;
56 | }
57 | info("initialized UART port on: %s\n",port);
58 | return 0;
59 | }
60 |
61 | byte ram_data[0x40000];
62 | byte in_data[0x400];
63 |
64 | int load_ram(char* rom_path) {
65 | std::ifstream fin(rom_path);
66 | if (!fin.is_open()) return 0;
67 | fin.seekg(0, std::ios_base::end);
68 | int ram_size = fin.tellg();
69 | info("RAM size: %x\n", ram_size);
70 | fin.seekg(0, std::ios_base::beg);
71 | fin.read(reinterpret_cast(ram_data), ram_size);
72 | for (int i=0;i<0x40; ++i) {
73 | info("%02x ", (byte)ram_data[i+0x1000]);
74 | if (!((i+1)%16)) info("\n");
75 | }
76 | fin.close();
77 | return ram_size;
78 | }
79 |
80 | int load_input(char* in_path) {
81 | if (!in_path) return 0;
82 | std::ifstream fin(in_path);
83 | if (!fin.is_open()) return 0;
84 | fin.seekg(0, std::ios_base::end);
85 | int in_size = fin.tellg();
86 | info("INPUT size: %x\n", in_size);
87 | fin.seekg(0, std::ios_base::beg);
88 | fin.read(reinterpret_cast(in_data), in_size);
89 | for (int i=0;i<0x10; ++i) {
90 | info("%02x ", (byte)in_data[i]);
91 | if (!((i+1)%16)) info("\n");
92 | }
93 | fin.close();
94 | return in_size;
95 | }
96 |
97 | clock_t start_tm;
98 | clock_t end_tm;
99 |
100 | void run() {
101 | // demo
102 |
103 | // debug packet format: see hci.v or README.md
104 | // send[0] is always OPCODE
105 | // to send debug packets, use uart_send(send,send_count)
106 | // to receive data after send, use uart_send(send,send_count,recv,recv_count)
107 | char c;
108 | int run = 0;
109 | while (1){
110 | info("Enter r to run, q to quit, p to get cpu PC(demo)\n");
111 | c=getchar();
112 | if (c=='q') {
113 | break;
114 | }
115 | else if (c=='p') {
116 | // demo for debugging cpu
117 | // add support in hci.v to allow more debug operations
118 | byte send[6]={0};
119 | byte recv[64]={0};
120 | send[0]=0x01;
121 | uart_send(send,1,recv,4);
122 | int pc = *reinterpret_cast(recv);
123 | info("pc:%08x\n",pc);
124 | send[0] = 0x09;
125 | int get_size = 16;
126 | *reinterpret_cast(send+1)=pc;
127 | *reinterpret_cast(send+4)=get_size;
128 | uart_send(send,6,recv,get_size);
129 | for (int i=0;i<16;++i) {
130 | info("%02x ",recv[i]);
131 | }
132 | info("\n");
133 | }
134 | else if (c=='r') {
135 | // run or pause cpu
136 | byte send[2];
137 | send[0]=(run?0x03:0x04);
138 | run = !run;
139 | info("CPU start\n");
140 | uart_send(send,1);
141 | start_tm = clock();
142 | // receive output bytes from fpga
143 | while (1) {
144 | byte data;
145 | // to debug cpu at the same time, implement separate thread
146 | while (!serPort.available());
147 | uart_read(&data,1);
148 | if (on_recv(data)) break;
149 | }
150 | end_tm = clock();
151 | info("\nCPU returned with running time: %f\n",(double)(end_tm - start_tm) / CLOCKS_PER_SEC);
152 |
153 | // manually pressing reset button is recommended
154 |
155 | // or pause and reset cpu through uart (TODO)
156 | // send[0]=(run?0x03:0x04);
157 | // run = !run;
158 | // uart_send(send,1);
159 |
160 | return;
161 | }
162 | }
163 | }
164 |
165 | void run_auto() {
166 | byte send[2];
167 | send[0]=(0x04);
168 | uart_send(send,1);
169 | start_tm = clock();
170 | while (1) {
171 | byte data;
172 | while (!serPort.available());
173 | uart_read(&data,1);
174 | if (data==0) break;
175 | putchar(data);
176 | }
177 | end_tm = clock();
178 | }
179 |
180 | int main(int argc, char** argv) {
181 | if (argc<4) {
182 | error("usage: path-to-ram [path-to-input] com-port -I(interactive)/-T(testing)\n");
183 | return 1;
184 | }
185 | char* ram_path = argv[1];
186 | int no_input = argc<5;
187 | char* input_path = no_input ? NULL : argv[2];
188 | char* comport = argv[argc-2];
189 | char param = argv[argc-1][1];
190 | if (param=='I') {
191 | run_mode = 1;
192 | } else if (param=='T') {
193 | run_mode = 0;
194 | }
195 | int ram_size = 0, in_size = 0;
196 | if (!(ram_size=load_ram(ram_path))) {
197 | error("failed to read ram file\n");
198 | return 1;
199 | }
200 | if (!no_input && !(in_size=load_input(input_path))){
201 | info("input file not found, skipping\n");
202 | }
203 | if (init_port(comport)) return 1;
204 | if (on_init()) return 1;
205 | upload_ram(ram_data, ram_size);
206 | upload_input(in_data, in_size);
207 | // verify_ram(ram_data, ram_size);
208 | if (run_mode) run();
209 | else run_auto();
210 | serPort.close();
211 | }
212 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/ctrl/listener.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | // UART port configuration, adjust according to implementation
9 | int baud_rate = 115200;
10 | serial::bytesize_t byte_size = serial::eightbits;
11 | serial::parity_t parity = serial::parity_odd;
12 | serial::stopbits_t stopbits = serial::stopbits_one;
13 | int inter_byte_timeout = 50;
14 | int read_timeout_constant = 50;
15 | int read_timeout_multiplier = 10;
16 | int write_timeout_constant = 50;
17 | int write_timeout_multiplier = 10;
18 |
19 | //methods
20 | int on_init() {
21 | using namespace std::chrono_literals;
22 | byte junk[10];
23 | uart_read(junk,8);
24 | std::this_thread::sleep_for(std::chrono::seconds(1));
25 | byte init[10];
26 | byte recv[10]={0};
27 | init[0] = 0x00;
28 | int len = 4;
29 | *reinterpret_cast(init+1) = len;
30 | char test[10] = "UART";
31 | for (int i=0;i(recv);
42 | if (strcmp(str,test)) {
43 | error("UART assertion failed\n");
44 | return 1;
45 | }
46 | return 0;
47 | }
48 |
49 | void upload_ram(byte* ram_data, int ram_size) {
50 | if (!ram_size) return;
51 | const int short blk_size = 0x400;
52 | const int pld_size = 1+3+2+blk_size;
53 | byte payload[pld_size];
54 | int blk_cnt = (ram_size / blk_size);
55 | if (blk_cnt*blk_size(payload+1) = addr;
63 | *reinterpret_cast(payload+4) = blk_size;
64 | for (int j=0;j(payload+1) = pre_size;
85 | uart_send(payload,1+2+pre_size);
86 | int rem_size = in_size;
87 | for (int i=0; i(payload+1) = dat_size;
93 | for (int j=0;j(payload+1) = addr;
117 | *reinterpret_cast(payload+4) = blk_size;
118 | uart_send(payload,6,recv_data,blk_size);
119 | for (int j=0; j ./test/test.out
13 | #if [ -f ./test/test.ans ]; then diff ./test/test.ans ./test/test.out; fi
14 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/sim/testbench.v:
--------------------------------------------------------------------------------
1 | // testbench top module file
2 | // for simulation only
3 |
4 | `timescale 1ns/1ps
5 | module testbench;
6 |
7 | reg clk;
8 | reg rst;
9 |
10 | riscv_top #(.SIM(1)) top(
11 | .EXCLK(clk),
12 | .btnC(rst),
13 | .Tx(),
14 | .Rx(),
15 | .led()
16 | );
17 |
18 | initial begin
19 | clk=0;
20 | rst=1;
21 | repeat(50) #1 clk=!clk;
22 | rst=0;
23 | forever #1 clk=!clk;
24 |
25 | $finish;
26 | end
27 |
28 | endmodule
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/src/common/block_ram/block_ram.v:
--------------------------------------------------------------------------------
1 | /***************************************************************************************************
2 | *
3 | * Copyright (c) 2012, Brian Bennett
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification, are permitted
7 | * provided that the following conditions are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
10 | * and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
12 | * conditions and the following disclaimer in the documentation and/or other materials provided
13 | * with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
22 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 | *
24 | * Various generic, inferred block ram descriptors.
25 | ***************************************************************************************************/
26 |
27 | // Dual port RAM with synchronous read. Modified version of listing 12.4 in "FPGA Prototyping by
28 | // Verilog Examples," itself a modified version of XST 8.11 v_rams_11.
29 | module dual_port_ram_sync
30 | #(
31 | parameter ADDR_WIDTH = 6,
32 | parameter DATA_WIDTH = 8
33 | )
34 | (
35 | input wire clk,
36 | input wire we,
37 | input wire [ADDR_WIDTH-1:0] addr_a,
38 | input wire [ADDR_WIDTH-1:0] addr_b,
39 | input wire [DATA_WIDTH-1:0] din_a,
40 | output wire [DATA_WIDTH-1:0] dout_a,
41 | output wire [DATA_WIDTH-1:0] dout_b
42 | );
43 |
44 | reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];
45 | reg [ADDR_WIDTH-1:0] q_addr_a;
46 | reg [ADDR_WIDTH-1:0] q_addr_b;
47 |
48 | always @(posedge clk)
49 | begin
50 | if (we)
51 | ram[addr_a] <= din_a;
52 | q_addr_a <= addr_a;
53 | q_addr_b <= addr_b;
54 | end
55 |
56 | assign dout_a = ram[q_addr_a];
57 | assign dout_b = ram[q_addr_b];
58 |
59 | endmodule
60 |
61 | // Single port RAM with synchronous read.
62 | module single_port_ram_sync
63 | #(
64 | parameter ADDR_WIDTH = 6,
65 | parameter DATA_WIDTH = 8
66 | )
67 | (
68 | input wire clk,
69 | input wire we,
70 | input wire [ADDR_WIDTH-1:0] addr_a,
71 | input wire [DATA_WIDTH-1:0] din_a,
72 | output wire [DATA_WIDTH-1:0] dout_a
73 | );
74 |
75 | reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];
76 | reg [ADDR_WIDTH-1:0] q_addr_a;
77 |
78 | always @(posedge clk)
79 | begin
80 | if (we)
81 | ram[addr_a] <= din_a;
82 | q_addr_a <= addr_a;
83 | end
84 |
85 | assign dout_a = ram[q_addr_a];
86 |
87 | // initialize ram content (for simulation)
88 | integer i;
89 | initial begin
90 | for (i=0;i<2**ADDR_WIDTH;i=i+1) begin
91 | ram[i] = 0;
92 | end
93 | $readmemh("test.data", ram); // add test.data to vivado project or specify a valid file path
94 | end
95 |
96 | endmodule
97 |
98 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/src/common/fifo/fifo.v:
--------------------------------------------------------------------------------
1 | /***************************************************************************************************
2 | *
3 | * Copyright (c) 2012, Brian Bennett
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification, are permitted
7 | * provided that the following conditions are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
10 | * and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
12 | * conditions and the following disclaimer in the documentation and/or other materials provided
13 | * with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
22 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 | *
24 | * Circular first in first out buffer implementation.
25 | ***************************************************************************************************/
26 |
27 | module fifo
28 | #(
29 | parameter DATA_BITS = 8,
30 | parameter ADDR_BITS = 3
31 | )
32 | (
33 | input wire clk, // 50MHz system clock
34 | input wire reset, // Reset signal
35 | input wire rd_en, // Read enable, pop front of queue
36 | input wire wr_en, // Write enable, add wr_data to end of queue
37 | input wire [DATA_BITS-1:0] wr_data, // Data to be written on wr_en
38 | output wire [DATA_BITS-1:0] rd_data, // Current front of fifo data
39 | output wire full, // FIFO is full (writes invalid)
40 | output wire empty // FIFO is empty (reads invalid)
41 | );
42 |
43 | reg [ADDR_BITS-1:0] q_rd_ptr;
44 | wire [ADDR_BITS-1:0] d_rd_ptr;
45 | reg [ADDR_BITS-1:0] q_wr_ptr;
46 | wire [ADDR_BITS-1:0] d_wr_ptr;
47 | reg q_empty;
48 | wire d_empty;
49 | reg q_full;
50 | wire d_full;
51 |
52 | reg [DATA_BITS-1:0] q_data_array [2**ADDR_BITS-1:0];
53 | wire [DATA_BITS-1:0] d_data;
54 |
55 | wire rd_en_prot;
56 | wire wr_en_prot;
57 |
58 | // FF update logic. Synchronous reset.
59 | always @(posedge clk)
60 | begin
61 | if (reset)
62 | begin
63 | q_rd_ptr <= 0;
64 | q_wr_ptr <= 0;
65 | q_empty <= 1'b1;
66 | q_full <= 1'b0;
67 | end
68 | else
69 | begin
70 | q_rd_ptr <= d_rd_ptr;
71 | q_wr_ptr <= d_wr_ptr;
72 | q_empty <= d_empty;
73 | q_full <= d_full;
74 | q_data_array[q_wr_ptr] <= d_data;
75 | end
76 | end
77 |
78 | // Derive "protected" read/write signals.
79 | assign rd_en_prot = (rd_en && !q_empty);
80 | assign wr_en_prot = (wr_en && !q_full);
81 |
82 | // Handle writes.
83 | assign d_wr_ptr = (wr_en_prot) ? q_wr_ptr + 1'h1 : q_wr_ptr;
84 | assign d_data = (wr_en_prot) ? wr_data : q_data_array[q_wr_ptr];
85 |
86 | // Handle reads.
87 | assign d_rd_ptr = (rd_en_prot) ? q_rd_ptr + 1'h1 : q_rd_ptr;
88 |
89 | wire [ADDR_BITS-1:0] addr_bits_wide_1;
90 | assign addr_bits_wide_1 = 1;
91 |
92 | // Detect empty state:
93 | // 1) We were empty before and there was no write.
94 | // 2) We had one entry and there was a read.
95 | assign d_empty = ((q_empty && !wr_en_prot) ||
96 | (((q_wr_ptr - q_rd_ptr) == addr_bits_wide_1) && rd_en_prot));
97 |
98 | // Detect full state:
99 | // 1) We were full before and there was no read.
100 | // 2) We had n-1 entries and there was a write.
101 | assign d_full = ((q_full && !rd_en_prot) ||
102 | (((q_rd_ptr - q_wr_ptr) == addr_bits_wide_1) && wr_en_prot));
103 |
104 | // Assign output signals to appropriate FFs.
105 | assign rd_data = q_data_array[q_rd_ptr];
106 | assign full = q_full;
107 | assign empty = q_empty;
108 |
109 | endmodule
110 |
111 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/src/common/uart/uart.v:
--------------------------------------------------------------------------------
1 | /***************************************************************************************************
2 | *
3 | * Copyright (c) 2012, Brian Bennett
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification, are permitted
7 | * provided that the following conditions are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
10 | * and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
12 | * conditions and the following disclaimer in the documentation and/or other materials provided
13 | * with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
22 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 | *
24 | * UART controller. Universal Asynchronous Receiver/Transmitter control module for an RS-232
25 | * (serial) port.
26 | ***************************************************************************************************/
27 |
28 | module uart
29 | #(
30 | parameter SYS_CLK_FREQ = 50000000,
31 | parameter BAUD_RATE = 19200,
32 | parameter DATA_BITS = 8,
33 | parameter STOP_BITS = 1,
34 | parameter PARITY_MODE = 0 // 0 = none, 1 = odd, 2 = even
35 | )
36 | (
37 | input wire clk, // System clk
38 | input wire reset, // Reset signal
39 | input wire rx, // RS-232 rx pin
40 | input wire [DATA_BITS-1:0] tx_data, // Data to be transmitted when wr_en is 1
41 | input wire rd_en, // Pops current read FIFO front off the queue
42 | input wire wr_en, // Write tx_data over serial connection
43 | output wire tx, // RS-232 tx pin
44 | output wire [DATA_BITS-1:0] rx_data, // Data currently at front of read FIFO
45 | output wire rx_empty, // 1 if there is no more read data available
46 | output wire tx_full, // 1 if the transmit FIFO cannot accept more requests
47 | output wire parity_err // 1 if a parity error has been detected
48 | );
49 |
50 | localparam BAUD_CLK_OVERSAMPLE_RATE = 16;
51 |
52 | wire baud_clk_tick;
53 |
54 | wire [DATA_BITS-1:0] rx_fifo_wr_data;
55 | wire rx_done_tick;
56 | wire rx_parity_err;
57 |
58 | wire [DATA_BITS-1:0] tx_fifo_rd_data;
59 | wire tx_done_tick;
60 | wire tx_fifo_empty;
61 |
62 | // Store parity error in a flip flop as persistent state.
63 | reg q_rx_parity_err;
64 | wire d_rx_parity_err;
65 |
66 | always @(posedge clk, posedge reset)
67 | begin
68 | if (reset)
69 | q_rx_parity_err <= 1'b0;
70 | else
71 | q_rx_parity_err <= d_rx_parity_err;
72 | end
73 |
74 | assign parity_err = q_rx_parity_err;
75 | assign d_rx_parity_err = q_rx_parity_err || rx_parity_err;
76 |
77 | // BAUD clock module
78 | uart_baud_clk #(.SYS_CLK_FREQ(SYS_CLK_FREQ),
79 | .BAUD(BAUD_RATE),
80 | .BAUD_CLK_OVERSAMPLE_RATE(BAUD_CLK_OVERSAMPLE_RATE)) uart_baud_clk_blk
81 | (
82 | .clk(clk),
83 | .reset(reset),
84 | .baud_clk_tick(baud_clk_tick)
85 | );
86 |
87 | // RX (receiver) module
88 | uart_rx #(.DATA_BITS(DATA_BITS),
89 | .STOP_BITS(STOP_BITS),
90 | .PARITY_MODE(PARITY_MODE),
91 | .BAUD_CLK_OVERSAMPLE_RATE(BAUD_CLK_OVERSAMPLE_RATE)) uart_rx_blk
92 | (
93 | .clk(clk),
94 | .reset(reset),
95 | .baud_clk_tick(baud_clk_tick),
96 | .rx(rx),
97 | .rx_data(rx_fifo_wr_data),
98 | .rx_done_tick(rx_done_tick),
99 | .parity_err(rx_parity_err)
100 | );
101 |
102 | // TX (transmitter) module
103 | uart_tx #(.DATA_BITS(DATA_BITS),
104 | .STOP_BITS(STOP_BITS),
105 | .PARITY_MODE(PARITY_MODE),
106 | .BAUD_CLK_OVERSAMPLE_RATE(BAUD_CLK_OVERSAMPLE_RATE)) uart_tx_blk
107 | (
108 | .clk(clk),
109 | .reset(reset),
110 | .baud_clk_tick(baud_clk_tick),
111 | .tx_start(~tx_fifo_empty),
112 | .tx_data(tx_fifo_rd_data),
113 | .tx_done_tick(tx_done_tick),
114 | .tx(tx)
115 | );
116 |
117 | // RX FIFO
118 | fifo #(.DATA_BITS(DATA_BITS),
119 | .ADDR_BITS(3)) uart_rx_fifo
120 | (
121 | .clk(clk),
122 | .reset(reset),
123 | .rd_en(rd_en),
124 | .wr_en(rx_done_tick),
125 | .wr_data(rx_fifo_wr_data),
126 | .rd_data(rx_data),
127 | .empty(rx_empty),
128 | .full()
129 | );
130 |
131 | // TX FIFO (increased size)
132 | fifo #(.DATA_BITS(DATA_BITS),
133 | .ADDR_BITS(10)) uart_tx_fifo
134 | (
135 | .clk(clk),
136 | .reset(reset),
137 | .rd_en(tx_done_tick),
138 | .wr_en(wr_en),
139 | .wr_data(tx_data),
140 | .rd_data(tx_fifo_rd_data),
141 | .empty(tx_fifo_empty),
142 | .full(tx_full)
143 | );
144 |
145 | endmodule
146 |
147 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/src/common/uart/uart_baud_clk.v:
--------------------------------------------------------------------------------
1 | /***************************************************************************************************
2 | ** fpga_nes/hw/src/cmn/uart/uart_baud_clk.v
3 | *
4 | * Copyright (c) 2012, Brian Bennett
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification, are permitted
8 | * provided that the following conditions are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
11 | * and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
13 | * conditions and the following disclaimer in the documentation and/or other materials provided
14 | * with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
23 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | *
25 | * Generates a tick signal at OVERSAMPLE_RATE times the baud rate. Should be fed to the uart_rx
26 | * and uart_tx blocks.
27 | ***************************************************************************************************/
28 |
29 | module uart_baud_clk
30 | #(
31 | parameter SYS_CLK_FREQ = 50000000,
32 | parameter BAUD = 19200,
33 | parameter BAUD_CLK_OVERSAMPLE_RATE = 16
34 | )
35 | (
36 | input wire clk,
37 | input wire reset,
38 | output wire baud_clk_tick
39 | );
40 |
41 | localparam [15:0] CLKS_PER_OVERSAMPLE_TICK = (SYS_CLK_FREQ / BAUD) / BAUD_CLK_OVERSAMPLE_RATE;
42 |
43 | // Registers
44 | reg [15:0] q_cnt;
45 | wire [15:0] d_cnt;
46 |
47 | always @(posedge clk, posedge reset)
48 | begin
49 | if (reset)
50 | q_cnt <= 0;
51 | else
52 | q_cnt <= d_cnt;
53 | end
54 |
55 | assign d_cnt = (q_cnt == (CLKS_PER_OVERSAMPLE_TICK - 1)) ? 16'h0000 : (q_cnt + 16'h0001);
56 | assign baud_clk_tick = (q_cnt == (CLKS_PER_OVERSAMPLE_TICK - 1)) ? 1'b1 : 1'b0;
57 |
58 | endmodule
59 |
60 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/src/common/uart/uart_rx.v:
--------------------------------------------------------------------------------
1 | /***************************************************************************************************
2 | ** fpga_nes/hw/src/cmn/uart/uart_rx.v
3 | *
4 | * Copyright (c) 2012, Brian Bennett
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification, are permitted
8 | * provided that the following conditions are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
11 | * and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
13 | * conditions and the following disclaimer in the documentation and/or other materials provided
14 | * with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
23 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | *
25 | * UART receiver.
26 | ***************************************************************************************************/
27 |
28 | module uart_rx
29 | #(
30 | parameter DATA_BITS = 8,
31 | parameter STOP_BITS = 1,
32 | parameter PARITY_MODE = 1, // 0 = NONE, 1 = ODD, 2 = EVEN
33 | parameter BAUD_CLK_OVERSAMPLE_RATE = 16
34 | )
35 | (
36 | input wire clk, // System clock
37 | input wire reset, // Reset signal
38 | input wire baud_clk_tick, // 1 tick per OVERSAMPLE_RATE baud clks
39 | input wire rx, // RX transmission wire
40 | output wire [DATA_BITS-1:0] rx_data, // Output data
41 | output wire rx_done_tick, // Output rdy signal
42 | output wire parity_err // Asserted for one clk on parity error
43 | );
44 |
45 | localparam [5:0] STOP_OVERSAMPLE_TICKS = STOP_BITS * BAUD_CLK_OVERSAMPLE_RATE;
46 |
47 | // Symbolic state representations.
48 | localparam [4:0] S_IDLE = 5'h01,
49 | S_START = 5'h02,
50 | S_DATA = 5'h04,
51 | S_PARITY = 5'h08,
52 | S_STOP = 5'h10;
53 |
54 | // Registers
55 | reg [4:0] q_state, d_state;
56 | reg [3:0] q_oversample_tick_cnt, d_oversample_tick_cnt;
57 | reg [DATA_BITS-1:0] q_data, d_data;
58 | reg [2:0] q_data_bit_idx, d_data_bit_idx;
59 | reg q_done_tick, d_done_tick;
60 | reg q_parity_err, d_parity_err;
61 | reg q_rx;
62 |
63 | always @(posedge clk, posedge reset)
64 | begin
65 | if (reset)
66 | begin
67 | q_state <= S_IDLE;
68 | q_oversample_tick_cnt <= 0;
69 | q_data <= 0;
70 | q_data_bit_idx <= 0;
71 | q_done_tick <= 1'b0;
72 | q_parity_err <= 1'b0;
73 | q_rx <= 1'b1;
74 | end
75 | else
76 | begin
77 | q_state <= d_state;
78 | q_oversample_tick_cnt <= d_oversample_tick_cnt;
79 | q_data <= d_data;
80 | q_data_bit_idx <= d_data_bit_idx;
81 | q_done_tick <= d_done_tick;
82 | q_parity_err <= d_parity_err;
83 | q_rx <= rx;
84 | end
85 | end
86 |
87 | always @*
88 | begin
89 | // Default most state to remain unchanged.
90 | d_state = q_state;
91 | d_data = q_data;
92 | d_data_bit_idx = q_data_bit_idx;
93 |
94 | // Increment the tick counter if the baud_clk counter ticked.
95 | d_oversample_tick_cnt = (baud_clk_tick) ? q_oversample_tick_cnt + 4'h1 : q_oversample_tick_cnt;
96 |
97 | // Default the done signal and parity err to 0.
98 | d_done_tick = 1'b0;
99 | d_parity_err = 1'b0;
100 |
101 | case (q_state)
102 | S_IDLE:
103 | begin
104 | // Detect incoming data when rx goes low (start bit).
105 | if (~q_rx)
106 | begin
107 | d_state = S_START;
108 | d_oversample_tick_cnt = 0;
109 | end
110 | end
111 |
112 | S_START:
113 | begin
114 | // Wait for BAUD_CLK_OVERSAMPLE_RATE / 2 ticks to get "centered" in the start bit signal.
115 | if (baud_clk_tick && (q_oversample_tick_cnt == ((BAUD_CLK_OVERSAMPLE_RATE - 1) / 2)))
116 | begin
117 | d_state = S_DATA;
118 | d_oversample_tick_cnt = 0;
119 | d_data_bit_idx = 0;
120 | end
121 | end
122 |
123 | S_DATA:
124 | begin
125 | // Every BAUD_CLK_OVERSAMPLE_RATE clocks, sample rx and shift its value into the data reg.
126 | if (baud_clk_tick && (q_oversample_tick_cnt == (BAUD_CLK_OVERSAMPLE_RATE - 1)))
127 | begin
128 | d_data = { q_rx, q_data[DATA_BITS-1:1] };
129 | d_oversample_tick_cnt = 0;
130 |
131 | if (q_data_bit_idx == (DATA_BITS - 1))
132 | begin
133 | if (PARITY_MODE == 0)
134 | d_state = S_STOP;
135 | else
136 | d_state = S_PARITY;
137 | end
138 | else
139 | d_data_bit_idx = q_data_bit_idx + 3'h1;
140 | end
141 | end
142 |
143 | S_PARITY:
144 | begin
145 | if (baud_clk_tick && (q_oversample_tick_cnt == (BAUD_CLK_OVERSAMPLE_RATE - 1)))
146 | begin
147 | if (PARITY_MODE == 1)
148 | d_parity_err = (q_rx != ~^q_data);
149 | else
150 | d_parity_err = (q_rx != ^q_data);
151 |
152 | d_state = S_STOP;
153 | d_oversample_tick_cnt = 0;
154 | end
155 | end
156 |
157 | S_STOP:
158 | begin
159 | // Wait for stop bit before returning to idle. Signal done_tick.
160 | if (baud_clk_tick && (q_oversample_tick_cnt == STOP_OVERSAMPLE_TICKS - 1))
161 | begin
162 | d_state = S_IDLE;
163 | d_done_tick = 1'b1;
164 | end
165 | end
166 | endcase
167 | end
168 |
169 | assign rx_data = q_data;
170 | assign rx_done_tick = q_done_tick;
171 | assign parity_err = q_parity_err;
172 |
173 | endmodule
174 |
175 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/src/cpu.v:
--------------------------------------------------------------------------------
1 | // RISCV32I CPU top module
2 | // port modification allowed for debugging purposes
3 |
4 | module cpu(
5 | input wire clk_in, // system clock signal
6 | input wire rst_in, // reset signal
7 | input wire rdy_in, // ready signal, pause cpu when low
8 |
9 | input wire [ 7:0] mem_din, // data input bus
10 | output wire [ 7:0] mem_dout, // data output bus
11 | output wire [31:0] mem_a, // address bus (only 17:0 is used)
12 | output wire mem_wr, // write/read signal (1 for write)
13 |
14 | input wire io_buffer_full, // 1 if uart buffer is full
15 |
16 | output wire [31:0] dbgreg_dout // cpu register output (debugging demo)
17 | );
18 |
19 | // implementation goes here
20 |
21 | // Specifications:
22 | // - Pause cpu(freeze pc, registers, etc.) when rdy_in is low
23 | // - Memory read result will be returned in the next cycle. Write takes 1 cycle(no need to wait)
24 | // - Memory is of size 128KB, with valid address ranging from 0x0 to 0x20000
25 | // - I/O port is mapped to address higher than 0x30000 (mem_a[17:16]==2'b11)
26 | // - 0x30000 read: read a byte from input
27 | // - 0x30000 write: write a byte to output (write 0x00 is ignored)
28 | // - 0x30004 read: read clocks passed since cpu starts (in dword, 4 bytes)
29 | // - 0x30004 write: indicates program stop (will output '\0' through uart tx)
30 |
31 | always @(posedge clk_in)
32 | begin
33 | if (rst_in)
34 | begin
35 |
36 | end
37 | else if (!rdy_in)
38 | begin
39 |
40 | end
41 | else
42 | begin
43 |
44 | end
45 | end
46 |
47 | endmodule
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/src/ram.v:
--------------------------------------------------------------------------------
1 | // implements 128KB of on-board RAM
2 |
3 | module ram
4 | #(
5 | parameter ADDR_WIDTH = 17
6 | )
7 | (
8 | input wire clk_in, // system clock
9 | input wire en_in, // chip enable
10 | input wire r_nw_in, // read/write select (read: 1, write: 0)
11 | input wire [ADDR_WIDTH-1:0] a_in, // memory address
12 | input wire [ 7:0] d_in, // data input
13 | output wire [ 7:0] d_out // data output
14 | );
15 |
16 | wire ram_bram_we;
17 | wire [7:0] ram_bram_dout;
18 |
19 | single_port_ram_sync #(.ADDR_WIDTH(ADDR_WIDTH),
20 | .DATA_WIDTH(8)) ram_bram(
21 | .clk(clk_in),
22 | .we(ram_bram_we),
23 | .addr_a(a_in),
24 | .din_a(d_in),
25 | .dout_a(ram_bram_dout)
26 | );
27 |
28 | assign ram_bram_we = (en_in) ? ~r_nw_in : 1'b0;
29 | assign d_out = (en_in) ? ram_bram_dout : 8'h00;
30 |
31 | endmodule
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/src/riscv_top.v:
--------------------------------------------------------------------------------
1 | // riscv top module file
2 | // modification allowed for debugging purposes
3 |
4 | module riscv_top
5 | #(
6 | parameter SIM = 0 // whether in simulation
7 | )
8 | (
9 | input wire EXCLK,
10 | input wire btnC,
11 | output wire Tx,
12 | input wire Rx,
13 | output wire led
14 | );
15 |
16 | localparam SYS_CLK_FREQ = 100000000;
17 | localparam UART_BAUD_RATE = 115200;
18 | localparam RAM_ADDR_WIDTH = 17; // 128KiB ram, should not be modified
19 |
20 | reg rst;
21 | reg rst_delay;
22 |
23 | wire clk;
24 |
25 | // assign EXCLK (or your own clock module) to clk
26 | assign clk = EXCLK;
27 |
28 | always @(posedge clk or posedge btnC)
29 | begin
30 | if (btnC)
31 | begin
32 | rst <= 1'b1;
33 | rst_delay <= 1'b1;
34 | end
35 | else
36 | begin
37 | rst_delay <= 1'b0;
38 | rst <= rst_delay;
39 | end
40 | end
41 |
42 | //
43 | // System Memory Buses
44 | //
45 | wire [ 7:0] cpumc_din;
46 | wire [31:0] cpumc_a;
47 | wire cpumc_wr;
48 |
49 | //
50 | // RAM: internal ram
51 | //
52 | wire ram_en;
53 | wire [RAM_ADDR_WIDTH-1:0] ram_a;
54 | wire [ 7:0] ram_dout;
55 |
56 | ram #(.ADDR_WIDTH(RAM_ADDR_WIDTH))ram0(
57 | .clk_in(clk),
58 | .en_in(ram_en),
59 | .r_nw_in(~cpumc_wr),
60 | .a_in(ram_a),
61 | .d_in(cpumc_din),
62 | .d_out(ram_dout)
63 | );
64 |
65 | assign ram_en = (cpumc_a[RAM_ADDR_WIDTH:RAM_ADDR_WIDTH-1] == 2'b11) ? 1'b0 : 1'b1;
66 | assign ram_a = cpumc_a[RAM_ADDR_WIDTH-1:0];
67 |
68 | //
69 | // CPU: CPU that implements RISC-V 32b integer base user-level real-mode ISA
70 | //
71 | wire [31:0] cpu_ram_a;
72 | wire cpu_ram_wr;
73 | wire [ 7:0] cpu_ram_din;
74 | wire [ 7:0] cpu_ram_dout;
75 | wire cpu_rdy;
76 |
77 | wire [31:0] cpu_dbgreg_dout;
78 |
79 |
80 | //
81 | // HCI: host communication interface block. Use controller to interact.
82 | //
83 | wire hci_active_out;
84 | wire [ 7:0] hci_ram_din;
85 | wire [ 7:0] hci_ram_dout;
86 | wire [RAM_ADDR_WIDTH-1:0] hci_ram_a;
87 | wire hci_ram_wr;
88 |
89 | wire hci_io_en;
90 | wire [ 2:0] hci_io_sel;
91 | wire [ 7:0] hci_io_din;
92 | wire [ 7:0] hci_io_dout;
93 | wire hci_io_wr;
94 | wire hci_io_full;
95 |
96 | wire program_finish;
97 |
98 | reg q_hci_io_en;
99 |
100 | cpu cpu0(
101 | .clk_in(clk),
102 | .rst_in(rst | program_finish),
103 | .rdy_in(cpu_rdy),
104 |
105 | .mem_din(cpu_ram_din),
106 | .mem_dout(cpu_ram_dout),
107 | .mem_a(cpu_ram_a),
108 | .mem_wr(cpu_ram_wr),
109 |
110 | .io_buffer_full(hci_io_full),
111 |
112 | .dbgreg_dout(cpu_dbgreg_dout)
113 | );
114 |
115 | hci #(.SYS_CLK_FREQ(SYS_CLK_FREQ),
116 | .RAM_ADDR_WIDTH(RAM_ADDR_WIDTH),
117 | .BAUD_RATE(UART_BAUD_RATE)) hci0
118 | (
119 | .clk(clk),
120 | .rst(rst),
121 | .tx(Tx),
122 | .rx(Rx),
123 | .active(hci_active_out),
124 | .ram_din(hci_ram_din),
125 | .ram_dout(hci_ram_dout),
126 | .ram_a(hci_ram_a),
127 | .ram_wr(hci_ram_wr),
128 | .io_sel(hci_io_sel),
129 | .io_en(hci_io_en),
130 | .io_din(hci_io_din),
131 | .io_dout(hci_io_dout),
132 | .io_wr(hci_io_wr),
133 | .io_full(hci_io_full),
134 |
135 | .program_finish(program_finish),
136 |
137 | .cpu_dbgreg_din(cpu_dbgreg_dout) // demo
138 | );
139 |
140 | assign hci_io_sel = cpumc_a[2:0];
141 | assign hci_io_en = (cpumc_a[RAM_ADDR_WIDTH:RAM_ADDR_WIDTH-1] == 2'b11) ? 1'b1 : 1'b0;
142 | assign hci_io_wr = cpumc_wr;
143 | assign hci_io_din = cpumc_din;
144 |
145 | // hci is always disabled in simulation
146 | wire hci_active;
147 | assign hci_active = hci_active_out & ~SIM;
148 |
149 | // indicates debug break
150 | assign led = hci_active;
151 |
152 | // pause cpu on hci active
153 | assign cpu_rdy = (hci_active) ? 1'b0 : 1'b1;
154 |
155 | // Mux cpumc signals from cpu or hci blk, depending on debug break state (hci_active).
156 | assign cpumc_a = (hci_active) ? hci_ram_a : cpu_ram_a;
157 | assign cpumc_wr = (hci_active) ? hci_ram_wr : cpu_ram_wr;
158 | assign cpumc_din = (hci_active) ? hci_ram_dout : cpu_ram_dout;
159 |
160 | // Fixed 2020-10-06: Inconsisitency of return value with I/O state
161 | always @ (posedge clk) begin
162 | q_hci_io_en <= hci_io_en;
163 | end
164 |
165 | assign cpu_ram_din = (q_hci_io_en) ? hci_io_dout : ram_dout;
166 |
167 | assign hci_ram_din = ram_dout;
168 |
169 | endmodule
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/sys/io.h:
--------------------------------------------------------------------------------
1 | #ifndef CPU_JUDGE_TEST_IO_H
2 | #define CPU_JUDGE_TEST_IO_H
3 |
4 | // #define SIM // whether in simulation
5 |
6 | #define BYTE_PORT_IN 0x30000 // port for reading bytes from input
7 | #define BYTE_PORT_OUT 0x30000 // port for writing bytes to output
8 |
9 | #define CPUCLK_PORT_IN 0x30004 // port that reads clocks passed since cpu starts
10 |
11 | #define CPU_CLK_FREQ 70000000 // clock frequency of the cpu on FPGA
12 |
13 | static inline unsigned char inb()
14 | {
15 | return *((volatile unsigned char *)BYTE_PORT_IN);
16 | }
17 |
18 | static inline void outb(const unsigned char data)
19 | {
20 | *((volatile unsigned char *)BYTE_PORT_OUT) = data;
21 | }
22 |
23 | static inline unsigned long inl()
24 | {
25 | unsigned long ret = 0;
26 | unsigned char ch;
27 | int sign=0;
28 | while ((ch=inb())) if(ch!='\n'&&ch!=' '&&ch!='\t') break;
29 | do {
30 | if(ch=='-'&&!sign) sign=1;
31 | else if(ch<'0'||ch>'9') break;
32 | ret = ret * 10 + ch - '0';
33 | }while ((ch=inb()));
34 | return sign?-ret:ret;
35 | }
36 |
37 | static inline void getstr(char* data)
38 | {
39 | char c;
40 | int i=0;
41 | while((c=inb())!='\n') data[i++]=c;
42 | data[i]='\0';
43 | }
44 |
45 | static inline unsigned int ord(char data)
46 | {
47 | return (unsigned int)data;
48 | }
49 |
50 | static inline void outl(const int data)
51 | {
52 | unsigned char str[12];
53 | int tmp = data;
54 | int i=0, s=0;
55 | if (tmp<0){
56 | s=1;
57 | tmp=-tmp;
58 | }
59 | do {
60 | str[i++] = tmp % 10 + '0';
61 | }
62 | while ((tmp/=10)>0);
63 | if(s) str[i++]='-';
64 | while (i--) {
65 | outb(str[i]);
66 | }
67 | }
68 |
69 | static inline void print(const char *str)
70 | {
71 | for (; *str; str++)
72 | outb(*str);
73 | }
74 |
75 | static inline void println(const char *str)
76 | {
77 | print(str);
78 | outb('\n');
79 | }
80 |
81 | static inline void outlln(const unsigned int data)
82 | {
83 | outl(data);
84 | outb('\n');
85 | }
86 |
87 | static inline unsigned int clock()
88 | {
89 | // return *((volatile unsigned int*)CPUCLK_PORT_IN);
90 | unsigned t1 = (unsigned)(*((volatile unsigned char *)(CPUCLK_PORT_IN)));
91 | unsigned t2 = (unsigned)(*((volatile unsigned char *)(CPUCLK_PORT_IN+1)));
92 | unsigned t3 = (unsigned)(*((volatile unsigned char *)(CPUCLK_PORT_IN+2)));
93 | unsigned t4 = (unsigned)(*((volatile unsigned char *)(CPUCLK_PORT_IN+3)));
94 | return (t4<<24) | (t3<<16) | (t2<<8) | (t1);
95 | }
96 |
97 | #ifdef SIM
98 | #define sleep(x)
99 | #else
100 | static inline void sleep(const unsigned int milli_sec)
101 | {
102 | unsigned int s = 0, d = milli_sec * (CPU_CLK_FREQ / 1000);
103 | s = clock();
104 | while (clock() - s < d);
105 | }
106 | #endif
107 |
108 | #endif
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/sys/memory.ld:
--------------------------------------------------------------------------------
1 | SECTIONS
2 | {
3 | . = 0x00000000;
4 | .rom :
5 | {
6 | *(.rom)
7 | }
8 |
9 | . = 0x00001000;
10 | .text :
11 | {
12 | *(.text)
13 | }
14 |
15 | .rodata ALIGN(4) :
16 | {
17 | *(.rodata)
18 | }
19 |
20 | .data ALIGN(4) :
21 | {
22 | *(.data)
23 | }
24 |
25 | __bss_start = .;
26 |
27 | .bss ALIGN(4) :
28 | {
29 | *(.bss)
30 | }
31 |
32 | __bss_end = .;
33 | __heap_start = (__bss_end + 0xfff) & 0xfffff000;
34 | }
35 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/sys/rom.s:
--------------------------------------------------------------------------------
1 | .section .rom,"ax"
2 | .globl main
3 |
4 | li sp, 0x00020000
5 | jal main
6 | li a0, 0xff
7 | .L0:
8 | lui a3, 0x30
9 | sb a0, 4(a3)
10 | j .L0
11 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/array_test1.ans:
--------------------------------------------------------------------------------
1 | 0000
2 | 1234
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/array_test1.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | //input: 1 2 3 4
3 |
4 | int a[4];
5 | int main()
6 | {
7 | int b[4];
8 | int i;
9 | for (i = 0; i < 4; i++)
10 | {
11 | a[i] = 0;
12 | b[i] = inl();
13 | }
14 | for (i = 0; i < 4; i++)
15 | {
16 | outl(a[i]);
17 | }
18 | println("");
19 | int *p;
20 | p=b;
21 | for (i = 0; i < 4; i++)
22 | {
23 | outl(p[i]);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/array_test1.in:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 | 4
5 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/array_test2.ans:
--------------------------------------------------------------------------------
1 | 4
2 | 1234
3 | 0000
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/array_test2.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | // input: 1 2 3 4
3 | int a[4];
4 | int *pa = a;
5 | int main()
6 | {
7 | int *pb[4];
8 | int i;
9 | pb[0] = pa;
10 | pb[1] = pa;
11 | pb[2] = pa;
12 | pb[3] = pa;
13 | outlln(4);
14 | for (i = 0; i < 4; i++)
15 | pb[0][i] = inl();
16 | for (i = 0; i < 4; i++)
17 | outl(pb[1][i]);
18 | println("");
19 | for (i = 0; i < 4; i++)
20 | pb[2][i] = 0;
21 | for (i = 0; i < 4; i++)
22 | outl(pb[3][i]);
23 | }
24 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/array_test2.in:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 | 4
5 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/basicopt1.ans:
--------------------------------------------------------------------------------
1 | 99850
2 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/basicopt1.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int main()
3 | {
4 | int a[100][100];
5 | int i;
6 | int j;
7 | int sum = 0;
8 |
9 | for (i = 0;i < 100;i++)
10 | for (j = 0;j < 100;j++)
11 | a[i][j] = 0;
12 | int quotient;
13 | int remainder;
14 | for (i = 0;i < 100;i++)
15 | if (i > 20 && i < 80) {
16 | for (j = 0;j < 100;j++)
17 | if (j > 5 || i < 90) {
18 | quotient = j * 4 / 100;
19 | remainder = j * 4 % 100;
20 | a[i + quotient][remainder] = j + (100 - 1 + 1 - 1 + 1) / 2;
21 | }
22 | }
23 |
24 | for (i = 0;i < 100;i++)
25 | for (j = 0;j < 100;j++)
26 | sum = sum + a[i][j];
27 | outlln(sum);
28 | }
29 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/bulgarian.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | // Target: Simulate a Bulgarian-solitaire game.
3 | // Possible opitimization: Dead code elimination, common expression, inline function, loop unrolling, etc.
4 | // REMARKS: A funny game. If you like, you can try to prove that when n=1+2+..+i(i>0), the game will always stop
5 | // and converge to the only solution: {1,2,...i}. :)
6 |
7 | int n;
8 | int h;
9 | int now;
10 | int a[100];
11 | int A = 48271;
12 | int M = 2147483647;
13 | int Q;
14 | int R;
15 | int seed=1;
16 | int random() {
17 | int tempseed = A * (seed % Q) - R * (seed / Q);
18 | if (tempseed >= 0)
19 | seed = tempseed;
20 | else
21 | seed = tempseed + M;
22 | return seed;
23 | }
24 | void initialize(int val) {
25 | seed = val;
26 | }
27 | void swap(int x,int y) {
28 | int temp = a[x];
29 | a[x] = a[y];
30 | a[y] = temp;
31 | }
32 | int pd(int x) {
33 | for (;h <= x; ++h)
34 | if (x == h * (h + 1) / 2)
35 | return 1;
36 | return 0;
37 | }
38 | void show() {
39 | int i;
40 | for (i = 0; i < now; ++i){
41 | outl(a[i]);
42 | print(" ");
43 | }
44 | println("");
45 | }
46 | int win()
47 | {
48 | int i;
49 | int j;
50 | int b[100];
51 | int temp;
52 | if (now != h)
53 | return 0;
54 | for (j = 0; j < now; ++j)
55 | b[j] = a[j];
56 | for (i = 0;i < now - 1; ++i)
57 | for (j = i + 1;j < now; ++j)
58 | if (b[i] > b[j]) {
59 | temp = b[i];
60 | b[i] = b[j];
61 | b[j] = temp;
62 | }
63 | for (i = 0; i < now; ++i)
64 | if (b[i] != i + 1)
65 | return 0;
66 | return 1;
67 | }
68 | void merge()
69 | {
70 | int i;
71 | for (i = 0;i < now; ++i)
72 | if (a[i] == 0) {
73 | int j;
74 | for (j = i+1; j < now; ++j)
75 | if (a[j] != 0) {
76 | swap(i,j);
77 | break;
78 | }
79 | }
80 | for (i=0;i n)
115 | a[i] = random() % 10 + 1;
116 | temp = temp + a[i];
117 | }
118 | a[now - 1] = n - temp;
119 | show();
120 | merge();
121 | while (!win()) {
122 | print("step ");
123 | outl(++count);
124 | println(":");
125 | move();
126 | merge();
127 | show();
128 | sleep(10); // to prevent UART buffer from overflowing
129 | }
130 | print("Total: ");
131 | outl(count);
132 | println(" step(s)");
133 | return 0;
134 | }
135 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/expr.ans:
--------------------------------------------------------------------------------
1 | -66060719 -323398799 -743275679
2 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/expr.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | //This file use massive recursive expression to test: Common Expression substitution.
3 | //For my optimized version: All: 1397 Load: 86 Store: 55 Jumped: 23
4 | //For my unoptimized version: All: 24519 Load: 12183 Store: 55 Jumped: 23
5 | //A better result is welcomed. ------ From JinTianxing.
6 |
7 | int A = 1;
8 | int B = 1;
9 | int C = 1;
10 |
11 | int main(){
12 | while (C < (1 << 29) && C > -(1 << 29)){
13 | A = ((((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))) - (((((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B)))) + (((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))));
14 | B = ((((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))) - (((((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B)))) + (((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))));
15 | C = ((((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))) - (((((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B)))) + (((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))));
16 | }
17 | outl(A);
18 | print(" ");
19 | outl(B);
20 | print(" ");
21 | outlln(C);
22 | return 0;
23 | }
24 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/gcd.ans:
--------------------------------------------------------------------------------
1 | 1
2 | 1029
3 | 171
4 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/gcd.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int gcd(int x, int y) {
3 | if (x%y == 0) return y;
4 | else return gcd(y, x%y);
5 | }
6 |
7 | int main() {
8 | outlln(gcd(10,1));
9 | outlln(gcd(34986,3087));
10 | outlln(gcd(2907,1539));
11 |
12 | return 0;
13 | }
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/hanoi.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int cd(int d, char* a, char* b, char* c, int sum) {
3 | sleep(5); // to prevent UART buffer from overflowing
4 | if (d == 1) {
5 | print("move ");
6 | print(a);
7 | print(" --> ");
8 | println(c);
9 | sum++;
10 | } else {
11 | sum = cd(d - 1, a, c, b, sum);
12 | print("move ");
13 | print(a);
14 | print(" --> ");
15 | println(c);
16 | sum = cd(d - 1, b, a, c, sum);
17 | sum++;
18 | }
19 | return sum;
20 | }
21 |
22 | int main() {
23 | char a[5] = "A";
24 | char b[5] = "B";
25 | char c[5] = "C";
26 | int d = inl();
27 | int sum = cd(d, a, b, c, 0);
28 | outlln(sum);
29 | return 0;
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/hanoi.in:
--------------------------------------------------------------------------------
1 | 10
2 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/heart.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | #define putchar outb
3 | float f(float x, float y, float z) {
4 | float a = x * x + 9.0f / 4.0f * y * y + z * z - 1;
5 | return a * a * a - x * x * z * z * z - 9.0f / 80.0f * y * y * z * z * z;
6 | }
7 |
8 | float h(float x, float z) {
9 | for (float y = 1.0f; y >= 0.0f; y -= 0.001f)
10 | if (f(x, y, z) <= 0.0f)
11 | return y;
12 | return 0.0f;
13 | }
14 |
15 | float mysqrt(float x) {
16 | if (x == 0) return 0;
17 | int i;
18 | double v = x / 2;
19 | for (i = 0; i < 50; ++i)
20 | v = (v + x / v)/2;
21 |
22 | return v;
23 | }
24 |
25 | int main() {
26 | for (float z = 1.5f; z > -1.5f; z -= 0.05f) {
27 | for (float x = -1.5f; x < 1.5f; x += 0.025f) {
28 | float v = f(x, 0.0f, z);
29 | if (v <= 0.0f) {
30 | float y0 = h(x, z);
31 | float ny = 0.01f;
32 | float nx = h(x + ny, z) - y0;
33 | float nz = h(x, z + ny) - y0;
34 | float nd = 1.0f / mysqrt(nx * nx + ny * ny + nz * nz);
35 | float d = (nx + ny - nz) * nd * 0.5f + 0.5f;
36 | int index = (int)(d * 5.0f);
37 | putchar(".:-=+*#%@"[index]);
38 | }
39 | else
40 | putchar('_');
41 | }
42 | putchar('\n');
43 | }
44 | }
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/looper.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | // san check: if your predictor && icache work, it should be 1.5s @ 100Mhz
3 | unsigned n, sum;
4 | void work() {
5 | for (int i = 1; i <= 5 * n; i++) {
6 | sum += i * 998244353;
7 | }
8 | }
9 | int main() {
10 | n = 50;
11 | work();
12 | n = 10000000;
13 | work();
14 | outlln(sum);
15 | }
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/lvalue2.ans:
--------------------------------------------------------------------------------
1 | 2
2 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/lvalue2.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int a[4];
3 | int main()
4 | {
5 | int b[4];
6 | b[2]=2;
7 | int *p;
8 | p=b;
9 | outlln(p[2]);
10 | }
11 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/magic.ans:
--------------------------------------------------------------------------------
1 | 2 7 6
2 | 9 5 1
3 | 4 3 8
4 |
5 | 2 9 4
6 | 7 5 3
7 | 6 1 8
8 |
9 | 4 3 8
10 | 9 5 1
11 | 2 7 6
12 |
13 | 4 9 2
14 | 3 5 7
15 | 8 1 6
16 |
17 | 6 1 8
18 | 7 5 3
19 | 2 9 4
20 |
21 | 6 7 2
22 | 1 5 9
23 | 8 3 4
24 |
25 | 8 1 6
26 | 3 5 7
27 | 4 9 2
28 |
29 | 8 3 4
30 | 1 5 9
31 | 6 7 2
32 |
33 | 8
34 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/magic.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int make[3][3];
3 | int color[10];
4 | int count[1];
5 | int i;
6 | int j;
7 |
8 | void origin(int N)
9 | {
10 | for (i = 0; i < N; i ++ ) {
11 | for (j = 0; j < N; j ++ )
12 | make[i][j] = 0;
13 | }
14 | }
15 |
16 | void search(int x, int y, int z)
17 | {
18 | int s;
19 | int i;
20 | int j;
21 | if ((y > 0 || y < 0) || x == 0 || make[x-1][0] + make[x-1][1] + make[x-1][2] == 15)
22 | {
23 | if (x == 2 && y == 2) {
24 | make[2][2] = 45 - z;
25 | s = make[0][0] + make[0][1] + make[0][2];
26 | if (make[1][0] + make[1][1] + make[1][2] == s &&
27 | make[2][0] + make[2][1] + make[2][2] == s &&
28 | make[0][0] + make[1][0] + make[2][0] == s &&
29 | make[0][1] + make[1][1] + make[2][1] == s &&
30 | make[0][2] + make[1][2] + make[2][2] == s &&
31 | make[0][0] + make[1][1] + make[2][2] == s &&
32 | make[2][0] + make[1][1] + make[0][2] == s)
33 | {
34 | count[0] = count[0] + 1;
35 | for (i = 0;i <= 2;i ++)
36 | {
37 | for (j = 0;j <= 2;j ++)
38 | {
39 | outl(make[i][j]);
40 | print(" ");
41 | }
42 | print("\n");
43 | }
44 | print("\n");
45 | }
46 | }
47 | else {
48 | if (y == 2) {
49 | make[x][y] = 15 - make[x][0] - make[x][1];
50 | if (make[x][y] > 0 && make[x][y] < 10 && color[make[x][y]] == 0) {
51 | color[make[x][y]] = 1;
52 | if (y == 2)
53 | search(x + 1, 0, z+make[x][y]);
54 | else
55 | search(x, y+1, z+make[x][y]);
56 | color[make[x][y]] = 0;
57 | }
58 | }
59 | else {
60 | for (i = 1;i <= 9;i ++) {
61 | if (color[i] == 0) {
62 | color[i] = 1;
63 | make[x][y] = i;
64 | if (y == 2)
65 | search(x + 1, 0, z+i);
66 | else
67 | search(x, y+1, z+i);
68 | make[x][y] = 0;
69 | color[i] = 0;
70 | }
71 | }
72 | }
73 | }
74 | }
75 | }
76 | int main()
77 | {
78 | origin(3);
79 | search(0, 0, 0);
80 | outlln(count[0]);
81 | return 0;
82 | }
83 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/manyarguments.ans:
--------------------------------------------------------------------------------
1 | 120
2 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/manyarguments.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int a(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15)
3 | {
4 | return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15;
5 | }
6 |
7 | int main()
8 | {
9 | outlln(a(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15));
10 | return 0;
11 | }
12 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/multiarray.ans:
--------------------------------------------------------------------------------
1 | 888
2 | 0
3 | 1
4 | 2
5 | 3
6 | 4
7 | 5
8 | 6
9 | 7
10 | 8
11 | 9
12 | 10
13 | 11
14 | 12
15 | 13
16 | 14
17 | 15
18 | 16
19 | 17
20 | 18
21 | 19
22 | 20
23 | 21
24 | 22
25 | 23
26 | 24
27 | 25
28 | 26
29 | 27
30 | 28
31 | 29
32 | 30
33 | 31
34 | 32
35 | 33
36 | 34
37 | 35
38 | 36
39 | 37
40 | 38
41 | 39
42 | 0
43 | -10
44 | -1
45 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/multiarray.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int a[4][11];
3 | int i;
4 | int j;
5 |
6 | struct rec {
7 | int num;
8 | int c;
9 | }b[5];
10 |
11 | void printNum(int num) {
12 | outlln(num);
13 | }
14 | int main() {
15 |
16 |
17 | for (i = 0; i < 4; i ++) {
18 | for (j = 0; j < 10; j ++)
19 | a[i][j] = 888;
20 | }
21 | for (i = 0; i < 5; i ++) {
22 | b[i].num = -1;
23 | }
24 |
25 | printNum(a[3][9]);
26 | for (i = 0; i <= 3; i ++)
27 | for (j = 0; j <= 9; j ++)
28 | a[i][j] = i * 10 + j;
29 |
30 | for (i = 0; i <= 3; i ++)
31 | for (j = 0; j <= 9; j ++)
32 | printNum(a[i][j]);
33 | a[2][10]=0;
34 | printNum(a[2][10]);
35 | b[0].num = -2;
36 | b[a[2][10]].num = -10;
37 | printNum(b[0].num);
38 | printNum(b[1].num);
39 | return 0;
40 | }
41 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/pi.ans:
--------------------------------------------------------------------------------
1 | 3141592653589793238462643383279528841971693993751058209749445923078164062862089986280348253421170679821480865132823664709384469555822317253594081284811174502841270193852115559644622948954930381964428810975665933446128475648233786783165271201991456485669234634861045432664821339360726024914127372458706606315588174881520920962829254917153643678925903611330530548820466521384146951941511609433057273657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566438602139494639522473719070217986943702770539217176293176752384674818467669451320005681271452635608277857713427577896091736371787214684409012249534301465495853710579227968925892354201995611212902196864344181598136297747713099605187072113499999983729780499510597317328160963185
2 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/pi.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int f[2801];
3 | int main() {
4 | int a = 10000;
5 | int b = 0;
6 | int c = 2800;
7 | int d = 0;
8 | int e = 0;
9 | int g = 0;
10 |
11 | for (;b-c!=0;)
12 | f[b++] = a/5;
13 | for (;; e = d%a){
14 | d = 0;
15 | g = c*2;
16 | if (g==0) break;
17 |
18 | for (b=c;;d=d*b){
19 | d=d+f[b]*a;
20 | f[b] = d%--g;
21 | d=d/g--;
22 | if (--b==0) break;
23 | }
24 |
25 | c = c-14;
26 | outl(e+d/a); // should be printf("%04b"), but let it be
27 | }
28 |
29 | print("\n");
30 | return 0;
31 | }
32 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/qsort.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | // Target: qsort
3 | // Possible optimization: Dead code elimination, common expression, strength reduction
4 | // REMARKS: nothing.
5 | //
6 | //
7 |
8 | //int a[10100];
9 | int a[10100];
10 | int n = 10000;
11 |
12 | int qsrt(int l, int r) {
13 | int i = l;
14 | int j = r;
15 | int x = a[(l + r) / 2];
16 | while (i <= j) {
17 | while (a[i] < x) i++;
18 | while (a[j] > x) j--;
19 | if (i <= j) {
20 | int temp = a[i];
21 | a[i] = a[j];
22 | a[j] = temp;
23 | i++;
24 | j--;
25 | }
26 | }
27 | if (l < j) qsrt(l, j);
28 | if (i < r) qsrt(i, r);
29 | return 0;
30 | }
31 |
32 | int main() {
33 | int i;
34 | for (i = 1; i <= n; i++)
35 | a[i] = n + 1 - i;
36 | qsrt(1, n);
37 | for (i = 1; i <= n; i++) {
38 | outl(a[i]);
39 | print(" ");
40 | sleep(1); // to prevent UART buffer from overflowing
41 | }
42 | print("\n");
43 | return 0;
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/queens.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int N = 8;
3 | int row[8];
4 | int col[8];
5 | int d[2][16];
6 |
7 | void printBoard() {
8 | int i;
9 | int j;
10 | for (i = 0; i < N; i++) {
11 | for (j = 0; j < N; j++) {
12 | if (col[i] == j)
13 | print(" O");
14 | else
15 | print(" .");
16 | }
17 | println("");
18 | }
19 | println("");
20 | sleep(50); // to prevent UART buffer from overflowing
21 | }
22 |
23 | void search(int c) {
24 | if (c == N) {
25 | printBoard();
26 | }
27 | else {
28 | int r;
29 | for (r = 0; r < N; r++) {
30 | if (row[r] == 0 && d[0][r+c] == 0 && d[1][r+N-1-c] == 0) {
31 | row[r] = d[0][r+c] = d[1][r+N-1-c] = 1;
32 | col[c] = r;
33 | search(c+1);
34 | row[r] = d[0][r+c] = d[1][r+N-1-c] = 0;
35 | }
36 | }
37 | }
38 | }
39 |
40 | int main() {
41 | search(0);
42 | return 0;
43 | }
44 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/statement_test.ans:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 2
4 | 4
5 | 2
6 | 6
7 | 4
8 | 6
9 | 4
10 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/statement_test.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | //考察点:section 8 语句,包括if,while,for,break,continue,return等
3 | //算法:线性筛法求欧拉函数
4 | //样例输入:10
5 | //样例输出:
6 | //1
7 | //2
8 | //2
9 | //4
10 | //2
11 | //6
12 | //4
13 | //6
14 | //4
15 |
16 | int N;
17 | int M = 0;
18 | int check[20];
19 |
20 | int main() {
21 | N = inl();
22 | int i = 0;
23 | while ( i <= N ) check[i++] = 1;
24 | int phi[15];
25 | int P[15];
26 | phi[1] = 1;
27 | for (i = 2; ; ++i ) {
28 | if ( i > N ) break;
29 | if ( check[i] ) {
30 | P[++M] = i;
31 | phi[i] = i - 1;
32 | }
33 | int k = i;
34 | int i;
35 | for (i = 1; i <= M && (k * P[i] <= N); i++) {
36 | int tmp = k * P[i];
37 | if ( tmp > N ) continue;
38 | check[tmp] = 0;
39 | if ( k % P[i] == 0) {
40 | phi[tmp] = phi[k] * P[i];
41 | break;
42 | }
43 | else {
44 | phi[k * P[i]] = phi[k] * (P[i] - 1);
45 | }
46 | }
47 | outlln(phi[k]);
48 | }
49 | return 0;
50 | }
51 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/statement_test.in:
--------------------------------------------------------------------------------
1 | 10
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/superloop.ans:
--------------------------------------------------------------------------------
1 | 720
2 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/superloop.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | //Target: use loops to calculate calculator of 6!
3 | //@author yixi
4 |
5 | int N;
6 | int h = 99;
7 | int i = 100;
8 | int j = 101;
9 | int k = 102;
10 | int total = 0;
11 |
12 | int main() {
13 | int a;
14 | int b;
15 | int c;
16 | int d;
17 | int e;
18 | int f;
19 | N=inl();
20 | for ( a=1; a<=N; a++ )
21 | for ( b=1; b<=N; b++ )
22 | for ( c=1; c<=N; c++ )
23 | for ( d=1; d<=N; d++ )
24 | for ( e=1; e<=N; e++ )
25 | for ( f=1; f<=N; f++ )
26 | if (a!=b && a!=c && a!=d && a!=e && a!=f && a!=h && a!=i && a!=j && a!=k
27 | && b!=c && b!=d && b!=e && b!=f && b!=h && b!=i && b!=j && b!=k
28 | && c!=d && c!=e && c!=f && c!=h && c!=i && c!=j && c!=k
29 | && d!=e && d!=f && d!=h && d!=i && d!=j && d!=k
30 | && e!=f && e!=h && e!=i && e!=j && e!=k
31 | && f!=h && f!=i && f!=j && f!=k && i!=j && h!=k)
32 | {
33 | total++;
34 | }
35 |
36 | outlln(total);
37 | return 0;
38 | }
39 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/superloop.in:
--------------------------------------------------------------------------------
1 | 6
2 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/tak.ans:
--------------------------------------------------------------------------------
1 | 13
2 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/tak.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int tak(int x, int y, int z) {
3 | if ( y < x ) return 1 + tak( tak(x-1, y, z), tak(y-1, z, x), tak(z-1, x, y) );
4 | else return z;
5 | }
6 |
7 | int main(){
8 | int a;
9 | int b;
10 | int c;
11 | a=inl();
12 | b=inl();
13 | c=inl();
14 | outlln(tak(a,b,c));
15 | return 0;
16 | }
17 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/tak.in:
--------------------------------------------------------------------------------
1 | 18
2 | 12
3 | 6
4 |
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/testsleep.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int main()
3 | {
4 | int a = clock();
5 | sleep(10000); // sleep for 10s
6 | int b = clock();
7 | outlln(b-a);
8 | outlln((b-a)/CPU_CLK_FREQ); // should be 10
9 | return 0; // check actual running time
10 | }
--------------------------------------------------------------------------------
/doc/RISCV-CPU-doc/riscv/testcase/uartboom.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 |
3 | int main(){
4 | int i = 0;
5 | for ( ; i < 0x1ff; i++) {
6 | outb('a');
7 | outb('b');
8 | outb('c');
9 | outb('d');
10 | outb('e');
11 | outb('f');
12 | outb('g');
13 | outb('h');
14 | outb('i');
15 | outb('j');
16 | outb('k');
17 | outb('l');
18 | outb('m');
19 | outb('n');
20 | outb('o');
21 | outb('p');
22 | }
23 | return 0;
24 | }
25 |
--------------------------------------------------------------------------------
/riscv/Makefile:
--------------------------------------------------------------------------------
1 | prefix = $(shell pwd)
2 | # Folder Path
3 | src = $(prefix)/src
4 | testspace = $(prefix)/testspace
5 |
6 | sim_testcase = $(prefix)/testcase/sim
7 | fpga_testcase = $(prefix)/testcase/fpga
8 |
9 | sim = $(prefix)/sim
10 | riscv_toolchain = /opt/riscv
11 | riscv_bin = $(riscv_toolchain)/bin
12 | sys = $(prefix)/sys
13 |
14 | _no_testcase_name_check:
15 | @$(if $(strip $(name)),, echo 'Missing Testcase Name')
16 | @$(if $(strip $(name)),, exit 1)
17 |
18 | # All build result are put at testspace
19 | build_sim:
20 | @cd $(src) && iverilog -o $(testspace)/test $(sim)/testbench.v $(src)/common/block_ram/*.v $(src)/common/fifo/*.v $(src)/common/uart/*.v $(src)/*.vh $(src)/*.v
21 |
22 | build_sim_test: _no_testcase_name_check
23 | @$(riscv_bin)/riscv32-unknown-elf-as -o $(sys)/rom.o -march=rv32i $(sys)/rom.s
24 | @cp $(sim_testcase)/*$(name)*.c $(testspace)/test.c
25 | @$(riscv_bin)/riscv32-unknown-elf-gcc -o $(testspace)/test.o -I $(sys) -c $(testspace)/test.c -O2 -march=rv32i -mabi=ilp32 -Wall
26 | @$(riscv_bin)/riscv32-unknown-elf-ld -T $(sys)/memory.ld $(sys)/rom.o $(testspace)/test.o -L $(riscv_toolchain)/riscv32-unknown-elf/lib/ -L $(riscv_toolchain)/lib/gcc/riscv32-unknown-elf/13.2.0/ -lc -lgcc -lm -lnosys -o $(testspace)/test.om
27 | @$(riscv_bin)/riscv32-unknown-elf-objcopy -O verilog $(testspace)/test.om $(testspace)/test.data
28 | @$(riscv_bin)/riscv32-unknown-elf-objdump -D $(testspace)/test.om > $(testspace)/test.dump
29 |
30 | run_sim:
31 | @cd $(testspace) && ./test
32 |
33 | clear:
34 | @rm $(sys)/rom.o $(testspace)/test*
35 |
36 | test_sim: build_sim build_sim_test run_sim
37 |
38 | .PHONY: _no_testcase_name_check build_sim build_sim_test run_sim clear test_sim
39 |
--------------------------------------------------------------------------------
/riscv/fpga/build.sh:
--------------------------------------------------------------------------------
1 | set -e
2 | dir=`dirname $0`
3 | g++ $dir/controller.cpp -std=c++14 -I /tmp/usr/local/include/ -L /tmp/usr/local/lib/ -lserial -lpthread -o $dir/fpga
4 |
--------------------------------------------------------------------------------
/riscv/fpga/controller.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | int run_mode;
9 |
10 | #define error(msg...) printf(msg)
11 | #define info(msg...) do{if(run_mode) printf(msg);}while(0)
12 |
13 | typedef std::uint8_t byte;
14 | typedef std::uint16_t word;
15 | typedef std::uint32_t dword;
16 |
17 | serial::Serial serPort;
18 |
19 | void uart_send(const byte *data, int send_count, byte* recv, int return_count) {
20 | serPort.write(data,send_count);
21 | if (!return_count) return;
22 | try {
23 | serPort.read(recv,return_count);
24 | } catch (std::exception &e) {
25 | error("recv error: %s\n",e.what());
26 | }
27 | }
28 | void uart_send(const std::vector data, byte* recv, int return_count) {
29 | uart_send(data.data(),data.size(),recv,return_count);
30 | }
31 | void uart_send(const std::string &data) { serPort.write(data); }
32 | void uart_send(const byte *data, int size) { serPort.write(data,size); }
33 | void uart_send(const std::vector &data) { serPort.write(data); }
34 | void uart_read(byte *data, int size) { serPort.read(data, size); }
35 |
36 | #include "listener.h"
37 |
38 | int init_port(char* port) {
39 | serPort.setPort(port);
40 | serPort.setBaudrate(baud_rate);
41 | serPort.setBytesize(byte_size);
42 | serPort.setParity(parity);
43 | serPort.setStopbits(stopbits);
44 | serPort.setTimeout(
45 | inter_byte_timeout,
46 | read_timeout_constant,
47 | read_timeout_multiplier,
48 | write_timeout_constant,
49 | write_timeout_multiplier
50 | );
51 | try {
52 | serPort.open();
53 | } catch (std::exception &e) {
54 | error("failed to open port: %s\n",e.what());
55 | return 1;
56 | }
57 | info("initialized UART port on: %s\n",port);
58 | return 0;
59 | }
60 |
61 | byte ram_data[0x40000];
62 | byte in_data[0x400];
63 |
64 | int load_ram(char* rom_path) {
65 | std::ifstream fin(rom_path);
66 | if (!fin.is_open()) return 0;
67 | fin.seekg(0, std::ios_base::end);
68 | int ram_size = fin.tellg();
69 | info("RAM size: %x\n", ram_size);
70 | fin.seekg(0, std::ios_base::beg);
71 | fin.read(reinterpret_cast(ram_data), ram_size);
72 | for (int i=0;i<0x40; ++i) {
73 | info("%02x ", (byte)ram_data[i+0x1000]);
74 | if (!((i+1)%16)) info("\n");
75 | }
76 | fin.close();
77 | return ram_size;
78 | }
79 |
80 | int load_input(char* in_path) {
81 | if (!in_path) return 0;
82 | std::ifstream fin(in_path);
83 | if (!fin.is_open()) return 0;
84 | fin.seekg(0, std::ios_base::end);
85 | int in_size = fin.tellg();
86 | info("INPUT size: %x\n", in_size);
87 | fin.seekg(0, std::ios_base::beg);
88 | fin.read(reinterpret_cast(in_data), in_size);
89 | for (int i=0;i<0x10; ++i) {
90 | info("%02x ", (byte)in_data[i]);
91 | if (!((i+1)%16)) info("\n");
92 | }
93 | fin.close();
94 | return in_size;
95 | }
96 |
97 | clock_t start_tm;
98 | clock_t end_tm;
99 |
100 | void run() {
101 | // demo
102 |
103 | // debug packet format: see hci.v or README.md
104 | // send[0] is always OPCODE
105 | // to send debug packets, use uart_send(send,send_count)
106 | // to receive data after send, use uart_send(send,send_count,recv,recv_count)
107 | char c;
108 | int run = 0;
109 | while (1){
110 | info("Enter r to run, q to quit, p to get cpu PC(demo)\n");
111 | c=getchar();
112 | if (c=='q') {
113 | break;
114 | }
115 | else if (c=='p') {
116 | // demo for debugging cpu
117 | // add support in hci.v to allow more debug operations
118 | byte send[6]={0};
119 | byte recv[64]={0};
120 | send[0]=0x01;
121 | uart_send(send,1,recv,4);
122 | int pc = *reinterpret_cast(recv);
123 | info("pc:%08x\n",pc);
124 | send[0] = 0x09;
125 | int get_size = 16;
126 | *reinterpret_cast(send+1)=pc;
127 | *reinterpret_cast(send+4)=get_size;
128 | uart_send(send,6,recv,get_size);
129 | for (int i=0;i<16;++i) {
130 | info("%02x ",recv[i]);
131 | }
132 | info("\n");
133 | }
134 | else if (c=='r') {
135 | // run or pause cpu
136 | byte send[2];
137 | send[0]=(run?0x03:0x04);
138 | run = !run;
139 | info("CPU start\n");
140 | uart_send(send,1);
141 | start_tm = clock();
142 | // receive output bytes from fpga
143 | while (1) {
144 | byte data;
145 | // to debug cpu at the same time, implement separate thread
146 | while (!serPort.available());
147 | uart_read(&data,1);
148 | if (on_recv(data)) break;
149 | }
150 | end_tm = clock();
151 | info("\nCPU returned with running time: %f\n",(double)(end_tm - start_tm) / CLOCKS_PER_SEC);
152 |
153 | // manually pressing reset button is recommended
154 |
155 | // or pause and reset cpu through uart (TODO)
156 | // send[0]=(run?0x03:0x04);
157 | // run = !run;
158 | // uart_send(send,1);
159 |
160 | return;
161 | }
162 | }
163 | }
164 |
165 | void run_auto() {
166 | byte send[2];
167 | send[0]=(0x04);
168 | uart_send(send,1);
169 | start_tm = clock();
170 | while (1) {
171 | byte data;
172 | while (!serPort.available());
173 | uart_read(&data,1);
174 | if (data==0) break;
175 | putchar(data);
176 | }
177 | end_tm = clock();
178 | }
179 |
180 | int main(int argc, char** argv) {
181 | if (argc<4) {
182 | error("usage: path-to-ram [path-to-input] com-port -I(interactive)/-T(testing)\n");
183 | return 1;
184 | }
185 | char* ram_path = argv[1];
186 | int no_input = argc<5;
187 | char* input_path = no_input ? NULL : argv[2];
188 | char* comport = argv[argc-2];
189 | char param = argv[argc-1][1];
190 | if (param=='I') {
191 | run_mode = 1;
192 | } else if (param=='T') {
193 | run_mode = 0;
194 | }
195 | int ram_size = 0, in_size = 0;
196 | if (!(ram_size=load_ram(ram_path))) {
197 | error("failed to read ram file\n");
198 | return 1;
199 | }
200 | if (!no_input && !(in_size=load_input(input_path))){
201 | info("input file not found, skipping\n");
202 | }
203 | if (init_port(comport)) return 1;
204 | if (on_init()) return 1;
205 | upload_ram(ram_data, ram_size);
206 | upload_input(in_data, in_size);
207 | // verify_ram(ram_data, ram_size);
208 | if (run_mode) run();
209 | else run_auto();
210 | serPort.close();
211 | }
212 |
--------------------------------------------------------------------------------
/riscv/fpga/listener.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | // UART port configuration, adjust according to implementation
9 | int baud_rate = 115200;
10 | serial::bytesize_t byte_size = serial::eightbits;
11 | serial::parity_t parity = serial::parity_odd;
12 | serial::stopbits_t stopbits = serial::stopbits_one;
13 | int inter_byte_timeout = 50;
14 | int read_timeout_constant = 50;
15 | int read_timeout_multiplier = 10;
16 | int write_timeout_constant = 50;
17 | int write_timeout_multiplier = 10;
18 |
19 | //methods
20 | int on_init() {
21 | using namespace std::chrono_literals;
22 | byte junk[10];
23 | uart_read(junk,8);
24 | std::this_thread::sleep_for(std::chrono::seconds(1));
25 | byte init[10];
26 | byte recv[10]={0};
27 | init[0] = 0x00;
28 | int len = 4;
29 | *reinterpret_cast(init+1) = len;
30 | char test[10] = "UART";
31 | for (int i=0;i(recv);
42 | if (strcmp(str,test)) {
43 | error("UART assertion failed\n");
44 | return 1;
45 | }
46 | return 0;
47 | }
48 |
49 | void upload_ram(byte* ram_data, int ram_size) {
50 | if (!ram_size) return;
51 | const int short blk_size = 0x400;
52 | const int pld_size = 1+3+2+blk_size;
53 | byte payload[pld_size];
54 | int blk_cnt = (ram_size / blk_size);
55 | if (blk_cnt*blk_size(payload+1) = addr;
63 | *reinterpret_cast(payload+4) = blk_size;
64 | for (int j=0;j(payload+1) = pre_size;
85 | uart_send(payload,1+2+pre_size);
86 | int rem_size = in_size;
87 | for (int i=0; i(payload+1) = dat_size;
93 | for (int j=0;j(payload+1) = addr;
117 | *reinterpret_cast(payload+4) = blk_size;
118 | uart_send(payload,6,recv_data,blk_size);
119 | for (int j=0; j ' + ('NUL' if isWin else '/dev/null'))
18 |
19 | def collect_test_cases():
20 | test_cases = []
21 | for f in os.listdir(test_cases_dir):
22 | if os.path.splitext(f)[1] == '.ans':
23 | test_cases.append(os.path.splitext(os.path.split(f)[1])[0])
24 | for s in excluded_test_cases:
25 | if s in test_cases: test_cases.remove(s)
26 | test_cases.sort()
27 | return test_cases
28 |
29 | def main():
30 | program_device()
31 | test_cases = collect_test_cases()
32 |
33 | print('Build controller...')
34 | if os.system(wslPrefix + './ctrl/build.sh'):
35 | print(color_red + 'Build Failed' + color_none)
36 | return
37 | print(color_green + 'Success' + color_none)
38 |
39 | for t in test_cases:
40 | print('Testing ' + t + ': ')
41 | if os.system(wslPrefix + './autorun_fpga.sh ' + t):
42 | print(color_red + 'Test Failed' + color_none)
43 | continue
44 | if os.system(wslPrefix + 'diff ./test/test.ans ./test/test.out > diff.out'):
45 | print(color_red + 'Wrong Answer' + color_none)
46 | continue
47 | print(color_green + 'Accepted' + color_none)
48 |
49 | if __name__ == '__main__':
50 | main()
--------------------------------------------------------------------------------
/riscv/script/autorun_fpga.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # build testcase
3 | ./build_test.sh $@
4 | # copy test input
5 | if [ -f ./testspace/$@.in ]; then cp ./testspace/$@.in ./test/test.in; fi
6 | # copy test output
7 | if [ -f ./testspace/$@.ans ]; then cp ./testspace/$@.ans ./test/test.ans; fi
8 | # add your own test script here
9 | # Example: assuming serial port on /dev/ttyUSB1
10 | # ./fpga/build.sh
11 | # ./fpga/run.sh ./test/test.bin ./test/test.in /dev/ttyUSB1 -I
12 | ./fpga/run.sh ./test/test.bin ./test/test.in /dev/ttyUSB1 -T > ./test/test.out
--------------------------------------------------------------------------------
/riscv/script/build_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 | prefix='/opt/riscv'
4 | rpath=$prefix/bin/
5 | # clearing test dir
6 | rm -rf ./test
7 | mkdir ./test
8 | # compiling rom
9 | ${rpath}riscv32-unknown-elf-as -o ./sys/rom.o -march=rv32i ./sys/rom.s
10 | # compiling testcase
11 | cp ./testcase/${1%.*}.c ./test/test.c
12 | ${rpath}riscv32-unknown-elf-gcc -o ./test/test.o -I ./sys -c ./test/test.c -O2 -march=rv32i -mabi=ilp32 -Wall
13 | # linking
14 | ${rpath}riscv32-unknown-elf-ld -T ./sys/memory.ld ./sys/rom.o ./test/test.o -L $prefix/riscv32-unknown-elf/lib/ -L $prefix/lib/gcc/riscv32-unknown-elf/13.2.0/ -lc -lgcc -lm -lnosys -o ./test/test.om
15 | # converting to verilog format
16 | ${rpath}riscv32-unknown-elf-objcopy -O verilog ./test/test.om ./test/test.data
17 | # converting to binary format(for ram uploading)
18 | ${rpath}riscv32-unknown-elf-objcopy -O binary ./test/test.om ./test/test.bin
19 | # decompile (for debugging)
20 | ${rpath}riscv32-unknown-elf-objdump -D ./test/test.om > ./test/test.dump
21 |
--------------------------------------------------------------------------------
/riscv/script/run_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # build testcase
3 | ./build_test.sh $@
4 | # copy test input
5 | if [ -f ./testspace/$@.in ]; then cp ./testspace/$@.in ./test/test.in; fi
6 | # copy test output
7 | if [ -f ./testspace/$@.ans ]; then cp ./testspace/$@.ans ./test/test.ans; fi
8 | # add your own test script here
9 | # Example:
10 | # - iverilog/gtkwave/vivado
11 | # - diff ./test/test.ans ./test/test.out
12 |
--------------------------------------------------------------------------------
/riscv/script/run_test_fpga.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # build testcase
3 | ./build_test.sh $@
4 | # copy test input
5 | if [ -f ./testspace/$@.in ]; then cp ./testspace/$@.in ./test/test.in; fi
6 | # copy test output
7 | if [ -f ./testspace/$@.ans ]; then cp ./testspace/$@.ans ./test/test.ans; fi
8 | # add your own test script here
9 | # Example: assuming serial port on /dev/ttyUSB1
10 | ./ctrl/build.sh
11 | ./ctrl/run.sh ./test/test.bin ./test/test.in /dev/ttyUSB1 -I
12 | #./ctrl/run.sh ./test/test.bin ./test/test.in /dev/ttyUSB1 -T > ./test/test.out
13 | #if [ -f ./test/test.ans ]; then diff ./test/test.ans ./test/test.out; fi
14 |
--------------------------------------------------------------------------------
/riscv/sim/testbench.v:
--------------------------------------------------------------------------------
1 | // testbench top module file
2 | // for simulation only
3 |
4 | `timescale 1ns/1ps
5 | module testbench;
6 |
7 | reg clk;
8 | reg rst;
9 |
10 | riscv_top #(.SIM(1)) top(
11 | .EXCLK(clk),
12 | .btnC(rst),
13 | .Tx(),
14 | .Rx(),
15 | .led()
16 | );
17 |
18 | initial begin
19 | clk=0;
20 | rst=1;
21 | repeat(50) #1 clk=!clk;
22 | rst=0;
23 | forever #1 clk=!clk;
24 |
25 | $finish;
26 | end
27 |
28 | initial begin
29 | $dumpfile("test.vcd");
30 | $dumpvars(0, testbench);
31 | #300000000 $finish;
32 | end
33 |
34 | endmodule
35 |
--------------------------------------------------------------------------------
/riscv/src/common/block_ram/block_ram.v:
--------------------------------------------------------------------------------
1 | /***************************************************************************************************
2 | *
3 | * Copyright (c) 2012, Brian Bennett
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification, are permitted
7 | * provided that the following conditions are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
10 | * and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
12 | * conditions and the following disclaimer in the documentation and/or other materials provided
13 | * with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
22 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 | *
24 | * Various generic, inferred block ram descriptors.
25 | ***************************************************************************************************/
26 |
27 | // Dual port RAM with synchronous read. Modified version of listing 12.4 in "FPGA Prototyping by
28 | // Verilog Examples," itself a modified version of XST 8.11 v_rams_11.
29 | module dual_port_ram_sync
30 | #(
31 | parameter ADDR_WIDTH = 6,
32 | parameter DATA_WIDTH = 8
33 | )
34 | (
35 | input wire clk,
36 | input wire we,
37 | input wire [ADDR_WIDTH-1:0] addr_a,
38 | input wire [ADDR_WIDTH-1:0] addr_b,
39 | input wire [DATA_WIDTH-1:0] din_a,
40 | output wire [DATA_WIDTH-1:0] dout_a,
41 | output wire [DATA_WIDTH-1:0] dout_b
42 | );
43 |
44 | reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];
45 | reg [ADDR_WIDTH-1:0] q_addr_a;
46 | reg [ADDR_WIDTH-1:0] q_addr_b;
47 |
48 | always @(posedge clk)
49 | begin
50 | if (we)
51 | ram[addr_a] <= din_a;
52 | q_addr_a <= addr_a;
53 | q_addr_b <= addr_b;
54 | end
55 |
56 | assign dout_a = ram[q_addr_a];
57 | assign dout_b = ram[q_addr_b];
58 |
59 | endmodule
60 |
61 | // Single port RAM with synchronous read.
62 | module single_port_ram_sync
63 | #(
64 | parameter ADDR_WIDTH = 6,
65 | parameter DATA_WIDTH = 8
66 | )
67 | (
68 | input wire clk,
69 | input wire we,
70 | input wire [ADDR_WIDTH-1:0] addr_a,
71 | input wire [DATA_WIDTH-1:0] din_a,
72 | output wire [DATA_WIDTH-1:0] dout_a
73 | );
74 |
75 | reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];
76 | reg [ADDR_WIDTH-1:0] q_addr_a;
77 |
78 | always @(posedge clk)
79 | begin
80 | if (we)
81 | ram[addr_a] <= din_a;
82 | q_addr_a <= addr_a;
83 | end
84 |
85 | assign dout_a = ram[q_addr_a];
86 |
87 | // initialize ram content (for simulation)
88 | integer i;
89 | initial begin
90 | for (i=0;i<2**ADDR_WIDTH;i=i+1) begin
91 | ram[i] = 0;
92 | end
93 | $readmemh("test.data", ram); // add test.data to vivado project or specify a valid file path
94 | end
95 |
96 | endmodule
97 |
98 |
--------------------------------------------------------------------------------
/riscv/src/common/fifo/fifo.v:
--------------------------------------------------------------------------------
1 | /***************************************************************************************************
2 | *
3 | * Copyright (c) 2012, Brian Bennett
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification, are permitted
7 | * provided that the following conditions are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
10 | * and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
12 | * conditions and the following disclaimer in the documentation and/or other materials provided
13 | * with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
22 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 | *
24 | * Circular first in first out buffer implementation.
25 | ***************************************************************************************************/
26 |
27 | module fifo
28 | #(
29 | parameter DATA_BITS = 8,
30 | parameter ADDR_BITS = 3
31 | )
32 | (
33 | input wire clk, // 50MHz system clock
34 | input wire reset, // Reset signal
35 | input wire rd_en, // Read enable, pop front of queue
36 | input wire wr_en, // Write enable, add wr_data to end of queue
37 | input wire [DATA_BITS-1:0] wr_data, // Data to be written on wr_en
38 | output wire [DATA_BITS-1:0] rd_data, // Current front of fifo data
39 | output wire full, // FIFO is full (writes invalid)
40 | output wire empty // FIFO is empty (reads invalid)
41 | );
42 |
43 | reg [ADDR_BITS-1:0] q_rd_ptr;
44 | wire [ADDR_BITS-1:0] d_rd_ptr;
45 | reg [ADDR_BITS-1:0] q_wr_ptr;
46 | wire [ADDR_BITS-1:0] d_wr_ptr;
47 | reg q_empty;
48 | wire d_empty;
49 | reg q_full;
50 | wire d_full;
51 |
52 | reg [DATA_BITS-1:0] q_data_array [2**ADDR_BITS-1:0];
53 | wire [DATA_BITS-1:0] d_data;
54 |
55 | wire rd_en_prot;
56 | wire wr_en_prot;
57 |
58 | // FF update logic. Synchronous reset.
59 | always @(posedge clk)
60 | begin
61 | if (reset)
62 | begin
63 | q_rd_ptr <= 0;
64 | q_wr_ptr <= 0;
65 | q_empty <= 1'b1;
66 | q_full <= 1'b0;
67 | end
68 | else
69 | begin
70 | q_rd_ptr <= d_rd_ptr;
71 | q_wr_ptr <= d_wr_ptr;
72 | q_empty <= d_empty;
73 | q_full <= d_full;
74 | q_data_array[q_wr_ptr] <= d_data;
75 | end
76 | end
77 |
78 | // Derive "protected" read/write signals.
79 | assign rd_en_prot = (rd_en && !q_empty);
80 | assign wr_en_prot = (wr_en && !q_full);
81 |
82 | // Handle writes.
83 | assign d_wr_ptr = (wr_en_prot) ? q_wr_ptr + 1'h1 : q_wr_ptr;
84 | assign d_data = (wr_en_prot) ? wr_data : q_data_array[q_wr_ptr];
85 |
86 | // Handle reads.
87 | assign d_rd_ptr = (rd_en_prot) ? q_rd_ptr + 1'h1 : q_rd_ptr;
88 |
89 | wire [ADDR_BITS-1:0] addr_bits_wide_1;
90 | assign addr_bits_wide_1 = 1;
91 |
92 | // Detect empty state:
93 | // 1) We were empty before and there was no write.
94 | // 2) We had one entry and there was a read.
95 | assign d_empty = ((q_empty && !wr_en_prot) ||
96 | (((q_wr_ptr - q_rd_ptr) == addr_bits_wide_1) && rd_en_prot));
97 |
98 | // Detect full state:
99 | // 1) We were full before and there was no read.
100 | // 2) We had n-1 entries and there was a write.
101 | assign d_full = ((q_full && !rd_en_prot) ||
102 | (((q_rd_ptr - q_wr_ptr) == addr_bits_wide_1) && wr_en_prot));
103 |
104 | // Assign output signals to appropriate FFs.
105 | assign rd_data = q_data_array[q_rd_ptr];
106 | assign full = q_full;
107 | assign empty = q_empty;
108 |
109 | endmodule
110 |
111 |
--------------------------------------------------------------------------------
/riscv/src/common/uart/uart.v:
--------------------------------------------------------------------------------
1 | /***************************************************************************************************
2 | *
3 | * Copyright (c) 2012, Brian Bennett
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification, are permitted
7 | * provided that the following conditions are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
10 | * and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
12 | * conditions and the following disclaimer in the documentation and/or other materials provided
13 | * with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
22 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 | *
24 | * UART controller. Universal Asynchronous Receiver/Transmitter control module for an RS-232
25 | * (serial) port.
26 | ***************************************************************************************************/
27 |
28 | module uart
29 | #(
30 | parameter SYS_CLK_FREQ = 50000000,
31 | parameter BAUD_RATE = 19200,
32 | parameter DATA_BITS = 8,
33 | parameter STOP_BITS = 1,
34 | parameter PARITY_MODE = 0 // 0 = none, 1 = odd, 2 = even
35 | )
36 | (
37 | input wire clk, // System clk
38 | input wire reset, // Reset signal
39 | input wire rx, // RS-232 rx pin
40 | input wire [DATA_BITS-1:0] tx_data, // Data to be transmitted when wr_en is 1
41 | input wire rd_en, // Pops current read FIFO front off the queue
42 | input wire wr_en, // Write tx_data over serial connection
43 | output wire tx, // RS-232 tx pin
44 | output wire [DATA_BITS-1:0] rx_data, // Data currently at front of read FIFO
45 | output wire rx_empty, // 1 if there is no more read data available
46 | output wire tx_full, // 1 if the transmit FIFO cannot accept more requests
47 | output wire parity_err // 1 if a parity error has been detected
48 | );
49 |
50 | localparam BAUD_CLK_OVERSAMPLE_RATE = 16;
51 |
52 | wire baud_clk_tick;
53 |
54 | wire [DATA_BITS-1:0] rx_fifo_wr_data;
55 | wire rx_done_tick;
56 | wire rx_parity_err;
57 |
58 | wire [DATA_BITS-1:0] tx_fifo_rd_data;
59 | wire tx_done_tick;
60 | wire tx_fifo_empty;
61 |
62 | // Store parity error in a flip flop as persistent state.
63 | reg q_rx_parity_err;
64 | wire d_rx_parity_err;
65 |
66 | always @(posedge clk, posedge reset)
67 | begin
68 | if (reset)
69 | q_rx_parity_err <= 1'b0;
70 | else
71 | q_rx_parity_err <= d_rx_parity_err;
72 | end
73 |
74 | assign parity_err = q_rx_parity_err;
75 | assign d_rx_parity_err = q_rx_parity_err || rx_parity_err;
76 |
77 | // BAUD clock module
78 | uart_baud_clk #(.SYS_CLK_FREQ(SYS_CLK_FREQ),
79 | .BAUD(BAUD_RATE),
80 | .BAUD_CLK_OVERSAMPLE_RATE(BAUD_CLK_OVERSAMPLE_RATE)) uart_baud_clk_blk
81 | (
82 | .clk(clk),
83 | .reset(reset),
84 | .baud_clk_tick(baud_clk_tick)
85 | );
86 |
87 | // RX (receiver) module
88 | uart_rx #(.DATA_BITS(DATA_BITS),
89 | .STOP_BITS(STOP_BITS),
90 | .PARITY_MODE(PARITY_MODE),
91 | .BAUD_CLK_OVERSAMPLE_RATE(BAUD_CLK_OVERSAMPLE_RATE)) uart_rx_blk
92 | (
93 | .clk(clk),
94 | .reset(reset),
95 | .baud_clk_tick(baud_clk_tick),
96 | .rx(rx),
97 | .rx_data(rx_fifo_wr_data),
98 | .rx_done_tick(rx_done_tick),
99 | .parity_err(rx_parity_err)
100 | );
101 |
102 | // TX (transmitter) module
103 | uart_tx #(.DATA_BITS(DATA_BITS),
104 | .STOP_BITS(STOP_BITS),
105 | .PARITY_MODE(PARITY_MODE),
106 | .BAUD_CLK_OVERSAMPLE_RATE(BAUD_CLK_OVERSAMPLE_RATE)) uart_tx_blk
107 | (
108 | .clk(clk),
109 | .reset(reset),
110 | .baud_clk_tick(baud_clk_tick),
111 | .tx_start(~tx_fifo_empty),
112 | .tx_data(tx_fifo_rd_data),
113 | .tx_done_tick(tx_done_tick),
114 | .tx(tx)
115 | );
116 |
117 | // RX FIFO
118 | fifo #(.DATA_BITS(DATA_BITS),
119 | .ADDR_BITS(3)) uart_rx_fifo
120 | (
121 | .clk(clk),
122 | .reset(reset),
123 | .rd_en(rd_en),
124 | .wr_en(rx_done_tick),
125 | .wr_data(rx_fifo_wr_data),
126 | .rd_data(rx_data),
127 | .empty(rx_empty),
128 | .full()
129 | );
130 |
131 | // TX FIFO (increased size)
132 | fifo #(.DATA_BITS(DATA_BITS),
133 | .ADDR_BITS(10)) uart_tx_fifo
134 | (
135 | .clk(clk),
136 | .reset(reset),
137 | .rd_en(tx_done_tick),
138 | .wr_en(wr_en),
139 | .wr_data(tx_data),
140 | .rd_data(tx_fifo_rd_data),
141 | .empty(tx_fifo_empty),
142 | .full(tx_full)
143 | );
144 |
145 | endmodule
146 |
147 |
--------------------------------------------------------------------------------
/riscv/src/common/uart/uart_baud_clk.v:
--------------------------------------------------------------------------------
1 | /***************************************************************************************************
2 | ** fpga_nes/hw/src/cmn/uart/uart_baud_clk.v
3 | *
4 | * Copyright (c) 2012, Brian Bennett
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification, are permitted
8 | * provided that the following conditions are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
11 | * and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
13 | * conditions and the following disclaimer in the documentation and/or other materials provided
14 | * with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
23 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | *
25 | * Generates a tick signal at OVERSAMPLE_RATE times the baud rate. Should be fed to the uart_rx
26 | * and uart_tx blocks.
27 | ***************************************************************************************************/
28 |
29 | module uart_baud_clk
30 | #(
31 | parameter SYS_CLK_FREQ = 50000000,
32 | parameter BAUD = 19200,
33 | parameter BAUD_CLK_OVERSAMPLE_RATE = 16
34 | )
35 | (
36 | input wire clk,
37 | input wire reset,
38 | output wire baud_clk_tick
39 | );
40 |
41 | localparam [15:0] CLKS_PER_OVERSAMPLE_TICK = (SYS_CLK_FREQ / BAUD) / BAUD_CLK_OVERSAMPLE_RATE;
42 |
43 | // Registers
44 | reg [15:0] q_cnt;
45 | wire [15:0] d_cnt;
46 |
47 | always @(posedge clk, posedge reset)
48 | begin
49 | if (reset)
50 | q_cnt <= 0;
51 | else
52 | q_cnt <= d_cnt;
53 | end
54 |
55 | assign d_cnt = (q_cnt == (CLKS_PER_OVERSAMPLE_TICK - 1)) ? 16'h0000 : (q_cnt + 16'h0001);
56 | assign baud_clk_tick = (q_cnt == (CLKS_PER_OVERSAMPLE_TICK - 1)) ? 1'b1 : 1'b0;
57 |
58 | endmodule
59 |
60 |
--------------------------------------------------------------------------------
/riscv/src/common/uart/uart_rx.v:
--------------------------------------------------------------------------------
1 | /***************************************************************************************************
2 | ** fpga_nes/hw/src/cmn/uart/uart_rx.v
3 | *
4 | * Copyright (c) 2012, Brian Bennett
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification, are permitted
8 | * provided that the following conditions are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
11 | * and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
13 | * conditions and the following disclaimer in the documentation and/or other materials provided
14 | * with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
23 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | *
25 | * UART receiver.
26 | ***************************************************************************************************/
27 |
28 | module uart_rx
29 | #(
30 | parameter DATA_BITS = 8,
31 | parameter STOP_BITS = 1,
32 | parameter PARITY_MODE = 1, // 0 = NONE, 1 = ODD, 2 = EVEN
33 | parameter BAUD_CLK_OVERSAMPLE_RATE = 16
34 | )
35 | (
36 | input wire clk, // System clock
37 | input wire reset, // Reset signal
38 | input wire baud_clk_tick, // 1 tick per OVERSAMPLE_RATE baud clks
39 | input wire rx, // RX transmission wire
40 | output wire [DATA_BITS-1:0] rx_data, // Output data
41 | output wire rx_done_tick, // Output rdy signal
42 | output wire parity_err // Asserted for one clk on parity error
43 | );
44 |
45 | localparam [5:0] STOP_OVERSAMPLE_TICKS = STOP_BITS * BAUD_CLK_OVERSAMPLE_RATE;
46 |
47 | // Symbolic state representations.
48 | localparam [4:0] S_IDLE = 5'h01,
49 | S_START = 5'h02,
50 | S_DATA = 5'h04,
51 | S_PARITY = 5'h08,
52 | S_STOP = 5'h10;
53 |
54 | // Registers
55 | reg [4:0] q_state, d_state;
56 | reg [3:0] q_oversample_tick_cnt, d_oversample_tick_cnt;
57 | reg [DATA_BITS-1:0] q_data, d_data;
58 | reg [2:0] q_data_bit_idx, d_data_bit_idx;
59 | reg q_done_tick, d_done_tick;
60 | reg q_parity_err, d_parity_err;
61 | reg q_rx;
62 |
63 | always @(posedge clk, posedge reset)
64 | begin
65 | if (reset)
66 | begin
67 | q_state <= S_IDLE;
68 | q_oversample_tick_cnt <= 0;
69 | q_data <= 0;
70 | q_data_bit_idx <= 0;
71 | q_done_tick <= 1'b0;
72 | q_parity_err <= 1'b0;
73 | q_rx <= 1'b1;
74 | end
75 | else
76 | begin
77 | q_state <= d_state;
78 | q_oversample_tick_cnt <= d_oversample_tick_cnt;
79 | q_data <= d_data;
80 | q_data_bit_idx <= d_data_bit_idx;
81 | q_done_tick <= d_done_tick;
82 | q_parity_err <= d_parity_err;
83 | q_rx <= rx;
84 | end
85 | end
86 |
87 | always @*
88 | begin
89 | // Default most state to remain unchanged.
90 | d_state = q_state;
91 | d_data = q_data;
92 | d_data_bit_idx = q_data_bit_idx;
93 |
94 | // Increment the tick counter if the baud_clk counter ticked.
95 | d_oversample_tick_cnt = (baud_clk_tick) ? q_oversample_tick_cnt + 4'h1 : q_oversample_tick_cnt;
96 |
97 | // Default the done signal and parity err to 0.
98 | d_done_tick = 1'b0;
99 | d_parity_err = 1'b0;
100 |
101 | case (q_state)
102 | S_IDLE:
103 | begin
104 | // Detect incoming data when rx goes low (start bit).
105 | if (~q_rx)
106 | begin
107 | d_state = S_START;
108 | d_oversample_tick_cnt = 0;
109 | end
110 | end
111 |
112 | S_START:
113 | begin
114 | // Wait for BAUD_CLK_OVERSAMPLE_RATE / 2 ticks to get "centered" in the start bit signal.
115 | if (baud_clk_tick && (q_oversample_tick_cnt == ((BAUD_CLK_OVERSAMPLE_RATE - 1) / 2)))
116 | begin
117 | d_state = S_DATA;
118 | d_oversample_tick_cnt = 0;
119 | d_data_bit_idx = 0;
120 | end
121 | end
122 |
123 | S_DATA:
124 | begin
125 | // Every BAUD_CLK_OVERSAMPLE_RATE clocks, sample rx and shift its value into the data reg.
126 | if (baud_clk_tick && (q_oversample_tick_cnt == (BAUD_CLK_OVERSAMPLE_RATE - 1)))
127 | begin
128 | d_data = { q_rx, q_data[DATA_BITS-1:1] };
129 | d_oversample_tick_cnt = 0;
130 |
131 | if (q_data_bit_idx == (DATA_BITS - 1))
132 | begin
133 | if (PARITY_MODE == 0)
134 | d_state = S_STOP;
135 | else
136 | d_state = S_PARITY;
137 | end
138 | else
139 | d_data_bit_idx = q_data_bit_idx + 3'h1;
140 | end
141 | end
142 |
143 | S_PARITY:
144 | begin
145 | if (baud_clk_tick && (q_oversample_tick_cnt == (BAUD_CLK_OVERSAMPLE_RATE - 1)))
146 | begin
147 | if (PARITY_MODE == 1)
148 | d_parity_err = (q_rx != ~^q_data);
149 | else
150 | d_parity_err = (q_rx != ^q_data);
151 |
152 | d_state = S_STOP;
153 | d_oversample_tick_cnt = 0;
154 | end
155 | end
156 |
157 | S_STOP:
158 | begin
159 | // Wait for stop bit before returning to idle. Signal done_tick.
160 | if (baud_clk_tick && (q_oversample_tick_cnt == STOP_OVERSAMPLE_TICKS - 1))
161 | begin
162 | d_state = S_IDLE;
163 | d_done_tick = 1'b1;
164 | end
165 | end
166 | endcase
167 | end
168 |
169 | assign rx_data = q_data;
170 | assign rx_done_tick = q_done_tick;
171 | assign parity_err = q_parity_err;
172 |
173 | endmodule
174 |
175 |
--------------------------------------------------------------------------------
/riscv/src/cpu.v:
--------------------------------------------------------------------------------
1 | // RISCV32I CPU top module
2 | // port modification allowed for debugging purposes
3 |
4 | module cpu(
5 | input wire clk_in, // system clock signal
6 | input wire rst_in, // reset signal
7 | input wire rdy_in, // ready signal, pause cpu when low
8 |
9 | input wire [ 7:0] mem_din, // data input bus
10 | output wire [ 7:0] mem_dout, // data output bus
11 | output wire [31:0] mem_a, // address bus (only 17:0 is used)
12 | output wire mem_wr, // write/read signal (1 for write)
13 |
14 | input wire io_buffer_full, // 1 if uart buffer is full
15 |
16 | output wire [31:0] dbgreg_dout // cpu register output (debugging demo)
17 | );
18 |
19 | // implementation goes here
20 |
21 | // Specifications:
22 | // - Pause cpu(freeze pc, registers, etc.) when rdy_in is low
23 | // - Memory read result will be returned in the next cycle. Write takes 1 cycle(no need to wait)
24 | // - Memory is of size 128KB, with valid address ranging from 0x0 to 0x20000
25 | // - I/O port is mapped to address higher than 0x30000 (mem_a[17:16]==2'b11)
26 | // - 0x30000 read: read a byte from input
27 | // - 0x30000 write: write a byte to output (write 0x00 is ignored)
28 | // - 0x30004 read: read clocks passed since cpu starts (in dword, 4 bytes)
29 | // - 0x30004 write: indicates program stop (will output '\0' through uart tx)
30 |
31 | always @(posedge clk_in)
32 | begin
33 | if (rst_in)
34 | begin
35 |
36 | end
37 | else if (!rdy_in)
38 | begin
39 |
40 | end
41 | else
42 | begin
43 |
44 | end
45 | end
46 |
47 | endmodule
--------------------------------------------------------------------------------
/riscv/src/ram.v:
--------------------------------------------------------------------------------
1 | // implements 128KB of on-board RAM
2 |
3 | module ram
4 | #(
5 | parameter ADDR_WIDTH = 17
6 | )
7 | (
8 | input wire clk_in, // system clock
9 | input wire en_in, // chip enable
10 | input wire r_nw_in, // read/write select (read: 1, write: 0)
11 | input wire [ADDR_WIDTH-1:0] a_in, // memory address
12 | input wire [ 7:0] d_in, // data input
13 | output wire [ 7:0] d_out // data output
14 | );
15 |
16 | wire ram_bram_we;
17 | wire [7:0] ram_bram_dout;
18 |
19 | single_port_ram_sync #(.ADDR_WIDTH(ADDR_WIDTH),
20 | .DATA_WIDTH(8)) ram_bram(
21 | .clk(clk_in),
22 | .we(ram_bram_we),
23 | .addr_a(a_in),
24 | .din_a(d_in),
25 | .dout_a(ram_bram_dout)
26 | );
27 |
28 | assign ram_bram_we = (en_in) ? ~r_nw_in : 1'b0;
29 | assign d_out = (en_in) ? ram_bram_dout : 8'h00;
30 |
31 | endmodule
--------------------------------------------------------------------------------
/riscv/src/riscv_top.v:
--------------------------------------------------------------------------------
1 | // riscv top module file
2 | // modification allowed for debugging purposes
3 |
4 | module riscv_top
5 | #(
6 | parameter SIM = 0 // whether in simulation
7 | )
8 | (
9 | input wire EXCLK,
10 | input wire btnC,
11 | output wire Tx,
12 | input wire Rx,
13 | output wire led
14 | );
15 |
16 | localparam SYS_CLK_FREQ = 100000000;
17 | localparam UART_BAUD_RATE = 115200;
18 | localparam RAM_ADDR_WIDTH = 17; // 128KiB ram, should not be modified
19 |
20 | reg rst;
21 | reg rst_delay;
22 |
23 | wire clk;
24 |
25 | // assign EXCLK (or your own clock module) to clk
26 | assign clk = EXCLK;
27 |
28 | always @(posedge clk or posedge btnC)
29 | begin
30 | if (btnC)
31 | begin
32 | rst <= 1'b1;
33 | rst_delay <= 1'b1;
34 | end
35 | else
36 | begin
37 | rst_delay <= 1'b0;
38 | rst <= rst_delay;
39 | end
40 | end
41 |
42 | //
43 | // System Memory Buses
44 | //
45 | wire [ 7:0] cpumc_din;
46 | wire [31:0] cpumc_a;
47 | wire cpumc_wr;
48 |
49 | //
50 | // RAM: internal ram
51 | //
52 | wire ram_en;
53 | wire [RAM_ADDR_WIDTH-1:0] ram_a;
54 | wire [ 7:0] ram_dout;
55 |
56 | ram #(.ADDR_WIDTH(RAM_ADDR_WIDTH))ram0(
57 | .clk_in(clk),
58 | .en_in(ram_en),
59 | .r_nw_in(~cpumc_wr),
60 | .a_in(ram_a),
61 | .d_in(cpumc_din),
62 | .d_out(ram_dout)
63 | );
64 |
65 | assign ram_en = (cpumc_a[RAM_ADDR_WIDTH:RAM_ADDR_WIDTH-1] == 2'b11) ? 1'b0 : 1'b1;
66 | assign ram_a = cpumc_a[RAM_ADDR_WIDTH-1:0];
67 |
68 | //
69 | // CPU: CPU that implements RISC-V 32b integer base user-level real-mode ISA
70 | //
71 | wire [31:0] cpu_ram_a;
72 | wire cpu_ram_wr;
73 | wire [ 7:0] cpu_ram_din;
74 | wire [ 7:0] cpu_ram_dout;
75 | wire cpu_rdy;
76 |
77 | wire [31:0] cpu_dbgreg_dout;
78 |
79 |
80 | //
81 | // HCI: host communication interface block. Use controller to interact.
82 | //
83 | wire hci_active_out;
84 | wire [ 7:0] hci_ram_din;
85 | wire [ 7:0] hci_ram_dout;
86 | wire [RAM_ADDR_WIDTH-1:0] hci_ram_a;
87 | wire hci_ram_wr;
88 |
89 | wire hci_io_en;
90 | wire [ 2:0] hci_io_sel;
91 | wire [ 7:0] hci_io_din;
92 | wire [ 7:0] hci_io_dout;
93 | wire hci_io_wr;
94 | wire hci_io_full;
95 |
96 | wire program_finish;
97 |
98 | reg q_hci_io_en;
99 |
100 | cpu cpu0(
101 | .clk_in(clk),
102 | .rst_in(rst | program_finish),
103 | .rdy_in(cpu_rdy),
104 |
105 | .mem_din(cpu_ram_din),
106 | .mem_dout(cpu_ram_dout),
107 | .mem_a(cpu_ram_a),
108 | .mem_wr(cpu_ram_wr),
109 |
110 | .io_buffer_full(hci_io_full),
111 |
112 | .dbgreg_dout(cpu_dbgreg_dout)
113 | );
114 |
115 | hci #(.SYS_CLK_FREQ(SYS_CLK_FREQ),
116 | .RAM_ADDR_WIDTH(RAM_ADDR_WIDTH),
117 | .BAUD_RATE(UART_BAUD_RATE)) hci0
118 | (
119 | .clk(clk),
120 | .rst(rst),
121 | .tx(Tx),
122 | .rx(Rx),
123 | .active(hci_active_out),
124 | .ram_din(hci_ram_din),
125 | .ram_dout(hci_ram_dout),
126 | .ram_a(hci_ram_a),
127 | .ram_wr(hci_ram_wr),
128 | .io_sel(hci_io_sel),
129 | .io_en(hci_io_en),
130 | .io_din(hci_io_din),
131 | .io_dout(hci_io_dout),
132 | .io_wr(hci_io_wr),
133 | .io_full(hci_io_full),
134 |
135 | .program_finish(program_finish),
136 |
137 | .cpu_dbgreg_din(cpu_dbgreg_dout) // demo
138 | );
139 |
140 | assign hci_io_sel = cpumc_a[2:0];
141 | assign hci_io_en = (cpumc_a[RAM_ADDR_WIDTH:RAM_ADDR_WIDTH-1] == 2'b11) ? 1'b1 : 1'b0;
142 | assign hci_io_wr = cpumc_wr;
143 | assign hci_io_din = cpumc_din;
144 |
145 | // hci is always disabled in simulation
146 | wire hci_active;
147 | assign hci_active = hci_active_out & ~SIM;
148 |
149 | // indicates debug break
150 | assign led = hci_active;
151 |
152 | // pause cpu on hci active
153 | assign cpu_rdy = (hci_active) ? 1'b0 : 1'b1;
154 |
155 | // Mux cpumc signals from cpu or hci blk, depending on debug break state (hci_active).
156 | assign cpumc_a = (hci_active) ? hci_ram_a : cpu_ram_a;
157 | assign cpumc_wr = (hci_active) ? hci_ram_wr : cpu_ram_wr;
158 | assign cpumc_din = (hci_active) ? hci_ram_dout : cpu_ram_dout;
159 |
160 | // Fixed 2020-10-06: Inconsisitency of return value with I/O state
161 | always @ (posedge clk) begin
162 | q_hci_io_en <= hci_io_en;
163 | end
164 |
165 | assign cpu_ram_din = (q_hci_io_en) ? hci_io_dout : ram_dout;
166 |
167 | assign hci_ram_din = ram_dout;
168 |
169 | endmodule
--------------------------------------------------------------------------------
/riscv/sys/io.h:
--------------------------------------------------------------------------------
1 | #ifndef CPU_JUDGE_TEST_IO_H
2 | #define CPU_JUDGE_TEST_IO_H
3 |
4 | // #define SIM // whether in simulation
5 |
6 | #define BYTE_PORT_IN 0x30000 // port for reading bytes from input
7 | #define BYTE_PORT_OUT 0x30000 // port for writing bytes to output
8 |
9 | #define CPUCLK_PORT_IN 0x30004 // port that reads clocks passed since cpu starts
10 |
11 | #define CPU_CLK_FREQ 70000000 // clock frequency of the cpu on FPGA
12 |
13 | static inline unsigned char inb()
14 | {
15 | return *((volatile unsigned char *)BYTE_PORT_IN);
16 | }
17 |
18 | static inline void outb(const unsigned char data)
19 | {
20 | *((volatile unsigned char *)BYTE_PORT_OUT) = data;
21 | }
22 |
23 | static inline unsigned long inl()
24 | {
25 | unsigned long ret = 0;
26 | unsigned char ch;
27 | int sign=0;
28 | while ((ch=inb())) if(ch!='\n'&&ch!=' '&&ch!='\t') break;
29 | do {
30 | if(ch=='-'&&!sign) sign=1;
31 | else if(ch<'0'||ch>'9') break;
32 | ret = ret * 10 + ch - '0';
33 | }while ((ch=inb()));
34 | return sign?-ret:ret;
35 | }
36 |
37 | static inline void getstr(char* data)
38 | {
39 | char c;
40 | int i=0;
41 | while((c=inb())!='\n') data[i++]=c;
42 | data[i]='\0';
43 | }
44 |
45 | static inline unsigned int ord(char data)
46 | {
47 | return (unsigned int)data;
48 | }
49 |
50 | static inline void outl(const int data)
51 | {
52 | unsigned char str[12];
53 | int tmp = data;
54 | int i=0, s=0;
55 | if (tmp<0){
56 | s=1;
57 | tmp=-tmp;
58 | }
59 | do {
60 | str[i++] = tmp % 10 + '0';
61 | }
62 | while ((tmp/=10)>0);
63 | if(s) str[i++]='-';
64 | while (i--) {
65 | outb(str[i]);
66 | }
67 | }
68 |
69 | static inline void print(const char *str)
70 | {
71 | for (; *str; str++)
72 | outb(*str);
73 | }
74 |
75 | static inline void println(const char *str)
76 | {
77 | print(str);
78 | outb('\n');
79 | }
80 |
81 | static inline void outlln(const unsigned int data)
82 | {
83 | outl(data);
84 | outb('\n');
85 | }
86 |
87 | static inline unsigned int clock()
88 | {
89 | // return *((volatile unsigned int*)CPUCLK_PORT_IN);
90 | unsigned t1 = (unsigned)(*((volatile unsigned char *)(CPUCLK_PORT_IN)));
91 | unsigned t2 = (unsigned)(*((volatile unsigned char *)(CPUCLK_PORT_IN+1)));
92 | unsigned t3 = (unsigned)(*((volatile unsigned char *)(CPUCLK_PORT_IN+2)));
93 | unsigned t4 = (unsigned)(*((volatile unsigned char *)(CPUCLK_PORT_IN+3)));
94 | return (t4<<24) | (t3<<16) | (t2<<8) | (t1);
95 | }
96 |
97 | #ifdef SIM
98 | #define sleep(x)
99 | #else
100 | static inline void sleep(const unsigned int milli_sec)
101 | {
102 | /* bug fix: clock may increase when we load from CPUCLK_PORT_IN */
103 | /* which will introduce unsigned value overflow. */
104 | /* unsigned int s = 0, d = milli_sec * (CPU_CLK_FREQ / 1000); */
105 | int s = 0, d = milli_sec * (CPU_CLK_FREQ / 1000);
106 | s = clock();
107 | while (clock() - s < d);
108 | }
109 | #endif
110 |
111 | #endif
--------------------------------------------------------------------------------
/riscv/sys/memory.ld:
--------------------------------------------------------------------------------
1 | SECTIONS
2 | {
3 | . = 0x00000000;
4 | .rom :
5 | {
6 | *(.rom)
7 | }
8 |
9 | . = 0x00001000;
10 | .text :
11 | {
12 | *(.text)
13 | }
14 |
15 | .rodata ALIGN(4) :
16 | {
17 | *(.rodata)
18 | }
19 |
20 | .data ALIGN(4) :
21 | {
22 | *(.data)
23 | }
24 |
25 | __bss_start = .;
26 |
27 | .bss ALIGN(4) :
28 | {
29 | *(.bss)
30 | }
31 |
32 | __bss_end = .;
33 | __heap_start = (__bss_end + 0xfff) & 0xfffff000;
34 | }
35 |
--------------------------------------------------------------------------------
/riscv/sys/rom.s:
--------------------------------------------------------------------------------
1 | .section .rom,"ax"
2 | .globl main
3 |
4 | li sp, 0x00020000
5 | jal main
6 | li a0, 0xff
7 | .L0:
8 | lui a3, 0x30
9 | sb a0, 4(a3)
10 | j .L0
11 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/array_test1.ans:
--------------------------------------------------------------------------------
1 | 0000
2 | 1234
--------------------------------------------------------------------------------
/riscv/testcase/fpga/array_test1.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | //input: 1 2 3 4
3 |
4 | int a[4];
5 | int main()
6 | {
7 | int b[4];
8 | int i;
9 | for (i = 0; i < 4; i++)
10 | {
11 | a[i] = 0;
12 | b[i] = inl();
13 | }
14 | for (i = 0; i < 4; i++)
15 | {
16 | outl(a[i]);
17 | }
18 | println("");
19 | int *p;
20 | p=b;
21 | for (i = 0; i < 4; i++)
22 | {
23 | outl(p[i]);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/array_test1.in:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 | 4
5 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/array_test2.ans:
--------------------------------------------------------------------------------
1 | 4
2 | 1234
3 | 0000
--------------------------------------------------------------------------------
/riscv/testcase/fpga/array_test2.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | // input: 1 2 3 4
3 | int a[4];
4 | int *pa = a;
5 | int main()
6 | {
7 | int *pb[4];
8 | int i;
9 | pb[0] = pa;
10 | pb[1] = pa;
11 | pb[2] = pa;
12 | pb[3] = pa;
13 | outlln(4);
14 | for (i = 0; i < 4; i++)
15 | pb[0][i] = inl();
16 | for (i = 0; i < 4; i++)
17 | outl(pb[1][i]);
18 | println("");
19 | for (i = 0; i < 4; i++)
20 | pb[2][i] = 0;
21 | for (i = 0; i < 4; i++)
22 | outl(pb[3][i]);
23 | }
24 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/array_test2.in:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 3
4 | 4
5 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/basicopt1.ans:
--------------------------------------------------------------------------------
1 | 99850
2 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/basicopt1.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int main()
3 | {
4 | int a[100][100];
5 | int i;
6 | int j;
7 | int sum = 0;
8 |
9 | for (i = 0;i < 100;i++)
10 | for (j = 0;j < 100;j++)
11 | a[i][j] = 0;
12 | int quotient;
13 | int remainder;
14 | for (i = 0;i < 100;i++)
15 | if (i > 20 && i < 80) {
16 | for (j = 0;j < 100;j++)
17 | if (j > 5 || i < 90) {
18 | quotient = j * 4 / 100;
19 | remainder = j * 4 % 100;
20 | a[i + quotient][remainder] = j + (100 - 1 + 1 - 1 + 1) / 2;
21 | }
22 | }
23 |
24 | for (i = 0;i < 100;i++)
25 | for (j = 0;j < 100;j++)
26 | sum = sum + a[i][j];
27 | outlln(sum);
28 | }
29 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/bulgarian.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | // Target: Simulate a Bulgarian-solitaire game.
3 | // Possible opitimization: Dead code elimination, common expression, inline function, loop unrolling, etc.
4 | // REMARKS: A funny game. If you like, you can try to prove that when n=1+2+..+i(i>0), the game will always stop
5 | // and converge to the only solution: {1,2,...i}. :)
6 |
7 | int n;
8 | int h;
9 | int now;
10 | int a[100];
11 | int A = 48271;
12 | int M = 2147483647;
13 | int Q;
14 | int R;
15 | int seed=1;
16 | int random() {
17 | int tempseed = A * (seed % Q) - R * (seed / Q);
18 | if (tempseed >= 0)
19 | seed = tempseed;
20 | else
21 | seed = tempseed + M;
22 | return seed;
23 | }
24 | void initialize(int val) {
25 | seed = val;
26 | }
27 | void swap(int x,int y) {
28 | int temp = a[x];
29 | a[x] = a[y];
30 | a[y] = temp;
31 | }
32 | int pd(int x) {
33 | for (;h <= x; ++h)
34 | if (x == h * (h + 1) / 2)
35 | return 1;
36 | return 0;
37 | }
38 | void show() {
39 | int i;
40 | for (i = 0; i < now; ++i){
41 | outl(a[i]);
42 | print(" ");
43 | }
44 | println("");
45 | }
46 | int win()
47 | {
48 | int i;
49 | int j;
50 | int b[100];
51 | int temp;
52 | if (now != h)
53 | return 0;
54 | for (j = 0; j < now; ++j)
55 | b[j] = a[j];
56 | for (i = 0;i < now - 1; ++i)
57 | for (j = i + 1;j < now; ++j)
58 | if (b[i] > b[j]) {
59 | temp = b[i];
60 | b[i] = b[j];
61 | b[j] = temp;
62 | }
63 | for (i = 0; i < now; ++i)
64 | if (b[i] != i + 1)
65 | return 0;
66 | return 1;
67 | }
68 | void merge()
69 | {
70 | int i;
71 | for (i = 0;i < now; ++i)
72 | if (a[i] == 0) {
73 | int j;
74 | for (j = i+1; j < now; ++j)
75 | if (a[j] != 0) {
76 | swap(i,j);
77 | break;
78 | }
79 | }
80 | for (i=0;i n)
115 | a[i] = random() % 10 + 1;
116 | temp = temp + a[i];
117 | }
118 | a[now - 1] = n - temp;
119 | show();
120 | merge();
121 | while (!win()) {
122 | print("step ");
123 | outl(++count);
124 | println(":");
125 | move();
126 | merge();
127 | show();
128 | sleep(10); // to prevent UART buffer from overflowing
129 | }
130 | print("Total: ");
131 | outl(count);
132 | println(" step(s)");
133 | return 0;
134 | }
135 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/expr.ans:
--------------------------------------------------------------------------------
1 | -66060719 -323398799 -743275679
2 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/expr.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | //This file use massive recursive expression to test: Common Expression substitution.
3 | //For my optimized version: All: 1397 Load: 86 Store: 55 Jumped: 23
4 | //For my unoptimized version: All: 24519 Load: 12183 Store: 55 Jumped: 23
5 | //A better result is welcomed. ------ From JinTianxing.
6 |
7 | int A = 1;
8 | int B = 1;
9 | int C = 1;
10 |
11 | int main(){
12 | while (C < (1 << 29) && C > -(1 << 29)){
13 | A = ((((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))) - (((((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B)))) + (((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))));
14 | B = ((((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))) - (((((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B)))) + (((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))));
15 | C = ((((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))) - (((((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B)))) + (((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))));
16 | }
17 | outl(A);
18 | print(" ");
19 | outl(B);
20 | print(" ");
21 | outlln(C);
22 | return 0;
23 | }
24 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/gcd.ans:
--------------------------------------------------------------------------------
1 | 1
2 | 1029
3 | 171
4 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/gcd.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int gcd(int x, int y) {
3 | if (x%y == 0) return y;
4 | else return gcd(y, x%y);
5 | }
6 |
7 | int main() {
8 | outlln(gcd(10,1));
9 | outlln(gcd(34986,3087));
10 | outlln(gcd(2907,1539));
11 |
12 | return 0;
13 | }
--------------------------------------------------------------------------------
/riscv/testcase/fpga/hanoi.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int cd(int d, char* a, char* b, char* c, int sum) {
3 | sleep(5); // to prevent UART buffer from overflowing
4 | if (d == 1) {
5 | print("move ");
6 | print(a);
7 | print(" --> ");
8 | println(c);
9 | sum++;
10 | } else {
11 | sum = cd(d - 1, a, c, b, sum);
12 | print("move ");
13 | print(a);
14 | print(" --> ");
15 | println(c);
16 | sum = cd(d - 1, b, a, c, sum);
17 | sum++;
18 | }
19 | return sum;
20 | }
21 |
22 | int main() {
23 | char a[5] = "A";
24 | char b[5] = "B";
25 | char c[5] = "C";
26 | int d = inl();
27 | int sum = cd(d, a, b, c, 0);
28 | outlln(sum);
29 | return 0;
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/hanoi.in:
--------------------------------------------------------------------------------
1 | 10
2 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/heart.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | #define putchar outb
3 | float f(float x, float y, float z) {
4 | float a = x * x + 9.0f / 4.0f * y * y + z * z - 1;
5 | return a * a * a - x * x * z * z * z - 9.0f / 80.0f * y * y * z * z * z;
6 | }
7 |
8 | float h(float x, float z) {
9 | for (float y = 1.0f; y >= 0.0f; y -= 0.001f)
10 | if (f(x, y, z) <= 0.0f)
11 | return y;
12 | return 0.0f;
13 | }
14 |
15 | float mysqrt(float x) {
16 | if (x == 0) return 0;
17 | int i;
18 | double v = x / 2;
19 | for (i = 0; i < 50; ++i)
20 | v = (v + x / v)/2;
21 |
22 | return v;
23 | }
24 |
25 | int main() {
26 | for (float z = 1.5f; z > -1.5f; z -= 0.05f) {
27 | for (float x = -1.5f; x < 1.5f; x += 0.025f) {
28 | float v = f(x, 0.0f, z);
29 | if (v <= 0.0f) {
30 | float y0 = h(x, z);
31 | float ny = 0.01f;
32 | float nx = h(x + ny, z) - y0;
33 | float nz = h(x, z + ny) - y0;
34 | float nd = 1.0f / mysqrt(nx * nx + ny * ny + nz * nz);
35 | float d = (nx + ny - nz) * nd * 0.5f + 0.5f;
36 | int index = (int)(d * 5.0f);
37 | putchar(".:-=+*#%@"[index]);
38 | }
39 | else
40 | putchar('_');
41 | }
42 | putchar('\n');
43 | }
44 | }
--------------------------------------------------------------------------------
/riscv/testcase/fpga/looper.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | // san check: if your predictor && icache work, it should be 1.5s @ 100Mhz
3 | unsigned n, sum;
4 | void work() {
5 | for (int i = 1; i <= 5 * n; i++) {
6 | sum += i * 998244353;
7 | }
8 | }
9 | int main() {
10 | n = 50;
11 | work();
12 | n = 10000000;
13 | work();
14 | outlln(sum);
15 | }
--------------------------------------------------------------------------------
/riscv/testcase/fpga/lvalue2.ans:
--------------------------------------------------------------------------------
1 | 2
2 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/lvalue2.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int a[4];
3 | int main()
4 | {
5 | int b[4];
6 | b[2]=2;
7 | int *p;
8 | p=b;
9 | outlln(p[2]);
10 | }
11 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/magic.ans:
--------------------------------------------------------------------------------
1 | 2 7 6
2 | 9 5 1
3 | 4 3 8
4 |
5 | 2 9 4
6 | 7 5 3
7 | 6 1 8
8 |
9 | 4 3 8
10 | 9 5 1
11 | 2 7 6
12 |
13 | 4 9 2
14 | 3 5 7
15 | 8 1 6
16 |
17 | 6 1 8
18 | 7 5 3
19 | 2 9 4
20 |
21 | 6 7 2
22 | 1 5 9
23 | 8 3 4
24 |
25 | 8 1 6
26 | 3 5 7
27 | 4 9 2
28 |
29 | 8 3 4
30 | 1 5 9
31 | 6 7 2
32 |
33 | 8
34 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/magic.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int make[3][3];
3 | int color[10];
4 | int count[1];
5 | int i;
6 | int j;
7 |
8 | void origin(int N)
9 | {
10 | for (i = 0; i < N; i ++ ) {
11 | for (j = 0; j < N; j ++ )
12 | make[i][j] = 0;
13 | }
14 | }
15 |
16 | void search(int x, int y, int z)
17 | {
18 | int s;
19 | int i;
20 | int j;
21 | if ((y > 0 || y < 0) || x == 0 || make[x-1][0] + make[x-1][1] + make[x-1][2] == 15)
22 | {
23 | if (x == 2 && y == 2) {
24 | make[2][2] = 45 - z;
25 | s = make[0][0] + make[0][1] + make[0][2];
26 | if (make[1][0] + make[1][1] + make[1][2] == s &&
27 | make[2][0] + make[2][1] + make[2][2] == s &&
28 | make[0][0] + make[1][0] + make[2][0] == s &&
29 | make[0][1] + make[1][1] + make[2][1] == s &&
30 | make[0][2] + make[1][2] + make[2][2] == s &&
31 | make[0][0] + make[1][1] + make[2][2] == s &&
32 | make[2][0] + make[1][1] + make[0][2] == s)
33 | {
34 | count[0] = count[0] + 1;
35 | for (i = 0;i <= 2;i ++)
36 | {
37 | for (j = 0;j <= 2;j ++)
38 | {
39 | outl(make[i][j]);
40 | print(" ");
41 | }
42 | print("\n");
43 | }
44 | print("\n");
45 | }
46 | }
47 | else {
48 | if (y == 2) {
49 | make[x][y] = 15 - make[x][0] - make[x][1];
50 | if (make[x][y] > 0 && make[x][y] < 10 && color[make[x][y]] == 0) {
51 | color[make[x][y]] = 1;
52 | if (y == 2)
53 | search(x + 1, 0, z+make[x][y]);
54 | else
55 | search(x, y+1, z+make[x][y]);
56 | color[make[x][y]] = 0;
57 | }
58 | }
59 | else {
60 | for (i = 1;i <= 9;i ++) {
61 | if (color[i] == 0) {
62 | color[i] = 1;
63 | make[x][y] = i;
64 | if (y == 2)
65 | search(x + 1, 0, z+i);
66 | else
67 | search(x, y+1, z+i);
68 | make[x][y] = 0;
69 | color[i] = 0;
70 | }
71 | }
72 | }
73 | }
74 | }
75 | }
76 | int main()
77 | {
78 | origin(3);
79 | search(0, 0, 0);
80 | outlln(count[0]);
81 | return 0;
82 | }
83 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/manyarguments.ans:
--------------------------------------------------------------------------------
1 | 120
2 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/manyarguments.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int a(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15)
3 | {
4 | return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15;
5 | }
6 |
7 | int main()
8 | {
9 | outlln(a(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15));
10 | return 0;
11 | }
12 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/multiarray.ans:
--------------------------------------------------------------------------------
1 | 888
2 | 0
3 | 1
4 | 2
5 | 3
6 | 4
7 | 5
8 | 6
9 | 7
10 | 8
11 | 9
12 | 10
13 | 11
14 | 12
15 | 13
16 | 14
17 | 15
18 | 16
19 | 17
20 | 18
21 | 19
22 | 20
23 | 21
24 | 22
25 | 23
26 | 24
27 | 25
28 | 26
29 | 27
30 | 28
31 | 29
32 | 30
33 | 31
34 | 32
35 | 33
36 | 34
37 | 35
38 | 36
39 | 37
40 | 38
41 | 39
42 | 0
43 | -10
44 | -1
45 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/multiarray.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int a[4][11];
3 | int i;
4 | int j;
5 |
6 | struct rec {
7 | int num;
8 | int c;
9 | }b[5];
10 |
11 | void printNum(int num) {
12 | outlln(num);
13 | }
14 | int main() {
15 |
16 |
17 | for (i = 0; i < 4; i ++) {
18 | for (j = 0; j < 10; j ++)
19 | a[i][j] = 888;
20 | }
21 | for (i = 0; i < 5; i ++) {
22 | b[i].num = -1;
23 | }
24 |
25 | printNum(a[3][9]);
26 | for (i = 0; i <= 3; i ++)
27 | for (j = 0; j <= 9; j ++)
28 | a[i][j] = i * 10 + j;
29 |
30 | for (i = 0; i <= 3; i ++)
31 | for (j = 0; j <= 9; j ++)
32 | printNum(a[i][j]);
33 | a[2][10]=0;
34 | printNum(a[2][10]);
35 | b[0].num = -2;
36 | b[a[2][10]].num = -10;
37 | printNum(b[0].num);
38 | printNum(b[1].num);
39 | return 0;
40 | }
41 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/pi.ans:
--------------------------------------------------------------------------------
1 | 3141592653589793238462643383279528841971693993751058209749445923078164062862089986280348253421170679821480865132823664709384469555822317253594081284811174502841270193852115559644622948954930381964428810975665933446128475648233786783165271201991456485669234634861045432664821339360726024914127372458706606315588174881520920962829254917153643678925903611330530548820466521384146951941511609433057273657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566438602139494639522473719070217986943702770539217176293176752384674818467669451320005681271452635608277857713427577896091736371787214684409012249534301465495853710579227968925892354201995611212902196864344181598136297747713099605187072113499999983729780499510597317328160963185
2 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/pi.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int f[2801];
3 | int main() {
4 | int a = 10000;
5 | int b = 0;
6 | int c = 2800;
7 | int d = 0;
8 | int e = 0;
9 | int g = 0;
10 |
11 | for (;b-c!=0;)
12 | f[b++] = a/5;
13 | for (;; e = d%a){
14 | d = 0;
15 | g = c*2;
16 | if (g==0) break;
17 |
18 | for (b=c;;d=d*b){
19 | d=d+f[b]*a;
20 | f[b] = d%--g;
21 | d=d/g--;
22 | if (--b==0) break;
23 | }
24 |
25 | c = c-14;
26 | outl(e+d/a); // should be printf("%04b"), but let it be
27 | }
28 |
29 | print("\n");
30 | return 0;
31 | }
32 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/qsort.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | // Target: qsort
3 | // Possible optimization: Dead code elimination, common expression, strength reduction
4 | // REMARKS: nothing.
5 | //
6 | //
7 |
8 | //int a[10100];
9 | int a[10100];
10 | int n = 10000;
11 |
12 | int qsrt(int l, int r) {
13 | int i = l;
14 | int j = r;
15 | int x = a[(l + r) / 2];
16 | while (i <= j) {
17 | while (a[i] < x) i++;
18 | while (a[j] > x) j--;
19 | if (i <= j) {
20 | int temp = a[i];
21 | a[i] = a[j];
22 | a[j] = temp;
23 | i++;
24 | j--;
25 | }
26 | }
27 | if (l < j) qsrt(l, j);
28 | if (i < r) qsrt(i, r);
29 | return 0;
30 | }
31 |
32 | int main() {
33 | int i;
34 | for (i = 1; i <= n; i++)
35 | a[i] = n + 1 - i;
36 | qsrt(1, n);
37 | for (i = 1; i <= n; i++) {
38 | outl(a[i]);
39 | print(" ");
40 | sleep(1); // to prevent UART buffer from overflowing
41 | }
42 | print("\n");
43 | return 0;
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/queens.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int N = 8;
3 | int row[8];
4 | int col[8];
5 | int d[2][16];
6 |
7 | void printBoard() {
8 | int i;
9 | int j;
10 | for (i = 0; i < N; i++) {
11 | for (j = 0; j < N; j++) {
12 | if (col[i] == j)
13 | print(" O");
14 | else
15 | print(" .");
16 | }
17 | println("");
18 | }
19 | println("");
20 | sleep(50); // to prevent UART buffer from overflowing
21 | }
22 |
23 | void search(int c) {
24 | if (c == N) {
25 | printBoard();
26 | }
27 | else {
28 | int r;
29 | for (r = 0; r < N; r++) {
30 | if (row[r] == 0 && d[0][r+c] == 0 && d[1][r+N-1-c] == 0) {
31 | row[r] = d[0][r+c] = d[1][r+N-1-c] = 1;
32 | col[c] = r;
33 | search(c+1);
34 | row[r] = d[0][r+c] = d[1][r+N-1-c] = 0;
35 | }
36 | }
37 | }
38 | }
39 |
40 | int main() {
41 | search(0);
42 | return 0;
43 | }
44 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/statement_test.ans:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 2
4 | 4
5 | 2
6 | 6
7 | 4
8 | 6
9 | 4
10 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/statement_test.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | //考察点:section 8 语句,包括if,while,for,break,continue,return等
3 | //算法:线性筛法求欧拉函数
4 | //样例输入:10
5 | //样例输出:
6 | //1
7 | //2
8 | //2
9 | //4
10 | //2
11 | //6
12 | //4
13 | //6
14 | //4
15 |
16 | int N;
17 | int M = 0;
18 | int check[20];
19 |
20 | int main() {
21 | N = inl();
22 | int i = 0;
23 | while ( i <= N ) check[i++] = 1;
24 | int phi[15];
25 | int P[15];
26 | phi[1] = 1;
27 | for (i = 2; ; ++i ) {
28 | if ( i > N ) break;
29 | if ( check[i] ) {
30 | P[++M] = i;
31 | phi[i] = i - 1;
32 | }
33 | int k = i;
34 | int i;
35 | for (i = 1; i <= M && (k * P[i] <= N); i++) {
36 | int tmp = k * P[i];
37 | if ( tmp > N ) continue;
38 | check[tmp] = 0;
39 | if ( k % P[i] == 0) {
40 | phi[tmp] = phi[k] * P[i];
41 | break;
42 | }
43 | else {
44 | phi[k * P[i]] = phi[k] * (P[i] - 1);
45 | }
46 | }
47 | outlln(phi[k]);
48 | }
49 | return 0;
50 | }
51 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/statement_test.in:
--------------------------------------------------------------------------------
1 | 10
--------------------------------------------------------------------------------
/riscv/testcase/fpga/superloop.ans:
--------------------------------------------------------------------------------
1 | 720
2 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/superloop.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | //Target: use loops to calculate calculator of 6!
3 | //@author yixi
4 |
5 | int N;
6 | int h = 99;
7 | int i = 100;
8 | int j = 101;
9 | int k = 102;
10 | int total = 0;
11 |
12 | int main() {
13 | int a;
14 | int b;
15 | int c;
16 | int d;
17 | int e;
18 | int f;
19 | N=inl();
20 | for ( a=1; a<=N; a++ )
21 | for ( b=1; b<=N; b++ )
22 | for ( c=1; c<=N; c++ )
23 | for ( d=1; d<=N; d++ )
24 | for ( e=1; e<=N; e++ )
25 | for ( f=1; f<=N; f++ )
26 | if (a!=b && a!=c && a!=d && a!=e && a!=f && a!=h && a!=i && a!=j && a!=k
27 | && b!=c && b!=d && b!=e && b!=f && b!=h && b!=i && b!=j && b!=k
28 | && c!=d && c!=e && c!=f && c!=h && c!=i && c!=j && c!=k
29 | && d!=e && d!=f && d!=h && d!=i && d!=j && d!=k
30 | && e!=f && e!=h && e!=i && e!=j && e!=k
31 | && f!=h && f!=i && f!=j && f!=k && i!=j && h!=k)
32 | {
33 | total++;
34 | }
35 |
36 | outlln(total);
37 | return 0;
38 | }
39 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/superloop.in:
--------------------------------------------------------------------------------
1 | 6
2 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/tak.ans:
--------------------------------------------------------------------------------
1 | 13
2 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/tak.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int tak(int x, int y, int z) {
3 | if ( y < x ) return 1 + tak( tak(x-1, y, z), tak(y-1, z, x), tak(z-1, x, y) );
4 | else return z;
5 | }
6 |
7 | int main(){
8 | int a;
9 | int b;
10 | int c;
11 | a=inl();
12 | b=inl();
13 | c=inl();
14 | outlln(tak(a,b,c));
15 | return 0;
16 | }
17 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/tak.in:
--------------------------------------------------------------------------------
1 | 18
2 | 12
3 | 6
4 |
--------------------------------------------------------------------------------
/riscv/testcase/fpga/testsleep.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int main()
3 | {
4 | int a = clock();
5 | sleep(10000); // sleep for 10s
6 | int b = clock();
7 | outlln(b-a);
8 | outlln((b-a)/CPU_CLK_FREQ); // should be 10
9 | return 0; // check actual running time
10 | }
--------------------------------------------------------------------------------
/riscv/testcase/fpga/uartboom.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 |
3 | int main(){
4 | int i = 0;
5 | for ( ; i < 0x1ff; i++) {
6 | outb('a');
7 | outb('b');
8 | outb('c');
9 | outb('d');
10 | outb('e');
11 | outb('f');
12 | outb('g');
13 | outb('h');
14 | outb('i');
15 | outb('j');
16 | outb('k');
17 | outb('l');
18 | outb('m');
19 | outb('n');
20 | outb('o');
21 | outb('p');
22 | }
23 | return 0;
24 | }
25 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/000_array_test1.ans:
--------------------------------------------------------------------------------
1 | 0000
2 | 1234
--------------------------------------------------------------------------------
/riscv/testcase/sim/000_array_test1.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | //input: 1 2 3 4
3 |
4 | int a[4];
5 | int main()
6 | {
7 | int b[4];
8 | int i;
9 | for (i = 0; i < 4; i++)
10 | {
11 | a[i] = 0;
12 | b[i] = i + 1;
13 | }
14 | for (i = 0; i < 4; i++)
15 | {
16 | outl(a[i]);
17 | }
18 | println("");
19 | int *p;
20 | p=b;
21 | for (i = 0; i < 4; i++)
22 | {
23 | outl(p[i]);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/001_array_test2.ans:
--------------------------------------------------------------------------------
1 | 4
2 | 1234
3 | 0000
--------------------------------------------------------------------------------
/riscv/testcase/sim/001_array_test2.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | // input: 1 2 3 4
3 | int a[4];
4 | int *pa = a;
5 | int main()
6 | {
7 | int *pb[4];
8 | int i;
9 | pb[0] = pa;
10 | pb[1] = pa;
11 | pb[2] = pa;
12 | pb[3] = pa;
13 | outlln(4);
14 | for (i = 0; i < 4; i++)
15 | pb[0][i] = i + 1;
16 | for (i = 0; i < 4; i++)
17 | outl(pb[1][i]);
18 | println("");
19 | for (i = 0; i < 4; i++)
20 | pb[2][i] = 0;
21 | for (i = 0; i < 4; i++)
22 | outl(pb[3][i]);
23 | }
24 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/002_expr.ans:
--------------------------------------------------------------------------------
1 | -66060719 -323398799 -743275679
2 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/002_expr.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | //This file use massive recursive expression to test: Common Expression substitution.
3 | //For my optimized version: All: 1397 Load: 86 Store: 55 Jumped: 23
4 | //For my unoptimized version: All: 24519 Load: 12183 Store: 55 Jumped: 23
5 | //A better result is welcomed. ------ From JinTianxing.
6 |
7 | int A = 1;
8 | int B = 1;
9 | int C = 1;
10 |
11 | int main(){
12 | while (C < (1 << 29) && C > -(1 << 29)){
13 | A = ((((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))) - (((((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B)))) + (((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))));
14 | B = ((((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))) - (((((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B)))) + (((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))));
15 | C = ((((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))) - (((((((A + B) + (C - A + B)) - ((A + B) + (C - A + B))) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B)))) + (((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))) + ((((C - A + B) - (A + B)) + (C - A + B)) - (((A + B) + (C - A + B)) - (A + B))))) + ((((((C - A + B) - (A + B)) + ((C - A + B) - (A + B))) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))) - (((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B))) - ((((A + B) + (C - A + B)) - (A + B)) + (((C - A + B) - (A + B)) + (C - A + B)))))));
16 | }
17 | outl(A);
18 | print(" ");
19 | outl(B);
20 | print(" ");
21 | outlln(C);
22 | return 0;
23 | }
24 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/003_looper.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | // san check: if your predictor && icache work, it should be 1.5s @ 100Mhz
3 | unsigned n, sum;
4 | void work() {
5 | for (int i = 1; i <= 5 * n; i++) {
6 | sum += i * 998244353;
7 | }
8 | }
9 | int main() {
10 | n = 50;
11 | work();
12 | n = 10000000;
13 | work();
14 | outlln(sum);
15 | }
--------------------------------------------------------------------------------
/riscv/testcase/sim/004_gcd.ans:
--------------------------------------------------------------------------------
1 | 1
2 | 1029
3 | 171
4 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/004_gcd.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int gcd(int x, int y) {
3 | if (x%y == 0) return y;
4 | else return gcd(y, x%y);
5 | }
6 |
7 | int main() {
8 | outlln(gcd(10,1));
9 | outlln(gcd(34986,3087));
10 | outlln(gcd(2907,1539));
11 |
12 | return 0;
13 | }
--------------------------------------------------------------------------------
/riscv/testcase/sim/005_lvalue2.ans:
--------------------------------------------------------------------------------
1 | 2
2 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/005_lvalue2.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int a[4];
3 | int main()
4 | {
5 | int b[4];
6 | b[2]=2;
7 | int *p;
8 | p=b;
9 | outlln(p[2]);
10 | }
11 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/006_multiarray.ans:
--------------------------------------------------------------------------------
1 | 888
2 | 0
3 | 1
4 | 2
5 | 3
6 | 4
7 | 5
8 | 6
9 | 7
10 | 8
11 | 9
12 | 10
13 | 11
14 | 12
15 | 13
16 | 14
17 | 15
18 | 16
19 | 17
20 | 18
21 | 19
22 | 20
23 | 21
24 | 22
25 | 23
26 | 24
27 | 25
28 | 26
29 | 27
30 | 28
31 | 29
32 | 30
33 | 31
34 | 32
35 | 33
36 | 34
37 | 35
38 | 36
39 | 37
40 | 38
41 | 39
42 | 0
43 | -10
44 | -1
45 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/006_multiarray.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int a[4][11];
3 | int i;
4 | int j;
5 |
6 | struct rec {
7 | int num;
8 | int c;
9 | }b[5];
10 |
11 | void printNum(int num) {
12 | outlln(num);
13 | }
14 | int main() {
15 |
16 |
17 | for (i = 0; i < 4; i ++) {
18 | for (j = 0; j < 10; j ++)
19 | a[i][j] = 888;
20 | }
21 | for (i = 0; i < 5; i ++) {
22 | b[i].num = -1;
23 | }
24 |
25 | printNum(a[3][9]);
26 | for (i = 0; i <= 3; i ++)
27 | for (j = 0; j <= 9; j ++)
28 | a[i][j] = i * 10 + j;
29 |
30 | for (i = 0; i <= 3; i ++)
31 | for (j = 0; j <= 9; j ++)
32 | printNum(a[i][j]);
33 | a[2][10]=0;
34 | printNum(a[2][10]);
35 | b[0].num = -2;
36 | b[a[2][10]].num = -10;
37 | printNum(b[0].num);
38 | printNum(b[1].num);
39 | return 0;
40 | }
41 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/007_hanoi.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int cd(int d, char* a, char* b, char* c, int sum) {
3 | sleep(5); // to prevent UART buffer from overflowing
4 | if (d == 1) {
5 | print("move ");
6 | print(a);
7 | print(" --> ");
8 | println(c);
9 | sum++;
10 | } else {
11 | sum = cd(d - 1, a, c, b, sum);
12 | print("move ");
13 | print(a);
14 | print(" --> ");
15 | println(c);
16 | sum = cd(d - 1, b, a, c, sum);
17 | sum++;
18 | }
19 | return sum;
20 | }
21 |
22 | int main() {
23 | char a[5] = "A";
24 | char b[5] = "B";
25 | char c[5] = "C";
26 | int d = 10;
27 | int sum = cd(d, a, b, c, 0);
28 | outlln(sum);
29 | return 0;
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/100_magic.ans:
--------------------------------------------------------------------------------
1 | 2 7 6
2 | 9 5 1
3 | 4 3 8
4 |
5 | 2 9 4
6 | 7 5 3
7 | 6 1 8
8 |
9 | 4 3 8
10 | 9 5 1
11 | 2 7 6
12 |
13 | 4 9 2
14 | 3 5 7
15 | 8 1 6
16 |
17 | 6 1 8
18 | 7 5 3
19 | 2 9 4
20 |
21 | 6 7 2
22 | 1 5 9
23 | 8 3 4
24 |
25 | 8 1 6
26 | 3 5 7
27 | 4 9 2
28 |
29 | 8 3 4
30 | 1 5 9
31 | 6 7 2
32 |
33 | 8
34 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/100_magic.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int make[3][3];
3 | int color[10];
4 | int count[1];
5 | int i;
6 | int j;
7 |
8 | void origin(int N)
9 | {
10 | for (i = 0; i < N; i ++ ) {
11 | for (j = 0; j < N; j ++ )
12 | make[i][j] = 0;
13 | }
14 | }
15 |
16 | void search(int x, int y, int z)
17 | {
18 | int s;
19 | int i;
20 | int j;
21 | if ((y > 0 || y < 0) || x == 0 || make[x-1][0] + make[x-1][1] + make[x-1][2] == 15)
22 | {
23 | if (x == 2 && y == 2) {
24 | make[2][2] = 45 - z;
25 | s = make[0][0] + make[0][1] + make[0][2];
26 | if (make[1][0] + make[1][1] + make[1][2] == s &&
27 | make[2][0] + make[2][1] + make[2][2] == s &&
28 | make[0][0] + make[1][0] + make[2][0] == s &&
29 | make[0][1] + make[1][1] + make[2][1] == s &&
30 | make[0][2] + make[1][2] + make[2][2] == s &&
31 | make[0][0] + make[1][1] + make[2][2] == s &&
32 | make[2][0] + make[1][1] + make[0][2] == s)
33 | {
34 | count[0] = count[0] + 1;
35 | for (i = 0;i <= 2;i ++)
36 | {
37 | for (j = 0;j <= 2;j ++)
38 | {
39 | outl(make[i][j]);
40 | print(" ");
41 | }
42 | print("\n");
43 | }
44 | print("\n");
45 | }
46 | }
47 | else {
48 | if (y == 2) {
49 | make[x][y] = 15 - make[x][0] - make[x][1];
50 | if (make[x][y] > 0 && make[x][y] < 10 && color[make[x][y]] == 0) {
51 | color[make[x][y]] = 1;
52 | if (y == 2)
53 | search(x + 1, 0, z+make[x][y]);
54 | else
55 | search(x, y+1, z+make[x][y]);
56 | color[make[x][y]] = 0;
57 | }
58 | }
59 | else {
60 | for (i = 1;i <= 9;i ++) {
61 | if (color[i] == 0) {
62 | color[i] = 1;
63 | make[x][y] = i;
64 | if (y == 2)
65 | search(x + 1, 0, z+i);
66 | else
67 | search(x, y+1, z+i);
68 | make[x][y] = 0;
69 | color[i] = 0;
70 | }
71 | }
72 | }
73 | }
74 | }
75 | }
76 | int main()
77 | {
78 | origin(3);
79 | search(0, 0, 0);
80 | outlln(count[0]);
81 | return 0;
82 | }
83 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/101_queens.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int N = 8;
3 | int row[8];
4 | int col[8];
5 | int d[2][16];
6 |
7 | void printBoard() {
8 | int i;
9 | int j;
10 | for (i = 0; i < N; i++) {
11 | for (j = 0; j < N; j++) {
12 | if (col[i] == j)
13 | print(" O");
14 | else
15 | print(" .");
16 | }
17 | println("");
18 | }
19 | println("");
20 | sleep(50); // to prevent UART buffer from overflowing
21 | }
22 |
23 | void search(int c) {
24 | if (c == N) {
25 | printBoard();
26 | }
27 | else {
28 | int r;
29 | for (r = 0; r < N; r++) {
30 | if (row[r] == 0 && d[0][r+c] == 0 && d[1][r+N-1-c] == 0) {
31 | row[r] = d[0][r+c] = d[1][r+N-1-c] = 1;
32 | col[c] = r;
33 | search(c+1);
34 | row[r] = d[0][r+c] = d[1][r+N-1-c] = 0;
35 | }
36 | }
37 | }
38 | }
39 |
40 | int main() {
41 | search(0);
42 | return 0;
43 | }
44 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/102_qsort.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | // Target: qsort
3 | // Possible optimization: Dead code elimination, common expression, strength reduction
4 | // REMARKS: nothing.
5 | //
6 | //
7 |
8 | //int a[10100];
9 | int a[10100];
10 | int n = 10000;
11 |
12 | int qsrt(int l, int r) {
13 | int i = l;
14 | int j = r;
15 | int x = a[(l + r) / 2];
16 | while (i <= j) {
17 | while (a[i] < x) i++;
18 | while (a[j] > x) j--;
19 | if (i <= j) {
20 | int temp = a[i];
21 | a[i] = a[j];
22 | a[j] = temp;
23 | i++;
24 | j--;
25 | }
26 | }
27 | if (l < j) qsrt(l, j);
28 | if (i < r) qsrt(i, r);
29 | return 0;
30 | }
31 |
32 | int main() {
33 | int i;
34 | for (i = 1; i <= n; i++)
35 | a[i] = n + 1 - i;
36 | qsrt(1, n);
37 | for (i = 1; i <= n; i++) {
38 | outl(a[i]);
39 | print(" ");
40 | sleep(1); // to prevent UART buffer from overflowing
41 | }
42 | print("\n");
43 | return 0;
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/103_bulgarian.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | // Target: Simulate a Bulgarian-solitaire game.
3 | // Possible opitimization: Dead code elimination, common expression, inline function, loop unrolling, etc.
4 | // REMARKS: A funny game. If you like, you can try to prove that when n=1+2+..+i(i>0), the game will always stop
5 | // and converge to the only solution: {1,2,...i}. :)
6 |
7 | int n;
8 | int h;
9 | int now;
10 | int a[100];
11 | int A = 48271;
12 | int M = 2147483647;
13 | int Q;
14 | int R;
15 | int seed=1;
16 | int random() {
17 | int tempseed = A * (seed % Q) - R * (seed / Q);
18 | if (tempseed >= 0)
19 | seed = tempseed;
20 | else
21 | seed = tempseed + M;
22 | return seed;
23 | }
24 | void initialize(int val) {
25 | seed = val;
26 | }
27 | void swap(int x,int y) {
28 | int temp = a[x];
29 | a[x] = a[y];
30 | a[y] = temp;
31 | }
32 | int pd(int x) {
33 | for (;h <= x; ++h)
34 | if (x == h * (h + 1) / 2)
35 | return 1;
36 | return 0;
37 | }
38 | void show() {
39 | int i;
40 | for (i = 0; i < now; ++i){
41 | outl(a[i]);
42 | print(" ");
43 | }
44 | println("");
45 | }
46 | int win()
47 | {
48 | int i;
49 | int j;
50 | int b[100];
51 | int temp;
52 | if (now != h)
53 | return 0;
54 | for (j = 0; j < now; ++j)
55 | b[j] = a[j];
56 | for (i = 0;i < now - 1; ++i)
57 | for (j = i + 1;j < now; ++j)
58 | if (b[i] > b[j]) {
59 | temp = b[i];
60 | b[i] = b[j];
61 | b[j] = temp;
62 | }
63 | for (i = 0; i < now; ++i)
64 | if (b[i] != i + 1)
65 | return 0;
66 | return 1;
67 | }
68 | void merge()
69 | {
70 | int i;
71 | for (i = 0;i < now; ++i)
72 | if (a[i] == 0) {
73 | int j;
74 | for (j = i+1; j < now; ++j)
75 | if (a[j] != 0) {
76 | swap(i,j);
77 | break;
78 | }
79 | }
80 | for (i=0;i n)
115 | a[i] = random() % 10 + 1;
116 | temp = temp + a[i];
117 | }
118 | a[now - 1] = n - temp;
119 | show();
120 | merge();
121 | while (!win()) {
122 | print("step ");
123 | outl(++count);
124 | println(":");
125 | move();
126 | merge();
127 | show();
128 | sleep(10); // to prevent UART buffer from overflowing
129 | }
130 | print("Total: ");
131 | outl(count);
132 | println(" step(s)");
133 | return 0;
134 | }
135 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/basicopt1.ans:
--------------------------------------------------------------------------------
1 | 99850
2 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/basicopt1.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int main()
3 | {
4 | int a[100][100];
5 | int i;
6 | int j;
7 | int sum = 0;
8 |
9 | for (i = 0;i < 100;i++)
10 | for (j = 0;j < 100;j++)
11 | a[i][j] = 0;
12 | int quotient;
13 | int remainder;
14 | for (i = 0;i < 100;i++)
15 | if (i > 20 && i < 80) {
16 | for (j = 0;j < 100;j++)
17 | if (j > 5 || i < 90) {
18 | quotient = j * 4 / 100;
19 | remainder = j * 4 % 100;
20 | a[i + quotient][remainder] = j + (100 - 1 + 1 - 1 + 1) / 2;
21 | }
22 | }
23 |
24 | for (i = 0;i < 100;i++)
25 | for (j = 0;j < 100;j++)
26 | sum = sum + a[i][j];
27 | outlln(sum);
28 | }
29 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/manyarguments.ans:
--------------------------------------------------------------------------------
1 | 120
2 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/manyarguments.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | int a(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15)
3 | {
4 | return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15;
5 | }
6 |
7 | int main()
8 | {
9 | outlln(a(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15));
10 | return 0;
11 | }
12 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/statement_test.ans:
--------------------------------------------------------------------------------
1 | 1
2 | 2
3 | 2
4 | 4
5 | 2
6 | 6
7 | 4
8 | 6
9 | 4
10 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/statement_test.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | //考察点:section 8 语句,包括if,while,for,break,continue,return等
3 | //算法:线性筛法求欧拉函数
4 | //样例输入:10
5 | //样例输出:
6 | //1
7 | //2
8 | //2
9 | //4
10 | //2
11 | //6
12 | //4
13 | //6
14 | //4
15 |
16 | int N;
17 | int M = 0;
18 | int check[20];
19 |
20 | int main() {
21 | N = 10;
22 | int i = 0;
23 | while ( i <= N ) check[i++] = 1;
24 | int phi[15];
25 | int P[15];
26 | phi[1] = 1;
27 | for (i = 2; ; ++i ) {
28 | if ( i > N ) break;
29 | if ( check[i] ) {
30 | P[++M] = i;
31 | phi[i] = i - 1;
32 | }
33 | int k = i;
34 | int i;
35 | for (i = 1; i <= M && (k * P[i] <= N); i++) {
36 | int tmp = k * P[i];
37 | if ( tmp > N ) continue;
38 | check[tmp] = 0;
39 | if ( k % P[i] == 0) {
40 | phi[tmp] = phi[k] * P[i];
41 | break;
42 | }
43 | else {
44 | phi[k * P[i]] = phi[k] * (P[i] - 1);
45 | }
46 | }
47 | outlln(phi[k]);
48 | }
49 | return 0;
50 | }
51 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/superloop.ans:
--------------------------------------------------------------------------------
1 | 720
2 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/superloop.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 | //Target: use loops to calculate calculator of 6!
3 | //@author yixi
4 |
5 | int N;
6 | int h = 99;
7 | int i = 100;
8 | int j = 101;
9 | int k = 102;
10 | int total = 0;
11 |
12 | int main() {
13 | int a;
14 | int b;
15 | int c;
16 | int d;
17 | int e;
18 | int f;
19 | N=6;
20 | for ( a=1; a<=N; a++ )
21 | for ( b=1; b<=N; b++ )
22 | for ( c=1; c<=N; c++ )
23 | for ( d=1; d<=N; d++ )
24 | for ( e=1; e<=N; e++ )
25 | for ( f=1; f<=N; f++ )
26 | if (a!=b && a!=c && a!=d && a!=e && a!=f && a!=h && a!=i && a!=j && a!=k
27 | && b!=c && b!=d && b!=e && b!=f && b!=h && b!=i && b!=j && b!=k
28 | && c!=d && c!=e && c!=f && c!=h && c!=i && c!=j && c!=k
29 | && d!=e && d!=f && d!=h && d!=i && d!=j && d!=k
30 | && e!=f && e!=h && e!=i && e!=j && e!=k
31 | && f!=h && f!=i && f!=j && f!=k && i!=j && h!=k)
32 | {
33 | total++;
34 | }
35 |
36 | outlln(total);
37 | return 0;
38 | }
39 |
--------------------------------------------------------------------------------
/riscv/testcase/sim/uartboom.c:
--------------------------------------------------------------------------------
1 | #include "io.h"
2 |
3 | int main(){
4 | int i = 0;
5 | for ( ; i < 0x1ff; i++) {
6 | outb('a');
7 | outb('b');
8 | outb('c');
9 | outb('d');
10 | outb('e');
11 | outb('f');
12 | outb('g');
13 | outb('h');
14 | outb('i');
15 | outb('j');
16 | outb('k');
17 | outb('l');
18 | outb('m');
19 | outb('n');
20 | outb('o');
21 | outb('p');
22 | }
23 | return 0;
24 | }
25 |
--------------------------------------------------------------------------------
/riscv/testspace/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACMClassCourse-2022/RISC-V-CPU-2023/ec253f029a987405359ee679ae397be53938d47a/riscv/testspace/.keep
--------------------------------------------------------------------------------