aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2021-01-01 18:05:00 +0100
committerTristan Gingold <tgingold@free.fr>2021-01-01 18:05:00 +0100
commite84f35edb1c36d07a15f8f15873b4990b55d9aaf (patch)
tree6476b548c6bf2311fa2b0a704196341e3ab90c54
parent28a81b3a60952607c03191b8f71e11588047c721 (diff)
downloadghdl-e84f35edb1c36d07a15f8f15873b4990b55d9aaf.tar.gz
ghdl-e84f35edb1c36d07a15f8f15873b4990b55d9aaf.tar.bz2
ghdl-e84f35edb1c36d07a15f8f15873b4990b55d9aaf.zip
netlists-inference: handle multiple dff with the same clock. Fix #1563
-rw-r--r--src/synth/netlists-gates.ads2
-rw-r--r--src/synth/netlists-inference.adb25
-rw-r--r--src/synth/netlists-utils.adb13
-rw-r--r--src/synth/netlists-utils.ads4
4 files changed, 39 insertions, 5 deletions
diff --git a/src/synth/netlists-gates.ads b/src/synth/netlists-gates.ads
index 4acf9f6b4..c20cddf74 100644
--- a/src/synth/netlists-gates.ads
+++ b/src/synth/netlists-gates.ads
@@ -186,6 +186,8 @@ package Netlists.Gates is
-- Output: 0: Q
Id_Iadff : constant Module_Id := 67;
+ subtype Dff_Module_Id is Module_Id range Id_Dff .. Id_Iadff;
+
-- Multi clock dff. ELSE is the output of the next DFF.
-- Inputs: 0: CLK
-- 1: D
diff --git a/src/synth/netlists-inference.adb b/src/synth/netlists-inference.adb
index 58df1b556..fe136008a 100644
--- a/src/synth/netlists-inference.adb
+++ b/src/synth/netlists-inference.adb
@@ -334,14 +334,19 @@ package body Netlists.Inference is
is
Ndata : Net;
Res : Net;
+ Els_Net : Net;
+ Els_Inst : Instance;
begin
+ Els_Net := Els;
+ pragma Unreferenced (Els);
+
if Off = 0
and then Rst = No_Net
and then not Synth.Flags.Flag_Debug_Nomemory1
and then Can_Infere_RAM (Data, Prev_Val)
then
-- Maybe it is a RAM.
- Res := Infere_RAM (Ctxt, Data, Els, Clk, Clk_Enable);
+ Res := Infere_RAM (Ctxt, Data, Els_Net, Clk, Clk_Enable);
else
if Clk_Enable /= No_Net then
-- If there is a condition with the clock, that's an enable which
@@ -363,7 +368,17 @@ package body Netlists.Inference is
if Rst = No_Net then
-- No async reset
pragma Assert (Rst_Val = No_Net);
- if Els = No_Net then
+
+ if Els_Net /= No_Net then
+ Els_Inst := Get_Net_Parent (Els_Net);
+ if Get_Id (Els_Inst) in Dff_Module_Id
+ and then Same_Clock (Clk, Get_Input_Net (Els_Inst, 0))
+ then
+ Els_Net := No_Net;
+ end if;
+ end if;
+
+ if Els_Net = No_Net then
if Init /= No_Net then
Res := Build_Idff (Ctxt, Clk, D => Ndata, Init => Init);
else
@@ -372,13 +387,13 @@ package body Netlists.Inference is
else
if Init /= No_Net then
Res := Build_Midff (Ctxt, Clk, D => Ndata,
- Els => Els, Init => Init);
+ Els => Els_Net, Init => Init);
else
- Res := Build_Mdff (Ctxt, Clk, D => Ndata, Els => Els);
+ Res := Build_Mdff (Ctxt, Clk, D => Ndata, Els => Els_Net);
end if;
end if;
else
- if Els /= No_Net then
+ if Els_Net /= No_Net then
Error_Msg_Synth
(Loc, "synchronous code does not expect else part");
end if;
diff --git a/src/synth/netlists-utils.adb b/src/synth/netlists-utils.adb
index 74df5908c..8463da355 100644
--- a/src/synth/netlists-utils.adb
+++ b/src/synth/netlists-utils.adb
@@ -289,6 +289,19 @@ package body Netlists.Utils is
end;
end Same_Net;
+ function Same_Clock (L, R : Net) return Boolean
+ is
+ Linst : constant Instance := Get_Net_Parent (L);
+ Rinst : constant Instance := Get_Net_Parent (R);
+ begin
+ if Get_Id (Linst) /= Get_Id (Rinst) then
+ return False;
+ end if;
+ pragma Assert (Get_Id (Linst) in Edge_Module_Id);
+ return Same_Net (Get_Input_Net (Linst, 0),
+ Get_Input_Net (Rinst, 0));
+ end Same_Clock;
+
procedure Copy_Attributes (Dest : Instance; Src : Instance)
is
Attr : Attribute;
diff --git a/src/synth/netlists-utils.ads b/src/synth/netlists-utils.ads
index 111c6f9f3..c7a76a502 100644
--- a/src/synth/netlists-utils.ads
+++ b/src/synth/netlists-utils.ads
@@ -90,6 +90,10 @@ package Netlists.Utils is
-- selection of the same net.
function Same_Net (L, R : Net) return Boolean;
+ -- Like Same_Net but for a clock. L and R must be both the output of
+ -- an edge detector.
+ function Same_Clock (L, R : Net) return Boolean;
+
-- If N is the output of a signal or isignal, return the driver of the
-- input.
function Skip_Signal (N : Net) return Net;