aboutsummaryrefslogtreecommitdiff
path: root/Makefile
blob: b364bde56a917328ae52ce5cbe9b26dfb7a8f4de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
PRJ_NAME = riscv_cpu
TOP_MODULE = top

# Directories
SRC_DIR = src
SIM_DIR = sim
GENTESTVEC_DIR = gentestvec
CST_DIR = cst
BUILD_DIR = build

# Source Files
SRC_FILES = $(wildcard $(SRC_DIR)/*.v)
SIM_FILES = $(wildcard $(SIM_DIR)/testbench_*.v)
GENTESTVEC_FILES = $(wildcard $(GENTESTVEC_DIR)/gentestvec_*.c)
CST_FILES = $(wildcard $(CST_DIR)/*.cst)

# Output Files
SIM_EXECUTABLES = $(patsubst $(SIM_DIR)/testbench_%.v, $(BUILD_DIR)/testbench_%,$(SIM_FILES))
GENTESTVEC_EXECUTABLES = $(patsubst $(GENTESTVEC_DIR)/gentestvec_%.c, $(BUILD_DIR)/gentestvec_%,$(GENTESTVEC_FILES))
TESTVECTOR_FILES = $(patsubst $(BUILD_DIR)/gentestvec_%, $(BUILD_DIR)/testvec_%.txt, $(GENTESTVEC_EXECUTABLES))
WAVEFORM_FILES = $(patsubst $(BUILD_DIR)/testbench_%, $(BUILD_DIR)/waveform_%.vcd, $(SIM_EXECUTABLES))

BITSTREAM = $(BUILD_DIR)/$(PRJ_NAME).fs

# Programs
CC = clang
CFLAGS = -O3

IVERILOG = iverilog
VVP = vvp
GTKWAVE = gtkwave

YOSYS = yosys
NEXTPNR = nextpnr-himbaechel
GOWIN_PACK = gowin_pack
PROGRAMMER = openFPGALoader

FAMILY = GW1N-9C
DEVICE = GW1NR-LV9QN88PC6/I5
BOARD = tangnano9k

# RISCV Toolchain
RISCV_TOOLCHAIN = riscv64-unknown-elf
RISCV_AS = $(RISCV_TOOLCHAIN)-as
RISCV_CC = $(RISCV_TOOLCHAIN)-gcc
RISCV_LD = $(RISCV_TOOLCHAIN)-ld
RISCV_OBJCOPY = $(RISCV_TOOLCHAIN)-objcopy

RISCV_ASFLAGS = -march=rv32i -mabi=ilp32
RISCV_CFLAGS = -march=rv32i -mabi=ilp32
RISCV_LDFLAGS = -T prog/link.ld -m elf32lriscv

PROG_SOURCE_DIR = prog/src

PROG_ASSEMBLY_SOURCES = $(wildcard $(PROG_SOURCE_DIR)/*.s)
PROG_C_SOURCES = $(wildcard $(PROG_SOURCE_DIR)/*.c)
PROG_OBJECT_FILES = $(PROG_ASSEMBLY_SOURCES:$(PROG_SOURCE_DIR)/%.s=$(BUILD_DIR)/%.o) $(PROG_C_SOURCES:$(PROG_SOURCE_DIR)/%.c=$(BUILD_DIR)/%.o)
PROG_ELF_FILE = $(BUILD_DIR)/prog.elf
PROG_BINARY_FILE = $(BUILD_DIR)/prog.bin
PROG_ROM_FILE = $(BUILD_DIR)/rom.hex


all: simulate


$(BUILD_DIR)/$(PRJ_NAME).json: $(SRC_FILES) | $(BUILD_DIR)
	@echo
	@echo "=================================================="
	@echo " Synthesizing"
	@echo "=================================================="
	$(YOSYS) -p "synth_gowin -top $(TOP_MODULE)" -o $(BUILD_DIR)/$(PRJ_NAME).json $(SRC_FILES)
	@echo "=================================================="
	@echo " Completed Synthesis"
	@echo "=================================================="
	@echo

$(BUILD_DIR)/$(PRJ_NAME)_pnr.json: $(BUILD_DIR)/$(PRJ_NAME).json $(CST_FILES)
	@echo
	@echo "==================================================="
	@echo " Routing"
	@echo "==================================================="
	$(NEXTPNR) --json $(BUILD_DIR)/$(PRJ_NAME).json --write $(BUILD_DIR)/$(PRJ_NAME)_pnr.json --device $(DEVICE) --vopt family=$(FAMILY) --vopt cst=$(CST_FILES)
	@echo "==================================================="
	@echo " Completed Routing"	
	@echo "==================================================="
	@echo

$(BITSTREAM): $(BUILD_DIR)/$(PRJ_NAME)_pnr.json
	@echo
	@echo "==================================================="
	@echo " Generating Bitstream"
	@echo "==================================================="
	$(GOWIN_PACK) -d $(FAMILY) -o $(BITSTREAM) $(BUILD_DIR)/$(PRJ_NAME)_pnr.json
	@echo "==================================================="
	@echo " Generated Bitstream"
	@echo "==================================================="
	@echo

bitstream: $(BITSTREAM)
	
upload: $(BITSTREAM)
	$(PROGRAMMER) -b $(BOARD) $(BITSTREAM)

flash: $(BITSTREAM)
	$(PROGRAMMER) -b $(BOARD) -f $(BITSTREAM)

simulate: $(WAVEFORM_FILES)

# Build the testbench executables
$(BUILD_DIR)/testbench_%: $(SIM_DIR)/testbench_%.v $(SRC_FILES) | $(BUILD_DIR) $(PROG_ROM_FILE)
	$(IVERILOG) -o $@ $^

# Build the test vector generator executables
$(BUILD_DIR)/gentestvec_%: $(GENTESTVEC_DIR)/gentestvec_%.c | $(BUILD_DIR)
	$(CC) $(CFLAGS) -o $@ $<

# Generate the test vector files
$(BUILD_DIR)/testvec_%.txt: $(BUILD_DIR)/gentestvec_%
	$< > $@

# Run the simulation and generate the waveform files
$(BUILD_DIR)/waveform_%.vcd: $(BUILD_DIR)/testbench_% $(BUILD_DIR)/testvec_%.txt
	@echo
	@echo "==================================================="
	@echo " Running Testbench ($*)"
	@echo "==================================================="
	$(VVP) $< +testvec=$(BUILD_DIR)/testvec_$*.txt +waveform=$@
	@echo "==================================================="
	@echo " Completed Testbench ($*)"
	@echo "==================================================="
	@echo

rom: $(PROG_ROM_FILE)

# Assemble assembly source files into object files
$(BUILD_DIR)/%.o: $(PROG_SOURCE_DIR)/%.s | $(BUILD_DIR)
	$(RISCV_AS) $(RISCV_ASFLAGS) -o $@ $<

# Compile C source files into object files
$(BUILD_DIR)/%.o: $(PROG_SOURCE_DIR)/%.c | $(BUILD_DIR)
	$(RISCV_CC) $(RISCV_CFLAGS) -c -o $@ $<

# Link the object files to create an ELF file
$(PROG_ELF_FILE): $(PROG_OBJECT_FILES)
	$(RISCV_LD) $(RISCV_LDFLAGS) -o $@ $^

# Convert the ELF file to a binary file
$(PROG_BINARY_FILE): $(PROG_ELF_FILE)
	$(RISCV_OBJCOPY) -O binary $< $@

# Convert the binary file to a hex file
$(PROG_ROM_FILE): $(PROG_BINARY_FILE)
	xxd -g 4 -c 4 -p $< | awk '{print substr($$0,7,2) substr($$0,5,2) substr($$0,3,2) substr($$0,1,2)}' > $@

# Create the build directory
$(BUILD_DIR):
	mkdir -p $(BUILD_DIR)

wave:
	$(GTKWAVE) -a debug/cpu.gtkw $(BUILD_DIR)/waveform_cpu.vcd

# Clean
clean:
	rm -rf $(BUILD_DIR)

.PHONY: all simulate rom bitsream upload flash wave clean