whitequark changed the topic of #amaranth-lang to: Amaranth hardware definition language · weekly meetings on Mondays at 1700 UTC · code https://github.com/amaranth-lang · logs https://libera.irclog.whitequark.org/amaranth-lang
trabucayre has quit [*.net *.split]
bob_twinkles has quit [*.net *.split]
anuejn has quit [*.net *.split]
bob_twinkles has joined #amaranth-lang
anuejn has joined #amaranth-lang
trabucayre has joined #amaranth-lang
Wolfvak has quit [Quit: ZNC - https://znc.in]
Wolfvak has joined #amaranth-lang
jjsuperpower has quit [Ping timeout: 246 seconds]
<whitequark> some random thoughts about improving Amaranth middle-end
<whitequark> I think what could be greatly beneficial is replacing the Fragment object with a Scope one
<whitequark> a Scope would not introduce hierarchy, but rather keep track of the implicit state used when constructing the design
<whitequark> so for example an amaranth.lib.fsm could provide a fsm = FSM(m); with fsm.state("NAME"): function which surrounds the statement inside the with fsm.state with a new Scope internally and now it can wrap the contents with a with m.If(fsm.state == ...):
<whitequark> ResetInserter, EnableInserter would all be introducing a new Scope whose reset and enable, correspondingly, would be tied to that signal
<whitequark> and during elaboration, all of the scopes would get flattened, and the resets/enables turned into appropriate decision trees
<whitequark> synchronous rst and en of a clock domain would be the initial values for the scope
jjsuperpower has joined #amaranth-lang
jn has quit [Ping timeout: 240 seconds]
jn has joined #amaranth-lang
jn has joined #amaranth-lang
jn has quit [Changing host]
Guest48 has joined #amaranth-lang
Guest48 has quit [Client Quit]
Degi_ has joined #amaranth-lang
Degi has quit [Ping timeout: 250 seconds]
Degi_ is now known as Degi
<charlottia> does the FSM example differ from what we have currently in the sense that the wrapping (/contents in general) of the scope can be determined later on in the elaboration process, in a way that can be done by user code? (where amaranth.lib.fsm is such a user, not needing access to Module internals like it does now)
<charlottia> also, "elaboration" feels like it's a very broad phase: scopes are flattened during elaboration, but also are only constructed during elaboration (i.e. in the bodies of elaborate() methods!).
<whitequark> <charlottia> "does the FSM example differ from..." <- ye
<whitequark> > <@charlotte:hrzn.ee> does the FSM example differ from what we have currently in the sense that the wrapping (/contents in general) of the scope can be determined later on in the elaboration process, in a way that can be done by user code? (where `amaranth.lib.fsm` is such a user, not needing access to `Module` internals like it does now)
<whitequark> * yes
<whitequark> <charlottia> "also, "elaboration" feels like..." <- also yes. it's not really conceived as a phase
<charlottia> indeed
<_whitenotifier-6> [amaranth] charlottia opened pull request #831: lib.data: remove unnecessary loop. - https://github.com/amaranth-lang/amaranth/pull/831
<whitequark> whitequark: this does benefit user code (besides FSMs, there are examples where parser generators can benefit by the same mechanism), but it also means what's currently in amaranth.hdl.dsl can get a lot less messy
<charlottia> yes! absolutely, I think making this kind of control structure describable from outside using more fundamental concepts (i.e. Scope) can only be good for the implementation.
<whitequark> moreover, right now there is the gross hack that is Fragment.flatten
<whitequark> it's used in only 1 or 2 places, but IIRC one of those is the Intel FPGA toplevel that requires all iobufs to live directly in top
<whitequark> s/Intel/Quartus/, s/FPGA/toolchain/, s/toplevel//
<_whitenotifier-6> [amaranth] codecov[bot] commented on pull request #831: lib.data: remove unnecessary loop. - https://github.com/amaranth-lang/amaranth/pull/831#issuecomment-1616383052
<whitequark> we don't have any way (other than that hack, which is undocumented and unsupported) to "just add a bunch of logic to a module"
<charlottia> (... I've only just read amaranth._utils.flatten for the first time. woof. :D)
<charlottia> whitequark: yepyep
<whitequark> no that's the other flatten
<charlottia> so I'm seeing ^_^
<_whitenotifier-6> [amaranth-lang/amaranth] github-merge-queue[bot] pushed 1 commit to gh-readonly-queue/main/pr-831-cdf8fcc32ffc8bab7aaf01d9def893ced368e376 [+0/-0/±1] https://github.com/amaranth-lang/amaranth/compare/d7302e9fda67...f4b013ac7338
<_whitenotifier-6> [amaranth-lang/amaranth] charlottia f4b013a - lib.data: no loop required, we return or die.
<whitequark> mwk: so the thing about ONFI flash is that the applet isn't even particularly good
<whitequark> er, wrong chnnel
jjsuperpower has quit [Ping timeout: 240 seconds]
<charlottia> ok, just semantically sated myself on the word "flatten", it no longer resembles a word.
<charlottia> when you say: "during elaboration, all of the scopes would get flattened", does this only mean "process all scopes such that they are removed from the hierarchy"? (my first read was "everything in the design gets flattened scope-wise", but that would just equate to flattening the whole design.) presumably one thing a scope can do _is_ to flatten its contents and that's where that functionality would live.
<charlottia>
<whitequark> yeah. like instead of scopes you just get reset and enable signals for dffs
<charlottia> yepyep, okay!
<_whitenotifier-6> [amaranth-lang/amaranth] github-merge-queue[bot] pushed 1 commit to main [+0/-0/±1] https://github.com/amaranth-lang/amaranth/compare/cdf8fcc32ffc...f4b013ac7338
<_whitenotifier-6> [amaranth-lang/amaranth] charlottia f4b013a - lib.data: no loop required, we return or die.
<_whitenotifier-6> [amaranth-lang/amaranth] github-merge-queue[bot] deleted branch gh-readonly-queue/main/pr-831-cdf8fcc32ffc8bab7aaf01d9def893ced368e376
<_whitenotifier-6> [amaranth] github-merge-queue[bot] deleted branch gh-readonly-queue/main/pr-831-cdf8fcc32ffc8bab7aaf01d9def893ced368e376 - https://github.com/amaranth-lang/amaranth
<_whitenotifier-6> [amaranth] whitequark closed pull request #831: lib.data: remove unnecessary loop. - https://github.com/amaranth-lang/amaranth/pull/831
<_whitenotifier-6> [amaranth-lang/amaranth-lang.github.io] whitequark pushed 1 commit to main [+0/-0/±30] https://github.com/amaranth-lang/amaranth-lang.github.io/compare/a5e26977753c...4c5d5b851a05
<_whitenotifier-6> [amaranth-lang/amaranth-lang.github.io] github-merge-queue[bot] 4c5d5b8 - Deploying to main from @ amaranth-lang/amaranth@f4b013ac7338923230aa03929a69ab5761a98ef7 🚀
<whitequark> an interesting thing about a Scope is that it has aspects of both "namespace" and "control structure"
<whitequark> ie: domains can be bound / partially rebound on scope level, but the same mechanism can be used to build control flow
<whitequark> it might make sense to have two mechanisms instead of one, i'm not sure yet
<charlottia> hm! it hadn't occurred to me anything that controls/modulates the enable for everything underneath it is a control structure by definition.
<whitequark> yes
<whitequark> there's a bit of complication
<whitequark> Reset/EnableInserters do not affect m.d.comb
<whitequark> but m.If very much does
<charlottia> whitequark: maybe! or maybe it's orthogonal enough that it can be one and some uses will use one, and some both; only comes out in impl.
<whitequark> exactly
<charlottia> whitequark: hmm, I need to think about this more.
<whitequark> also I guess you probably don't want to control-enable the submodule if you put it into a with m.If branch
<charlottia> is that only a product of expectations from current use? (see also, varying opinions on whether one should describe logic in methods called from elaborate etc.) it seems like it wouldn't be a terrible thing to have that behaviour and thus mandate always-on submodules are put at the top level.
<charlottia> I agree it does seem surprising, though.
<whitequark> ya i don't know honestly
<charlottia> ye
Degi has quit [Ping timeout: 245 seconds]
<d1b2> <olivier_galibert> wq: don’t forget to read my rfc at some point 🙂
<robtaylor> <whitequark> "it might make sense to have..." <- one small benefit to having seperate things for namespace and control flow would be the names could be clearer then 'scope', especially for a user thats not used to thinking about scoping deeply
<_whitenotifier-6> [amaranth] charlottia reviewed pull request #830 commit - https://github.com/amaranth-lang/amaranth/pull/830#discussion_r1249437756
<_whitenotifier-6> [amaranth] charlottia commented on pull request #830: hdl.ast: implement ShapeCastable.__subclasshook__. - https://github.com/amaranth-lang/amaranth/pull/830#issuecomment-1616610286
<_whitenotifier-6> [amaranth] codecov[bot] commented on pull request #830: hdl.ast: implement ShapeCastable.__subclasshook__. - https://github.com/amaranth-lang/amaranth/pull/830#issuecomment-1616610350
<_whitenotifier-6> [amaranth] charlottia commented on pull request #830: hdl.ast: implement ShapeCastable.__subclasshook__. - https://github.com/amaranth-lang/amaranth/pull/830#issuecomment-1616610400
<_whitenotifier-6> [amaranth] charlottia commented on pull request #830: hdl.ast: implement ShapeCastable.__subclasshook__. - https://github.com/amaranth-lang/amaranth/pull/830#issuecomment-1616610688
<_whitenotifier-6> [amaranth] charlottia opened pull request #832: lib.enum: reject enums with zero for shape-casting in one place. - https://github.com/amaranth-lang/amaranth/pull/832
<_whitenotifier-6> [amaranth] codecov[bot] commented on pull request #832: lib.enum: reject enums with zero for shape-casting in one place. - https://github.com/amaranth-lang/amaranth/pull/832#issuecomment-1616617484
jjsuperpower has joined #amaranth-lang
mithro has quit [Server closed connection]
mithro has joined #amaranth-lang
jjsuperpower has quit [Ping timeout: 260 seconds]
jfng[m] has quit [Server closed connection]
jfng[m] has joined #amaranth-lang
adamgreig[m] has quit [Server closed connection]
adamgreig[m] has joined #amaranth-lang
<fl4shk[m]> I wonder how hard it'll be for me to translate my existing use of my own Splitintf to amaranth.lib.component
<fl4shk[m]> probably not that hard
<fl4shk[m]> but I'll have to eliminate the tags stuff
<fl4shk[m]> or otherwise convert the code to handle tags to amaranth.lib.component
<fl4shk[m]> with some kind of recursive function that calls each connect()
<galibert[m]> connect is recursive by itself?
<fl4shk[m]> well
<fl4shk[m]> yes
<fl4shk[m]> but it doesn't include my tags system
<fl4shk[m]> which is something I've been relying on
<fl4shk[m]> it basically only lets connect() be called if two (sub-)interfaces have the same tag
<fl4shk[m]> and it handles name conflicts
<fl4shk[m]> I might not need the tags
<fl4shk[m]> I could just connect things using tags by hand
<fl4shk[m]> connect things by hand
<fl4shk[m]> *
<galibert[m]> your tags feel like they could be sub-signatures
<fl4shk[m]> that could be
<fl4shk[m]> in fact
<fl4shk[m]> this is for connecting (my equivalent of) two sub-signatures from just the top level
<fl4shk[m]> It's not super useful
<fl4shk[m]> so I think the main reason I use these tags is that, upon constructing a Splitintf, sub-signatures end up being of Splitintf type
<fl4shk[m]> hm, well, maybe that's still wrong
<fl4shk[m]> but in any case sometimes you want to connect things where names don't match
<fl4shk[m]> like say a pipeline skid buffer
<fl4shk[m]> you'd want to connect the forward sub-signature of the current psb to the backwards sub-signature of the next psb
<galibert[m]> which names don't match?
<fl4shk[m]> forward and `backwards
<fl4shk[m]> backwards
<fl4shk[m]> those names don't match, but you still want to connect them
<galibert[m]> do you have a signal called forwards in one module and backwads in the other?
<fl4shk[m]> yes but they're two instances of they same module
<fl4shk[m]> of the same module*
<fl4shk[m]> just that they connect by forwards and backwards
<galibert[m]> a signal is not an instance?
<fl4shk[m]> uh
<fl4shk[m]> they are instances
<fl4shk[m]> a "pipeline skid buffer" is an instance
<galibert[m]> I think we're not talking of the same names
<fl4shk[m]> it's an Elaboratable
<fl4shk[m]> hm
<galibert[m]> a signal is not an Elaboratable (I hope)
<fl4shk[m]> I'm not referring to a signal
<fl4shk[m]> I'm referring to forwards and backwards as being ports of the pipeline skid buffer Elaboratable
<galibert[m]> "do you have a signal called forwards in one module and backwads in the other?" -> "yes but they're two instances of they same module"
<galibert[m]> color me confused
<fl4shk[m]> oh I see
<fl4shk[m]> I messed up
<fl4shk[m]> sorry, that's my bad
<galibert[m]> that's ok, chat is hard
<fl4shk[m]> in any case
<fl4shk[m]> the tags system solves this
<fl4shk[m]> in any case, I don't think it's that much work to connect a sub-signature to another sub-signature
<fl4shk[m]> so I will abandon the tags system
<galibert[m]> I mean I currently fail to see how you're in a case that can't be solved by either m.d.comb += a.backwards.eq(b.forwards) or connector.connect(m, a.backwards, b.forwards)
<fl4shk[m]> yeah, that's what I'm admitting right now
<galibert[m]> but I clearly don't fully understand your use case :-)
<fl4shk[m]> well
<galibert[m]> in any case, it seems to be clear to you, so that's good :-)
<fl4shk[m]> yeah
<fl4shk[m]> the issue I thought existed doesn't exist
<galibert[m]> those are the best issues
<fl4shk[m]> yes
<fl4shk[m]> btw
<fl4shk[m]> I found out I was handling priority wrongly in my crossbar switch
<fl4shk[m]> so I fixed it
<fl4shk[m]> today
<galibert[m]> cool
Bluefoxicy has quit [Read error: Connection reset by peer]
Bluefoxicy has joined #amaranth-lang
jjsuperpower has joined #amaranth-lang
jjsuperpower has quit [Ping timeout: 246 seconds]
jjsuperpower has joined #amaranth-lang
jjsuperpower has quit [Ping timeout: 250 seconds]
<fl4shk[m]> How does a sub-Signature get affected by its parent Signature's Flow for the sub-Signature?
key2 has quit [Quit: Connection closed for inactivity]
antoinevg[m] has quit [Server closed connection]
antoinevg[m] has joined #amaranth-lang
<charlottia> <FL4SHK[m]> "How does a sub-Signature get..." <- > If `flow` is `Flow.In`, then the actual flow of every port recursively described by `signature` is the reverse of the stated direction.
feldim2425 has quit [Quit: ZNC 1.8.2+deb2build5 - https://znc.in]
feldim2425 has joined #amaranth-lang
<mwk> whitequark: is there a "blessed" way to squash away the MustUse warning on elaboratables you don't actually intend to elaborate? motivating use case is testcases like this one that spam the CI log with warnings: https://github.com/GlasgowEmbedded/glasgow/blob/main/software/glasgow/gateware/pads.py#L106
<adamgreig[m]> you can set a class variable _MustUse__silence = True, or in a test file, # amaranth: UnnusedElaboratable=no
<adamgreig[m]> * you can set a class variable _MustUse__silence = True, or in a test file, # amaranth: UnusedElaboratable=no
<fl4shk[m]> <charlottia> "> If `flow` is `Flow.In`, then..." <- that works, thanks
jjsuperpower has joined #amaranth-lang
<mwk> adamgreig[m]: neither of those has enough fine control to do what I want
<charlottia> <mwk> "Catherine: is there a "blessed..." <- You could also use `warnings.catch_warnings(action=“ignore”, category=amaranth.UnusedMustUse)` as a context manager. There’s probably a decorator for the unit test functions …?
<mwk> charlottia: I don't think I can; these warnings seem to all trigger afterwards during GC
<mwk> hm
<adamgreig[m]> mwk: could you put `pads._MustUse__silence = True` immediately after creating it, or alternatively move the test cases to a tests file and then stick the linter comment in that?
<mwk> perhaps the correct thing to do would be to split off glasgow tests into separate files from the actual classes they test, then use the `# amaranth:` thing, but... that only covers direct instantiation of elaboratables from the testsuite, not ones recursively instantiated by hierarchy
<adamgreig[m]> afaik those are the two ways to silence that warning, and amaranth uses both
<adamgreig[m]> ah, it's elaboratables instantiated by the top-level unused elaboratable that are also unused? somehow i've not come across that as a problem
<mwk> mhm
<mwk> it happens in some glasgow applet test, let me narrow that down
<mwk> ... ugh why doesn't abc have the good sense to die when hit by SIGINT
<charlottia> Lol :)
<mwk> oh.
<mwk> I see
jjsuperpower has quit [Quit: Leaving]
<mwk> so this happens in every @applet_hardware_test test
<mwk> where the entire target gateware is constructed as part of normal applet construction process, then completely discarded in favor of attaching a mock hardware interface from a fixture file to the applet software
<mwk> actually... I don't think it's even possible to *find* all instantiated elaboratables in this mess without actually elaborating the resulting applet, since they can be stuffed in all sorts of private variables
<mwk> so I think the easiest way to deal with it would be to just Fragment.get?
<mwk> ... yup this seems to work
<mwk> lol.
<mwk> https://github.com/GlasgowEmbedded/glasgow/blob/main/software/glasgow/gateware/pads.py#L132 this is a fun one: cannot add _MustUse__silence nor run Fragment.get because the constructor obviously fails; the `# amaranth:` thing also doesn't work, since the immediate caller is unittest