aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2022-06-03 08:32:59 +0200
committerTristan Gingold <tgingold@free.fr>2022-06-03 08:32:59 +0200
commit0875ce87c2e565023a350faf444ca2b3e3477ec7 (patch)
treec8d3e4a40045eca7e0d61852f99d1364086e175d
parent10f847e928897cb420a4dae0785e412ba5b3dfe0 (diff)
downloadghdl-0875ce87c2e565023a350faf444ca2b3e3477ec7.tar.gz
ghdl-0875ce87c2e565023a350faf444ca2b3e3477ec7.tar.bz2
ghdl-0875ce87c2e565023a350faf444ca2b3e3477ec7.zip
synth-vhdl_eval: handle more operations
-rw-r--r--src/synth/synth-ieee-numeric_std.adb270
-rw-r--r--src/synth/synth-ieee-numeric_std.ads17
-rw-r--r--src/synth/synth-vhdl_eval.adb101
3 files changed, 384 insertions, 4 deletions
diff --git a/src/synth/synth-ieee-numeric_std.adb b/src/synth/synth-ieee-numeric_std.adb
index 7f5d0cbf2..d23b4e858 100644
--- a/src/synth/synth-ieee-numeric_std.adb
+++ b/src/synth/synth-ieee-numeric_std.adb
@@ -920,7 +920,7 @@ package body Synth.Ieee.Numeric_Std is
Dlen : constant Uns32 := Dem.Typ.Abound.Len;
pragma Assert (Nlen > 0);
pragma Assert (Dlen > 0);
- pragma Assert (Quot.Typ.Abound.Len = Nlen);
+ pragma Assert (Quot.Typ = null or else Quot.Typ.Abound.Len = Nlen);
Reg : Std_Logic_Vector_Type (0 .. Dlen);
Sub : Std_Logic_Vector_Type (0 .. Dlen - 1);
Carry : Sl_X01;
@@ -944,7 +944,9 @@ package body Synth.Ieee.Numeric_Std is
-- Extra REG bit.
Carry := Compute_Carry (Carry, Reg (0), '1');
-- Test
- Write_Std_Logic (Quot.Mem, I, Carry);
+ if Quot.Mem /= null then
+ Write_Std_Logic (Quot.Mem, I, Carry);
+ end if;
if Carry = '1' then
Reg (0) := '0';
Reg (1 .. Dlen) := Sub;
@@ -1003,6 +1005,28 @@ package body Synth.Ieee.Numeric_Std is
return Quot;
end Div_Uns_Uns;
+ function Div_Uns_Nat (L : Memtyp; R : Uns64; Loc : Syn_Src) return Memtyp
+ is
+ Rv : Memtyp;
+ begin
+ if L.Typ.Abound.Len = 0 then
+ return Create_Memory (L.Typ); -- FIXME: typ
+ end if;
+ Rv := To_Unsigned (R, L.Typ);
+ return Div_Uns_Uns (L, Rv, Loc);
+ end Div_Uns_Nat;
+
+ function Div_Nat_Uns (L : Uns64; R : Memtyp; Loc : Syn_Src) return Memtyp
+ is
+ Lv : Memtyp;
+ begin
+ if R.Typ.Abound.Len = 0 then
+ return Create_Memory (R.Typ); -- FIXME: typ
+ end if;
+ Lv := To_Unsigned (L, R.Typ);
+ return Div_Uns_Uns (Lv, R, Loc);
+ end Div_Nat_Uns;
+
function Div_Sgn_Sgn (L, R : Memtyp; Loc : Syn_Src) return Memtyp
is
Nlen : constant Uns32 := L.Typ.Abound.Len;
@@ -1057,4 +1081,246 @@ package body Synth.Ieee.Numeric_Std is
return Quot;
end Div_Sgn_Sgn;
+ function Div_Sgn_Int (L : Memtyp; R : Int64; Loc : Syn_Src) return Memtyp
+ is
+ Rv : Memtyp;
+ begin
+ if L.Typ.Abound.Len = 0 then
+ return Create_Memory (L.Typ); -- FIXME: typ
+ end if;
+ Rv := To_Signed (R, L.Typ);
+ return Div_Sgn_Sgn (L, Rv, Loc);
+ end Div_Sgn_Int;
+
+ function Div_Int_Sgn (L : Int64; R : Memtyp; Loc : Syn_Src) return Memtyp
+ is
+ Lv : Memtyp;
+ begin
+ if R.Typ.Abound.Len = 0 then
+ return Create_Memory (R.Typ); -- FIXME: typ
+ end if;
+ Lv := To_Signed (L, R.Typ);
+ return Div_Sgn_Sgn (Lv, R, Loc);
+ end Div_Int_Sgn;
+
+ function Rem_Uns_Uns (L, R : Memtyp; Loc : Syn_Src) return Memtyp
+ is
+ Nlen : constant Uns32 := L.Typ.Abound.Len;
+ Dlen : constant Uns32 := R.Typ.Abound.Len;
+ Rema : Memtyp;
+ R0 : Sl_X01;
+ begin
+ Rema.Typ := Create_Res_Type (R.Typ, Dlen);
+ Rema := Create_Memory (Rema.Typ);
+ if Nlen = 0 or Dlen = 0 then
+ return Rema;
+ end if;
+
+ R0 := Has_0x (R);
+ if Has_0x (L) = 'X' or R0 = 'X' then
+ Warning_Msg_Synth
+ (+Loc, "NUMERIC_STD.""rem"": non logical value detected");
+ Fill (Rema, 'X');
+ return Rema;
+ end if;
+ if R0 = '0' then
+ Error_Msg_Synth (+Loc, "NUMERIC_STD.""rem"": division by 0");
+ Fill (Rema, 'X');
+ return Rema;
+ end if;
+ Divmod (L, R, Null_Memtyp, Rema);
+ return Rema;
+ end Rem_Uns_Uns;
+
+ function Rem_Uns_Nat (L : Memtyp; R : Uns64; Loc : Syn_Src) return Memtyp
+ is
+ Rv : Memtyp;
+ begin
+ if L.Typ.Abound.Len = 0 then
+ return Create_Memory (L.Typ); -- FIXME: typ
+ end if;
+ Rv := To_Unsigned (R, L.Typ);
+ return Rem_Uns_Uns (L, Rv, Loc);
+ end Rem_Uns_Nat;
+
+ function Rem_Nat_Uns (L : Uns64; R : Memtyp; Loc : Syn_Src) return Memtyp
+ is
+ Lv : Memtyp;
+ begin
+ if R.Typ.Abound.Len = 0 then
+ return Create_Memory (R.Typ); -- FIXME: typ
+ end if;
+ Lv := To_Unsigned (L, R.Typ);
+ return Rem_Uns_Uns (Lv, R, Loc);
+ end Rem_Nat_Uns;
+
+ function Rem_Sgn_Sgn (L, R : Memtyp; Loc : Syn_Src) return Memtyp
+ is
+ Nlen : constant Uns32 := L.Typ.Abound.Len;
+ Dlen : constant Uns32 := R.Typ.Abound.Len;
+ Rema : Memtyp;
+ R0 : Sl_X01;
+ Lu : Memtyp;
+ Ru : Memtyp;
+ Neg : Boolean;
+ begin
+ Rema.Typ := Create_Res_Type (L.Typ, Dlen);
+ Rema := Create_Memory (Rema.Typ);
+ if Nlen = 0 or Dlen = 0 then
+ return Rema;
+ end if;
+
+ R0 := Has_0x (R);
+ if Has_0x (L) = 'X' or R0 = 'X' then
+ Warning_Msg_Synth
+ (+Loc, "NUMERIC_STD.""rem"": non logical value detected");
+ Fill (Rema, 'X');
+ return Rema;
+ end if;
+ if R0 = '0' then
+ Error_Msg_Synth (+Loc, "NUMERIC_STD.""rem"": division by 0");
+ Fill (Rema, 'X');
+ return Rema;
+ end if;
+
+ if To_X01 (Read_Std_Logic (L.Mem, 0)) = '1' then
+ Lu.Typ := L.Typ;
+ Lu.Mem := Neg_Vec_Notyp (L);
+ Neg := True;
+ else
+ Neg := False;
+ Lu := L;
+ end if;
+
+ if To_X01 (Read_Std_Logic (R.Mem, 0)) = '1' then
+ Ru.Typ := R.Typ;
+ Ru.Mem := Neg_Vec_Notyp (R);
+ else
+ Ru := R;
+ end if;
+
+ Divmod (Lu, Ru, Null_Memtyp, Rema);
+
+ -- Result of rem has the sign of the dividend.
+ if Neg then
+ Neg_Vec (Rema);
+ end if;
+ return Rema;
+ end Rem_Sgn_Sgn;
+
+ function Rem_Sgn_Int (L : Memtyp; R : Int64; Loc : Syn_Src) return Memtyp
+ is
+ Rv : Memtyp;
+ begin
+ if L.Typ.Abound.Len = 0 then
+ return Create_Memory (L.Typ); -- FIXME: typ
+ end if;
+ Rv := To_Signed (R, L.Typ);
+ return Rem_Sgn_Sgn (L, Rv, Loc);
+ end Rem_Sgn_Int;
+
+ function Rem_Int_Sgn (L : Int64; R : Memtyp; Loc : Syn_Src) return Memtyp
+ is
+ Lv : Memtyp;
+ begin
+ if R.Typ.Abound.Len = 0 then
+ return Create_Memory (R.Typ); -- FIXME: typ
+ end if;
+ Lv := To_Signed (L, R.Typ);
+ return Rem_Sgn_Sgn (Lv, R, Loc);
+ end Rem_Int_Sgn;
+
+ function Mod_Sgn_Sgn (L, R : Memtyp; Loc : Syn_Src) return Memtyp
+ is
+ Nlen : constant Uns32 := L.Typ.Abound.Len;
+ Dlen : constant Uns32 := R.Typ.Abound.Len;
+ Rema : Memtyp;
+ R0 : Sl_X01;
+ Lu : Memtyp;
+ Ru : Memtyp;
+ L_Neg, R_Neg : Boolean;
+ begin
+ Rema.Typ := Create_Res_Type (L.Typ, Dlen);
+ Rema := Create_Memory (Rema.Typ);
+ if Nlen = 0 or Dlen = 0 then
+ return Rema;
+ end if;
+
+ R0 := Has_0x (R);
+ if Has_0x (L) = 'X' or R0 = 'X' then
+ Warning_Msg_Synth
+ (+Loc, "NUMERIC_STD.""rem"": non logical value detected");
+ Fill (Rema, 'X');
+ return Rema;
+ end if;
+ if R0 = '0' then
+ Error_Msg_Synth (+Loc, "NUMERIC_STD.""rem"": division by 0");
+ Fill (Rema, 'X');
+ return Rema;
+ end if;
+
+ if To_X01 (Read_Std_Logic (L.Mem, 0)) = '1' then
+ Lu.Typ := L.Typ;
+ Lu.Mem := Neg_Vec_Notyp (L);
+ L_Neg := True;
+ else
+ Lu := L;
+ L_Neg := False;
+ end if;
+
+ if To_X01 (Read_Std_Logic (R.Mem, 0)) = '1' then
+ Ru.Typ := R.Typ;
+ Ru.Mem := Neg_Vec_Notyp (R);
+ R_Neg := True;
+ else
+ Ru := R;
+ R_Neg := False;
+ end if;
+
+ Divmod (Lu, Ru, Null_Memtyp, Rema);
+
+ if Has_0x (Rema) = '0' then
+ -- If the remainder is 0, then the modulus is 0.
+ return Rema;
+ else
+ -- Result of rem has the sign of the divisor.
+ if R_Neg then
+ if L_Neg then
+ Neg_Vec (Rema);
+ return Rema;
+ else
+ return Add_Vec_Vec (R, Rema, True, Loc);
+ end if;
+ else
+ if L_Neg then
+ return Sub_Vec_Vec (R, Rema, True, Loc);
+ else
+ return Rema;
+ end if;
+ end if;
+ end if;
+ end Mod_Sgn_Sgn;
+
+ function Mod_Sgn_Int (L : Memtyp; R : Int64; Loc : Syn_Src) return Memtyp
+ is
+ Rv : Memtyp;
+ begin
+ if L.Typ.Abound.Len = 0 then
+ return Create_Memory (L.Typ); -- FIXME: typ
+ end if;
+ Rv := To_Signed (R, L.Typ);
+ return Mod_Sgn_Sgn (L, Rv, Loc);
+ end Mod_Sgn_Int;
+
+ function Mod_Int_Sgn (L : Int64; R : Memtyp; Loc : Syn_Src) return Memtyp
+ is
+ Lv : Memtyp;
+ begin
+ if R.Typ.Abound.Len = 0 then
+ return Create_Memory (R.Typ); -- FIXME: typ
+ end if;
+ Lv := To_Signed (L, R.Typ);
+ return Mod_Sgn_Sgn (Lv, R, Loc);
+ end Mod_Int_Sgn;
+
end Synth.Ieee.Numeric_Std;
diff --git a/src/synth/synth-ieee-numeric_std.ads b/src/synth/synth-ieee-numeric_std.ads
index 2d6ba68d5..884c8378f 100644
--- a/src/synth/synth-ieee-numeric_std.ads
+++ b/src/synth/synth-ieee-numeric_std.ads
@@ -64,7 +64,24 @@ package Synth.Ieee.Numeric_Std is
-- "/"
function Div_Uns_Uns (L, R : Memtyp; Loc : Syn_Src) return Memtyp;
+ function Div_Uns_Nat (L : Memtyp; R : Uns64; Loc : Syn_Src) return Memtyp;
+ function Div_Nat_Uns (L : Uns64; R : Memtyp; Loc : Syn_Src) return Memtyp;
function Div_Sgn_Sgn (L, R : Memtyp; Loc : Syn_Src) return Memtyp;
+ function Div_Sgn_Int (L : Memtyp; R : Int64; Loc : Syn_Src) return Memtyp;
+ function Div_Int_Sgn (L : Int64; R : Memtyp; Loc : Syn_Src) return Memtyp;
+
+ -- "rem"
+ function Rem_Uns_Uns (L, R : Memtyp; Loc : Syn_Src) return Memtyp;
+ function Rem_Uns_Nat (L : Memtyp; R : Uns64; Loc : Syn_Src) return Memtyp;
+ function Rem_Nat_Uns (L : Uns64; R : Memtyp; Loc : Syn_Src) return Memtyp;
+ function Rem_Sgn_Sgn (L, R : Memtyp; Loc : Syn_Src) return Memtyp;
+ function Rem_Sgn_Int (L : Memtyp; R : Int64; Loc : Syn_Src) return Memtyp;
+ function Rem_Int_Sgn (L : Int64; R : Memtyp; Loc : Syn_Src) return Memtyp;
+
+ -- "mod"
+ function Mod_Sgn_Sgn (L, R : Memtyp; Loc : Syn_Src) return Memtyp;
+ function Mod_Sgn_Int (L : Memtyp; R : Int64; Loc : Syn_Src) return Memtyp;
+ function Mod_Int_Sgn (L : Int64; R : Memtyp; Loc : Syn_Src) return Memtyp;
-- Shift
function Shift_Vec (Val : Memtyp;
diff --git a/src/synth/synth-vhdl_eval.adb b/src/synth/synth-vhdl_eval.adb
index 4a45fb989..17d4548c8 100644
--- a/src/synth/synth-vhdl_eval.adb
+++ b/src/synth/synth-vhdl_eval.adb
@@ -953,7 +953,7 @@ package body Synth.Vhdl_Eval is
declare
Res : Boolean;
begin
- Res := Compare_Sgn_Sgn (Left, Right, Less, Expr) <= Equal;
+ Res := Compare_Sgn_Sgn (Left, Right, Greater, Expr) <= Equal;
return Create_Memory_U8 (Boolean'Pos (Res), Res_Typ);
end;
@@ -982,7 +982,7 @@ package body Synth.Vhdl_Eval is
declare
Res : Boolean;
begin
- Res := Compare_Sgn_Sgn (Left, Right, Less, Expr) < Equal;
+ Res := Compare_Sgn_Sgn (Left, Right, Greater, Expr) < Equal;
return Create_Memory_U8 (Boolean'Pos (Res), Res_Typ);
end;
@@ -1028,8 +1028,41 @@ package body Synth.Vhdl_Eval is
when Iir_Predefined_Ieee_Numeric_Std_Div_Uns_Uns =>
return Div_Uns_Uns (Left, Right, Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Div_Uns_Nat =>
+ return Div_Uns_Nat (Left, To_Uns64 (Read_Discrete (Right)), Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Div_Nat_Uns =>
+ return Div_Nat_Uns (To_Uns64 (Read_Discrete (Left)), Right, Expr);
+
when Iir_Predefined_Ieee_Numeric_Std_Div_Sgn_Sgn =>
return Div_Sgn_Sgn (Left, Right, Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Div_Int_Sgn =>
+ return Div_Int_Sgn (Read_Discrete (Left), Right, Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Div_Sgn_Int =>
+ return Div_Sgn_Int (Left, Read_Discrete (Right), Expr);
+
+ when Iir_Predefined_Ieee_Numeric_Std_Rem_Uns_Uns
+ | Iir_Predefined_Ieee_Numeric_Std_Mod_Uns_Uns =>
+ return Rem_Uns_Uns (Left, Right, Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Rem_Uns_Nat
+ | Iir_Predefined_Ieee_Numeric_Std_Mod_Uns_Nat =>
+ return Rem_Uns_Nat (Left, To_Uns64 (Read_Discrete (Right)), Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Rem_Nat_Uns
+ | Iir_Predefined_Ieee_Numeric_Std_Mod_Nat_Uns =>
+ return Rem_Nat_Uns (To_Uns64 (Read_Discrete (Left)), Right, Expr);
+
+ when Iir_Predefined_Ieee_Numeric_Std_Rem_Sgn_Sgn =>
+ return Rem_Sgn_Sgn (Left, Right, Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Rem_Int_Sgn =>
+ return Rem_Int_Sgn (Read_Discrete (Left), Right, Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Rem_Sgn_Int =>
+ return Rem_Sgn_Int (Left, Read_Discrete (Right), Expr);
+
+ when Iir_Predefined_Ieee_Numeric_Std_Mod_Sgn_Sgn =>
+ return Mod_Sgn_Sgn (Left, Right, Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Mod_Int_Sgn =>
+ return Mod_Int_Sgn (Read_Discrete (Left), Right, Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Mod_Sgn_Int =>
+ return Mod_Sgn_Int (Left, Read_Discrete (Right), Expr);
when Iir_Predefined_Ieee_Numeric_Std_Srl_Uns_Int
| Iir_Predefined_Ieee_Numeric_Std_Srl_Sgn_Int =>
@@ -1574,6 +1607,58 @@ package body Synth.Vhdl_Eval is
return String_To_Memtyp (Str, Res_Typ);
end Eval_Bit_Vector_To_String;
+ function Eval_Logic_Vector_To_String (Val : Memtyp;
+ Res_Typ : Type_Acc;
+ Log_Base : Natural) return Memtyp
+ is
+ Base : constant Natural := 2 ** Log_Base;
+ Blen : constant Uns32 := Val.Typ.Abound.Len;
+ Str : String (1 .. (Natural (Blen) + Log_Base - 1) / Log_Base);
+ Pos : Natural;
+ D : Std_Ulogic;
+ V : Natural;
+ N : Natural;
+ Has_X, Has_Z, Has_D : Boolean;
+ begin
+ V := 0;
+ N := 1;
+ Has_X := False;
+ Has_Z := False;
+ Has_D := False;
+ Pos := Str'Last;
+ for I in 1 .. Blen loop
+ D := Read_Std_Logic (Val.Mem, Blen - I);
+ case D is
+ when '0' | 'L' =>
+ Has_D := True;
+ when '1' | 'H' =>
+ Has_D := True;
+ V := V + N;
+ when 'Z' | 'W' =>
+ Has_Z := True;
+ when 'X' | 'U' | '-' =>
+ Has_X := True;
+ end case;
+ N := N * 2;
+ if N = Base or else I = Blen then
+ if Has_X or (Has_Z and Has_D) then
+ Str (Pos) := 'X';
+ elsif Has_Z then
+ Str (Pos) := 'Z';
+ else
+ Str (Pos) := Hex_Chars (V);
+ end if;
+ Pos := Pos - 1;
+ N := 1;
+ V := 0;
+ Has_X := False;
+ Has_Z := False;
+ Has_D := False;
+ end if;
+ end loop;
+ return String_To_Memtyp (Str, Res_Typ);
+ end Eval_Logic_Vector_To_String;
+
function Eval_Static_Predefined_Function_Call (Param1 : Valtyp;
Param2 : Valtyp;
Res_Typ : Type_Acc;
@@ -1862,6 +1947,18 @@ package body Synth.Vhdl_Eval is
return Create_Memory_U8 (Boolean'Pos (B = 'X'), Res_Typ);
end;
+ when Iir_Predefined_Ieee_1164_To_Stdlogicvector_Suv
+ | Iir_Predefined_Ieee_1164_To_Stdulogicvector_Slv =>
+ -- TODO
+ return (Param1.Typ, Param1.Val.Mem);
+
+ when Iir_Predefined_Ieee_1164_To_Hstring =>
+ return Eval_Logic_Vector_To_String
+ (Get_Memtyp (Param1), Res_Typ, 4);
+ when Iir_Predefined_Ieee_1164_To_Ostring =>
+ return Eval_Logic_Vector_To_String
+ (Get_Memtyp (Param1), Res_Typ, 3);
+
when Iir_Predefined_Ieee_Math_Real_Log2 =>
declare
function Log2 (Arg : Fp64) return Fp64;