aboutsummaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2015-06-06 14:01:37 +0200
committerClifford Wolf <clifford@clifford.at>2015-06-06 14:14:32 +0200
commit77ba5a18973bd02b461ab96047acfcc3fb62cf7b (patch)
tree573afedb6a3a14c91224e16724fa21ba3a939de2 /firmware
downloadpicorv32-77ba5a18973bd02b461ab96047acfcc3fb62cf7b.tar.gz
picorv32-77ba5a18973bd02b461ab96047acfcc3fb62cf7b.zip
Initial import
Diffstat (limited to 'firmware')
-rw-r--r--firmware/makehex.py17
-rw-r--r--firmware/sections.lds9
-rw-r--r--firmware/sieve.c78
-rw-r--r--firmware/start.S80
-rw-r--r--firmware/stats.c43
5 files changed, 227 insertions, 0 deletions
diff --git a/firmware/makehex.py b/firmware/makehex.py
new file mode 100644
index 0000000..a5ae740
--- /dev/null
+++ b/firmware/makehex.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python3
+
+from sys import argv
+
+with open(argv[1], "rb") as f:
+ bindata = f.read()
+
+assert len(bindata) < 60*1024
+assert len(bindata) % 4 == 0
+
+for i in range(64*1024//4):
+ if i < len(bindata) // 4:
+ w = bindata[4*i : 4*i+4]
+ print("%02x%02x%02x%02x" % (w[3], w[2], w[1], w[0]))
+ else:
+ print("0")
+
diff --git a/firmware/sections.lds b/firmware/sections.lds
new file mode 100644
index 0000000..5e6e40c
--- /dev/null
+++ b/firmware/sections.lds
@@ -0,0 +1,9 @@
+SECTIONS {
+ .memory : {
+ . = 0x000000;
+ start*(.text);
+ *(.text);
+ *(*);
+ end = .;
+ }
+}
diff --git a/firmware/sieve.c b/firmware/sieve.c
new file mode 100644
index 0000000..c3372f4
--- /dev/null
+++ b/firmware/sieve.c
@@ -0,0 +1,78 @@
+// A simple Sieve of Eratosthenes
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define BITMAP_SIZE 64
+#define OUTPORT 0x10000000
+
+static uint32_t bitmap[BITMAP_SIZE/32];
+
+static void bitmap_set(int idx)
+{
+ bitmap[idx/32] |= 1 << (idx % 32);
+}
+
+static bool bitmap_get(int idx)
+{
+ return (bitmap[idx/32] & (1 << (idx % 32))) != 0;
+}
+
+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++) = val % 10;
+ val = val / 10;
+ }
+ while (p != buffer) {
+ *((volatile uint32_t*)OUTPORT) = '0' + *(--p);
+ }
+}
+
+static void print_prime(int idx, int val)
+{
+ if (idx < 10)
+ print_str(" ");
+ print_dec(idx);
+ if (idx / 10 == 1)
+ goto force_th;
+ switch (idx % 10) {
+ case 1: print_str("st"); break;
+ case 2: print_str("nd"); break;
+ case 3: print_str("rd"); break;
+ force_th:
+ default: print_str("th"); break;
+ }
+ print_str(" prime is ");
+ print_dec(val);
+ print_str(".\n");
+}
+
+void sieve()
+{
+ int i, j, k;
+ int idx = 1;
+ print_prime(idx++, 2);
+ for (i = 0; i < BITMAP_SIZE; i++) {
+ if (bitmap_get(i))
+ continue;
+ print_prime(idx++, 3+2*i);
+ for (j = 2*(3+2*i);; j += 3+2*i) {
+ if (j%2 == 0)
+ continue;
+ k = (j-3)/2;
+ if (k >= BITMAP_SIZE)
+ break;
+ bitmap_set(k);
+ }
+ }
+}
+
diff --git a/firmware/start.S b/firmware/start.S
new file mode 100644
index 0000000..34e44d8
--- /dev/null
+++ b/firmware/start.S
@@ -0,0 +1,80 @@
+ .section .text
+ .global start
+ .global sieve
+ .global stats
+
+#define TEST(n) \
+ .global n; .global n ## _ret; \
+ jal zero,n; n ## _ret:
+
+start:
+ TEST(lui)
+ TEST(auipc)
+ TEST(j)
+ TEST(jal)
+ TEST(jalr)
+
+ TEST(beq)
+ TEST(bne)
+ TEST(blt)
+ TEST(bge)
+ TEST(bltu)
+ TEST(bgeu)
+
+ TEST(lb)
+ TEST(lh)
+ TEST(lw)
+ TEST(lbu)
+ TEST(lhu)
+
+ TEST(sb)
+ TEST(sh)
+ TEST(sw)
+
+ TEST(addi)
+ TEST(slti) // also tests sltiu
+ TEST(xori)
+ TEST(ori)
+ TEST(andi)
+ TEST(slli)
+ TEST(srli)
+ TEST(srai)
+
+ TEST(add)
+ TEST(sub)
+ TEST(sll)
+ TEST(slt) // what is with sltu ?
+ TEST(xor)
+ TEST(srl)
+ TEST(sra)
+ TEST(or)
+ TEST(and)
+
+ TEST(fence_i)
+ TEST(simple)
+
+ /* set stack pointer */
+ lui sp,(64*1024)>>12
+
+ /* jump to sieve C code */
+ jal ra,sieve
+
+ /* jump to stats C code */
+ jal ra,stats
+
+ /* print "DONE\n" */
+ lui a0,0x10000000>>12
+ addi a1,zero,'D'
+ addi a2,zero,'O'
+ addi a3,zero,'N'
+ addi a4,zero,'E'
+ addi a5,zero,'\n'
+ sw a1,0(a0)
+ sw a2,0(a0)
+ sw a3,0(a0)
+ sw a4,0(a0)
+ sw a5,0(a0)
+
+ /* break */
+ sbreak
+
diff --git a/firmware/stats.c b/firmware/stats.c
new file mode 100644
index 0000000..c7b1b8e
--- /dev/null
+++ b/firmware/stats.c
@@ -0,0 +1,43 @@
+#include <stdint.h>
+#include <stdbool.h>
+#define OUTPORT 0x10000000
+
+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)
+{
+ char buffer[32];
+ char *p = buffer;
+ while (val || digits > 0) {
+ if (val)
+ *(p++) = '0' + val % 10;
+ else
+ *(p++) = zero_pad ? '0' : ' ';
+ val = val / 10;
+ digits--;
+ }
+ while (p != buffer) {
+ if (p[-1] == ' ' && p[-2] == ' ') p[-1] = '.';
+ *((volatile uint32_t*)OUTPORT) = *(--p);
+ }
+}
+
+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);
+ print_str("\nInstruction counter ..");
+ print_dec(num_instr, 8, false);
+ print_str("\nCPI: ");
+ print_dec((num_cycles / num_instr), 0, false);
+ print_str(".");
+ print_dec(((100 * num_cycles) / num_instr) % 100, 2, true);
+ print_str("\n");
+}
+