1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
-- 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
-- Return False iff INST has no outputs (and INST is not Id_Free).
-- Return True iff all outputs of INST are unconnected.
-- Return False otherwise.
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;
-- Move INST on LIST iff INST is unused.
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);
-- But keep the self-instance.
Inst := Get_Next_Instance (Inst);
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
-- Disconnect the input.
Disconnect (Inp);
-- Possibly consider the driver as unconnected if was
-- the last input connected.
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;
|