Commit 3ed72808 authored by logan's avatar logan
Browse files

mult mod

parent 6462b4df
Pipeline #216467 passed with stages
in 15 minutes and 48 seconds
......@@ -33,6 +33,9 @@ public:
bool resIsNeg;
int i;
ac_int<32, false> dataAUnsigned, dataBUnsigned;
bool forward_minus_minus = false, forward_minus_plus = false, forward_plus_minus = false;
bool forward_result_unsigned = false, forward_result_signed = false;
bool process(struct DCtoEx dctoEx, ac_int<32, false>& result, bool& stall);
};
......
......@@ -7,106 +7,168 @@ bool MultiplicationUnit::process(struct DCtoEx dctoEx, ac_int<32, false>& result
bool valRet = false;
if (dctoEx.opCode == RISCV_OP && dctoEx.funct7 == RISCV_OP_M) {
if (state == 0) {
forward_result_unsigned |= (dataAUnsigned ^ dctoEx.lhs) | (dataBUnsigned ^ dctoEx.rhs);
forward_result_unsigned = !forward_result_unsigned;
forward_minus_minus |= (dataAUnsigned ^ -dctoEx.lhs) | (dataBUnsigned ^ -dctoEx.rhs);
forward_minus_minus = !forward_minus_minus;
forward_minus_plus |= (dataAUnsigned ^ -dctoEx.lhs) | (dataBUnsigned ^ dctoEx.rhs);
forward_minus_plus = !forward_minus_plus;
forward_plus_minus |= (dataAUnsigned ^ dctoEx.lhs) | (dataBUnsigned ^ -dctoEx.rhs);
forward_plus_minus = !forward_plus_minus;
forward_result_signed = forward_minus_minus | forward_minus_plus | forward_plus_minus | forward_result_unsigned;
dataAUnsigned.set_slc(0, dctoEx.lhs);
dataBUnsigned.set_slc(0, dctoEx.rhs);
// mult results
ac_int<32, false> resultU = dataAUnsigned * dataBUnsigned;
ac_int<32, false> resultS = dctoEx.lhs * dctoEx.rhs;
ac_int<32, false> resultSU = dctoEx.lhs * dataBUnsigned;
ac_int<64, false> resultU = dataAUnsigned * dataBUnsigned;
ac_int<64, false> resultS = dctoEx.lhs * dctoEx.rhs;
ac_int<64, false> resultSU = dctoEx.lhs * dataBUnsigned;
resIsNeg = dctoEx.lhs[31] ^ dctoEx.rhs[31];
switch (dctoEx.funct3) {
case RISCV_OP_M_MUL:
result = resultS.slc<32>(0);
valRet = true;
break;
case RISCV_OP_M_MULH:
result = resultS.slc<32>(32);
valRet = true;
break;
case RISCV_OP_M_MULHSU:
result = resultSU.slc<32>(32);
valRet = true;
break;
case RISCV_OP_M_MULHU:
result = resultU.slc<32>(32);
valRet = true;
break;
case RISCV_OP_M_DIV:
if (dctoEx.lhs[31]) {
dataAUnsigned = -dctoEx.lhs;
}
if (dctoEx.rhs[31]) {
dataBUnsigned = -dctoEx.rhs;
}
case RISCV_OP_M_DIVU:
if (dataBUnsigned == 0) {
result = -1;
valRet = true;
} else {
state = 32;
quotient = 0;
remainder = 0;
}
break;
case RISCV_OP_M_REM:
if (dctoEx.lhs[31]) {
dataAUnsigned = -dctoEx.lhs;
}
if (dctoEx.rhs[31]) {
dataBUnsigned = -dctoEx.rhs;
}
case RISCV_OP_M_REMU:
if (dataBUnsigned == 0) {
result = dataAUnsigned;
} else {
state = 32;
quotient = 0;
remainder = 0;
}
break;
case RISCV_OP_M_MUL:
result = resultS.slc<32>(0);
valRet = true;
break;
case RISCV_OP_M_MULH:
result = resultS.slc<32>(32);
valRet = true;
break;
case RISCV_OP_M_MULHSU:
result = resultSU.slc<32>(32);
valRet = true;
break;
case RISCV_OP_M_MULHU:
result = resultU.slc<32>(32);
valRet = true;
break;
case RISCV_OP_M_DIV:
if (dataBUnsigned == 0) { // division by zero
result = -1;
valRet = true;
} else if (dataAUnsigned == 0x80000000 && dataBUnsigned == 0xfffffffc){ // Overflow 32 bits
result = 0x80000000;
valRet = true;
} else if(forward_result_signed){
if (resIsNeg)
result = -quotient;
else
result = quotient;
valRet = true;
} else {
state = 32;
quotient = 0;
remainder = 0;
if (dctoEx.lhs[31]) {
dataAUnsigned = -dctoEx.lhs;
}
if (dctoEx.rhs[31]) {
dataBUnsigned = -dctoEx.rhs;
}
}
break;
case RISCV_OP_M_DIVU:
if (dataBUnsigned == 0) { // division by zero
result = -1;
valRet = true;
} else if (forward_result_unsigned){
result = quotient;
valRet = true;
} else {
state = 32;
quotient = 0;
remainder = 0;
}
break;
case RISCV_OP_M_REM:
if (dataBUnsigned == 0) { // division by zero
result = dataAUnsigned;
valRet = true;
} else if (dataAUnsigned == 0x80000000 && dataBUnsigned == 0xfffffffc){ // Overflow
result = 0;
valRet = true;
} else if(forward_result_signed){
if (dctoEx.lhs[31])
result = -remainder;
else
result = remainder;
valRet = true;
} else {
state = 32;
quotient = 0;
remainder = 0;
if (dctoEx.lhs[31]) {
dataAUnsigned = -dctoEx.lhs;
}
if (dctoEx.rhs[31]) {
dataBUnsigned = -dctoEx.rhs;
}
}
break;
case RISCV_OP_M_REMU:
if (dataBUnsigned == 0) { // division by zero
result = dataAUnsigned;
valRet = true;
} else if(forward_result_unsigned) {
result = remainder;
valRet = true;
} else {
state = 32;
quotient = 0;
remainder = 0;
}
break;
default:
break;
}
} else {
// Loop for the division
for (i = 0; i < 4; i++) {
state--;
remainder = remainder << 1;
remainder[0] = dataAUnsigned[state];
if (remainder >= dataBUnsigned) {
remainder = remainder - dataBUnsigned;
quotient[state] = 1;
}
state--;
remainder = remainder << 1;
remainder[0] = dataAUnsigned[state];
if (remainder >= dataBUnsigned) {
remainder = remainder - dataBUnsigned;
quotient[state] = 1;
}
}
if (state == 0) {
switch (dctoEx.funct3) {
case RISCV_OP_M_DIV:
if (resIsNeg)
result = -quotient;
else
result = quotient;
valRet = true;
break;
case RISCV_OP_M_DIVU:
result = quotient;
valRet = true;
break;
case RISCV_OP_M_REM:
if (dataAUnsigned[31])
result = -remainder;
else
result = remainder;
valRet = true;
break;
case RISCV_OP_M_REMU:
result = remainder;
valRet = true;
break;
}
switch (dctoEx.funct3) {
case RISCV_OP_M_DIV:
if (resIsNeg)
result = -quotient;
else
result = quotient;
valRet = true;
break;
case RISCV_OP_M_DIVU:
result = quotient;
valRet = true;
break;
case RISCV_OP_M_REM:
if (dctoEx.lhs[31])
result = -remainder;
else
result = remainder;
valRet = true;
break;
case RISCV_OP_M_REMU:
result = remainder;
valRet = true;
break;
default:
break;
}
}
}
stall |= (state != 0);
}
return valRet;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment