whitequark[cis] changed the topic of #amaranth-lang to: Amaranth hardware definition language · weekly meetings: Amaranth each Mon 1700 UTC, Amaranth SoC each Fri 1700 UTC · code https://github.com/amaranth-lang · logs https://libera.irclog.whitequark.org/amaranth-lang · Matrix #amaranth-lang:matrix.org
Raito_Bezarius has joined #amaranth-lang
Raito_Bezarius has quit [Ping timeout: 255 seconds]
Raito_Bezarius has joined #amaranth-lang
toshywoshy has joined #amaranth-lang
nelgau has joined #amaranth-lang
nelgau has quit [Read error: Connection reset by peer]
nelgau has joined #amaranth-lang
jjsuperpower has joined #amaranth-lang
nelgau_ has joined #amaranth-lang
nelgau has quit [Ping timeout: 258 seconds]
Degi_ has joined #amaranth-lang
Degi has quit [Ping timeout: 272 seconds]
Degi_ is now known as Degi
<cr1901> I accidentally have "with m.Case()" in my code. Does this by default match nothing or everything (as if I wrote "with m.Default()"). Should it be a diagnostic?
Guest86 has joined #amaranth-lang
Guest86 has quit [Client Quit]
<whitequark[cis]> there's an open issue for making that a diagnostic
<whitequark[cis]> it does the same thing as with m.Default():
<cr1901> Cool, I thought so, but wanted to make sure
jjsuperpower has quit [Ping timeout: 258 seconds]
Guest39 has joined #amaranth-lang
Guest39 has quit [Client Quit]
smkz has quit [Ping timeout: 240 seconds]
smkz has joined #amaranth-lang
nelgau_ has quit [Read error: Connection reset by peer]
nelgau has joined #amaranth-lang
nelgau has quit [Read error: Connection reset by peer]
nelgau_ has joined #amaranth-lang
nelgau_ has quit [Ping timeout: 255 seconds]
nelgau has joined #amaranth-lang
<galibert[m]> Catherine: can I annoy you with some unclear details on the sim?
<whitequark[cis]> sure!
<galibert[m]> so, if I understand correctly, yield x.eq(y) queues the setting, and the next Settle commits the queue
<galibert[m]> I'm trying to fully understand the interaction with Tick(). Is Settle called before any Tick()?
<whitequark[cis]> so Settle isn't *really* a thing
<whitequark[cis]> it is the same as yield Delay(0)
<galibert[m]> Settle isn't commit with a coat a paint?
<whitequark[cis]> and Tick() involves advancing time
<whitequark[cis]> no, it is not commit
<whitequark[cis]> it is an entire sequence of eval and commit
<galibert[m]> Oh
<whitequark[cis]> hence "settle"
<whitequark[cis]> "until the logic settles"
<whitequark[cis]> (any delay at all involves settling of logic, necessarily)
<galibert[m]> yeah
<galibert[m]> what I don't get, and maybe the answer is "it's not possible", how do you build a simulation coroutine that changes values on a given domain Tick in the presense of other domains?
<galibert[m]> I have a feeling the value change can happen at any time (but only once, of course)
<galibert[m]> TIL: usb cables need to be plugged on both sides to work. If you don't see the fpga board on usb while it's plugged in, check the other end of the damn cables
<whitequark[cis]> galibert[m]: I don't understand the question
<galibert[m]> If you have one process that does yield Tick("a"); yield x.eq(something) in a loop (e.g. any behavorial simulation on domain "a")
<galibert[m]> when is the x change visible to other processes?
<galibert[m]> in the presence of other domains, like a "b" that's 180-out-of-phase?
<whitequark[cis]> that is an extremely good question
<galibert[m]> that's where I'm confused :-)
<whitequark[cis]> the answer is "it depends"; it is visible whenever the time is advanced past the time of Tick("a"), but within that 0-length instant, there is still a happens-before relationship
<whitequark[cis]> so if another process does `yield Tick("a"); yield Settle(); <here>` then this is visible
<whitequark[cis]> but before yield Settle() it is not
<galibert[m]> ewwww that's... hard to reason about
<whitequark[cis]> (this all gets much worse once you realize that generated clocks, like enabled or divided ones, happen within the same 0-length instant too)
<whitequark[cis]> it is
<whitequark[cis]> the fact that right now, everyone gets exposed to this, and not just people doing multiclock simulations or weird behavioral stuff, is the primary motivation for add_testbench
<galibert[m]> yeah, I do multiclock simulations all the time :/ Old cpus simulations are essentially impossible without a 180 second domain, there's chains of dependencies that break
<galibert[m]> that explains why it's kind of a mess though, I thought I was getting stupid
<whitequark[cis]> well if you have a 180 phase domain, there's no issue, is there?
<galibert[m]> well yeah, my test code alternates yield Tick("phi1") and Tick("phi2"), but what-is-visible-when I sometimes a hardscratcher
<galibert[m]> s/I/is/
<whitequark[cis]> this is unfortunately the nature of the beast
<whitequark[cis]> you'd get something as bad, if not worse, in Verilog, I think
<whitequark[cis]> bad in different ways
<galibert[m]> I kinda... let's be polite, not like verilog much
<galibert[m]> I mean I could do my stuff in Verilog or VHDL, I just don't want to :-)
<galibert[m]> Neither is a complicated language once you understand what's under it (and happen to know another two dozen programming languages, like you probably do too)
<whitequark[cis]> what I mean is that we at least do not regress over the industry standard
<whitequark[cis]> improving on it is an open research problem
<whitequark[cis]> I've been tackling it in the background but it's a tricky one
<galibert[m]> You just made me shudder thinking of rewriting Amaranth in tcl
<whitequark[cis]> wh. Why
<galibert[m]> Industry standard !
<whitequark[cis]> I actually do not know how many programming languages I know
<whitequark[cis]> not even remotely
<galibert[m]> Same here, and it's even worse where it comes to assembly
<whitequark[cis]> sometimes I encounter a name I do not remember and discover I somehow know how to use that
<galibert[m]> There's one language I've never been able to understand, even after having tried multiple times: Lambda prolog
<whitequark[cis]> whitequark[cis]: it's possible that the number is uncomputable, because attempting to enumerate them would cause me to design a new one or a two
<galibert[m]> Oh, another Heisenberg effect?
<whitequark[cis]> quarks follow quantum physics rules after all
<galibert[m]> (and you did boneless, so even assembly is not safe)
nelgau has quit [Read error: Connection reset by peer]
nelgau has joined #amaranth-lang
PotentialUser-86 has joined #amaranth-lang
PotentialUser-86 has quit [Quit: Client closed]
_whitenotifier has joined #amaranth-lang
<_whitenotifier> [amaranth] cbiffle opened issue #943: iCE40 BRAM errata workaround silently disappears once a clock domain named "sync" is defined - https://github.com/amaranth-lang/amaranth/issues/943
GenTooMan has quit [Ping timeout: 245 seconds]
GenTooMan has joined #amaranth-lang
Lord_Nightmare has quit [Quit: ZNC - http://znc.in]
Lord_Nightmare has joined #amaranth-lang
<_whitenotifier> [amaranth] whitequark commented on issue #943: iCE40 BRAM errata workaround silently disappears once a clock domain named "sync" is defined - https://github.com/amaranth-lang/amaranth/issues/943#issuecomment-1777937836
<_whitenotifier> [amaranth] wanda-phi opened pull request #944: test_lib_wiring: squash UnusedElaboratable warnings. - https://github.com/amaranth-lang/amaranth/pull/944
<_whitenotifier> [amaranth] codecov[bot] commented on pull request #944: test_lib_wiring: squash UnusedElaboratable warnings. - https://github.com/amaranth-lang/amaranth/pull/944#issuecomment-1777951213
<_whitenotifier> [amaranth] github-merge-queue[bot] created branch gh-readonly-queue/main/pr-944-00699f7c41a97cf8373a15e0b28e29361e017812 - https://github.com/amaranth-lang/amaranth
<_whitenotifier> [amaranth-lang/amaranth] github-merge-queue[bot] pushed 1 commit to main [+0/-0/±1] https://github.com/amaranth-lang/amaranth/compare/00699f7c41a9...e53d78474fed
<_whitenotifier> [amaranth-lang/amaranth] wanda-phi e53d784 - test_lib_wiring: squash UnusedElaboratable warnings.
<_whitenotifier> [amaranth] github-merge-queue[bot] deleted branch gh-readonly-queue/main/pr-944-00699f7c41a97cf8373a15e0b28e29361e017812 - https://github.com/amaranth-lang/amaranth
<_whitenotifier> [amaranth] whitequark closed pull request #944: test_lib_wiring: squash UnusedElaboratable warnings. - https://github.com/amaranth-lang/amaranth/pull/944
<_whitenotifier> [amaranth-lang/amaranth-lang.github.io] whitequark pushed 1 commit to main [+0/-0/±32] https://github.com/amaranth-lang/amaranth-lang.github.io/compare/88ab97a7e937...3e93e2dcee8f
<_whitenotifier> [amaranth-lang/amaranth-lang.github.io] github-merge-queue[bot] 3e93e2d - Deploying to main from @ amaranth-lang/amaranth@e53d78474fed3e7e4ab469ab023a9d3b5eb12b24 🚀
<_whitenotifier> [amaranth] wanda-phi opened pull request #945: Implement RFC 20: Deprecate non-FWFT FIFOs. - https://github.com/amaranth-lang/amaranth/pull/945
<Wanda[cis]> now that is a refactor I'm somehow more uneasy about than the new IR
<_whitenotifier> [amaranth] codecov[bot] commented on pull request #945: Implement RFC 20: Deprecate non-FWFT FIFOs. - https://github.com/amaranth-lang/amaranth/pull/945#issuecomment-1778005664
<Wanda[cis]> Catherine: so there's something I don't quite understand
<Wanda[cis]> while I'm reasonably sure the special-cased FIFO of size 1 is implemented correctly, the formal tests don't seem to catch one faulty version
<Wanda[cis]> specifically, insert (unconditional) m.d.sync += self.r_data.eq(self.w_data) at line 274 of amaranth/lib/fifo.py
<Wanda[cis]> AFAICS it's buggy, but accepted by formal for some reason?
<whitequark[cis]> odd
<_whitenotifier> [amaranth] github-merge-queue[bot] created branch gh-readonly-queue/main/pr-945-e53d78474fed3e7e4ab469ab023a9d3b5eb12b24 - https://github.com/amaranth-lang/amaranth
<_whitenotifier> [amaranth-lang/amaranth] github-merge-queue[bot] pushed 3 commits to main [+0/-0/±6] https://github.com/amaranth-lang/amaranth/compare/e53d78474fed...4e4085a95b50
<_whitenotifier> [amaranth-lang/amaranth] wanda-phi bfd9626 - lib.fifo: make `fwft=True` the default
<_whitenotifier> [amaranth-lang/amaranth] wanda-phi a60b996 - lib.fifo: reimplement `SyncFIFOBuffered` without inner `SyncFIFO`.
<_whitenotifier> [amaranth-lang/amaranth] wanda-phi 4e4085a - Implement RFC 20: Deprecate non-FWFT FIFOs.
<_whitenotifier> [amaranth] whitequark closed pull request #945: Implement RFC 20: Deprecate non-FWFT FIFOs. - https://github.com/amaranth-lang/amaranth/pull/945
<_whitenotifier> [amaranth] github-merge-queue[bot] deleted branch gh-readonly-queue/main/pr-945-e53d78474fed3e7e4ab469ab023a9d3b5eb12b24 - https://github.com/amaranth-lang/amaranth
<_whitenotifier> [amaranth-lang/amaranth-lang.github.io] whitequark pushed 1 commit to main [+0/-0/±37] https://github.com/amaranth-lang/amaranth-lang.github.io/compare/3e93e2dcee8f...65c5a90eb61c
<_whitenotifier> [amaranth-lang/amaranth-lang.github.io] github-merge-queue[bot] 65c5a90 - Deploying to main from @ amaranth-lang/amaranth@4e4085a95b50e41288615d20211c6c5a41a01193 🚀
<Wanda[cis]> so I'm looking at https://github.com/amaranth-lang/amaranth/issues/778 (enumeration type safety)
<Wanda[cis]> the immediate issue that one runs into with this plan is that eg. plain_value + E.x will immediately call Value.__add__, which will immediately return an Operator instance without even consulting anything on E.x (other than Value.casting it, which has to succeed by contract)
<Wanda[cis]> so... I don't think we even have enough extension points to do this?
<Wanda[cis]> basically Value seems too eager to Value.cast everything coming into contact with it to implement type safety
<Wanda[cis]> ... RFC 28 would actually do the trick here, but it'd involve explicitly having to implement all Value-supported operators with raise TypeError
<Wanda[cis]> actually, speaking of RFC 28, wouldn't an extension point for Value.eq be likewise desirable? you'd think that assigning between plain value / fixed-point should perform a conversion
<zyp[m]> <Wanda[cis]> "actually, speaking of RFC 28..." <- that did cross my mind before, but it felt like going too far
<zyp[m]> for the fixedpoint code I currently feel like the most reasonable option is that an implicit assignment to a value just assigns the underlying storage, and then you've got a .truncate() or .round() or something with an optional argument that states how many fractional bits to keep
<zyp[m]> so e.g. Q(1, 2).const(1.25) directly assigned to a value results in 5, while Q(1, 2).const(1.25).truncate() results in 1
<_whitenotifier> [amaranth] cbiffle commented on issue #943: iCE40 BRAM errata workaround silently disappears once a clock domain named "sync" is defined - https://github.com/amaranth-lang/amaranth/issues/943#issuecomment-1778137789
<whitequark[cis]> <Wanda[cis]> "basically Value seems too..." <- yes, this is the case, but like you observe, RFC 28 would do it
<whitequark[cis]> <Wanda[cis]> "... RFC 28 would actually do the..." <- I see no particular issue with doing that; it's a bit awkward but our numerics system is just inherently awkward for historical reasons
<whitequark[cis]> retrofitting things into it does involve making code like this, but... as long as it works reliably, why the heck not?
<whitequark[cis]> the ugliness is contained in amaranth.lib and everyone's happily using that; that's it
<whitequark[cis]> re: enumerations, there is something I want to ask you to implement first
<whitequark[cis]> can you make it so that if shape is not supplied, the metaclass returns an instance of the builtin enum and not amaranth enum?
<whitequark[cis]> that would make it truly transparent in that case
<whitequark[cis]> (the metaclass new doesn't actually need to return an instance of the metaclass (!!) it can just return whatever
<whitequark[cis]> * (the metaclass __new__ doesn't actually need to return an instance of the metaclass (!!) it can just return whatever)
<Wanda[cis]> whitequark[cis]: unfortunately I know that
<whitequark[cis]> of course >.>
<Wanda[cis]> anyway, yeah, sure, sounds doable
<whitequark[cis]> thanks ^___^
<Wanda[cis]> this means that RFC 28 is transitively included in 0.4, right?
<whitequark[cis]> yes, I do believe so
<whitequark[cis]> I expect it to be accepted on the next meeting, so no issue with that
<whitequark[cis]> and it's a very nice addition regardless
<Wanda[cis]> mhm
<Wanda[cis]> what about eq?
<whitequark[cis]> I... don't know
<whitequark[cis]> do we need an .req?
<Wanda[cis]> the usecase for enums would be entirely about rejecting assignments of course
<whitequark[cis]> mmm, do we really want that for enums specifically?
<whitequark[cis]> I think assigning enums to random ints is common enough it should probably be alloewd
<whitequark[cis]> s/alloewd/allowed/
<Wanda[cis]> shrug if you ask me, the entire language could use more type checking
<whitequark[cis]> well yes but like
<Wanda[cis]> but that seems impossible to retrofit
<whitequark[cis]> we kinda have to keep it at least somewhat compatible <.<
<whitequark[cis]> we can keep retrofitting stuff to it and gradually raising the floor
<whitequark[cis]> and i think that's valuable and useful
<Wanda[cis]> could always require an explicit cast operator
<Wanda[cis]> but... yeah, it may not be worth doing a req
<whitequark[cis]> we can always retrofit that later, I think
<whitequark[cis]> so it's not a huge deal rn
<Wanda[cis]> alright then, I'm going to not think about this again until RFC 28 happens
<Wanda[cis]> and just do the metaclass magic
lf has quit [Ping timeout: 258 seconds]
lf has joined #amaranth-lang
<Wanda[cis]> <whitequark[cis]> "can you make it so that if ..." <- so that's supposed to just be a 3-line change, right? no catch to it?
<Wanda[cis]> or umm.
<Wanda[cis]> okaaaay, that's a lot of fallout
notgull has quit [Ping timeout: 240 seconds]
notgull has joined #amaranth-lang
<Wanda[cis]> right. of course it cannot just work like this, since it'd just make amaranth.lib.enum.Enum an instance of the plain EnumMeta and completely disable the subclassing behavior
<Wanda[cis]> I can do a horrible, and special-case it
<Wanda[cis]> I think I broke Python
<whitequark[cis]> nice (?)
<Wanda[cis]> I somehow got the metaclass to recurse on itself while attempting to call super()
<Wanda[cis]> I'm probably not supposed to have something in MRO that is a subclass of my metaclass
<Wanda[cis]> * MRO that has a metaclass that is a
<whitequark[cis]> fantastic
<Wanda[cis]> I can apply more hacks.
<whitequark[cis]> always
<whitequark[cis]> horrific
<Wanda[cis]> this causes two test failures that essentially rely on, well, the amaranth metaclass being actually present even without shape
<whitequark[cis]> instead of _init_done you could check for the absence of the global inside of globals()
<whitequark[cis]> like
<whitequark[cis]> u get the idea i think
<Wanda[cis]> yes, because I didn't commit enough crimes here yet
<whitequark[cis]> giggles
<Wanda[cis]> so do you want to continue with this idea or should I encase it in concrete and dump somewhere with warnings about places of honor?
<whitequark[cis]> I think this is perfectly reasonable
<whitequark[cis]> I would just want to dress this up a little
<whitequark[cis]> no real functional change
<Wanda[cis]> hmmm
<Wanda[cis]> can I change the metaclass of a type after the fact
<whitequark[cis]> not afaik
<Wanda[cis]> oh. I can. nice.
<whitequark[cis]> ...
<whitequark[cis]> what
<whitequark[cis]> how
<Wanda[cis]> so I can get rid of _init_done entirely by just constructing them without special metaclass, and injecting it after the fact
<Wanda[cis]> see, cleaner code
<whitequark[cis]> that's unhinged but I'm completely OK with it
<Wanda[cis]> see, you can always get rid of a problem by moving it a meta level up.
<Wanda[cis]> it'll have no repercussions whatsoever
<whitequark[cis]> this is completely true