PyRTL's Jupyter Notebook support is quite messy, see _currently_in_jupyter_notebook() and its callsites. There are several problems:
_currently_in_jupyter_notebook() does not work reliably across different notebook implementations.
- It is confusing that PyRTL functions like
render_trace() behave differently depending on whether they're running in a notebook environment or not, and even more confusing when we can't reliably detect notebook environments.
- PyRTL modules often mix data and how that data is presented. See
Block.__str__() for example. This approach tends to spray UI code across core PyRTL modules, for example every __str__() method would end up with tons of if statements to support all presentation styles.
To clean this up:
- Refactor PyRTL's core modules so they only return data, so the user can do whatever they want with that data (pass it to another library, throw it in a Protocol Buffer, etc).
- All presentation and formatting code should move into separate modules built on top of these core-data modules.
- Most of these presentation-and-formatting modules should not be top-level components in the
pyrtl module.
- Users should invoke these formatting modules explicitly, for predictable behavior.
- Avoid magic code that guesses what the user wants to see. Magic code inevitably does the wrong thing for someone at at some point. Magic code is a maintenance burden because it usually can't be fixed, only slightly improved by piling on more heuristics.
Edit: Tim and I discussed this a bit more offline. Two more notes:
- Users shouldn't have to repeat themselves, so they shouldn't need keep reminding us about how they want their output styled, for example. NumPy's
np.setprintoptions seems like a good example of designing with this principle in mind.
- Some PyRTL functions like
render_trace can produce a lot of output. These functions must support writing the output to a file, without buffering the entire output in memory.
PyRTL's Jupyter Notebook support is quite messy, see
_currently_in_jupyter_notebook()and its callsites. There are several problems:_currently_in_jupyter_notebook()does not work reliably across different notebook implementations.render_trace()behave differently depending on whether they're running in a notebook environment or not, and even more confusing when we can't reliably detect notebook environments.Block.__str__()for example. This approach tends to spray UI code across core PyRTL modules, for example every__str__()method would end up with tons ofifstatements to support all presentation styles.To clean this up:
pyrtlmodule.Edit: Tim and I discussed this a bit more offline. Two more notes:
np.setprintoptionsseems like a good example of designing with this principle in mind.render_tracecan produce a lot of output. These functions must support writing the output to a file, without buffering the entire output in memory.