Description
Issue by whitequark
Monday Dec 17, 2018 at 20:57 GMT
Originally opened as m-labs/nmigen#9
I know @jordens expressed in the past a desire to simplify the boilerplate around .get_fragment
. Also, there is currently both Module.lower
and Module.get_fragment
(aliased to one another), which is confusing and unnecessary. Also#2, Migen has a Module.get_fragment()
and combining Migen modules with nMigen modules gets even more confusing with that.
The design I see for the function currently named .get_fragment()
is as follows:
- There are 2 kinds of synthesizable entities in nMigen: fragments (which are directly synthesizable) and anything that has
.get_fragment(platform)
(which is iterated to a fixed point, i.e. a fragment, when a fragment is required). - Instances, memory ports, etc, are synthesizable. Which class they actually are is an implementation detail that is subject to change. (Instances are currently just fragments, memory ports are significantly more complex due to some mismatch between Yosys and Migen representation of ports, etc).
- There is a
Fragment.get(obj, platform)
function that iterates an object to a fixed point with.get_fragment(platform)
or fails in a nice way.
Modules are in a somewhat weird space here. Modules should be synthesizable so that you can replace:
sm = Module()
# ... operate on sm
m = Module()
m.submodules += sm
with:
class SubCircuit:
def get_fragment(self, platform):
m = Module()
return m.lower(platform)
sm = SubCircuit()
m = Module()
m.submodules += sm
that is without having to do downstream changes after replacing a Module
with a user class. This means that in principle you can directly return a module, like return m
.
But this means two things:
- The actual
get_fragment
call for that module is delayed. The conversion of a module to a fragment is mostly (but not entirely) error-free, so delaying this call means some errors lose context. I think it might be more useful to makeModule.get_fragment
actually never fail, and permitreturn m
. - If a parent module directly calls
get_fragment
on a submodule, it gets aModule
object with the DSL enabled, as opposed to aFragment
object. So it can potentially abuse the DSL that way. This isn't very likely so maybe we should just ignore it.
And finally, there is an important question of what to rename .get_fragment
too. I don't want something like .build
because it is ambiguous and prone to collisions. What about .synthesize
?