Skip to content

Commit 2f22c3d

Browse files
c program
1 parent 0cb1a8e commit 2f22c3d

10 files changed

Lines changed: 190 additions & 71 deletions

File tree

.gitignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ local.properties
127127
*.app
128128
*.i*86
129129
*.x86_64
130-
*.hex
131130

132131
# Debug files
133132
*.dSYM/
@@ -427,5 +426,4 @@ xvlog.*
427426
## checkpoint files
428427
*.dcp
429428

430-
431-
429+
xpack-riscv-none-elf-gcc-15.2.0-1

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,18 @@ class MainTemplateSpec extends AnyFreeSpec with Matchers with ChiselSim {
122122
cd simulation
123123
verilator --cc --sv --exe --build -j 0 -CFLAGS "-I./obj_dir" -Wall vga-image.cpp VGAController.sv
124124
./obj_dir/VVGAController
125-
nix-shell -p imagemagick --run "convert frame.ppm frame.png"
125+
nix-shell -p imagemagick --run "convert frame.ppm frame.png"
126+
127+
.\xpack-riscv-none-elf-gcc-15.2.0-1\bin\riscv-none-elf-gcc.exe -S -O0 -march=rv32i -mabi=ilp32 ./programs/hello.c -o ./programs/hello.s
128+
129+
## Compiling a C program
130+
131+
.\xpack-riscv-none-elf-gcc-15.2.0-1\bin\riscv-none-elf-gcc.exe -c -O0 -march=rv32i -mabi=ilp32 ./programs/hello.c -o ./programs/hello.o
132+
133+
.\xpack-riscv-none-elf-gcc-15.2.0-1\bin\riscv-none-elf-gcc.exe -march=rv32i -mabi=ilp32 -nostdlib "-Wl,--section-start=.text=0x0" -o ./programs/hello.elf ./programs/hello.o
134+
135+
.\xpack-riscv-none-elf-gcc-15.2.0-1\bin\riscv-none-elf-objcopy.exe -O binary ./programs/hello.elf ./programs/hello.bin
136+
137+
python convert.py
138+
139+
python.exe .\load_program.py .\programs\test.hex --port COM6

convert.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
with open("./programs/hello.bin", "rb") as f:
2+
data = f.read()
3+
4+
with open("./programs/hello.hex", "w") as f:
5+
for i in range(0, len(data), 4):
6+
word = data[i:i+4]
7+
val = int.from_bytes(word, "little")
8+
f.write(f"{val:08x}\n")

load_program.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
Sends a .hex file over UART to the uart_program_loader module.
55
66
Usage:
7-
python3 load_program.py program.hex
8-
python3 load_program.py program.hex --port /dev/ttyUSB1
9-
python3 load_program.py program.hex --port COM3 --baud 115200
7+
python load_program.py program.hex
8+
python load_program.py program.hex --port COM3
9+
python load_program.py program.hex --port COM3 --baud 115200
1010
"""
1111

1212
import serial
@@ -19,7 +19,7 @@
1919
# -------------------------------------------------------
2020
parser = argparse.ArgumentParser(description="Load a RISC-V hex program onto Basys3 over UART")
2121
parser.add_argument("hex_file", help="Path to the .hex program file")
22-
parser.add_argument("--port", default="/dev/ttyUSB1", help="Serial port (default: /dev/ttyUSB0)")
22+
parser.add_argument("--port", default="COM3", help="Serial port (default: COM3)")
2323
parser.add_argument("--baud", default=115200, type=int, help="Baud rate (default: 115200)")
2424
parser.add_argument("--delay", default=0.01, type=float, help="Delay between words in seconds (default: 0.01)")
2525
args = parser.parse_args()
@@ -63,9 +63,9 @@
6363
ser.write(data)
6464
time.sleep(args.delay)
6565

66-
# Progress bar
66+
# Progress bar (use ASCII chars instead of unicode)
6767
pct = (i + 1) / len(words) * 100
68-
bar = '' * int(pct / 2) + '' * (50 - int(pct / 2))
68+
bar = '#' * int(pct / 2) + '-' * (50 - int(pct / 2))
6969
print(f"\r[{bar}] {pct:.1f}% ({i+1}/{len(words)} words)", end='', flush=True)
7070

7171
print() # newline after progress bar
@@ -80,4 +80,4 @@
8080
except serial.SerialException as e:
8181
print(f"Serial error: {e}")
8282
print(f"Make sure the board is connected and '{args.port}' is correct")
83-
sys.exit(1)
83+
sys.exit(1)

programs/hello.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
int main() {
2+
volatile unsigned char* mem = (volatile unsigned char*)0x4000;
3+
int counter = 0;
4+
5+
while (1) {
6+
counter++;
7+
mem[counter] = counter; // sb x1, 0(x2) — store counter byte
8+
9+
// busy-wait pause loop (~2000 iterations)
10+
for (int i = 0; i < 2000; i++) {
11+
__asm__("nop"); // prevent compiler from optimizing away
12+
}
13+
}
14+
}

programs/hello.hex

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
fe010113
2+
00112e23
3+
00812c23
4+
02010413
5+
000047b7
6+
fef42223
7+
fe042623
8+
fec42783
9+
00178793
10+
fef42623
11+
fec42783
12+
fe442703
13+
00f707b3
14+
fec42703
15+
0ff77713
16+
00e78023
17+
fe042423
18+
0140006f
19+
00000013
20+
fe842783
21+
00178793
22+
fef42423
23+
fe842703
24+
7cf00793
25+
fee7d4e3
26+
fb9ff06f

programs/hello.s

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
.file "hello.c"
2+
.option nopic
3+
.attribute arch, "rv32i2p1"
4+
.attribute unaligned_access, 0
5+
.attribute stack_align, 16
6+
.text
7+
.align 2
8+
.globl main
9+
.type main, @function
10+
main:
11+
addi sp,sp,-32
12+
sw ra,28(sp)
13+
sw s0,24(sp)
14+
addi s0,sp,32
15+
li a5,16384
16+
sw a5,-28(s0)
17+
sw zero,-20(s0)
18+
.L4:
19+
lw a5,-20(s0)
20+
addi a5,a5,1
21+
sw a5,-20(s0)
22+
lw a5,-20(s0)
23+
lw a4,-28(s0)
24+
add a5,a4,a5
25+
lw a4,-20(s0)
26+
andi a4,a4,0xff
27+
sb a4,0(a5)
28+
sw zero,-24(s0)
29+
j .L2
30+
.L3:
31+
#APP
32+
# 11 "./programs/hello.c" 1
33+
nop
34+
# 0 "" 2
35+
#NO_APP
36+
lw a5,-24(s0)
37+
addi a5,a5,1
38+
sw a5,-24(s0)
39+
.L2:
40+
lw a4,-24(s0)
41+
li a5,1999
42+
ble a4,a5,.L3
43+
j .L4
44+
.size main, .-main
45+
.ident "GCC: (xPack GNU RISC-V Embedded GCC x86_64) 15.2.0"
46+
.section .note.GNU-stack,"",@progbits

programs/test.hex

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
00004137
2+
000041b7
3+
7d000293
4+
00108093
5+
00218133
6+
00110023
7+
00000213
8+
00120213
9+
fe521ee3
10+
fe9ff06f

src/main/scala/RISCV/Main.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@ class Main() extends Module {
1818
val vsync = Output(Bool())
1919
val rgb = Output(UInt(12.W))
2020
val blanking = Output(Bool())
21+
22+
val debug_1 = Output(UInt(32.W))
23+
val debug_2 = Output(UInt(32.W))
2124
})
2225

26+
io.debug_1 := 0.U
27+
io.debug_2 := 0.U
28+
2329
val program_pointer = RegInit(0.U(32.W))
2430

2531
val registers = Module(new Registers())

src/test/scala/RISCV/MainSpec.scala

Lines changed: 57 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -10,80 +10,77 @@ import java.nio.ByteBuffer
1010
import chisel3.simulator.PeekPokeAPI.TestableRecord
1111

1212
class MainSpec extends AnyFreeSpec with Matchers with ChiselSim {
13-
// "Main should execute LUI correctly" in {
14-
// simulate(new Main()) { dut =>
15-
// val bytes = Files.readAllBytes(Paths.get("./programs/fib-loop.bin"))
16-
17-
// val instructions = bytes.grouped(4).map { instrBytes =>
18-
// val paddedBytes = instrBytes.padTo(4, 0.toByte)
19-
// val signedInt = ByteBuffer.wrap(paddedBytes).order(java.nio.ByteOrder.BIG_ENDIAN).getInt()
20-
// signedInt.toLong & 0xFFFFFFFFL
21-
// }.toSeq
22-
23-
// dut.io.debug_write.poke(true.B)
24-
// instructions.zipWithIndex.foreach { case (instr, idx) =>
25-
// println(s"Instruction: ${instr.toBinaryString.reverse.padTo(32, '0').reverse}")
26-
// println(s"Address: ${idx * 4}")
13+
"Main should execute Store and Load Instructions correctly" in {
14+
simulate(new Main()) { dut =>
15+
// Load hex file, one instruction per line
16+
val instructions = Source
17+
.fromFile("./programs/hello.hex")
18+
.getLines()
19+
.filter(_.trim.nonEmpty)
20+
.map(line => java.lang.Long.parseLong(line.trim, 16))
21+
.toSeq
2722

28-
// dut.io.debug_write_data.poke(instr.U(32.W))
29-
// dut.io.debug_write_addressess.poke((idx * 4).U)
30-
// dut.clock.step(1)
31-
// }
23+
dut.io.debug_write.poke(true.B)
3224

33-
// dut.io.debug_write.poke(false.B);
34-
// dut.io.execute.poke(true.B);
25+
instructions.zipWithIndex.foreach { case (instr, idx) =>
26+
dut.io.debug_write_address.poke(idx.U)
27+
dut.io.debug_write_data.poke(instr.U(32.W))
28+
dut.clock.step(1)
29+
}
3530

36-
// dut.clock.step(1);
31+
dut.io.debug_write.poke(false.B)
32+
dut.clock.step(1)
3733

38-
// dut.clock.step(50);
39-
// }
40-
// }
34+
dut.io.execute.poke(true.B)
35+
dut.clock.step(100)
36+
}
37+
}
4138

42-
"Main should execute Store and Load Instructions correctly" in {
43-
simulate(new Main()) { dut =>
44-
dut.io.debug_write.poke(true.B)
39+
// "Main should execute Store and Load Instructions correctly" in {
40+
// simulate(new Main()) { dut =>
41+
// dut.io.debug_write.poke(true.B)
4542

46-
dut.io.debug_write_address.poke(0.U)
47-
dut.io.debug_write_data.poke(0x00004137L.U)
48-
dut.clock.step(1)
43+
// dut.io.debug_write_address.poke(0.U)
44+
// dut.io.debug_write_data.poke(0x00004137L.U)
45+
// dut.clock.step(1)
4946

50-
dut.io.debug_write_address.poke(1.U)
51-
dut.io.debug_write_data.poke(0x000041b7L.U)
52-
dut.clock.step(1)
47+
// dut.io.debug_write_address.poke(1.U)
48+
// dut.io.debug_write_data.poke(0x000041b7L.U)
49+
// dut.clock.step(1)
5350

54-
dut.io.debug_write_address.poke(2.U)
55-
dut.io.debug_write_data.poke(0x00408093L.U)
56-
dut.clock.step(1)
51+
// dut.io.debug_write_address.poke(2.U)
52+
// dut.io.debug_write_data.poke(0x00408093L.U)
53+
// dut.clock.step(1)
5754

58-
dut.io.debug_write_address.poke(3.U)
59-
dut.io.debug_write_data.poke(0x00218133L.U)
60-
dut.clock.step(1)
55+
// dut.io.debug_write_address.poke(3.U)
56+
// dut.io.debug_write_data.poke(0x00218133L.U)
57+
// dut.clock.step(1)
6158

62-
dut.io.debug_write_address.poke(4.U)
63-
dut.io.debug_write_data.poke(0x00110023L.U)
64-
dut.clock.step(1)
59+
// dut.io.debug_write_address.poke(4.U)
60+
// dut.io.debug_write_data.poke(0x00110023L.U)
61+
// dut.clock.step(1)
6562

66-
dut.io.debug_write_address.poke(5.U)
67-
dut.io.debug_write_data.poke(0xff5ff06fL.U)
68-
dut.clock.step(1)
63+
// dut.io.debug_write_address.poke(5.U)
64+
// dut.io.debug_write_data.poke(0xff5ff06fL.U)
65+
// dut.clock.step(1)
6966

70-
// dut.io.debug_write_address.poke(0.U)
71-
// dut.io.debug_write_data.poke(0b000000000111_00000_000_00001_0010011.U) // ADDI
72-
// dut.clock.step(1)
67+
// // dut.io.debug_write_address.poke(0.U)
68+
// // dut.io.debug_write_data.poke(0b000000000111_00000_000_00001_0010011.U) // ADDI
69+
// // dut.clock.step(1)
7370

74-
// dut.io.debug_write_address.poke(1.U)
75-
// dut.io.debug_write_data.poke(0b0000000_00001_00000_010_00000_0100011.U) // SW
76-
// dut.clock.step(1)
71+
// // dut.io.debug_write_address.poke(1.U)
72+
// // dut.io.debug_write_data.poke(0b0000000_00001_00000_010_00000_0100011.U) // SW
73+
// // dut.clock.step(1)
7774

78-
// dut.io.debug_write_address.poke(2.U)
79-
// dut.io.debug_write_data.poke(0b000000000000_00000_010_00010_0000011.U) // LW
80-
// dut.clock.step(1)
75+
// // dut.io.debug_write_address.poke(2.U)
76+
// // dut.io.debug_write_data.poke(0b000000000000_00000_010_00010_0000011.U) // LW
77+
// // dut.clock.step(1)
8178

82-
dut.io.debug_write.poke(false.B)
83-
dut.clock.step(1)
79+
// dut.io.debug_write.poke(false.B)
80+
// dut.clock.step(1)
8481

85-
dut.io.execute.poke(true.B)
86-
dut.clock.step(24)
87-
}
88-
}
82+
// dut.io.execute.poke(true.B)
83+
// dut.clock.step(24)
84+
// }
85+
// }
8986
}

0 commit comments

Comments
 (0)