summaryrefslogtreecommitdiff
path: root/translate/grt/grt-vcd.adb
diff options
context:
space:
mode:
Diffstat (limited to 'translate/grt/grt-vcd.adb')
-rw-r--r--translate/grt/grt-vcd.adb98
1 files changed, 96 insertions, 2 deletions
diff --git a/translate/grt/grt-vcd.adb b/translate/grt/grt-vcd.adb
index bf1842d..b2e3dfa 100644
--- a/translate/grt/grt-vcd.adb
+++ b/translate/grt/grt-vcd.adb
@@ -257,6 +257,9 @@ package body Grt.Vcd is
if Rti1.Kind = Ghdl_Rtik_Type_I32 then
return Vcd_Integer32;
end if;
+ if Rti1.Kind = Ghdl_Rtik_Type_F64 then
+ return Vcd_Float64;
+ end if;
return Vcd_Bad;
end Rti_To_Vcd_Kind;
@@ -395,6 +398,8 @@ package body Grt.Vcd is
case Vcd_El.Kind is
when Vcd_Integer32 =>
Vcd_Put ("integer 32");
+ when Vcd_Float64 =>
+ Vcd_Put ("real 64");
when Vcd_Bool
| Vcd_Bit
| Vcd_Stdlogic =>
@@ -548,6 +553,85 @@ package body Grt.Vcd is
end loop;
end Vcd_Put_Integer32;
+ -- Using the floor attribute of Ghdl_F64 will result on a link error while
+ -- trying to simulate a design. So it was needed to create a floor function
+ function Digit_Floor (V : Ghdl_F64) return Ghdl_I32
+ is
+ Var : Ghdl_I32;
+ begin
+ -- V is alway positiv in our case and we are only interested when it is a digit
+ if V > 10.0 then
+ return -1;
+ else
+ Var := Ghdl_I32(V-0.5); --Ghdl_I32 rounds to the nearest integer
+ -- The rounding made by Ghdl_I32 is asymetric :
+ -- 0.5 will be rounded to 1, but -0.5 to -1 instead of 0
+ if Var > 0 then
+ return Var;
+ else
+ return 0;
+ end if;
+ end if;
+ end Digit_Floor;
+
+ procedure Vcd_Put_Float64 (V : Ghdl_F64)
+ is
+ Val_tmp, Fact : Ghdl_F64;
+ Digit, Exp, Delta_Exp, N_Exp : Ghdl_I32;
+ --
+ begin
+ Exp := 0;
+ if V /= V then
+ Vcd_Put("NaN");
+ return;
+ end if;
+ if V < 0.0 then
+ Vcd_Putc ('-');
+ Val_tmp := -V;
+ elsif V = 0.0 then
+ Vcd_Put("0.0");
+ return;
+ else
+ Val_tmp := V;
+ end if;
+ if Val_tmp > Ghdl_F64'Last then
+ Vcd_Put("Inf");
+ return;
+ elsif Val_tmp < 1.0 then
+ Fact := 10.0;
+ Delta_Exp := -1;
+ else
+ Fact := 0.1;
+ Delta_Exp := 1;
+ end if;
+ while 1 = 1 loop -- Seek the first digit
+ Digit := Digit_Floor(Val_tmp);
+ if Digit > 0 then
+ exit;
+ end if;
+ Exp := Exp + Delta_Exp;
+ Val_tmp := Val_tmp * Fact;
+ end loop;
+ Vcd_Putc(Character'Val(Digit + 48));
+ Vcd_Putc('.');
+ for i in 0..4 loop -- 5 digits displayed after the point
+ Val_tmp := abs(Val_tmp - Ghdl_F64(Digit))*10.0;
+ Digit := Digit_Floor(Val_tmp);
+ Vcd_Putc(Character'Val(Digit + 48));
+ end loop;
+ Vcd_Putc('E');
+ if Exp < 0 then
+ Vcd_Putc('-');
+ Exp := -Exp;
+ end if;
+ N_Exp := 100;
+ while N_Exp > 0 loop
+ Vcd_Putc(Character'Val(Exp/N_Exp + 48));
+ Exp := Exp Mod N_Exp;
+ N_Exp := N_Exp/10;
+ end loop;
+ end Vcd_Put_Float64;
+
procedure Vcd_Put_Var (I : Vcd_Index_Type)
is
Addr : Address;
@@ -572,6 +656,10 @@ package body Grt.Vcd is
Vcd_Putc ('b');
Vcd_Put_Integer32 (To_Signal_Arr_Ptr (Addr)(0).Value.E32);
Vcd_Putc (' ');
+ when Vcd_Float64 =>
+ Vcd_Putc ('r');
+ Vcd_Put_Float64 (To_Signal_Arr_Ptr (Addr)(0).Value.F64);
+ Vcd_Putc (' ');
when Vcd_Bitvector =>
Vcd_Putc ('b');
for J in 0 .. Len - 1 loop
@@ -601,6 +689,10 @@ package body Grt.Vcd is
Vcd_Put_Integer32
(To_Signal_Arr_Ptr (Addr)(0).Driving_Value.E32);
Vcd_Putc (' ');
+ when Vcd_Float64 =>
+ Vcd_Putc ('r');
+ Vcd_Put_Float64 (To_Signal_Arr_Ptr (Addr)(0).Driving_Value.F64);
+ Vcd_Putc (' ');
when Vcd_Bitvector =>
Vcd_Putc ('b');
for J in 0 .. Len - 1 loop
@@ -643,7 +735,8 @@ package body Grt.Vcd is
| Vcd_Stdlogic
| Vcd_Bitvector
| Vcd_Stdlogic_Vector
- | Vcd_Integer32 =>
+ | Vcd_Integer32
+ | Vcd_Float64 =>
for J in 0 .. Len - 1 loop
if To_Signal_Arr_Ptr (Info.Addr)(J).Last_Event = Last then
return True;
@@ -659,7 +752,8 @@ package body Grt.Vcd is
| Vcd_Stdlogic
| Vcd_Bitvector
| Vcd_Stdlogic_Vector
- | Vcd_Integer32 =>
+ | Vcd_Integer32
+ | Vcd_Float64 =>
for J in 0 .. Len - 1 loop
if To_Signal_Arr_Ptr (Info.Addr)(J).Last_Active = Last
then