aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2019-05-22 06:33:58 +0200
committerTristan Gingold <tgingold@free.fr>2019-05-22 06:43:33 +0200
commit1f63ad0215f932c3776057e14946e2d3202c5779 (patch)
treea03caf53f0ee1981ded7c2ee39d25d2093fc8eaa
parent0611b41484571bb92e8a87b39fdfa4d45fe65d83 (diff)
downloadghdl-1f63ad0215f932c3776057e14946e2d3202c5779.tar.gz
ghdl-1f63ad0215f932c3776057e14946e2d3202c5779.tar.bz2
ghdl-1f63ad0215f932c3776057e14946e2d3202c5779.zip
synth: use only one edge gate, make it fully abstract. Handle falling_edge.
-rw-r--r--src/synth/netlists-builders.adb20
-rw-r--r--src/synth/netlists-builders.ads7
-rw-r--r--src/synth/netlists-gates.ads9
-rw-r--r--src/synth/synth-expr.adb24
-rw-r--r--src/synth/synth-inference.adb9
5 files changed, 34 insertions, 35 deletions
diff --git a/src/synth/netlists-builders.adb b/src/synth/netlists-builders.adb
index d131db121..8b239573f 100644
--- a/src/synth/netlists-builders.adb
+++ b/src/synth/netlists-builders.adb
@@ -163,15 +163,14 @@ package body Netlists.Builders is
procedure Create_Edge_Module (Ctxt : Context_Acc;
Res : out Module;
- Name : Name_Id;
- Id : Module_Id)
+ Name : Name_Id)
is
Outputs : Port_Desc_Array (0 .. 0);
Inputs : Port_Desc_Array (0 .. 0);
begin
Res := New_User_Module
- (Ctxt.Design, New_Sname_Artificial (Name), Id, 1, 1, 0);
+ (Ctxt.Design, New_Sname_Artificial (Name), Id_Edge, 1, 1, 0);
Inputs := (0 => Create_Input ("i", 1));
Outputs := (0 => Create_Output ("o", 1));
Set_Port_Desc (Res, Inputs, Outputs);
@@ -325,8 +324,7 @@ package body Netlists.Builders is
Create_Monadic_Module (Design, Res.M_Extend (Id_Sextend),
Get_Identifier ("sextend"), Id_Sextend);
- Create_Edge_Module (Res, Res.M_Posedge, Name_Posedge, Id_Posedge);
- Create_Edge_Module (Res, Res.M_Negedge, Name_Negedge, Id_Negedge);
+ Create_Edge_Module (Res, Res.M_Edge, Name_Posedge);
Create_Mux_Modules (Res);
Create_Objects_Module (Res);
@@ -432,21 +430,13 @@ package body Netlists.Builders is
return O;
end Build_Const_UL32;
- function Build_Edge (Ctxt : Context_Acc;
- Is_Pos : Boolean;
- Src : Net) return Net
+ function Build_Edge (Ctxt : Context_Acc; Src : Net) return Net
is
pragma Assert (Get_Width (Src) = 1);
- M : Module;
Inst : Instance;
O : Net;
begin
- if Is_Pos then
- M := Ctxt.M_Posedge;
- else
- M := Ctxt.M_Negedge;
- end if;
- Inst := New_Internal_Instance (Ctxt, M);
+ Inst := New_Internal_Instance (Ctxt, Ctxt.M_Edge);
O := Get_Output (Inst, 0);
pragma Assert (Get_Width (O) = 1);
Connect (Get_Input (Inst, 0), Src);
diff --git a/src/synth/netlists-builders.ads b/src/synth/netlists-builders.ads
index b439a5351..122d1b862 100644
--- a/src/synth/netlists-builders.ads
+++ b/src/synth/netlists-builders.ads
@@ -50,9 +50,7 @@ package Netlists.Builders is
Xz : Uns32;
W : Width) return Net;
- function Build_Edge (Ctxt : Context_Acc;
- Is_Pos : Boolean;
- Src : Net) return Net;
+ function Build_Edge (Ctxt : Context_Acc; Src : Net) return Net;
function Build_Mux2 (Ctxt : Context_Acc;
Sel : Net;
@@ -111,8 +109,7 @@ private
M_Concat : Module_Arr (Concat_Module_Id);
M_Const_UB32 : Module;
M_Const_UL32 : Module;
- M_Posedge : Module;
- M_Negedge : Module;
+ M_Edge : Module;
M_Mux2 : Module;
M_Mux4 : Module;
M_Output : Module;
diff --git a/src/synth/netlists-gates.ads b/src/synth/netlists-gates.ads
index 2e1dd0e75..84b8db756 100644
--- a/src/synth/netlists-gates.ads
+++ b/src/synth/netlists-gates.ads
@@ -103,11 +103,10 @@ package Netlists.Gates is
-- Extract a bit or a slice at a constant offset.
Id_Extract : constant Module_Id := 44;
- -- Edge detectors. These are pseudo gates.
- Id_Posedge : constant Module_Id := 50;
- Id_Negedge : constant Module_Id := 51;
-
- subtype Edge_Module_Id is Module_Id range Id_Posedge .. Id_Negedge;
+ -- Positive/rising edge detector. This is a pseudo gate.
+ -- A negative edge detector can be made using by negating the clock before
+ -- the detector.
+ Id_Edge : constant Module_Id := 50;
-- Constants are gates with only one constant output. There are multiple
-- kind of constant gates: for small width, the value is stored as a
diff --git a/src/synth/synth-expr.adb b/src/synth/synth-expr.adb
index 0384aa785..51e187f4f 100644
--- a/src/synth/synth-expr.adb
+++ b/src/synth/synth-expr.adb
@@ -680,19 +680,19 @@ package body Synth.Expr is
Clk := Get_Net (Synth_Name (Syn_Inst, Prefix));
if Get_Kind (Expr) /= Iir_Kind_Equality_Operator then
Error_Msg_Synth (+Expr, "ill-formed clock-level, '=' expected");
- return Build_Edge (Build_Context, True, Clk);
+ return Build_Edge (Build_Context, Clk);
end if;
Imp := Get_Implementation (Expr);
if Get_Implicit_Definition (Imp) /= Iir_Predefined_Enum_Equality then
Error_Msg_Synth (+Expr, "ill-formed clock-level, '=' expected");
- return Build_Edge (Build_Context, True, Clk);
+ return Build_Edge (Build_Context, Clk);
end if;
Left := Get_Left (Expr);
Right := Get_Right (Expr);
if Get_Kind (Right) /= Iir_Kind_Character_Literal then
Error_Msg_Synth
(+Expr, "ill-formed clock-level, '0' or '1' expected");
- return Build_Edge (Build_Context, True, Clk);
+ return Build_Edge (Build_Context, Clk);
end if;
Lit := Get_Named_Entity (Right);
if Lit = Vhdl.Std_Package.Bit_0
@@ -712,7 +712,10 @@ package body Synth.Expr is
Error_Msg_Synth
(+Left, "clock signal name doesn't match");
end if;
- return Build_Edge (Build_Context, Posedge, Clk);
+ if not Posedge then
+ Clk := Build_Monadic (Build_Context, Id_Not, Clk);
+ end if;
+ return Build_Edge (Build_Context, Clk);
end Extract_Clock_Level;
function Synth_Clock_Edge (Syn_Inst : Synth_Instance_Acc; Expr : Iir)
@@ -850,13 +853,21 @@ package body Synth.Expr is
declare
Imp : constant Iir := Get_Implementation (Expr);
Clk : Net;
+ Edge : Net;
begin
if Imp = Vhdl.Ieee.Std_Logic_1164.Rising_Edge then
Clk := Get_Net
(Synth_Assoc_In
(Syn_Inst, Get_Parameter_Association_Chain (Expr)));
- return Create_Value_Net
- (Build_Edge (Build_Context, True, Clk), No_Range);
+ Edge := Build_Edge (Build_Context, Clk);
+ return Create_Value_Net (Edge, No_Range);
+ elsif Imp = Vhdl.Ieee.Std_Logic_1164.Falling_Edge then
+ Clk := Get_Net
+ (Synth_Assoc_In
+ (Syn_Inst, Get_Parameter_Association_Chain (Expr)));
+ Clk := Build_Monadic (Build_Context, Id_Not, Clk);
+ Edge := Build_Edge (Build_Context, Clk);
+ return Create_Value_Net (Edge, No_Range);
end if;
Error_Msg_Synth
(+Expr, "user function call to %i is not handled", +Imp);
@@ -866,6 +877,7 @@ package body Synth.Expr is
when others =>
Error_Kind ("synth_expression", Expr);
end case;
+ raise Fatal_Error;
return null;
end Synth_Expression_With_Type;
diff --git a/src/synth/synth-inference.adb b/src/synth/synth-inference.adb
index bdf5d3dd7..8df96d677 100644
--- a/src/synth/synth-inference.adb
+++ b/src/synth/synth-inference.adb
@@ -76,7 +76,7 @@ package body Synth.Inference is
Inst : constant Instance := Get_Net_Parent (N);
begin
case Get_Id (Inst) is
- when Edge_Module_Id =>
+ when Id_Edge =>
return True;
when Id_And =>
-- Assume the condition is canonicalized, ie of the form:
@@ -152,8 +152,9 @@ package body Synth.Inference is
Enable := No_Net;
case Get_Id (Inst) is
- when Edge_Module_Id =>
- Clk := N;
+ when Id_Edge =>
+ -- Get rid of the edge gate, just return the signal.
+ Clk := Get_Driver (Get_Input (Inst, 0));
when Id_And =>
-- Assume the condition is canonicalized, ie of the form:
-- CLK and EXPR.
@@ -164,7 +165,7 @@ package body Synth.Inference is
Drv : Net;
begin
Drv := Get_Driver (I0);
- if Get_Id (Get_Net_Parent (Drv)) in Edge_Module_Id then
+ if Get_Id (Get_Net_Parent (Drv)) = Id_Edge then
-- INST is clearly not synthesizable (boolean operation on
-- an edge). Will be removed at the end by
-- remove_unused_instances. Do not remove it now as its