diff options
author | Tristan Gingold <tgingold@free.fr> | 2020-05-15 05:39:31 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2020-05-15 05:39:31 +0200 |
commit | f4d0374404bc7539f78d07e0a926f9a600ff0096 (patch) | |
tree | 00e9d84f1892a95935770063201d075540888651 /src/synth/synth-stmts.adb | |
parent | e5db97602f30de4abf3b1e42e354a385352477b2 (diff) | |
download | ghdl-f4d0374404bc7539f78d07e0a926f9a600ff0096.tar.gz ghdl-f4d0374404bc7539f78d07e0a926f9a600ff0096.tar.bz2 ghdl-f4d0374404bc7539f78d07e0a926f9a600ff0096.zip |
synth-stmts: ignore choices with L/H/W/X/Z/-/U values.
Diffstat (limited to 'src/synth/synth-stmts.adb')
-rw-r--r-- | src/synth/synth-stmts.adb | 92 |
1 files changed, 86 insertions, 6 deletions
diff --git a/src/synth/synth-stmts.adb b/src/synth/synth-stmts.adb index 27176b491..99d64be5d 100644 --- a/src/synth/synth-stmts.adb +++ b/src/synth/synth-stmts.adb @@ -37,6 +37,7 @@ with Vhdl.Sem_Inst; with Vhdl.Utils; use Vhdl.Utils; with Vhdl.Std_Package; with Vhdl.Evaluation; +with Vhdl.Ieee.Std_Logic_1164; with PSL.Types; with PSL.Nodes; @@ -792,6 +793,63 @@ package body Synth.Stmts is type Alternative_Index is new Int32; + -- Only keep '0' and '1' in choices for std_logic. + function Ignore_Choice_Logic (V : Ghdl_U8; Loc : Node) return Boolean is + begin + case V is + when Vhdl.Ieee.Std_Logic_1164.Std_Logic_0_Pos + | Vhdl.Ieee.Std_Logic_1164.Std_Logic_1_Pos => + return False; + when Vhdl.Ieee.Std_Logic_1164.Std_Logic_L_Pos + | Vhdl.Ieee.Std_Logic_1164.Std_Logic_H_Pos => + Warning_Msg_Synth + (+Loc, "choice with 'L' or 'H' value is ignored"); + return True; + when Vhdl.Ieee.Std_Logic_1164.Std_Logic_U_Pos + | Vhdl.Ieee.Std_Logic_1164.Std_Logic_X_Pos + | Vhdl.Ieee.Std_Logic_1164.Std_Logic_D_Pos + | Vhdl.Ieee.Std_Logic_1164.Std_Logic_Z_Pos + | Vhdl.Ieee.Std_Logic_1164.Std_Logic_W_Pos => + Warning_Msg_Synth (+Loc, "choice with meta-value is ignored"); + return True; + when others => + -- Only 9 values. + raise Internal_Error; + end case; + end Ignore_Choice_Logic; + + function Ignore_Choice_Expression (V : Valtyp; Loc : Node) return Boolean is + begin + case V.Typ.Kind is + when Type_Bit => + return False; + when Type_Logic => + if V.Typ = Logic_Type then + return Ignore_Choice_Logic (Read_U8 (V.Val.Mem), Loc); + else + return False; + end if; + when Type_Discrete => + return False; + when Type_Vector => + if V.Typ.Vec_El = Logic_Type then + for I in 1 .. Size_Type (V.Typ.Vbound.Len) loop + if Ignore_Choice_Logic (Read_U8 (V.Val.Mem + (I - 1)), Loc) + then + return True; + end if; + end loop; + return False; + else + return False; + end if; + when Type_Array => + return False; + when others => + raise Internal_Error; + end case; + end Ignore_Choice_Expression; + -- Create the condition for choices of CHOICE chain belonging to the same -- alternative. Update CHOICE to the next alternative. procedure Synth_Choice (Syn_Inst : Synth_Instance_Acc; @@ -804,7 +862,9 @@ package body Synth.Stmts is is Ctxt : constant Context_Acc := Get_Build (Syn_Inst); Cond : Net; + Res : Net; begin + Res := No_Net; loop case Iir_Kinds_Case_Choice (Get_Kind (Choice)) is when Iir_Kind_Choice_By_Expression => @@ -815,8 +875,13 @@ package body Synth.Stmts is (Syn_Inst, Get_Choice_Expression (Choice)); V := Synth_Subtype_Conversion (Ctxt, V, Choice_Typ, False, Choice); - Cond := Build_Compare (Ctxt, Id_Eq, Sel, Get_Net (Ctxt, V)); - Set_Location (Cond, Choice); + if Ignore_Choice_Expression (V, Choice) then + Cond := No_Net; + else + Cond := Build_Compare + (Ctxt, Id_Eq, Sel, Get_Net (Ctxt, V)); + Set_Location (Cond, Choice); + end if; end; when Iir_Kind_Choice_By_Range => @@ -865,7 +930,8 @@ package body Synth.Stmts is end; when Iir_Kind_Choice_By_Others => - -- Last one. + -- Last and only one. + pragma Assert (Res = No_Net); Other_Choice := Choice_Idx + 1; pragma Assert (Get_Chain (Choice) = Null_Node); Choice := Null_Node; @@ -873,17 +939,31 @@ package body Synth.Stmts is end case; if not Get_Same_Alternative_Flag (Choice) then + -- First choice. Choice_Idx := Choice_Idx + 1; + Res := Cond; else - Cond := Build_Dyadic (Ctxt, Id_Or, Nets (Choice_Idx), Cond); - Set_Location (Cond, Choice); + if Cond = No_Net then + -- No new condition. + null; + else + if Res /= No_Net then + Res := Build_Dyadic (Ctxt, Id_Or, Res, Cond); + Set_Location (Res, Choice); + else + Res := Cond; + end if; + end if; end if; - Nets (Choice_Idx) := Cond; Choice := Get_Chain (Choice); exit when Choice = Null_Node or else not Get_Same_Alternative_Flag (Choice); end loop; + if Res = No_Net then + Res := Build_Const_UB32 (Ctxt, 0, 1); + end if; + Nets (Choice_Idx) := Res; end Synth_Choice; type Alternative_Data_Type is record |