aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2022-06-05 17:51:09 +0200
committerTristan Gingold <tgingold@free.fr>2022-06-05 17:51:09 +0200
commitcedc5e056534f8c30843947d7cf925f3cf082856 (patch)
treece11b53e6d5a1078061f1951ca82249665a77eba
parent56dc0a430681fd5745587907fd0fa117e563e8bb (diff)
downloadghdl-cedc5e056534f8c30843947d7cf925f3cf082856.tar.gz
ghdl-cedc5e056534f8c30843947d7cf925f3cf082856.tar.bz2
ghdl-cedc5e056534f8c30843947d7cf925f3cf082856.zip
synth-vhdl-eval: handle more operations
-rw-r--r--src/synth/synth-ieee-numeric_std.adb122
-rw-r--r--src/synth/synth-ieee-numeric_std.ads23
-rw-r--r--src/synth/synth-ieee-std_logic_1164.ads12
-rw-r--r--src/synth/synth-vhdl_eval.adb146
4 files changed, 272 insertions, 31 deletions
diff --git a/src/synth/synth-ieee-numeric_std.adb b/src/synth/synth-ieee-numeric_std.adb
index f2a9ac634..f850456b0 100644
--- a/src/synth/synth-ieee-numeric_std.adb
+++ b/src/synth/synth-ieee-numeric_std.adb
@@ -21,7 +21,6 @@ with Types_Utils; use Types_Utils;
with Elab.Memtype; use Elab.Memtype;
with Synth.Errors; use Synth.Errors;
-with Synth.Ieee.Std_Logic_1164; use Synth.Ieee.Std_Logic_1164;
package body Synth.Ieee.Numeric_Std is
subtype Sl_01 is Std_Ulogic range '0' .. '1';
@@ -1551,4 +1550,125 @@ package body Synth.Ieee.Numeric_Std is
end loop;
return -1;
end Find_Leftmost;
+
+ function Match_Vec (L, R : Memtyp; Loc : Location_Type) return Boolean
+ is
+ Llen : constant Uns32 := L.Typ.Abound.Len;
+ Rlen : constant Uns32 := R.Typ.Abound.Len;
+ begin
+ if Llen = 0 or Rlen = 0 then
+ Warn_Compare_Null (Loc);
+ return False;
+ end if;
+ if Llen /= Rlen then
+ Warning_Msg_Synth
+ (+Loc, "NUMERIC_STD.STD_MATCH: length mismatch, returning FALSE");
+ return False;
+ end if;
+
+ for I in 1 .. Llen loop
+ if Match_Eq_Table (Read_Std_Logic (L.Mem, I - 1),
+ Read_Std_Logic (R.Mem, I - 1)) /= '1'
+ then
+ return False;
+ end if;
+ end loop;
+ return True;
+ end Match_Vec;
+
+ function Match_Eq_Vec_Vec (Left, Right : Memtyp;
+ Is_Signed : Boolean;
+ Loc : Location_Type) return Std_Ulogic
+ is
+ Lw : constant Uns32 := Left.Typ.W;
+ Rw : constant Uns32 := Right.Typ.W;
+ Len : constant Uns32 := Uns32'Max (Left.Typ.W, Right.Typ.W);
+ L, R, T : Std_Ulogic;
+ Res : Std_Ulogic;
+ begin
+ if Len = 0 then
+ Warn_Compare_Null (Loc);
+ return 'X';
+ end if;
+
+ Res := '1';
+ for I in 1 .. Len loop
+ if I > Lw then
+ if not Is_Signed then
+ L := '0';
+ end if;
+ else
+ L := Read_Std_Logic (Left.Mem, Lw - I);
+ end if;
+ if I > Rw then
+ if not Is_Signed then
+ R := '0';
+ end if;
+ else
+ R := Read_Std_Logic (Right.Mem, Rw - I);
+ end if;
+ T := Match_Eq_Table (L, R);
+ if T = 'U' then
+ return T;
+ elsif T = 'X' or Res = 'X' then
+ -- Lower priority than 'U'.
+ Res := 'X';
+ elsif T = '0' then
+ Res := '0';
+ end if;
+ end loop;
+ return Res;
+ end Match_Eq_Vec_Vec;
+
+ function Has_Xd (V : Memtyp) return Std_Ulogic
+ is
+ Res : Std_Ulogic;
+ E : Std_Ulogic;
+ begin
+ Res := '0';
+ for I in 0 .. V.Typ.Abound.Len - 1 loop
+ E := Read_Std_Logic (V.Mem, I);
+ if E = '-' then
+ return '-';
+ elsif To_X01 (E) = 'X' then
+ Res := 'X';
+ end if;
+ end loop;
+ return Res;
+ end Has_Xd;
+
+ function Match_Cmp_Vec_Vec (Left, Right : Memtyp;
+ Map : Order_Map_Type;
+ Is_Signed : Boolean;
+ Loc : Location_Type) return Memtyp
+ is
+ Llen : constant Uns32 := Left.Typ.Abound.Len;
+ Rlen : constant Uns32 := Right.Typ.Abound.Len;
+ L, R : Std_Ulogic;
+ Res : Std_Ulogic;
+ Cmp : Order_Type;
+ begin
+ if Rlen = 0 or Llen = 0 then
+ Warn_Compare_Null (Loc);
+ Res := 'X';
+ else
+ L := Has_Xd (Left);
+ R := Has_Xd (Right);
+ if L = '-' or R = '-' then
+ Warning_Msg_Synth (+Loc, "'-' found in compare string");
+ Res := 'X';
+ elsif L = 'X' or R = 'X' then
+ Res := 'X';
+ else
+ if Is_Signed then
+ Cmp := Compare_Sgn_Sgn (Left, Right, Equal, Loc);
+ else
+ Cmp := Compare_Uns_Uns (Left, Right, Equal, Loc);
+ end if;
+ Res := Map (Cmp);
+ end if;
+ end if;
+
+ return Create_Memory_U8 (Std_Ulogic'Pos (Res), Logic_Type);
+ end Match_Cmp_Vec_Vec;
end Synth.Ieee.Numeric_Std;
diff --git a/src/synth/synth-ieee-numeric_std.ads b/src/synth/synth-ieee-numeric_std.ads
index 3431117c5..81158954c 100644
--- a/src/synth/synth-ieee-numeric_std.ads
+++ b/src/synth/synth-ieee-numeric_std.ads
@@ -20,6 +20,8 @@ with Types; use Types;
with Elab.Vhdl_Objtypes; use Elab.Vhdl_Objtypes;
+with Synth.Ieee.Std_Logic_1164; use Synth.Ieee.Std_Logic_1164;
+
package Synth.Ieee.Numeric_Std is
-- Reminder: vectors elements are from left to right.
@@ -137,4 +139,25 @@ package Synth.Ieee.Numeric_Std is
-- Find_Rightmost/Find_Leftmost
function Find_Rightmost (Arg : Memtyp; Val : Memtyp) return Int32;
function Find_Leftmost (Arg : Memtyp; Val : Memtyp) return Int32;
+
+ -- Std_Match
+ function Match_Vec (L, R : Memtyp; Loc : Location_Type) return Boolean;
+
+ -- Matching comparisons.
+ function Match_Eq_Vec_Vec (Left, Right : Memtyp;
+ Is_Signed : Boolean;
+ Loc : Location_Type) return Std_Ulogic;
+
+ type Order_Map_Type is array (Order_Type) of X01;
+
+ Map_Lt : constant Order_Map_Type := "100";
+ Map_Le : constant Order_Map_Type := "110";
+ Map_Ge : constant Order_Map_Type := "011";
+ Map_Gt : constant Order_Map_Type := "001";
+
+ function Match_Cmp_Vec_Vec (Left, Right : Memtyp;
+ Map : Order_Map_Type;
+ Is_Signed : Boolean;
+ Loc : Location_Type) return Memtyp;
+
end Synth.Ieee.Numeric_Std;
diff --git a/src/synth/synth-ieee-std_logic_1164.ads b/src/synth/synth-ieee-std_logic_1164.ads
index 96c91bb1a..324fb2a52 100644
--- a/src/synth/synth-ieee-std_logic_1164.ads
+++ b/src/synth/synth-ieee-std_logic_1164.ads
@@ -44,7 +44,7 @@ package Synth.Ieee.Std_Logic_1164 is
'-' -- Don't care.
);
- subtype X01 is Std_Ulogic range 'X' .. '1';
+ subtype X01 is Std_Ulogic range 'X' .. '1';
function Read_Std_Logic (M : Memory_Ptr; Off : Uns32) return Std_Ulogic;
procedure Write_Std_Logic (M : Memory_Ptr; Off : Uns32; Val : Std_Ulogic);
@@ -60,11 +60,11 @@ package Synth.Ieee.Std_Logic_1164 is
type Table_1d_X01 is array (Std_Ulogic) of X01;
- -- UX01ZWLH-
- To_X01 : constant Table_1d_X01 := "XX01XX01X";
- Map_X01 : constant Table_1d := "XX01XX01X";
- Map_X01Z : constant Table_1d := "XX01ZX01X"; -- Note: W => X
- Map_UX01 : constant Table_1d := "UX01XX01X";
+ -- UX01ZWLH-
+ To_X01 : constant Table_1d_X01 := "XX01XX01X";
+ Map_X01 : constant Table_1d := "XX01XX01X";
+ Map_X01Z : constant Table_1d := "XX01ZX01X"; -- Note: W => X
+ Map_UX01 : constant Table_1d := "UX01XX01X";
And_Table : constant Table_2d :=
-- UX01ZWLH-
diff --git a/src/synth/synth-vhdl_eval.adb b/src/synth/synth-vhdl_eval.adb
index 4bb9dde96..2e7e26d22 100644
--- a/src/synth/synth-vhdl_eval.adb
+++ b/src/synth/synth-vhdl_eval.adb
@@ -110,8 +110,7 @@ package body Synth.Vhdl_Eval is
end Eval_Vector_Dyadic;
function Eval_Logic_Vector_Scalar (Vect, Scal : Memtyp;
- Op : Table_2d;
- Neg : Boolean := False) return Memtyp
+ Op : Table_2d) return Memtyp
is
Res : Memtyp;
Vs, Vv, Vr : Std_Ulogic;
@@ -121,9 +120,6 @@ package body Synth.Vhdl_Eval is
for I in 1 .. Vect.Typ.Abound.Len loop
Vv := Read_Std_Logic (Vect.Mem, I - 1);
Vr := Op (Vs, Vv);
- if Neg then
- Vr := Not_Table (Vr);
- end if;
Write_Std_Logic (Res.Mem, I - 1, Vr);
end loop;
return Res;
@@ -814,31 +810,55 @@ package body Synth.Vhdl_Eval is
when Iir_Predefined_Std_Ulogic_Array_Match_Inequality =>
return Eval_Vector_Match (Left, Right, True, Expr);
- when Iir_Predefined_Ieee_1164_And_Suv_Log =>
+ when Iir_Predefined_Ieee_1164_And_Suv_Log
+ | Iir_Predefined_Ieee_Numeric_Std_And_Uns_Log
+ | Iir_Predefined_Ieee_Numeric_Std_And_Sgn_Log =>
return Eval_Logic_Vector_Scalar (Left, Right, And_Table);
- when Iir_Predefined_Ieee_1164_Or_Suv_Log =>
+ when Iir_Predefined_Ieee_1164_Or_Suv_Log
+ | Iir_Predefined_Ieee_Numeric_Std_Or_Uns_Log
+ | Iir_Predefined_Ieee_Numeric_Std_Or_Sgn_Log =>
return Eval_Logic_Vector_Scalar (Left, Right, Or_Table);
- when Iir_Predefined_Ieee_1164_Xor_Suv_Log =>
+ when Iir_Predefined_Ieee_1164_Xor_Suv_Log
+ | Iir_Predefined_Ieee_Numeric_Std_Xor_Uns_Log
+ | Iir_Predefined_Ieee_Numeric_Std_Xor_Sgn_Log =>
return Eval_Logic_Vector_Scalar (Left, Right, Xor_Table);
- when Iir_Predefined_Ieee_1164_Nand_Suv_Log =>
- return Eval_Logic_Vector_Scalar (Left, Right, And_Table, True);
- when Iir_Predefined_Ieee_1164_Nor_Suv_Log =>
- return Eval_Logic_Vector_Scalar (Left, Right, Or_Table, True);
- when Iir_Predefined_Ieee_1164_Xnor_Suv_Log =>
- return Eval_Logic_Vector_Scalar (Left, Right, Xor_Table, True);
-
- when Iir_Predefined_Ieee_1164_And_Log_Suv =>
+ when Iir_Predefined_Ieee_1164_Nand_Suv_Log
+ | Iir_Predefined_Ieee_Numeric_Std_Nand_Uns_Log
+ | Iir_Predefined_Ieee_Numeric_Std_Nand_Sgn_Log =>
+ return Eval_Logic_Vector_Scalar (Left, Right, Nand_Table);
+ when Iir_Predefined_Ieee_1164_Nor_Suv_Log
+ | Iir_Predefined_Ieee_Numeric_Std_Nor_Uns_Log
+ | Iir_Predefined_Ieee_Numeric_Std_Nor_Sgn_Log =>
+ return Eval_Logic_Vector_Scalar (Left, Right, Nor_Table);
+ when Iir_Predefined_Ieee_1164_Xnor_Suv_Log
+ | Iir_Predefined_Ieee_Numeric_Std_Xnor_Uns_Log
+ | Iir_Predefined_Ieee_Numeric_Std_Xnor_Sgn_Log =>
+ return Eval_Logic_Vector_Scalar (Left, Right, Xnor_Table);
+
+ when Iir_Predefined_Ieee_1164_And_Log_Suv
+ | Iir_Predefined_Ieee_Numeric_Std_And_Log_Uns
+ | Iir_Predefined_Ieee_Numeric_Std_And_Log_Sgn =>
return Eval_Logic_Vector_Scalar (Right, Left, And_Table);
- when Iir_Predefined_Ieee_1164_Or_Log_Suv =>
+ when Iir_Predefined_Ieee_1164_Or_Log_Suv
+ | Iir_Predefined_Ieee_Numeric_Std_Or_Log_Uns
+ | Iir_Predefined_Ieee_Numeric_Std_Or_Log_Sgn =>
return Eval_Logic_Vector_Scalar (Right, Left, Or_Table);
- when Iir_Predefined_Ieee_1164_Xor_Log_Suv =>
+ when Iir_Predefined_Ieee_1164_Xor_Log_Suv
+ | Iir_Predefined_Ieee_Numeric_Std_Xor_Log_Uns
+ | Iir_Predefined_Ieee_Numeric_Std_Xor_Log_Sgn =>
return Eval_Logic_Vector_Scalar (Right, Left, Xor_Table);
- when Iir_Predefined_Ieee_1164_Nand_Log_Suv =>
- return Eval_Logic_Vector_Scalar (Right, Left, And_Table, True);
- when Iir_Predefined_Ieee_1164_Nor_Log_Suv =>
- return Eval_Logic_Vector_Scalar (Right, Left, Or_Table, True);
- when Iir_Predefined_Ieee_1164_Xnor_Log_Suv =>
- return Eval_Logic_Vector_Scalar (Right, Left, Xor_Table, True);
+ when Iir_Predefined_Ieee_1164_Nand_Log_Suv
+ | Iir_Predefined_Ieee_Numeric_Std_Nand_Log_Uns
+ | Iir_Predefined_Ieee_Numeric_Std_Nand_Log_Sgn =>
+ return Eval_Logic_Vector_Scalar (Right, Left, Nand_Table);
+ when Iir_Predefined_Ieee_1164_Nor_Log_Suv
+ | Iir_Predefined_Ieee_Numeric_Std_Nor_Log_Uns
+ | Iir_Predefined_Ieee_Numeric_Std_Nor_Log_Sgn =>
+ return Eval_Logic_Vector_Scalar (Right, Left, Nor_Table);
+ when Iir_Predefined_Ieee_1164_Xnor_Log_Suv
+ | Iir_Predefined_Ieee_Numeric_Std_Xnor_Log_Uns
+ | Iir_Predefined_Ieee_Numeric_Std_Xnor_Log_Sgn =>
+ return Eval_Logic_Vector_Scalar (Right, Left, Xnor_Table);
when Iir_Predefined_Ieee_1164_Vector_Sll
| Iir_Predefined_Ieee_Numeric_Std_Sla_Uns_Int =>
@@ -1253,6 +1273,58 @@ package body Synth.Vhdl_Eval is
end if;
end;
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Eq_Uns_Uns =>
+ declare
+ Res : Std_Ulogic;
+ begin
+ Res := Match_Eq_Vec_Vec (Left, Right, False, +Expr);
+ return Create_Memory_U8 (Std_Ulogic'Pos (Res), Res_Typ);
+ end;
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Ne_Uns_Uns =>
+ declare
+ Res : Std_Ulogic;
+ begin
+ Res := Match_Eq_Vec_Vec (Left, Right, False, +Expr);
+ Res := Not_Table (Res);
+ return Create_Memory_U8 (Std_Ulogic'Pos (Res), Res_Typ);
+ end;
+
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Lt_Uns_Uns =>
+ return Match_Cmp_Vec_Vec (Left, Right, Map_Lt, False, +Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Lt_Sgn_Sgn =>
+ return Match_Cmp_Vec_Vec (Left, Right, Map_Lt, True, +Expr);
+
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Le_Uns_Uns =>
+ return Match_Cmp_Vec_Vec (Left, Right, Map_Le, False, +Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Le_Sgn_Sgn =>
+ return Match_Cmp_Vec_Vec (Left, Right, Map_Le, True, +Expr);
+
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Gt_Uns_Uns =>
+ return Match_Cmp_Vec_Vec (Left, Right, Map_Gt, False, +Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Gt_Sgn_Sgn =>
+ return Match_Cmp_Vec_Vec (Left, Right, Map_Gt, True, +Expr);
+
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Ge_Uns_Uns =>
+ return Match_Cmp_Vec_Vec (Left, Right, Map_Ge, False, +Expr);
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Ge_Sgn_Sgn =>
+ return Match_Cmp_Vec_Vec (Left, Right, Map_Ge, True, +Expr);
+
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Eq_Sgn_Sgn =>
+ declare
+ Res : Std_Ulogic;
+ begin
+ Res := Match_Eq_Vec_Vec (Left, Right, True, +Expr);
+ return Create_Memory_U8 (Std_Ulogic'Pos (Res), Res_Typ);
+ end;
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Ne_Sgn_Sgn =>
+ declare
+ Res : Std_Ulogic;
+ begin
+ Res := Match_Eq_Vec_Vec (Left, Right, True, +Expr);
+ Res := Not_Table (Res);
+ return Create_Memory_U8 (Std_Ulogic'Pos (Res), Res_Typ);
+ end;
+
when Iir_Predefined_Ieee_Math_Real_Pow =>
declare
function Pow (L, R : Fp64) return Fp64;
@@ -1995,11 +2067,20 @@ package body Synth.Vhdl_Eval is
return Eval_To_Log_Vector
(Uns64 (Read_Discrete (Param1)), Read_Discrete (Param2),
Res_Typ);
+ when Iir_Predefined_Ieee_Numeric_Std_Touns_Nat_Uns_Uns =>
+ return Eval_To_Log_Vector
+ (Uns64 (Read_Discrete (Param1)), Int64 (Param2.Typ.Abound.Len),
+ Res_Typ);
when Iir_Predefined_Ieee_Numeric_Std_Tosgn_Int_Nat_Sgn
| Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Vector_Int =>
return Eval_To_Log_Vector
(To_Uns64 (Read_Discrete (Param1)), Read_Discrete (Param2),
Res_Typ);
+ when Iir_Predefined_Ieee_Numeric_Std_Tosgn_Int_Sgn_Sgn =>
+ return Eval_To_Log_Vector
+ (To_Uns64 (Read_Discrete (Param1)),
+ Int64 (Param2.Typ.Abound.Len),
+ Res_Typ);
when Iir_Predefined_Ieee_Numeric_Std_Toint_Uns_Nat
| Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Integer_Uns
| Iir_Predefined_Ieee_Std_Logic_Unsigned_Conv_Integer =>
@@ -2038,9 +2119,15 @@ package body Synth.Vhdl_Eval is
when Iir_Predefined_Ieee_Numeric_Std_Resize_Sgn_Nat =>
return Resize_Vec
(Get_Memtyp (Param1), Uns32 (Read_Discrete (Param2)), True);
+ when Iir_Predefined_Ieee_Numeric_Std_Resize_Sgn_Sgn =>
+ return Resize_Vec
+ (Get_Memtyp (Param1), Param2.Typ.Abound.Len, True);
when Iir_Predefined_Ieee_Numeric_Std_Resize_Uns_Nat =>
return Resize_Vec
(Get_Memtyp (Param1), Uns32 (Read_Discrete (Param2)), False);
+ when Iir_Predefined_Ieee_Numeric_Std_Resize_Uns_Uns =>
+ return Resize_Vec
+ (Get_Memtyp (Param1), Param2.Typ.Abound.Len, False);
when Iir_Predefined_Ieee_1164_To_Stdulogic =>
declare
@@ -2087,6 +2174,17 @@ package body Synth.Vhdl_Eval is
return Res;
end;
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Log =>
+ return Create_Memory_Boolean
+ (Match_Eq_Table (Read_Std_Logic (Param1.Val.Mem, 0),
+ Read_Std_Logic (Param2.Val.Mem, 0)) = '1');
+
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Suv
+ | Iir_Predefined_Ieee_Numeric_Std_Match_Uns
+ | Iir_Predefined_Ieee_Numeric_Std_Match_Sgn =>
+ return Create_Memory_Boolean
+ (Match_Vec (Get_Memtyp (Param1), Get_Memtyp (Param2), +Expr));
+
when Iir_Predefined_Ieee_1164_To_Bit =>
declare
V : Std_Ulogic;