diff options
Diffstat (limited to 'src/vhdl/evaluation.adb')
-rw-r--r-- | src/vhdl/evaluation.adb | 91 |
1 files changed, 87 insertions, 4 deletions
diff --git a/src/vhdl/evaluation.adb b/src/vhdl/evaluation.adb index 14e3d97db..baa100c87 100644 --- a/src/vhdl/evaluation.adb +++ b/src/vhdl/evaluation.adb @@ -33,6 +33,8 @@ package body Evaluation is function Eval_Enum_To_String (Lit : Iir; Orig : Iir) return Iir; function Eval_Integer_Image (Val : Iir_Int64; Orig : Iir) return Iir; + function Eval_Scalar_Compare (Left, Right : Iir) return Compare_Type; + function Get_Physical_Value (Expr : Iir) return Iir_Int64 is pragma Unsuppress (Overflow_Check); @@ -610,6 +612,8 @@ package body Evaluation is function Eval_Monadic_Operator (Orig : Iir; Operand : Iir) return Iir is pragma Unsuppress (Overflow_Check); + subtype Iir_Predefined_Vector_Minmax is Iir_Predefined_Functions range + Iir_Predefined_Vector_Minimum .. Iir_Predefined_Vector_Maximum; Func : Iir_Predefined_Functions; begin @@ -680,6 +684,55 @@ package body Evaluation is when Iir_Predefined_Integer_To_String => return Eval_Integer_Image (Get_Value (Operand), Orig); + when Iir_Predefined_Vector_Minimum + | Iir_Predefined_Vector_Maximum => + -- LRM08 5.3.2.4 Predefined operations on array types + declare + Saggr : Iir; + Lits : Iir_List; + Res : Iir; + El : Iir; + Cmp : Compare_Type; + begin + Saggr := Eval_String_Literal (Operand); + Lits := Get_Simple_Aggregate_List (Saggr); + + if Get_Nbr_Elements (Lits) = 0 then + declare + Typ : constant Iir := + Get_Type (Get_Implementation (Orig)); + Rng : constant Iir := Eval_Static_Range (Typ); + begin + case Iir_Predefined_Vector_Minmax (Func) is + when Iir_Predefined_Vector_Minimum => + Res := Get_High_Limit (Rng); + when Iir_Predefined_Vector_Maximum => + Res := Get_Low_Limit (Rng); + end case; + Res := Eval_Static_Expr (Res); + end; + else + Res := Get_Nth_Element (Lits, 0); + for I in Positive loop + El := Get_Nth_Element (Lits, I); + exit when El = Null_Iir; + Cmp := Eval_Scalar_Compare (El, Res); + case Iir_Predefined_Vector_Minmax (Func) is + when Iir_Predefined_Vector_Minimum => + if Cmp <= Compare_Eq then + Res := El; + end if; + when Iir_Predefined_Vector_Maximum => + if Cmp >= Compare_Eq then + Res := El; + end if; + end case; + end loop; + end if; + Free_Eval_String_Literal (Saggr, Operand); + return Res; + end; + when others => Error_Internal (Orig, "eval_monadic_operator: " & Iir_Predefined_Functions'Image (Func)); @@ -1039,7 +1092,7 @@ package body Evaluation is return Build_Simple_Aggregate (Res_List, Orig, Res_Type, Res_Type); end Eval_Concatenation; - function Eval_Discrete_Compare (Left, Right : Iir) return Compare_Type + function Eval_Scalar_Compare (Left, Right : Iir) return Compare_Type is Ltype : constant Iir := Get_Base_Type (Get_Type (Left)); begin @@ -1062,6 +1115,21 @@ package body Evaluation is end if; end if; end; + when Iir_Kind_Physical_Type_Definition => + declare + L_Val : constant Iir_Int64 := Get_Physical_Value (Left); + R_Val : constant Iir_Int64 := Get_Physical_Value (Right); + begin + if L_Val = R_Val then + return Compare_Eq; + else + if L_Val < R_Val then + return Compare_Lt; + else + return Compare_Gt; + end if; + end if; + end; when Iir_Kind_Integer_Type_Definition => declare L_Val : constant Iir_Int64 := Get_Value (Left); @@ -1077,10 +1145,25 @@ package body Evaluation is end if; end if; end; + when Iir_Kind_Floating_Type_Definition => + declare + L_Val : constant Iir_Fp64 := Get_Fp_Value (Left); + R_Val : constant Iir_Fp64 := Get_Fp_Value (Right); + begin + if L_Val = R_Val then + return Compare_Eq; + else + if L_Val < R_Val then + return Compare_Lt; + else + return Compare_Gt; + end if; + end if; + end; when others => - Error_Kind ("eval_discrete_compare", Ltype); + Error_Kind ("eval_scalar_compare", Ltype); end case; - end Eval_Discrete_Compare; + end Eval_Scalar_Compare; function Eval_Array_Compare (Left, Right : Iir) return Compare_Type is begin @@ -1137,7 +1220,7 @@ package body Evaluation is Res := Compare_Eq; P := 0; while P < L_Len and P < R_Len loop - Res := Eval_Discrete_Compare (Get_Nth_Element (L_List, P), + Res := Eval_Scalar_Compare (Get_Nth_Element (L_List, P), Get_Nth_Element (R_List, P)); exit when Res /= Compare_Eq; P := P + 1; |