aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2023-03-14 08:17:24 +0100
committerTristan Gingold <tgingold@free.fr>2023-03-14 08:17:24 +0100
commite4740a99eb4db83bfbc212a699745d2d51494554 (patch)
tree9560bdc2f6d5f6d35bb9d54b5d5419e95891bda2 /src
parentc0975bc8a3e2ba9058a2236d01c79aaec3dc4169 (diff)
downloadghdl-e4740a99eb4db83bfbc212a699745d2d51494554.tar.gz
ghdl-e4740a99eb4db83bfbc212a699745d2d51494554.tar.bz2
ghdl-e4740a99eb4db83bfbc212a699745d2d51494554.zip
synth_conditiona_signal_assignment: handle simple case directly.
Fix #2390
Diffstat (limited to 'src')
-rw-r--r--src/synth/synth-vhdl_stmts.adb125
1 files changed, 79 insertions, 46 deletions
diff --git a/src/synth/synth-vhdl_stmts.adb b/src/synth/synth-vhdl_stmts.adb
index 9a8e0e36a..6a6285a96 100644
--- a/src/synth/synth-vhdl_stmts.adb
+++ b/src/synth/synth-vhdl_stmts.adb
@@ -857,7 +857,7 @@ package body Synth.Vhdl_Stmts is
Marker : Mark_Type;
Targ : Target_Info;
Cond : Node;
- Cwf, Wf : Node;
+ Cwf, Next_Cwf, Wf : Node;
Inp : Input;
Val, Cond_Val : Valtyp;
Cond_Net : Net;
@@ -866,59 +866,92 @@ package body Synth.Vhdl_Stmts is
begin
Mark_Expr_Pool (Marker);
Targ := Synth_Target (Syn_Inst, Get_Target (Stmt));
- Last := No_Net;
Cwf := Get_Conditional_Waveform_Chain (Stmt);
- Cond := Null_Node;
- while Cwf /= Null_Node loop
- Wf := Get_Waveform_Chain (Cwf);
- if Get_Kind (Wf) = Iir_Kind_Unaffected_Waveform then
- -- For unaffected, read the current value.
- Val := Synth_Read (Syn_Inst, Targ, Stmt);
- else
+ Cond := Get_Condition (Cwf);
+ Next_Cwf := Get_Chain (Cwf);
+
+ -- Handle directly:
+ -- targ <= value when cond [else unaffected]
+ if Cond /= Null_Node
+ and then
+ (Next_Cwf = Null_Node
+ or else (Get_Kind (Get_Waveform_Chain (Next_Cwf))
+ = Iir_Kind_Unaffected_Waveform))
+ then
+ declare
+ Phi_True : Phi_Type;
+ Phi_False : Phi_Type;
+ begin
+ Cond_Val := Synth_Expression (Syn_Inst, Cond);
+
+ Push_Phi;
+ Wf := Get_Waveform_Chain (Cwf);
Val := Synth_Waveform (Syn_Inst, Wf, Targ.Targ_Type);
- end if;
- if Val = No_Valtyp then
- -- Mark the error, but try to continue.
- Set_Error (Syn_Inst);
- else
- V := Get_Net (Ctxt, Val);
- Cond := Get_Condition (Cwf);
- if Cond /= Null_Node then
- -- Add a mux to make it conditional.
- Cond_Val := Synth_Expression (Syn_Inst, Cond);
- if Cond_Val = No_Valtyp then
- Cond_Net := Build_Const_UB32 (Ctxt, 0, 1);
- else
- Cond_Net := Get_Net (Ctxt, Cond_Val);
- end if;
+ Synth_Assignment (Syn_Inst, Targ, Val, Stmt);
+ Pop_Phi (Phi_True);
- V := Build_Mux2 (Ctxt, Cond_Net, No_Net, V);
- Set_Location (V, Cwf);
- end if;
+ Push_Phi;
+ Pop_Phi (Phi_False);
- -- Append
- if Last /= No_Net then
- Inp := Get_Input (Get_Net_Parent (Last), 1);
- Connect (Inp, V);
+ Cond_Net := Get_Net (Ctxt, Cond_Val);
+ Merge_Phis
+ (Ctxt, Cond_Net, Phi_True, Phi_False, Get_Location (Stmt));
+ end;
+ else
+ Last := No_Net;
+ Cond := Null_Node;
+ while Cwf /= Null_Node loop
+ Wf := Get_Waveform_Chain (Cwf);
+ if Get_Kind (Wf) = Iir_Kind_Unaffected_Waveform then
+ -- For unaffected, read the current value.
+ Val := Synth_Read (Syn_Inst, Targ, Stmt);
else
- First := V;
+ Val := Synth_Waveform (Syn_Inst, Wf, Targ.Targ_Type);
+ end if;
+ if Val = No_Valtyp then
+ -- Mark the error, but try to continue.
+ Set_Error (Syn_Inst);
+ else
+ V := Get_Net (Ctxt, Val);
+ Cond := Get_Condition (Cwf);
+ if Cond /= Null_Node then
+ -- Add a mux to make it conditional.
+ Cond_Val := Synth_Expression (Syn_Inst, Cond);
+ if Cond_Val = No_Valtyp then
+ Cond_Net := Build_Const_UB32 (Ctxt, 0, 1);
+ else
+ Cond_Net := Get_Net (Ctxt, Cond_Val);
+ end if;
+
+ V := Build_Mux2 (Ctxt, Cond_Net, No_Net, V);
+ Set_Location (V, Cwf);
+ end if;
+
+ -- Append
+ if Last /= No_Net then
+ Inp := Get_Input (Get_Net_Parent (Last), 1);
+ Connect (Inp, V);
+ else
+ First := V;
+ end if;
+ Last := V;
+ end if;
+ Cwf := Get_Chain (Cwf);
+ end loop;
+ if Cond /= Null_Node then
+ -- If the last waveform has a condition, set the else branch.
+ pragma Assert (Last /= No_Net);
+ Inp := Get_Input (Get_Net_Parent (Last), 1);
+ if Get_Driver (Inp) = No_Net then
+ -- No else.
+ Val := Synth_Read (Syn_Inst, Targ, Stmt);
+ Connect (Inp, Get_Net (Ctxt, Val));
end if;
- Last := V;
- end if;
- Cwf := Get_Chain (Cwf);
- end loop;
- if Cond /= Null_Node then
- -- If the last waveform has a condition, set the else branch.
- pragma Assert (Last /= No_Net);
- Inp := Get_Input (Get_Net_Parent (Last), 1);
- if Get_Driver (Inp) = No_Net then
- -- No else.
- Val := Synth_Read (Syn_Inst, Targ, Stmt);
- Connect (Inp, Get_Net (Ctxt, Val));
end if;
+ Val := Create_Value_Net (First, Targ.Targ_Type);
+ Synth_Assignment (Syn_Inst, Targ, Val, Stmt);
end if;
- Val := Create_Value_Net (First, Targ.Targ_Type);
- Synth_Assignment (Syn_Inst, Targ, Val, Stmt);
+
Release_Expr_Pool (Marker);
end Synth_Conditional_Signal_Assignment;