aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/synth-stmts.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2020-05-02 07:59:09 +0200
committerTristan Gingold <tgingold@free.fr>2020-05-02 07:59:09 +0200
commitaeb47655ddfed9d3fd85c4986d21a60f83b9a8c6 (patch)
treeaa27d773849c84fffd2fd25bb0893b1bc0ebe7ef /src/synth/synth-stmts.adb
parente98cc23b32e85d7f31ca6427d40c33df70749238 (diff)
downloadghdl-aeb47655ddfed9d3fd85c4986d21a60f83b9a8c6.tar.gz
ghdl-aeb47655ddfed9d3fd85c4986d21a60f83b9a8c6.tar.bz2
ghdl-aeb47655ddfed9d3fd85c4986d21a60f83b9a8c6.zip
synth: use static values for control nets when possible.
Diffstat (limited to 'src/synth/synth-stmts.adb')
-rw-r--r--src/synth/synth-stmts.adb186
1 files changed, 106 insertions, 80 deletions
diff --git a/src/synth/synth-stmts.adb b/src/synth/synth-stmts.adb
index c2e923c65..b24425943 100644
--- a/src/synth/synth-stmts.adb
+++ b/src/synth/synth-stmts.adb
@@ -20,6 +20,7 @@
with Ada.Unchecked_Deallocation;
+with Grt.Types; use Grt.Types;
with Grt.Algos;
with Areapools;
with Name_Table;
@@ -1725,6 +1726,7 @@ package body Synth.Stmts is
Imp : constant Node := Get_Implementation (Call);
Is_Func : constant Boolean := Is_Function_Declaration (Imp);
Bod : constant Node := Vhdl.Sem_Inst.Get_Subprogram_Body_Origin (Imp);
+ Ctxt : constant Context_Acc := Get_Build (Syn_Inst);
Res : Valtyp;
C : Seq_Context (Mode_Dynamic);
Wire_Mark : Wire_Id;
@@ -1760,20 +1762,20 @@ package body Synth.Stmts is
Set_Wire_Gate (C.W_Val,
Build_Control_Signal (Sub_Inst, C.Ret_Typ.W, Imp));
C.Ret_Init := Build_Const_X (Build_Context, C.Ret_Typ.W);
- Phi_Assign_Net (Build_Context, C.W_Val, C.Ret_Init, 0);
+ Phi_Assign_Net (Ctxt, C.W_Val, C.Ret_Init, 0);
end if;
Set_Wire_Gate
(C.W_En, Build_Control_Signal (Sub_Inst, 1, Imp));
if En = No_Net then
- Phi_Assign_Net (Build_Context, C.W_En, Get_Inst_Bit1 (Syn_Inst), 0);
+ Phi_Assign_Static (C.W_En, Bit1);
else
- Phi_Assign_Net (Build_Context, C.W_En, En, 0);
+ Phi_Assign_Net (Ctxt, C.W_En, En, 0);
end if;
Set_Wire_Gate
(C.W_Ret, Build_Control_Signal (Sub_Inst, 1, Imp));
- Phi_Assign_Net (Build_Context, C.W_Ret, Get_Inst_Bit1 (Syn_Inst), 0);
+ Phi_Assign_Static (C.W_Ret, Bit1);
Decls.Synth_Declarations (C.Inst, Get_Declaration_Chain (Bod), En, True);
if not Is_Error (C.Inst) then
@@ -1790,7 +1792,7 @@ package body Synth.Stmts is
Res := C.Ret_Value;
else
Res := Create_Value_Net
- (Get_Current_Value (Build_Context, C.W_Val), C.Ret_Value.Typ);
+ (Get_Current_Value (Ctxt, C.W_Val), C.Ret_Value.Typ);
end if;
else
Res := No_Valtyp;
@@ -1809,7 +1811,7 @@ package body Synth.Stmts is
-- But assignment for outer wires (passed through parameters) have
-- to be kept. We cannot merge phi because this won't be allowed for
-- local wires.
- Propagate_Phi_Until_Mark (Get_Build (C.Inst), Subprg_Phi, Wire_Mark);
+ Propagate_Phi_Until_Mark (Ctxt, Subprg_Phi, Wire_Mark);
-- Free wires.
Free_Wire (C.W_En);
@@ -2038,49 +2040,88 @@ package body Synth.Stmts is
Write_Discrete (V, T);
end Update_Index;
+ -- Return True iff WID is a static wire and its value is 0.
+ function Is_Static_Bit (Wid : Wire_Id; V : Ghdl_U8) return Boolean
+ is
+ M : Memtyp;
+ begin
+ if not Is_Static_Wire (Wid) then
+ return False;
+ end if;
+ M := Get_Static_Wire (Wid);
+ return Read_U8 (M) = V;
+ end Is_Static_Bit;
+
+ function Is_Static_Bit0 (Wid : Wire_Id) return Boolean is
+ begin
+ return Is_Static_Bit (Wid, 0);
+ end Is_Static_Bit0;
+
+ function Is_Static_Bit1 (Wid : Wire_Id) return Boolean is
+ begin
+ return Is_Static_Bit (Wid, 1);
+ end Is_Static_Bit1;
+
+ pragma Inline (Is_Static_Bit0);
+ pragma Inline (Is_Static_Bit1);
+
procedure Loop_Control_Init (C : Seq_Context; Stmt : Node)
is
Lc : constant Loop_Context_Acc := C.Cur_Loop;
-
begin
+ -- We might create new wires that will be destroy at the end of the
+ -- loop. Use mark and sweep to control their lifetime.
Mark (C.Cur_Loop.Wire_Mark);
- if (Lc.Prev_Loop /= null and then Lc.Prev_Loop.Need_Quit) then
+ if Lc.Prev_Loop /= null and then Lc.Prev_Loop.Need_Quit then
+ -- An exit or next statement that targets an outer loop may suspend
+ -- the execution of this loop.
Lc.W_Quit := Alloc_Wire (Wire_Variable, Lc.Loop_Stmt);
Set_Wire_Gate (Lc.W_Quit, Build_Control_Signal (C.Inst, 1, Stmt));
- Phi_Assign_Net (Get_Build (C.Inst),
- Lc.W_Quit, Get_Inst_Bit1 (C.Inst), 0);
+ Phi_Assign_Static (Lc.W_Quit, Bit1);
end if;
if Get_Exit_Flag (Stmt) or else Get_Next_Flag (Stmt) then
- Lc.Saved_En := Get_Current_Value (null, C.W_En);
+ -- There is an exit or next statement that target this loop.
+ -- We need to save W_En, as if the execution is suspended due to
+ -- exit or next, it will resume at the end of the loop.
+ if Is_Static_Wire (C.W_En) then
+ pragma Assert (Is_Static_Bit1 (C.W_En));
+ Lc.Saved_En := No_Net;
+ else
+ Lc.Saved_En := Get_Current_Value (null, C.W_En);
+ end if;
+ -- Subloops may be suspended if there is an exit or a next statement
+ -- for this loop within subloops.
Lc.Need_Quit := True;
end if;
if Get_Exit_Flag (Stmt) then
- -- Exit statement for this loop.
+ -- There is an exit statement for this loop. Create the wire.
Lc.W_Exit := Alloc_Wire (Wire_Variable, Lc.Loop_Stmt);
Set_Wire_Gate (Lc.W_Exit, Build_Control_Signal (C.Inst, 1, Stmt));
- Phi_Assign_Net (Get_Build (C.Inst),
- Lc.W_Exit, Get_Inst_Bit1 (C.Inst), 0);
+ Phi_Assign_Static (Lc.W_Exit, Bit1);
end if;
end Loop_Control_Init;
- function Loop_Control_And (C : Seq_Context; L, R : Net) return Net
+ function Loop_Control_And (C : Seq_Context; L : Net; R : Wire_Id) return Net
is
- B1 : constant Net := Get_Inst_Bit1 (C.Inst);
Res : Net;
begin
- -- Optimize common cases.
- if L = B1 then
- return R;
- elsif R = B1 then
+ if R = No_Wire_Id or else Is_Static_Bit1 (R) then
return L;
- else
- Res := Build_Dyadic (Get_Build (C.Inst), Id_And, L, R);
+ end if;
+
+ pragma Assert (not Is_Static_Bit0 (R));
+
+ -- Optimize common cases.
+ Res := Get_Current_Value (null, R);
+
+ if L /= No_Net then
+ Res := Build_Dyadic (Get_Build (C.Inst), Id_And, L, Res);
Set_Location (Res, C.Cur_Loop.Loop_Stmt);
- return Res;
end if;
+ return Res;
end Loop_Control_And;
procedure Loop_Control_Update (C : Seq_Context)
@@ -2088,30 +2129,29 @@ package body Synth.Stmts is
Lc : constant Loop_Context_Acc := C.Cur_Loop;
Res : Net;
begin
+ if not Lc.Need_Quit then
+ -- No next/exit statement for this loop. So no control.
+ return;
+ end if;
+
-- Execution continue iff:
-- 1. Loop was enabled (Lc.Saved_En)
Res := Lc.Saved_En;
- if Res = No_Net then
- -- No loop control.
- return;
- end if;
-- 2. No return (C.W_Ret)
- if C.W_Ret /= No_Wire_Id then
- Res := Loop_Control_And (C, Res, Get_Current_Value (null, C.W_Ret));
- end if;
+ Res := Loop_Control_And (C, Res, C.W_Ret);
-- 3. No exit.
- if Lc.W_Exit /= No_Wire_Id then
- Res := Loop_Control_And (C, Res, Get_Current_Value (null, Lc.W_Exit));
- end if;
+ Res := Loop_Control_And (C, Res, Lc.W_Exit);
-- 4. No quit.
- if Lc.W_Quit /= No_Wire_Id then
- Res := Loop_Control_And (C, Res, Get_Current_Value (null, Lc.W_Quit));
- end if;
+ Res := Loop_Control_And (C, Res, Lc.W_Quit);
- Phi_Assign_Net (Get_Build (C.Inst), C.W_En, Res, 0);
+ if Res /= No_Net then
+ Phi_Assign_Net (Get_Build (C.Inst), C.W_En, Res, 0);
+ else
+ Phi_Assign_Static (C.W_En, Bit1);
+ end if;
end Loop_Control_Update;
procedure Loop_Control_Finish (C : Seq_Context)
@@ -2119,23 +2159,20 @@ package body Synth.Stmts is
Lc : constant Loop_Context_Acc := C.Cur_Loop;
Res : Net;
begin
- -- Execute continue iff:
- -- 1. Loop was enabled (Lc.Saved_En)
- Res := Lc.Saved_En;
- if Res = No_Net then
- -- No loop control.
+ if not Lc.Need_Quit then
+ -- No next/exit statement for this loop. So no control.
return;
end if;
+ -- Execution continue after this loop iff:
+ -- 1. Loop was enabled (Lc.Saved_En)
+ Res := Lc.Saved_En;
+
-- 2. No return (C.W_Ret)
- if C.W_Ret /= No_Wire_Id then
- Res := Loop_Control_And (C, Res, Get_Current_Value (null, C.W_Ret));
- end if;
+ Res := Loop_Control_And (C, Res, C.W_Ret);
-- 3. No quit (C.W_Quit)
- if Lc.W_Quit /= No_Wire_Id then
- Res := Loop_Control_And (C, Res, Get_Current_Value (null, Lc.W_Quit));
- end if;
+ Res := Loop_Control_And (C, Res, Lc.W_Quit);
Phi_Discard_Wires (Lc.W_Quit, Lc.W_Exit);
@@ -2149,7 +2186,11 @@ package body Synth.Stmts is
Release (C.Cur_Loop.Wire_Mark);
- Phi_Assign_Net (Get_Build (C.Inst), C.W_En, Res, 0);
+ if Res /= No_Net then
+ Phi_Assign_Net (Get_Build (C.Inst), C.W_En, Res, 0);
+ else
+ Phi_Assign_Static (C.W_En, Bit1);
+ end if;
end Loop_Control_Finish;
procedure Synth_Dynamic_Exit_Next_Statement
@@ -2180,7 +2221,7 @@ package body Synth.Stmts is
end if;
-- Execution is suspended for the current loop.
- Phi_Assign_Net (Ctxt, C.W_En, Get_Inst_Bit0 (C.Inst), 0);
+ Phi_Assign_Static (C.W_En, Bit0);
Lc := C.Cur_Loop;
@@ -2198,11 +2239,11 @@ package body Synth.Stmts is
if Lc.Loop_Stmt = Loop_Label then
-- Final loop.
if Is_Exit then
- Phi_Assign_Net (Ctxt, Lc.W_Exit, Get_Inst_Bit0 (C.Inst), 0);
+ Phi_Assign_Static (Lc.W_Exit, Bit0);
end if;
exit;
else
- Phi_Assign_Net (Ctxt, Lc.W_Quit, Get_Inst_Bit0 (C.Inst), 0);
+ Phi_Assign_Static (Lc.W_Quit, Bit0);
end if;
Lc := Lc.Prev_Loop;
end loop;
@@ -2323,7 +2364,7 @@ package body Synth.Stmts is
Loop_Control_Update (C);
-- Constant exit.
- exit when (Get_Current_Value (null, C.W_En) = Get_Inst_Bit0 (C.Inst));
+ exit when Is_Static_Bit0 (C.W_En);
-- FIXME: dynamic exits.
end loop;
@@ -2367,7 +2408,6 @@ package body Synth.Stmts is
procedure Synth_Dynamic_While_Loop_Statement
(C : in out Seq_Context; Stmt : Node)
is
- Bit0 : constant Net := Get_Inst_Bit0 (C.Inst);
Stmts : constant Node := Get_Sequential_Statement_Chain (Stmt);
Cond : constant Node := Get_Condition (Stmt);
Val : Valtyp;
@@ -2404,21 +2444,9 @@ package body Synth.Stmts is
Loop_Control_Update (C);
-- Exit from the loop if W_Exit/W_Ret/W_Quit = 0
- if Lc.W_Exit /= No_Wire_Id
- and then Get_Current_Value (null, Lc.W_Exit) = Bit0
- then
- exit;
- end if;
- if C.W_Ret /= No_Wire_Id
- and then Get_Current_Value (null, C.W_Ret) = Bit0
- then
- exit;
- end if;
- if Lc.W_Quit /= No_Wire_Id
- and then Get_Current_Value (null, Lc.W_Quit) = Bit0
- then
- exit;
- end if;
+ exit when Lc.W_Exit /= No_Wire_Id and then Is_Static_Bit0 (Lc.W_Exit);
+ exit when C.W_Ret /= No_Wire_Id and then Is_Static_Bit0 (C.W_Ret);
+ exit when Lc.W_Quit /= No_Wire_Id and then Is_Static_Bit0 (Lc.W_Quit);
Iter_Nbr := Iter_Nbr + 1;
if Iter_Nbr > Flags.Flag_Max_Loop and Flags.Flag_Max_Loop /= 0 then
@@ -2504,12 +2532,10 @@ package body Synth.Stmts is
if Is_Dyn then
-- The subprogram has returned. Do not execute further statements.
- Phi_Assign_Net (Get_Build (C.Inst),
- C.W_En, Get_Inst_Bit0 (C.Inst), 0);
+ Phi_Assign_Static (C.W_En, Bit0);
if C.W_Ret /= No_Wire_Id then
- Phi_Assign_Net (Get_Build (C.Inst),
- C.W_Ret, Get_Inst_Bit0 (C.Inst), 0);
+ Phi_Assign_Static (C.W_Ret, Bit0);
end if;
end if;
@@ -2609,14 +2635,12 @@ package body Synth.Stmts is
Stmt : Node;
Phi_T, Phi_F : Phi_Type;
Has_Phi : Boolean;
- En : Net;
begin
Stmt := Stmts;
while Is_Valid (Stmt) loop
if Is_Dyn then
- En := Get_Current_Value (null, C.W_En);
- pragma Assert (En /= Get_Inst_Bit0 (C.Inst));
- Has_Phi := En /= Get_Inst_Bit1 (C.Inst);
+ 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;
@@ -2698,7 +2722,8 @@ package body Synth.Stmts is
Get_Current_Value (Build_Context, C.W_En),
Phi_T, Phi_F, Stmt);
end if;
- if Get_Current_Value (null, C.W_En) = Get_Inst_Bit0 (C.Inst) then
+ if Is_Static_Bit0 (C.W_En) then
+ -- Not more execution.
return;
end if;
else
@@ -2755,12 +2780,13 @@ package body Synth.Stmts is
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);
M : Areapools.Mark_Type;
C_Sname : Sname;
C : Seq_Context (Mode_Dynamic);
begin
if Label = Null_Identifier then
- C_Sname := New_Internal_Name (Build_Context, Get_Sname (Syn_Inst));
+ C_Sname := New_Internal_Name (Ctxt, Get_Sname (Syn_Inst));
else
C_Sname := New_Sname_User (Label, Get_Sname (Syn_Inst));
end if;
@@ -2784,7 +2810,7 @@ package body Synth.Stmts is
end if;
Set_Wire_Gate (C.W_En, Build_Control_Signal (Syn_Inst, 1, Proc));
- Phi_Assign_Net (Build_Context, C.W_En, Get_Inst_Bit1 (Syn_Inst), 0);
+ Phi_Assign_Static (C.W_En, Bit1);
case Iir_Kinds_Process_Statement (Get_Kind (Proc)) is
when Iir_Kind_Sensitized_Process_Statement =>