Test firmware refactoring
This commit is contained in:
parent
f0b824ad9a
commit
d4331491a8
|
@ -1,5 +1,5 @@
|
|||
/tests/*.o
|
||||
/firmware/start.o
|
||||
/firmware/*.o
|
||||
/firmware/firmware.bin
|
||||
/firmware/firmware.elf
|
||||
/firmware/firmware.hex
|
||||
|
|
10
Makefile
10
Makefile
|
@ -1,5 +1,6 @@
|
|||
|
||||
TEST_OBJS=$(addsuffix .o,$(basename $(wildcard tests/*.S)))
|
||||
TEST_OBJS = $(addsuffix .o,$(basename $(wildcard tests/*.S)))
|
||||
FIRMWARE_OBJS = firmware/start.o firmware/irq.o firmware/print.o firmware/sieve.o firmware/stats.o
|
||||
|
||||
test: testbench.exe firmware/firmware.hex
|
||||
vvp -N testbench.exe
|
||||
|
@ -22,15 +23,18 @@ firmware/firmware.bin: firmware/firmware.elf
|
|||
riscv64-unknown-elf-objcopy -O binary $< $@
|
||||
chmod -x $@
|
||||
|
||||
firmware/firmware.elf: $(TEST_OBJS) firmware/sections.lds firmware/start.o firmware/sieve.c firmware/stats.c
|
||||
firmware/firmware.elf: $(FIRMWARE_OBJS) $(TEST_OBJS) firmware/sections.lds
|
||||
riscv64-unknown-elf-gcc -Os -m32 -march=RV32I -ffreestanding -nostdlib -o $@ \
|
||||
-Wl,-Bstatic,-T,firmware/sections.lds,-Map,firmware/firmware.map,--strip-debug \
|
||||
firmware/start.o firmware/sieve.c firmware/stats.c $(TEST_OBJS) -lgcc
|
||||
$(FIRMWARE_OBJS) $(TEST_OBJS) -lgcc
|
||||
chmod -x $@
|
||||
|
||||
firmware/start.o: firmware/start.S
|
||||
riscv64-unknown-elf-gcc -c -m32 -o $@ $<
|
||||
|
||||
firmware/%.o: firmware/%.c
|
||||
riscv64-unknown-elf-gcc -c -Os -m32 -march=RV32I -ffreestanding -nostdlib -o $@ $<
|
||||
|
||||
tests/%.o: tests/%.S tests/riscv_test.h tests/test_macros.h
|
||||
riscv64-unknown-elf-gcc -m32 -march=RV32I -c -o $@ -DTEST_FUNC_NAME=$(notdir $(basename $<)) \
|
||||
-DTEST_FUNC_TXT='"$(notdir $(basename $<))"' -DTEST_FUNC_RET=$(notdir $(basename $<))_ret $<
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef FIRMWARE_H
|
||||
#define FIRMWARE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// irq.c
|
||||
uint32_t *irq(uint32_t *regs, uint32_t irqs);
|
||||
|
||||
// print.c
|
||||
void print_chr(char ch);
|
||||
void print_str(const char *p);
|
||||
void print_dec(int val);
|
||||
void print_hex(unsigned int val);
|
||||
|
||||
// sieve.c
|
||||
void sieve();
|
||||
|
||||
// stats.c
|
||||
void stats();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,111 @@
|
|||
|
||||
#include "firmware.h"
|
||||
|
||||
uint32_t *irq(uint32_t *regs, uint32_t irqs)
|
||||
{
|
||||
static int ext_irq_4_count = 0;
|
||||
static int ext_irq_5_count = 0;
|
||||
static int timer_irq_count = 0;
|
||||
|
||||
if ((irqs & (1<<4)) != 0) {
|
||||
ext_irq_4_count++;
|
||||
// print_str("[EXT-IRQ-4]");
|
||||
}
|
||||
|
||||
if ((irqs & (1<<5)) != 0) {
|
||||
ext_irq_5_count++;
|
||||
// print_str("[EXT-IRQ-5]");
|
||||
}
|
||||
|
||||
if ((irqs & 1) != 0) {
|
||||
timer_irq_count++;
|
||||
// print_str("[TIMER-IRQ]");
|
||||
}
|
||||
|
||||
if ((irqs & 6) != 0)
|
||||
{
|
||||
int i, k;
|
||||
uint32_t pc = regs[0] - 4;
|
||||
uint32_t instr = *(uint32_t*)pc;
|
||||
|
||||
print_str("\n");
|
||||
print_str("------------------------------------------------------------\n");
|
||||
|
||||
if ((irqs & 2) != 0) {
|
||||
if (instr == 0x00100073) {
|
||||
print_str("SBREAK instruction at 0x");
|
||||
print_hex(pc);
|
||||
print_str("\n");
|
||||
} else {
|
||||
print_str("Illegal Instruction at 0x");
|
||||
print_hex(pc);
|
||||
print_str(": 0x");
|
||||
print_hex(instr);
|
||||
print_str("\n");
|
||||
}
|
||||
}
|
||||
|
||||
if ((irqs & 4) != 0) {
|
||||
print_str("Bus error in Instruction at 0x");
|
||||
print_hex(pc);
|
||||
print_str(": 0x");
|
||||
print_hex(instr);
|
||||
print_str("\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
for (k = 0; k < 4; k++)
|
||||
{
|
||||
int r = i + k*8;
|
||||
|
||||
if (r == 0) {
|
||||
print_str("pc ");
|
||||
} else
|
||||
if (r < 10) {
|
||||
print_chr('x');
|
||||
print_chr('0' + r);
|
||||
print_chr(' ');
|
||||
print_chr(' ');
|
||||
} else
|
||||
if (r < 20) {
|
||||
print_chr('x');
|
||||
print_chr('1');
|
||||
print_chr('0' + r - 10);
|
||||
print_chr(' ');
|
||||
} else
|
||||
if (r < 30) {
|
||||
print_chr('x');
|
||||
print_chr('2');
|
||||
print_chr('0' + r - 20);
|
||||
print_chr(' ');
|
||||
} else {
|
||||
print_chr('x');
|
||||
print_chr('3');
|
||||
print_chr('0' + r - 30);
|
||||
print_chr(' ');
|
||||
}
|
||||
|
||||
print_hex(regs[r]);
|
||||
print_str(k == 3 ? "\n" : " ");
|
||||
}
|
||||
|
||||
print_str("------------------------------------------------------------\n");
|
||||
|
||||
print_str("Number of fast external IRQs counted: ");
|
||||
print_dec(ext_irq_4_count);
|
||||
print_str("\n");
|
||||
|
||||
print_str("Number of slow external IRQs counted: ");
|
||||
print_dec(ext_irq_5_count);
|
||||
print_str("\n");
|
||||
|
||||
print_str("Number of timer IRQs counted: ");
|
||||
print_dec(timer_irq_count);
|
||||
print_str("\n");
|
||||
|
||||
__asm__("sbreak");
|
||||
}
|
||||
|
||||
return regs;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
#include "firmware.h"
|
||||
|
||||
#define OUTPORT 0x10000000
|
||||
|
||||
void print_chr(char ch)
|
||||
{
|
||||
*((volatile uint32_t*)OUTPORT) = ch;
|
||||
}
|
||||
|
||||
void print_str(const char *p)
|
||||
{
|
||||
while (*p != 0)
|
||||
*((volatile uint32_t*)OUTPORT) = *(p++);
|
||||
}
|
||||
|
||||
void print_dec(int val)
|
||||
{
|
||||
char buffer[10];
|
||||
char *p = buffer;
|
||||
while (val || p == buffer) {
|
||||
*(p++) = val % 10;
|
||||
val = val / 10;
|
||||
}
|
||||
while (p != buffer) {
|
||||
*((volatile uint32_t*)OUTPORT) = '0' + *(--p);
|
||||
}
|
||||
}
|
||||
|
||||
void print_hex(unsigned int val)
|
||||
{
|
||||
int i;
|
||||
for (i = 32-4; i >= 0; i -= 4)
|
||||
*((volatile uint32_t*)OUTPORT) = "0123456789ABCDEF"[(val >> i) % 16];
|
||||
}
|
||||
|
164
firmware/sieve.c
164
firmware/sieve.c
|
@ -1,12 +1,17 @@
|
|||
// A simple Sieve of Eratosthenes
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "firmware.h"
|
||||
|
||||
#define BITMAP_SIZE 64
|
||||
#define OUTPORT 0x10000000
|
||||
|
||||
static uint32_t bitmap[BITMAP_SIZE/32];
|
||||
static uint32_t hash;
|
||||
|
||||
static uint32_t mkhash(uint32_t a, uint32_t b)
|
||||
{
|
||||
// The XOR version of DJB2
|
||||
return ((a << 5) + a) ^ b;
|
||||
}
|
||||
|
||||
static void bitmap_set(int idx)
|
||||
{
|
||||
|
@ -18,37 +23,6 @@ static bool bitmap_get(int idx)
|
|||
return (bitmap[idx/32] & (1 << (idx % 32))) != 0;
|
||||
}
|
||||
|
||||
static void print_chr(char ch)
|
||||
{
|
||||
*((volatile uint32_t*)OUTPORT) = ch;
|
||||
}
|
||||
|
||||
static void print_str(const char *p)
|
||||
{
|
||||
while (*p != 0)
|
||||
*((volatile uint32_t*)OUTPORT) = *(p++);
|
||||
}
|
||||
|
||||
static void print_dec(int val)
|
||||
{
|
||||
char buffer[10];
|
||||
char *p = buffer;
|
||||
while (val || p == buffer) {
|
||||
*(p++) = val % 10;
|
||||
val = val / 10;
|
||||
}
|
||||
while (p != buffer) {
|
||||
*((volatile uint32_t*)OUTPORT) = '0' + *(--p);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_hex(unsigned int val)
|
||||
{
|
||||
int i;
|
||||
for (i = 32-4; i >= 0; i -= 4)
|
||||
*((volatile uint32_t*)OUTPORT) = "0123456789ABCDEF"[(val >> i) % 16];
|
||||
}
|
||||
|
||||
static void print_prime(int idx, int val)
|
||||
{
|
||||
if (idx < 10)
|
||||
|
@ -66,12 +40,16 @@ static void print_prime(int idx, int val)
|
|||
print_str(" prime is ");
|
||||
print_dec(val);
|
||||
print_str(".\n");
|
||||
|
||||
hash = mkhash(hash, idx);
|
||||
hash = mkhash(hash, val);
|
||||
}
|
||||
|
||||
void sieve()
|
||||
{
|
||||
int i, j, k;
|
||||
int idx = 1;
|
||||
hash = 5381;
|
||||
print_prime(idx++, 2);
|
||||
for (i = 0; i < BITMAP_SIZE; i++) {
|
||||
if (bitmap_get(i))
|
||||
|
@ -86,113 +64,15 @@ void sieve()
|
|||
bitmap_set(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *irq(uint32_t *regs, uint32_t irqs)
|
||||
{
|
||||
static int ext_irq_4_count = 0;
|
||||
static int ext_irq_5_count = 0;
|
||||
static int timer_irq_count = 0;
|
||||
|
||||
if ((irqs & (1<<4)) != 0) {
|
||||
ext_irq_4_count++;
|
||||
// print_str("[EXT-IRQ-4]");
|
||||
}
|
||||
|
||||
if ((irqs & (1<<5)) != 0) {
|
||||
ext_irq_5_count++;
|
||||
// print_str("[EXT-IRQ-5]");
|
||||
}
|
||||
|
||||
if ((irqs & 1) != 0) {
|
||||
timer_irq_count++;
|
||||
// print_str("[TIMER-IRQ]");
|
||||
}
|
||||
|
||||
if ((irqs & 6) != 0)
|
||||
{
|
||||
int i, k;
|
||||
uint32_t pc = regs[0] - 4;
|
||||
uint32_t instr = *(uint32_t*)pc;
|
||||
|
||||
print_str("\n");
|
||||
print_str("------------------------------------------------------------\n");
|
||||
|
||||
if ((irqs & 2) != 0) {
|
||||
if (instr == 0x00100073) {
|
||||
print_str("SBREAK instruction at 0x");
|
||||
print_hex(pc);
|
||||
print_str("\n");
|
||||
} else {
|
||||
print_str("Illegal Instruction at 0x");
|
||||
print_hex(pc);
|
||||
print_str(": 0x");
|
||||
print_hex(instr);
|
||||
print_str("\n");
|
||||
}
|
||||
}
|
||||
|
||||
if ((irqs & 4) != 0) {
|
||||
print_str("Bus error in Instruction at 0x");
|
||||
print_hex(pc);
|
||||
print_str(": 0x");
|
||||
print_hex(instr);
|
||||
print_str("\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
for (k = 0; k < 4; k++)
|
||||
{
|
||||
int r = i + k*8;
|
||||
|
||||
if (r == 0) {
|
||||
print_str("pc ");
|
||||
} else
|
||||
if (r < 10) {
|
||||
print_chr('x');
|
||||
print_chr('0' + r);
|
||||
print_chr(' ');
|
||||
print_chr(' ');
|
||||
} else
|
||||
if (r < 20) {
|
||||
print_chr('x');
|
||||
print_chr('1');
|
||||
print_chr('0' + r - 10);
|
||||
print_chr(' ');
|
||||
} else
|
||||
if (r < 30) {
|
||||
print_chr('x');
|
||||
print_chr('2');
|
||||
print_chr('0' + r - 20);
|
||||
print_chr(' ');
|
||||
} else {
|
||||
print_chr('x');
|
||||
print_chr('3');
|
||||
print_chr('0' + r - 30);
|
||||
print_chr(' ');
|
||||
}
|
||||
|
||||
print_hex(regs[r]);
|
||||
print_str(k == 3 ? "\n" : " ");
|
||||
}
|
||||
|
||||
print_str("------------------------------------------------------------\n");
|
||||
|
||||
print_str("Number of fast external IRQs counted: ");
|
||||
print_dec(ext_irq_4_count);
|
||||
print_str("\n");
|
||||
|
||||
print_str("Number of slow external IRQs counted: ");
|
||||
print_dec(ext_irq_5_count);
|
||||
print_str("\n");
|
||||
|
||||
print_str("Number of timer IRQs counted: ");
|
||||
print_dec(timer_irq_count);
|
||||
print_str("\n");
|
||||
|
||||
__asm__("sbreak");
|
||||
}
|
||||
|
||||
return regs;
|
||||
|
||||
print_str("checksum: ");
|
||||
print_hex(hash);
|
||||
|
||||
if (hash == 0x1772A48F) {
|
||||
print_str(" OK\n");
|
||||
} else {
|
||||
print_str(" ERROR\n");
|
||||
asm volatile ("sbreak");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#define OUTPORT 0x10000000
|
||||
#include "firmware.h"
|
||||
|
||||
static void print_str(const char *p)
|
||||
{
|
||||
while (*p != 0)
|
||||
*((volatile uint32_t*)OUTPORT) = *(p++);
|
||||
}
|
||||
|
||||
static void print_dec(int val, int digits, bool zero_pad)
|
||||
static void stats_print_dec(int val, int digits, bool zero_pad)
|
||||
{
|
||||
char buffer[32];
|
||||
char *p = buffer;
|
||||
|
@ -22,7 +14,7 @@ static void print_dec(int val, int digits, bool zero_pad)
|
|||
}
|
||||
while (p != buffer) {
|
||||
if (p[-1] == ' ' && p[-2] == ' ') p[-1] = '.';
|
||||
*((volatile uint32_t*)OUTPORT) = *(--p);
|
||||
print_chr(*(--p));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,13 +23,13 @@ void stats()
|
|||
int num_cycles, num_instr;
|
||||
asm("rdcycle %0; rdinstret %1;" : "=r"(num_cycles), "=r"(num_instr));
|
||||
print_str("Cycle counter ........");
|
||||
print_dec(num_cycles, 8, false);
|
||||
stats_print_dec(num_cycles, 8, false);
|
||||
print_str("\nInstruction counter ..");
|
||||
print_dec(num_instr, 8, false);
|
||||
stats_print_dec(num_instr, 8, false);
|
||||
print_str("\nCPI: ");
|
||||
print_dec((num_cycles / num_instr), 0, false);
|
||||
stats_print_dec((num_cycles / num_instr), 0, false);
|
||||
print_str(".");
|
||||
print_dec(((100 * num_cycles) / num_instr) % 100, 2, true);
|
||||
stats_print_dec(((100 * num_cycles) / num_instr) % 100, 2, true);
|
||||
print_str("\n");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue