diff options
author | Tristan Gingold <tgingold@free.fr> | 2022-06-05 17:51:09 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2022-06-05 17:51:09 +0200 |
commit | cedc5e056534f8c30843947d7cf925f3cf082856 (patch) | |
tree | ce11b53e6d5a1078061f1951ca82249665a77eba | |
parent | 56dc0a430681fd5745587907fd0fa117e563e8bb (diff) | |
download | ghdl-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.adb | 122 | ||||
-rw-r--r-- | src/synth/synth-ieee-numeric_std.ads | 23 | ||||
-rw-r--r-- | src/synth/synth-ieee-std_logic_1164.ads | 12 | ||||
-rw-r--r-- | src/synth/synth-vhdl_eval.adb | 146 |
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; |