diff options
author | Brian Padalino <bpadalino@gmail.com> | 2021-09-22 01:27:51 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-22 07:27:51 +0200 |
commit | b4b25fe5e5d77ba712552acc5edae7c64832d1ca (patch) | |
tree | 152d73a22b34d98b79b2eb35da368c4444280ff6 /src/vhdl | |
parent | 140ec48166f9c8c478d1433507c632cea80929bc (diff) | |
download | ghdl-b4b25fe5e5d77ba712552acc5edae7c64832d1ca.tar.gz ghdl-b4b25fe5e5d77ba712552acc5edae7c64832d1ca.tar.bz2 ghdl-b4b25fe5e5d77ba712552acc5edae7c64832d1ca.zip |
Implement Matching Operators (#1872)
Implement the matching operators ?<, ?<=, ?>, ?>=, ?/=.
Diffstat (limited to 'src/vhdl')
-rw-r--r-- | src/vhdl/vhdl-evaluation.adb | 156 |
1 files changed, 148 insertions, 8 deletions
diff --git a/src/vhdl/vhdl-evaluation.adb b/src/vhdl/vhdl-evaluation.adb index 6305cdbae..76faa1b73 100644 --- a/src/vhdl/vhdl-evaluation.adb +++ b/src/vhdl/vhdl-evaluation.adb @@ -1556,6 +1556,124 @@ package body Vhdl.Evaluation is end if; end Eval_Logic_Match_Equality; + function Eval_Logic_Or(L, R : Iir_Index32) + return Iir_Index32 + is + use Vhdl.Ieee.Std_Logic_1164; + begin + if L = Std_Logic_1_Pos or L = Std_Logic_H_Pos or + R = Std_Logic_1_Pos or R = Std_Logic_H_Pos then + return Std_Logic_1_Pos ; + elsif (L = Std_Logic_0_Pos or L = Std_Logic_L_Pos) and + (R = Std_Logic_0_Pos or R = Std_Logic_L_Pos) then + return Std_Logic_0_Pos ; + elsif L = Std_Logic_U_Pos or R = Std_Logic_U_Pos then + return Std_Logic_U_Pos ; + else + return Std_Logic_X_Pos ; + end if ; + end Eval_Logic_Or ; + + function Eval_Logic_Not(X : Iir_Index32) return Iir_Index32 + is + use Vhdl.Ieee.Std_Logic_1164; + begin + if X = Std_Logic_0_Pos or X = Std_Logic_L_Pos then + return Std_Logic_1_Pos ; + elsif X = Std_Logic_1_Pos or X = Std_Logic_H_Pos then + return Std_Logic_0_Pos ; + elsif X = Std_Logic_U_Pos then + return Std_Logic_U_Pos ; + else + return Std_Logic_X_Pos ; + end if ; + end Eval_Logic_Not ; + + function Eval_Logic_Match_Inequality (L, R : Iir_Int32; Loc : Iir) + return Iir_Index32 + is + E : Iir_Index32; + begin + -- Defined as the not operator applied to the equal operator + E := Eval_Logic_Match_Equality(L, R, Loc) ; + return Eval_Logic_Not(E) ; + end Eval_Logic_Match_Inequality; + + function Eval_Logic_Match_Less (L, R : Iir_Int32; Loc : Iir) + return Iir_Index32 + is + use Vhdl.Ieee.Std_Logic_1164; + begin + -- LRM19 9.2.3 table + -- '-' always returns 'X' + if L = Std_Logic_D_Pos or R = Std_Logic_D_Pos then + Warning_Msg_Sem + (Warnid_Analyze_Assert, +Loc, + "STD_LOGIC_1164: '-' operand for matching ordering operator"); + return Std_Logic_X_Pos; + end if; + + -- 'U' always returns 'U' + if L = Std_Logic_U_Pos or R = Std_Logic_U_Pos then + return Std_Logic_U_Pos ; + end if ; + + -- Only when R is '1' or 'H' will we ever return '1' + if R = Std_Logic_1_Pos or R = Std_Logic_H_Pos then + if L = Std_Logic_0_Pos or L = Std_Logic_L_Pos then + -- L = [0,L] R = [1,H] + return Std_Logic_1_Pos ; + elsif L = Std_Logic_1_Pos or L = Std_Logic_H_Pos then + -- L = [1,H] R = [1,H] + return Std_Logic_0_Pos ; + else + -- Everything else is 'X' + return Std_Logic_X_Pos ; + end if ; + elsif R = Std_Logic_0_Pos or R = Std_Logic_L_Pos then + -- R = [0,1] + return Std_Logic_0_Pos ; + else + -- Everything else is 'X' + return Std_Logic_X_Pos ; + end if ; + end Eval_Logic_Match_Less ; + + function Eval_Logic_Match_Less_Equal (L, R : Iir_Int32; Loc : Iir) + return Iir_Index32 + is + Less : Iir_Index32 ; + Equal : Iir_Index32 ; + begin + -- LRM19 9.2.3 + -- ?<= is defined as (< or =) + Less := Eval_Logic_Match_Less(L, R, Loc) ; + Equal := Eval_Logic_Match_Equality(L, R, Loc) ; + return Eval_Logic_Or(Less, Equal) ; + end Eval_Logic_Match_Less_Equal ; + + function Eval_Logic_Match_Greater (L, R : Iir_Int32; Loc : Iir) + return Iir_Index32 + is + Le : Iir_Index32; + begin + -- LRM19 9.2.3 + -- ?> is defined as not(?<=) + Le := Eval_Logic_Match_Less_Equal(L, R, Loc); + return Eval_Logic_Not(Le); + end Eval_Logic_Match_Greater ; + + function Eval_Logic_Match_Greater_Equal (L, R : Iir_Int32; Loc : Iir) + return Iir_Index32 + is + Less : Iir_Index32 ; + begin + -- LRM19 9.2.3 + -- ?>= is defined as not(?<) + Less := Eval_Logic_Match_Less(L, R, Loc) ; + return Eval_Logic_Not(Less) ; + end Eval_Logic_Match_Greater_Equal ; + function Eval_Equality (Left, Right : Iir) return Boolean; -- CHOICES is a chain of choice from a record aggregate; FEL is an Flist @@ -1591,7 +1709,6 @@ package body Vhdl.Evaluation is end loop; end Fill_Flist_From_Record_Aggregate; - function Eval_Record_Equality (Left, Right : Iir) return Boolean is pragma Assert (Get_Kind (Left) = Iir_Kind_Aggregate); @@ -2075,13 +2192,36 @@ package body Vhdl.Evaluation is (Eval_Logic_Match_Equality (Get_Enum_Pos (Left), Get_Enum_Pos (Right), Orig), Orig); - when Iir_Predefined_Std_Ulogic_Match_Inequality - | Iir_Predefined_Std_Ulogic_Match_Less - | Iir_Predefined_Std_Ulogic_Match_Less_Equal - | Iir_Predefined_Std_Ulogic_Match_Greater - | Iir_Predefined_Std_Ulogic_Match_Greater_Equal => - -- TODO - raise Internal_Error; + + when Iir_Predefined_Std_Ulogic_Match_Inequality => + return Build_Enumeration + (Eval_Logic_Match_Inequality (Get_Enum_Pos (Left), + Get_Enum_Pos (Right), Orig), + Orig); + + when Iir_Predefined_Std_Ulogic_Match_Less => + return Build_Enumeration + (Eval_Logic_Match_Less (Get_Enum_Pos (Left), + Get_Enum_Pos (Right), Orig), + Orig); + + when Iir_Predefined_Std_Ulogic_Match_Greater => + return Build_Enumeration + (Eval_Logic_Match_Greater (Get_Enum_Pos (Left), + Get_Enum_Pos (Right), Orig), + Orig); + + when Iir_Predefined_Std_Ulogic_Match_Greater_Equal => + return Build_Enumeration + (Eval_Logic_Match_Greater_Equal (Get_Enum_Pos (Left), + Get_Enum_Pos (Right), Orig), + Orig); + + when Iir_Predefined_Std_Ulogic_Match_Less_Equal => + return Build_Enumeration + (Eval_Logic_Match_Less_Equal (Get_Enum_Pos (Left), + Get_Enum_Pos (Right), Orig), + Orig); when Iir_Predefined_Real_To_String_Digits | Iir_Predefined_Time_To_String_Unit => |