Skip to content

Commit b83f84f

Browse files
committed
up
1 parent 184b2d6 commit b83f84f

15 files changed

Lines changed: 2103 additions & 481 deletions

File tree

docs/coremark/COREMARK_PORTING.md

Lines changed: 390 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,390 @@
1+
# CoreMark Porting Guide for Ceres-V RV32IMC_Zicsr
2+
3+
Bu döküman, CoreMark benchmark'ının Ceres-V RV32IMC_Zicsr işlemcisi için nasıl port edildiğini açıklar.
4+
5+
## İçindekiler
6+
7+
1. [Genel Bakış](#genel-bakış)
8+
2. [Dosya Yapısı](#dosya-yapısı)
9+
3. [Donanım Konfigürasyonu](#donanım-konfigürasyonu)
10+
4. [Port Dosyaları](#port-dosyaları)
11+
5. [Derleme ve Kullanım](#derleme-ve-kullanım)
12+
6. [Çıktı Dosyaları](#çıktı-dosyaları)
13+
7. [Sorun Giderme](#sorun-giderme)
14+
15+
---
16+
17+
## Genel Bakış
18+
19+
CoreMark, EEMBC (Embedded Microprocessor Benchmark Consortium) tarafından geliştirilen, gömülü sistemler için standart bir benchmark'tır. Bu port, CoreMark'ın Ceres-V RV32IMC_Zicsr işlemcisinde çalışmasını sağlar.
20+
21+
### Hedef Platform
22+
- **İşlemci**: Ceres-V
23+
- **ISA**: RV32IMC_Zicsr (32-bit, Integer, Multiply, Compressed, CSR)
24+
- **Clock**: 50 MHz
25+
- **UART**: 115200 baud
26+
27+
---
28+
29+
## Dosya Yapısı
30+
31+
```
32+
level-v/
33+
├── env/coremark/ceresv/ # Port kaynak dosyaları (master copy)
34+
│ ├── core_portme.h # Platform konfigürasyonu
35+
│ ├── core_portme.c # Platform fonksiyonları
36+
│ ├── core_portme.mak # Build ayarları
37+
│ ├── crt0.S # Startup kodu
38+
│ ├── link.ld # Linker script
39+
│ ├── ee_printf.c # Printf implementasyonu
40+
│ └── cvt.c # Float-to-string conversion
41+
42+
├── subrepo/coremark/ # CoreMark kaynak kodu (submodule)
43+
│ └── ceresv/ # Build sırasında kopyalanır
44+
45+
├── build/tests/coremark/ # Derlenen çıktılar
46+
│ ├── coremark.elf
47+
│ ├── coremark.bin
48+
│ ├── coremark.hex
49+
│ ├── coremark.mem
50+
│ └── coremark.dump
51+
52+
└── script/makefiles/
53+
└── rules_coremark.mk # Build kuralları
54+
```
55+
56+
---
57+
58+
## Donanım Konfigürasyonu
59+
60+
### Memory Map
61+
62+
| Bölge | Başlangıç Adresi | Boyut | Açıklama |
63+
|-------|------------------|-------|----------|
64+
| Code (ROM) | 0x80000000 | 64 KB | Program kodu |
65+
| Data (RAM) | 0x80010000 | 64 KB | Data + Stack |
66+
| UART | 0x20000000 | 16 B | UART registers |
67+
| Timer | 0x30000000 | 8 B | 64-bit timer |
68+
69+
### UART Registers
70+
71+
```c
72+
#define UART_CTRL (*(volatile uint32_t*)0x20000000) // Control
73+
#define UART_STATUS (*(volatile uint32_t*)0x20000004) // Status
74+
#define UART_RDATA (*(volatile uint32_t*)0x20000008) // RX Data
75+
#define UART_WDATA (*(volatile uint32_t*)0x2000000c) // TX Data
76+
```
77+
78+
**UART Control Register (0x20000000)**:
79+
- Bits [31:16]: Baud divider (CPU_CLK / BAUD_RATE)
80+
- Bit [1]: RX Enable
81+
- Bit [0]: TX Enable
82+
83+
**UART Status Register (0x20000004)**:
84+
- Bit [3]: RX Empty
85+
- Bit [2]: TX Empty
86+
- Bit [1]: RX Full
87+
- Bit [0]: TX Full
88+
89+
### Timer Registers
90+
91+
```c
92+
#define TIMER_LOW (*(volatile uint32_t*)0x30000000) // Lower 32-bit
93+
#define TIMER_HIGH (*(volatile uint32_t*)0x30000004) // Upper 32-bit
94+
```
95+
96+
Timer, CPU clock hızında (50 MHz) çalışır.
97+
98+
---
99+
100+
## Port Dosyaları
101+
102+
### 1. core_portme.h
103+
104+
Platform-specific konfigürasyon:
105+
106+
```c
107+
// Donanım tanımları
108+
#define CPU_CLK 50000000 // 50 MHz
109+
#define BAUD_RATE 115200
110+
111+
// CoreMark konfigürasyonu
112+
#define HAS_FLOAT 0 // Hardware FPU yok
113+
#define HAS_TIME_H 0 // Baremetal
114+
#define USE_CLOCK 0
115+
#define HAS_STDIO 0
116+
#define HAS_PRINTF 0 // Kendi ee_printf kullanılır
117+
#define MAIN_HAS_NOARGC 1 // argc/argv yok
118+
#define SEED_METHOD SEED_VOLATILE
119+
#define MEM_METHOD MEM_STACK
120+
121+
// Data tipleri (RV32 için)
122+
typedef unsigned int ee_u32;
123+
typedef ee_u32 ee_ptr_int; // 32-bit pointer
124+
```
125+
126+
### 2. core_portme.c
127+
128+
Platform fonksiyonları:
129+
130+
```c
131+
// UART başlatma
132+
static void uart_init(void) {
133+
uint32_t baud_div = CPU_CLK / BAUD_RATE;
134+
UART_CTRL = (baud_div << 16) | UART_CTRL_TX_EN | UART_CTRL_RX_EN;
135+
}
136+
137+
// Karakter gönderme
138+
void uart_putc(char c) {
139+
while (UART_STATUS & UART_STATUS_TX_FULL);
140+
UART_WDATA = (uint32_t)c;
141+
}
142+
143+
// Timer okuma
144+
static CORETIMETYPE read_timer(void) {
145+
return TIMER_LOW;
146+
}
147+
148+
// Zaman fonksiyonları
149+
CORETIMETYPE barebones_clock() {
150+
return read_timer();
151+
}
152+
153+
void start_time(void) {
154+
GETMYTIME(&start_time_val);
155+
}
156+
157+
void stop_time(void) {
158+
GETMYTIME(&stop_time_val);
159+
}
160+
161+
// Platform başlatma
162+
void portable_init(core_portable *p, int *argc, char *argv[]) {
163+
uart_init();
164+
ee_printf("CoreMark on Ceres-V RV32IMC_Zicsr\n");
165+
// ...
166+
}
167+
```
168+
169+
### 3. crt0.S
170+
171+
Startup kodu:
172+
173+
```asm
174+
_start:
175+
# Interrupt'ları kapat
176+
csrw mie, zero
177+
178+
# Register'ları sıfırla
179+
li x1, 0
180+
# ... x31'e kadar
181+
182+
# Global pointer ayarla
183+
la gp, __global_pointer$
184+
185+
# Stack pointer ayarla
186+
la sp, _stack_top
187+
188+
# BSS temizle
189+
la t0, _bss_start
190+
la t1, _bss_end
191+
bss_clear:
192+
bge t0, t1, bss_done
193+
sw zero, 0(t0)
194+
addi t0, t0, 4
195+
j bss_clear
196+
bss_done:
197+
198+
# main çağır
199+
call main
200+
201+
# Sonsuz döngü
202+
_exit:
203+
j _exit
204+
```
205+
206+
### 4. link.ld
207+
208+
Linker script:
209+
210+
```ld
211+
OUTPUT_ARCH("riscv")
212+
ENTRY(_start)
213+
214+
MEMORY {
215+
ROM (rx) : ORIGIN = 0x80000000, LENGTH = 64K
216+
RAM (rwx) : ORIGIN = 0x80010000, LENGTH = 64K
217+
}
218+
219+
SECTIONS {
220+
.text : { *(.text.init) *(.text*) } > ROM
221+
.data : { *(.data*) } > RAM AT > ROM
222+
.bss : { *(.bss*) } > RAM
223+
224+
_stack_size = 8K;
225+
.stack : { . = . + _stack_size; _stack_top = .; } > RAM
226+
}
227+
```
228+
229+
### 5. core_portme.mak
230+
231+
Build konfigürasyonu:
232+
233+
```makefile
234+
# RISC-V Toolchain
235+
RISCV_PREFIX ?= riscv32-unknown-elf-
236+
CC = $(RISCV_PREFIX)gcc
237+
LD = $(RISCV_PREFIX)gcc
238+
239+
# Compiler flags
240+
ARCH_FLAGS = -march=rv32imc_zicsr -mabi=ilp32
241+
PORT_CFLAGS = -O2 -g $(ARCH_FLAGS) -fno-builtin -nostdlib -nostartfiles
242+
243+
# Linker flags
244+
LFLAGS = $(ARCH_FLAGS) -T$(PORT_DIR)/link.ld -nostdlib -nostartfiles
245+
LFLAGS_END = -lm -lgcc
246+
247+
# Port kaynak dosyaları
248+
PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/ee_printf.c \
249+
$(PORT_DIR)/cvt.c $(PORT_DIR)/crt0.S
250+
```
251+
252+
### 6. ee_printf.c
253+
254+
UART üzerinden printf:
255+
256+
```c
257+
void uart_send_char(char c) {
258+
while (UART_STATUS & UART_STATUS_TX_FULL);
259+
UART_WDATA = (ee_u32)c;
260+
}
261+
262+
int ee_printf(const char *fmt, ...) {
263+
char buf[1024];
264+
va_list args;
265+
va_start(args, fmt);
266+
ee_vsprintf(buf, fmt, args);
267+
va_end(args);
268+
269+
char *p = buf;
270+
while (*p) {
271+
uart_send_char(*p++);
272+
}
273+
return strlen(buf);
274+
}
275+
```
276+
277+
---
278+
279+
## Derleme ve Kullanım
280+
281+
### Temel Kullanım
282+
283+
```bash
284+
# CoreMark derle (1000 iterasyon)
285+
make coremark
286+
287+
# Özel iterasyon sayısı
288+
make coremark COREMARK_ITERATIONS=2000
289+
290+
# Temizle
291+
make coremark_clean
292+
293+
# Yardım
294+
make coremark_help
295+
```
296+
297+
### Build Süreci
298+
299+
1. **coremark_check**: `subrepo/coremark` var mı kontrol eder, yoksa clone eder
300+
2. **coremark_setup**: `env/coremark/ceresv/``subrepo/coremark/ceresv/` kopyalar
301+
3. **coremark_build**: CoreMark derler, çıktıları `build/tests/coremark/` altına koyar
302+
303+
### İterasyon Sayısı Hesaplama
304+
305+
CoreMark en az 10 saniye çalışmalıdır. Formül:
306+
307+
```
308+
ITERATIONS >= CoreMark/MHz × MHz × 10 saniye
309+
```
310+
311+
Örnek (4 CoreMark/MHz, 50 MHz için):
312+
```
313+
ITERATIONS >= 4 × 50 × 10 = 2000
314+
```
315+
316+
---
317+
318+
## Çıktı Dosyaları
319+
320+
Build sonrası `build/tests/coremark/` altında:
321+
322+
| Dosya | Açıklama |
323+
|-------|----------|
324+
| `coremark.elf` | ELF executable (debug bilgisi içerir) |
325+
| `coremark.bin` | Raw binary |
326+
| `coremark.hex` | Intel HEX format |
327+
| `coremark.mem` | Verilog $readmemh formatı |
328+
| `coremark.dump` | Disassembly listesi |
329+
330+
### Memory Dosyası Formatı
331+
332+
```
333+
@80000000
334+
73 10 40 30 73 10 40 34 81 40 01 41 ...
335+
```
336+
337+
- `@80000000`: Başlangıç adresi
338+
- Byte-addressable hex değerler
339+
340+
---
341+
342+
## Sorun Giderme
343+
344+
### 1. Toolchain Bulunamıyor
345+
346+
```bash
347+
# PATH kontrol
348+
which riscv32-unknown-elf-gcc
349+
350+
# Yoksa ekle
351+
export PATH=$HOME/tools/riscv/bin:$PATH
352+
```
353+
354+
### 2. Timer Overflow
355+
356+
32-bit timer 50 MHz'de ~85.9 saniyede overflow olur. Çok uzun testler için dikkat.
357+
358+
### 3. UART Çıktısı Yok
359+
360+
- Baud rate kontrol (115200)
361+
- UART TX enable kontrol
362+
- Simülasyonda UART modelini kontrol
363+
364+
### 4. Build Hataları
365+
366+
```bash
367+
# Temiz build
368+
make coremark_clean
369+
make coremark
370+
```
371+
372+
### 5. Linker Hataları
373+
374+
`-lm -lgcc` ile math library ve GCC runtime linklenmeli.
375+
376+
---
377+
378+
## Referanslar
379+
380+
- [CoreMark GitHub](https://github.com/eembc/coremark)
381+
- [CoreMark Barebones Porting Guide](https://github.com/eembc/coremark/blob/main/barebones_porting.md)
382+
- [RISC-V Specifications](https://riscv.org/specifications/)
383+
384+
---
385+
386+
## Değişiklik Geçmişi
387+
388+
| Tarih | Açıklama |
389+
|-------|----------|
390+
| 2025-11-28 | İlk port oluşturuldu |

0 commit comments

Comments
 (0)