diff options
Diffstat (limited to 'translate/grt/grt-vcd.adb')
-rw-r--r-- | translate/grt/grt-vcd.adb | 98 |
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 |