diff options
author | Tristan Gingold <tgingold@free.fr> | 2019-11-01 18:18:27 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2019-11-01 18:18:27 +0100 |
commit | cc550c2d630d27166f0b7e9b085926d3b5582f4c (patch) | |
tree | b052fa34e75054acb5f6d8ccce01287be9f1a619 | |
parent | 6aa790b8d8ec7f3afa20fec929acaabb48ed8ca8 (diff) | |
download | ghdl-cc550c2d630d27166f0b7e9b085926d3b5582f4c.tar.gz ghdl-cc550c2d630d27166f0b7e9b085926d3b5582f4c.tar.bz2 ghdl-cc550c2d630d27166f0b7e9b085926d3b5582f4c.zip |
netlists-expands: expand dyn_insert
-rw-r--r-- | src/synth/netlists-expands.adb | 213 | ||||
-rw-r--r-- | src/synth/netlists-gates.ads | 3 |
2 files changed, 174 insertions, 42 deletions
diff --git a/src/synth/netlists-expands.adb b/src/synth/netlists-expands.adb index 018ba8018..8c17e2313 100644 --- a/src/synth/netlists-expands.adb +++ b/src/synth/netlists-expands.adb @@ -25,6 +25,7 @@ with Netlists.Utils; use Netlists.Utils; with Netlists.Butils; use Netlists.Butils; with Netlists.Locations; use Netlists.Locations; with Netlists.Memories; use Netlists.Memories; +with Netlists.Concats; use Netlists.Concats; package body Netlists.Expands is type Memidx_Array_Type is array (Natural range <>) of Instance; @@ -111,6 +112,57 @@ package body Netlists.Expands is Addr := Build2_Concat (Ctxt, Res_Arr); end Extract_Address; + procedure Truncate_Address + (Ctxt : Context_Acc; Addr : in out Net; Nbr_Els : Natural) + is + Addr_Len : Width; + begin + Addr_Len := Uns32 (Clog2 (Uns64 (Nbr_Els))); + if Get_Width (Addr) > Addr_Len then + -- Truncate the address. This is requied so that synth_case doesn't + -- use default value. + Addr := Build_Trunc (Ctxt, Id_Utrunc, Addr, Addr_Len); + end if; + end Truncate_Address; + + procedure Gather_Memidx (Addr_Net : Net; + Memidx_Arr : out Memidx_Array_Type; + Nbr_Els : out Natural) + is + N : Net; + P : Natural; + Ninst : Instance; + Memidx : Instance; + Max : Uns32; + begin + N := Addr_Net; + Nbr_Els := 1; + P := Memidx_Arr'Last; + loop + Ninst := Get_Net_Parent (N); + case Get_Id (Ninst) is + when Id_Memidx => + Memidx := Ninst; + when Id_Addidx => + -- Extract memidx. + Memidx := Get_Net_Parent (Get_Input_Net (Ninst, 1)); + pragma Assert (Get_Id (Memidx) = Id_Memidx); + N := Get_Input_Net (Ninst, 0); + when others => + raise Internal_Error; + end case; + + Memidx_Arr (P) := Memidx; + P := P - 1; + + Max := Get_Param_Uns32 (Memidx, 1); + pragma Assert (Max /= 0); + Nbr_Els := Nbr_Els * Natural (Max + 1); + + exit when Memidx = Ninst; + end loop; + end Gather_Memidx; + procedure Expand_Dyn_Extract (Ctxt : Context_Acc; Inst : Instance) is Val : constant Net := Get_Input_Net (Inst, 0); @@ -123,8 +175,6 @@ package body Netlists.Expands is Memidx_Arr : Memidx_Array_Type (1 .. Ndims); - Addr_Len : Uns32; - Els : Case_Element_Array_Acc; Res : Net; Addr : Net; @@ -132,40 +182,7 @@ package body Netlists.Expands is begin -- 1.1 Fill memidx_arr. -- 2. compute number of cells. - declare - N : Net; - P : Natural; - Ninst : Instance; - Memidx : Instance; - Max : Uns32; - begin - N := Addr_Net; - Nbr_Els := 1; - P := Memidx_Arr'Last; - loop - Ninst := Get_Net_Parent (N); - case Get_Id (Ninst) is - when Id_Memidx => - Memidx := Ninst; - when Id_Addidx => - -- Extract memidx. - Memidx := Get_Net_Parent (Get_Input_Net (Ninst, 1)); - pragma Assert (Get_Id (Memidx) = Id_Memidx); - N := Get_Input_Net (Ninst, 0); - when others => - raise Internal_Error; - end case; - - Memidx_Arr (P) := Memidx; - P := P - 1; - - Max := Get_Param_Uns32 (Memidx, 1); - pragma Assert (Max /= 0); - Nbr_Els := Nbr_Els * Natural (Max + 1); - - exit when Memidx = Ninst; - end loop; - end; + Gather_Memidx (Addr_Net, Memidx_Arr, Nbr_Els); -- 2. build extract gates Els := new Case_Element_Array (1 .. Nbr_Els); @@ -182,12 +199,7 @@ package body Netlists.Expands is -- 3. build mux tree Extract_Address (Ctxt, Addr_Net, Ndims, Addr); - Addr_Len := Uns32 (Clog2 (Uns64 (Nbr_Els))); - if Get_Width (Addr) > Addr_Len then - -- Truncate the address. This is requied so that synth_case doesn't - -- use default value. - Addr := Build_Trunc (Ctxt, Id_Utrunc, Addr, Addr_Len); - end if; + Truncate_Address (Ctxt, Addr, Nbr_Els); Def := No_Net; Synth_Case (Ctxt, Addr, Els.all, Def, Res, Loc); @@ -200,6 +212,120 @@ package body Netlists.Expands is Free_Case_Element_Array (Els); end Expand_Dyn_Extract; + procedure Generate_Decoder + (Ctxt : Context_Acc; Addr : Net; Net_Arr : out Net_Array) + is + W : constant Width := Get_Width (Addr); + V0, V1 : Net; + V : Net; + J : Int32; + Step : Int32; + begin + for I in reverse 0 .. W - 1 loop + V1 := Build_Extract_Bit (Ctxt, Addr, I); + V0 := Build_Monadic (Ctxt, Id_Not, V1); + Step := 2**Natural (I); + if I = W - 1 then + Net_Arr (0) := V0; + Net_Arr (Step) := V1; + else + J := 0; + loop + V := Net_Arr (J); + Net_Arr (J) := Build_Dyadic (Ctxt, Id_And, V, V0); + J := J + Step; + exit when J > Net_Arr'Last; + Net_Arr (J) := Build_Dyadic (Ctxt, Id_And, V, V1); + J := J + Step; + exit when J > Net_Arr'Last; + end loop; + end if; + end loop; + end Generate_Decoder; + + procedure Generate_Muxes (Ctxt : Context_Acc; + Concat : in out Concat_Type; + Mem : Net; + Off : in out Uns32; + Dat : Net; + Memidx_Arr : Memidx_Array_Type; + Arr_Idx : Natural; + Net_Arr : Net_Array; + Sel : in out Int32) + is + Inst : constant Instance := Memidx_Arr (Arr_Idx); + Step : constant Uns32 := Get_Param_Uns32 (Inst, 0); + Max : constant Uns32 := Get_Param_Uns32 (Inst, 1); + V : Net; + begin + for I in 0 .. Max loop + if Arr_Idx < Memidx_Arr'Last then + -- Recurse. + Generate_Muxes (Ctxt, Concat, Mem, Off, Dat, + Memidx_Arr, Arr_Idx + 1, Net_Arr, Sel); + else + V := Build_Extract (Ctxt, Mem, Off, Get_Width (Dat)); + V := Build_Mux2 (Ctxt, Net_Arr (Sel), V, Dat); + Append (Concat, V); + Off := Off + Step; + Sel := Sel + 1; + end if; + end loop; + end Generate_Muxes; + + procedure Expand_Dyn_Insert (Ctxt : Context_Acc; Inst : Instance) + is + Mem : constant Net := Get_Input_Net (Inst, 0); + Dat : constant Net := Get_Input_Net (Inst, 1); + Addr_Net : constant Net := Get_Input_Net (Inst, 2); + -- Loc : constant Location_Type := Get_Location (Inst); + -- W : constant Width := Get_Width (Get_Output (Inst, 0)); + -- 1. compute number of dims, check order. + Ndims : constant Natural := Count_Memidx (Addr_Net); + Nbr_Els : Natural; + + Memidx_Arr : Memidx_Array_Type (1 .. Ndims); + + Net_Arr : Net_Array_Acc; + + Addr : Net; + + Concat : Concat_Type; + Res : Net; + begin + Gather_Memidx (Addr_Net, Memidx_Arr, Nbr_Els); + + -- Generate decoder. + Net_Arr := new Net_Array(0 .. Int32 (Nbr_Els - 1)); + Extract_Address (Ctxt, Addr_Net, Ndims, Addr); + Truncate_Address (Ctxt, Addr, Nbr_Els); + Generate_Decoder (Ctxt, Addr, Net_Arr.all); + + -- Build muxes + declare + Off : Uns32; + Sel : Int32; + begin + Off := Get_Param_Uns32 (Inst, 0); + if Off /= 0 then + Append (Concat, Build_Extract (Ctxt, Mem, 0, Off)); + end if; + Sel := 0; + Generate_Muxes (Ctxt, Concat, Mem, Off, Dat, + Memidx_Arr, 1, Net_Arr.all, Sel); + end; + Build (Ctxt, Concat, Res); + + Free_Net_Array (Net_Arr); + + -- Replace gate. + Redirect_Inputs (Get_Output (Inst, 0), Res); + Disconnect (Get_Input (Inst, 0)); + Disconnect (Get_Input (Inst, 1)); + Disconnect (Get_Input (Inst, 2)); + Remove_Instance (Inst); + end Expand_Dyn_Insert; + procedure Expand_Gates (Ctxt : Context_Acc; M : Module) is Inst : Instance; @@ -211,6 +337,9 @@ package body Netlists.Expands is when Id_Dyn_Extract => Expand_Dyn_Extract (Ctxt, Inst); + when Id_Dyn_Insert => + Expand_Dyn_Insert (Ctxt, Inst); + when others => null; end case; diff --git a/src/synth/netlists-gates.ads b/src/synth/netlists-gates.ads index 69546f479..9458cf796 100644 --- a/src/synth/netlists-gates.ads +++ b/src/synth/netlists-gates.ads @@ -148,6 +148,9 @@ package Netlists.Gates is Id_Dyn_Extract : constant Module_Id := 69; -- Like Insert but for dynamic values. + -- Input0: the memory + -- Input1: the value to insert + -- Input2: the index. -- T := IN0 -- T [IN2+OFF+WD-1:IN2+OFF] := IN1 -- OUT := T |