aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/synth-environment.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-environment.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-environment.adb')
-rw-r--r--src/synth/synth-environment.adb120
1 files changed, 95 insertions, 25 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;