1 # gaf.netlist - gEDA Netlist Extraction and Generation
2 # Copyright (C) 1998-2010 Ales Hvezda
3 # Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
4 # Copyright (C) 2013-2020 Roland Lutz
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software Foundation,
18 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 ## \file util_repackage.py
21 ## Re-grouping components into packages using a custom refdes function.
24 from gettext
import gettext
as _
25 import gaf
.netlist
.package
27 class Package(gaf
.netlist
.package
.Package
):
28 def __init__(self
, *args
, **kwds
):
29 gaf
.netlist
.package
.Package
.__init
__(self
, *args
, **kwds
)
32 sys
.stderr
.write(_("(re-packaged) package `%s': error: %s\n") % (
34 self
.netlist
.failed
= True
37 sys
.stderr
.write(_("(re-packaged) package `%s': warning: %s\n") % (
40 class PackagePin(gaf
.netlist
.package
.PackagePin
):
41 def __init__(self
, *args
, **kwds
):
42 gaf
.netlist
.package
.PackagePin
.__init
__(self
, *args
, **kwds
)
46 _("(re-packaged) package `%s', pin `%s': error: %s\n") % (
47 self
.package
.refdes
, self
.number
, msg
))
48 self
.package
.netlist
.failed
= True
52 _("(re-packaged) package `%s', pin `%s': warning: %s\n") % (
53 self
.package
.refdes
, self
.number
, msg
))
55 def blueprint_requires_refdes(component
):
56 if component
.is_graphical
or component
.has_netname_attrib \
57 or component
.has_portname_attrib
:
60 for pin
in component
.pins
:
66 ## Re-group components into packages using a custom refdes function.
68 # With the new netlisting code, netlist generation is completely
69 # independent from the backend invocation. Therefore, it is no longer
70 # possible for a backend to override the way \c gnetlist determines
71 # the refdes of a component in order to achieve a different grouping
72 # of components into packages.
74 # This function allows a backend to repeat the grouping stage using a
75 # custom refdes function. It doesn't change the actual netlist but
76 # returns a list of "alternative" package objects which can be used
77 # instead of \c netlist.packages.
79 # \a refdes_func should be a callback function which returns the
80 # desired refdes for a given component instance. In the simplest
81 # case, it would do some kind of transformation on \c
82 # component.blueprint.refdes.
84 def repackage(netlist
, refdes_func
):
88 for component
in netlist
.components
:
89 new_refdes
= refdes_func(component
)
91 if new_refdes
is None:
92 if blueprint_requires_refdes(component
.blueprint
):
93 component
.warning(_("component dropped during re-packaging"))
96 if netlist
.flat_package_namespace
:
99 namespace
= component
.sheet
.instantiating_component
102 package
= pkg_dict
[namespace
, new_refdes
]
104 package
= Package(netlist
, namespace
, new_refdes
)
105 new_packages
.append(package
)
106 pkg_dict
[namespace
, new_refdes
] = package
108 package
.components
.append(component
)
110 for cpin
in component
.cpins
:
112 ppin
= package
.pins_by_number
[cpin
.blueprint
.number
]
114 ppin
= PackagePin(package
, cpin
.blueprint
.number
)
115 package
.pins
.append(ppin
)
116 package
.pins_by_number
[cpin
.blueprint
.number
] = ppin
117 ppin
.cpins
.append(cpin
)
119 for package
in new_packages
:
120 for ppin
in package
.pins
:
122 for cpin
in ppin
.cpins
:
123 if cpin
.local_net
.net
not in nets
:
124 nets
.append(cpin
.local_net
.net
)
127 ppin
.error(_("multiple nets connected to pin "
128 "after re-packaging: %s")
129 % _(" vs. ").join(_("\"%s\"") % net
.name
133 for package
in new_packages
:
134 if package
.namespace
is not None:
135 package
.refdes
= netlist
.refdes_mangle_func(
136 package
.unmangled_refdes
, package
.namespace
)
138 # If refdes mangling is disabled, packages don't have
139 # a sheet attribute, so just use the unmangled refdes.
140 package
.refdes
= package
.unmangled_refdes
142 # compile convenience hash, checking for cross-page name clashes
143 packages_by_refdes
= {}
144 for package
in new_packages
:
145 if package
.refdes
in packages_by_refdes
:
146 other_package
= packages_by_refdes
[package
.refdes
]
147 self
.error(_("refdes conflict across hierarchy after re-packaging: "
148 "refdes `%s' is used by package `%s' on page "
149 "`%s' and by package `%s' on page `%s'") % (
151 other_package
.unmangled_refdes
,
152 netlist
.refdes_mangle_func('', other_package
.namespace
),
153 package
.unmangled_refdes
,
154 netlist
.refdes_mangle_func('', package
.namespace
)))
155 packages_by_refdes
[package
.refdes
] = package