diff options
author | Tristan Gingold <tgingold@free.fr> | 2019-05-22 06:33:58 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2019-05-22 06:43:33 +0200 |
commit | 1f63ad0215f932c3776057e14946e2d3202c5779 (patch) | |
tree | a03caf53f0ee1981ded7c2ee39d25d2093fc8eaa | |
parent | 0611b41484571bb92e8a87b39fdfa4d45fe65d83 (diff) | |
download | ghdl-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.adb | 20 | ||||
-rw-r--r-- | src/synth/netlists-builders.ads | 7 | ||||
-rw-r--r-- | src/synth/netlists-gates.ads | 9 | ||||
-rw-r--r-- | src/synth/synth-expr.adb | 24 | ||||
-rw-r--r-- | src/synth/synth-inference.adb | 9 |
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 |