From e707eeb7c80c12dcbe86c41d293ad9caeceae989 Mon Sep 17 00:00:00 2001 From: "James E. Stine" Date: Fri, 12 Jan 2024 00:37:50 -0600 Subject: [PATCH] THis includes fix for special case when conversion from fp to int/long. The previous src did not test both the flags and result and so missed this subtle bug when an Invalid happens for this type of conversion. These results are indications of undefined behavior for these operations. All fp operations now passs when this update is fixed. Much of the information why these outputs should occur is somewhat alluded to by Pascal Cuoq originally from INSA in Lyon here: https://frama-c.com/2013/10/09/Overflow-float-integer.html --- src/fpu/postproc/specialcase.sv | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/fpu/postproc/specialcase.sv b/src/fpu/postproc/specialcase.sv index c8442595a..b765375d1 100644 --- a/src/fpu/postproc/specialcase.sv +++ b/src/fpu/postproc/specialcase.sv @@ -266,28 +266,34 @@ module specialcase import cvw::*; #(parameter cvw_t P) ( // integer result selection /////////////////////////////////////////////////////////////////////////////////////// + // Causes undefined behavior for invalid: + // unsigned: if invalid (e.g., negative fp to unsigned int, result should overflow and + // overflows to the maximum value + // signed: if invalid, result should overflow to maximum negative value + // but is undefined and used for information only + // select the overflow integer res // - negitive infinity and out of range negitive input - // | int | long | - // signed | -2^31 | -2^63 | - // unsigned | 0 | 0 | + // | int | long | + // signed | -2^31 | -2^63 | + // unsigned | 2^32-1 | 2^64-1 | // // - positive infinity and out of range positive input and NaNs // | int | long | - // signed | 2^31-1 | 2^63-1 | + // signed | -2^31 |-2^63 | // unsigned | 2^32-1 | 2^64-1 | // - // other: 32 bit unsinged res should be sign extended as if it were a signed number + // other: 32 bit unsigned res should be sign extended as if it were a signed number always_comb if(Signed) if(Xs&~NaNIn) // signed negitive if(Int64) OfIntRes = {1'b1, {P.XLEN-1{1'b0}}}; else OfIntRes = {{P.XLEN-32{1'b1}}, 1'b1, {31{1'b0}}}; else // signed positive - if(Int64) OfIntRes = {1'b0, {P.XLEN-1{1'b1}}}; - else OfIntRes = {{P.XLEN-32{1'b0}}, 1'b0, {31{1'b1}}}; + if(Int64) OfIntRes = {1'b1, {P.XLEN-1{1'b0}}}; + else OfIntRes = {{P.XLEN-32{1'b1}}, 1'b1, {31{1'b0}}}; else - if(Xs&~NaNIn) OfIntRes = {P.XLEN{1'b0}}; // unsigned negitive + if(Xs&~NaNIn) OfIntRes = {P.XLEN{1'b1}}; // unsigned negitive else OfIntRes = {P.XLEN{1'b1}}; // unsigned positive // select the integer output