Skip to content

Commit 5570ad6

Browse files
committed
ci: check SoC, core and memory config
1 parent 9f15ba8 commit 5570ad6

File tree

6 files changed

+177
-31
lines changed

6 files changed

+177
-31
lines changed

.github/scripts/check_sim.sh

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,20 @@ expected_lines=(
1111
"\[CORE\] Waking core via CLINT msip"
1212
"\[JTAG\] Halting hart 0"
1313
"\[JTAG\] Resumed hart 0"
14-
"\[UART\] Hello World!"
15-
"\[UART\] Loopback received: internal msg"
16-
"\[UART\] Result: 0x8940, Cycles: 0xBD"
17-
"\[UART\] Tick"
18-
"\[UART\] Tock"
14+
"\[UART\] Hello World from Croc v1!"
15+
"\[UART\] iDMAEnable: 0"
16+
"\[UART\] Core: CVE2, RV32CIU"
17+
"\[UART\] PMPEnable: 0"
18+
"\[UART\] SRAM: 2h banks x 200h words"
19+
"\[UART\] Debug\s*: present"
20+
"\[UART\] Bootrom\s*: present"
21+
"\[UART\] CLINT\s*: present"
22+
"\[UART\] SoC Ctrl\s*: present"
23+
"\[UART\] UART\s*: present"
24+
"\[UART\] GPIO\s*: present"
25+
"\[UART\] Timer\s*: present"
26+
"\[UART\] iDMA\s*: not present"
27+
"\[UART\] User ROM\s*: not present"
1928
)
2029

2130
for line in "${expected_lines[@]}"; do
@@ -25,22 +34,5 @@ for line in "${expected_lines[@]}"; do
2534
fi
2635
done
2736

28-
tick=$(awk '/\[UART\] Tick/ {print $2+0}' "$LOG_FILE")
29-
tock=$(awk '/\[UART\] Tock/ {print $2+0}' "$LOG_FILE")
30-
31-
echo "Tick time: ${tick}"
32-
echo "Tock time: ${tock}"
33-
34-
time_diff=$(echo "scale=2; ($tock - $tick) / 1000000" | bc)
35-
time_diff_ms=$(printf "%.0f" $time_diff)
36-
37-
# 1.5ms tolerance
38-
if ((time_diff_ms >= 9 && time_diff_ms <= 11)); then
39-
echo "Timer correct: The gap between Tick and Tock is approximately 10ms: ${time_diff}ms."
40-
else
41-
echo "Timer Error: The gap between Tick and Tock is not approximately 10ms: ${time_diff}ms."
42-
exit 1
43-
fi
44-
4537
echo "Hello world simulation passed."
4638
exit 0

.github/scripts/run_sim_flow.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ make -C sw
3131
cd verilator
3232
./run_verilator.sh --build
3333
./run_verilator.sh --run ../sw/bin/helloworld.hex
34-
cd "$CROC_ROOT"
34+
grep -q "\[UART\] Hello World from Croc!" croc.log || exit 1
35+
36+
./run_verilator.sh --run ../sw/bin/print_config.hex
37+
"$SCRIPT_DIR/check_sim.sh" croc.log
3538

36-
# verify helloworld output
37-
"$SCRIPT_DIR/check_sim.sh" verilator/croc.log
39+
cd "$CROC_ROOT"
3840

3941
echo ""
4042
echo "============================================="

.github/scripts/run_tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ for hex in "${hex_files[@]}"; do
5959
test_name=$(basename "$hex" .hex)
6060
log_file="${test_name}.log"
6161

62-
printf "Running %-30s ... " "$test_name"
62+
printf "Running %-20s ... " "$test_name"
6363

6464
# Run simulation with timeout, capture log, don't exit on failure
6565
if timeout "$TIMEOUT" "$SIM_BINARY" "+binary=$hex" > "$log_file" 2>&1; then

.github/scripts/set_croc_config.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ for arg in "$@"; do
4545
fi
4646

4747
# put RHS with equal sign into capture group, match PARAM and replace RHS with VALUE
48-
sed -i -E "s/(localparam\s+[a-zA-Z0-9_]+\s+${PARAM}\s*=\s*)[0-9a-z_']+;/\1${VALUE};/" "$PKG_FILE"
48+
sed -i -E "s/(localparam\s+[a-zA-Z0-9_]+\s+${PARAM}\s*=)\s*[0-9a-z_']+;/\1 ${VALUE};/" "$PKG_FILE"
4949

50-
if grep -q "localparam\s+[a-zA-Z0-9_]+\s+${PARAM}\s*=\s*${VALUE};" "$PKG_FILE"; then
50+
if grep -q -E "localparam\s+[a-zA-Z0-9_]+\s+${PARAM}\s*=\s*${VALUE};" "$PKG_FILE"; then
5151
echo "[INFO] ${PARAM} set to ${VALUE}"
5252
else
5353
echo "[ERROR] Failed to set ${PARAM} (parameter not found in croc_pkg.sv)" >&2
5454
echo "[INFO] Restoring croc_pkg.sv to default" >&2
55-
git -C "$CROC_ROOT" restore "$PKG_FILE"
55+
#git -C "$CROC_ROOT" restore "$PKG_FILE"
5656
exit 1
5757
fi
5858
done

sw/lib/inc/soc_ctrl.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,28 @@
66

77
#pragma once
88

9-
#define SOC_CTRL_BOOTADDR_REG_OFFSET 0x00
10-
#define SOC_CTRL_FETCHEN_REG_OFFSET 0x04
9+
#define SOC_CTRL_BOOTADDR_REG_OFFSET 0x00
10+
#define SOC_CTRL_FETCHEN_REG_OFFSET 0x04
1111
#define SOC_CTRL_CORESTATUS_REG_OFFSET 0x08
12+
#define SOC_CTRL_BOOTMODE_REG_OFFSET 0x0C
13+
#define SOC_CTRL_SRAM_DLY_REG_OFFSET 0x10
14+
15+
// Read-only hardware info register (see soc_ctrl_regs.sv for full field layout)
16+
// Groups: SoC identity/features [31:24], core identity/features [23:16], SRAM config [15:5]
17+
#define SOC_CTRL_INFO_REG_OFFSET 0x14
18+
// SoC identity & features [31:24]
19+
#define SOC_CTRL_INFO_VERSION_OFFSET 28 // [31:28] major SoC version
20+
#define SOC_CTRL_INFO_VERSION_MASK 0xF
21+
#define SOC_CTRL_INFO_IDMA_BIT 27 // [27]
22+
// Core identity & features [23:16]
23+
#define SOC_CTRL_INFO_CORE_ID_OFFSET 22 // [23:22]
24+
#define SOC_CTRL_INFO_CORE_ID_MASK 0x3
25+
#define SOC_CTRL_INFO_CORE_ID_CVE2 0
26+
#define SOC_CTRL_INFO_CORE_ID_CUSTOM 3
27+
#define SOC_CTRL_INFO_PMP_BIT 21 // [21]
28+
// Memory configuration [15:5]
29+
#define SOC_CTRL_INFO_SRAM_BANKS_OFFSET 13 // [15:13]
30+
#define SOC_CTRL_INFO_SRAM_BANKS_MASK 0x7
31+
#define SOC_CTRL_INFO_SRAM_WORDS_OFFSET 5 // [12:5] stored as SramBankNumWords/64
32+
#define SOC_CTRL_INFO_SRAM_WORDS_MASK 0xFF
33+
// Note: M and B ISA extensions are readable from the misa CSR (bits 12 and 1)

sw/test/print_config.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// Copyright (c) 2026 ETH Zurich and University of Bologna.
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
// Authors:
6+
// - Philippe Sauter <phsauter@iis.ee.ethz.ch>
7+
8+
#include "uart.h"
9+
#include "print.h"
10+
#include "util.h"
11+
#include "config.h"
12+
#include "soc_ctrl.h"
13+
14+
// maximum characters to read from user ROM string
15+
#define ROM_STRING_MAX_LEN 256
16+
17+
18+
// set by croc_exception_handler on OBI load access fault (mcause == 5)
19+
volatile int obi_error = 0;
20+
21+
// Overrides the default exception handler in crt0.S.
22+
// On an OBI load error: sets obi_error and advances mepc past the faulting load.
23+
void croc_exception_handler(uint32_t mcause) {
24+
if (mcause == 5) { // Load access fault
25+
obi_error = 1;
26+
uint32_t mepc;
27+
asm volatile("csrr %0, mepc" : "=r"(mepc));
28+
asm volatile("csrw mepc, %0" :: "r"(mepc + 4));
29+
}
30+
}
31+
32+
// Attempt a 32-bit word read from addr.
33+
static int probe_read(uint32_t addr, uint32_t *val) {
34+
obi_error = 0;
35+
*val = *(volatile uint32_t *)addr;
36+
return obi_error;
37+
}
38+
39+
// Print a null-terminated string from a memory-mapped ROM.
40+
// Reads one word at a time; stops on null terminator, OBI error, or max length.
41+
static void print_rom_str(uint32_t addr) {
42+
uint32_t word;
43+
for (uint32_t n = 0, off = 0; n < ROM_STRING_MAX_LEN; off += 4) {
44+
if (probe_read(addr + off, &word))
45+
return;
46+
for (int b = 0; b < 4 && n < ROM_STRING_MAX_LEN; b++, n++) {
47+
char c = (char)((word >> (b * 8)) & 0xFF);
48+
if (!c) return;
49+
putchar(c);
50+
}
51+
}
52+
}
53+
54+
// Peripheral table: name (8 chars, space-padded for alignment) and base address
55+
static const struct {
56+
const char *name;
57+
uint32_t addr;
58+
} peripherals[] = {
59+
{ "Debug ", DEBUG_BASE_ADDR },
60+
{ "Bootrom ", BOOTROM_BASE_ADDR },
61+
{ "CLINT ", CLINT_BASE_ADDR },
62+
{ "SoC Ctrl", SOCCTRL_BASE_ADDR },
63+
{ "UART ", UART_BASE_ADDR },
64+
{ "GPIO ", GPIO_BASE_ADDR },
65+
{ "Timer ", OBI_TIMER_BASE_ADDR },
66+
{ "iDMA ", IDMA_BASE_ADDR },
67+
{ "User ROM", USER_ROM_BASE_ADDR },
68+
};
69+
#define NUM_PERIPHERALS (sizeof(peripherals) / sizeof(peripherals[0]))
70+
71+
int main() {
72+
uart_init();
73+
74+
// Read compile-time configuration from the SoC control info register
75+
uint32_t info = *reg32(SOCCTRL_BASE_ADDR, SOC_CTRL_INFO_REG_OFFSET);
76+
uint32_t version = ((info >> SOC_CTRL_INFO_VERSION_OFFSET) & SOC_CTRL_INFO_VERSION_MASK) + 1;
77+
uint32_t core_id = (info >> SOC_CTRL_INFO_CORE_ID_OFFSET) & SOC_CTRL_INFO_CORE_ID_MASK;
78+
uint32_t sram_banks = (info >> SOC_CTRL_INFO_SRAM_BANKS_OFFSET) & SOC_CTRL_INFO_SRAM_BANKS_MASK;
79+
uint32_t sram_words = ((info >> SOC_CTRL_INFO_SRAM_WORDS_OFFSET) & SOC_CTRL_INFO_SRAM_WORDS_MASK) * 64;
80+
uint8_t has_idma = (info >> SOC_CTRL_INFO_IDMA_BIT) & 1;
81+
uint8_t has_pmp = (info >> SOC_CTRL_INFO_PMP_BIT) & 1;
82+
83+
// Read ISA extensions from the misa CSR (bits 0-25 map to extensions A-Z)
84+
uint32_t misa;
85+
asm volatile("csrr %0, misa" : "=r"(misa));
86+
87+
printf("Hello World from Croc v%x!\n", version);
88+
89+
// SoC features
90+
printf(" iDMAEnable: %x\n", has_idma);
91+
92+
// Core: type, ISA string from misa, optional PMP
93+
printf(" Core: ");
94+
printf(core_id == SOC_CTRL_INFO_CORE_ID_CVE2 ? "CVE2" :
95+
core_id == SOC_CTRL_INFO_CORE_ID_CUSTOM ? "custom" : "unknown");
96+
printf(", RV32");
97+
for (int i = 0; i < 26; i++) {
98+
if (misa & (1u << i))
99+
putchar('A' + i);
100+
}
101+
putchar('\n');
102+
printf(" PMPEnable: %x\n", has_pmp);
103+
104+
// Memory
105+
printf(" SRAM: %xh banks x %xh words\n", sram_banks, sram_words);
106+
107+
uart_write_flush();
108+
109+
// Scan all peripherals
110+
printf("Peripherals:\n");
111+
uint32_t word;
112+
for (uint32_t i = 0; i < NUM_PERIPHERALS; i++) {
113+
printf(" ");
114+
printf(peripherals[i].name);
115+
printf(": ");
116+
if (probe_read(peripherals[i].addr, &word)) {
117+
printf("not present\n");
118+
} else if (peripherals[i].addr == USER_ROM_BASE_ADDR) {
119+
// User ROM: print its null-terminated product string
120+
putchar('"');
121+
print_rom_str(USER_ROM_BASE_ADDR);
122+
printf("\"\n");
123+
} else {
124+
printf("present\n");
125+
}
126+
}
127+
uart_write_flush();
128+
129+
return 0;
130+
}

0 commit comments

Comments
 (0)