Remove irq support.
This commit is contained in:
parent
2b3f3d3f3d
commit
ef6fb8848f
4
Makefile
4
Makefile
|
@ -12,7 +12,7 @@ IVERILOG = iverilog$(ICARUS_SUFFIX)
|
||||||
VVP = vvp$(ICARUS_SUFFIX)
|
VVP = vvp$(ICARUS_SUFFIX)
|
||||||
|
|
||||||
TEST_OBJS = $(addsuffix .o,$(basename $(wildcard tests/*.S)))
|
TEST_OBJS = $(addsuffix .o,$(basename $(wildcard tests/*.S)))
|
||||||
FIRMWARE_OBJS = build/start.o build/irq.o build/print.o build/hello.o build/sieve.o build/multest.o build/stats.o
|
FIRMWARE_OBJS = build/start.o build/print.o build/hello.o build/sieve.o build/multest.o build/stats.o
|
||||||
GCC_WARNS = -Werror -Wall -Wextra -Wshadow -Wundef -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings
|
GCC_WARNS = -Werror -Wall -Wextra -Wshadow -Wundef -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings
|
||||||
GCC_WARNS += -Wredundant-decls -Wstrict-prototypes -Wmissing-prototypes -pedantic # -Wconversion
|
GCC_WARNS += -Wredundant-decls -Wstrict-prototypes -Wmissing-prototypes -pedantic # -Wconversion
|
||||||
TOOLCHAIN_PREFIX = $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)/bin/riscv32-unknown-elf-
|
TOOLCHAIN_PREFIX = $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)/bin/riscv32-unknown-elf-
|
||||||
|
@ -25,7 +25,7 @@ test_verilator: build/testbench_verilator build/firmware.hex build/dhry.hex
|
||||||
cd build && ./testbench_verilator firmware.hex
|
cd build && ./testbench_verilator firmware.hex
|
||||||
cd build && ./testbench_verilator dhry.hex
|
cd build && ./testbench_verilator dhry.hex
|
||||||
|
|
||||||
firmware: build/testbench_verilator
|
firmware: build/testbench_verilator build/firmware.hex
|
||||||
cd build && ./testbench_verilator firmware.hex
|
cd build && ./testbench_verilator firmware.hex
|
||||||
|
|
||||||
dhry: build/firmware.hex build/dhry.hex
|
dhry: build/firmware.hex build/dhry.hex
|
||||||
|
|
|
@ -11,9 +11,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
// irq.c
|
|
||||||
uint32_t *irq(uint32_t *regs, uint32_t irqs);
|
|
||||||
|
|
||||||
// print.c
|
// print.c
|
||||||
void print_chr(char ch);
|
void print_chr(char ch);
|
||||||
void print_str(const char *p);
|
void print_str(const char *p);
|
||||||
|
|
140
firmware/irq.c
140
firmware/irq.c
|
@ -1,140 +0,0 @@
|
||||||
// This is free and unencumbered software released into the public domain.
|
|
||||||
//
|
|
||||||
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
||||||
// distribute this software, either in source code form or as a compiled
|
|
||||||
// binary, for any purpose, commercial or non-commercial, and by any
|
|
||||||
// means.
|
|
||||||
|
|
||||||
#include "firmware.h"
|
|
||||||
|
|
||||||
uint32_t *irq(uint32_t *regs, uint32_t irqs)
|
|
||||||
{
|
|
||||||
static unsigned int ext_irq_4_count = 0;
|
|
||||||
static unsigned int ext_irq_5_count = 0;
|
|
||||||
static unsigned int timer_irq_count = 0;
|
|
||||||
|
|
||||||
// checking compressed isa q0 reg handling
|
|
||||||
if ((irqs & 6) != 0) {
|
|
||||||
uint32_t pc = (regs[0] & 1) ? regs[0] - 3 : regs[0] - 4;
|
|
||||||
uint32_t instr = *(uint16_t*)pc;
|
|
||||||
|
|
||||||
if ((instr & 3) == 3)
|
|
||||||
instr = instr | (*(uint16_t*)(pc + 2)) << 16;
|
|
||||||
|
|
||||||
if (((instr & 3) != 3) != (regs[0] & 1)) {
|
|
||||||
print_str("Mismatch between q0 LSB and decoded instruction word! q0=0x");
|
|
||||||
print_hex(regs[0], 8);
|
|
||||||
print_str(", instr=0x");
|
|
||||||
if ((instr & 3) == 3)
|
|
||||||
print_hex(instr, 8);
|
|
||||||
else
|
|
||||||
print_hex(instr, 4);
|
|
||||||
print_str("\n");
|
|
||||||
__asm__ volatile ("ebreak");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
uint32_t pc = (regs[0] & 1) ? regs[0] - 3 : regs[0] - 4;
|
|
||||||
uint32_t instr = *(uint16_t*)pc;
|
|
||||||
|
|
||||||
if ((instr & 3) == 3)
|
|
||||||
instr = instr | (*(uint16_t*)(pc + 2)) << 16;
|
|
||||||
|
|
||||||
print_str("\n");
|
|
||||||
print_str("------------------------------------------------------------\n");
|
|
||||||
|
|
||||||
if ((irqs & 2) != 0) {
|
|
||||||
if (instr == 0x00100073 || instr == 0x9002) {
|
|
||||||
print_str("EBREAK instruction at 0x");
|
|
||||||
print_hex(pc, 8);
|
|
||||||
print_str("\n");
|
|
||||||
} else {
|
|
||||||
print_str("Illegal Instruction at 0x");
|
|
||||||
print_hex(pc, 8);
|
|
||||||
print_str(": 0x");
|
|
||||||
print_hex(instr, ((instr & 3) == 3) ? 8 : 4);
|
|
||||||
print_str("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((irqs & 4) != 0) {
|
|
||||||
print_str("Bus error in Instruction at 0x");
|
|
||||||
print_hex(pc, 8);
|
|
||||||
print_str(": 0x");
|
|
||||||
print_hex(instr, ((instr & 3) == 3) ? 8 : 4);
|
|
||||||
print_str("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
for (int 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], 8);
|
|
||||||
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__ volatile ("ebreak");
|
|
||||||
}
|
|
||||||
|
|
||||||
return regs;
|
|
||||||
}
|
|
||||||
|
|
309
firmware/start.S
309
firmware/start.S
|
@ -5,26 +5,14 @@
|
||||||
// binary, for any purpose, commercial or non-commercial, and by any
|
// binary, for any purpose, commercial or non-commercial, and by any
|
||||||
// means.
|
// means.
|
||||||
|
|
||||||
#define ENABLE_QREGS
|
|
||||||
#define ENABLE_HELLO
|
#define ENABLE_HELLO
|
||||||
#define ENABLE_RVTST
|
|
||||||
#define ENABLE_SIEVE
|
#define ENABLE_SIEVE
|
||||||
#define ENABLE_MULTST
|
#define ENABLE_MULTST
|
||||||
#define ENABLE_STATS
|
#define ENABLE_STATS
|
||||||
|
|
||||||
#ifndef ENABLE_QREGS
|
|
||||||
# undef ENABLE_RVTST
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Only save registers in IRQ wrapper that are to be saved by the caller in
|
|
||||||
// the RISC-V ABI, with the excpetion of the stack pointer. The IRQ handler
|
|
||||||
// will save the rest if necessary. I.e. skip x3, x4, x8, x9, and x18-x27.
|
|
||||||
#undef ENABLE_FASTIRQ
|
|
||||||
|
|
||||||
#include "custom_ops.S"
|
#include "custom_ops.S"
|
||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
.global irq
|
|
||||||
.global hello
|
.global hello
|
||||||
.global sieve
|
.global sieve
|
||||||
.global multest
|
.global multest
|
||||||
|
@ -39,305 +27,8 @@
|
||||||
.global stats
|
.global stats
|
||||||
|
|
||||||
reset_vec:
|
reset_vec:
|
||||||
// no more than 16 bytes here !
|
|
||||||
picorv32_waitirq_insn(zero)
|
|
||||||
picorv32_maskirq_insn(zero, zero)
|
|
||||||
j start
|
j start
|
||||||
|
|
||||||
|
|
||||||
/* Interrupt handler
|
|
||||||
**********************************/
|
|
||||||
|
|
||||||
.balign 16
|
|
||||||
irq_vec:
|
|
||||||
/* save registers */
|
|
||||||
|
|
||||||
#ifdef ENABLE_QREGS
|
|
||||||
|
|
||||||
picorv32_setq_insn(q2, x1)
|
|
||||||
picorv32_setq_insn(q3, x2)
|
|
||||||
|
|
||||||
lui x1, %hi(irq_regs)
|
|
||||||
addi x1, x1, %lo(irq_regs)
|
|
||||||
|
|
||||||
picorv32_getq_insn(x2, q0)
|
|
||||||
sw x2, 0*4(x1)
|
|
||||||
|
|
||||||
picorv32_getq_insn(x2, q2)
|
|
||||||
sw x2, 1*4(x1)
|
|
||||||
|
|
||||||
picorv32_getq_insn(x2, q3)
|
|
||||||
sw x2, 2*4(x1)
|
|
||||||
|
|
||||||
#ifdef ENABLE_FASTIRQ
|
|
||||||
sw x5, 5*4(x1)
|
|
||||||
sw x6, 6*4(x1)
|
|
||||||
sw x7, 7*4(x1)
|
|
||||||
sw x10, 10*4(x1)
|
|
||||||
sw x11, 11*4(x1)
|
|
||||||
sw x12, 12*4(x1)
|
|
||||||
sw x13, 13*4(x1)
|
|
||||||
sw x14, 14*4(x1)
|
|
||||||
sw x15, 15*4(x1)
|
|
||||||
sw x16, 16*4(x1)
|
|
||||||
sw x17, 17*4(x1)
|
|
||||||
sw x28, 28*4(x1)
|
|
||||||
sw x29, 29*4(x1)
|
|
||||||
sw x30, 30*4(x1)
|
|
||||||
sw x31, 31*4(x1)
|
|
||||||
#else
|
|
||||||
sw x3, 3*4(x1)
|
|
||||||
sw x4, 4*4(x1)
|
|
||||||
sw x5, 5*4(x1)
|
|
||||||
sw x6, 6*4(x1)
|
|
||||||
sw x7, 7*4(x1)
|
|
||||||
sw x8, 8*4(x1)
|
|
||||||
sw x9, 9*4(x1)
|
|
||||||
sw x10, 10*4(x1)
|
|
||||||
sw x11, 11*4(x1)
|
|
||||||
sw x12, 12*4(x1)
|
|
||||||
sw x13, 13*4(x1)
|
|
||||||
sw x14, 14*4(x1)
|
|
||||||
sw x15, 15*4(x1)
|
|
||||||
sw x16, 16*4(x1)
|
|
||||||
sw x17, 17*4(x1)
|
|
||||||
sw x18, 18*4(x1)
|
|
||||||
sw x19, 19*4(x1)
|
|
||||||
sw x20, 20*4(x1)
|
|
||||||
sw x21, 21*4(x1)
|
|
||||||
sw x22, 22*4(x1)
|
|
||||||
sw x23, 23*4(x1)
|
|
||||||
sw x24, 24*4(x1)
|
|
||||||
sw x25, 25*4(x1)
|
|
||||||
sw x26, 26*4(x1)
|
|
||||||
sw x27, 27*4(x1)
|
|
||||||
sw x28, 28*4(x1)
|
|
||||||
sw x29, 29*4(x1)
|
|
||||||
sw x30, 30*4(x1)
|
|
||||||
sw x31, 31*4(x1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else // ENABLE_QREGS
|
|
||||||
|
|
||||||
#ifdef ENABLE_FASTIRQ
|
|
||||||
sw gp, 0*4+0x200(zero)
|
|
||||||
sw x1, 1*4+0x200(zero)
|
|
||||||
sw x2, 2*4+0x200(zero)
|
|
||||||
sw x5, 5*4+0x200(zero)
|
|
||||||
sw x6, 6*4+0x200(zero)
|
|
||||||
sw x7, 7*4+0x200(zero)
|
|
||||||
sw x10, 10*4+0x200(zero)
|
|
||||||
sw x11, 11*4+0x200(zero)
|
|
||||||
sw x12, 12*4+0x200(zero)
|
|
||||||
sw x13, 13*4+0x200(zero)
|
|
||||||
sw x14, 14*4+0x200(zero)
|
|
||||||
sw x15, 15*4+0x200(zero)
|
|
||||||
sw x16, 16*4+0x200(zero)
|
|
||||||
sw x17, 17*4+0x200(zero)
|
|
||||||
sw x28, 28*4+0x200(zero)
|
|
||||||
sw x29, 29*4+0x200(zero)
|
|
||||||
sw x30, 30*4+0x200(zero)
|
|
||||||
sw x31, 31*4+0x200(zero)
|
|
||||||
#else
|
|
||||||
sw gp, 0*4+0x200(zero)
|
|
||||||
sw x1, 1*4+0x200(zero)
|
|
||||||
sw x2, 2*4+0x200(zero)
|
|
||||||
sw x3, 3*4+0x200(zero)
|
|
||||||
sw x4, 4*4+0x200(zero)
|
|
||||||
sw x5, 5*4+0x200(zero)
|
|
||||||
sw x6, 6*4+0x200(zero)
|
|
||||||
sw x7, 7*4+0x200(zero)
|
|
||||||
sw x8, 8*4+0x200(zero)
|
|
||||||
sw x9, 9*4+0x200(zero)
|
|
||||||
sw x10, 10*4+0x200(zero)
|
|
||||||
sw x11, 11*4+0x200(zero)
|
|
||||||
sw x12, 12*4+0x200(zero)
|
|
||||||
sw x13, 13*4+0x200(zero)
|
|
||||||
sw x14, 14*4+0x200(zero)
|
|
||||||
sw x15, 15*4+0x200(zero)
|
|
||||||
sw x16, 16*4+0x200(zero)
|
|
||||||
sw x17, 17*4+0x200(zero)
|
|
||||||
sw x18, 18*4+0x200(zero)
|
|
||||||
sw x19, 19*4+0x200(zero)
|
|
||||||
sw x20, 20*4+0x200(zero)
|
|
||||||
sw x21, 21*4+0x200(zero)
|
|
||||||
sw x22, 22*4+0x200(zero)
|
|
||||||
sw x23, 23*4+0x200(zero)
|
|
||||||
sw x24, 24*4+0x200(zero)
|
|
||||||
sw x25, 25*4+0x200(zero)
|
|
||||||
sw x26, 26*4+0x200(zero)
|
|
||||||
sw x27, 27*4+0x200(zero)
|
|
||||||
sw x28, 28*4+0x200(zero)
|
|
||||||
sw x29, 29*4+0x200(zero)
|
|
||||||
sw x30, 30*4+0x200(zero)
|
|
||||||
sw x31, 31*4+0x200(zero)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // ENABLE_QREGS
|
|
||||||
|
|
||||||
/* call interrupt handler C function */
|
|
||||||
|
|
||||||
lui sp, %hi(irq_stack)
|
|
||||||
addi sp, sp, %lo(irq_stack)
|
|
||||||
|
|
||||||
// arg0 = address of regs
|
|
||||||
lui a0, %hi(irq_regs)
|
|
||||||
addi a0, a0, %lo(irq_regs)
|
|
||||||
|
|
||||||
// arg1 = interrupt type
|
|
||||||
#ifdef ENABLE_QREGS
|
|
||||||
picorv32_getq_insn(a1, q1)
|
|
||||||
#else
|
|
||||||
addi a1, tp, 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// call to C function
|
|
||||||
jal ra, irq
|
|
||||||
|
|
||||||
/* restore registers */
|
|
||||||
|
|
||||||
#ifdef ENABLE_QREGS
|
|
||||||
|
|
||||||
// new irq_regs address returned from C code in a0
|
|
||||||
addi x1, a0, 0
|
|
||||||
|
|
||||||
lw x2, 0*4(x1)
|
|
||||||
picorv32_setq_insn(q0, x2)
|
|
||||||
|
|
||||||
lw x2, 1*4(x1)
|
|
||||||
picorv32_setq_insn(q1, x2)
|
|
||||||
|
|
||||||
lw x2, 2*4(x1)
|
|
||||||
picorv32_setq_insn(q2, x2)
|
|
||||||
|
|
||||||
#ifdef ENABLE_FASTIRQ
|
|
||||||
lw x5, 5*4(x1)
|
|
||||||
lw x6, 6*4(x1)
|
|
||||||
lw x7, 7*4(x1)
|
|
||||||
lw x10, 10*4(x1)
|
|
||||||
lw x11, 11*4(x1)
|
|
||||||
lw x12, 12*4(x1)
|
|
||||||
lw x13, 13*4(x1)
|
|
||||||
lw x14, 14*4(x1)
|
|
||||||
lw x15, 15*4(x1)
|
|
||||||
lw x16, 16*4(x1)
|
|
||||||
lw x17, 17*4(x1)
|
|
||||||
lw x28, 28*4(x1)
|
|
||||||
lw x29, 29*4(x1)
|
|
||||||
lw x30, 30*4(x1)
|
|
||||||
lw x31, 31*4(x1)
|
|
||||||
#else
|
|
||||||
lw x3, 3*4(x1)
|
|
||||||
lw x4, 4*4(x1)
|
|
||||||
lw x5, 5*4(x1)
|
|
||||||
lw x6, 6*4(x1)
|
|
||||||
lw x7, 7*4(x1)
|
|
||||||
lw x8, 8*4(x1)
|
|
||||||
lw x9, 9*4(x1)
|
|
||||||
lw x10, 10*4(x1)
|
|
||||||
lw x11, 11*4(x1)
|
|
||||||
lw x12, 12*4(x1)
|
|
||||||
lw x13, 13*4(x1)
|
|
||||||
lw x14, 14*4(x1)
|
|
||||||
lw x15, 15*4(x1)
|
|
||||||
lw x16, 16*4(x1)
|
|
||||||
lw x17, 17*4(x1)
|
|
||||||
lw x18, 18*4(x1)
|
|
||||||
lw x19, 19*4(x1)
|
|
||||||
lw x20, 20*4(x1)
|
|
||||||
lw x21, 21*4(x1)
|
|
||||||
lw x22, 22*4(x1)
|
|
||||||
lw x23, 23*4(x1)
|
|
||||||
lw x24, 24*4(x1)
|
|
||||||
lw x25, 25*4(x1)
|
|
||||||
lw x26, 26*4(x1)
|
|
||||||
lw x27, 27*4(x1)
|
|
||||||
lw x28, 28*4(x1)
|
|
||||||
lw x29, 29*4(x1)
|
|
||||||
lw x30, 30*4(x1)
|
|
||||||
lw x31, 31*4(x1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
picorv32_getq_insn(x1, q1)
|
|
||||||
picorv32_getq_insn(x2, q2)
|
|
||||||
|
|
||||||
#else // ENABLE_QREGS
|
|
||||||
|
|
||||||
// new irq_regs address returned from C code in a0
|
|
||||||
addi a1, zero, 0x200
|
|
||||||
beq a0, a1, 1f
|
|
||||||
ebreak
|
|
||||||
1:
|
|
||||||
|
|
||||||
#ifdef ENABLE_FASTIRQ
|
|
||||||
lw gp, 0*4+0x200(zero)
|
|
||||||
lw x1, 1*4+0x200(zero)
|
|
||||||
lw x2, 2*4+0x200(zero)
|
|
||||||
lw x5, 5*4+0x200(zero)
|
|
||||||
lw x6, 6*4+0x200(zero)
|
|
||||||
lw x7, 7*4+0x200(zero)
|
|
||||||
lw x10, 10*4+0x200(zero)
|
|
||||||
lw x11, 11*4+0x200(zero)
|
|
||||||
lw x12, 12*4+0x200(zero)
|
|
||||||
lw x13, 13*4+0x200(zero)
|
|
||||||
lw x14, 14*4+0x200(zero)
|
|
||||||
lw x15, 15*4+0x200(zero)
|
|
||||||
lw x16, 16*4+0x200(zero)
|
|
||||||
lw x17, 17*4+0x200(zero)
|
|
||||||
lw x28, 28*4+0x200(zero)
|
|
||||||
lw x29, 29*4+0x200(zero)
|
|
||||||
lw x30, 30*4+0x200(zero)
|
|
||||||
lw x31, 31*4+0x200(zero)
|
|
||||||
#else
|
|
||||||
lw gp, 0*4+0x200(zero)
|
|
||||||
lw x1, 1*4+0x200(zero)
|
|
||||||
lw x2, 2*4+0x200(zero)
|
|
||||||
// do not restore x3 (gp)
|
|
||||||
lw x4, 4*4+0x200(zero)
|
|
||||||
lw x5, 5*4+0x200(zero)
|
|
||||||
lw x6, 6*4+0x200(zero)
|
|
||||||
lw x7, 7*4+0x200(zero)
|
|
||||||
lw x8, 8*4+0x200(zero)
|
|
||||||
lw x9, 9*4+0x200(zero)
|
|
||||||
lw x10, 10*4+0x200(zero)
|
|
||||||
lw x11, 11*4+0x200(zero)
|
|
||||||
lw x12, 12*4+0x200(zero)
|
|
||||||
lw x13, 13*4+0x200(zero)
|
|
||||||
lw x14, 14*4+0x200(zero)
|
|
||||||
lw x15, 15*4+0x200(zero)
|
|
||||||
lw x16, 16*4+0x200(zero)
|
|
||||||
lw x17, 17*4+0x200(zero)
|
|
||||||
lw x18, 18*4+0x200(zero)
|
|
||||||
lw x19, 19*4+0x200(zero)
|
|
||||||
lw x20, 20*4+0x200(zero)
|
|
||||||
lw x21, 21*4+0x200(zero)
|
|
||||||
lw x22, 22*4+0x200(zero)
|
|
||||||
lw x23, 23*4+0x200(zero)
|
|
||||||
lw x24, 24*4+0x200(zero)
|
|
||||||
lw x25, 25*4+0x200(zero)
|
|
||||||
lw x26, 26*4+0x200(zero)
|
|
||||||
lw x27, 27*4+0x200(zero)
|
|
||||||
lw x28, 28*4+0x200(zero)
|
|
||||||
lw x29, 29*4+0x200(zero)
|
|
||||||
lw x30, 30*4+0x200(zero)
|
|
||||||
lw x31, 31*4+0x200(zero)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // ENABLE_QREGS
|
|
||||||
|
|
||||||
picorv32_retirq_insn()
|
|
||||||
|
|
||||||
.balign 0x200
|
|
||||||
irq_regs:
|
|
||||||
// registers are saved to this memory region during interrupt handling
|
|
||||||
// the program counter is saved as register 0
|
|
||||||
.fill 32,4
|
|
||||||
|
|
||||||
// stack for the interrupt handler
|
|
||||||
.fill 128,4
|
|
||||||
irq_stack:
|
|
||||||
|
|
||||||
|
|
||||||
/* Main program
|
/* Main program
|
||||||
**********************************/
|
**********************************/
|
||||||
|
|
||||||
|
|
193
picorv32.v
193
picorv32.v
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
`timescale 1 ns / 1 ps
|
`timescale 1 ns / 1 ps
|
||||||
// `default_nettype none
|
// `default_nettype none
|
||||||
|
// `define DEBUG
|
||||||
|
|
||||||
`ifdef DEBUG
|
`ifdef DEBUG
|
||||||
`define debug(debug_command) debug_command
|
`define debug(debug_command) debug_command
|
||||||
|
@ -40,10 +41,7 @@
|
||||||
|
|
||||||
module picorv32 #(
|
module picorv32 #(
|
||||||
parameter [0:0] ENABLE_TRACE = 0,
|
parameter [0:0] ENABLE_TRACE = 0,
|
||||||
parameter [31:0] MASKED_IRQ = 32'h0000_0000,
|
|
||||||
parameter [31:0] LATCHED_IRQ = 32'hffff_ffff,
|
|
||||||
parameter [31:0] PROGADDR_RESET = 32'h0000_0000,
|
parameter [31:0] PROGADDR_RESET = 32'h0000_0000,
|
||||||
parameter [31:0] PROGADDR_IRQ = 32'h0000_0010,
|
|
||||||
parameter [31:0] STACKADDR = 32'hffff_ffff
|
parameter [31:0] STACKADDR = 32'hffff_ffff
|
||||||
) (
|
) (
|
||||||
input clk,
|
input clk,
|
||||||
|
@ -76,10 +74,6 @@ module picorv32 #(
|
||||||
input pcpi_wait,
|
input pcpi_wait,
|
||||||
input pcpi_ready,
|
input pcpi_ready,
|
||||||
|
|
||||||
// IRQ Interface
|
|
||||||
input [31:0] irq,
|
|
||||||
output reg [31:0] eoi,
|
|
||||||
|
|
||||||
// Trace Interface
|
// Trace Interface
|
||||||
output reg trace_valid,
|
output reg trace_valid,
|
||||||
output reg [35:0] trace_data,
|
output reg [35:0] trace_data,
|
||||||
|
@ -90,16 +84,11 @@ module picorv32 #(
|
||||||
output reg [31:0] dbg_insn_addr,
|
output reg [31:0] dbg_insn_addr,
|
||||||
output reg [63:0] dbg_ascii_instr
|
output reg [63:0] dbg_ascii_instr
|
||||||
);
|
);
|
||||||
localparam integer irq_timer = 0;
|
|
||||||
localparam integer irq_ebreak = 1;
|
|
||||||
localparam integer irq_buserror = 2;
|
|
||||||
|
|
||||||
localparam integer irqregs_offset = 32;
|
localparam integer regfile_size = 32;
|
||||||
localparam integer regfile_size = 32 + 4;
|
localparam integer regindex_bits = 5;
|
||||||
localparam integer regindex_bits = 5 + 1;
|
|
||||||
localparam [35:0] TRACE_BRANCH = {4'b0001, 32'b0};
|
localparam [35:0] TRACE_BRANCH = {4'b0001, 32'b0};
|
||||||
localparam [35:0] TRACE_ADDR = {4'b0010, 32'b0};
|
localparam [35:0] TRACE_ADDR = {4'b0010, 32'b0};
|
||||||
localparam [35:0] TRACE_IRQ = {4'b1000, 32'b0};
|
|
||||||
|
|
||||||
reg [63:0] count_cycle, count_instr;
|
reg [63:0] count_cycle, count_instr;
|
||||||
reg [31:0] reg_pc, reg_next_pc, reg_op1, reg_op2, reg_out;
|
reg [31:0] reg_pc, reg_next_pc, reg_op1, reg_op2, reg_out;
|
||||||
|
@ -120,12 +109,6 @@ module picorv32 #(
|
||||||
|
|
||||||
wire [31:0] next_pc;
|
wire [31:0] next_pc;
|
||||||
|
|
||||||
reg irq_delay;
|
|
||||||
reg irq_active;
|
|
||||||
reg [31:0] irq_mask;
|
|
||||||
reg [31:0] irq_pending;
|
|
||||||
reg [31:0] timer;
|
|
||||||
|
|
||||||
task empty_statement;
|
task empty_statement;
|
||||||
// This task is used by the `assert directive in non-formal mode to
|
// This task is used by the `assert directive in non-formal mode to
|
||||||
// avoid empty statement (which are unsupported by plain Verilog syntax).
|
// avoid empty statement (which are unsupported by plain Verilog syntax).
|
||||||
|
@ -362,7 +345,6 @@ module picorv32 #(
|
||||||
reg instr_add, instr_sub, instr_sll, instr_slt, instr_sltu;
|
reg instr_add, instr_sub, instr_sll, instr_slt, instr_sltu;
|
||||||
reg instr_xor, instr_srl, instr_sra, instr_or, instr_and;
|
reg instr_xor, instr_srl, instr_sra, instr_or, instr_and;
|
||||||
reg instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh, instr_ecall_ebreak;
|
reg instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh, instr_ecall_ebreak;
|
||||||
reg instr_getq, instr_setq, instr_retirq, instr_maskirq, instr_waitirq, instr_timer;
|
|
||||||
wire instr_trap;
|
wire instr_trap;
|
||||||
|
|
||||||
reg [regindex_bits-1:0] decoded_rd, decoded_rs1, decoded_rs2;
|
reg [regindex_bits-1:0] decoded_rd, decoded_rs1, decoded_rs2;
|
||||||
|
@ -392,8 +374,7 @@ module picorv32 #(
|
||||||
instr_lb, instr_lh, instr_lw, instr_lbu, instr_lhu, instr_sb, instr_sh, instr_sw,
|
instr_lb, instr_lh, instr_lw, instr_lbu, instr_lhu, instr_sb, instr_sh, instr_sw,
|
||||||
instr_addi, instr_slti, instr_sltiu, instr_xori, instr_ori, instr_andi, instr_slli, instr_srli, instr_srai,
|
instr_addi, instr_slti, instr_sltiu, instr_xori, instr_ori, instr_andi, instr_slli, instr_srli, instr_srai,
|
||||||
instr_add, instr_sub, instr_sll, instr_slt, instr_sltu, instr_xor, instr_srl, instr_sra, instr_or, instr_and,
|
instr_add, instr_sub, instr_sll, instr_slt, instr_sltu, instr_xor, instr_srl, instr_sra, instr_or, instr_and,
|
||||||
instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh,
|
instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh};
|
||||||
instr_getq, instr_setq, instr_retirq, instr_maskirq, instr_waitirq, instr_timer};
|
|
||||||
|
|
||||||
wire is_rdcycle_rdcycleh_rdinstr_rdinstrh;
|
wire is_rdcycle_rdcycleh_rdinstr_rdinstrh;
|
||||||
assign is_rdcycle_rdcycleh_rdinstr_rdinstrh = |{instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh};
|
assign is_rdcycle_rdcycleh_rdinstr_rdinstrh = |{instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh};
|
||||||
|
@ -461,12 +442,6 @@ module picorv32 #(
|
||||||
if (instr_rdinstr) new_ascii_instr = "rdinstr";
|
if (instr_rdinstr) new_ascii_instr = "rdinstr";
|
||||||
if (instr_rdinstrh) new_ascii_instr = "rdinstrh";
|
if (instr_rdinstrh) new_ascii_instr = "rdinstrh";
|
||||||
|
|
||||||
if (instr_getq) new_ascii_instr = "getq";
|
|
||||||
if (instr_setq) new_ascii_instr = "setq";
|
|
||||||
if (instr_retirq) new_ascii_instr = "retirq";
|
|
||||||
if (instr_maskirq) new_ascii_instr = "maskirq";
|
|
||||||
if (instr_waitirq) new_ascii_instr = "waitirq";
|
|
||||||
if (instr_timer) new_ascii_instr = "timer";
|
|
||||||
end
|
end
|
||||||
|
|
||||||
reg [63:0] q_ascii_instr;
|
reg [63:0] q_ascii_instr;
|
||||||
|
@ -554,8 +529,6 @@ module picorv32 #(
|
||||||
instr_auipc <= mem_rdata_latched[6:0] == 7'b0010111;
|
instr_auipc <= mem_rdata_latched[6:0] == 7'b0010111;
|
||||||
instr_jal <= mem_rdata_latched[6:0] == 7'b1101111;
|
instr_jal <= mem_rdata_latched[6:0] == 7'b1101111;
|
||||||
instr_jalr <= mem_rdata_latched[6:0] == 7'b1100111 && mem_rdata_latched[14:12] == 3'b000;
|
instr_jalr <= mem_rdata_latched[6:0] == 7'b1100111 && mem_rdata_latched[14:12] == 3'b000;
|
||||||
instr_retirq <= mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000010;
|
|
||||||
instr_waitirq <= mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000100;
|
|
||||||
|
|
||||||
is_beq_bne_blt_bge_bltu_bgeu <= mem_rdata_latched[6:0] == 7'b1100011;
|
is_beq_bne_blt_bge_bltu_bgeu <= mem_rdata_latched[6:0] == 7'b1100011;
|
||||||
is_lb_lh_lw_lbu_lhu <= mem_rdata_latched[6:0] == 7'b0000011;
|
is_lb_lh_lw_lbu_lhu <= mem_rdata_latched[6:0] == 7'b0000011;
|
||||||
|
@ -570,12 +543,6 @@ module picorv32 #(
|
||||||
decoded_rd <= mem_rdata_latched[11:7];
|
decoded_rd <= mem_rdata_latched[11:7];
|
||||||
decoded_rs1 <= mem_rdata_latched[19:15];
|
decoded_rs1 <= mem_rdata_latched[19:15];
|
||||||
decoded_rs2 <= mem_rdata_latched[24:20];
|
decoded_rs2 <= mem_rdata_latched[24:20];
|
||||||
|
|
||||||
if (mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000000)
|
|
||||||
decoded_rs1[regindex_bits-1] <= 1; // instr_getq
|
|
||||||
|
|
||||||
if (mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000010)
|
|
||||||
decoded_rs1 <= irqregs_offset; // instr_retirq
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if (decoder_trigger && !decoder_pseudo_trigger) begin
|
if (decoder_trigger && !decoder_pseudo_trigger) begin
|
||||||
|
@ -629,11 +596,6 @@ module picorv32 #(
|
||||||
|
|
||||||
instr_ecall_ebreak <= (mem_rdata_q[6:0] == 7'b1110011 && !mem_rdata_q[31:21] && !mem_rdata_q[19:7]);
|
instr_ecall_ebreak <= (mem_rdata_q[6:0] == 7'b1110011 && !mem_rdata_q[31:21] && !mem_rdata_q[19:7]);
|
||||||
|
|
||||||
instr_getq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000000;
|
|
||||||
instr_setq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000001;
|
|
||||||
instr_maskirq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000011;
|
|
||||||
instr_timer <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000101;
|
|
||||||
|
|
||||||
is_slli_srli_srai <= is_alu_reg_imm && |{
|
is_slli_srli_srai <= is_alu_reg_imm && |{
|
||||||
mem_rdata_q[14:12] == 3'b001 && mem_rdata_q[31:25] == 7'b0000000,
|
mem_rdata_q[14:12] == 3'b001 && mem_rdata_q[31:25] == 7'b0000000,
|
||||||
mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0000000,
|
mem_rdata_q[14:12] == 3'b101 && mem_rdata_q[31:25] == 7'b0000000,
|
||||||
|
@ -717,7 +679,6 @@ module picorv32 #(
|
||||||
localparam cpu_state_ldmem = 8'b00000001;
|
localparam cpu_state_ldmem = 8'b00000001;
|
||||||
|
|
||||||
reg [7:0] cpu_state;
|
reg [7:0] cpu_state;
|
||||||
reg [1:0] irq_state;
|
|
||||||
|
|
||||||
always @* begin
|
always @* begin
|
||||||
dbg_ascii_state = "";
|
dbg_ascii_state = "";
|
||||||
|
@ -750,9 +711,6 @@ module picorv32 #(
|
||||||
reg [3:0] pcpi_timeout_counter;
|
reg [3:0] pcpi_timeout_counter;
|
||||||
reg pcpi_timeout;
|
reg pcpi_timeout;
|
||||||
|
|
||||||
reg [31:0] next_irq_pending;
|
|
||||||
reg do_waitirq;
|
|
||||||
|
|
||||||
reg [31:0] alu_out, alu_out_q;
|
reg [31:0] alu_out, alu_out_q;
|
||||||
reg alu_out_0, alu_out_0_q;
|
reg alu_out_0, alu_out_0_q;
|
||||||
|
|
||||||
|
@ -815,14 +773,6 @@ module picorv32 #(
|
||||||
cpuregs_wrdata = latched_stalu ? alu_out_q : reg_out;
|
cpuregs_wrdata = latched_stalu ? alu_out_q : reg_out;
|
||||||
cpuregs_write = 1;
|
cpuregs_write = 1;
|
||||||
end
|
end
|
||||||
irq_state[0]: begin
|
|
||||||
cpuregs_wrdata = reg_next_pc;
|
|
||||||
cpuregs_write = 1;
|
|
||||||
end
|
|
||||||
irq_state[1]: begin
|
|
||||||
cpuregs_wrdata = irq_pending & ~irq_mask;
|
|
||||||
cpuregs_write = 1;
|
|
||||||
end
|
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -851,7 +801,7 @@ module picorv32 #(
|
||||||
cpuregs_rs2 = decoded_rs2 ? cpuregs_rdata2 : 0;
|
cpuregs_rs2 = decoded_rs2 ? cpuregs_rdata2 : 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
assign launch_next_insn = cpu_state == cpu_state_fetch && decoder_trigger && (irq_delay || irq_active || !(irq_pending & ~irq_mask));
|
assign launch_next_insn = cpu_state == cpu_state_fetch && decoder_trigger;
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
trap <= 0;
|
trap <= 0;
|
||||||
|
@ -875,18 +825,12 @@ module picorv32 #(
|
||||||
if (pcpi_timeout_counter) pcpi_timeout_counter <= pcpi_timeout_counter - 1;
|
if (pcpi_timeout_counter) pcpi_timeout_counter <= pcpi_timeout_counter - 1;
|
||||||
end else pcpi_timeout_counter <= ~0;
|
end else pcpi_timeout_counter <= ~0;
|
||||||
pcpi_timeout <= !pcpi_timeout_counter;
|
pcpi_timeout <= !pcpi_timeout_counter;
|
||||||
count_cycle <= resetn ? count_cycle + 1 : 0;
|
count_cycle <= resetn ? count_cycle + 1 : 0;
|
||||||
next_irq_pending = irq_pending & LATCHED_IRQ;
|
|
||||||
|
|
||||||
if (timer) begin
|
|
||||||
timer <= timer - 1;
|
|
||||||
end
|
|
||||||
|
|
||||||
decoder_trigger <= mem_do_rinst && mem_done;
|
decoder_trigger <= mem_do_rinst && mem_done;
|
||||||
decoder_trigger_q <= decoder_trigger;
|
decoder_trigger_q <= decoder_trigger;
|
||||||
decoder_pseudo_trigger <= 0;
|
decoder_pseudo_trigger <= 0;
|
||||||
decoder_pseudo_trigger_q <= decoder_pseudo_trigger;
|
decoder_pseudo_trigger_q <= decoder_pseudo_trigger;
|
||||||
do_waitirq <= 0;
|
|
||||||
|
|
||||||
trace_valid <= 0;
|
trace_valid <= 0;
|
||||||
|
|
||||||
|
@ -905,13 +849,6 @@ module picorv32 #(
|
||||||
latched_is_lb <= 0;
|
latched_is_lb <= 0;
|
||||||
pcpi_valid <= 0;
|
pcpi_valid <= 0;
|
||||||
pcpi_timeout <= 0;
|
pcpi_timeout <= 0;
|
||||||
irq_active <= 0;
|
|
||||||
irq_delay <= 0;
|
|
||||||
irq_mask <= ~0;
|
|
||||||
next_irq_pending = 0;
|
|
||||||
irq_state <= 0;
|
|
||||||
eoi <= 0;
|
|
||||||
timer <= 0;
|
|
||||||
if (~STACKADDR) begin
|
if (~STACKADDR) begin
|
||||||
latched_store <= 1;
|
latched_store <= 1;
|
||||||
latched_rd <= 2;
|
latched_rd <= 2;
|
||||||
|
@ -925,7 +862,7 @@ module picorv32 #(
|
||||||
end
|
end
|
||||||
|
|
||||||
cpu_state_fetch: begin
|
cpu_state_fetch: begin
|
||||||
mem_do_rinst <= !decoder_trigger && !do_waitirq;
|
mem_do_rinst <= !decoder_trigger;
|
||||||
mem_wordsize <= 0;
|
mem_wordsize <= 0;
|
||||||
|
|
||||||
current_pc = reg_next_pc;
|
current_pc = reg_next_pc;
|
||||||
|
@ -941,23 +878,13 @@ module picorv32 #(
|
||||||
`debug($display("ST_RD: %2d 0x%08x", latched_rd, latched_stalu ? alu_out_q : reg_out
|
`debug($display("ST_RD: %2d 0x%08x", latched_rd, latched_stalu ? alu_out_q : reg_out
|
||||||
);)
|
);)
|
||||||
end
|
end
|
||||||
irq_state[0]: begin
|
|
||||||
current_pc = PROGADDR_IRQ;
|
|
||||||
irq_active <= 1;
|
|
||||||
mem_do_rinst <= 1;
|
|
||||||
end
|
|
||||||
irq_state[1]: begin
|
|
||||||
eoi <= irq_pending & ~irq_mask;
|
|
||||||
next_irq_pending = next_irq_pending & irq_mask;
|
|
||||||
end
|
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
if (ENABLE_TRACE && latched_trace) begin
|
if (ENABLE_TRACE && latched_trace) begin
|
||||||
latched_trace <= 0;
|
latched_trace <= 0;
|
||||||
trace_valid <= 1;
|
trace_valid <= 1;
|
||||||
if (latched_branch)
|
if (latched_branch) trace_data <= TRACE_BRANCH | (current_pc & 32'hfffffffe);
|
||||||
trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_BRANCH | (current_pc & 32'hfffffffe);
|
else trace_data <= latched_stalu ? alu_out_q : reg_out;
|
||||||
else trace_data <= (irq_active ? TRACE_IRQ : 0) | (latched_stalu ? alu_out_q : reg_out);
|
|
||||||
end
|
end
|
||||||
|
|
||||||
reg_pc <= current_pc;
|
reg_pc <= current_pc;
|
||||||
|
@ -971,19 +898,8 @@ module picorv32 #(
|
||||||
latched_is_lb <= 0;
|
latched_is_lb <= 0;
|
||||||
latched_rd <= decoded_rd;
|
latched_rd <= decoded_rd;
|
||||||
|
|
||||||
if (((decoder_trigger && !irq_active && !irq_delay && |(irq_pending & ~irq_mask)) || irq_state)) begin
|
if (decoder_trigger) begin
|
||||||
irq_state <= irq_state == 2'b00 ? 2'b01 : irq_state == 2'b01 ? 2'b10 : 2'b00;
|
|
||||||
latched_rd <= irqregs_offset | irq_state[0];
|
|
||||||
end else if ((decoder_trigger || do_waitirq) && instr_waitirq) begin
|
|
||||||
if (irq_pending) begin
|
|
||||||
latched_store <= 1;
|
|
||||||
reg_out <= irq_pending;
|
|
||||||
reg_next_pc <= current_pc + 4;
|
|
||||||
mem_do_rinst <= 1;
|
|
||||||
end else do_waitirq <= 1;
|
|
||||||
end else if (decoder_trigger) begin
|
|
||||||
`debug($display("-- %-0t", $time);)
|
`debug($display("-- %-0t", $time);)
|
||||||
irq_delay <= irq_active;
|
|
||||||
reg_next_pc <= current_pc + 4;
|
reg_next_pc <= current_pc + 4;
|
||||||
if (ENABLE_TRACE) latched_trace <= 1;
|
if (ENABLE_TRACE) latched_trace <= 1;
|
||||||
count_instr <= count_instr + 1;
|
count_instr <= count_instr + 1;
|
||||||
|
@ -993,7 +909,7 @@ module picorv32 #(
|
||||||
latched_branch <= 1;
|
latched_branch <= 1;
|
||||||
end else begin
|
end else begin
|
||||||
mem_do_rinst <= 0;
|
mem_do_rinst <= 0;
|
||||||
mem_do_prefetch <= !instr_jalr && !instr_retirq;
|
mem_do_prefetch <= !instr_jalr;
|
||||||
cpu_state <= cpu_state_ld_rs1;
|
cpu_state <= cpu_state_ld_rs1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1025,10 +941,7 @@ module picorv32 #(
|
||||||
end else if (pcpi_timeout || instr_ecall_ebreak) begin
|
end else if (pcpi_timeout || instr_ecall_ebreak) begin
|
||||||
pcpi_valid <= 0;
|
pcpi_valid <= 0;
|
||||||
`debug($display("EBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);)
|
`debug($display("EBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);)
|
||||||
if (!irq_mask[irq_ebreak] && !irq_active) begin
|
cpu_state <= cpu_state_trap;
|
||||||
next_irq_pending[irq_ebreak] = 1;
|
|
||||||
cpu_state <= cpu_state_fetch;
|
|
||||||
end else cpu_state <= cpu_state_trap;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
is_rdcycle_rdcycleh_rdinstr_rdinstrh: begin
|
is_rdcycle_rdcycleh_rdinstr_rdinstrh: begin
|
||||||
|
@ -1048,52 +961,6 @@ module picorv32 #(
|
||||||
mem_do_rinst <= mem_do_prefetch;
|
mem_do_rinst <= mem_do_prefetch;
|
||||||
cpu_state <= cpu_state_exec;
|
cpu_state <= cpu_state_exec;
|
||||||
end
|
end
|
||||||
instr_getq: begin
|
|
||||||
`debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);)
|
|
||||||
reg_out <= cpuregs_rs1;
|
|
||||||
dbg_rs1val <= cpuregs_rs1;
|
|
||||||
dbg_rs1val_valid <= 1;
|
|
||||||
latched_store <= 1;
|
|
||||||
cpu_state <= cpu_state_fetch;
|
|
||||||
end
|
|
||||||
instr_setq: begin
|
|
||||||
`debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);)
|
|
||||||
reg_out <= cpuregs_rs1;
|
|
||||||
dbg_rs1val <= cpuregs_rs1;
|
|
||||||
dbg_rs1val_valid <= 1;
|
|
||||||
latched_rd <= latched_rd | irqregs_offset;
|
|
||||||
latched_store <= 1;
|
|
||||||
cpu_state <= cpu_state_fetch;
|
|
||||||
end
|
|
||||||
instr_retirq: begin
|
|
||||||
eoi <= 0;
|
|
||||||
irq_active <= 0;
|
|
||||||
latched_branch <= 1;
|
|
||||||
latched_store <= 1;
|
|
||||||
`debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);)
|
|
||||||
reg_out <= cpuregs_rs1 & 32'hfffffffe;
|
|
||||||
dbg_rs1val <= cpuregs_rs1;
|
|
||||||
dbg_rs1val_valid <= 1;
|
|
||||||
cpu_state <= cpu_state_fetch;
|
|
||||||
end
|
|
||||||
instr_maskirq: begin
|
|
||||||
latched_store <= 1;
|
|
||||||
reg_out <= irq_mask;
|
|
||||||
`debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);)
|
|
||||||
irq_mask <= cpuregs_rs1 | MASKED_IRQ;
|
|
||||||
dbg_rs1val <= cpuregs_rs1;
|
|
||||||
dbg_rs1val_valid <= 1;
|
|
||||||
cpu_state <= cpu_state_fetch;
|
|
||||||
end
|
|
||||||
instr_timer: begin
|
|
||||||
latched_store <= 1;
|
|
||||||
reg_out <= timer;
|
|
||||||
`debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);)
|
|
||||||
timer <= cpuregs_rs1;
|
|
||||||
dbg_rs1val <= cpuregs_rs1;
|
|
||||||
dbg_rs1val_valid <= 1;
|
|
||||||
cpu_state <= cpu_state_fetch;
|
|
||||||
end
|
|
||||||
is_lb_lh_lw_lbu_lhu && !instr_trap: begin
|
is_lb_lh_lw_lbu_lhu && !instr_trap: begin
|
||||||
`debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);)
|
`debug($display("LD_RS1: %2d 0x%08x", decoded_rs1, cpuregs_rs1);)
|
||||||
reg_op1 <= cpuregs_rs1;
|
reg_op1 <= cpuregs_rs1;
|
||||||
|
@ -1167,10 +1034,7 @@ module picorv32 #(
|
||||||
end else if (pcpi_timeout || instr_ecall_ebreak) begin
|
end else if (pcpi_timeout || instr_ecall_ebreak) begin
|
||||||
pcpi_valid <= 0;
|
pcpi_valid <= 0;
|
||||||
`debug($display("EBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);)
|
`debug($display("EBREAK OR UNSUPPORTED INSN AT 0x%08x", reg_pc);)
|
||||||
if (!irq_mask[irq_ebreak] && !irq_active) begin
|
cpu_state <= cpu_state_trap;
|
||||||
next_irq_pending[irq_ebreak] = 1;
|
|
||||||
cpu_state <= cpu_state_fetch;
|
|
||||||
end else cpu_state <= cpu_state_trap;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
is_sb_sh_sw: begin
|
is_sb_sh_sw: begin
|
||||||
|
@ -1205,7 +1069,6 @@ module picorv32 #(
|
||||||
cpu_state <= cpu_state_fetch;
|
cpu_state <= cpu_state_fetch;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
cpu_state_shift: begin
|
cpu_state_shift: begin
|
||||||
latched_store <= 1;
|
latched_store <= 1;
|
||||||
if (reg_sh == 0) begin
|
if (reg_sh == 0) begin
|
||||||
|
@ -1243,7 +1106,7 @@ module picorv32 #(
|
||||||
endcase
|
endcase
|
||||||
if (ENABLE_TRACE) begin
|
if (ENABLE_TRACE) begin
|
||||||
trace_valid <= 1;
|
trace_valid <= 1;
|
||||||
trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_ADDR | ((reg_op1 + decoded_imm) & 32'hffffffff);
|
trace_data <= TRACE_ADDR | ((reg_op1 + decoded_imm) & 32'hffffffff);
|
||||||
end
|
end
|
||||||
reg_op1 <= reg_op1 + decoded_imm;
|
reg_op1 <= reg_op1 + decoded_imm;
|
||||||
set_mem_do_wdata = 1;
|
set_mem_do_wdata = 1;
|
||||||
|
@ -1271,7 +1134,7 @@ module picorv32 #(
|
||||||
latched_is_lb <= instr_lb;
|
latched_is_lb <= instr_lb;
|
||||||
if (ENABLE_TRACE) begin
|
if (ENABLE_TRACE) begin
|
||||||
trace_valid <= 1;
|
trace_valid <= 1;
|
||||||
trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_ADDR | ((reg_op1 + decoded_imm) & 32'hffffffff);
|
trace_data <= TRACE_ADDR | ((reg_op1 + decoded_imm) & 32'hffffffff);
|
||||||
end
|
end
|
||||||
reg_op1 <= reg_op1 + decoded_imm;
|
reg_op1 <= reg_op1 + decoded_imm;
|
||||||
set_mem_do_rdata = 1;
|
set_mem_do_rdata = 1;
|
||||||
|
@ -1291,28 +1154,19 @@ module picorv32 #(
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
next_irq_pending = next_irq_pending | irq;
|
|
||||||
if (timer) if (timer - 1 == 0) next_irq_pending[irq_timer] = 1;
|
|
||||||
|
|
||||||
if (resetn && (mem_do_rdata || mem_do_wdata)) begin
|
if (resetn && (mem_do_rdata || mem_do_wdata)) begin
|
||||||
if (mem_wordsize == 0 && reg_op1[1:0] != 0) begin
|
if (mem_wordsize == 0 && reg_op1[1:0] != 0) begin
|
||||||
`debug($display("MISALIGNED WORD: 0x%08x", reg_op1);)
|
`debug($display("MISALIGNED WORD: 0x%08x", reg_op1);)
|
||||||
if (!irq_mask[irq_buserror] && !irq_active) begin
|
cpu_state <= cpu_state_trap;
|
||||||
next_irq_pending[irq_buserror] = 1;
|
|
||||||
end else cpu_state <= cpu_state_trap;
|
|
||||||
end
|
end
|
||||||
if (mem_wordsize == 1 && reg_op1[0] != 0) begin
|
if (mem_wordsize == 1 && reg_op1[0] != 0) begin
|
||||||
`debug($display("MISALIGNED HALFWORD: 0x%08x", reg_op1);)
|
`debug($display("MISALIGNED HALFWORD: 0x%08x", reg_op1);)
|
||||||
if (!irq_mask[irq_buserror] && !irq_active) begin
|
cpu_state <= cpu_state_trap;
|
||||||
next_irq_pending[irq_buserror] = 1;
|
|
||||||
end else cpu_state <= cpu_state_trap;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if (resetn && mem_do_rinst && (|reg_pc[1:0])) begin
|
if (resetn && mem_do_rinst && (|reg_pc[1:0])) begin
|
||||||
`debug($display("MISALIGNED INSTRUCTION: 0x%08x", reg_pc);)
|
`debug($display("MISALIGNED INSTRUCTION: 0x%08x", reg_pc);)
|
||||||
if (!irq_mask[irq_buserror] && !irq_active) begin
|
cpu_state <= cpu_state_trap;
|
||||||
next_irq_pending[irq_buserror] = 1;
|
|
||||||
end else cpu_state <= cpu_state_trap;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if (!resetn || mem_done) begin
|
if (!resetn || mem_done) begin
|
||||||
|
@ -1326,7 +1180,6 @@ module picorv32 #(
|
||||||
if (set_mem_do_rdata) mem_do_rdata <= 1;
|
if (set_mem_do_rdata) mem_do_rdata <= 1;
|
||||||
if (set_mem_do_wdata) mem_do_wdata <= 1;
|
if (set_mem_do_wdata) mem_do_wdata <= 1;
|
||||||
|
|
||||||
irq_pending <= next_irq_pending & ~MASKED_IRQ;
|
|
||||||
current_pc = 'bx;
|
current_pc = 'bx;
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1334,15 +1187,15 @@ endmodule
|
||||||
module picorv32_regs (
|
module picorv32_regs (
|
||||||
input clk,
|
input clk,
|
||||||
wen,
|
wen,
|
||||||
input [5:0] waddr,
|
input [4:0] waddr,
|
||||||
input [5:0] raddr1,
|
input [4:0] raddr1,
|
||||||
input [5:0] raddr2,
|
input [4:0] raddr2,
|
||||||
input [31:0] wdata,
|
input [31:0] wdata,
|
||||||
output [31:0] rdata1,
|
output [31:0] rdata1,
|
||||||
output [31:0] rdata2
|
output [31:0] rdata2
|
||||||
);
|
);
|
||||||
reg [31:0] regs[0:35];
|
reg [31:0] regs[0:31];
|
||||||
always @(posedge clk) if (wen) regs[waddr[5:0]] <= wdata;
|
always @(posedge clk) if (wen) regs[waddr[4:0]] <= wdata;
|
||||||
assign rdata1 = regs[raddr1];
|
assign rdata1 = regs[raddr1];
|
||||||
assign rdata2 = regs[raddr2];
|
assign rdata2 = regs[raddr2];
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -113,10 +113,7 @@ module picorv32_wb #(
|
||||||
|
|
||||||
picorv32 #(
|
picorv32 #(
|
||||||
.ENABLE_TRACE(1),
|
.ENABLE_TRACE(1),
|
||||||
.MASKED_IRQ(32'h0000_0000),
|
|
||||||
.LATCHED_IRQ(32'hffff_ffff),
|
|
||||||
.PROGADDR_RESET(32'h0001_0000),
|
.PROGADDR_RESET(32'h0001_0000),
|
||||||
.PROGADDR_IRQ(32'h0001_0010),
|
|
||||||
.STACKADDR(32'h0001_0000)
|
.STACKADDR(32'h0001_0000)
|
||||||
) picorv32_core (
|
) picorv32_core (
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
|
@ -135,8 +132,6 @@ module picorv32_wb #(
|
||||||
.mem_la_addr (mem_la_addr),
|
.mem_la_addr (mem_la_addr),
|
||||||
.mem_la_wdata(mem_la_wdata),
|
.mem_la_wdata(mem_la_wdata),
|
||||||
.mem_la_wstrb(mem_la_wstrb),
|
.mem_la_wstrb(mem_la_wstrb),
|
||||||
.irq (irq),
|
|
||||||
.eoi (eoi),
|
|
||||||
|
|
||||||
.trace_valid(trace_valid),
|
.trace_valid(trace_valid),
|
||||||
.trace_data (trace_data),
|
.trace_data (trace_data),
|
||||||
|
|
Loading…
Reference in New Issue