diff --git a/src/include/support/liburiscv/liburiscv.h b/src/include/support/liburiscv/liburiscv.h index 70df0aa..9e5c98a 100644 --- a/src/include/support/liburiscv/liburiscv.h +++ b/src/include/support/liburiscv/liburiscv.h @@ -154,4 +154,8 @@ extern void INITCPU(unsigned int cpuid, STATE_PTR start_state); extern int CAS(volatile unsigned int *atomic, unsigned int oldval, unsigned int newval); +extern int ACQUIRE_LOCK(volatile unsigned int *atomic); + +extern int RELEASE_LOCK(volatile unsigned int *atomic); + #endif /* !defined(URISCV_LIBURISCV_H) */ diff --git a/src/include/uriscv/csr.h b/src/include/uriscv/csr.h index dabb2d7..2401108 100644 --- a/src/include/uriscv/csr.h +++ b/src/include/uriscv/csr.h @@ -57,5 +57,6 @@ #define CSR_INDEX 0x802 #define CSR_RANDOM 0x803 #define CSR_BADVADDR 0x804 +#define PRID 0x805 #endif diff --git a/src/include/uriscv/processor_defs.h b/src/include/uriscv/processor_defs.h index ea76629..71944ca 100644 --- a/src/include/uriscv/processor_defs.h +++ b/src/include/uriscv/processor_defs.h @@ -277,6 +277,7 @@ #define OP_CSRRSI 0x6 #define OP_CSRRCI 0x7 #define R_TYPE 0x33 +#define A_TYPE 0x2F #define OP_MUL_FUNC7 0x1 #define OP_MUL_FUNC3 0x0 @@ -295,6 +296,12 @@ #define OP_REMU_FUNC3 0x7 #define OP_REMU_FUNC7 0x1 +#define OP_AMOSWAP_FUNC3 0x2 +#define OP_AMOSWAP_FUNC7 0x4 +#define OP_AMOSWAP_RL_FUNC7 0x5 +#define OP_AMOSWAP_AQ_FUNC7 0x6 +#define OP_AMOSWAP_RL_AQ_FUNC7 0x7 + #define OP_ADD_FUNC3 0x0 #define OP_ADD_FUNC7 0x0 #define OP_SUB_FUNC3 0x0 diff --git a/src/support/bios/exec.S b/src/support/bios/exec.S index 7e649b4..88845f9 100644 --- a/src/support/bios/exec.S +++ b/src/support/bios/exec.S @@ -17,7 +17,7 @@ #define ASIDSTEP 0x00000040 #define VPNMASK 0xFFFFF000 -#define VECTSIZE 140 +#define STATE_T_SIZE_IN_BYTES 148 /* NOP padding: 30 nops - string length (32 bytes) */ #define PANIC_PADDING (30 * 4) - 32 @@ -59,7 +59,7 @@ bios: * 0x00000000 address * This is the entry point for UTLB type exceptions. */ - j LEXCHandler + j LEXCHandler nop EndStr: @@ -73,6 +73,45 @@ PanicStr: * 0x00000080: panic() * Print a message on terminal 0 and loop forever */ + j LPanic + nop + + .space 0x80 - 0x8 + /* + * 0x00000100 address + * Secondary processor startup routine + */ + j LInitSecondaryProcessor + nop + +/* + * Get a cpu up and runing: initialize BIOS related structures and + * load the supplied processor state. + */ +LInitSecondaryProcessor: + /* Initialize ptr to exception state vector */ + li t0, STATE_T_SIZE_IN_BYTES + csrrw t1, PRID, zero + mul t0, t0, t1 + li t2, BIOS_DATA_PAGE_BASE + add t0, t0, t2 + li t2, BIOS_EXCPT_VECT_BASE + sw t0, 0(t2) + + /* Initialize ptr to PC/SP area */ + li t0, 16 + mul t0, t0, t1 + li t1, BIOS_EXEC_HANDLERS_ADDRS + add t0, t0, t1 + li t2, BIOS_PC_AREA_BASE + sw t0, 0(t2) + + /* Load the new state - address of start_state cached at start of exception vector */ + li t0, BIOS_EXCPT_VECT_BASE + lw t2, 0(t0) + lw t2, 0(t2) + WRITEK0(t2) + j LLoadStart LPanic: li a0, PANICSTRADDR - 1 diff --git a/src/support/liburiscv/CMakeLists.txt b/src/support/liburiscv/CMakeLists.txt index 60cf89f..74ac172 100644 --- a/src/support/liburiscv/CMakeLists.txt +++ b/src/support/liburiscv/CMakeLists.txt @@ -6,7 +6,7 @@ set(URISCV_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/uriscv) set(LIBURISCV_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include/support/liburiscv) -set(LIBURISCV_CFLAGS -ffreestanding -ansi -Wall -c -static -g -march=rv32imfd -mabi=ilp32d -fno-pic) +set(LIBURISCV_CFLAGS -ffreestanding -ansi -Wall -c -static -g -march=rv32imafd -mabi=ilp32d -fno-pic) set(LIBURISCV_CPPFLAGS -I${PROJECT_SOURCE_DIR}/include) add_custom_target(liburiscv.o ALL diff --git a/src/support/liburiscv/liburiscv.S b/src/support/liburiscv/liburiscv.S index 6728e0c..323c3b6 100644 --- a/src/support/liburiscv/liburiscv.S +++ b/src/support/liburiscv/liburiscv.S @@ -11,6 +11,9 @@ #include "uriscv/cpu.h" #include "uriscv/const.h" +#define STATE_T_SIZE_IN_BYTES 148 +#define INIT_SECONDARY_PROCESSOR_ROUTINE_ADDRESS 0x00000100 + #define LEAF_FUNC(func) \ .globl func; \ .type func, @function; \ @@ -86,7 +89,7 @@ LEAF_FUNC(getEPC) jr ra LEAF_FUNC(getPRID) - addi a0,a0,3 + csrrw a0,PRID,zero jr ra LEAF_FUNC(getMIE) @@ -325,3 +328,42 @@ LEAF_FUNC(PANIC) nop jr ra +/* + * INITCPU + * + * SYNOPSIS: + * void INITCPU(u32 cpu_id, state t *start_state) + */ +LEAF_FUNC(INITCPU) + li t0, MCTL_BOOT_PC + li t1, INIT_SECONDARY_PROCESSOR_ROUTINE_ADDRESS + + sw t1, 0(t0) + + /* Compute starting address for this CPUs stored exception vector */ + li t0, STATE_T_SIZE_IN_BYTES + mul t0, t0, a0 + li t1, BIOS_DATA_PAGE_BASE + add t0, t1, t0 + + /* store start_state at start of this CPU's stored exception vector */ + sw a1, 0(t0) + + li t0, MCTL_RESET_CPU + sw a0, 0(t0) + + jr ra + + +LEAF_FUNC(ACQUIRE_LOCK) + li t0, 1 + li t1, 0 + retry: + amoswap.w t0, t0, 0(a0) + bne t0, t1, retry # if a1 != 0 then goto retry + jr ra + +LEAF_FUNC(RELEASE_LOCK) + li t0, 0 + amoswap.w t0, t0, 0(a0) + jr ra diff --git a/src/uriscv/disassemble.cc b/src/uriscv/disassemble.cc index abac74d..a9051c4 100644 --- a/src/uriscv/disassemble.cc +++ b/src/uriscv/disassemble.cc @@ -195,7 +195,7 @@ HIDDEN void StrRInstr(Word instr) { uint8_t func3 = FUNC3(instr); uint8_t func7 = FUNC7(instr); - if (func7 == 0x20) + if (func7 == 0x20) // sub, sra func7 = 2; if (func7 > 2) { sprintf(strbuf, "unknown instruction"); @@ -207,6 +207,23 @@ HIDDEN void StrRInstr(Word instr) { regName[RS2(instr)]); } +HIDDEN const char *const AInstrName[] = {"amoswap.w", "amoswap.w", "amoswap.w", "amoswap.w"}; + +HIDDEN void StrAInstr(Word instr) { + uint8_t func3 = FUNC3(instr); + uint8_t func7 = FUNC7(instr); + + if (0x4 <= func7 && func7 <= 0x7) { // amoswap.w + func7 -= 4; + } else { + sprintf(strbuf, "unknown instruction A-type %x %x", func3, func7); + return; + } + + sprintf(strbuf, "%s\t%s,%s%s,%s0(%s)", AInstrName[func7], regName[RD(instr)], sep, regName[RS2(instr)], + sep, regName[RS1(instr)]); +} + HIDDEN const char *const loadInstrName[] = {"lb", "lh", "lw", "", "lbu", "lhu"}; HIDDEN void StrLoadInstr(Word instr) { @@ -543,6 +560,10 @@ const char *StrInstr(Word instr) { StrSInstr(instr); } break; + case A_TYPE: { + StrAInstr(instr); + } break; + case OP_AUIPC: case OP_LUI: { sprintf(strbuf, "%s\t%s,%s0x%x", opcode == OP_LUI ? "lui" : "auipc", diff --git a/src/uriscv/processor.cc b/src/uriscv/processor.cc index 3c6a275..87989ce 100644 --- a/src/uriscv/processor.cc +++ b/src/uriscv/processor.cc @@ -156,6 +156,7 @@ void Processor::initCSR() { csr[TIME].perm = RRR; csr[TIMEH].perm = RRR; + csr[PRID].perm = RRR; csr[INSTRET].perm = RRR; csr[MINSTRET].perm = NNW; @@ -270,6 +271,9 @@ void Processor::Reset(Word pc, Word sp) { csrWrite(MIE, 0); csrWrite(MCAUSE, 0); csrWrite(TIME, 0); + csrWrite(PRID, id); + csrWrite(MIP, 0); + csrWrite(MTVEC, 0); mode = 0x3; currPC = pc; @@ -451,7 +455,9 @@ void Processor::getPrevStatus(Word *pc, Word *instr) { // exception happened (thanks to excName[] array) const char *Processor::getExcCauseStr() { // 0 means no exception - if (excCause) + if (CAUSE_IS_INT(excCause)) + return "INT"; + else if (excCause) return excName[excCause]; else return (EMPTYSTR); @@ -618,9 +624,9 @@ void Processor::popKUIEStack() { // otherwise, and sets CP0 registers if needed bool Processor::checkForInt() { // check if interrupts are enabled and pending - if (csrRead(MSTATUS) & MSTATUS_MIE_MASK && (csrRead(MIE) & csrRead(MIP))) { + uint mip = csrRead(MIE) & csrRead(MIP); + if (csrRead(MSTATUS) & MSTATUS_MIE_MASK && mip) { uint l = 0; - uint mip = csrRead(MIP); while (mip > 1) { mip >>= 1; l++; @@ -909,7 +915,7 @@ bool Processor::execInstrR(Word instr) { break; } default: { - ERRORMSG("R-type not recognized (%x)\n", FUNC7); + ERRORMSG("R-type not recognized (%x, %x)\n", FUNC3, FUNC7); SignalExc(EXC_II, 0); e = true; break; @@ -918,7 +924,7 @@ bool Processor::execInstrR(Word instr) { break; } /* 0x2 */ - case OP_MULHSU_FUNC3 | OP_SLT_FUNC3: { + case OP_MULHSU_FUNC3 | OP_SLT_FUNC3 | OP_AMOSWAP_FUNC3: { switch (FUNC7) { case OP_MULHSU_FUNC7: { SWord high = 0, low = 0; @@ -933,9 +939,22 @@ bool Processor::execInstrR(Word instr) { regName[rs1], regRead(rs1), regRead(rs2)); regWrite(rd, SWord(regRead(rs1)) < SWord(regRead(rs2)) ? 1 : 0); break; + } + case OP_AMOSWAP_FUNC7: + case OP_AMOSWAP_RL_FUNC7: + case OP_AMOSWAP_AQ_FUNC7: + case OP_AMOSWAP_RL_AQ_FUNC7: { + DISASSMSG("AMOSWAP %d,%d,%s(%x)\n", regRead(rd), regRead(rs2), regName[rs1], regRead(rs1)); + Word datap; + Word reg1 = regRead(rs1); + Word reg2 = regRead(rs2); + this->bus->DataRead(reg1, &datap, this); + regWrite(rd, datap); + this->bus->DataWrite(reg1, reg2, this); + break; } default: { - ERRORMSG("R-type not recognized (%x)\n", FUNC7); + ERRORMSG("R-type not recognized (%x, %x)\n", FUNC3, FUNC7); SignalExc(EXC_II, 0); e = true; break; @@ -961,7 +980,7 @@ bool Processor::execInstrR(Word instr) { break; } default: { - ERRORMSG("R-type not recognized (%x)\n", FUNC7); + ERRORMSG("R-type not recognized (%x, %x)\n", FUNC3, FUNC7); SignalExc(EXC_II, 0); e = true; break; @@ -989,7 +1008,7 @@ bool Processor::execInstrR(Word instr) { break; } default: { - ERRORMSG("R-type not recognized (%x)\n", FUNC7); + ERRORMSG("R-type not recognized (%x, %x)\n", FUNC3, FUNC7); SignalExc(EXC_II, 0); e = true; break; @@ -1021,7 +1040,7 @@ bool Processor::execInstrR(Word instr) { break; } default: { - ERRORMSG("R-type not recognized (%x)\n", FUNC7); + ERRORMSG("R-type not recognized (%x, %x)\n", FUNC3, FUNC7); SignalExc(EXC_II, 0); e = true; break; @@ -1047,7 +1066,7 @@ bool Processor::execInstrR(Word instr) { break; } default: { - ERRORMSG("R-type not recognized (%x)\n", FUNC7); + ERRORMSG("R-type not recognized (%x, %x)\n", FUNC3, FUNC7); SignalExc(EXC_II, 0); e = true; break; @@ -1073,7 +1092,7 @@ bool Processor::execInstrR(Word instr) { break; } default: { - ERRORMSG("R-type not recognized (%x)\n", FUNC7); + ERRORMSG("R-type not recognized (%x, %x)\n", FUNC3, FUNC7); SignalExc(EXC_II, 0); e = true; break; @@ -1528,6 +1547,10 @@ bool Processor::execInstr(Word instr) { e = execInstrS(instr); break; } + case A_TYPE: { + e = execInstrR(instr); + break; + } case OP_AUIPC: { DISASSMSG("\tU-type | AUIPC\n"); uint8_t rd = RD(instr);