aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/synth-environment.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2020-03-22 08:23:36 +0100
committerTristan Gingold <tgingold@free.fr>2020-03-22 08:23:36 +0100
commit283a032e58d32a72873c647e017da3760bdedb53 (patch)
tree332b757b61753d9c43ddf191b26c67b4e9e1a727 /src/synth/synth-environment.adb
parente3bac06b441a7e5b95b0a0f662c5e0fce8f57d3c (diff)
downloadghdl-283a032e58d32a72873c647e017da3760bdedb53.tar.gz
ghdl-283a032e58d32a72873c647e017da3760bdedb53.tar.bz2
ghdl-283a032e58d32a72873c647e017da3760bdedb53.zip
synth: handle reuse of inferred dff in the same process.
Fix tgingold/ghdlsynth-beta#93
Diffstat (limited to 'src/synth/synth-environment.adb')
-rw-r--r--src/synth/synth-environment.adb85
1 files changed, 60 insertions, 25 deletions
diff --git a/src/synth/synth-environment.adb b/src/synth/synth-environment.adb
index 8063f17fc..49230cce6 100644
--- a/src/synth/synth-environment.adb
+++ b/src/synth/synth-environment.adb
@@ -366,48 +366,83 @@ package body Synth.Environment is
Stmt : Source.Syn_Src)
is
Phi : Phi_Type;
- First, Last : Seq_Assign;
- Asgn, Next_Asgn : Seq_Assign;
+ Asgn : Seq_Assign;
begin
Pop_Phi (Phi);
- First := No_Seq_Assign;
- Last := No_Seq_Assign;
+ -- It is possible that the same value is assigned to different targets.
+ -- Example:
+ -- if rising_edge(clk) then
+ -- a := c;
+ -- end if;
+ -- b := a;
+ -- Because the assignment is not yet done, only the net is stored in
+ -- the partial assign. When the net for variable A is infered and
+ -- changed to a dff, it is not known that it will also be assigned to
+ -- variable B.
+ --
+ -- Mark gates that will be infered. And if already marked, insert
+ -- a nop.
+ Asgn := Phi.First;
+ while Asgn /= No_Seq_Assign loop
+ declare
+ Asgn_Rec : Seq_Assign_Record renames Assign_Table.Table (Asgn);
+ P : Partial_Assign;
+ begin
+ P := Asgn_Rec.Asgns;
+ pragma Assert (P /= No_Partial_Assign);
+ while P /= No_Partial_Assign loop
+ declare
+ Pa : Partial_Assign_Record
+ renames Partial_Assign_Table.Table (P);
+ Res_Inst : constant Instance := Get_Net_Parent (Pa.Value);
+ begin
+ if Get_Mark_Flag (Res_Inst)
+ and then Get_Id (Res_Inst) = Gates.Id_Mux2
+ then
+ -- A nop is needed iff the value is reused and will be
+ -- inferred (which is only possible for Id_Mux2).
+ Pa.Value := Build_Nop (Ctxt, Pa.Value);
+ else
+ Set_Mark_Flag (Res_Inst, True);
+ end if;
- -- First variables.
+ P := Pa.Next;
+ end;
+ end loop;
+ Asgn := Asgn_Rec.Chain;
+ end;
+ end loop;
+
+ -- Clear mark flag.
Asgn := Phi.First;
while Asgn /= No_Seq_Assign loop
declare
Asgn_Rec : Seq_Assign_Record renames Assign_Table.Table (Asgn);
- Wire_Rec : Wire_Id_Record renames
- Wire_Id_Table.Table (Asgn_Rec.Id);
+ P : Partial_Assign;
begin
- Next_Asgn := Asgn_Rec.Chain;
- Asgn_Rec.Chain := No_Seq_Assign;
+ P := Asgn_Rec.Asgns;
+ pragma Assert (P /= No_Partial_Assign);
+ while P /= No_Partial_Assign loop
+ declare
+ Pa : Partial_Assign_Record
+ renames Partial_Assign_Table.Table (P);
+ Res_Inst : constant Instance := Get_Net_Parent (Pa.Value);
+ begin
+ Set_Mark_Flag (Res_Inst, False);
- if Wire_Rec.Kind = Wire_Variable then
- Pop_And_Merge_Phi_Wire (Ctxt, Asgn_Rec, Stmt);
- else
- if First = No_Seq_Assign then
- First := Asgn;
- else
- Set_Assign_Chain (Last, Asgn);
- end if;
- Last := Asgn;
- end if;
- Asgn := Next_Asgn;
+ P := Pa.Next;
+ end;
+ end loop;
+ Asgn := Asgn_Rec.Chain;
end;
end loop;
- -- Then signals.
- Asgn := First;
+ Asgn := Phi.First;
while Asgn /= No_Seq_Assign loop
declare
Asgn_Rec : Seq_Assign_Record renames Assign_Table.Table (Asgn);
- Wire_Rec : Wire_Id_Record renames
- Wire_Id_Table.Table (Asgn_Rec.Id);
begin
- pragma Assert (Wire_Rec.Kind /= Wire_Variable);
Pop_And_Merge_Phi_Wire (Ctxt, Asgn_Rec, Stmt);
Asgn := Asgn_Rec.Chain;
end;