Skip to content

doc/embedding: add skeleton of "Embedding Glasgow"#1117

Draft
jwise wants to merge 13 commits intoGlasgowEmbedded:mainfrom
jwise:jwise/doc/embedding-glasgow
Draft

doc/embedding: add skeleton of "Embedding Glasgow"#1117
jwise wants to merge 13 commits intoGlasgowEmbedded:mainfrom
jwise:jwise/doc/embedding-glasgow

Conversation

@jwise
Copy link
Copy Markdown
Contributor

@jwise jwise commented Feb 28, 2026

Here is a skeleton of what I have been trying to put together in my head.

Maybe this ought be expanded further into a section on 'installing as embeddable' (and more concrete examples of why you might want to do this / who ought do this?); the actual HOWTO; and pointers to other resources?

Signed-off-by: Joshua Wise <joshua@joshuawise.com>
…adable

Signed-off-by: Joshua Wise <joshua@accelerated.tech>
@whitequark whitequark added the waiting-on-review Status: Waiting for review label Mar 1, 2026
Signed-off-by: Joshua Wise <joshua@accelerated.tech>
@jwise
Copy link
Copy Markdown
Contributor Author

jwise commented Mar 1, 2026

This page is likely to grow large enough that it needs to get cracked into multiple pages.

jwise added 2 commits March 1, 2026 15:50
Signed-off-by: Joshua Wise <joshua@accelerated.tech>
Signed-off-by: Joshua Wise <joshua@accelerated.tech>
@jwise jwise force-pushed the jwise/doc/embedding-glasgow branch from 2ae351a to 948724d Compare March 1, 2026 22:46
Elaboratable abstract base class
<https://amaranth-lang.org/docs/amaranth/latest/guide.html#elaboration>`_, and then called the Assembly's
``add_submodule()`` method; in order to implement our own logic, we will
want to create our own ``Elaboratable`` object. (Later, when we connect
Copy link
Copy Markdown
Member

@whitequark whitequark Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No new documentation should explain how to use Elaboratable in a context like this.

I realize that in this case you'll get an error trying to instantiate one if you just leave out the annotations, but this will work:

class a(Component):
    def __init__(self):
        super().__init__({})

and it leaves people out of wondering "what is the difference between Elaboratable and Component".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think I disagree on this.

Elaboratable and Component are two different things on totally different abstraction layers (at least, as far as I understand). My goal with adding-your-own-logic.rst is to describe the abstraction layer of modules and submodules, and very much not to describe the abstraction layer of Wiring. (Also, I don't understand the abstraction layer of Wiring yet and I need to do the research part of it so that I do!)

Wiring is a very helpful way to describe "things that you can connect together". But in this stage of the document, we are not there yet -- we are describing only "things that contain logic". We'll have to be careful to describe this.

How do you feel about the more pointed .. note:: that I beefed this up with in 3f39304?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(For the record, and the explanation below notwithstanding, I think this is definitely one of the things where reasonable people can disagree. I reserve the right to change it to fit the way I want to teach the language—or to leave it be—but that would be an editorial decision, not a purely correctness based one.)

Elaboratable and Component are two different things on totally different abstraction layers (at least, as far as I understand).

Yes. This is true both from an implementation perspective and a specification one. If someone already knows the language well, then this is the only answer someone needs to have. But if they don't, then I think the language should be taught holistically; the question of "when do I use an Elaboratable and when do I use a Component" is something that would only confuse a learner for essentially no benefit.

The reason we even have two of them is historical, a result of path dependence: Elaboratable was there from day 1, and I was being very conservative with the introduction of lib.wiring alongside existing, non-conforming code, without breaking it and while allowing old and new code to interoperate. Had I designed the language today, Component would've been a built-in. Perhaps one day it will be, but this isn't on the roadmap.

How do you feel about the more pointed .. note:: that I beefed this up with in 3f39304?

This isn't really accurate. There is one main case where someone would instantiate an Elaboratable today in practice: the toplevel. The top-level ports are IOValues, not Values, and lib.wiring only deals with Values. But you can also make a Component with an empty signature like usual and it'll work just fine, so you don't have to do that, and I plan to teach things that way in the Amaranth tutorial.

Wiring is a very helpful way to describe "things that you can connect together". But in this stage of the document, we are not there yet -- we are describing only "things that contain logic". We'll have to be careful to describe this.

I agree that this is one way to see it but I think the complexity of introducing a new choice outweighs the separation, pedagogically speaking. One can equally say that "Components contain logic <...later...> also each Component has an Interface which can be connected to other things".

``wiring.Component``; since our logic keeps all of its I/Os internally, we
do not need to use it!)

All ``Elaboratable`` objects have a method, ``elaborate``, that instantiates
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably do an inter-sphinx link to Amaranth docs (I can set that up for you if you're not sure how).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I would appreciate it if you could set this up! If you drop an example I can probably take it from there.

# Platform object that we were passed (which represents the Glasgow
# board we are running on), and we retrieve I/O pads associated with
# each of the five LEDs directly from there.
led_pads = [platform.request("led", n) for n in range(5)]
Copy link
Copy Markdown
Member

@whitequark whitequark Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're using a deprecated method to use IO pins that will be removed. (platform.request used to instantiate IO buffers for you but it turned out to be intractable for more complex situations, so it won't in the future, and for now there's a compatibility shim here.) Since this will result in a deprecation warning when run, and since the main Glasgow code has no equivalent of this at all, you should introduce io.Buffer here; it is unavoidable so the earlier it's explained the better.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why the DeprecationWarning did not, in fact, appear for me here. Even if I logging.captureWarnings(True), I still do not get the warning! (This would have pointed me to dir="-" as how to do this previously.) How about change fe55359?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try PYTHONWARNINGS=all or something; the default severity for deprecations is kind of nonsense. (Hm, this should be fixed in Amaranth.)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I'm at a proper keyboard, I can explain how this works. For some reason that is beyond me, Python only enables deprecation warnings by default in the main module (basically only the .py file on the command line I think?). There is a way to enable or disable warnings depending on where they're raised, and because Amaranth tries to provide accurate diagnostics, the warnings end up "contained" in user code, which isn't covered by default.

We could potentially make Amaranth force-enable deprecation warning display everywhere but this would be somewhat invasive since it would also cover all third party code. We could do something more hacky and force-enable deprecation warnings only in modules where you import it (which is a pain to actually do but less invasive).

jwise added 7 commits March 28, 2026 03:18
Signed-off-by: Joshua Wise <joshua@accelerated.tech>
…boratable directly

Signed-off-by: Joshua Wise <joshua@accelerated.tech>
Signed-off-by: Joshua Wise <joshua@accelerated.tech>
Signed-off-by: Joshua Wise <joshua@accelerated.tech>
… I write the text

Signed-off-by: Joshua Wise <joshua@accelerated.tech>
Signed-off-by: Joshua Wise <joshua@accelerated.tech>
…g-pipes

Signed-off-by: Joshua Wise <joshua@accelerated.tech>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting-on-review Status: Waiting for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants