aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2022-10-01 18:37:21 +0200
committerTristan Gingold <tgingold@free.fr>2022-10-02 11:47:36 +0200
commit16c6edba870d326b9189e99d9937779c42d41e12 (patch)
treeae736d9a3379666516b94ab0ba02d3d041b4adb7 /src
parent9c17ff87468773dd87d743c6eb20eb774ce24f8b (diff)
downloadghdl-16c6edba870d326b9189e99d9937779c42d41e12.tar.gz
ghdl-16c6edba870d326b9189e99d9937779c42d41e12.tar.bz2
ghdl-16c6edba870d326b9189e99d9937779c42d41e12.zip
synth-vhdl_stmts: handle passive process. Fix ghdl/ghdl-yosys-plugin#174
Diffstat (limited to 'src')
-rw-r--r--src/synth/synth-vhdl_stmts.adb222
1 files changed, 204 insertions, 18 deletions
diff --git a/src/synth/synth-vhdl_stmts.adb b/src/synth/synth-vhdl_stmts.adb
index 7b13214d2..246b771bc 100644
--- a/src/synth/synth-vhdl_stmts.adb
+++ b/src/synth/synth-vhdl_stmts.adb
@@ -3819,9 +3819,194 @@ package body Synth.Vhdl_Stmts is
end loop;
end Synth_Sequential_Statements;
+ procedure Synth_Sequential_Statement
+ (C : in out Seq_Context; Stmt : Node)
+ is
+ Is_Dyn : constant Boolean := not Get_Instance_Const (C.Inst);
+ Marker : Mark_Type;
+ Has_Phi : Boolean;
+ begin
+ Mark_Expr_Pool (Marker);
+
+ if Is_Dyn then
+ pragma Assert (not Is_Static_Bit0 (C.W_En));
+ Has_Phi := not Is_Static_Bit1 (C.W_En);
+ if Has_Phi then
+ Push_Phi;
+ end if;
+ end if;
+
+ if Flags.Flag_Trace_Statements then
+ Elab.Vhdl_Debug.Put_Stmt_Trace (Stmt);
+ end if;
+ if Elab.Debugger.Flag_Need_Debug then
+ Elab.Debugger.Debug_Break (C.Inst, Stmt);
+ end if;
+
+ case Get_Kind (Stmt) is
+ when Iir_Kind_If_Statement =>
+ Synth_If_Statement (C, Stmt);
+ when Iir_Kind_Simple_Signal_Assignment_Statement =>
+ Synth_Simple_Signal_Assignment (C.Inst, Stmt);
+ when Iir_Kind_Conditional_Signal_Assignment_Statement =>
+ Synth_Conditional_Signal_Assignment (C.Inst, Stmt);
+ when Iir_Kind_Variable_Assignment_Statement =>
+ Synth_Variable_Assignment (C.Inst, Stmt);
+ when Iir_Kind_Conditional_Variable_Assignment_Statement =>
+ Synth_Conditional_Variable_Assignment (C.Inst, Stmt);
+ when Iir_Kind_Case_Statement =>
+ Synth_Case_Statement (C, Stmt);
+ when Iir_Kind_For_Loop_Statement =>
+ if Is_Dyn then
+ Synth_Dynamic_For_Loop_Statement (C, Stmt);
+ else
+ Synth_Static_For_Loop_Statement (C, Stmt);
+ end if;
+ when Iir_Kind_While_Loop_Statement =>
+ if Is_Dyn then
+ Synth_Dynamic_While_Loop_Statement (C, Stmt);
+ else
+ Synth_Static_While_Loop_Statement (C, Stmt);
+ end if;
+ when Iir_Kind_Null_Statement =>
+ -- Easy
+ null;
+ when Iir_Kind_Return_Statement =>
+ Synth_Return_Statement (C, Stmt);
+ when Iir_Kind_Procedure_Call_Statement =>
+ Synth_Procedure_Call (C.Inst, Stmt);
+ when Iir_Kind_Report_Statement =>
+ if not Is_Dyn then
+ Execute_Report_Statement (C.Inst, Stmt);
+ else
+ -- Not executed.
+ -- Depends on the execution path: the report statement may
+ -- be conditionally executed.
+ Synth_Dynamic_Report_Statement (C.Inst, Stmt, True);
+ end if;
+ when Iir_Kind_Assertion_Statement =>
+ if not Is_Dyn then
+ Execute_Assertion_Statement (C.Inst, Stmt);
+ else
+ Synth_Dynamic_Assertion_Statement (C, Stmt);
+ end if;
+ when Iir_Kind_Exit_Statement
+ | Iir_Kind_Next_Statement =>
+ if Is_Dyn then
+ Synth_Dynamic_Exit_Next_Statement (C, Stmt);
+ else
+ Synth_Static_Exit_Next_Statement (C, Stmt);
+ end if;
+ when Iir_Kind_Wait_Statement =>
+ Error_Msg_Synth
+ (C.Inst, Stmt, "wait statement not allowed for synthesis");
+ when others =>
+ Error_Kind ("synth_sequential_statements", Stmt);
+ end case;
+ if Is_Dyn then
+ if Has_Phi then
+ declare
+ Ctxt : constant Context_Acc := Get_Build (C.Inst);
+ Phi_T, Phi_F : Phi_Type;
+ begin
+ Pop_Phi (Phi_T);
+ Push_Phi;
+ Pop_Phi (Phi_F);
+ Merge_Phis (Ctxt, Get_Current_Value (Ctxt, C.W_En),
+ Phi_T, Phi_F, Get_Location (Stmt));
+ end;
+ end if;
+ if Is_Static_Bit0 (C.W_En) then
+ -- Not more execution.
+ return;
+ end if;
+ else
+ if not C.S_En or C.Nbr_Ret /= 0 then
+ return;
+ end if;
+ end if;
+ end Synth_Sequential_Statement;
+
+ function Make_Process_Instance (Syn_Inst : Synth_Instance_Acc;
+ Proc : Node) return Synth_Instance_Acc
+ is
+ Label : constant Name_Id := Get_Identifier (Proc);
+ P_Sname : constant Sname := Get_Sname (Syn_Inst);
+ C_Sname : Sname;
+ begin
+ if Label = Null_Identifier then
+ C_Sname := New_Internal_Name (Get_Build (Syn_Inst), P_Sname);
+ else
+ C_Sname := New_Sname_User (Label, P_Sname);
+ end if;
+ return Make_Instance (Syn_Inst, Proc, C_Sname);
+ end Make_Process_Instance;
+
+ -- Non-sensitized process statement whose first statement is no a wait.
+ -- Allow:
+ -- * conditional if/then with globally static conditions
+ -- * asserts with globally static conditions
+ -- * reports
+ -- * final wait (without any expression).
+ procedure Synth_Non_Sensitized_Process_Statement
+ (Syn_Inst : Synth_Instance_Acc; Proc : Node)
+ is
+ use Areapools;
+ Decls : constant Node := Get_Declaration_Chain (Proc);
+ Prev_Instance_Pool : constant Areapool_Acc := Instance_Pool;
+ Proc_Marker : Areapools.Mark_Type;
+ C : Seq_Context (Mode_Static);
+ Stmt : Node;
+ begin
+ C := (Mode_Static,
+ Inst => Make_Process_Instance (Syn_Inst, Proc),
+ Cur_Loop => null,
+ S_En => True,
+ Ret_Value => No_Valtyp,
+ Ret_Typ => null,
+ Nbr_Ret => 0);
+ Set_Instance_Const (C.Inst, True);
+
+ Mark (Proc_Marker, Proc_Pool);
+ Instance_Pool := Proc_Pool'Access;
+
+ Synth_Declarations (C.Inst, Decls, True);
+
+ Stmt := Get_Sequential_Statement_Chain (Proc);
+ while Stmt /= Null_Node loop
+ if Get_Kind (Stmt) = Iir_Kind_Wait_Statement then
+ if Get_Chain (Stmt) /= Null_Node then
+ Error_Msg_Synth (C.Inst, Stmt,
+ "wait must be the last statement");
+ elsif Get_Condition_Clause (Stmt) /= Null_Node
+ or else Get_Timeout_Clause (Stmt) /= Null_Node
+ or else Get_Sensitivity_List (Stmt) /= Null_Iir_List
+ then
+ Error_Msg_Synth (C.Inst, Stmt,
+ "wait statement must have no clauses");
+ end if;
+ exit;
+ end if;
+
+ Synth_Sequential_Statement (C, Stmt);
+
+ Stmt := Get_Chain (Stmt);
+ end loop;
+ if Stmt = Null_Node then
+ Error_Msg_Synth (C.Inst, Proc,
+ "missing wait statement at end of process");
+ end if;
+
+ Finalize_Declarations (C.Inst, Decls);
+
+ Free_Instance (C.Inst);
+ Release (Proc_Marker, Proc_Pool);
+ Instance_Pool := Prev_Instance_Pool;
+ end Synth_Non_Sensitized_Process_Statement;
+
-- Synthesis of statements of a non-sensitized process.
procedure Synth_Process_Sequential_Statements
- (C : in out Seq_Context; Proc : Node)
+ (C : in out Seq_Context; Stmts : Node)
is
Ctxt : constant Context_Acc := Get_Build (C.Inst);
Marker : Mark_Type;
@@ -3831,13 +4016,7 @@ package body Synth.Vhdl_Stmts is
Phi_True : Phi_Type;
Phi_False : Phi_Type;
begin
- Stmt := Get_Sequential_Statement_Chain (Proc);
-
- -- The first statement must be a wait statement.
- if Get_Kind (Stmt) /= Iir_Kind_Wait_Statement then
- Error_Msg_Synth (C.Inst, Stmt, "expect wait as the first statement");
- return;
- end if;
+ Stmt := Stmts;
Mark_Expr_Pool (Marker);
@@ -3865,21 +4044,29 @@ package body Synth.Vhdl_Stmts is
(Syn_Inst : Synth_Instance_Acc; Proc : Node)
is
use Areapools;
- Label : constant Name_Id := Get_Identifier (Proc);
Decls_Chain : constant Node := Get_Declaration_Chain (Proc);
Prev_Instance_Pool : constant Areapool_Acc := Instance_Pool;
Ctxt : constant Context_Acc := Get_Build (Syn_Inst);
+ Stmts : constant Node := Get_Sequential_Statement_Chain (Proc);
M : Areapools.Mark_Type;
- C_Sname : Sname;
C : Seq_Context (Mode_Dynamic);
begin
- if Label = Null_Identifier then
- C_Sname := New_Internal_Name (Ctxt, Get_Sname (Syn_Inst));
- else
- C_Sname := New_Sname_User (Label, Get_Sname (Syn_Inst));
+ -- Quick check for non-sensitized processes
+ if Get_Kind (Proc) = Iir_Kind_Process_Statement then
+ if Stmts = Null_Node then
+ Error_Msg_Synth (Syn_Inst, Proc,
+ "empty process statement not allowed");
+ return;
+ end if;
+ if Get_Kind (Stmts) /= Iir_Kind_Wait_Statement then
+ -- Don't start with a wait, assume a passive process.
+ Synth_Non_Sensitized_Process_Statement (Syn_Inst, Proc);
+ return;
+ end if;
end if;
+
C := (Mode => Mode_Dynamic,
- Inst => Make_Instance (Syn_Inst, Proc, C_Sname),
+ Inst => Make_Process_Instance (Syn_Inst, Proc),
Cur_Loop => null,
W_En => Alloc_Wire (Wire_Variable, (Proc, Bit_Type)),
W_Ret => No_Wire_Id,
@@ -3905,11 +4092,10 @@ package body Synth.Vhdl_Stmts is
if not Is_Error (C.Inst) then
case Iir_Kinds_Process_Statement (Get_Kind (Proc)) is
when Iir_Kind_Sensitized_Process_Statement =>
- Synth_Sequential_Statements
- (C, Get_Sequential_Statement_Chain (Proc));
+ Synth_Sequential_Statements (C, Stmts);
-- FIXME: check sensitivity list.
when Iir_Kind_Process_Statement =>
- Synth_Process_Sequential_Statements (C, Proc);
+ Synth_Process_Sequential_Statements (C, Stmts);
end case;
end if;
pragma Assert (Is_Expr_Pool_Empty);