diff options
author | Tristan Gingold <tgingold@free.fr> | 2019-11-03 07:37:47 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2019-11-03 21:15:07 +0100 |
commit | ce507d676a43233523fbdc1fc631b7a2043ce4e1 (patch) | |
tree | 1a61b0a20f07ca2af7bac610d44f525b65183727 | |
parent | 9d8c3f48d303ebdd9585a183ba46b736194bf0ab (diff) | |
download | ghdl-ce507d676a43233523fbdc1fc631b7a2043ce4e1.tar.gz ghdl-ce507d676a43233523fbdc1fc631b7a2043ce4e1.tar.bz2 ghdl-ce507d676a43233523fbdc1fc631b7a2043ce4e1.zip |
netlists-expands: rewrite generate_muxes.
-rw-r--r-- | src/synth/netlists-expands.adb | 126 |
1 files changed, 102 insertions, 24 deletions
diff --git a/src/synth/netlists-expands.adb b/src/synth/netlists-expands.adb index 365f9ab4a..7e6b1bff4 100644 --- a/src/synth/netlists-expands.adb +++ b/src/synth/netlists-expands.adb @@ -260,27 +260,106 @@ package body Netlists.Expands is Off : in out Uns32; Dat : Net; Memidx_Arr : Memidx_Array_Type; - Arr_Idx : Natural; - Net_Arr : Net_Array; - Sel : in out Int32) + Net_Arr : Net_Array) is - Inst : constant Instance := Memidx_Arr (Arr_Idx); - Step : constant Uns32 := Get_Param_Uns32 (Inst, 0); - Max : constant Uns32 := Get_Param_Uns32 (Inst, 1); + Dat_W : constant Width := Get_Width (Dat); + type Count_Type is record + Step : Uns32; + Max : Uns32; + Val : Uns32; + end record; + type Count_Array is array (Memidx_Arr'Range) of Count_Type; + Count : Count_Array; + V : Net; + Sel : Int32; + Next_Off : Uns32; + Prev_Net : Net; + Step : Uns32; 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)); + -- Initialize count. + for I in Memidx_Arr'Range loop + declare + Inst : constant Instance := Memidx_Arr (I); + begin + Count (I) := (Step => Get_Param_Uns32 (Inst, 0), + Max => Get_Param_Uns32 (Inst, 1), + Val => 0); + end; + end loop; + + Sel := 0; + + Prev_Net := No_Net; + Next_Off := 0; + + if Off /= 0 then + Append (Concat, Build_Extract (Ctxt, Mem, 0, Off)); + Next_Off := Off; + end if; + + loop + if Next_Off > Off then + -- Partial overlap. + -- Append previous net partially, extract from previous net and + -- mem. + -- + -- |<----------- Dat_W ------------>| + -- |<- Step ->| + -- Off Next_Off + -- +----------+----------+----------++ + -- | Prev | + -- +----------+----------+----------+ + -- +----------+----------+----------+----------+ + -- | Mem | + -- +----------+----------+----------+----------+ + -- +----------+----------+----------+ + -- | Dat | + -- +----------+----------+----------+ + Step := Dat_W - (Next_Off - Off); + Append (Concat, Build_Extract (Ctxt, Prev_Net, 0, Step)); + V := Build_Concat2 + (Ctxt, + Build_Extract (Ctxt, Mem, Next_Off, Step), + Build_Extract (Ctxt, Prev_Net, Step, Dat_W - Step)); V := Build_Mux2 (Ctxt, Net_Arr (Sel), V, Dat); - Append (Concat, V); - Off := Off + Step; - Sel := Sel + 1; + Prev_Net := V; + Next_Off := Off + Dat_W; + elsif Next_Off = Off then + -- No overlap, no gap + if Prev_Net /= No_Net then + Append (Concat, Prev_Net); + end if; + V := Build_Extract (Ctxt, Mem, Off, Dat_W); + V := Build_Mux2 (Ctxt, Net_Arr (Sel), V, Dat); + Prev_Net := V; + Next_Off := Off + Dat_W; + else + pragma Assert (Next_Off < Off); + -- Gap. + raise Internal_Error; end if; + + Sel := Sel + 1; + + -- Increase Off. + for I in reverse Memidx_Arr'Range loop + declare + C : Count_Type renames Count (I); + begin + C.Val := C.Val + C.Step; + Off := Off + C.Step; + exit when C.Val <= C.Max * C.Step; + if I = Memidx_Arr'First then + -- End. + Append (Concat, Prev_Net); + Off := Next_Off; + return; + end if; + Count (I).Val := 0; + Off := Count (I - 1).Val; + end; + end loop; end loop; end Generate_Muxes; @@ -290,7 +369,8 @@ package body Netlists.Expands is 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)); + O : constant Net := Get_Output (Inst, 0); + O_W : constant Width := Get_Width (O); -- 1. compute number of dims, check order. Ndims : constant Natural := Count_Memidx (Addr_Net); Nbr_Els : Natural; @@ -315,22 +395,20 @@ package body Netlists.Expands is -- 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)); + Generate_Muxes (Ctxt, Concat, Mem, Off, Dat, Memidx_Arr, Net_Arr.all); + if Off < O_W then + Append (Concat, Build_Extract (Ctxt, Mem, Off, O_W - Off)); end if; - Sel := 0; - Generate_Muxes (Ctxt, Concat, Mem, Off, Dat, - Memidx_Arr, 1, Net_Arr.all, Sel); end; Build (Ctxt, Concat, Res); + pragma Assert (Get_Width (Res) = O_W); Free_Net_Array (Net_Arr); -- Replace gate. - Redirect_Inputs (Get_Output (Inst, 0), Res); + Redirect_Inputs (O, Res); Disconnect (Get_Input (Inst, 0)); Disconnect (Get_Input (Inst, 1)); Disconnect (Get_Input (Inst, 2)); |