diff --git a/wally-pipelined/config/rv64ic/wally-config.vh b/wally-pipelined/config/rv64ic/wally-config.vh index 518da71c..bedfc4f3 100644 --- a/wally-pipelined/config/rv64ic/wally-config.vh +++ b/wally-pipelined/config/rv64ic/wally-config.vh @@ -67,7 +67,7 @@ // Integer Divider Configuration // DIV_BITSPERCYCLE must be 1, 2, or 4 -`define DIV_BITSPERCYCLE 4 +`define DIV_BITSPERCYCLE 1 // Legal number of PMP entries are 0, 16, or 64 `define PMP_ENTRIES 64 diff --git a/wally-pipelined/src/muldiv/intdivrestoring.sv b/wally-pipelined/src/muldiv/intdivrestoring.sv index b28f63e6..a0ddb309 100644 --- a/wally-pipelined/src/muldiv/intdivrestoring.sv +++ b/wally-pipelined/src/muldiv/intdivrestoring.sv @@ -31,7 +31,7 @@ module intdivrestoring ( input logic clk, input logic reset, input logic StallM, FlushM, - input logic SignedDivideE, + input logic SignedDivideE, W64E, input logic StartDivideE, input logic [`XLEN-1:0] XE, DE, output logic BusyE, DivDoneM, @@ -40,7 +40,7 @@ module intdivrestoring ( logic [`XLEN-1:0] WE[`DIV_BITSPERCYCLE:0]; logic [`XLEN-1:0] XQE[`DIV_BITSPERCYCLE:0]; - logic [`XLEN-1:0] DSavedE, XSavedE, XSavedM, DnE, DAbsBE, XnE, XInitE, WM, XQM, WnM, XQnM; + logic [`XLEN-1:0] DSavedE, XSavedE, XSavedM, DinE, XinE, DnE, DAbsBE, XnE, XInitE, WM, XQM, WnM, XQnM; localparam STEPBITS = $clog2(`XLEN/`DIV_BITSPERCYCLE); logic [STEPBITS:0] step; logic Div0E, Div0M; @@ -52,9 +52,22 @@ module intdivrestoring ( // Saving the inputs is the most hardware-efficient way to fix the issue. flopen #(`XLEN) dsavereg(~clk, StartDivideE, DE, DSavedE); flopen #(`XLEN) xsavereg(~clk, StartDivideE, XE, XSavedE); - assign SignDE = DSavedE[`XLEN-1]; - assign SignXE = XSavedE[`XLEN-1]; - assign Div0E = (DSavedE == 0); + + // Handle sign extension for W-type instructions + generate + if (`XLEN == 64) begin // RV64 has W-type instructions + mux2 #(`XLEN) xinmux(XSavedE, {XSavedE[31:0], 32'b0}, W64E, XinE); + mux2 #(`XLEN) dinmux(DSavedE, {{32{DSavedE[31]&SignedDivideE}}, DSavedE[31:0]}, W64E, DinE); + end else begin // RV32 has no W-type instructions + assign XinE = XSavedE; + assign DinE = DSavedE; + end + endgenerate + + // Extract sign bits and check fo division by zero + assign SignDE = DinE[`XLEN-1]; + assign SignXE = XinE[`XLEN-1]; + assign Div0E = (DinE == 0); // pipeline registers flopenrc #(1) SignedDivideMReg(clk, reset, FlushM, ~StallM, SignedDivideE, SignedDivideM); @@ -64,10 +77,10 @@ module intdivrestoring ( flopenrc #(`XLEN) XSavedMReg(clk, reset, FlushM, ~StallM, XSavedE, XSavedM); // is this truly necessary? // Take absolute value for signed operations, and negate D to handle subtraction in divider stages - neg #(`XLEN) negd(DSavedE, DnE); - mux2 #(`XLEN) dabsmux(DnE, DSavedE, SignedDivideE & SignDE, DAbsBE); // take absolute value for signed operations, and negate for subtraction setp - neg #(`XLEN) negx(XSavedE, XnE); - mux2 #(`XLEN) xabsmux(XSavedE, XnE, SignedDivideE & SignXE, XInitE); // need original X as remainder if doing divide by 0 + neg #(`XLEN) negd(DinE, DnE); + mux2 #(`XLEN) dabsmux(DnE, DinE, SignedDivideE & SignDE, DAbsBE); // take absolute value for signed operations, and negate for subtraction setp + neg #(`XLEN) negx(XinE, XnE); + mux2 #(`XLEN) xabsmux(XinE, XnE, SignedDivideE & SignXE, XInitE); // need original X as remainder if doing divide by 0 // initialization multiplexers on first cycle of operation (one cycle after start is asserted) mux2 #(`XLEN) wmux(WM, {`XLEN{1'b0}}, DivInitE, WE[0]); @@ -106,7 +119,7 @@ module intdivrestoring ( end else if (BusyE & ~DivDoneM) begin // pause one cycle at beginning of signed operations for absolute value DivInitE = 0; step = step + 1; - if (step[STEPBITS]) begin + if (step[STEPBITS] | (`XLEN==64) & W64E & step[STEPBITS-1]) begin // complete in half the time for W-type instructions step = 0; BusyE = 0; DivDoneM = 1; diff --git a/wally-pipelined/src/muldiv/intdivrestoringstep.sv b/wally-pipelined/src/muldiv/intdivrestoringstep.sv index 339695fc..73c4b546 100644 --- a/wally-pipelined/src/muldiv/intdivrestoringstep.sv +++ b/wally-pipelined/src/muldiv/intdivrestoringstep.sv @@ -34,11 +34,10 @@ module intdivrestoringstep( logic [`XLEN-1:0] WShift, WPrime; logic qi, qib; - assign {WShift, XQOut} = {W[`XLEN-2:0], XQ, qi}; - adder #(`XLEN+1) wdsub({1'b0, WShift}, {1'b1, DAbsB}, {qib, WPrime}); - //assign {qib, WPrime} = {1'b0, WShift} + {1'b1, DAbsB}; // effective subtractor, carry out determines quotient bit + assign {WShift, XQOut} = {W[`XLEN-2:0], XQ, qi}; // shift W and X/Q left, insert quotient bit at bottom + adder #(`XLEN+1) wdsub({1'b0, WShift}, {1'b1, DAbsB}, {qib, WPrime}); // effective subtractor, carry out determines quotient bit assign qi = ~qib; - mux2 #(`XLEN) wrestoremux(WShift, WPrime, qi, WOut); + mux2 #(`XLEN) wrestoremux(WShift, WPrime, qi, WOut); // if quotient is zero, restore W endmodule /* verilator lint_on UNOPTFLAT */ diff --git a/wally-pipelined/src/muldiv/muldiv.sv b/wally-pipelined/src/muldiv/muldiv.sv index 7cccf2d7..b887fa9d 100644 --- a/wally-pipelined/src/muldiv/muldiv.sv +++ b/wally-pipelined/src/muldiv/muldiv.sv @@ -65,20 +65,12 @@ module muldiv ( flopenrc #(`XLEN*2) ProdMReg(clk, reset, FlushM, ~StallM, ProdE, ProdM); // Divide - - // Handle sign extension for W-type instructions - if (`XLEN == 64) begin // RV64 has W-type instructions - assign XE = W64E ? {{32{SrcAE[31]&SignedDivideE}}, SrcAE[31:0]} : SrcAE; - assign DE = W64E ? {{32{SrcBE[31]&SignedDivideE}}, SrcBE[31:0]} : SrcBE; - end else begin // RV32 has no W-type instructions - assign XE = SrcAE; - assign DE = SrcBE; - end - + assign XE = SrcAE; + assign DE = SrcBE; assign SignedDivideE = ~Funct3E[0]; // simplified from (Funct3E[2]&~Funct3E[1]&~Funct3E[0]) | (Funct3E[2]&Funct3E[1]&~Funct3E[0]); //intdiv #(`XLEN) div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, StartDivideE, SignedDivideE); intdivrestoring div(.clk, .reset, .StallM, .FlushM, - .SignedDivideE, .StartDivideE, .XE, .DE, .BusyE, .DivDoneM, .QuotM, .RemM); + .SignedDivideE, .W64E, .StartDivideE, .XE, .DE, .BusyE, .DivDoneM, .QuotM, .RemM); // Start a divide when a new division instruction is received and the divider isn't already busy or finishing assign StartDivideE = MulDivE & Funct3E[2] & ~BusyE & ~DivDoneM; diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 65fc5681..3f6d449e 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -161,6 +161,10 @@ string tests32f[] = '{ }; string tests64m[] = '{ + "rv64m/I-REMUW-01", "3000", + "rv64m/I-REMW-01", "3000", + "rv64m/I-DIVUW-01", "3000", + "rv64m/I-DIVW-01", "3000", "rv64m/I-MUL-01", "3000", "rv64m/I-MULH-01", "3000", "rv64m/I-MULHSU-01", "3000", @@ -168,12 +172,8 @@ string tests32f[] = '{ "rv64m/I-MULW-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-REMU-01", "3000", - "rv64m/I-REMUW-01", "3000", - "rv64m/I-REMW-01", "3000" + "rv64m/I-REMU-01", "3000" }; string tests64ic[] = '{ @@ -536,11 +536,11 @@ string tests32f[] = '{ tests = {tests64p,tests64i, tests64periph}; if (`C_SUPPORTED) tests = {tests, tests64ic}; else tests = {tests, tests64iNOc}; - if (`M_SUPPORTED) tests = {tests, tests64m}; if (`F_SUPPORTED) tests = {tests64f, tests}; if (`D_SUPPORTED) tests = {tests64d, tests}; if (`MEM_VIRTMEM) tests = {tests64mmu, tests}; if (`A_SUPPORTED) tests = {tests64a, tests}; + if (`M_SUPPORTED) tests = {tests64m, tests}; end //tests = {tests64a, tests}; end else begin // RV32