Commit 6b449c12 authored by Benoit Rat's avatar Benoit Rat

field: improve convertion and test unit

We still need to

* improve overflow checking
* add full 32bit Fixed Point support
* throw exceptions when bad constructor parameters
parent 065de6b7
......@@ -60,6 +60,13 @@ EWBField::EWBField(EWBReg *pReg,
for (; mask; mask >>= 1, i++)
this->width=i-shift;
if(this->type==EWBF_32FP) {
if((this->width > this->nfb)==false) TRACE_P_WARNING("%s Width (%d) must be superior than nbfp (%d)",getCName(),width,nfb);
}
else {
if((this->width >= this->nfb)==false) TRACE_P_WARNING("%s Width (%d) must be superior or equal than nbfp (%d)",getCName(),width,nfb);
}
if(pReg)
{
......@@ -145,8 +152,41 @@ bool EWBField::regCvt(float *value, uint32_t *reg_data, bool to_value) const
ret=this->regCvt(&fixed,reg_data,to_value);
}
break;
case EWBF_32I:
utmp=(1<<(this->width-1));
if(to_value)
{
ret=this->regCvt(&fixed,reg_data,to_value);
if(fixed & utmp) *value=-1.f*(float)(fixed & ~utmp);
else *value=(float)fixed;
}
else
{
fixed=(uint32_t)round(fabs(*value)) & ~utmp;
if(*value<0) fixed |=utmp;
ret=this->regCvt(&fixed,reg_data,to_value);
}
break;
case EWBF_TM_SIGN_2COMP:
if(to_value)
{
ret=this->regCvt(&fixed,reg_data,to_value);
if (fixed & (1 << (this->width-1))) //Negative 2C
{
fixed=((~fixed)+1) & (this->mask >> this->shift);
*value=-1.f*(float)fixed;
}
else
*value=(float)fixed;
}
else
{
fixed=(uint32_t)round(fabs(*value));
if(*value<0) fixed=(~(fixed))+1; //convert absolute signed fixed point to 2C fixed point when value <0
ret=this->regCvt(&fixed,reg_data,to_value);
}
break;
case EWBF_TM_FIXED_POINT: //Unsigned Fixed point conversion
case EWBF_32FP: //Signed Fixed point conversion
if(to_value)
{
ret=this->regCvt(&fixed,reg_data,to_value);
......@@ -158,6 +198,21 @@ bool EWBField::regCvt(float *value, uint32_t *reg_data, bool to_value) const
ret=this->regCvt(&fixed,reg_data,to_value);
}
break;
case EWBF_32FP: //Signed Fixed point conversion
utmp=(1<<(this->width-1));
if(to_value)
{
ret=this->regCvt(&fixed,reg_data,to_value);
if(fixed & utmp) *value=-1.f*(float)((fixed & ~utmp)/pow(2,this->nfb));
else *value=(float)(fixed/pow(2,this->nfb));
}
else
{
fixed=(uint32_t)(round(fabs(*value) * pow(2,this->nfb))) & ~utmp;
if(*value<0) fixed |=utmp;
ret=this->regCvt(&fixed,reg_data,to_value);
}
break;
case EWBF_32F2C: //2 complements fixed point conversion
if(to_value)
{
......@@ -165,10 +220,10 @@ bool EWBField::regCvt(float *value, uint32_t *reg_data, bool to_value) const
if (fixed & (1 << (this->width-1)))
{
fixed=((~fixed)+1) & (this->mask >> this->shift) ; //Convert negative 2C to negative Fixed Point
*value=(-1.f / (float)(1<<this->nfb)) * (float)fixed; // then to floating
*value=(-1.f / (float)(1ULL<<this->nfb)) * (float)fixed; // then to floating
}
else
*value= (1.f / (float)(1<<this->nfb)) * (float)fixed; //Convert directly Fixed Point to Floating Point
*value= (1.f / (float)(1ULL<<this->nfb)) * (float)fixed; //Convert directly Fixed Point to Floating Point
}
else
{
......@@ -176,9 +231,10 @@ bool EWBField::regCvt(float *value, uint32_t *reg_data, bool to_value) const
if(checkOverflow)
{
utmp=1 << ((this->width-this->nfb)-1);
if(ftmp >= utmp) ftmp=(float)utmp;
if(ftmp >= utmp)
ftmp=(float)utmp;
}
fixed=round(ftmp * (float)(1 << this->nfb)); //convert to signed fixed point using absolute value
fixed=round((double)ftmp * (double)(1ULL << this->nfb)); //convert to signed fixed point using absolute value
if(*value<0) fixed=(~(fixed))+1; //convert absolute signed fixed point to 2C fixed point when value <0
ret=this->regCvt(&fixed,reg_data,to_value);
}
......
......@@ -10,8 +10,6 @@
#include "files/wbtest.h"
//EWBField f(NULL,WB2_FIELD_ARGS(TEST,CSR,RST));
namespace
{
......@@ -27,7 +25,7 @@ TEST(EWBField,ConstructorRst)
EXPECT_EQ(WB2_TEST_CSR_RST_NBFP,f.getNOfFractionBit());
EXPECT_EQ(0,f.getFloat());
std::cout << f << std::endl;
//std::cout << f << std::endl;
}
......@@ -43,9 +41,304 @@ TEST(EWBField,ConstructorNumber)
EXPECT_EQ(0,f.getFloat());
}
//TEST(EWBField,ConstructorNumber)
TEST(EWBField,ReadOnly)
{
EWBField f(NULL,WB2_FIELD_ARGS(TEST,CSR,NUMBER));
uint32_t val=123;
uint32_t reg;
EXPECT_FALSE(f.isValid());
EXPECT_FALSE(f.convert(&val,true)); //No EWBReg defined
EXPECT_TRUE(f.regCvt(&val,&reg,true));
f.getU32();
}
TEST(EWBField,CvtIQ)
{
EWBField fI(NULL,WB2_FIELD_ARGS(TEST,DAC,I));
EWBField fQ(NULL,WB2_FIELD_ARGS(TEST,DAC,Q));
float I=0.5436,Q=0.0234;
float abs_error=0.01;
float Irbk,Qrbk;
uint32_t reg1=0, reg2=0, reg_tmp;
EXPECT_FALSE(fI.isValid());
EXPECT_FALSE(fI.convert(&I,true)); //EWBReg is NULL
EXPECT_TRUE(fI.regCvt(&I,&reg1,false));
EXPECT_TRUE(fI.regCvt(&Irbk,&reg1,true));
EXPECT_NEAR(I, Irbk, abs_error);
reg_tmp=reg1;
EXPECT_FALSE(fQ.isValid());
EXPECT_FALSE(fQ.convert(&Q,true)); //EWBReg is NULL
EXPECT_TRUE(fQ.regCvt(&Q,&reg1,false));
EXPECT_TRUE(fQ.regCvt(&Qrbk,&reg1,true));
EXPECT_NEAR(Q, Qrbk, abs_error);
//Check Register mask
EXPECT_NE(reg_tmp,reg1);
EXPECT_EQ(reg_tmp,reg1 & WB2_TEST_DAC_I_MASK);
EXPECT_TRUE(fQ.regCvt(&Q,&reg2,false));
reg_tmp=reg2;
EXPECT_TRUE(fI.regCvt(&I,&reg2,false));
EXPECT_NE(reg_tmp,reg2);
EXPECT_EQ(reg_tmp,reg2 & WB2_TEST_DAC_Q_MASK);
EXPECT_EQ(reg2,reg1);
}
TEST(EWBField,CvtAmpPh)
{
EWBField fA(NULL,WB2_FIELD_ARGS(TEST,ADC,AMP));
EWBField fP(NULL,WB2_FIELD_ARGS(TEST,ADC,PHA));
float Amp,Pha;
float AmpRbk,PhaRbk;
float AmpErr=0.01,PhaErr=0.1;
uint32_t reg=0;
//Start playing with conversion
Amp=0;
EXPECT_TRUE(fA.regCvt(&Amp,&reg,false));
EXPECT_TRUE(fA.regCvt(&AmpRbk,&reg,true));
EXPECT_NEAR(Amp,AmpRbk,AmpErr);
Amp=-1/3;
EXPECT_TRUE(fA.regCvt(&Amp,&reg,false));
EXPECT_TRUE(fA.regCvt(&AmpRbk,&reg,true));
EXPECT_NEAR(Amp,AmpRbk,AmpErr);
Amp=-2;
EXPECT_TRUE(fA.regCvt(&Amp,&reg,false));
EXPECT_TRUE(fA.regCvt(&AmpRbk,&reg,true));
EXPECT_NEAR(Amp,AmpRbk,AmpErr);
Amp=1.11111;
EXPECT_TRUE(fA.regCvt(&Amp,&reg,false));
EXPECT_TRUE(fA.regCvt(&AmpRbk,&reg,true));
EXPECT_NEAR(Amp,AmpRbk,AmpErr);
Amp=1.8;
EXPECT_TRUE(fA.regCvt(&Amp,&reg,false));
EXPECT_TRUE(fA.regCvt(&AmpRbk,&reg,true));
EXPECT_NEAR(Amp,AmpRbk,AmpErr);
//TODO: Correct this case
Amp=2;
EXPECT_TRUE(fA.regCvt(&Amp,&reg,false));
EXPECT_TRUE(fA.regCvt(&AmpRbk,&reg,true));
EXPECT_TRUE(fA.isOverflowPrevented());
EXPECT_NEAR(Amp,AmpRbk,AmpErr);
Pha=0;
EXPECT_TRUE(fP.regCvt(&Pha,&reg,false));
EXPECT_TRUE(fP.regCvt(&PhaRbk,&reg,true));
EXPECT_NEAR(Pha,PhaRbk,PhaErr);
Pha=180;
EXPECT_TRUE(fP.regCvt(&Pha,&reg,false));
EXPECT_TRUE(fP.regCvt(&PhaRbk,&reg,true));
EXPECT_NEAR(Pha,PhaRbk,PhaErr);
Pha=-179;
EXPECT_TRUE(fP.regCvt(&Pha,&reg,false));
EXPECT_TRUE(fP.regCvt(&PhaRbk,&reg,true));
EXPECT_NEAR(Pha,PhaRbk,PhaErr);
Pha=(2*180/3.f);
EXPECT_TRUE(fP.regCvt(&Pha,&reg,false));
EXPECT_TRUE(fP.regCvt(&PhaRbk,&reg,true));
EXPECT_NEAR(Pha,PhaRbk,PhaErr);
Pha=128.5;
EXPECT_TRUE(fP.regCvt(&Pha,&reg,false));
EXPECT_TRUE(fP.regCvt(&PhaRbk,&reg,true));
EXPECT_EQ(0x404,reg >> 16); //128<<3 |(int)(0.5f/0.125f));
EXPECT_NEAR(Pha,PhaRbk,PhaErr);
uint32_t tmp;
EXPECT_TRUE(fP.regCvt(&tmp,&reg,true));
EXPECT_EQ(0x404,tmp);
}
/**
* This test check if everything works fine when we use
* the 32bit as unsigned integer.
*/
TEST(EWBField,FullU32)
{
EWBField f(NULL,WB2_FIELD_ARGS(TEST,FULL,U32));
uint32_t val,valRbk;
uint32_t reg=0;
val=0xFFFFFFFF;
EXPECT_TRUE(f.regCvt(&val,&reg,false));
EXPECT_TRUE(f.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
EXPECT_EQ(val,reg);
val=0xAAAAAAAA;
EXPECT_TRUE(f.regCvt(&val,&reg,false));
EXPECT_TRUE(f.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
EXPECT_EQ(val,reg);
val=0x55555555;
EXPECT_TRUE(f.regCvt(&val,&reg,false));
EXPECT_TRUE(f.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
EXPECT_EQ(val,reg);
}
/**
* This test check when the 32bits of the register
* are used as fixed decimal bit.
*/
TEST(EWBField,FullFixed)
{
EWBField f(NULL,WB2_FIELD_ARGS(TEST,FULLFIXED,ALL));
float val,valRbk,valErr=0.000001;
uint32_t reg=0;
//Start playing with conversion
val=-0.999991;
EXPECT_TRUE(f.regCvt(&val,&reg,false));
EXPECT_TRUE(f.regCvt(&valRbk,&reg,true));
EXPECT_NEAR(val,valRbk,valErr);
//Start playing with conversion
val= 0.999991;
EXPECT_TRUE(f.regCvt(&val,&reg,false));
EXPECT_TRUE(f.regCvt(&valRbk,&reg,true));
EXPECT_NEAR(val,valRbk,valErr);
//Start playing with conversion
val=-0.000000001;
EXPECT_TRUE(f.regCvt(&val,&reg,false));
EXPECT_TRUE(f.regCvt(&valRbk,&reg,true));
EXPECT_NEAR(val,valRbk,valErr);
uint32_t regTmp=reg;
//Start playing with conversion
val=+0.000000001;
EXPECT_TRUE(f.regCvt(&val,&reg,false));
EXPECT_TRUE(f.regCvt(&valRbk,&reg,true));
EXPECT_NEAR(val,valRbk,valErr);
EXPECT_NEAR(0,reg-regTmp,10); //The two value should be really near (when 2c)
}
TEST(EWBField,Signess)
{
uint32_t reg=0;
float val,valRbk;
//Unsigned byte
EWBField fU=EWBField(NULL,WB2_FIELD_ARGS(TEST,BSIGN,U));
val=255;
EXPECT_TRUE(fU.regCvt(&val,&reg,false));
EXPECT_TRUE(fU.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
val=-128;
EXPECT_TRUE(fU.regCvt(&val,&reg,false));
EXPECT_TRUE(fU.regCvt(&valRbk,&reg,true));
EXPECT_NE(val,valRbk);
EXPECT_EQ(-val,valRbk);
EWBField f1=EWBField(NULL,WB2_FIELD_ARGS(TEST,BSIGN,SIGN1));
val=127;
EXPECT_TRUE(f1.regCvt(&val,&reg,false));
EXPECT_TRUE(f1.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
uint32_t regTmp=reg;
val=-127;
EXPECT_TRUE(f1.regCvt(&val,&reg,false));
EXPECT_TRUE(f1.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
EXPECT_NE(regTmp,reg);
val=-128;
EXPECT_TRUE(f1.regCvt(&val,&reg,false));
EXPECT_TRUE(f1.regCvt(&valRbk,&reg,true));
EXPECT_NE(val,valRbk);
EXPECT_EQ(0,valRbk);
//printf("x%x x%x\n",reg,regTmp);
EWBField f2=EWBField(NULL,WB2_FIELD_ARGS(TEST,BSIGN,SIGN2));
val=127;
EXPECT_TRUE(f2.regCvt(&val,&reg,false));
EXPECT_TRUE(f2.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
val=-128;
EXPECT_TRUE(f2.regCvt(&val,&reg,false));
EXPECT_TRUE(f2.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
}
TEST(EWBField,FixedSigness)
{
uint32_t reg=0;
float val,valRbk;
float step8=1/(256.f);
float step7=1/(128.f);
//Unsigned byte
EWBField fU=EWBField(NULL,WB2_FIELD_ARGS(TEST,BFIXED,U));
val=0.00390625; // 1/256
EXPECT_TRUE(fU.regCvt(&val,&reg,false));
EXPECT_TRUE(fU.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
val=-0.125;
EXPECT_TRUE(fU.regCvt(&val,&reg,false));
EXPECT_TRUE(fU.regCvt(&valRbk,&reg,true));
EXPECT_NE(val,valRbk);
EXPECT_TRUE(valRbk>0);
EWBField f1=EWBField(NULL,WB2_FIELD_ARGS(TEST,BFIXED,SIGN1));
val=(1-step7);
EXPECT_TRUE(f1.regCvt(&val,&reg,false));
EXPECT_TRUE(f1.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
val=-(1-step7);
EXPECT_TRUE(f1.regCvt(&val,&reg,false));
EXPECT_TRUE(f1.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
EWBField f2=EWBField(NULL,WB2_FIELD_ARGS(TEST,BFIXED,SIGN2));
val=0.5-step8;
EXPECT_TRUE(f2.regCvt(&val,&reg,false));
EXPECT_TRUE(f2.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
val=-0.5;
EXPECT_TRUE(f2.regCvt(&val,&reg,false));
EXPECT_TRUE(f2.regCvt(&valRbk,&reg,true));
EXPECT_EQ(val,valRbk);
}
//TEST(EWBField,Overflow)
//{
// EXPECT_NEAR(val1, val2, abs_error);
// EWBField f(NULL,WB2_FIELD_ARGS(TEST,CSR,NUMBER));
// uint32_t val=28389;
// f.convert(&val,true);
//Amp=-3;
//EXPECT_TRUE(fA.regCvt(&Amp,&reg,false));
//EXPECT_TRUE(fA.regCvt(&AmpRbk,&reg,true));
//EXPECT_NEAR(Amp,AmpRbk,AmpErr);
//}
}
This diff is collapsed.
top = peripheral {
name = "TestWB";
name = "TestWB";
description = "Fake peripheral to test all possibilities";
hdl_entity = "wb_test";
c_prefix = "WB2_test";
hdl_prefix = "WB2Test";
reg {
c_prefix = "WB2_test";
hdl_prefix = "WB2Test";
reg {
name = "Control Statut Register";
description = "Reset";
prefix = "CSR";
......@@ -20,7 +20,6 @@ top = peripheral {
load = LOAD_EXT;
};
field {
name = "Enable";
description = "This registers indicates the ADC chip selected";
......@@ -40,14 +39,14 @@ top = peripheral {
align = 8;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
};
reg {
name = "ADC_IQ";
reg {
name = "DAC_IQ";
description = "I,Q repreTypicial Amplitude P.";
prefix = "adc";
prefix = "dac";
field {
name = "I";
......@@ -58,7 +57,7 @@ top = peripheral {
nbfp = 14;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
field {
name = "Q";
......@@ -70,11 +69,40 @@ top = peripheral {
align = 16;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
};
reg {
name = "ADC";
description = "Amplitude/Phase representation";
prefix = "adc";
field {
name = "Amplitude";
description = "Voltage units: 16 bits with 2 bits integer (2'complement)";
prefix = "Amp";
type = SLV;
size = 16;
nbfp = 14;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Phase";
description = "Degrees units: 16 bits with 13 bits integer (2'complement)";
prefix = "Pha";
type = SLV;
size = 16;
nbfp = 3;
align = 16;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
reg {
name = "Full Integer";
description = "Minimun Voltage register until Reset";
prefix = "Full";
......@@ -87,10 +115,11 @@ top = peripheral {
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
};
reg {
reg {
name = "Full Fixed Integer";
description = "Minimun Voltage register until Reset";
prefix = "FullFixed";
......@@ -104,14 +133,14 @@ top = peripheral {
nbfp = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
};
reg {
name = "TestByteSign";
description = "Test on the 4 bytes";
prefix = "testbsign";
prefix = "bsign";
field {
name = "Unsigned";
......@@ -136,7 +165,6 @@ top = peripheral {
access_dev = WRITE_ONLY;
};
field {
name = "Sign2C";
description = "2Complement's signess";
......@@ -144,17 +172,19 @@ top = peripheral {
type = SLV;
size = 8;
align = 16;
sign= 1;
sign= 2;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
};
reg {
name = "TestByteFixed";
description = "Test full fixed point on the 4 bytes";
prefix = "testbfixed";
field {
prefix = "bfixed";
field {
name = "Unsigned";
description = "Unsigned byte";
prefix = "u";
......@@ -179,7 +209,6 @@ top = peripheral {
access_dev = WRITE_ONLY;
};
field {
name = "Sign2C";
description = "2Complement's signess";
......@@ -188,11 +217,10 @@ top = peripheral {
size = 8;
align = 16;
nbfp = 8;
sign = 1;
sign = 2;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
field {
name = "Default";
......@@ -202,10 +230,8 @@ top = peripheral {
size = 8;
align = 24;
nbfp = 8;
sign = 2;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
};
};
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