diff options
author | Tristan Gingold <tgingold@free.fr> | 2020-02-18 20:26:38 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2020-02-18 20:26:38 +0100 |
commit | 26aefc178f1f2d1eee9f0e48d919adb56b274466 (patch) | |
tree | 1158d127cb746a19aa5509a9eb7556901fbcefe5 | |
parent | 5abd825112fcddd8a61407a422a38a6bdd3f94a8 (diff) | |
download | ghdl-26aefc178f1f2d1eee9f0e48d919adb56b274466.tar.gz ghdl-26aefc178f1f2d1eee9f0e48d919adb56b274466.tar.bz2 ghdl-26aefc178f1f2d1eee9f0e48d919adb56b274466.zip |
synth: rework static predefined function calls.
-rw-r--r-- | src/synth/synth-oper.adb | 219 | ||||
-rw-r--r-- | src/synth/synth-static_oper.adb | 153 | ||||
-rw-r--r-- | src/synth/synth-static_oper.ads | 4 |
3 files changed, 224 insertions, 152 deletions
diff --git a/src/synth/synth-oper.adb b/src/synth/synth-oper.adb index 7ed87de68..ec32aa1f0 100644 --- a/src/synth/synth-oper.adb +++ b/src/synth/synth-oper.adb @@ -18,7 +18,6 @@ -- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -- MA 02110-1301, USA. -with Ada.Unchecked_Conversion; with Types; use Types; with Types_Utils; use Types_Utils; with Mutils; @@ -40,14 +39,9 @@ with Synth.Errors; use Synth.Errors; with Synth.Stmts; use Synth.Stmts; with Synth.Expr; use Synth.Expr; with Synth.Source; -with Synth.Files_Operations; with Synth.Static_Oper; use Synth.Static_Oper; package body Synth.Oper is - -- As log2(3m) is directly referenced, the program must be linked with -lm - -- (math library) on unix systems. - pragma Linker_Options ("-lm"); - procedure Set_Location (N : Net; Loc : Node) renames Synth.Source.Set_Location; @@ -1223,45 +1217,17 @@ package body Synth.Oper is return Create_Value_Net (Res, Boolean_Type); end Synth_Std_Match; - function Eval_To_Vector (Arg : Uns64; Sz : Int64; Res_Type : Type_Acc) - return Value_Acc + function Synth_Dynamic_Predefined_Function_Call + (Subprg_Inst : Synth_Instance_Acc; Expr : Node) return Value_Acc is - Len : constant Iir_Index32 := Iir_Index32 (Sz); - El_Type : constant Type_Acc := Get_Array_Element (Res_Type); - Arr : Value_Array_Acc; - Bnd : Type_Acc; - B : Uns64; - begin - Arr := Create_Value_Array (Len); - for I in 1 .. Len loop - B := Shift_Right_Arithmetic (Arg, Natural (I - 1)) and 1; - Arr.V (Len - I + 1) := Create_Value_Discrete - (Std_Logic_0_Pos + Int64 (B), El_Type); - end loop; - Bnd := Create_Vec_Type_By_Length (Width (Len), El_Type); - return Create_Value_Const_Array (Bnd, Arr); - end Eval_To_Vector; - - function Synth_Predefined_Function_Call - (Syn_Inst : Synth_Instance_Acc; Expr : Node) return Value_Acc - is - Ctxt : constant Context_Acc := Get_Build (Syn_Inst); + Ctxt : constant Context_Acc := Get_Build (Subprg_Inst); Imp : constant Node := Get_Implementation (Expr); Def : constant Iir_Predefined_Functions := Get_Implicit_Definition (Imp); - Assoc_Chain : constant Node := Get_Parameter_Association_Chain (Expr); Inter_Chain : constant Node := Get_Interface_Declaration_Chain (Imp); Param1 : Node; Param2 : Node; - Subprg_Inst : Synth_Instance_Acc; - M : Areapools.Mark_Type; begin - Areapools.Mark (M, Instance_Pool.all); - Subprg_Inst := Make_Instance (Syn_Inst, Imp); - - Synth_Subprogram_Association - (Subprg_Inst, Syn_Inst, Inter_Chain, Assoc_Chain); - Param1 := Inter_Chain; if Param1 /= Null_Node then Param2 := Get_Chain (Inter_Chain); @@ -1270,14 +1236,6 @@ package body Synth.Oper is end if; case Def is - when Iir_Predefined_Endfile => - declare - L : constant Value_Acc := Get_Value (Subprg_Inst, Param1); - Res : Boolean; - begin - Res := Synth.Files_Operations.Endfile (L.File, Expr); - return Create_Value_Discrete (Boolean'Pos (Res), Boolean_Type); - end; when Iir_Predefined_Ieee_1164_Rising_Edge => declare Clk : Net; @@ -1312,6 +1270,15 @@ package body Synth.Oper is end if; return Create_Value_Net (Get_Net (L), Create_Res_Bound (L)); end; + when Iir_Predefined_Ieee_1164_To_Stdlogicvector => + declare + L : constant Value_Acc := Get_Value (Subprg_Inst, Param1); + begin + if Is_Static (L) then + raise Internal_Error; + end if; + return Create_Value_Net (Get_Net (L), Create_Res_Bound (L)); + end; when Iir_Predefined_Ieee_Numeric_Std_Touns_Nat_Nat_Uns | Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Unsigned_Int => declare @@ -1322,23 +1289,15 @@ package body Synth.Oper is Size := Get_Value (Subprg_Inst, Param2); if not Is_Static (Size) then Error_Msg_Synth (+Expr, "to_unsigned size must be constant"); - return Arg; - else - Strip_Const (Size); - -- FIXME: what if the arg is constant too ? - if Is_Static (Arg) then - return Eval_To_Vector - (Uns64 (Arg.Scal), Size.Scal, - Get_Value_Type (Syn_Inst, Get_Type (Imp))); - else - Arg_Net := Get_Net (Arg); - return Create_Value_Net - (Build2_Uresize (Ctxt, Arg_Net, Uns32 (Size.Scal), - Get_Location (Expr)), - Create_Vec_Type_By_Length (Uns32 (Size.Scal), - Logic_Type)); - end if; + return null; end if; + Strip_Const (Size); + Arg_Net := Get_Net (Arg); + return Create_Value_Net + (Build2_Uresize (Ctxt, Arg_Net, Uns32 (Size.Scal), + Get_Location (Expr)), + Create_Vec_Type_By_Length (Uns32 (Size.Scal), + Logic_Type)); end; when Iir_Predefined_Ieee_Numeric_Std_Tosgn_Int_Nat_Sgn => declare @@ -1349,23 +1308,15 @@ package body Synth.Oper is Size := Get_Value (Subprg_Inst, Param2); if not Is_Static (Size) then Error_Msg_Synth (+Expr, "to_signed size must be constant"); - return Arg; - else - Strip_Const (Size); - -- FIXME: what if the arg is constant too ? - if Is_Static (Arg) then - return Eval_To_Vector - (To_Uns64 (Arg.Scal), Size.Scal, - Get_Value_Type (Syn_Inst, Get_Type (Imp))); - else - Arg_Net := Get_Net (Arg); - return Create_Value_Net - (Build2_Sresize (Ctxt, Arg_Net, Uns32 (Size.Scal), - Get_Location (Expr)), - Create_Vec_Type_By_Length (Uns32 (Size.Scal), - Logic_Type)); - end if; + return null; end if; + Strip_Const (Size); + Arg_Net := Get_Net (Arg); + return Create_Value_Net + (Build2_Sresize (Ctxt, Arg_Net, Uns32 (Size.Scal), + Get_Location (Expr)), + Create_Vec_Type_By_Length (Uns32 (Size.Scal), + Logic_Type)); end; when Iir_Predefined_Ieee_Numeric_Std_Toint_Uns_Nat | Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Integer_Uns @@ -1373,7 +1324,7 @@ package body Synth.Oper is -- UNSIGNED to Natural. declare Int_Type : constant Type_Acc := - Get_Value_Type (Syn_Inst, + Get_Value_Type (Subprg_Inst, Vhdl.Std_Package.Integer_Subtype_Definition); begin return Create_Value_Net @@ -1408,8 +1359,7 @@ package body Synth.Oper is end if; W := Uns32 (Sz.Scal); return Create_Value_Net - (Build2_Sresize (Get_Build (Syn_Inst), Get_Net (V), W, - Get_Location (Expr)), + (Build2_Sresize (Ctxt, Get_Net (V), W, Get_Location (Expr)), Create_Vec_Type_By_Length (W, Logic_Type)); end; when Iir_Predefined_Ieee_Numeric_Std_Shl_Uns_Nat @@ -1464,85 +1414,52 @@ package body Synth.Oper is return null; end if; end; - when Iir_Predefined_Ieee_Math_Real_Log2 => - declare - V : constant Value_Acc := Get_Value (Subprg_Inst, Param1); - - function Log2 (Arg : Fp64) return Fp64; - pragma Import (C, Log2); - begin - if V.Typ.Kind /= Type_Float then - Error_Msg_Synth (+Expr, "argument must be a float value"); - return null; - end if; - return Create_Value_Float - (Log2 (V.Fp), Get_Value_Type (Syn_Inst, Get_Type (Imp))); - end; - when Iir_Predefined_Ieee_Math_Real_Ceil => - declare - V : constant Value_Acc := Get_Value (Subprg_Inst, Param1); - - function Ceil (Arg : Fp64) return Fp64; - pragma Import (C, Ceil); - begin - if V.Typ.Kind /= Type_Float then - Error_Msg_Synth(+Expr, "argument must be a float value"); - return null; - end if; - return Create_Value_Float - (Ceil (V.Fp), Get_Value_Type (Syn_Inst, Get_Type (Imp))); - end; - when Iir_Predefined_Ieee_Math_Real_Round => - declare - V : constant Value_Acc := Get_Value (Subprg_Inst, Param1); - - function Round (Arg : Fp64) return Fp64; - pragma Import (C, Round); - begin - if V.Typ.Kind /= Type_Float then - Error_Msg_Synth(+Expr, "argument must be a float value"); - return null; - end if; - return Create_Value_Float - (Round (V.Fp), Get_Value_Type (Syn_Inst, Get_Type (Imp))); - end; - when Iir_Predefined_Ieee_Math_Real_Sin => - declare - V : constant Value_Acc := Get_Value (Subprg_Inst, Param1); - - function Sin (Arg : Fp64) return Fp64; - pragma Import (C, Sin); - begin - if V.Typ.Kind /= Type_Float then - Error_Msg_Synth (+Expr, "argument must be a float value"); - return null; - end if; - return Create_Value_Float - (Sin (V.Fp), Get_Value_Type (Syn_Inst, Get_Type (Imp))); - end; - when Iir_Predefined_Ieee_Math_Real_Cos => - declare - V : constant Value_Acc := Get_Value (Subprg_Inst, Param1); - - function Cos (Arg : Fp64) return Fp64; - pragma Import (C, Cos); - begin - if V.Typ.Kind /= Type_Float then - Error_Msg_Synth (+Expr, "argument must be a float value"); - return null; - end if; - return Create_Value_Float - (Cos (V.Fp), Get_Value_Type (Syn_Inst, Get_Type (Imp))); - end; when others => Error_Msg_Synth (+Expr, "unhandled function: " & Iir_Predefined_Functions'Image (Def)); + return null; end case; + end Synth_Dynamic_Predefined_Function_Call; + + function Synth_Predefined_Function_Call + (Syn_Inst : Synth_Instance_Acc; Expr : Node) return Value_Acc + is + Imp : constant Node := Get_Implementation (Expr); + Assoc_Chain : constant Node := Get_Parameter_Association_Chain (Expr); + Inter_Chain : constant Node := Get_Interface_Declaration_Chain (Imp); + Inter : Node; + Subprg_Inst : Synth_Instance_Acc; + M : Areapools.Mark_Type; + Static : Boolean; + Res : Value_Acc; + begin + Areapools.Mark (M, Instance_Pool.all); + Subprg_Inst := Make_Instance (Syn_Inst, Imp); + + Synth_Subprogram_Association + (Subprg_Inst, Syn_Inst, Inter_Chain, Assoc_Chain); + + -- If all operands are static, handle the call differently. + Static := True; + Inter := Inter_Chain; + while Inter /= Null_Node loop + if not Is_Static (Get_Value (Subprg_Inst, Inter)) then + Static := False; + exit; + end if; + Inter := Get_Chain (Inter); + end loop; + + if Static then + Res := Synth_Static_Predefined_Function_Call (Subprg_Inst, Expr); + else + Res := Synth_Dynamic_Predefined_Function_Call (Subprg_Inst, Expr); + end if; Free_Instance (Subprg_Inst); Areapools.Release (M, Instance_Pool.all); - return null; + return Res; end Synth_Predefined_Function_Call; end Synth.Oper; diff --git a/src/synth/synth-static_oper.adb b/src/synth/synth-static_oper.adb index 3bf2a1b9f..65506ea07 100644 --- a/src/synth/synth-static_oper.adb +++ b/src/synth/synth-static_oper.adb @@ -19,9 +19,10 @@ -- MA 02110-1301, USA. with Types; use Types; +with Types_Utils; use Types_Utils; with Vhdl.Utils; use Vhdl.Utils; -with Vhdl.Ieee.Std_Logic_1164; +with Vhdl.Ieee.Std_Logic_1164; use Vhdl.Ieee.Std_Logic_1164; with Netlists; use Netlists; with Netlists.Utils; use Netlists.Utils; @@ -33,8 +34,13 @@ with Synth.Expr; use Synth.Expr; with Synth.Oper; with Synth.Ieee.Std_Logic_1164; use Synth.Ieee.Std_Logic_1164; with Synth.Ieee.Numeric_Std; use Synth.Ieee.Numeric_Std; +with Synth.Files_Operations; package body Synth.Static_Oper is + -- As log2(3m) is directly referenced, the program must be linked with -lm + -- (math library) on unix systems. + pragma Linker_Options ("-lm"); + -- From openiee: type Static_Arr_Kind is (Sarr_Value, Sarr_Net); @@ -651,4 +657,149 @@ package body Synth.Static_Oper is raise Internal_Error; end case; end Synth_Static_Monadic_Predefined; + + function Eval_To_Vector (Arg : Uns64; Sz : Int64; Res_Type : Type_Acc) + return Value_Acc + is + Len : constant Iir_Index32 := Iir_Index32 (Sz); + El_Type : constant Type_Acc := Get_Array_Element (Res_Type); + Arr : Value_Array_Acc; + Bnd : Type_Acc; + B : Uns64; + begin + Arr := Create_Value_Array (Len); + for I in 1 .. Len loop + B := Shift_Right_Arithmetic (Arg, Natural (I - 1)) and 1; + Arr.V (Len - I + 1) := Create_Value_Discrete + (Std_Logic_0_Pos + Int64 (B), El_Type); + end loop; + Bnd := Create_Vec_Type_By_Length (Width (Len), El_Type); + return Create_Value_Const_Array (Bnd, Arr); + end Eval_To_Vector; + + function Eval_Unsigned_To_Integer + (Arg : Value_Acc; Res_Type : Type_Acc; Loc : Node) return Value_Acc + is + Res : Uns64; + begin + Res := 0; + for I in Arg.Arr.V'Range loop + case Arg.Arr.V (I).Scal is + when Std_Logic_0_Pos + | Std_Logic_L_Pos => + Res := Res * 2; + when Std_Logic_1_Pos + | Std_Logic_H_Pos => + Res := Res * 2 + 1; + when Std_Logic_U_Pos + | Std_Logic_X_Pos + | Std_Logic_Z_Pos + | Std_Logic_W_Pos + | Std_Logic_D_Pos => + Warning_Msg_Synth + (+Loc, "metavalue detected, returning 0"); + Res := 0; + exit; + when others => + raise Internal_Error; + end case; + end loop; + return Create_Value_Discrete (To_Int64 (Res), Res_Type); + end Eval_Unsigned_To_Integer; + + function Synth_Static_Predefined_Function_Call + (Subprg_Inst : Synth_Instance_Acc; Expr : Node) return Value_Acc + is + Imp : constant Node := Get_Implementation (Expr); + Def : constant Iir_Predefined_Functions := + Get_Implicit_Definition (Imp); + Inter_Chain : constant Node := Get_Interface_Declaration_Chain (Imp); + Param1 : Value_Acc; + Param2 : Value_Acc; + Res_Typ : Type_Acc; + Inter : Node; + begin + Inter := Inter_Chain; + if Inter /= Null_Node then + Param1 := Get_Value (Subprg_Inst, Inter); + Strip_Const (Param1); + Inter := Get_Chain (Inter); + else + Param1 := null; + end if; + if Inter /= Null_Node then + Param2 := Get_Value (Subprg_Inst, Inter); + Strip_Const (Param2); + Inter := Get_Chain (Inter); + else + Param2 := null; + end if; + + Res_Typ := Get_Value_Type (Subprg_Inst, Get_Type (Imp)); + + case Def is + when Iir_Predefined_Endfile => + declare + Res : Boolean; + begin + Res := Synth.Files_Operations.Endfile (Param1.File, Expr); + return Create_Value_Discrete (Boolean'Pos (Res), Boolean_Type); + end; + + when Iir_Predefined_Ieee_Numeric_Std_Touns_Nat_Nat_Uns + | Iir_Predefined_Ieee_Std_Logic_Arith_Conv_Unsigned_Int => + return Eval_To_Vector + (Uns64 (Param1.Scal), Param2.Scal, Res_Typ); + when Iir_Predefined_Ieee_Numeric_Std_Tosgn_Int_Nat_Sgn => + return Eval_To_Vector + (To_Uns64 (Param1.Scal), Param2.Scal, 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 => + -- UNSIGNED to Natural. + return Eval_Unsigned_To_Integer (Param1, Res_Typ, Expr); + + when Iir_Predefined_Ieee_Math_Real_Log2 => + declare + function Log2 (Arg : Fp64) return Fp64; + pragma Import (C, Log2); + begin + return Create_Value_Float (Log2 (Param1.Fp), Res_Typ); + end; + when Iir_Predefined_Ieee_Math_Real_Ceil => + declare + function Ceil (Arg : Fp64) return Fp64; + pragma Import (C, Ceil); + begin + return Create_Value_Float (Ceil (Param1.Fp), Res_Typ); + end; + when Iir_Predefined_Ieee_Math_Real_Round => + declare + function Round (Arg : Fp64) return Fp64; + pragma Import (C, Round); + begin + return Create_Value_Float (Round (Param1.Fp), Res_Typ); + end; + when Iir_Predefined_Ieee_Math_Real_Sin => + declare + function Sin (Arg : Fp64) return Fp64; + pragma Import (C, Sin); + begin + return Create_Value_Float (Sin (Param1.Fp), Res_Typ); + end; + when Iir_Predefined_Ieee_Math_Real_Cos => + declare + function Cos (Arg : Fp64) return Fp64; + pragma Import (C, Cos); + begin + return Create_Value_Float (Cos (Param1.Fp), Res_Typ); + end; + when others => + Error_Msg_Synth + (+Expr, "unhandled (static) function: " + & Iir_Predefined_Functions'Image (Def)); + return null; + end case; + end Synth_Static_Predefined_Function_Call; + end Synth.Static_Oper; diff --git a/src/synth/synth-static_oper.ads b/src/synth/synth-static_oper.ads index d166a8469..4c2e51695 100644 --- a/src/synth/synth-static_oper.ads +++ b/src/synth/synth-static_oper.ads @@ -32,4 +32,8 @@ package Synth.Static_Oper is Imp : Node; Operand : Value_Acc; Expr : Node) return Value_Acc; + + function Synth_Static_Predefined_Function_Call + (Subprg_Inst : Synth_Instance_Acc; Expr : Node) return Value_Acc; + end Synth.Static_Oper; |