diff options
author | Tristan Gingold <tgingold@free.fr> | 2019-07-01 18:21:59 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2019-07-01 18:21:59 +0200 |
commit | 10e0d932d67e90263dfd393be8b3719e26fe6514 (patch) | |
tree | 1ed2df92180c602fb428378ef9fadac452f5bc8c | |
parent | 5ee88f60d0052fc028cfc55e9182349343260e2f (diff) | |
download | ghdl-10e0d932d67e90263dfd393be8b3719e26fe6514.tar.gz ghdl-10e0d932d67e90263dfd393be8b3719e26fe6514.tar.bz2 ghdl-10e0d932d67e90263dfd393be8b3719e26fe6514.zip |
synth: add dyn_insert module.
-rw-r--r-- | src/synth/netlists-builders.adb | 51 | ||||
-rw-r--r-- | src/synth/netlists-builders.ads | 7 | ||||
-rw-r--r-- | src/synth/netlists-disp_vhdl.adb | 46 | ||||
-rw-r--r-- | src/synth/netlists-gates.ads | 14 | ||||
-rw-r--r-- | src/synth/synth-expr.adb | 18 | ||||
-rw-r--r-- | src/synth/synth-expr.ads | 2 | ||||
-rw-r--r-- | src/synth/synth-stmts.adb | 20 |
7 files changed, 130 insertions, 28 deletions
diff --git a/src/synth/netlists-builders.adb b/src/synth/netlists-builders.adb index bc5e4aa68..957ba565c 100644 --- a/src/synth/netlists-builders.adb +++ b/src/synth/netlists-builders.adb @@ -202,6 +202,28 @@ package body Netlists.Builders is Typ => Param_Uns32))); end Create_Insert_Module; + procedure Create_Dyn_Insert_Module (Ctxt : Context_Acc) + is + Outputs : Port_Desc_Array (0 .. 0); + Inputs : Port_Desc_Array (0 .. 2); + Res : Module; + begin + Res := New_User_Module + (Ctxt.Design, New_Sname_Artificial (Get_Identifier ("dyn_insert")), + Id_Dyn_Insert, 3, 1, 2); + Ctxt.M_Dyn_Insert := Res; + Outputs := (0 => Create_Output ("o")); + Inputs := (0 => Create_Input ("i"), + 1 => Create_Input ("v"), + 2 => Create_Input ("p")); + Set_Port_Desc (Res, Inputs, Outputs); + Set_Param_Desc + (Res, (0 => (New_Sname_Artificial (Get_Identifier ("step")), + Typ => Param_Uns32), + 1 => (New_Sname_Artificial (Get_Identifier ("offset")), + Typ => Param_Uns32))); + end Create_Dyn_Insert_Module; + procedure Create_Edge_Module (Ctxt : Context_Acc; Res : out Module; Name : Name_Id) @@ -363,6 +385,7 @@ package body Netlists.Builders is Create_Extract_Module (Res); Create_Dyn_Extract_Module (Res); Create_Insert_Module (Res); + Create_Dyn_Insert_Module (Res); Create_Monadic_Module (Design, Res.M_Truncate (Id_Utrunc), Get_Identifier ("utrunc"), Id_Utrunc); @@ -630,6 +653,27 @@ package body Netlists.Builders is return O; end Build_Insert; + function Build_Dyn_Insert + (Ctxt : Context_Acc; + I : Net; V : Net; P : Net; Step : Uns32; Off : Int32) + return Net + is + Wd : constant Width := Get_Width (I); + pragma Assert (Wd /= No_Width); + Inst : Instance; + O : Net; + begin + Inst := New_Internal_Instance (Ctxt, Ctxt.M_Dyn_Insert); + O := Get_Output (Inst, 0); + Set_Width (O, Wd); + Connect (Get_Input (Inst, 0), I); + Connect (Get_Input (Inst, 1), V); + Connect (Get_Input (Inst, 2), P); + Set_Param_Uns32 (Inst, 0, Step); + Set_Param_Uns32 (Inst, 1, To_Uns32 (Off)); + return O; + end Build_Dyn_Insert; + function Build_Object (Ctxt : Context_Acc; M : Module; W : Width) return Net is Inst : Instance; @@ -775,12 +819,11 @@ package body Netlists.Builders is function Build_Dyn_Extract (Ctxt : Context_Acc; - I : Net; V : Net; Step : Uns32; Off : Uns32; W : Width) return Net + I : Net; P : Net; Step : Uns32; Off : Int32; W : Width) return Net is Wd : constant Width := Get_Width (I); pragma Assert (Wd /= No_Width); pragma Assert (W > 0); - pragma Assert (W + Off <= Wd); Inst : Instance; O : Net; begin @@ -788,9 +831,9 @@ package body Netlists.Builders is O := Get_Output (Inst, 0); Set_Width (O, W); Connect (Get_Input (Inst, 0), I); - Connect (Get_Input (Inst, 1), V); + Connect (Get_Input (Inst, 1), P); Set_Param_Uns32 (Inst, 0, Step); - Set_Param_Uns32 (Inst, 1, Off); + Set_Param_Uns32 (Inst, 1, To_Uns32 (Off)); return O; end Build_Dyn_Extract; diff --git a/src/synth/netlists-builders.ads b/src/synth/netlists-builders.ads index 644e558c4..214484168 100644 --- a/src/synth/netlists-builders.ads +++ b/src/synth/netlists-builders.ads @@ -73,13 +73,15 @@ package Netlists.Builders is (Ctxt : Context_Acc; I : Net; Off, W : Width) return Net; function Build_Extract_Bit (Ctxt : Context_Acc; I : Net; Off : Width) return Net; - function Build_Dyn_Extract (Ctxt : Context_Acc; - I : Net; V : Net; Step : Uns32; Off : Uns32; W : Width) return Net; + I : Net; P : Net; Step : Uns32; Off : Int32; W : Width) return Net; function Build_Insert (Ctxt : Context_Acc; I : Net; V : Net; Off : Width) return Net; + function Build_Dyn_Insert + (Ctxt : Context_Acc; I : Net; V : Net; P : Net; Step : Uns32; Off : Int32) + return Net; function Build_Output (Ctxt : Context_Acc; W : Width) return Net; function Build_Signal (Ctxt : Context_Acc; Name : Sname; W : Width) @@ -131,5 +133,6 @@ private M_Extract : Module; M_Insert : Module; M_Dyn_Extract : Module; + M_Dyn_Insert : Module; end record; end Netlists.Builders; diff --git a/src/synth/netlists-disp_vhdl.adb b/src/synth/netlists-disp_vhdl.adb index 44d8ad848..42916179e 100644 --- a/src/synth/netlists-disp_vhdl.adb +++ b/src/synth/netlists-disp_vhdl.adb @@ -449,6 +449,52 @@ package body Netlists.Disp_Vhdl is Put_Uns32 (Off); Put_Line (");"); end; + when Id_Insert => + declare + O : constant Net := Get_Output (Inst, 0); + Ow : constant Width := Get_Width (O); + Iw : constant Width := Get_Width (Get_Input_Net (Inst, 1)); + Off : constant Uns32 := Get_Param_Uns32 (Inst, 0); + begin + Disp_Template + (" process (\i0, \i1)" & NL & + " begin" & NL & + " \o0 <= \i0;" & NL, + Inst, (0 => Ow - 1)); + if Iw > 1 then + Disp_Template (" \o0 (\n0 downto \n1)", Inst, + (0 => Off + Iw - 1, 1 => Off)); + else + Disp_Template (" \o0 (\n0)", Inst, (0 => Off)); + end if; + Disp_Template + (" <= \i1;" & NL & + " end process;" & NL, Inst); + end; + when Id_Dyn_Insert => + declare + -- I0: Input, I1: Value, I2: position + -- P0: Step, P1: offset + O : constant Net := Get_Output (Inst, 0); + Ow : constant Width := Get_Width (O); + Iw : constant Width := Get_Width (Get_Input_Net (Inst, 1)); + Off : constant Uns32 := Get_Param_Uns32 (Inst, 0); + begin + Disp_Template + (" process (\i0, \i1)" & NL & + " begin" & NL & + " \o0 <= \i0;" & NL, + Inst, (0 => Ow - 1)); + if Iw > 1 then + Disp_Template (" \o0 (\n0 downto \n1)", Inst, + (0 => Off + Iw - 1, 1 => Off)); + else + Disp_Template (" \o0 (\n0)", Inst, (0 => Off)); + end if; + Disp_Template + (" <= \i1;" & NL & + " end process;" & NL, Inst); + end; when Id_Const_UB32 => declare O : constant Net := Get_Output (Inst, 0); diff --git a/src/synth/netlists-gates.ads b/src/synth/netlists-gates.ads index 60955221c..120088760 100644 --- a/src/synth/netlists-gates.ads +++ b/src/synth/netlists-gates.ads @@ -117,13 +117,19 @@ package Netlists.Gates is -- OUT := IN0[IN1*STEP+OFF+WD-1:IN1*STEP+OFF] Id_Dyn_Extract : constant Module_Id := 47; - -- This gate has two inputs A, B and one parameter POS. - -- It replaces bits POS + width(B) - 1 .. POS of A by B, ie: - -- T := A; - -- T (POS + width(B) - 1 .. POS) := B + -- This gate has two inputs I, V and one parameter POS. + -- It replaces bits POS + width(V) - 1 .. POS of I by V, ie: + -- T := I; + -- T [POS+width(V)-1:POS] := V -- OUT := T. Id_Insert : constant Module_Id := 48; + -- Like Insert but for dynamic values. + -- T := IN0 + -- T [IN2*STEP+OFF+WD-1:IN2*STEP+OFF] := IN1 + -- OUT := T + Id_Dyn_Insert : constant Module_Id := 49; + -- Positive/rising edge detector. This is a pseudo gate. -- A negative edge detector can be made using by negating the clock before -- the detector. diff --git a/src/synth/synth-expr.adb b/src/synth/synth-expr.adb index 0c7b636b4..4dfa7225e 100644 --- a/src/synth/synth-expr.adb +++ b/src/synth/synth-expr.adb @@ -1021,7 +1021,7 @@ package body Synth.Expr is Right : Net; Inp : out Net; Step : out Uns32; - Off : out Uns32; + Off : out Int32; Width : out Uns32) is L_Inp, R_Inp : Net; @@ -1047,7 +1047,7 @@ package body Synth.Expr is if L_Inp /= R_Inp then Error_Msg_Synth - (+Loc, "cannot extract same variable factor for dynamic slice"); + (+Loc, "cannot extract same variable part for dynamic slice"); return; end if; Inp := L_Inp; @@ -1062,10 +1062,10 @@ package body Synth.Expr is case Pfx_Bnd.Dir is when Iir_To => - Off := Uns32 (L_Add - Pfx_Bnd.Left); + Off := L_Add - Pfx_Bnd.Left; Width := Uns32 (R_Add - L_Add + 1); when Iir_Downto => - Off := Uns32 (R_Add - Pfx_Bnd.Right); + Off := R_Add - Pfx_Bnd.Right; Width := Uns32 (L_Add - R_Add + 1); end case; end Synth_Extract_Dyn_Suffix; @@ -1076,7 +1076,7 @@ package body Synth.Expr is Res_Bnd : out Value_Bound_Acc; Inp : out Net; Step : out Uns32; - Off : out Uns32; + Off : out Int32; Wd : out Uns32) is Expr : constant Node := Get_Suffix (Name); @@ -1133,7 +1133,7 @@ package body Synth.Expr is Len => Wd, Left => Int32 (Left.Scal), Right => Int32 (Right.Scal))); - Off := Uns32 (Pfx_Bnd.Right - Res_Bnd.Right); + Off := Pfx_Bnd.Right - Res_Bnd.Right; when Iir_Downto => Wd := Width (Left.Scal - Right.Scal + 1); Res_Bnd := Create_Value_Bound @@ -1141,7 +1141,7 @@ package body Synth.Expr is Len => Wd, Left => Int32 (Left.Scal), Right => Int32 (Right.Scal))); - Off := Uns32 (Res_Bnd.Right - Pfx_Bnd.Right); + Off := Res_Bnd.Right - Pfx_Bnd.Right; end case; end if; end Synth_Slice_Suffix; @@ -1155,7 +1155,7 @@ package body Synth.Expr is Res_Bnd : Value_Bound_Acc; Inp : Net; Step : Uns32; - Off : Uns32; + Off : Int32; Wd : Uns32; begin Bnd := Extract_Bound (Pfx); @@ -1170,7 +1170,7 @@ package body Synth.Expr is return Create_Value_Net (Build_Extract (Build_Context, Get_Net (Pfx, Get_Type (Pfx_Node)), - Off, Wd), + Uns32 (Off), Wd), Res_Bnd); end if; end Synth_Slice_Name; diff --git a/src/synth/synth-expr.ads b/src/synth/synth-expr.ads index 84c7e6860..f41eb626d 100644 --- a/src/synth/synth-expr.ads +++ b/src/synth/synth-expr.ads @@ -62,6 +62,6 @@ package Synth.Expr is Res_Bnd : out Value_Bound_Acc; Inp : out Net; Step : out Uns32; - Off : out Uns32; + Off : out Int32; Wd : out Uns32); end Synth.Expr; diff --git a/src/synth/synth-stmts.adb b/src/synth/synth-stmts.adb index f0240836a..c83c44b56 100644 --- a/src/synth/synth-stmts.adb +++ b/src/synth/synth-stmts.adb @@ -154,12 +154,14 @@ package body Synth.Stmts is Pfx : constant Node := Get_Prefix (Target); Targ : constant Value_Acc := Get_Value (Syn_Inst, Get_Base_Name (Pfx)); - V : Net; Res_Bnd : Value_Bound_Acc; Inp : Net; Step : Uns32; - Off : Uns32; + Off : Int32; Wd : Uns32; + I : Net; + V : Net; + Res : Net; begin if Targ.Kind /= Value_Wire then -- Only support assignment of vector. @@ -167,14 +169,16 @@ package body Synth.Stmts is end if; Synth_Slice_Suffix (Syn_Inst, Target, Extract_Bound (Targ), Res_Bnd, Inp, Step, Off, Wd); - if Step /= 0 then - raise Internal_Error; + I := Get_Net (Targ, Get_Type (Pfx)); + V := Get_Net (Val, Get_Type (Target)); + if Inp /= No_Net then + Res := Build_Dyn_Insert + (Build_Context, I, V, Inp, Step, Off); + else + Res := Build_Insert (Build_Context, I, V, Uns32 (Off)); end if; - V := Build_Insert (Build_Context, - Get_Net (Targ, Get_Type (Pfx)), - Get_Net (Val, Get_Type (Target)), Off); Synth_Assign - (Targ, Create_Value_Net (V, Res_Bnd), Get_Type (Pfx)); + (Targ, Create_Value_Net (Res, Res_Bnd), Get_Type (Pfx)); end; when others => Error_Kind ("synth_assignment", Target); |