diff options
Diffstat (limited to 'src/synth')
-rw-r--r-- | src/synth/netlists-cleanup.adb | 27 | ||||
-rw-r--r-- | src/synth/netlists-cleanup.ads | 6 | ||||
-rw-r--r-- | src/synth/netlists-disp_verilog.adb | 67 | ||||
-rw-r--r-- | src/synth/netlists-expands.adb | 62 | ||||
-rw-r--r-- | src/synth/netlists-memories.adb | 5 | ||||
-rw-r--r-- | src/synth/synth-flags.ads | 4 | ||||
-rw-r--r-- | src/synth/synth-vhdl_insts.adb | 7 | ||||
-rw-r--r-- | src/synth/synthesis.adb | 4 |
8 files changed, 137 insertions, 45 deletions
diff --git a/src/synth/netlists-cleanup.adb b/src/synth/netlists-cleanup.adb index c2fc603b4..52b3c87e0 100644 --- a/src/synth/netlists-cleanup.adb +++ b/src/synth/netlists-cleanup.adb @@ -385,4 +385,31 @@ package body Netlists.Cleanup is end; end Mark_And_Sweep; + procedure Replace_Null_Inputs (Ctxt : Context_Acc; M : Module) + is + Inst : Instance; + Drv : Net; + Inp : Input; + Null_X : Net; + begin + Null_X := No_Net; + + Inst := Get_First_Instance (M); + while Inst /= No_Instance loop + for I in 1 .. Get_Nbr_Inputs (Inst) loop + Inp := Get_Input (Inst, I - 1); + Drv := Get_Driver (Inp); + if Drv /= No_Net and then Get_Width (Drv) = 0 then + if Null_X = No_Net then + Null_X := Build_Const_X (Ctxt, 0); + end if; + Disconnect (Inp); + Connect (Inp, Null_X); + end if; + end loop; + + Inst := Get_Next_Instance (Inst); + end loop; + end Replace_Null_Inputs; + end Netlists.Cleanup; diff --git a/src/synth/netlists-cleanup.ads b/src/synth/netlists-cleanup.ads index be4f0e0fb..a13e66c47 100644 --- a/src/synth/netlists-cleanup.ads +++ b/src/synth/netlists-cleanup.ads @@ -16,6 +16,8 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see <gnu.org/licenses>. +with Netlists.Builders; use Netlists.Builders; + package Netlists.Cleanup is -- Remove instances of module M whose outputs are not connected. -- Their inputs will be deconnected, which can result in new instances @@ -26,6 +28,10 @@ package Netlists.Cleanup is -- sweep algorithm. procedure Mark_And_Sweep (M : Module); + -- Reconnection inputs of width 0 (the null inputs) to an Const_X gate. + -- This will make all the null logic unconnected and ready to be cleaned. + procedure Replace_Null_Inputs (Ctxt : Context_Acc; M : Module); + -- Remove Id_Output gates. procedure Remove_Output_Gates (M : Module); end Netlists.Cleanup; diff --git a/src/synth/netlists-disp_verilog.adb b/src/synth/netlists-disp_verilog.adb index 848adc05b..cd13a6d77 100644 --- a/src/synth/netlists-disp_verilog.adb +++ b/src/synth/netlists-disp_verilog.adb @@ -31,6 +31,10 @@ package body Netlists.Disp_Verilog is Flag_Merge_Lit : constant Boolean := True; Flag_Merge_Edge : constant Boolean := True; + -- Wires/regs/parameters of size 0 are not possible in verilog. + -- Do not display them. + Flag_Null_Wires : constant Boolean := False; + procedure Put_Type (W : Width) is begin if W > 1 then @@ -158,10 +162,12 @@ package body Netlists.Disp_Verilog is is Imod : constant Module := Get_Module (Inst); Idx : Port_Idx; + Drv : Net; Max_Idx : Port_Idx; Name : Sname; First : Boolean; Param : Param_Desc; + Desc : Port_Desc; begin Put (" "); @@ -217,33 +223,37 @@ package body Netlists.Disp_Verilog is Idx := 0; Max_Idx := Get_Nbr_Inputs (Imod); for I of Inputs (Inst) loop - if First then - First := False; - else - Put_Line (","); - end if; - Put (" "); - if Idx < Max_Idx then - Put ("."); - Put_Interface_Name (Get_Input_Desc (Imod, Idx).Name); - Put ("("); - end if; - Disp_Net_Name (Get_Driver (I)); - if Idx < Max_Idx then - Put (")"); - Idx := Idx + 1; + Drv := Get_Driver (I); + if Flag_Null_Wires or else Get_Width (Drv) /= 0 then + if First then + First := False; + else + Put_Line (","); + end if; + Put (" "); + if Idx < Max_Idx then + Put ("."); + Put_Interface_Name (Get_Input_Desc (Imod, Idx).Name); + Put ("("); + end if; + Disp_Net_Name (Get_Driver (I)); + if Idx < Max_Idx then + Put (")"); + end if; end if; + Idx := Idx + 1; end loop; -- Outputs Idx := 0; for O of Outputs (Inst) loop + Desc := Get_Output_Desc (Imod, Idx); if First then First := False; else Put_Line (","); end if; Put (" ."); - Put_Interface_Name (Get_Output_Desc (Imod, Idx).Name); + Put_Interface_Name (Desc.Name); Idx := Idx + 1; Put ("("); declare @@ -434,9 +444,14 @@ package body Netlists.Disp_Verilog is -- a name. In that case, a signal will be created and driven. function Need_Signal (Inst : Instance) return Boolean is + O : constant Net := Get_Output (Inst, 0); I : Input; begin - I := Get_First_Sink (Get_Output (Inst, 0)); + if not Flag_Null_Wires and then Get_Width (O) = 0 then + return False; + end if; + + I := Get_First_Sink (O); while I /= No_Input loop if Need_Name (Get_Input_Parent (I)) then return True; @@ -1212,14 +1227,18 @@ package body Netlists.Disp_Verilog is -- Output assignments. declare Idx : Port_Idx; + Desc : Port_Desc; begin Idx := 0; for I of Inputs (Self_Inst) loop - Put (" assign "); - Put_Name (Get_Output_Desc (M, Idx).Name); - Put (" = "); - Disp_Net_Name (Get_Driver (I)); - Put_Line (";"); + Desc := Get_Output_Desc (M, Idx); + if Desc.W /= 0 or Flag_Null_Wires then + Put (" assign "); + Put_Name (Desc.Name); + Put (" = "); + Disp_Net_Name (Get_Driver (I)); + Put_Line (";"); + end if; Idx := Idx + 1; end loop; end; @@ -1246,6 +1265,10 @@ package body Netlists.Disp_Verilog is is Attr : Attribute; begin + if not (Desc.W /= 0 or Flag_Null_Wires) then + return; + end if; + if First then Put (" ("); First := False; diff --git a/src/synth/netlists-expands.adb b/src/synth/netlists-expands.adb index efb9fc93f..0f69dd93d 100644 --- a/src/synth/netlists-expands.adb +++ b/src/synth/netlists-expands.adb @@ -46,6 +46,9 @@ package body Netlists.Expands is N := Addr_Net; Nbr_Els := 1; P := Memidx_Arr'Last; + if P = 0 then + return; + end if; loop Ninst := Get_Net_Parent (N); case Get_Id (Ninst) is @@ -213,34 +216,47 @@ package body Netlists.Expands is -- 2. compute number of cells. Gather_Memidx (Addr_Net, Memidx_Arr, Nbr_Els); - -- 2. build extract gates - Els := new Case_Element_Array (1 .. Nbr_Els); - declare - Idx : Positive; - Off : Uns32; - Sel : Uns64; - begin - Idx := 1; - Off := Get_Param_Uns32 (Inst, 0); - Sel := 0; - Fill_Els (Ctxt, Memidx_Arr, 1, Val, Els, Idx, Addr_Net, Off, W, Sel); - end; + if Nbr_Els = 1 then + -- There is only one element, so it's not really dynamic. + -- Just return the value. + Res := Get_Input_Net (Inst, 0); + -- Disconnect the address + Addr := Disconnect_And_Get (Inst, 1); + if not Is_Connected (Addr) then + -- Should be a Const_X. + Remove_Instance (Get_Net_Parent (Addr)); + end if; + else + -- 2. build extract gates + Els := new Case_Element_Array (1 .. Nbr_Els); + declare + Idx : Positive; + Off : Uns32; + Sel : Uns64; + begin + Idx := 1; + Off := Get_Param_Uns32 (Inst, 0); + Sel := 0; + Fill_Els (Ctxt, Memidx_Arr, + 1, Val, Els, Idx, Addr_Net, Off, W, Sel); + end; - -- 3. build mux tree - Disconnect (Get_Input (Inst, 1)); - Extract_Address (Ctxt, Addr_Net, Ndims, Addr); - Truncate_Address (Ctxt, Addr, Nbr_Els); - Def := No_Net; - Synth_Case (Ctxt, Addr, Els.all, Def, Res, Loc); + -- 3. build mux tree + Disconnect (Get_Input (Inst, 1)); + Extract_Address (Ctxt, Addr_Net, Ndims, Addr); + Truncate_Address (Ctxt, Addr, Nbr_Els); + Def := No_Net; + Synth_Case (Ctxt, Addr, Els.all, Def, Res, Loc); + + -- 4. remove old dyn_extract. + Remove_Memidx (Memidx_Arr); + + Free_Case_Element_Array (Els); + end if; - -- 4. remove old dyn_extract. Disconnect (Get_Input (Inst, 0)); Redirect_Inputs (Get_Output (Inst, 0), Res); Remove_Instance (Inst); - - Remove_Memidx (Memidx_Arr); - - Free_Case_Element_Array (Els); end Expand_Dyn_Extract; procedure Generate_Decoder (Ctxt : Context_Acc; diff --git a/src/synth/netlists-memories.adb b/src/synth/netlists-memories.adb index 2764ec380..ffc3316ba 100644 --- a/src/synth/netlists-memories.adb +++ b/src/synth/netlists-memories.adb @@ -243,6 +243,11 @@ package body Netlists.Memories is end if; Res := Res + 1; N := Get_Input_Net (Inst, 0); + when Id_Const_X => + -- For a null wire. + pragma Assert (Res = 0); + pragma Assert (Get_Width (N) = 0); + return 0; when others => raise Internal_Error; end case; diff --git a/src/synth/synth-flags.ads b/src/synth/synth-flags.ads index fed17efc1..211c01c1d 100644 --- a/src/synth/synth-flags.ads +++ b/src/synth/synth-flags.ads @@ -51,8 +51,12 @@ package Synth.Flags is Flag_Debug_Nomemory2 : Boolean := False; + -- Do not expand dynamic gates. Flag_Debug_Noexpand : Boolean := False; + -- Do not transform null net to null X. + Flag_Debug_Nonull : Boolean := False; + Flag_Trace_Statements : Boolean := False; -- Display source of elaborated design. diff --git a/src/synth/synth-vhdl_insts.adb b/src/synth/synth-vhdl_insts.adb index 8d77b06b5..2d3f3360f 100644 --- a/src/synth/synth-vhdl_insts.adb +++ b/src/synth/synth-vhdl_insts.adb @@ -198,6 +198,13 @@ package body Synth.Vhdl_Insts is T := T.Arr_El; end loop; end; + when Type_Record => + for I in Typ.Rec.E'Range loop + Hash_Bounds (C, Typ.Rec.E (I).Typ); + end loop; + when Type_Bit + | Type_Logic => + null; when others => raise Internal_Error; end case; diff --git a/src/synth/synthesis.adb b/src/synth/synthesis.adb index 310a30a59..911b2d5f6 100644 --- a/src/synth/synthesis.adb +++ b/src/synth/synthesis.adb @@ -79,6 +79,10 @@ package body Synthesis is procedure Instance_Passes (Ctxt : Context_Acc; M : Module) is begin + if not Synth.Flags.Flag_Debug_Nonull then + Netlists.Cleanup.Replace_Null_Inputs (Ctxt, M); + end if; + -- Remove unused gates. This is not only an optimization but also -- a correctness point: there might be some unsynthesizable gates, like -- the one created for 'rising_egde (clk) and not rst'. |