Compare commits

28 Commits

Author SHA1 Message Date
9dddfd07c2 add icon
All checks were successful
Build / Run Test `test_basic` (push) Successful in -50s
Build / Run Test `test_c` (push) Successful in -58s
2025-08-29 01:36:02 -06:00
4beed25f84 update README.md
All checks were successful
Build / Run Test `test_basic` (push) Successful in -59s
Build / Run Test `test_c` (push) Successful in -58s
2025-08-29 01:29:04 -06:00
ecba3742d3 add more reference links
All checks were successful
Build / Run Test `test_basic` (push) Successful in -56s
Build / Run Test `test_c` (push) Successful in -53s
2025-08-29 01:14:26 -06:00
8f7783f801 whoops. messed up my markdown
All checks were successful
Build / Run Test `test_basic` (push) Successful in -58s
Build / Run Test `test_c` (push) Successful in -59s
2025-08-29 00:55:58 -06:00
1a135b5966 update README.md
All checks were successful
Build / Run Test `test_basic` (push) Successful in -41s
Build / Run Test `test_c` (push) Successful in -51s
2025-08-29 00:53:21 -06:00
a52c425024 editable pngs are nifty 2025-08-29 00:53:05 -06:00
8ae90cb4ef update documentation 2025-08-29 00:45:50 -06:00
2c28eb4194 remove some deprecated files 2025-08-29 00:41:25 -06:00
63d7d59580 eliminate some warnings 2025-08-29 00:37:59 -06:00
cf85106ef9 disable c function call
All checks were successful
Build / Run Test `test_basic` (push) Successful in -55s
Build / Run Test `test_c` (push) Successful in -52s
2025-08-29 00:26:20 -06:00
de1ed2978b add .text.startup section 2025-08-29 00:22:51 -06:00
76d1c52cb2 dump elf 2025-08-29 00:21:57 -06:00
8ec06e6ed8 explicit integer widths 2025-08-28 23:26:04 -06:00
5d8d652c9a use all of the object files 2025-08-28 23:25:45 -06:00
b8568acb26 build all objects 2025-08-28 23:05:30 -06:00
43e2e897f7 remove riscv toolchain
All checks were successful
Build / Run Test `test_basic` (push) Successful in -1m0s
2025-08-28 22:57:29 -06:00
cfbc68221a passing simulation
All checks were successful
Build / Run Test `test_basic` (push) Successful in 33s
2025-08-28 22:35:48 -06:00
b231133858 verbosity
All checks were successful
Build / Enumerate tests (push) Successful in -1m10s
Build / Run Test `test_basic` (push) Successful in -1m9s
2025-08-28 20:26:54 -06:00
1533ddb4f5 explicit matrix because gitea runner isn't happy
All checks were successful
Build / Enumerate tests (push) Successful in -1m10s
Build / Run Test `test_basic` (push) Successful in -1m8s
2025-08-28 20:25:33 -06:00
bb13d09825 Build all tests in CI
Some checks failed
Build / Enumerate tests (push) Successful in -1m6s
Build / Run Test `${{ matrix.test }}` (push) Failing after -1m5s
2025-08-28 20:09:26 -06:00
9c254f29fa remove gitlab CI indicator from README.md
All checks were successful
Build / Build C code (push) Successful in 11s
2025-08-28 00:58:01 -06:00
965e127989 move wire definitions before usage 2025-08-28 00:54:08 -06:00
01c91fec99 add risc-v syntax hilighting 2025-08-28 00:53:50 -06:00
294dfc6b47 trying to get sim to run in CI properly 2025-08-28 00:53:13 -06:00
ecf0b6bba2 update github actions 2025-08-28 00:14:57 -06:00
50a342fe9c switch to a newer riscv toolchain image with a Dockerfile I can edit if I ever want 2025-08-25 21:43:44 -06:00
5eb65bce9d change gcc prefix to match docker image 2025-08-25 21:32:36 -06:00
70a53c200c compile riscv in docker 2025-08-25 21:31:48 -06:00
23 changed files with 168 additions and 122 deletions

68
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,68 @@
name: Build
on: push
jobs:
# lint:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@master
# - uses: chipsalliance/verible-linter-action@main
# # with:
# # paths: |
# # ./src
# # ./lib
# # ./tests
# # extra_args: "--check_syntax=true"
# enumerate-tests:
# name: Enumerate tests
# runs-on: ubuntu-latest
# outputs:
# matrix: ${{ steps.set-matrix.outputs.matrix }}
# steps:
# - uses: actions/checkout@v2
# - id: set-matrix
# run: echo "::set-output name=matrix::$(ls tests | grep test_* | jq -R -s -c 'split("\n")[:-1]')"
test:
# needs: enumerate-tests
name: Run Test `${{ matrix.test }}`
runs-on: ubuntu-latest
strategy:
matrix:
# test: ${{ fromJson(needs.enumerate-tests.outputs.matrix) }}
test:
- test_basic
- test_c
max-parallel: 1
steps:
- uses: actions/checkout@v4
- name: Build executables
uses: docker://runtimeverificationinc/riscv-gnu-toolchain:ubuntu-jammy-2024.04.12
with:
entrypoint: sh
args: |
-c "\
cd tests/${{ matrix.test }} && \
make obj && \
riscv64-unknown-elf-ld -melf32lriscv -T tb.ld *.o -o tb.elf && \
riscv64-unknown-elf-objcopy --target=verilog tb.elf tb.hex && \
riscv64-unknown-elf-objdump -xhdtsf tb.elf && \
echo "done" \
"
- name: Run Simulation
uses: docker://brendanhaines/iverilog:latest
with:
entrypoint: bash
args: |
-c "\
cd tests/${{ matrix.test }} && \
iverilog -g2012 -o tb.out tb.sv ../../src/*.v -Y .sv -I ../../lib && \
./tb.out | tee tb.log &&\
grep -q "ERROR" tb.log || true &&\
grep -q "SUCCESS" tb.log &&\
echo "done"
"

View File

@@ -1,20 +0,0 @@
image: ubuntu
stages:
- simulate
testbench:
stage: simulate
script:
- echo "Installing dependencies..."
- apt update && apt install -y make iverilog gcc-10-riscv64-linux-gnu
- echo "Running tests..."
- make -C tests
testbench_libraries:
stage: simulate
script:
- echo "Installing dependencies..."
- apt update && apt install -y make iverilog
- echo "Running tests..."
- make -C lib/tb

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "riscv-gnu-toolchain"]
path = riscv-gnu-toolchain
url = https://github.com/riscv-collab/riscv-gnu-toolchain.git

View File

@@ -2,6 +2,7 @@
"recommendations": [
"mshr-h.veriloghdl",
"zhwu95.riscv",
"hediet.vscode-drawio"
"hediet.vscode-drawio",
"sunshaoce.risc-v"
]
}

View File

@@ -1,25 +1,36 @@
![pipeline status](https://gitlab.com/brendanhaines/0039_cpu/badges/master/pipeline.svg)
# RISC-V CPU
Short Term To Do:
* add stalls for memory access
* use AXI for memory access (depends on AXIL memory module for test)
* add tests for non-pipelined case
* get C working (may depend on memory stalls)
- [ ] add stalls for memory access
- [ ] use AXI for memory access (depends on AXIL memory module for test)
- [ ] add tests for non-pipelined case
- [ ] get C working (may depend on memory stalls)
Desired features:
* 1- or 5-stage pipeline selectable via parameter
* AXI-lite Master for both instruction and data memory
* 32, 64, (or 128?) bit word size
* floating point
* multiplication
* division
* instruction and data caches
* JTAG debug probe
- [ ] 1- or 5-stage pipeline selectable via parameter
- [ ] AXI-lite Master for both instruction and data memory
- [ ] 32, 64, (or 128?) bit word size
- [ ] floating point
- [ ] multiplication
- [ ] division
- [ ] instruction and data caches
- [ ] JTAG debug probe
## Installation
Run `setup.sh` to install GCC
## Development
### Testing
I'm using [act](https://github.com/nektos/act) for local testing. No special installation is required since everything gets built and tested in containers as part of the CI actions.
To run the tests, use
```bash
act push
```
## Resources
* [AXI4 Protocol Specification](https://developer.arm.com/documentation/ihi0022/e/AMBA-AXI3-and-AXI4-Protocol-Specification?lang=en)
* [JTAG Bus Description](https://web.archive.org/web/20230314233136/http://www.interfacebus.com/Design_Connector_JTAG_Bus.html)
* [1149.1-2013 - IEEE Standard for Test Access Port and Boundary-Scan Architecture](https://ieeexplore.ieee.org/document/6515989)
## Attribution
* [Icon](https://www.flaticon.com/free-icon/cpu_543275)

View File

@@ -1 +0,0 @@
<mxfile host="www.draw.io" modified="2021-07-04T02:03:34.409Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36" etag="gyPD3FephFzBolRvCJxz" version="14.8.4" type="device"><diagram id="K6ND4OlvUQiSsjvqaGL3" name="Page-1">7Vpbc5s4FP41ntl9iAchwPjRl2SbnWa2M9mZbR8VkA1dGXmEnNj99SuMMCAJ16kh0G384EEHSaDvfOeig0Zwsdn/wdA2eqAhJiPbCvcjuBzZ9tQH4j8THHKBa8FcsGZxmItAKXiMv2EptKR0F4c4rXXklBIeb+vCgCYJDnhNhhijL/VuK0rqT92iNdYEjwEiuvSfOORRLvVdq5R/wPE6Kp4MLHlng4rOUpBGKKQvFRG8HcEFo5TnV5v9ApMMuwKXfNxdw93TizGc8EsGPN18Q/HKWzjLP7nvEJAs/rq/sZ18mmdEdnLF8m35oYCA0V0S4mwWawTnL1HM8eMWBdndF6FzIYv4hogWEJchSqNj36yxiglZUEKZaCc0ESPm8nGYcbxvXAg4wSNohekGc3YQXeQATwIqGVXg+1Kqx/GlLKqoxi6ESFJifZq5RE1cSOBeASK0WwaxitvIhqvVyg4CIU85o//i9hGdKIhCHVJoGSD1ukLUnnSLaOhiP3Q6RBROVZLqkALHAOm0M0i9nxxShaQGjjqeAVDQmdlPNfxwKGKHbFLGI7qmCSK3pXReR7js85HSrcT1K+b8IAMh2nFaRx3vY/45Gz52ZetL5c5yL2c+Ng5FIxHLrQzKml+q98phx1YxLuWI8VkWRIUgIChN46AQ38WkeKUchmzt5zUroKI7FuAzkBYRHrE15mf6uWamMEwQj5/r79G63oFmSAFlePx8nTm1YCF+3UIcg4WYXI7TmcvRgFoijoTkAW/o8cUXKIhw77idEDgo7aqztt8SOaghd58Iv7oLeEyT4QHoDw0/AN99c9u+2bnQN8M+fbO+nWkwnA8oCQlmQzMdYNjNvLHp6Gnhu+lcaTruhaZj95rWuJrtzD7fjzLy3Yl/cX3zUViDuPztAaUcs9/7JAqo0KQkjZkoFyo8jdA2e+iK4L3s3ToJGv2ANYbQkaZ3sb7lbJ9oLF6mUh9RfMpkOp64vmdbnj/1XNeG9RlzWspJqgWkYt6iI12tUsw1op0Wc0WmaPXJJWts/5DXsf8nbgdMr/Q7x6FiaehQ6bDN2JM201SrOqn1S7U/vK5/UcFq7K8VGGr9xUW+wlaJr/tcZYvkEaG5+ZNIVLx1djWUvEXdMwGv78RFLxm+NnyZAgBOwgab1cVXhinxqOITA/DGXu3n5/elK3PHPqz9Osj0z0QqT9e0qTp8El4Zz6BimI6lUChf0JkA1hQYVS4OIBIC30RjSV3VGVyRiJm4PuTkrEV6+21Eu++SS/s40kCutoij82aJn3brrEZERR5CyRCihqOC1H+l6KfMPAeeeF5axm8INNfGC1AnmfpJ7dJwoc4DJm9r0QD0S83Jr0zNboIEtBVK/Wgqo02kfuVs4OZrN2mOagPf2UQ53tn+3WyigP5p+5j6q+nSgtE0fUL9h0E1VzBEweLcVDUIwu7OW9hmBA2bp0eCnvF76e91TqehwNJ97Q/Cwdf+wFTjnqyB/J1Rnxw/c9LdlgjulHWRgZU/YO/fbWy9lJStfIuZ4WSCWDivY2I8tWM4v4dIvE4yWxJAiQ0FnGcwxgEiM3ljE4fh0d5NSqirqXZWsAOlXKoTuzOd6NT+JByPkOipna6SNqFeiT1g5bDWZDbzvUJeuG3Qggq0nNlw7s14OLOzkxT6aR2pArsHFZRQaypZOLOJc9eOIQD1QIbbmRZEszzCnIeE8hw4vP0P</diagram></mxfile>

BIN
docs/cpu.drawio.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -1,7 +0,0 @@
sudo apt-get install -y autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev
SCRIPT=$(realpath "$0")
SCRIPTPATH=$(dirname "$SCRIPT")
cd $SCRIPTPATH/riscv-gnu-toolchain
./configure --prefix=$SCRIPTPATH/toolchain/riscv --enable-multilib
make

View File

@@ -120,19 +120,6 @@ reg s_if_stall = 0;
reg [31:0] s_if_next_pc;
reg [31:0] s_if_inst;
always @(*) begin
s_if_stall = s_id_stall;
if (s_ex_take_branch) begin
s_if_next_pc = s_ex_branch_addr;
end else begin
s_if_next_pc = r_if_pc + 4;
end
mem_inst_addr = r_if_pc;
s_if_inst = mem_inst_data;
end
// ID
reg s_id_stall;
reg [6:0] s_id_opcode;
@@ -177,7 +164,39 @@ localparam ALUOP_ADD = 4'b0000,
ALUOP_SLT = 4'b1000,
ALUOP_SLTU = 4'b1001;
// EX
reg s_ex_stall = 0;
reg [31:0] s_ex_data1, s_ex_data2;
reg [31:0] s_ex_alu_out;
reg s_ex_alu_zero;
reg s_ex_take_branch;
reg [31:0] s_ex_branch_addr;
reg [31:0] s_ex_ra;
// MEM
reg s_mem_stall = 0;
reg s_mem_bp;
reg [31:0] s_mem_load_data;
// WB
reg [31:0] s_wb_data;
reg s_wb_write;
// IF
always @(*) begin
s_if_stall = s_id_stall;
if (s_ex_take_branch) begin
s_if_next_pc = s_ex_branch_addr;
end else begin
s_if_next_pc = r_if_pc + 4;
end
mem_inst_addr = r_if_pc;
s_if_inst = mem_inst_data;
end
// ID
always @(*) begin
s_id_invalid = 0;
s_id_store = 0;
@@ -332,14 +351,6 @@ always @(*) begin
end
// EX
reg s_ex_stall = 0;
reg [31:0] s_ex_data1, s_ex_data2;
reg [31:0] s_ex_alu_out;
reg s_ex_alu_zero;
reg s_ex_take_branch;
reg [31:0] s_ex_branch_addr;
reg [31:0] s_ex_ra;
always @(*) begin
s_ex_stall = s_mem_stall;
@@ -394,10 +405,6 @@ always @(*) begin
end
// MEM
reg s_mem_stall = 0;
reg s_mem_bp;
reg [31:0] s_mem_load_data;
always @(*) begin
s_mem_stall = 0; // TODO: add stall logic when actually reading/writing
s_mem_bp = 0;
@@ -417,9 +424,6 @@ always @(*) begin
end
// WB
reg [31:0] s_wb_data;
reg s_wb_write;
always @(*) begin
// load instructions do not use output of alu in wb
@@ -475,6 +479,8 @@ always @(posedge clk) begin: pipeline_update
end
end else begin
// $display("%0t:\tPC=0x%h", $time, s_if_next_pc);
// IF
if (!s_if_stall) begin
r_if_pc <= s_if_next_pc;

6
tests/.gitignore vendored
View File

@@ -1,3 +1,3 @@
*.out
*.vcd
*.log
**/*.out
**/*.vcd
**/*.log

View File

@@ -1,18 +0,0 @@
all: verify
BENCH ?= $(sort $(dir $(wildcard test_*/)))
# override bench to disable test_c
BENCH = test_basic
verify:
$(foreach dir, $(BENCH), make -C $(dir) verify;)
clean:
$(foreach dir, $(BENCH), make -C $(dir) clean;)
help:
$(info BENCH options: [${BENCH}])
.SECONDARY:
.PHONY: all clean verify help

View File

@@ -11,15 +11,15 @@ OBJ = $(notdir $(SOURCE_AS:.S=.o))
OBJ += $(notdir $(SOURCE_C:.c=.o))
# Software compilation
CC = riscv64-linux-gnu-gcc
CC = riscv64-unknown-elf-gcc
CFLAGS = -march=rv32i -mabi=ilp32
CPPFLAGS =
AS = riscv64-linux-gnu-as
AS = riscv64-unknown-elf-as
ASFLAGS = -march=rv32i -mabi=ilp32
LD = riscv64-linux-gnu-ld
LD = riscv64-unknown-elf-ld
LDFLAGS = -melf32lriscv_ilp32
# $(info $$TESTBENCH_V is [${TESTBENCH_V}])
@@ -40,7 +40,7 @@ LDFLAGS = -melf32lriscv_ilp32
$(LD) $(LDFLAGS) -T $^ -o $@
%.hex: %.elf
riscv64-linux-gnu-objcopy --target=verilog $< $@
riscv64-unknown-elf-objcopy --target=verilog $< $@
# Hardware compilation
%.out: %.sv $(SOURCE_V)
@@ -57,5 +57,7 @@ verify: $(LOGS)
clean:
rm -rf *.vcd *.log *.out *.hex
obj: $(OBJ)
.SECONDARY: %.log %.vcd
.PHONY: all clean verify
.PHONY: all clean verify obj

View File

@@ -1,5 +1,5 @@
# basic_test
Verify basic usage of all instructions. Includes tests to ensure pipeline stalls sufficiently for correctness but does not test for unnecessary stalls.
Verify basic usage of all instructions. Includes tests to ensure pipeline stalls sufficiently for correctness but does not test for unnecessary/excessive stalls.
Currently store/load does not implement proper stalling so these operations are padded with nop
Currently store/load does not implement proper stalling so these operations are padded with `nop`

View File

@@ -31,7 +31,7 @@ initial $readmemh("tb.hex", mem);
// Instruction Memory
wire [31:0] mem_inst_addr;
reg [31:0] mem_inst_data;
always @(*) begin
always_comb begin
if (mem_inst_addr < MEM_LENGTH - 3) begin
mem_inst_data[ 7: 0] = mem[mem_inst_addr+0];
mem_inst_data[15: 8] = mem[mem_inst_addr+1];

View File

@@ -10,18 +10,18 @@ SOURCE_AS = $(wildcard *.S)
OBJ = $(notdir $(SOURCE_AS:.S=.o))
OBJ += $(notdir $(SOURCE_C:.c=.o))
CC = riscv64-linux-gnu-gcc
CC = riscv64-unknown-elf-gcc
CFLAGS = -march=rv32i -mabi=ilp32
# CFLAGS = -march=rv64i -mabi=lp64
# CFLAGS += -nostdlib -lgcc
CPPFLAGS =
AS = riscv64-linux-gnu-as
AS = riscv64-unknown-elf-as
ASFLAGS = -march=rv32i -mabi=ilp32
# ASFLAGS = -march=rv64i -mabi=lp64
LD = riscv64-linux-gnu-ld
LD = riscv64-unknown-elf-ld
LDFLAGS = -melf32lriscv_ilp32
# LDFLAGS =
@@ -45,7 +45,7 @@ LDFLAGS = -melf32lriscv_ilp32
$(LD) $(LDFLAGS) -T $^ -o $@
%.hex: %.elf
riscv64-linux-gnu-objcopy --target=verilog $< $@
riscv64-unknown-elf-objcopy --target=verilog $< $@
%.out: %.sv $(SOURCE_V)
iverilog -g2012 -o $@ $^
@@ -62,6 +62,8 @@ verify: $(LOGS)
clean:
rm -rf *.vcd *.log *.out *.hex
.SECONDARY: %.log %.vcd
.PHONY: all clean verify
obj: $(OBJ)
.SECONDARY: %.log %.vcd
.PHONY: all clean verify obj

View File

@@ -1,5 +1,5 @@
# basic_test
# C test
Verify basic usage of all instructions. Includes tests to ensure pipeline stalls sufficiently for correctness but does not test for unnecessary stalls.
Verify basic ability to use C
Currently store/load does not implement proper stalling so these operations are padded with nop
Currently all C functions fail because store/load do not stall properly.

View File

@@ -1,6 +1,6 @@
// #include <stdint.h>
#include <stdint.h>
unsigned int addathing(unsigned int a)
uint32_t addathing(uint32_t a)
{
return a + 0x29;
}

View File

@@ -1,5 +1,4 @@
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
MEMORY
{
@@ -14,6 +13,7 @@ SECTIONS
{
/* . = ALIGN(4); */
_text = .;
*(.text.startup)
*(.text*)
*(.rodata*)
_etext = .;

View File

@@ -31,7 +31,7 @@ initial $readmemh("tb.hex", mem);
// Instruction Memory
wire [31:0] mem_inst_addr;
reg [31:0] mem_inst_data;
always @(*) begin
always_comb begin
if (mem_inst_addr < MEM_LENGTH - 3) begin
mem_inst_data[ 7: 0] = mem[mem_inst_addr+0];
mem_inst_data[15: 8] = mem[mem_inst_addr+1];

View File

@@ -1,17 +1,23 @@
.global _start
.global addathing
.section .text.startup # start vector
j _start
nop
nop
nop
nop
nop
.text
_start:
addi a0, zero, 0x134
addi a1, zero, 0x0
nop
nop
nop
nop
nop
call addathing
# call addathing # c compilation has sw/lw instructions. Missing stalls break execution
nop
nop
nop