aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/synth/netlists-builders.adb30
-rw-r--r--src/synth/netlists-builders.ads8
-rw-r--r--src/synth/netlists-gates.ads8
-rw-r--r--src/synth/netlists-inference.adb54
4 files changed, 88 insertions, 12 deletions
diff --git a/src/synth/netlists-builders.adb b/src/synth/netlists-builders.adb
index c591c38a8..99080d9ae 100644
--- a/src/synth/netlists-builders.adb
+++ b/src/synth/netlists-builders.adb
@@ -487,7 +487,15 @@ package body Netlists.Builders is
2 => Create_Input ("rst"),
3 => Create_Input ("rst_val"),
4 => Create_Input ("init")),
- Outputs);
+ Outputs);
+
+ Ctxt.M_Mdff := New_User_Module
+ (Ctxt.Design, New_Sname_Artificial (Get_Identifier ("mdff"), No_Sname),
+ Id_Mdff, 3, 1, 0);
+ Set_Ports_Desc (Ctxt.M_Mdff, (0 => Create_Input ("clk", 1),
+ 1 => Create_Input ("d"),
+ 2 => Create_Input ("els")),
+ Outputs);
end Create_Dff_Modules;
procedure Create_Assert_Assume_Cover (Ctxt : Context_Acc)
@@ -1338,6 +1346,26 @@ package body Netlists.Builders is
return O;
end Build_Iadff;
+ function Build_Mdff (Ctxt : Context_Acc;
+ Clk : Net;
+ D : Net;
+ Els : Net) return Net
+ is
+ Wd : constant Width := Get_Width (D);
+ pragma Assert (Get_Width (Clk) = 1);
+ pragma Assert (Get_Width (Els) = Wd);
+ Inst : Instance;
+ O : Net;
+ begin
+ Inst := New_Internal_Instance (Ctxt, Ctxt.M_Mdff);
+ O := Get_Output (Inst, 0);
+ Set_Width (O, Wd);
+ Connect (Get_Input (Inst, 0), Clk);
+ Connect (Get_Input (Inst, 1), D);
+ Connect (Get_Input (Inst, 2), Els);
+ return O;
+ end Build_Mdff;
+
function Build_Extract
(Ctxt : Context_Acc; I : Net; Off, W : Width) return Net
is
diff --git a/src/synth/netlists-builders.ads b/src/synth/netlists-builders.ads
index 36554acad..de2a9da3c 100644
--- a/src/synth/netlists-builders.ads
+++ b/src/synth/netlists-builders.ads
@@ -185,7 +185,12 @@ package Netlists.Builders is
function Build_Iadff (Ctxt : Context_Acc;
Clk : Net;
D : Net; Rst : Net; Rst_Val : Net;
- Init : Net) return Net;
+ Init : Net) return Net;
+
+ function Build_Mdff (Ctxt : Context_Acc;
+ Clk : Net;
+ D : Net;
+ Els : Net) return Net;
private
type Module_Arr is array (Module_Id range <>) of Module;
@@ -217,6 +222,7 @@ private
M_Idff : Module;
M_Adff : Module;
M_Iadff : Module;
+ M_Mdff : Module;
M_Truncate : Module_Arr (Truncate_Module_Id);
M_Extend : Module_Arr (Extend_Module_Id);
M_Reduce : Module_Arr (Reduce_Module_Id);
diff --git a/src/synth/netlists-gates.ads b/src/synth/netlists-gates.ads
index bb5e64204..848c7a10f 100644
--- a/src/synth/netlists-gates.ads
+++ b/src/synth/netlists-gates.ads
@@ -141,6 +141,7 @@ package Netlists.Gates is
-- 2: INIT (initial value)
-- Output: 0: Q
Id_Idff : constant Module_Id := 52;
+
-- A DFF with an asynchronous reset and an initial value.
-- Inputs: 0: CLK
-- 1: D
@@ -150,6 +151,13 @@ package Netlists.Gates is
-- Output: 0: Q
Id_Iadff : constant Module_Id := 53;
+ -- Multi clock dff. ELSE is the output of the next DFF.
+ -- Inputs: 0: CLK
+ -- 1: D
+ -- 2: ELSE
+ -- Output: 0: Q
+ Id_Mdff : constant Module_Id := 54;
+
-- Width change: truncate or extend. Sign is know in order to possibly
-- detect loss of value.
Id_Utrunc : constant Module_Id := 64;
diff --git a/src/synth/netlists-inference.adb b/src/synth/netlists-inference.adb
index 9f82e7207..8786d42eb 100644
--- a/src/synth/netlists-inference.adb
+++ b/src/synth/netlists-inference.adb
@@ -328,6 +328,7 @@ package body Netlists.Inference is
Stmt : Synth.Source.Syn_Src) return Net
is
O : constant Net := Get_Output (Last_Mux, 0);
+ Mux_Loc : constant Location_Type := Get_Location (Last_Mux);
Data : Net;
Res : Net;
Sig : Instance;
@@ -335,6 +336,7 @@ package body Netlists.Inference is
Rst : Net;
Rst_Val : Net;
Enable : Net;
+ Els : Net;
begin
-- Create and return the DFF.
@@ -344,12 +346,31 @@ package body Netlists.Inference is
Sel : constant Input := Get_Mux2_Sel (Last_Mux);
I0 : constant Input := Get_Mux2_I0 (Last_Mux);
I1 : constant Input := Get_Mux2_I1 (Last_Mux);
+ Els_Inst : Instance;
+ Els_Clk : Net;
+ Els_En : Net;
begin
-- There must be no 'else' part for clock expression.
- if not Is_Prev_FF_Value (Get_Driver (I0), Prev_Val, Off) then
- Error_Msg_Synth
- (+Stmt, "synchronous code does not expect else part");
- return Prev_Val;
+ Els := Get_Driver (I0);
+ if Is_Prev_FF_Value (Els, Prev_Val, Off) then
+ -- The loop.
+ Els := No_Net;
+ else
+ Els_Inst := Get_Net_Parent (Els);
+ if Get_Id (Els_Inst) = Id_Mux2 then
+ Extract_Clock (Ctxt, Get_Driver (Get_Mux2_Sel (Els_Inst)),
+ Els_Clk, Els_En);
+ else
+ Els_Clk := No_Net;
+ end if;
+ if Els_Clk = No_Net then
+ Error_Msg_Synth
+ (+Stmt, "clocked logic requires clocked logic on else part");
+ Els := No_Net;
+ else
+ Els := Infere_FF (Ctxt, Prev_Val, Off, Els_Inst,
+ Els_Clk, Els_En, Stmt);
+ end if;
end if;
Disconnect (Sel);
@@ -471,6 +492,8 @@ package body Netlists.Inference is
end loop;
end;
+ Free_Instance (Last_Mux);
+
if Off = 0
and then Can_Infere_RAM (Data, Prev_Val)
then
@@ -493,12 +516,25 @@ package body Netlists.Inference is
-- Create the FF.
if Rst = No_Net then
pragma Assert (Rst_Val = No_Net);
- if Init /= No_Net then
- Res := Build_Idff (Ctxt, Clk, D => Data, Init => Init);
+ if Els = No_Net then
+ if Init /= No_Net then
+ Res := Build_Idff (Ctxt, Clk, D => Data, Init => Init);
+ else
+ Res := Build_Dff (Ctxt, Clk, D => Data);
+ end if;
else
- Res := Build_Dff (Ctxt, Clk, D => Data);
+ if Init /= No_Net then
+ raise Internal_Error;
+ else
+ Res := Build_Mdff (Ctxt, Clk, D => Data, Els => Els);
+ end if;
end if;
else
+ if Els /= No_Net then
+ Error_Msg_Synth
+ (+Stmt, "synchronous code does not expect else part");
+ end if;
+
if Init /= No_Net then
Res := Build_Iadff (Ctxt, Clk, D => Data,
Rst => Rst, Rst_Val => Rst_Val,
@@ -508,9 +544,7 @@ package body Netlists.Inference is
Rst => Rst, Rst_Val => Rst_Val);
end if;
end if;
- Copy_Location (Res, Last_Mux);
-
- Free_Instance (Last_Mux);
+ Set_Location (Res, Mux_Loc);
return Res;
end Infere_FF;