mirror of https://github.com/YosysHQ/picorv32.git
180 lines
3.1 KiB
C
180 lines
3.1 KiB
C
// 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_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++) = 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)
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
void irq(uint32_t *regs, uint32_t irqnum)
|
|
{
|
|
static int ext_irq_count = 0;
|
|
static int timer_irq_count = 0;
|
|
|
|
if (irqnum == 0) {
|
|
ext_irq_count++;
|
|
// print_str("[EXT-IRQ]");
|
|
return;
|
|
}
|
|
|
|
if (irqnum == 1) {
|
|
timer_irq_count++;
|
|
// print_str("[TIMER-IRQ]");
|
|
return;
|
|
}
|
|
|
|
if (irqnum == 2)
|
|
{
|
|
int i, k;
|
|
uint32_t pc = regs[0] - 4;
|
|
uint32_t instr = *(uint32_t*)pc;
|
|
|
|
print_str("\n");
|
|
print_str("------------------------------------------------------------\n");
|
|
|
|
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");
|
|
}
|
|
|
|
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 external IRQs counted: ");
|
|
print_dec(ext_irq_count);
|
|
print_str("\n");
|
|
|
|
print_str("Number of timer IRQs counted: ");
|
|
print_dec(timer_irq_count);
|
|
print_str("\n");
|
|
|
|
__asm__("sbreak");
|
|
return;
|
|
}
|
|
}
|
|
|