<_whitenotifier-8>
[amaranth-lang/amaranth-lang.github.io] whitequark 4767344 - Deploying to main from @ amaranth-lang/rfcs@632560717252abeb275b80d50ccd2552783635b3 🚀
<_whitenotifier-8>
[amaranth-lang/amaranth-lang.github.io] whitequark 80360a7 - Deploying to main from @ amaranth-lang/rfcs@47d49effe8b739e4f8facffa8984f3c47ffcb259 🚀
<_whitenotifier-8>
[amaranth-lang/amaranth-lang.github.io] whitequark dec4385 - Deploying to main from @ amaranth-lang/rfcs@04b2370973eb3d7f54561df12145a7c53166f60a 🚀
<d1b2>
<Olivier Galibert> Records are also on the chopping block
<whitequark>
re: one-hot mux
<whitequark>
I'd probably use an Array([a, b, c])[sel.find_first_one()]... except we don't have an ff1 operation
<jfng[m]>
.find_first_one() would be equivalent to using a priority encoder ?
<whitequark>
oh yeah
<d1b2>
<Olivier Galibert> How do I tell the synth that I'm sure there wont be two active at the same time so that it doesn't route more than necessary?
<d1b2>
<Olivier Galibert> at least or-of-and isn't perfect but trees relatively easily
<whitequark>
you can't do this in Amaranth
<whitequark>
(intentionally)
<whitequark>
hm, so if the invariant is that it's exactly one hot (or at most one hot), then you can do..
<whitequark>
oh, nevermind, I was about to suggest the exact same thing jfng said, but in slightly different words
<whitequark>
that produces the best RTL you can get in Amaranth
<whitequark>
I'm not actually sure if you can do better in Verilog
<mwk>
Verilog would use parallel_case casez with selects like 5'???1?
<whitequark>
oh yeah, but in this specific case, |([x,y,z]&repl([selx,sely,selz])) is probably the optimal RTL
<mwk>
(or without parallel_case, you can do a lot of one-hot selects, plus assign all-x in the default)
<whitequark>
so having 'x doesn't help you get better
<mwk>
quite possibly, yes
<mwk>
it may unlock more optimizations somewhere?
<whitequark>
mhm, true
<d1b2>
<Olivier Galibert> that muxing is currently my only use of Repl. I'm always annoying by principle when doing the same thing ends ups using longer words 🙂
<d1b2>
<Olivier Galibert> but it looks like the Repl-and or the pileof-Mux with zero (which is ugly too) is the best solution
<d1b2>
<Olivier Galibert> I wonder if my use of that is specific of my reimplementation of nmos/cmos circuits, or if it's really often useful in "normal" designs.
<whitequark>
no, that sort of thing is fairly common. it's used in amaranth-soc already
<d1b2>
<Olivier Galibert> Would a one-hot-select top level function make sense then?
<whitequark>
absolutely not, let's not add more stuff to the prelude
<whitequark>
it already has too much
<d1b2>
<Olivier Galibert> ok
<d1b2>
<Olivier Galibert> couldn't be an override of Mux, e.g. give it 2n+1 parameters for any n>=1 instead of always 3?
<d1b2>
<Olivier Galibert> extension more than override
<whitequark>
I don't think that's a good idea either
<whitequark>
it's another case where one is overly focusing on some very specific use case and making it expressible in a concise way, but not necessarily noticing that this adds cognitive burden on everyone reading any use of Mux
<d1b2>
<Olivier Galibert> Yeah
<d1b2>
<Olivier Galibert> of course Mux itself is (b & a.replicate(b.shape)) | (c & (~a).replicate(b.shape)), but writing Mux is nice. I wonder where the line should be. Good thing I'm not the one who has to decide 🙂
<d1b2>
<Olivier Galibert> (b.shape is subtly incorrect, but we all know that)
<whitequark>
Mux is actually a primitive
<whitequark>
it's lowered by the backend directly to a $mux cell if we're talking about yosys
<whitequark>
and you end up with a?b:c in verilog
<whitequark>
Repl is also a primitive, which could be used to output a {n{v}} construct in Verilog, but because it roundtrips through Yosys it doesn't happen
<whitequark>
and also any half-decently written backend should automatically detect replications anyway
<d1b2>
<Olivier Galibert> hopefully 🙂
<d1b2>
<Olivier Galibert> of course I could always write (b & a) | (c & ~a) if I make a signed(1)
<d1b2>
<Olivier Galibert> but now that would be kinda horrible
<d1b2>
<Olivier Galibert> subtletly is amusing but Bad in practice
<whitequark>
what would be?
<d1b2>
<Olivier Galibert> using the sign-extension to have an automatically sized replication done
<whitequark>
huh? I don't understand where sign extension comes in
<whitequark>
oh, the Matrix bridge has dropped a message
<d1b2>
<Olivier Galibert> og
<d1b2>
<Olivier Galibert> oh
<d1b2>
<Olivier Galibert> I understand your reaction then 🙂
<whitequark>
that's a little cursed but I guess it works?
<whitequark>
it's explicitly specified to do what you want
<d1b2>
<Olivier Galibert> yeah, taht's the problem, it works. I'm old enough to know it's not a good idea, maintainability-wise though
<d1b2>
<Olivier Galibert> 20 years ago I would probably have done it 🙂
<d1b2>
<Olivier Galibert> It’s interesting that rtlil has an explicit Mux, because from what I see it’s not really a hardware primitive, at least since cmos
<whitequark>
it's for optimization
<whitequark>
also there's patterns that need to be inferred from input Verilog and you recognize those by looking at $mux and $pmux (which is just Verilog if much of the time)
<d1b2>
<Olivier Galibert> Oh, it’s very verilog then