diff options
-rw-r--r-- | src/synth/netlists-builders.adb | 38 | ||||
-rw-r--r-- | src/synth/netlists-builders.ads | 4 | ||||
-rw-r--r-- | src/synth/netlists-gates.ads | 10 | ||||
-rw-r--r-- | src/synth/synth-expr.adb | 39 | ||||
-rw-r--r-- | src/synth/synth-expr.ads | 5 | ||||
-rw-r--r-- | src/synth/synth-stmts.adb | 30 |
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; |