From f755827c9079ab65f293897c2859f4399ab2b6fa Mon Sep 17 00:00:00 2001 From: bbracker Date: Mon, 24 May 2021 18:11:56 -0400 Subject: [PATCH 2/4] slightly more path independence for using verilator --- wally-pipelined/lint-wally | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wally-pipelined/lint-wally b/wally-pipelined/lint-wally index 47a43235..d741d368 100755 --- a/wally-pipelined/lint-wally +++ b/wally-pipelined/lint-wally @@ -1,7 +1,8 @@ #!/bin/bash # check for warnings in Verilog code # The verilator lint tool is faster and better than Modelsim so it is best to run this first. -verilator="/usr/local/bin/verilator" +export PATH=$PATH:/usr/local/bin/ +verilator=`which verilator` basepath=$(dirname $0) for config in rv64ic rv32ic; do From 295263e122139b255abedd05e606a3956055ff52 Mon Sep 17 00:00:00 2001 From: "James E. Stine" Date: Mon, 24 May 2021 19:29:13 -0500 Subject: [PATCH 3/4] Mod for DIV/REM instruction and update to div.sv unit --- wally-pipelined/src/muldiv/div.sv | 108 ++++++++++++++++-- wally-pipelined/src/muldiv/muldiv.sv | 7 +- .../testbench/testbench-imperas.sv | 4 +- 3 files changed, 104 insertions(+), 15 deletions(-) diff --git a/wally-pipelined/src/muldiv/div.sv b/wally-pipelined/src/muldiv/div.sv index f1145780..9d6d672d 100755 --- a/wally-pipelined/src/muldiv/div.sv +++ b/wally-pipelined/src/muldiv/div.sv @@ -31,12 +31,13 @@ `include "wally-config.vh" -module div (Qf, remf, done, divBusy, div0, N, D, clk, reset, start); +module div (Qf, remf, done, divBusy, div0, N, D, clk, reset, start, S); input logic [63:0] N, D; input logic clk; input logic reset; input logic start; + input logic S; output logic [63:0] Qf; output logic [63:0] remf; @@ -58,6 +59,24 @@ module div (Qf, remf, done, divBusy, div0, N, D, clk, reset, start); logic shiftResult; logic enablev, state0v, donev, divdonev, oftzerov, divBusyv, ulp; + logic [63:0] twoD; + logic [63:0] twoN; + logic SignD; + logic SignN; + logic [63:0] QT, remT; + logic D_NegOne; + logic Max_N; + + // Check if negative (two's complement) + // If so, convert to positive + adder #(64) cpa1 ((D ^ {64{D[63]&S}}), {63'h0, D[63]&S}, twoD); + adder #(64) cpa2 ((N ^ {64{N[63]&S}}), {63'h0, N[63]&S}, twoN); + assign SignD = D[63]; + assign SignN = N[63]; + // Max N and D = -1 (Overflow) + assign Max_N = (~|N[62:0]) & N[63]; + assign D_NegOne = &D; + // Divider goes the distance to 37 cycles // (thanks the evil divisor for D = 0x1) // but could theoretically be stopped when @@ -74,17 +93,14 @@ module div (Qf, remf, done, divBusy, div0, N, D, clk, reset, start); // exception is given to FSM to tell the operation to // quit gracefully. - // div0 produced output errors have untested results - // (it is assumed the OS would handle some output) - - lz64 p1 (P, V, D); - shifter_l64 p2 (op2, D, P); - assign op1 = N; + lz64 p1 (P, V, twoD); + shifter_l64 p2 (op2, twoD, P); + assign op1 = twoN; assign div0 = ~V; // #iter: N = m+v+s = m+(s+2) = m+2+s (mod k = 0) // v = 2 since \rho < 1 (add 4 to make sure its a ceil) - adder #(8) cpa1 ({2'b0, P}, + adder #(8) cpa3 ({2'b0, P}, {5'h0, shiftResult, ~shiftResult, 1'b0}, Num); @@ -130,9 +146,23 @@ module div (Qf, remf, done, divBusy, div0, N, D, clk, reset, start); // n ln(r) shifter_r64 p4 (rem0, Rem5, RemShift); + // Adjust Q/Rem for Signed + assign tcQ = (SignN ^ SignD) & S; + assign tcR = SignN & S; + // Signed Divide + // - When N and D are negative: Remainder is negative (undergoes a two's complement). + // - When N is negative: Quotient and Remainder are both negative (undergo a two's complement). + // - When D is negative: Quotient is negative (undergoes a two's complement). + adder #(64) cpa4 ((rem0 ^ {64{tcR}}), {63'h0, tcR}, remT); + adder #(64) cpa5 ((Q ^ {64{tcQ}}), {63'h0, tcQ}, QT); + + // RISC-V has exceptions for divide by 0 and overflow (see Table 6.1 of spec) + exception_int exc (QT, remT, N, S, div0, Max_N, D_NegOne, Qf, remf); + + // Delete me if works // RISC-V has exceptions for divide by 0 (Table 6.1 of SPEC) - mux2 #(64) exc1 (Q, {64{1'b1}}, div0, Qf); - mux2 #(64) exc2 (rem0, op1, div0, remf); + //mux2 #(64) exc1 (Q, {64{1'b1}}, div0, Qf); + //mux2 #(64) exc2 (rem0, op1, div0, remf); endmodule // int32div @@ -1609,6 +1639,64 @@ module shift_left #(parameter WIDTH=8) endmodule // shift_right +module exception_int (Q, rem, op1, S, div0, Max_N, D_NegOne, Qf, remf); + + input logic [63:0] Q; + input logic [63:0] rem; + input logic [63:0] op1; + input logic S; + input logic div0; + input logic Max_N; + input logic D_NegOne; + + output logic [63:0] Qf; + output logic [63:0] remf; + + // Needs to be optimized + always_comb + case ({div0, S, Max_N, D_NegOne}) + 4'b0000 : Qf = Q; + 4'b0001 : Qf = Q; + 4'b0010 : Qf = Q; + 4'b0011 : Qf = Q; + 4'b0100 : Qf = Q; + 4'b0101 : Qf = Q; + 4'b0110 : Qf = Q; + 4'b0111 : Qf = {1'b1, 31'h0}; + 4'b1000 : Qf = {64{1'b1}}; + 4'b1001 : Qf = {64{1'b1}}; + 4'b1010 : Qf = {64{1'b1}}; + 4'b1011 : Qf = {64{1'b1}}; + 4'b1100 : Qf = {64{1'b1}}; + 4'b1101 : Qf = {64{1'b1}}; + 4'b1110 : Qf = {64{1'b1}}; + 4'b1111 : Qf = {64{1'b1}}; + default: Qf = Q; + endcase + + always_comb + case ({div0, S, Max_N, D_NegOne}) + 4'b0000 : remf = rem; + 4'b0001 : remf = rem; + 4'b0010 : remf = rem; + 4'b0011 : remf = rem; + 4'b0100 : remf = rem; + 4'b0101 : remf = rem; + 4'b0110 : remf = rem; + 4'b0111 : remf = 64'h0; + 4'b1000 : remf = op1; + 4'b1001 : remf = op1; + 4'b1010 : remf = op1; + 4'b1011 : remf = op1; + 4'b1100 : remf = op1; + 4'b1101 : remf = op1; + 4'b1110 : remf = op1; + 4'b1111 : remf = op1; + default: remf = rem; + endcase + +endmodule // exception_int + /* verilator lint_on COMBDLY */ /* verilator lint_on IMPLICIT */ diff --git a/wally-pipelined/src/muldiv/muldiv.sv b/wally-pipelined/src/muldiv/muldiv.sv index 0df7e5d7..17c4aac5 100644 --- a/wally-pipelined/src/muldiv/muldiv.sv +++ b/wally-pipelined/src/muldiv/muldiv.sv @@ -57,7 +57,8 @@ module muldiv ( logic gclk; logic DivStartE; - logic startDivideE; + logic startDivideE; + logic signedDivide; // Multiplier mul mul(.*); @@ -76,8 +77,8 @@ module muldiv ( flopenrc #(`XLEN) reg_den (.d(SrcBE), .q(D), .en(startDivideE), .clear(DivDoneE), .reset(reset), .clk(~gclk)); - - div div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, startDivideE); + assign signedDivide = (Funct3E[2]&~Funct3E[1]&~Funct3E[0]) | (Funct3E[2]&Funct3E[1]&~Funct3E[0]); + div div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, startDivideE, signedDivide); // Added for debugging of start signal for divide assign startDivideE = MulDivE&DivStartE&~DivBusyE; diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index e6798586..ddee23a1 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -163,11 +163,11 @@ string tests32f[] = '{ "rv64m/I-MULHSU-01", "3000", "rv64m/I-MULHU-01", "3000", "rv64m/I-MULW-01", "3000", - //"rv64m/I-DIV-01", "3000", + "rv64m/I-DIV-01", "3000", "rv64m/I-DIVU-01", "3000", //"rv64m/I-DIVUW-01", "3000", //"rv64m/I-DIVW-01", "3000", - //"rv64m/I-REM-01", "3000", + "rv64m/I-REM-01", "3000", "rv64m/I-REMU-01", "3000" //"rv64m/I-REMUW-01", "3000", //"rv64m/I-REMW-01", "3000" From c4f3f2f78372ef7f194b45541cacfc8d6f688d9c Mon Sep 17 00:00:00 2001 From: "James E. Stine" Date: Mon, 24 May 2021 19:30:28 -0500 Subject: [PATCH 4/4] Minor cosmetic elements on div.sv --- wally-pipelined/src/muldiv/div.sv | 6 ------ 1 file changed, 6 deletions(-) diff --git a/wally-pipelined/src/muldiv/div.sv b/wally-pipelined/src/muldiv/div.sv index 9d6d672d..db830ca3 100755 --- a/wally-pipelined/src/muldiv/div.sv +++ b/wally-pipelined/src/muldiv/div.sv @@ -130,7 +130,6 @@ module div (Qf, remf, done, divBusy, div0, N, D, clk, reset, start, S); // shifting N right by v+s so that (m+v+s) mod k = 0. And, // the quotient has to be aligned to the integer position. - // Actual divider unit FIXME: r16 (jes) divide4x64 p3 (Qd, Rd, quotient, op1, op2, clk, reset, state0, enable, otfzero, shiftResult); @@ -159,11 +158,6 @@ module div (Qf, remf, done, divBusy, div0, N, D, clk, reset, start, S); // RISC-V has exceptions for divide by 0 and overflow (see Table 6.1 of spec) exception_int exc (QT, remT, N, S, div0, Max_N, D_NegOne, Qf, remf); - // Delete me if works - // RISC-V has exceptions for divide by 0 (Table 6.1 of SPEC) - //mux2 #(64) exc1 (Q, {64{1'b1}}, div0, Qf); - //mux2 #(64) exc2 (rem0, op1, div0, remf); - endmodule // int32div module divide4x64 (Q, rem0, quotient, op1, op2, clk, reset, state0,