提交 7579093b 编写于 作者: 饶先宏's avatar 饶先宏

202108261010

上级 9b05ffb2
......@@ -30,8 +30,8 @@
*/
/*
* riscv_core.c
202108200823: rxh, initial version
* hdl4se_riscv_core_v2.c
202108261008: rxh, initial version
*/
#include "stdlib.h"
......@@ -47,14 +47,7 @@
#include "hdl4se_riscv.h"
#undef IMPLEMENT_GUID
#ifdef WIN32
#define DATADIR "d:/gitwork/hdl4se/examples/hdl4se_riscv/"
#else
#define DATADIR "/media/raoxianhong/_dde_data/gitwork/hdl4se/examples/hdl4se_riscv/"
#endif
#define riscv_core_MODULE_VERSION_STRING "0.4.0-20210820.0855 RISCV Core cell"
#define riscv_core_MODULE_VERSION_STRING "0.4.2-20210826.1008 RISCV Core cell"
#define riscv_core_MODULE_CLSID CLSID_HDL4SE_RISCV_CORE
#define M_ID(id) riscv_core##id
......@@ -85,7 +78,8 @@ IDLIST
VID(readreg),
VID(state),
VID(dstreg),
VID(dstvalue)
VID(dstvalue),
VID(ldaddr),
END_IDLIST
enum riscv_core_state {
......@@ -101,8 +95,6 @@ enum riscv_core_state {
};
MODULE_DECLARE(riscv_core)
// unsigned int dstreg;
// unsigned int dstvalue;
END_MODULE_DECLARE(riscv_core)
static unsigned int sign_expand(unsigned int v, int bit)
......@@ -116,7 +108,6 @@ static unsigned int sign_expand(unsigned int v, int bit)
return v;
}
DEFINE_FUNC(riscv_core_wr_sig, "write, writeaddr, writedata, writemask") {
VAssign(wWrite, write);
VAssign(bWriteAddr, writeaddr);
......@@ -150,6 +141,30 @@ DEFINE_FUNC(riscv_core_read_sig, "state, pc, instr, bReadData, rs1") {
}
} END_DEFINE_FUNC
DEFINE_FUNC(riscv_core_gen_ldaddr, "state, pc, instr, rs1") {
unsigned int state;
state = vget(state);
if (state == RISCVSTATE_READ_INST) {
vput(ldaddr, vget(pc));
}
else if (state == RISCVSTATE_EXEC_INST) {
unsigned int instr;
instr = vget(instr);
if ((instr & 0x7f) == 0x03) {
/* ld inst */
unsigned int imm;
unsigned int rs1;
unsigned int rdaddr;
imm = instr >> 20;
rs1 = vget(rs1);
imm = sign_expand(imm, 11);
rdaddr = rs1 + imm;
vput(ldaddr, rdaddr);
}
}
} END_DEFINE_FUNC
DEFINE_FUNC(riscv_core_reg_wr_sig, "state, dstreg, dstvalue, bReadData, instr, regrddata, pc") {
unsigned int state = vget(state);
switch (state) {
......@@ -206,146 +221,12 @@ FILE* recordfileGet();
#define DEBUG_CODE_DECODE fprintf(recordfileGet(),
#define INSTR_FORMAT_ERROR fprintf(recordfileGet(), "instruction format error, we support rv32im only: pc=%08x: %x\n", pc, instr);
#define RISCV_SETREG(rd, rst)
/* \
do { \
pobj->dstreg = rd; \
pobj->dstvalue = rst; \
} while (0)
*/
#define RISCV_SETDSTREG(rd, rst) \
do { \
vput(dstreg, rd); \
vput(dstvalue, rst); \
} while (0)
void riscv_core_exec_lui_inst(MODULE_DATA_TYPE* pobj, unsigned int pc, unsigned int instr, unsigned int rs1, unsigned int rs2) {
/* lui */
unsigned int imm;
unsigned int rd;
rd = (instr >> 7) & 0x1f;
imm = vget(imm);
RISCV_SETREG(rd, imm);
}
void riscv_core_exec_auipc_inst(MODULE_DATA_TYPE* pobj, unsigned int pc, unsigned int instr, unsigned int rs1, unsigned int rs2) {
/* auipc */
unsigned int imm;
unsigned int rd;
rd = (instr >> 7) & 0x1f;
imm = vget(imm);
RISCV_SETREG(rd, imm + pc);
}
void riscv_core_exec_jal_inst(MODULE_DATA_TYPE* pobj, unsigned int pc, unsigned int instr, unsigned int rs1, unsigned int rs2) {
/* jal */
unsigned int imm;
unsigned int rd;
rd = (instr >> 7) & 0x1f;
imm = vget(imm);
vput(pc, pc + imm);
RISCV_SETREG(rd, pc + 4);
}
void riscv_core_exec_jalr_inst(MODULE_DATA_TYPE* pobj, unsigned int pc, unsigned int instr, unsigned int rs1, unsigned int rs2) {
/* jalr */
unsigned int imm;
unsigned int rd;
unsigned int func3;
func3 = (instr >> 12) & 0x7;
rd = (instr >> 7) & 0x1f;
imm = vget(imm);
vput(pc, rs1 + imm);
RISCV_SETREG(rd, pc + 4);
}
void riscv_core_exec_b_inst(MODULE_DATA_TYPE* pobj, unsigned int pc, unsigned int instr, unsigned int rs1, unsigned int rs2) {
/* beq, bne, blt, bge, bltu, bgeu */
unsigned int imm;
unsigned int func3;
int cond;
func3 = (instr >> 12) & 0x7;
imm = vget(imm);
cond = 0;
switch (func3) {
case 0:/*beq*/ cond = rs1 == rs2; break;
case 1:/*bne*/ cond = rs1 != rs2; break;
case 4:/*blt*/ cond = (*(int*)&rs1) < (*(int*)&rs2); break;
case 5:/*bge*/ cond = (*(int*)&rs1) >= (*(int*)&rs2); break;
case 6:/*bltu*/cond = rs1 < rs2; break;
case 7:/*bgeu*/cond = rs1 >= rs2; break;
default:
INSTR_FORMAT_ERROR;
exit(-2);
break;
}
if (cond)
vput(pc, pc + imm);
}
void riscv_core_exec_ld_inst(MODULE_DATA_TYPE* pobj, unsigned int pc, unsigned int instr, unsigned int rs1, unsigned int rs2) {
/* lb, lh, lw, lbu, lhu */
unsigned int rd;
rd = (instr >> 7) & 0x1f;
vput(readreg, rd);
}
void riscv_core_exec_st_inst(MODULE_DATA_TYPE* pobj, unsigned int pc, unsigned int instr, unsigned int rs1, unsigned int rs2) {
/* sb, sh, sw */
unsigned int imm;
unsigned int func3;
unsigned int v;
unsigned int writeaddr;
unsigned int writemask;
unsigned int writedata;
func3 = (instr >> 12) & 0x7;
imm = vget(imm);
v = 0;
/* riscv支持地址不对齐访问,但是假定写在一个32位字中 */
writeaddr = rs1 + imm;
writemask = 0;
writedata = rs2;
switch (func3) {
case 0:/*sb*/
switch (writeaddr & 3) {
case 0: writemask = 0xe; writedata <<= 0; break; //1110
case 1: writemask = 0xd; writedata <<= 8; break; //1101
case 2: writemask = 0xb; writedata <<= 16; break; //1011
case 3: writemask = 0x7; writedata <<= 24; break; //0111
}
break;
case 1:/*sh*/
switch (writeaddr & 3) {
case 0: writemask = 0xc; writedata <<= 0; break; //1100
case 1: writemask = 0x9; writedata <<= 8; break; //1001
case 2: writemask = 0x3; writedata <<= 16; break; //0011
case 3: {
printf("we support store instruction write in one word only %08x: %08x\n", pc, instr);
exit(-6);
}break;
}
break;
case 2:/*sw*/
if (writeaddr & 3) {
printf("we support store instruction write in one word only %08x: %08x\n", pc, instr);
exit(-6);
}
break;
default:
DEBUG_CODE_FUNC;
exit(-7);
break;
}
vput(writeaddr, writeaddr);
vput(write, 1);
vput(writedata, writedata);
vput(writemask, writemask);
}
void riscv_core_exec_alui_inst(MODULE_DATA_TYPE* pobj, unsigned int pc, unsigned int instr, unsigned int rs1, unsigned int rs2) {
/* addi, slti, sltiu, xori, ori, andi, slli, srli, srai */
unsigned int imm;
......@@ -504,13 +385,12 @@ DEFINE_FUNC(riscv_core_exec_inst, "") {
exit(-2);
}
opcode >>= 2;
vput(pc, pc+4); /* 默认往后跳一指令 */
switch (opcode) {
case 0x0d: break;// riscv_core_exec_lui_inst(pobj, pc, instr, rs1, rs2); break;
case 0x05: break;// riscv_core_exec_auipc_inst(pobj, pc, instr, rs1, rs2); break;
case 0x1b: riscv_core_exec_jal_inst(pobj, pc, instr, rs1, rs2); break;
case 0x19: riscv_core_exec_jalr_inst(pobj, pc, instr, rs1, rs2); break;
case 0x18: riscv_core_exec_b_inst(pobj, pc, instr, rs1, rs2); break;
case 0x1b: break;// riscv_core_exec_jal_inst(pobj, pc, instr, rs1, rs2); break;
case 0x19: break;// riscv_core_exec_jalr_inst(pobj, pc, instr, rs1, rs2); break;
case 0x18: break;// riscv_core_exec_b_inst(pobj, pc, instr, rs1, rs2); break;
case 0x00: break;// riscv_core_exec_ld_inst(pobj, pc, instr, rs1, rs2); break;
case 0x08: break;//riscv_core_exec_st_inst(pobj, pc, instr, rs1, rs2); break;
case 0x04: break;// riscv_core_exec_alui_inst(pobj, pc, instr, rs1, rs2); break;
......@@ -524,7 +404,7 @@ DEFINE_FUNC(riscv_core_exec_inst, "") {
}
} END_DEFINE_FUNC
DEFINE_FUNC(riscv_core_gen_dstreg, "state, instr, rs1, pc, regrddata, imm") {
DEFINE_FUNC(riscv_core_gen_dstreg, "state, instr, ldaddr, readreg, bReadData, pc, rs1, regrddata, imm") {
switch (vget(state)) {
case RISCVSTATE_INIT_REGX1: {
RISCV_SETDSTREG(1, 0x8c);
......@@ -533,7 +413,68 @@ DEFINE_FUNC(riscv_core_gen_dstreg, "state, instr, rs1, pc, regrddata, imm") {
RISCV_SETDSTREG(2, RAMSIZE * 4 - 16);
}break;
case RISCVSTATE_WAIT_LD: {
RISCV_SETDSTREG(vget(readreg), vget(bReadData));
unsigned int instr = vget(instr);
unsigned int func3 = (instr >> 12) & 0x7;
unsigned int v;
unsigned int ldaddr = vget(ldaddr) & 3;
unsigned int readreg = vget(readreg);
v = vget(bReadData);
switch (func3) {
case 0:/*lb*/
switch (ldaddr) {
case 0: v = (v >> 0) & 0xff; break;
case 1: v = (v >> 8) & 0xff; break;
case 2: v = (v >> 16) & 0xff; break;
case 3: v = (v >> 24) & 0xff; break;
}
v = sign_expand(v, 7);
RISCV_SETDSTREG(readreg, v);
break;
case 1:/*lh*/
switch (ldaddr) {
case 0: v = (v >> 0) & 0xffff; break;
case 1: v = (v >> 8) & 0xffff; break;
case 2: v = (v >> 16) & 0xffff; break;
case 3: {
printf("No support for load 16bit in more than one word\n");
exit(-8);
}break;
}
v = sign_expand(v, 15);
RISCV_SETDSTREG(readreg, v);
break;
case 2:/*lw*/
if (ldaddr != 0) {
printf("No support for load 16bit in more than one word\n");
exit(-9);
}
RISCV_SETDSTREG(readreg, v);
break;
case 4:/*lbu*/
switch (ldaddr) {
case 0: v = (v >> 0) & 0xff; break;
case 1: v = (v >> 8) & 0xff; break;
case 2: v = (v >> 16) & 0xff; break;
case 3: v = (v >> 24) & 0xff; break;
}
RISCV_SETDSTREG(readreg, v);
break;
case 5:/*lhu*/
switch (ldaddr) {
case 0: v = (v >> 0) & 0xffff; break;
case 1: v = (v >> 8) & 0xffff; break;
case 2: v = (v >> 16) & 0xffff; break;
case 3: {
printf("No support for load 16bit in more than one word\n");
exit(-8);
}break;
}
RISCV_SETDSTREG(readreg, v);
break;
default:
RISCV_SETDSTREG(0, 0);
break;
}
}break;
case RISCVSTATE_EXEC_INST: {
unsigned int pc = vget(pc);
......@@ -576,13 +517,13 @@ DEFINE_FUNC(riscv_core_gen_imm, "instr, state") {
opcode = instr & 0x7f;
opcode >>= 2;
switch (opcode) {
case 0x0d: {//riscv_core_exec_lui_inst(pobj, pc, instr, rs1, rs2); break;
case 0x0d: {
vput(imm, instr & 0xfffff000);
}break;
case 0x05: {//riscv_core_exec_auipc_inst(pobj, pc, instr, rs1, rs2); break;
case 0x05: {
vput(imm, instr & 0xfffff000);
}break;
case 0x1b: {//riscv_core_exec_jal_inst(pobj, pc, instr, rs1, rs2); break;
case 0x1b: {
unsigned int imm;
imm = (instr & (1 << 20)) ? (1 << 11) : 0;
imm |= (instr >> 20) & 0x7fe;
......@@ -591,13 +532,13 @@ DEFINE_FUNC(riscv_core_gen_imm, "instr, state") {
imm = sign_expand(imm, 20);
vput(imm, imm);
}break;
case 0x19: {//riscv_core_exec_jalr_inst(pobj, pc, instr, rs1, rs2); break;
case 0x19: {
unsigned int imm;
imm = instr >> 20;
imm = sign_expand(imm, 11);
vput(imm, imm);
}break;
case 0x18: {//riscv_core_exec_b_inst(pobj, pc, instr, rs1, rs2); break;
case 0x18: {
unsigned int imm;
unsigned int immh;
unsigned int immd;
......@@ -611,30 +552,24 @@ DEFINE_FUNC(riscv_core_gen_imm, "instr, state") {
imm = sign_expand(imm, 12);
vput(imm, imm);
}break;
case 0x00: {//riscv_core_exec_ld_inst(pobj, pc, instr, rs1, rs2); break;
case 0x00: {
unsigned int imm;
imm = instr >> 20;
imm = sign_expand(imm, 11);
vput(imm, imm);
}break;
case 0x08: {//riscv_core_exec_st_inst(pobj, pc, instr, rs1, rs2); break;
case 0x08: {
unsigned int imm;
imm = ((instr >> 20) & 0xfe0) | ((instr >> 7) & 0x1f);
imm = sign_expand(imm, 11);
vput(imm, imm);
}break;
case 0x04: {//riscv_core_exec_alui_inst(pobj, pc, instr, rs1, rs2); break;
case 0x04: {
unsigned int imm;
imm = instr >> 20;
imm = sign_expand(imm, 11);
vput(imm, imm);
}break;
case 0x0c: {//riscv_core_exec_alu_inst(pobj, pc, instr, rs1, rs2); break;
}break;
case 0x03: {//riscv_core_exec_fence_inst(pobj, pc, instr, rs1, rs2); break;
}break;
case 0x1c: {//riscv_core_exec_sys_inst(pobj, pc, instr, rs1, rs2); break;
}break;
}
}
} END_DEFINE_FUNC
......@@ -696,10 +631,59 @@ DEFINE_FUNC(riscv_core_gen_write, "nwReset, state, pc, instr, rs1, regrddata, im
unsigned int rs2 = vget(regrddata);
unsigned int opcode = instr & 0x7f;
opcode >>= 2;
if (opcode == 0x08)
riscv_core_exec_st_inst(pobj, pc, instr, rs1, rs2);
else
if (opcode == 0x08) {
unsigned int imm;
unsigned int func3;
unsigned int v;
unsigned int writeaddr;
unsigned int writemask;
unsigned int writedata;
func3 = (instr >> 12) & 0x7;
imm = vget(imm);
v = 0;
/* riscv支持地址不对齐访问,但是假定写在一个32位字中 */
writeaddr = rs1 + imm;
writemask = 0;
writedata = rs2;
switch (func3) {
case 0:/*sb*/
switch (writeaddr & 3) {
case 0: writemask = 0xe; writedata <<= 0; break; //1110
case 1: writemask = 0xd; writedata <<= 8; break; //1101
case 2: writemask = 0xb; writedata <<= 16; break; //1011
case 3: writemask = 0x7; writedata <<= 24; break; //0111
}
break;
case 1:/*sh*/
switch (writeaddr & 3) {
case 0: writemask = 0xc; writedata <<= 0; break; //1100
case 1: writemask = 0x9; writedata <<= 8; break; //1001
case 2: writemask = 0x3; writedata <<= 16; break; //0011
case 3: {
printf("we support store instruction write in one word only %08x: %08x\n", pc, instr);
exit(-6);
}break;
}
break;
case 2:/*sw*/
if (writeaddr & 3) {
printf("we support store instruction write in one word only %08x: %08x\n", pc, instr);
exit(-6);
}
break;
default:
DEBUG_CODE_FUNC;
exit(-7);
break;
}
vput(writeaddr, writeaddr);
vput(write, 1);
vput(writedata, writedata);
vput(writemask, writemask);
}
else {
vput(write, 0);
}
}
else {
vput(write, 0);
......@@ -735,10 +719,58 @@ DEFINE_FUNC(riscv_core_reg_gen_instr, "state, bReadData") {
}
} END_DEFINE_FUNC
DEFINE_FUNC(riscv_core_reg_gen_pc, "nwReset, state, instr, pc, rs1, imm, regrddata") {
if (vget(nwReset) == 0) {
vput(pc, 0x74);
}
else {
int state = vget(state);
if (state == RISCVSTATE_EXEC_INST) {
unsigned int instr = vget(instr);
unsigned int pc = vget(pc);
unsigned int rs1 = vget(rs1);
unsigned int imm = vget(imm);
unsigned int opcode = instr & 0x7f;
opcode >>= 2;
switch (opcode) {
case 0x1b: vput(pc, pc + imm); break;
case 0x19: vput(pc, rs1 + imm); break;
case 0x18: {
unsigned int func3;
unsigned int rs2 = vget(regrddata);
int cond;
func3 = (instr >> 12) & 0x7;
cond = 0;
switch (func3) {
case 0:/*beq*/ cond = rs1 == rs2; break;
case 1:/*bne*/ cond = rs1 != rs2; break;
case 4:/*blt*/ cond = (*(int*)&rs1) < (*(int*)&rs2); break;
case 5:/*bge*/ cond = (*(int*)&rs1) >= (*(int*)&rs2); break;
case 6:/*bltu*/cond = rs1 < rs2; break;
case 7:/*bgeu*/cond = rs1 >= rs2; break;
default:
INSTR_FORMAT_ERROR;
exit(-2);
break;
}
if (cond)
vput(pc, pc + imm);
else
vput(pc, pc + 4);
}break;
default: {
vput(pc, pc + 4);
break;
}
}
}
}
} END_DEFINE_FUNC
DEFINE_FUNC(riscv_core_clktick, "") {
if (vget(nwReset) == 0) {
vput(pc, 0x74);
}
else {
int state = vget(state);
......@@ -751,8 +783,6 @@ DEFINE_FUNC(riscv_core_clktick, "") {
} END_DEFINE_FUNC
MODULE_INIT(riscv_core)
int i;
//pobj->dstreg = 0;
PORT_IN(wClk, 1);
PORT_IN(nwReset, 1);
GPORT_OUT(wWrite, 1, riscv_core_wr_sig);
......@@ -767,7 +797,7 @@ MODULE_INIT(riscv_core)
GPORT_OUT(regwrdata, 31, riscv_core_reg_wr_sig);
GPORT_OUT(regwren, 1, riscv_core_reg_wr_sig);
PORT_IN(regrddata, 32);
REG(pc, 32);
GREG(pc, 32, riscv_core_reg_gen_pc);
GREG(instr, 32, riscv_core_reg_gen_instr);
GREG(rs1, 32, riscv_core_reg_gen_rs1);
GREG(write, 1, riscv_core_gen_write);
......@@ -779,6 +809,7 @@ MODULE_INIT(riscv_core)
GREG(imm, 32, riscv_core_gen_imm);
GREG(dstreg, 5, riscv_core_gen_dstreg);
GREG(dstvalue, 32, riscv_core_gen_dstreg);
GREG(ldaddr, 2, riscv_core_gen_ldaddr);
CLKTICK_FUNC(riscv_core_clktick);
END_MODULE_INIT(riscv_core)
......@@ -171,9 +171,6 @@ DEFINE_FUNC(riscv_regfile_register, "wren, data, byteena, address") {
MODULE_INIT(riscv_regfile)
pobj->ram[0] = 0;
pobj->ram[1] = 0x8c;
pobj->ram[2] = RAMSIZE * 4-16;
pobj->ramwren = 0;
PORT_IN(clock, 1);
PORT_IN(wren, 1);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册