aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth
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
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')
-rw-r--r--src/synth/synth-environment.adb120
-rw-r--r--src/synth/synth-environment.ads3
-rw-r--r--src/synth/synth-objtypes.adb35
-rw-r--r--src/synth/synth-objtypes.ads6
-rw-r--r--src/synth/synth-stmts.adb186
-rw-r--r--src/synth/synth-stmts.ads1
-rw-r--r--src/synth/synth-values.adb19
-rw-r--r--src/synth/synth-values.ads1
8 files changed, 241 insertions, 130 deletions
diff --git a/src/synth/synth-environment.adb b/src/synth/synth-environment.adb
index cf5384eb3..ff295dba9 100644
--- a/src/synth/synth-environment.adb
+++ b/src/synth/synth-environment.adb
@@ -156,6 +156,11 @@ package body Synth.Environment is
return Assign_Table.Table (Asgn).Val.Asgns;
end Get_Assign_Partial;
+ function Get_Assign_Partial (Asgn : Seq_Assign) return Seq_Assign_Value is
+ begin
+ return Assign_Table.Table (Asgn).Val;
+ end Get_Assign_Partial;
+
function New_Partial_Assign (Val : Net; Offset : Uns32)
return Partial_Assign is
begin
@@ -198,8 +203,9 @@ package body Synth.Environment is
Nbr => 0));
end Push_Phi;
+ -- Concatenate when possible partial assignments of HEAD.
procedure Merge_Partial_Assignments
- (Ctxt : Context_Acc; Head : Partial_Assign)
+ (Ctxt : Context_Acc; Head : Seq_Assign_Value)
is
use Netlists.Concats;
First : Partial_Assign;
@@ -209,7 +215,11 @@ package body Synth.Environment is
Next_Off : Uns32;
Next_Val : Net;
begin
- First := Head;
+ if Head.Is_Static then
+ return;
+ end if;
+
+ First := Head.Asgns;
loop
exit when First = No_Partial_Assign;
@@ -1310,26 +1320,81 @@ package body Synth.Environment is
end Merge_Assigns;
-- Force the value of a Seq_Assign to be a net if needed, return it.
- function Get_Assign_Partial_Force (Asgn : Seq_Assign) return Partial_Assign
+ function Get_Assign_Value_Force (Val : Seq_Assign_Value)
+ return Partial_Assign
is
- Asgn_Rec : Seq_Assign_Record renames Assign_Table.Table (Asgn);
N : Net;
- Res : Partial_Assign;
begin
- if Asgn_Rec.Val.Is_Static then
- N := Synth.Context.Get_Memtyp_Net (Asgn_Rec.Val.Val);
- Res := New_Partial_Assign (N, 0);
- if False then
- -- Overwrite ?
- Asgn_Rec.Val := (Is_Static => False,
- Asgns => Res);
- end if;
+ if Val.Is_Static then
+ N := Synth.Context.Get_Memtyp_Net (Val.Val);
+ return New_Partial_Assign (N, 0);
else
- Res := Asgn_Rec.Val.Asgns;
+ return Val.Asgns;
end if;
- return Res;
+ end Get_Assign_Value_Force;
+
+ -- Force the value of a Seq_Assign to be a net if needed, return it.
+ function Get_Assign_Partial_Force (Asgn : Seq_Assign)
+ return Partial_Assign is
+ begin
+ return Get_Assign_Value_Force (Get_Assign_Partial (Asgn));
end Get_Assign_Partial_Force;
+ function Merge_Static_Assigns (Wid : Wire_Id; Tv, Fv : Seq_Assign_Value)
+ return Boolean
+ is
+ Prev : Memtyp;
+ begin
+ -- First case: both TV and FV are static.
+ if Tv.Is_Static and then Fv.Is_Static then
+ if Is_Equal (Tv.Val, Fv.Val) then
+ Phi_Assign_Static (Wid, Tv.Val);
+ return True;
+ else
+ return False;
+ end if;
+ end if;
+
+ -- If either TV or FV are not static, they cannot be merged.
+ if not Tv.Is_Static and then Tv.Asgns /= No_Partial_Assign
+ then
+ return False;
+ end if;
+ if not Fv.Is_Static and then Fv.Asgns /= No_Partial_Assign
+ then
+ return False;
+ end if;
+
+ -- Get the previous value.
+ declare
+ Wire_Rec : Wire_Id_Record renames Wire_Id_Table.Table (Wid);
+ pragma Assert (Wire_Rec.Kind /= Wire_None);
+ First_Seq : Seq_Assign;
+ begin
+ -- Latest seq assign
+ First_Seq := Wire_Rec.Cur_Assign;
+
+ -- If no seq assign, fails.
+ if First_Seq = No_Seq_Assign then
+ return False;
+ end if;
+
+ if not Get_Assign_Is_Static (First_Seq) then
+ return False;
+ end if;
+ Prev := Get_Assign_Static_Val (First_Seq);
+ end;
+
+ if Tv.Is_Static then
+ pragma Assert (Fv = No_Seq_Assign_Value);
+ return Is_Equal (Tv.Val, Prev);
+ else
+ pragma Assert (Fv.Is_Static);
+ pragma Assert (Tv = No_Seq_Assign_Value);
+ return Is_Equal (Fv.Val, Prev);
+ end if;
+ end Merge_Static_Assigns;
+
-- Add muxes for two lists T and F of assignments.
procedure Merge_Phis (Ctxt : Builders.Context_Acc;
Sel : Net;
@@ -1339,7 +1404,7 @@ package body Synth.Environment is
T_Asgns : Seq_Assign;
F_Asgns : Seq_Assign;
W : Wire_Id;
- Tp, Fp : Partial_Assign;
+ Tv, Fv : Seq_Assign_Value;
begin
T_Asgns := Sort_Phi (T);
F_Asgns := Sort_Phi (F);
@@ -1352,8 +1417,8 @@ package body Synth.Environment is
then
-- Has an assignment only for the false branch.
W := Get_Wire_Id (F_Asgns);
- Fp := Get_Assign_Partial_Force (F_Asgns);
- Tp := No_Partial_Assign;
+ Fv := Get_Assign_Partial (F_Asgns);
+ Tv := No_Seq_Assign_Value;
F_Asgns := Get_Assign_Chain (F_Asgns);
elsif F_Asgns = No_Seq_Assign
or else (T_Asgns /= No_Seq_Assign
@@ -1361,23 +1426,28 @@ package body Synth.Environment is
then
-- Has an assignment only for the true branch.
W := Get_Wire_Id (T_Asgns);
- Fp := No_Partial_Assign;
- Tp := Get_Assign_Partial_Force (T_Asgns);
+ Fv := No_Seq_Assign_Value;
+ Tv := Get_Assign_Partial (T_Asgns);
T_Asgns := Get_Assign_Chain (T_Asgns);
else
-- Has assignments for both the true and the false branch.
pragma Assert (Get_Wire_Id (F_Asgns) = Get_Wire_Id (T_Asgns));
W := Get_Wire_Id (F_Asgns);
- Fp := Get_Assign_Partial_Force (F_Asgns);
- Tp := Get_Assign_Partial_Force (T_Asgns);
+ Fv := Get_Assign_Partial (F_Asgns);
+ Tv := Get_Assign_Partial (T_Asgns);
T_Asgns := Get_Assign_Chain (T_Asgns);
F_Asgns := Get_Assign_Chain (F_Asgns);
end if;
-- Merge partial assigns as much as possible. This reduce
-- propagation of splits.
- Merge_Partial_Assignments (Ctxt, Fp);
- Merge_Partial_Assignments (Ctxt, Tp);
- Merge_Assigns (Ctxt, W, Sel, Fp, Tp, Stmt);
+ Merge_Partial_Assignments (Ctxt, Fv);
+ Merge_Partial_Assignments (Ctxt, Tv);
+ if not Merge_Static_Assigns (W, Tv, Fv) then
+ Merge_Assigns (Ctxt, W, Sel,
+ Get_Assign_Value_Force (Fv),
+ Get_Assign_Value_Force (Tv),
+ Stmt);
+ end if;
end loop;
end Merge_Phis;
diff --git a/src/synth/synth-environment.ads b/src/synth/synth-environment.ads
index a183e68ca..a2f209302 100644
--- a/src/synth/synth-environment.ads
+++ b/src/synth/synth-environment.ads
@@ -281,6 +281,9 @@ private
end case;
end record;
+ No_Seq_Assign_Value : constant Seq_Assign_Value :=
+ (Is_Static => False, Asgns => No_Partial_Assign);
+
type Seq_Assign_Record is record
-- Target of the assignment.
Id : Wire_Id;
diff --git a/src/synth/synth-objtypes.adb b/src/synth/synth-objtypes.adb
index 8c9867a28..10602256b 100644
--- a/src/synth/synth-objtypes.adb
+++ b/src/synth/synth-objtypes.adb
@@ -661,14 +661,14 @@ package body Synth.Objtypes is
return Read_Fp64 (Mt.Mem);
end Read_Fp64;
+ function To_Address is new Ada.Unchecked_Conversion
+ (Memory_Ptr, System.Address);
+ function To_Memory_Ptr is new Ada.Unchecked_Conversion
+ (System.Address, Memory_Ptr);
+
function "+" (Base : Memory_Ptr; Off : Size_Type) return Memory_Ptr
is
use System.Storage_Elements;
-
- function To_Address is new Ada.Unchecked_Conversion
- (Memory_Ptr, System.Address);
- function To_Memory_Ptr is new Ada.Unchecked_Conversion
- (System.Address, Memory_Ptr);
begin
return To_Memory_Ptr (To_Address (Base) + Storage_Offset (Off));
end "+";
@@ -758,11 +758,36 @@ package body Synth.Objtypes is
return (Vtype, Res);
end Create_Memory_Discrete;
+ function Is_Equal (L, R : Memtyp) return Boolean is
+ begin
+ if L = R then
+ return True;
+ end if;
+
+ if L.Typ.Sz /= R.Typ.Sz then
+ return False;
+ end if;
+
+ -- FIXME: not correct for records, not correct for floats!
+ for I in 1 .. L.Typ.Sz loop
+ if L.Mem (I - 1) /= R.Mem (I - 1) then
+ return False;
+ end if;
+ end loop;
+ return True;
+ end Is_Equal;
+
+ Bit0_Mem : constant Memory_Element := 0;
+ Bit1_Mem : constant Memory_Element := 1;
+
procedure Init is
begin
Instance_Pool := Global_Pool'Access;
Boolean_Type := Create_Bit_Type;
Logic_Type := Create_Logic_Type;
Bit_Type := Create_Bit_Type;
+
+ Bit0 := (Bit_Type, To_Memory_Ptr (Bit0_Mem'Address));
+ Bit1 := (Bit_Type, To_Memory_Ptr (Bit1_Mem'Address));
end Init;
end Synth.Objtypes;
diff --git a/src/synth/synth-objtypes.ads b/src/synth/synth-objtypes.ads
index c79a473c4..91ffcc32e 100644
--- a/src/synth/synth-objtypes.ads
+++ b/src/synth/synth-objtypes.ads
@@ -281,10 +281,16 @@ package Synth.Objtypes is
function Create_Memory (Vtype : Type_Acc) return Memtyp;
+ function Is_Equal (L, R : Memtyp) return Boolean;
+
procedure Init;
-- Set by Init.
Boolean_Type : Type_Acc := null;
Logic_Type : Type_Acc := null;
Bit_Type : Type_Acc := null;
+
+ -- Also set by init.
+ Bit0 : Memtyp;
+ Bit1 : Memtyp;
end Synth.Objtypes;
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 =>
diff --git a/src/synth/synth-stmts.ads b/src/synth/synth-stmts.ads
index c946746cd..330cf156e 100644
--- a/src/synth/synth-stmts.ads
+++ b/src/synth/synth-stmts.ads
@@ -117,6 +117,7 @@ private
case Mode is
when Mode_Dynamic =>
+ -- Set when this loop has next/exit statements for itself.
-- Set to true so that inner loops have to declare W_Quit.
Need_Quit : Boolean;
diff --git a/src/synth/synth-values.adb b/src/synth/synth-values.adb
index 995f41d55..ed042c849 100644
--- a/src/synth/synth-values.adb
+++ b/src/synth/synth-values.adb
@@ -89,25 +89,6 @@ package body Synth.Values is
return (V.Typ, Strip_Alias_Const (V.Val));
end Strip_Alias_Const;
- function Is_Equal (L, R : Memtyp) return Boolean is
- begin
- if L = R then
- return True;
- end if;
-
- if L.Typ.Sz /= R.Typ.Sz then
- return False;
- end if;
-
- -- FIXME: not correct for records, not correct for floats!
- for I in 1 .. L.Typ.Sz loop
- if L.Mem (I - 1) /= R.Mem (I - 1) then
- return False;
- end if;
- end loop;
- return True;
- end Is_Equal;
-
function Is_Equal (L, R : Valtyp) return Boolean is
begin
return Is_Equal (Get_Memtyp (L), Get_Memtyp (R));
diff --git a/src/synth/synth-values.ads b/src/synth/synth-values.ads
index e90bbedbc..77798c9f0 100644
--- a/src/synth/synth-values.ads
+++ b/src/synth/synth-values.ads
@@ -110,7 +110,6 @@ package Synth.Values is
function Is_Static_Val (Val : Value_Acc) return Boolean;
function Is_Equal (L, R : Valtyp) return Boolean;
- function Is_Equal (L, R : Memtyp) return Boolean;
function Create_Value_Memtyp (Mt : Memtyp) return Valtyp;