aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/synth/netlists-builders.adb38
-rw-r--r--src/synth/netlists-builders.ads4
-rw-r--r--src/synth/netlists-gates.ads10
-rw-r--r--src/synth/synth-expr.adb39
-rw-r--r--src/synth/synth-expr.ads5
-rw-r--r--src/synth/synth-stmts.adb30
6 files changed, 110 insertions, 16 deletions
diff --git a/src/synth/netlists-builders.adb b/src/synth/netlists-builders.adb
index 4309974fa..054699233 100644
--- a/src/synth/netlists-builders.adb
+++ b/src/synth/netlists-builders.adb
@@ -161,6 +161,25 @@ package body Netlists.Builders is
Typ => Param_Uns32)));
end Create_Extract_Module;
+ procedure Create_Insert_Module (Ctxt : Context_Acc)
+ is
+ Outputs : Port_Desc_Array (0 .. 0);
+ Inputs : Port_Desc_Array (0 .. 1);
+ Res : Module;
+ begin
+ Res := New_User_Module
+ (Ctxt.Design, New_Sname_Artificial (Get_Identifier ("insert")),
+ Id_Extract, 2, 1, 1);
+ Ctxt.M_Insert := Res;
+ Outputs := (0 => Create_Output ("o"));
+ Inputs := (0 => Create_Input ("i"),
+ 1 => Create_Input ("v"));
+ Set_Port_Desc (Res, Inputs, Outputs);
+ Set_Param_Desc
+ (Res, (0 => (New_Sname_Artificial (Get_Identifier ("index")),
+ Typ => Param_Uns32)));
+ end Create_Insert_Module;
+
procedure Create_Edge_Module (Ctxt : Context_Acc;
Res : out Module;
Name : Name_Id)
@@ -318,6 +337,7 @@ package body Netlists.Builders is
Create_Const_Modules (Res);
Create_Extract_Module (Res);
+ Create_Insert_Module (Res);
Create_Monadic_Module (Design, Res.M_Truncate (Id_Utrunc),
Get_Identifier ("utrunc"), Id_Utrunc);
@@ -564,6 +584,24 @@ package body Netlists.Builders is
return O;
end Build_Extend;
+ function Build_Insert
+ (Ctxt : Context_Acc; I : Net; V : Net; Off : Width) return Net
+ is
+ Wd : constant Width := Get_Width (I);
+ pragma Assert (Off < Wd);
+ pragma Assert (Get_Width (V) + Off <= Wd);
+ Inst : Instance;
+ O : Net;
+ begin
+ Inst := New_Internal_Instance (Ctxt, Ctxt.M_Insert);
+ Connect (Get_Input (Inst, 0), I);
+ Connect (Get_Input (Inst, 1), V);
+ Set_Param_Uns32 (Inst, 0, Off);
+ O := Get_Output (Inst, 0);
+ Set_Width (O, Wd);
+ return O;
+ end Build_Insert;
+
function Build_Object (Ctxt : Context_Acc; M : Module; W : Width) return Net
is
Inst : Instance;
diff --git a/src/synth/netlists-builders.ads b/src/synth/netlists-builders.ads
index 122d1b862..a4f635b77 100644
--- a/src/synth/netlists-builders.ads
+++ b/src/synth/netlists-builders.ads
@@ -74,6 +74,9 @@ package Netlists.Builders is
function Build_Extract_Bit
(Ctxt : Context_Acc; I : Net; Off : Width) return Net;
+ function Build_Insert
+ (Ctxt : Context_Acc; I : Net; V : Net; Off : Width) return Net;
+
function Build_Output (Ctxt : Context_Acc; W : Width) return Net;
function Build_Signal (Ctxt : Context_Acc; Name : Sname; W : Width)
return Net;
@@ -122,5 +125,6 @@ private
M_Truncate : Module_Arr (Truncate_Module_Id);
M_Extend : Module_Arr (Extend_Module_Id);
M_Extract : Module;
+ M_Insert : Module;
end record;
end Netlists.Builders;
diff --git a/src/synth/netlists-gates.ads b/src/synth/netlists-gates.ads
index 84b8db756..20df29ad2 100644
--- a/src/synth/netlists-gates.ads
+++ b/src/synth/netlists-gates.ads
@@ -103,6 +103,16 @@ package Netlists.Gates is
-- Extract a bit or a slice at a constant offset.
Id_Extract : constant Module_Id := 44;
+ Id_Dyn_Extract : constant Module_Id := 45;
+ Id_Step_Extract : constant Module_Id := 46;
+
+ -- 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
+ -- OUT := T.
+ Id_Insert : constant Module_Id := 47;
+
-- 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 7dd97588c..78285cc09 100644
--- a/src/synth/synth-expr.adb
+++ b/src/synth/synth-expr.adb
@@ -863,6 +863,26 @@ package body Synth.Expr is
end case;
end In_Bounds;
+ function Index_To_Offset (Pfx : Value_Acc; Idx : Int64; Loc : Node)
+ return Uns32
+ is
+ Rng : Value_Bound_Acc;
+ begin
+ Rng := Extract_Bound (Pfx);
+ if not In_Bounds (Rng, Int32 (Idx)) then
+ Error_Msg_Synth (+Loc, "index not within bounds");
+ return 0;
+ end if;
+
+ -- The offset is from the LSB (bit 0). Bit 0 is the rightmost one.
+ case Rng.Dir is
+ when Iir_To =>
+ return Uns32 (Rng.Right - Int32 (Idx));
+ when Iir_Downto =>
+ return Uns32 (Int32 (Idx) - Rng.Right);
+ end case;
+ end Index_To_Offset;
+
function Synth_Indexed_Name (Syn_Inst : Synth_Instance_Acc; Name : Node)
return Value_Acc
is
@@ -871,8 +891,7 @@ package body Synth.Expr is
Indexes : constant Iir_Flist := Get_Index_List (Name);
Idx_Val : constant Value_Acc :=
Synth_Expression (Syn_Inst, Get_Nth_Element (Indexes, 0));
- Rng : Value_Bound_Acc;
- Off : Int32;
+ Off : Uns32;
begin
if Get_Nbr_Elements (Indexes) /= 1 then
Error_Msg_Synth (+Name, "multi-dim arrays not supported");
@@ -884,20 +903,8 @@ package body Synth.Expr is
return null;
end if;
- Rng := Extract_Bound (Pfx);
- if not In_Bounds (Rng, Int32 (Idx_Val.Scal)) then
- Error_Msg_Synth (+Name, "index not within bounds");
- return null;
- end if;
-
- -- The offset is from the LSB (bit 0). Bit 0 is the rightmost one.
- case Rng.Dir is
- when Iir_To =>
- Off := Rng.Right - Int32 (Idx_Val.Scal);
- when Iir_Downto =>
- Off := Int32 (Idx_Val.Scal) - Rng.Right;
- end case;
- return Bit_Extract (Pfx, Uns32 (Off));
+ Off := Index_To_Offset (Pfx, Idx_Val.Scal, Name);
+ return Bit_Extract (Pfx, Off);
end Synth_Indexed_Name;
function Synth_Slice_Name (Syn_Inst : Synth_Instance_Acc; Name : Node)
diff --git a/src/synth/synth-expr.ads b/src/synth/synth-expr.ads
index 0061767a0..1f4cf3ee2 100644
--- a/src/synth/synth-expr.ads
+++ b/src/synth/synth-expr.ads
@@ -50,4 +50,9 @@ package Synth.Expr is
function Synth_Range_Expression
(Syn_Inst : Synth_Instance_Acc; Rng : Node) return Value_Acc;
+
+ -- Convert index IDX in PFX to an offset. LOC is used in case of error.
+ function Index_To_Offset (Pfx : Value_Acc; Idx : Int64; Loc : Node)
+ return Uns32;
+
end Synth.Expr;
diff --git a/src/synth/synth-stmts.adb b/src/synth/synth-stmts.adb
index 17be7396a..92384c42c 100644
--- a/src/synth/synth-stmts.adb
+++ b/src/synth/synth-stmts.adb
@@ -119,6 +119,36 @@ package body Synth.Stmts is
Val, Get_Type (Target));
when Iir_Kind_Aggregate =>
Synth_Assignment_Aggregate (Syn_Inst, Target, Val);
+ when Iir_Kind_Indexed_Name =>
+ declare
+ Pfx : constant Node := Get_Prefix (Target);
+ Targ : constant Value_Acc :=
+ Get_Value (Syn_Inst, Get_Base_Name (Pfx));
+ Indexes : constant Node_Flist := Get_Index_List (Target);
+ N_Idx : Node;
+ Idx : Value_Acc;
+ V : Net;
+ begin
+ if Get_Nbr_Elements (Indexes) /= 1
+ or else Targ.Kind /= Value_Wire
+ then
+ -- Only support assignment of vector.
+ raise Internal_Error;
+ end if;
+ N_Idx := Get_Nth_Element (Indexes, 0);
+ Idx := Synth_Expression_With_Type
+ (Syn_Inst, N_Idx, Get_Type (N_Idx));
+ if Is_Const (Idx) then
+ -- FIXME: check index.
+ V := Build_Insert (Build_Context,
+ Get_Net (Targ, Get_Type (Pfx)),
+ Get_Net (Val, Get_Type (Target)),
+ Index_To_Offset (Targ, Idx.Scal, Target));
+ else
+ raise Internal_Error;
+ end if;
+ Synth_Assign (Targ, Create_Value_Net (V, null), Get_Type (Pfx));
+ end;
when others =>
Error_Kind ("synth_assignment", Target);
end case;