aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/netlists-cleanup.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/synth/netlists-cleanup.adb')
-rw-r--r--src/synth/netlists-cleanup.adb107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/synth/netlists-cleanup.adb b/src/synth/netlists-cleanup.adb
new file mode 100644
index 000000000..207a8a63e
--- /dev/null
+++ b/src/synth/netlists-cleanup.adb
@@ -0,0 +1,107 @@
+-- Netlist cleanup.
+-- Copyright (C) 2019 Tristan Gingold
+--
+-- This file is part of GHDL.
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+-- MA 02110-1301, USA.
+
+with Netlists.Utils; use Netlists.Utils;
+
+package body Netlists.Cleanup is
+ function Is_Unused_Instance (Inst : Instance) return Boolean
+ is
+ Nbr_Outputs : constant Port_Idx := Get_Nbr_Outputs (Inst);
+ N : Net;
+ begin
+ -- An instance without outputs is considered as used.
+ if Nbr_Outputs = 0 then
+ return Get_Module (Inst) = Free_Module;
+ end if;
+
+ for Idx in 0 .. Nbr_Outputs - 1 loop
+ N := Get_Output (Inst, Idx);
+ if Is_Connected (N) then
+ -- Connected output.
+ return False;
+ end if;
+ end loop;
+
+ -- All outputs are unconnected.
+ return True;
+ end Is_Unused_Instance;
+
+ procedure Extract_If_Unused (Inst : Instance; List : in out Instance) is
+ begin
+ if Is_Unused_Instance (Inst) then
+ Extract_Instance (Inst);
+ Set_Next_Instance (Inst, List);
+ List := Inst;
+ end if;
+ end Extract_If_Unused;
+
+ -- TODO: use mark & sweep to remove unused assignments ?
+ procedure Remove_Unconnected_Instances (M : Module)
+ is
+ Inst : Instance;
+ Next_Inst : Instance;
+ List : Instance;
+ begin
+ -- Extract from instances of M all unconnected instances. Put them
+ -- in a list.
+ List := No_Instance;
+
+ Inst := Get_First_Instance (M);
+ while Inst /= No_Instance loop
+ Next_Inst := Get_Next_Instance (Inst);
+ Extract_If_Unused (Inst, List);
+ Inst := Next_Inst;
+ end loop;
+
+ -- While the list is not empty:
+ -- extract the first instance of the list.
+ -- unconnect all inputs of the instance, free the instance.
+ -- if unconnected an input resulted in an instance without connected
+ -- output, extract it from M and append it in the list.
+ while List /= No_Instance loop
+ Inst := List;
+ List := Get_Next_Instance (Inst);
+
+ declare
+ Nbr_Inputs : constant Port_Nbr := Get_Nbr_Inputs (Inst);
+ Inp : Input;
+ Drv : Net;
+ Inst2 : Instance;
+ begin
+ if Nbr_Inputs > 0 then
+ for K in 0 .. Nbr_Inputs - 1 loop
+ Inp := Get_Input (Inst, K);
+ Drv := Get_Driver (Inp);
+ if Drv /= No_Net then
+ -- The input was already unconnected.
+ Disconnect (Inp);
+ if Get_First_Sink (Drv) = No_Input then
+ Inst2 := Get_Net_Parent (Drv);
+ Extract_If_Unused (Inst2, List);
+ end if;
+ end if;
+ end loop;
+ end if;
+ end;
+
+ Free_Instance (Inst);
+ end loop;
+ end Remove_Unconnected_Instances;
+end Netlists.Cleanup;