aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2019-07-01 18:21:59 +0200
committerTristan Gingold <tgingold@free.fr>2019-07-01 18:21:59 +0200
commit10e0d932d67e90263dfd393be8b3719e26fe6514 (patch)
tree1ed2df92180c602fb428378ef9fadac452f5bc8c
parent5ee88f60d0052fc028cfc55e9182349343260e2f (diff)
downloadghdl-10e0d932d67e90263dfd393be8b3719e26fe6514.tar.gz
ghdl-10e0d932d67e90263dfd393be8b3719e26fe6514.tar.bz2
ghdl-10e0d932d67e90263dfd393be8b3719e26fe6514.zip
synth: add dyn_insert module.
-rw-r--r--src/synth/netlists-builders.adb51
-rw-r--r--src/synth/netlists-builders.ads7
-rw-r--r--src/synth/netlists-disp_vhdl.adb46
-rw-r--r--src/synth/netlists-gates.ads14
-rw-r--r--src/synth/synth-expr.adb18
-rw-r--r--src/synth/synth-expr.ads2
-rw-r--r--src/synth/synth-stmts.adb20
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);