Test firmware refactoring

This commit is contained in:
Clifford Wolf 2015-06-26 22:02:22 +02:00
parent f0b824ad9a
commit d4331491a8
7 changed files with 206 additions and 161 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
/tests/*.o /tests/*.o
/firmware/start.o /firmware/*.o
/firmware/firmware.bin /firmware/firmware.bin
/firmware/firmware.elf /firmware/firmware.elf
/firmware/firmware.hex /firmware/firmware.hex

View File

@ -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 test: testbench.exe firmware/firmware.hex
vvp -N testbench.exe vvp -N testbench.exe
@ -22,15 +23,18 @@ firmware/firmware.bin: firmware/firmware.elf
riscv64-unknown-elf-objcopy -O binary $< $@ riscv64-unknown-elf-objcopy -O binary $< $@
chmod -x $@ 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 $@ \ riscv64-unknown-elf-gcc -Os -m32 -march=RV32I -ffreestanding -nostdlib -o $@ \
-Wl,-Bstatic,-T,firmware/sections.lds,-Map,firmware/firmware.map,--strip-debug \ -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 $@ chmod -x $@
firmware/start.o: firmware/start.S firmware/start.o: firmware/start.S
riscv64-unknown-elf-gcc -c -m32 -o $@ $< 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 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 $<)) \ 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 $< -DTEST_FUNC_TXT='"$(notdir $(basename $<))"' -DTEST_FUNC_RET=$(notdir $(basename $<))_ret $<

22
firmware/firmware.h Normal file
View File

@ -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

111
firmware/irq.c Normal file
View File

@ -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;
}

36
firmware/print.c Normal file
View File

@ -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];
}

View File

@ -1,12 +1,17 @@
// A simple Sieve of Eratosthenes // A simple Sieve of Eratosthenes
#include <stdint.h> #include "firmware.h"
#include <stdbool.h>
#define BITMAP_SIZE 64 #define BITMAP_SIZE 64
#define OUTPORT 0x10000000
static uint32_t bitmap[BITMAP_SIZE/32]; 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) static void bitmap_set(int idx)
{ {
@ -18,37 +23,6 @@ static bool bitmap_get(int idx)
return (bitmap[idx/32] & (1 << (idx % 32))) != 0; 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) static void print_prime(int idx, int val)
{ {
if (idx < 10) if (idx < 10)
@ -66,12 +40,16 @@ static void print_prime(int idx, int val)
print_str(" prime is "); print_str(" prime is ");
print_dec(val); print_dec(val);
print_str(".\n"); print_str(".\n");
hash = mkhash(hash, idx);
hash = mkhash(hash, val);
} }
void sieve() void sieve()
{ {
int i, j, k; int i, j, k;
int idx = 1; int idx = 1;
hash = 5381;
print_prime(idx++, 2); print_prime(idx++, 2);
for (i = 0; i < BITMAP_SIZE; i++) { for (i = 0; i < BITMAP_SIZE; i++) {
if (bitmap_get(i)) if (bitmap_get(i))
@ -86,113 +64,15 @@ void sieve()
bitmap_set(k); bitmap_set(k);
} }
} }
}
uint32_t *irq(uint32_t *regs, uint32_t irqs) print_str("checksum: ");
{ print_hex(hash);
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) { if (hash == 0x1772A48F) {
ext_irq_4_count++; print_str(" OK\n");
// 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 { } else {
print_str("Illegal Instruction at 0x"); print_str(" ERROR\n");
print_hex(pc); asm volatile ("sbreak");
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;
}

View File

@ -1,14 +1,6 @@
#include <stdint.h> #include "firmware.h"
#include <stdbool.h>
#define OUTPORT 0x10000000
static void print_str(const char *p) static void stats_print_dec(int val, int digits, bool zero_pad)
{
while (*p != 0)
*((volatile uint32_t*)OUTPORT) = *(p++);
}
static void print_dec(int val, int digits, bool zero_pad)
{ {
char buffer[32]; char buffer[32];
char *p = buffer; char *p = buffer;
@ -22,7 +14,7 @@ static void print_dec(int val, int digits, bool zero_pad)
} }
while (p != buffer) { while (p != buffer) {
if (p[-1] == ' ' && p[-2] == ' ') p[-1] = '.'; 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; int num_cycles, num_instr;
asm("rdcycle %0; rdinstret %1;" : "=r"(num_cycles), "=r"(num_instr)); asm("rdcycle %0; rdinstret %1;" : "=r"(num_cycles), "=r"(num_instr));
print_str("Cycle counter ........"); print_str("Cycle counter ........");
print_dec(num_cycles, 8, false); stats_print_dec(num_cycles, 8, false);
print_str("\nInstruction counter .."); print_str("\nInstruction counter ..");
print_dec(num_instr, 8, false); stats_print_dec(num_instr, 8, false);
print_str("\nCPI: "); print_str("\nCPI: ");
print_dec((num_cycles / num_instr), 0, false); stats_print_dec((num_cycles / num_instr), 0, false);
print_str("."); 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"); print_str("\n");
} }