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
lf has quit [Ping timeout: 260 seconds]
lf_ has joined #amaranth-lang
nyanotech has quit [Quit: No Ping reply in 180 seconds.]
galibert[m] has quit [Quit: Idle timeout reached: 172800s]
nyanotech has joined #amaranth-lang
Wanda[cis] has quit [Quit: Idle timeout reached: 172800s]
whitequark[cis] has quit [Quit: Idle timeout reached: 172800s]
Degi_ has joined #amaranth-lang
Degi has quit [Ping timeout: 264 seconds]
Degi_ is now known as Degi
byteit101 has joined #amaranth-lang
<_whitenotifier-3> [amaranth] whitequark opened issue #1079: Refactor `Fragment` to have a mapping from statements to domains - https://github.com/amaranth-lang/amaranth/issues/1079
<_whitenotifier-3> [amaranth] whitequark created branch remove-subclassing - https://github.com/amaranth-lang/amaranth
<_whitenotifier-3> [amaranth] whitequark opened pull request #1080: Remove subclassing of `AnyValue` and `Property` - https://github.com/amaranth-lang/amaranth/pull/1080
<_whitenotifier-c> [amaranth] codecov[bot] commented on pull request #1080: Remove subclassing of `AnyValue` and `Property` - https://github.com/amaranth-lang/amaranth/pull/1080#issuecomment-1926278890
<_whitenotifier-3> [amaranth] github-merge-queue[bot] created branch gh-readonly-queue/main/pr-1080-115954b4d957b4ba642ad056ab1670bf5d185fb6 - https://github.com/amaranth-lang/amaranth
<_whitenotifier-c> [amaranth-lang/amaranth] whitequark 1fe7bd0 - hdl: remove subclassing of `AnyValue` and `Property`.
<_whitenotifier-3> [amaranth-lang/amaranth] github-merge-queue[bot] pushed 1 commit to main [+0/-0/±5] https://github.com/amaranth-lang/amaranth/compare/115954b4d957...1fe7bd010f99
<_whitenotifier-c> [amaranth] whitequark closed pull request #1080: Remove subclassing of `AnyValue` and `Property` - https://github.com/amaranth-lang/amaranth/pull/1080
<_whitenotifier-c> [amaranth] github-merge-queue[bot] deleted branch gh-readonly-queue/main/pr-1080-115954b4d957b4ba642ad056ab1670bf5d185fb6 - https://github.com/amaranth-lang/amaranth
<_whitenotifier-c> [amaranth] whitequark deleted branch remove-subclassing - https://github.com/amaranth-lang/amaranth
<_whitenotifier-c> [amaranth-lang/amaranth-lang.github.io] whitequark pushed 1 commit to main [+0/-0/±34] https://github.com/amaranth-lang/amaranth-lang.github.io/compare/ff1f0a2f934f...c078cc8d2f1f
<_whitenotifier-3> [amaranth-lang/amaranth-lang.github.io] github-merge-queue[bot] c078cc8 - Deploying to main from @ amaranth-lang/amaranth@1fe7bd010f9984407d53daee04556b62194181fd 🚀
byteit101 has quit [Remote host closed the connection]
byteit101 has joined #amaranth-lang
<_whitenotifier-c> [amaranth] whitequark commented on issue #1066: Improve code generation strategy for FSMs - https://github.com/amaranth-lang/amaranth/issues/1066#issuecomment-1926455899
oter has quit [Ping timeout: 256 seconds]
oter has joined #amaranth-lang
_whitenotifier-c has quit [Ping timeout: 268 seconds]
cyrozap_ has joined #amaranth-lang
qookie_ has joined #amaranth-lang
nak_ has joined #amaranth-lang
nak has quit [*.net *.split]
cyrozap has quit [*.net *.split]
miek has quit [*.net *.split]
qookie has quit [*.net *.split]
miek has joined #amaranth-lang
dyniec has quit [Ping timeout: 264 seconds]
dyniec has joined #amaranth-lang
notgull has joined #amaranth-lang
notgull has quit [Ping timeout: 252 seconds]
jfng[m] has quit [Quit: Idle timeout reached: 172800s]
jn_ is now known as jn
notgull has joined #amaranth-lang
mwk has quit [Ping timeout: 260 seconds]
mwk has joined #amaranth-lang
qookie_ has quit [Quit: https://quassel-irc.org - Chat comfortably. Anywhere.]
qookie has joined #amaranth-lang
notgull has quit [Ping timeout: 264 seconds]
whitequark[cis] has joined #amaranth-lang
<whitequark[cis]> good evening everyone, it is the time for our weekly Amaranth meeting
galibert[m] has joined #amaranth-lang
<galibert[m]> good evening to you too
<whitequark[cis]> today we have many RFCs on the agenda: https://github.com/amaranth-lang/rfcs/pulls?q=is%3Apr+is%3Aopen+label%3Ameta%3Anominated+label%3Aarea%3Acore. I would like to start with the infrastructure RFCs that bring incremental change to the language and use the remaining time for some of the other proposals
<whitequark[cis]> who is attending?
Wanda[cis] has joined #amaranth-lang
<Wanda[cis]> meow
zyp[m] has joined #amaranth-lang
<zyp[m]> I am
<cr1901> me
jfng[m] has joined #amaranth-lang
<jfng[m]> o/
<galibert[m]> infrastructure is which one?
Chips4MakersakaS has joined #amaranth-lang
<Chips4MakersakaS> o/
<whitequark[cis]> the ones that touch the HDL rather than the stdlib
<Wanda[cis]> small-scale cruft like 43 and 46
<whitequark[cis]> the first one on the agenda is RFC 46: "Change Shape.cast(range(1)) to unsigned(0)" https://github.com/amaranth-lang/rfcs/pull/46 https://github.com/wanda-phi/rfcs/blob/shape-range-1/text/0046-shape-range-1.md
<whitequark[cis]> please add your comments or disposition: merge or close
<Wanda[cis]> merge; not sure what to do about bits_for
<zyp[m]> merge
<whitequark[cis]> this one is almost too small to be an RFC, but seeing as it's a change to some of the most core bits of the language, it's probably OK that it is one
<whitequark[cis]> mine is merge
<whitequark[cis]> I'm happy to leave bits_for as it is until a later point
<galibert[m]> merge, what's wrong with bits_for btw?
<jfng[m]> merge
<Chips4MakersakaS> merge
<Wanda[cis]> (but also I don't believe we actually need to deal with bits_for now)
<cr1901> merge
<whitequark[cis]> galibert: "it has weird behavior". we can discuss after the meeting
<Wanda[cis]> galibert[m]: `bits_for(0) == 0` is what caused this issue in the first place
<galibert[m]> works for me
<Wanda[cis]> er
<Wanda[cis]> s/0/1/
<whitequark[cis]> RFC 46: merge, without changes
<whitequark[cis]> this RFC has been discussed several times before and I had to rewrite much of its text, though without changing the underlying proposal
<whitequark[cis]> I've added a much longer motivation section that explains in detail and with executable examples why the existing API is bad
<whitequark[cis]> this is a blocker for both async simulator functions and having helpers like fifo.read()
<galibert[m]> Does it handle multi-domain? I don't see a syntax example for that
<whitequark[cis]> it doesn't do anything special for single-domain.
<zyp[m]> yield Tick(domain)
<Wanda[cis]> my disposition on this one has been "merge" for 4 years and remains so
<cr1901> It'll take me some getting used to, but I don't have any good reason _not_ to merge, so... merge
<zyp[m]> merge
<Wanda[cis]> ie. it's the thing that makes testbenches actually work
<galibert[m]> Took me a while to understand it, and I forgot part of the explanation by now, but I remember it was good, so merge
<whitequark[cis]> cr1901: I expect you'll have a much easier time with the new API tbh
<cr1901> ack
<whitequark[cis]> it's what you intuitively expect, instead of the pipelined version of that
* cr1901 nods
<jfng[m]> merge, will be very helpful for testbenches of bus primitives
<Chips4MakersakaS> merge from me also although I feel there is much improvement possible in the API. If I ever find the time...
<_whitenotifier-3> [rfcs] whitequark commented on pull request #46: Add RFC for `Shape.cast(range(1))` change. - https://github.com/amaranth-lang/rfcs/pull/46#issuecomment-1927506246
<whitequark[cis]> Chips4Makers (aka Staf Verhaegen): this is definitely true and RFC 27 is only meant as a stepping stone to enable further work
<whitequark[cis]> e.g. zyp's
<zyp[m]> RFC 36 is about improving the simulator API
<whitequark[cis]> I expect that relatively few people will use add_testbench with not an async function, and async testbenches have a different API already
<cr1901> I have one god-awful Verilog testbench using non-synthesizable constructs, that will require add_comb_process to port. So this is a good step
<cr1901> This is a single data point, but: The drawback isn't a drawback to me precisely _because_ Signal already behaves this way. So merge unless other ppl have comments.
_whitenotifier-5 has joined #amaranth-lang
<_whitenotifier-5> [rfcs] whitequark commented on pull request #27: Testbench functions for the simulator - https://github.com/amaranth-lang/rfcs/pull/27#issuecomment-1927510772
<_whitenotifier-5> [amaranth] wanda-phi opened issue #1081: Tracking issue for RFC 46: Change `Shape.cast(range(1))` to `unsigned(0)` - https://github.com/amaranth-lang/amaranth/issues/1081
<galibert[m]> Could unsigned(8).const(42) exists too while we're at it? Make no difference?
<galibert[m]> s/exists/exist/
<whitequark[cis]> this is really just about making Signal and Const behave symmetrically
<jfng[m]> merge
<zyp[m]> galibert[m]: it's less useful, because you couldn't do e.g. `range(16).const(4)`
<whitequark[cis]> galibert: shapes are not currently implementing ShapeCastable just like values do not implement ValueCastable. that would be a different change, I think
<galibert[m]> range(16) isn't a Shape
<galibert[m]> is it?
<whitequark[cis]> and yeah what zyp says
<Chips4MakersakaS> merge
<whitequark[cis]> so we have currently three categories: shape-castable, shape, and all other shape-likes. we may reduce that to two eventually
<Wanda[cis]> I think this is technically a breaking change, but only in kinda insane circumstances
<Wanda[cis]> merge
<galibert[m]> merge, but if at all possible it would be nice to reduce the differences between shape-castable and shape (and value-castable vs. value), to make extensions even less abstraction-leaking
<whitequark[cis]> personally I think that is an entirely viable direction to move the language in and I'm happy to vote merge on a different RFC that proposes it
<whitequark[cis]> my interest in getting this done quickly is my documentation work
<whitequark[cis]> my vote is merge
<whitequark[cis]> okay, disposition on RFC 42: merge (I think everyone voted)
<whitequark[cis]> next item on the agenda is RFC 45: "Move hdl.Memory to lib.Memory" https://github.com/amaranth-lang/rfcs/pull/45 https://github.com/whitequark/amaranth-rfcs/blob/lib-memory/text/0000-lib-memory.md
<whitequark[cis]> this is a fairly big RFC that doesn't bring almost any new functionality itself (it addresses some issues with transparency) but fixes a lot of longstanding weirdness about memories
<galibert[m]> can hdl refer to lib for deprecation without anything blowing up?
<whitequark[cis]> yeah
<galibert[m]> ok good
<cr1901> >an array of Signals (which is also how its simulation is internally implemented) <-- weren't we trying to move away from this b/c of a perf problem? If so, will that make Memory _more_ special/weird than it already is?
<whitequark[cis]> there's no issue on the implementation side; only on the contractual side
<whitequark[cis]> (though the implementation gets a little dirty)
<galibert[m]> and can something in lib create a rtlil primitive?
<Wanda[cis]> I like this RFC, but there's bits regarding sim that I feel we may want to address
<_whitenotifier-3> [rfcs] whitequark commented on pull request #42: Add an RFC for `Const` from shape-castable. - https://github.com/amaranth-lang/rfcs/pull/42#issuecomment-1927526016
<zyp[m]> galibert[m]: that'll still be `hdl.MemoryInstance` AIUI
<Wanda[cis]> the MemoryTolken primitive specifically
<Wanda[cis]> s/MemoryTolken/`MemoryToken`/
<galibert[m]> (not 100% sure how the conversion works, but afair it was incestuous in the Values implementation)
<galibert[m]> Ah, so lib.Memory will use undocumented/here be dragons stuff from hdl?
<whitequark[cis]> no, the point of the RFC is to exactly avoid that
<whitequark[cis]> hdl.MemoryInstance will be documented, although discouraged from use
<Wanda[cis]> so, I have a draft PR open, https://github.com/amaranth-lang/amaranth/pull/1078 ; it implements MemoryInstance according to this RFC and moves the memory sim away from array towards native support
<Wanda[cis]> except the RFC as stated doesn't quite support simulation, we needed to add a "memory identity token" marker class that is used to essentially thread the unique memory identifier across elaboration and simulator
<galibert[m]> I'm sure the answer is in the rfc but I'm a little lost in it, what will be added to .submodules after the rfc? The memory? The ports? Both?
<zyp[m]> just the memory
<zyp[m]> ports will just be interfaces
<Wanda[cis]> the memory
<Wanda[cis]> ports should have never been elaboratable to begin with
<galibert[m]> that's saner than the current situation
<whitequark[cis]> Wanda: so, some of the deeper implementatino-tied simulation bits have been intentionally left undefined, since that interface is something we expect most people won't use
<whitequark[cis]> s/implementatino/implementation/
<Wanda[cis]> we have mismatched MemoryInstance signature.
<whitequark[cis]> ah?
<Wanda[cis]> well it needs the token?
<whitequark[cis]> oh I see
<Wanda[cis]> like, if we're documenting the MemoryInstance interface, let's document one that is actually usable
<galibert[m]> Can I vote "merge once Wanda is happy"? :-)
<whitequark[cis]> this isn't documentation, this is an RFC
<whitequark[cis]> considering that the interface is explicitly not covered by our stability guarantee I think we can just add the token or whatever we decide to call it
<Wanda[cis]> fair
<whitequark[cis]> I can't imagine anyone's view on whether this is the right approach changing depending on minutae of exactly how the simulator talks to it
<whitequark[cis]> please do take a look at Unresolved questions
<whitequark[cis]> the first two especially
<zyp[m]> Memory should have empty signature (or no signature at all, could be Elaboratable instead of Component), the future DeclarativeMemory should have ports in signature
<galibert[m]> I'm not 100% sure that conceptually the ports are part of the signature
<whitequark[cis]> yeah, I think it should probably have empty signatuer
<whitequark[cis]> s/signatuer/signature/
<cr1901> Agreed, b/c I would immediately try to use a non-empty signature interchangeably with ports
<cr1901> which would lead to pain
<whitequark[cis]> it doesn't really fit any other way with the imperative interface anyway
<jfng[m]> in this imperative pattern (not just `Memory`, but also bus decoders, etc); having an empty signature allows it to still have some metadata attached
<galibert[m]> I'm not convinced by the rules on init=. Eventual inderminate initialization should be explicitely requested for, don't be C.
<jfng[m]> jfng[m]: so i don't think `Elaboratable` would be suitable
<Chips4MakersakaS> For ASICs memories will most of the time not support initialization. So having init now mandatory means that for ASICs memories currently will only be able to be compiled to flops if one wants to follow API strictly.
<zyp[m]> jfng[m]: fair point, I agree
<whitequark[cis]> Chips4Makers (aka Staf Verhaegen): this is the status quo; this RFC actually introduces a path towards ASIC memories by defining `init=` semantics in a way that eventually allow uninitialized ones
<whitequark[cis]> galibert: unlike C we are not actually going to introduce this functionality until the simulator(s) have support for dealing with uninitialized memory (think built-in msan)
<galibert[m]> you're not going to run a full riscv program on the simulator though
<whitequark[cis]> huh? of course you would
* cr1901 has
<cr1901> many times
<galibert[m]> yeah, I guess you would :-)
<whitequark[cis]> thing is, FPGA BRAMs are actually a very big exception in that they allow initialization, and even then it doesn't persist after reset
<whitequark[cis]> so your code already must deal with initialization if it targets some types of FPGA RAMs that can't do that, or with post-power-on reset, or if it targets ASICs
<galibert[m]> so, do you expect that future amaranth will start all signals as uninitialized instead of zero?
<whitequark[cis]> even if you do supply init= you do still have to think about initialization except in a small subset of cases
<cr1901> >all signals as uninitialized That would be a disaster
<whitequark[cis]> only reset_less signals
<whitequark[cis]> signals can be initialized at reset, memories cannot (I am sure you are aware that no one makes SRAM cells with a reset input)
<Chips4MakersakaS> whitequark[cis]: I think you do that by assuming value is random even if simulation thinks it is always 0.
<whitequark[cis]> correct; your code should, in most cases, already be robust to having uninitialized values
<whitequark[cis]> (none of the discussion above applies to ROMs, of course, which work the same on FPGAs or ASICs)
<galibert[m]> Except when you use a memory as boot rom of course
<galibert[m]> yeah
<whitequark[cis]> * uninitialized values in a memory
<whitequark[cis]> the docs are going to loudly call out the limitations on init= and how you should deal with those
<galibert[m]> C's experience makes it frightening that the default behaviour when you don't say anything is to get what's essentially UB, but it may be different in HDL land
<zyp[m]> does memory.init need to be mutable?
<whitequark[cis]> galibert: no, we are explicitly not letting this become UB, and having a memory write port basically inhibits memory optimization in all toolchains I can think of
<whitequark[cis]> zyp: strictly speaking no but this can be pretty convenient
<whitequark[cis]> actually, no, it has
<whitequark[cis]> it's tricky to make a memory with holes otherwise
<whitequark[cis]> * a memory initializer with holes
<galibert[m]> zyp: it could be nice once we get a little more introspection to init things like boot roms from whatever instantiates the top level rather than trying to find a way to pass down the information to where the Memory itself is instantiated
<cr1901> re: immutability... can init accept a dict() for holes?
<whitequark[cis]> yeah, I think being able to overwrite the bootrom contents after creating the design but before elaboration is valuable
<whitequark[cis]> cr1901: that sounds like a nightmare since you now have to deal with overlaps
<cr1901> init = { range(0,2) = val, range(3,4) = val2 }
<cr1901> why can't you disallow overlaps?
<whitequark[cis]> wtf
<whitequark[cis]> no
<whitequark[cis]> just... no
<zyp[m]> okay, I don't see anything in the RFC that I object to, so my vote is merge
<whitequark[cis]> nothing else anywhere in Python uses that syntax
<Chips4MakersakaS> For boot ROM you may want to use a single mask programmable ROM so you can change with ordering one mask and not redoing the full RTL2GDS. But I think we are deviating...
<whitequark[cis]> let's not invent a weird slice indexing syntax for memory.init and nothing else whatsoever, that also allows overlaps in ways that simply mutating the memory doesn't
<cr1901> whitequark[cis]: s/=/:/, since I forgot how to do a Python dict apparently
<cr1901> you can't hash ranges, can you?
<whitequark[cis]> you can
<whitequark[cis]> what you propose works technically, I just think this is a terrible idea syntactically
<cr1901> And yea, I can see overlaps being annoying with that syntax
<cr1901> you'd have to check every memory for overlaps w/ that syntax
<whitequark[cis]> it's actually more about this not being a Python syntax but a one-off syntax for lib.memory specifically
<galibert[m]> and the off-by-one errors will be amusing (not)
<whitequark[cis]> there is no justification for having that one-off syntax in lib.memory and nowhere else
<whitequark[cis]> you can already do memory.init[0:2] = 1 with the existing proposal
<whitequark[cis]> the dict syntax is just sugar for a subset of mutation (are integer keys allowed too? then perhaps not a subset) which you have to state all upfront
<whitequark[cis]> and because of overlaps, it actually has the semantics of mutation, just in a weird looking way
<jfng[m]> what do `r_ports` and `w_ports` return ? a list of ports, and port indices are just their index in the list ?
<whitequark[cis]> jfng: port indices appear nowhere in `lib.memory`, those are only for `MemoryInstance`
<whitequark[cis]> they return port objects
<cr1901> Oh... right re: overlaps being mutability. Nevermind then.
<whitequark[cis]> the meeting is coming to an end, does anyone else have any questions that need an answer before a vote?
<Wanda[cis]> I vote for merge, no changes
<jfng[m]> whitequark[cis]: yeah, i'm thinking of how to get indices for the `transparent_for=` parameter; i guess one could just use the return value of `.write_port()` or something
<galibert[m]> merge
<cr1901> merge
<whitequark[cis]> jfng: you give ports to `ReadPort(transparent_for=)`
<Chips4MakersakaS> merge
<jfng[m]> ah, i misread mb
<whitequark[cis]> and yeah you use the return value of .write_port()
<jfng[m]> merge
<galibert[m]> Some day we can add some swichable_with=<port> for memory ports where you can either read or write but not at the same time, but iirc yosys doesn't handle that yet
<whitequark[cis]> Chips4Makers (aka Staf Verhaegen): btw, one thing that this RFC allows is lowering memories to something that is not a Verilog unpacked array, which permits ASIC implementations where you have a precompiled SRAM block
<galibert[m]> that rfc does not preclude it in any case
<Wanda[cis]> galibert[m]: it's actually handled by horrifying amount of magic
<whitequark[cis]> zyp: I take it the behavior of `granularity` with `ArrayLayout` seems good to you?
<whitequark[cis]> galibert: I think Yosys already handles this with a SAT solver
<zyp[m]> whitequark[cis]: yes
<Wanda[cis]> if yosys can prove, with a SAT solver, that a read port and a write port that share an address input can never be active at the same time, it can assign them to the same hardware port
<galibert[m]> Wanda: Well, I like explicit :-)
<whitequark[cis]> disposition on RFC 45: merge, with no textual changes
<Wanda[cis]> the problem with explicit here is that the exact rules for what you can do become really hardware dependent
<galibert[m]> (use case, framebuffer on a bus at 50Mhz with video output at 135MHz on the same dual-port ram)
<whitequark[cis]> galibert: unfortunately that complicates semantics in case you say that and then actually use them simultaneously
<galibert[m]> Catherine: you get to keep all 256 pieces?
<jfng[m]> whitequark[cis]: > transparent_for must be a list of write port indices that this read port should be transparent with
<jfng[m]> i didn't misread, actually ? (doesn't change my vote)
<whitequark[cis]> the meeting has come to a close. thanks everyone, this has been a productive one, even though we haven't been able to visit everything on the agenda
<whitequark[cis]> galibert: didn't we just decide to not be C?
<Wanda[cis]> jfng[m]: > <@jfng:matrix.org> > transparent_for must be a list of write port indices that this read port should be transparent with
<Wanda[cis]> > i didn't misread, actually ? (doesn't change my vote)
<Wanda[cis]> `transparent_for` is made of `WritePort` for `lib.Memnory` and of raw ints for the low-level `MemoryInstance`
<galibert[m]> Catherine: nah, you didn't change the init= stuff, so you do want to be C :-P
<Chips4MakersakaS> For ASICs a SRAM with single R/W port is much smaller area than SRAM with read and write port (typically around 40% in area).
<whitequark[cis]> galibert: not true, operating on uninitialized values in Amaranth has defined behavior, unlike in C
<Wanda[cis]> in both cases, the corresponding .write_port() function returns whatever you need to stuff into transparent_for
<jfng[m]> i see
<galibert[m]> right now uninitialized values don't exist in amaranth, so... :-)
<whitequark[cis]> galibert: while your thing would have proper UB-like behavior that I'm trying to eradicate from the language as much as possible
<whitequark[cis]> sure they do, it's the value of a reset_less signal after a domain reset
<whitequark[cis]> they just aren't handled properly
<galibert[m]> aren't asic srams random at POR?
<whitequark[cis]> one other thing with potentially UB-like behavior I'm planning to eradicate is the current attrs dictionary; it should be replaced with something like platform.add_unsafe_attribute(what, attrs) to make it clear that it's super easy to break your design with them
<Chips4MakersakaS> galibert[m]: They are.
<whitequark[cis]> galibert: they're semi-random; most cells will come up in the same state usually, I think, and some are random
<whitequark[cis]> depending on the small variations in transistor sizes
<whitequark[cis]> (provided you properly drained the device of power and waited for a while; after a warm reset it's random)
<whitequark[cis]> what I'm trying to draw a distinction between here is undefined values (values which the optimizer can use to break your circuit) and indeterminate values (values that will only break your circuit if your logic isn't prepared to handle them)
<whitequark[cis]> Amaranth code already has to contend with indeterminate values in both Signal and Memory, so very little changes there, except for the ability to eventually opt-in into ASIC memory inference
<whitequark[cis]> (which this particular RFC just enables, as init= is still mandatory)
<galibert[m]> C had a fucklot of errors due to indeterminate values before optimizers went insane
<whitequark[cis]> yes, which is why the Amaranth simulator should do X-propagation for indeterminate values, to detect these errors which already exist in current code
<Wanda[cis]> whitequark[cis]: I thought this was well-defined to be "no change"? like we have code in glasgow that actually relies on that
<cr1901> Fun fact: There's a SNES game that crashes 1/256 of the time on real hardware based on the POR values of RAM :). Some accurate SNES emulators do, in fact, emulate this lmao
<Chips4MakersakaS> Going AFK now and prepare dinner...
<whitequark[cis]> Wanda: that depends on an external invariant (your clock tree)
<whitequark[cis]> in general, if you consider one domain in isolation, it's indeterminate
<whitequark[cis]> but it can be determinate in a larger system
<Wanda[cis]> but, I agree, amaranth does still have ways to create undefined values, and they're not really exorcisable
<whitequark[cis]> meanwhile, Amaranth code currently does not ever have to deal with undefined values, except for cases where you misuse an Instance, add a weird attribute, or ... I think those two are all?
<whitequark[cis]> I guess when some external code passes you one
<Wanda[cis]> create Memory with depth of 3, read it at address of 3; what happens is entirely dependent on synth tool
<whitequark[cis]> Wanda: ... oh, that will actually produce an 'x. we should probably handle that explicitly
<Wanda[cis]> it may alias a random other memory cell, be tied to const, etc.
<galibert[m]> or it may have been rounded up to 4
<whitequark[cis]> (by adding a comparator and a mux)
<whitequark[cis]> galibert: as you can see, my position on the places where you can get UB in Amaranth is "fix, even at a performance cost"
<whitequark[cis]> it's just that uninit memory contents isn't that
<galibert[m]> Well, UB was the wrong term there, but uninit contents have always been a plague in C
<cr1901> Wanda[cis]: I'm having a parse fail... what is "this" in "I thought this was well-defined to be "no change""?
<whitequark[cis]> it is UB in C
<whitequark[cis]> it's just that it's not UB in Amaranth
<Wanda[cis]> cr1901: the semantics of a reset_less signal
<galibert[m]> cr1901: reset on reset_less signal
<whitequark[cis]> and we kind of have to keep it around if we want Amaranth to be a serious contender for ASIC work, which I do want it to be
<galibert[m]> yeah but it was the wrong term in amaranth's context
<whitequark[cis]> right
<galibert[m]> I wasn't arguing about not having it, I was arguing about for just being "no init parameter" but instead "uninit=True"
<galibert[m]> * about for not just being
<galibert[m]> perfectly normal and supported but you have to explicitely ask for it
<whitequark[cis]> my main objection to that is that uninit is the typical case of a memory
<whitequark[cis]> you should be always prepared to handle an uninit memory when writing code not tied to a specific FPGA technology
<whitequark[cis]> in something like C, the use of an uninitialized variable is always a bug. it's never legal, nor is it ever wanted
<whitequark[cis]> in Amaranth the use of an uninitialized memory is both legal and desirable often
<galibert[m]> Well, wasn't it openssl which stupidly wanted it?
<whitequark[cis]> so? openssl was plainly wrong
<galibert[m]> I'm not sure it's desirable even with amaranth to read a memory that has not yet been initialized
<whitequark[cis]> also, doing what they did in Amaranth is actually somewhat well-defined (SRAMs are a shitty source of randomness but the compiler isn't going to break your code for using it)
<whitequark[cis]> desirable? maybe not. avoidable? no
<whitequark[cis]> if you have a CPU using an iCE40 SPRAM for its main memory, it will inevitably read uninitialized memory contents, and that has to be well-defined
<whitequark[cis]> (because there is no way to initialize that FPGA memory)
<galibert[m]> beware though, you have a tendency to think that people who are going to use amaranth are extremely competent. I have my doubts
<Wanda[cis]> reading unitialised SRAMs is explicitly desirable for PUF purposes, actually
<Wanda[cis]> but I feel this is deviating really far from the point
<galibert[m]> PUF?
<whitequark[cis]> I don't really think I have such a tendency, considering that I've been systematically eradicating any sharp corners from the language even at a significant cost
<Wanda[cis]> we have to support uninitialized memory, and we have to use them like everywhere in eg. stdlib, because that's what ASICs support
<Wanda[cis]> there's no feasible way around this fact of life
<whitequark[cis]> though it's not about competency as I see it (I don't see people who are proud of their perceived ability to use C as "competent", I see it as hubris)
<whitequark[cis]> yeah, what Wanda says
<galibert[m]> Wanda: and I'm just saying to add a way to distinguish between "yeah, I know it is/can be initialized" and "damn I forgot to add init=[]"
<galibert[m]> * Wanda: and I'm just saying to add a way to distinguish between "yeah, I know it is/can be uninitialized" and "damn I forgot to add init=\[\]"
<whitequark[cis]> well, you can comment on it whenever there is a proposal to make init= actually optional
<galibert[m]> But that's a think where we can easily agree to disagree and it won't at all be a problem :-)
<whitequark[cis]> which this one isn't, despite all of this length discussion
<whitequark[cis]> s/length/lengthy/
<whitequark[cis]> in fact, it ensures that basically all Amaranth code will have an explicit init= argument, training everyone in the use of that pattern long before we even consider introducing anything like that
<whitequark[cis]> (how's that for "being C"?)
<galibert[m]> "When support for indeterminate values is added to Amaranth at a later point, the init argument will become optional, and not providing init or providing init=None will leave the memory filled with indeterminate values."
<galibert[m]> I was reacting to what's written in the RFC :-)
<galibert[m]> It is arguably already proposing to make it optional
<whitequark[cis]> that would still require another RFC by our policy, precisely for this reason
<whitequark[cis]> ("[first-class] support for indeterminate values" is a major user-visible change)
<galibert[m]> It's way too late for language lawyering, and I like that RFC anyway :-)
<whitequark[cis]> it's not even clear exactly how that will play out; there's been different proposals (my X-prop proposal, Staf's randomization proposal, others perhaps)
<whitequark[cis]> hey, you started it
<galibert[m]> yeah, and I'm finishing it if you're ok with it :-)
<whitequark[cis]> yeah
<_whitenotifier-5> [rfcs] whitequark commented on pull request #45: Move `hdl.memory` to `lib.memory` and extend it - https://github.com/amaranth-lang/rfcs/pull/45#issuecomment-1927752244
<_whitenotifier-5> [amaranth-lang/rfcs] whitequark pushed 2 commits to main [+2/-0/±0] https://github.com/amaranth-lang/rfcs/compare/e10875bca9bf...1d4c81ba6b0e
<_whitenotifier-3> [amaranth-lang/rfcs] wanda-phi d6c50a2 - Add RFC for `Shape.cast(range(1))` change.
<_whitenotifier-5> [amaranth-lang/rfcs] whitequark 1d4c81b - RFC #36: Change `Shape.cast(range(1))` to `unsigned(0)`
<_whitenotifier-5> [rfcs] whitequark closed pull request #46: Add RFC for `Shape.cast(range(1))` change. - https://github.com/amaranth-lang/rfcs/pull/46
<_whitenotifier-3> [amaranth-lang/amaranth-lang.github.io] whitequark pushed 1 commit to main [+1/-0/±31] https://github.com/amaranth-lang/amaranth-lang.github.io/compare/c078cc8d2f1f...ec1300ed85ac
<_whitenotifier-5> [amaranth-lang/amaranth-lang.github.io] whitequark ec1300e - Deploying to main from @ amaranth-lang/rfcs@1d4c81ba6b0e222cbc16e8712c83d3439070c7bc 🚀
<_whitenotifier-3> [amaranth] whitequark opened issue #1082: Tracking issue for RFC 27: Testbench functions for the simulator - https://github.com/amaranth-lang/amaranth/issues/1082
<whitequark[cis]> galibert: btw, I am tentatively putting clock domain rework on the roadmap for Amaranth 0.6
<galibert[m]> Cool
<whitequark[cis]> the new IR is nearing completion, so we should have all the infrastructure to build it with
<Wanda[cis]> 0.6?
<galibert[m]> There are a lot of open questions in that rfc, it’s not at all a finished one
<whitequark[cis]> Wanda: yeah. anything wrong with that?
<whitequark[cis]> the version after the next release
<Wanda[cis]> oh, fine with me
<galibert[m]> We can discuss it outside of the fixed meetings to flesh it more if you have the time and the inclination
<Wanda[cis]> just ... I somehow thought you wanted it earlier
<whitequark[cis]> oh, no, it's a huge chunk of work and I want a 0.5 release as soon as we have usable streams
<galibert[m]> Smaller but significant releases is good
<Wanda[cis]> oh, huh.
<galibert[m]> (Not sure we can call streams small, but heh)
<whitequark[cis]> it was never the intent to have years-long release cycle
<whitequark[cis]> I was just ill
<Wanda[cis]> yeah, just
<Wanda[cis]> I looked at 0.5 milestone and
<Wanda[cis]> uh
<Wanda[cis]> nevermind, I think it just looks large?
<whitequark[cis]> it mostly looks large, yes
<_whitenotifier-5> [amaranth-lang/rfcs] whitequark pushed 5 commits to main [+3/-1/±2] https://github.com/amaranth-lang/rfcs/compare/1d4c81ba6b0e...0ab1c2e271ef
<_whitenotifier-3> [amaranth-lang/rfcs] whitequark a846faf - Add an RFC for introducing the concept of testbench processes to the simulator.
<_whitenotifier-3> [amaranth-lang/rfcs] whitequark 6dd7982 - RFC #27: Update to address feedback.
<_whitenotifier-5> [amaranth-lang/rfcs] whitequark c56b613 - Add an RFC for introducing the concept of testbench processes to the simulator.
<_whitenotifier-3> [amaranth-lang/rfcs] ... and 2 more commits.
<_whitenotifier-3> [rfcs] whitequark closed pull request #27: Testbench functions for the simulator - https://github.com/amaranth-lang/rfcs/pull/27
<_whitenotifier-3> [amaranth-lang/amaranth-lang.github.io] whitequark pushed 1 commit to main [+1/-0/±32] https://github.com/amaranth-lang/amaranth-lang.github.io/compare/ec1300ed85ac...e0f4978d2e46
<_whitenotifier-5> [amaranth-lang/amaranth-lang.github.io] whitequark e0f4978 - Deploying to main from @ amaranth-lang/rfcs@0ab1c2e271ef66e2051ba4275577a756ff9aa061 🚀
<whitequark[cis]> Wanda: can you take care of the implementation for RFC 27? I think mine is outdated
<Wanda[cis]> hmmmm, Print cell
<whitequark[cis]> re RFC cell
<Wanda[cis]> I should just go and do it one day
<whitequark[cis]> * re RFC text
<whitequark[cis]> oh yeah, that would be quite welcome
<whitequark[cis]> I think we should probably have a quick discussion on format strings and general implementation strategy first
<Wanda[cis]> yes
<whitequark[cis]> (not today)
<Wanda[cis]> and there's a bunch of infrastructure that needs to land first
<Wanda[cis]> well, not needs to, but
<Wanda[cis]> maybe let's not make it more painful than it has to be
<_whitenotifier-5> [amaranth] whitequark opened issue #1083: Tracking issue for RFC 45: Move `hdl.Memory` to `lib.Memory` - https://github.com/amaranth-lang/amaranth/issues/1083
<_whitenotifier-5> [amaranth] whitequark commented on pull request #1077: Implement RFC 46: Change `Shape.cast(range(1))` to `unsigned(0)`. - https://github.com/amaranth-lang/amaranth/pull/1077#issuecomment-1927793243
<zyp[m]> <whitequark[cis]> "Wanda: can you take care of..." <- there's a rebased commit and a fixup in my RFC 36 branch
<_whitenotifier-3> [amaranth] wanda-phi commented on pull request #1077: Implement RFC 46: Change `Shape.cast(range(1))` to `unsigned(0)`. - https://github.com/amaranth-lang/amaranth/pull/1077#issuecomment-1927797522
<galibert[m]> amaranth is still moving away infrastructure-wise from its migen root, it looks like it will eventually land in a nice place
<whitequark[cis]> we're quite far from anything migen was already
<galibert[m]> yeah, but still moving
<Wanda[cis]> I think scopes are going to be the big one
<Wanda[cis]> a really major change
<galibert[m]> scopes?
<Wanda[cis]> a... hm
<Wanda[cis]> a kinda unified replacement for control flow, submodules, and domain shenanigans
<Wanda[cis]> I don't know how to describe it well
<galibert[m]> well, I will be interested to see it once it happens
<Wanda[cis]> it ties in heavily to any clock domain refactors actually
<whitequark[cis]> a scope is a binding for late bound names (clock, reset, enable signals) coupled with a decision tree that can use those signals
<galibert[m]> decision tree as enable-ish m.If?
<whitequark[cis]> it makes it explicit which names are bound to which signals, regardless of clock domain propagation behavior, and also let us ditch AST rewriting entirely
<whitequark[cis]> something like that (it's closer to the currently internal Switch() class, just less... bad)
<galibert[m]> that promises to be interesting
<_whitenotifier-3> [amaranth] whitequark commented on pull request #1077: Implement RFC 46: Change `Shape.cast(range(1))` to `unsigned(0)`. - https://github.com/amaranth-lang/amaranth/pull/1077#issuecomment-1927815252
<whitequark[cis]> it can start out as an internal simplification, without an RFC (though it might eventually be something we want to make public)
<whitequark[cis]> because it means that we can fairly freely change the behavior of the designer-visible ClockDomain() construct
<whitequark[cis]> EnableInserter and ResetInserter would simply wrap the module into a scope with a new binding for enable or reset signal
byteit101 has quit [Quit: http://quassel-irc.org - Chat comfortably. Anywhere.]
<_whitenotifier-3> [rfcs] whitequark closed pull request #45: Move `hdl.memory` to `lib.memory` and extend it - https://github.com/amaranth-lang/rfcs/pull/45
<_whitenotifier-5> [amaranth-lang/rfcs] whitequark pushed 2 commits to main [+2/-0/±2] https://github.com/amaranth-lang/rfcs/compare/0ab1c2e271ef...0ca51f2b774b
<_whitenotifier-3> [amaranth-lang/rfcs] whitequark 94230aa - Add RFC for moving `hdl.memory` to `lib.memory`.
<_whitenotifier-3> [amaranth-lang/rfcs] whitequark 0ca51f2 - RFC #45: Move `hdl.memory` to `lib.memory`
<whitequark[cis]> galibert: I've made it much more explicit that the exact semantics of `init=` is left to a future RFC
<_whitenotifier-3> [amaranth-lang/amaranth-lang.github.io] whitequark pushed 1 commit to main [+1/-0/±33] https://github.com/amaranth-lang/amaranth-lang.github.io/compare/e0f4978d2e46...63547e4b7474
<_whitenotifier-5> [amaranth-lang/amaranth-lang.github.io] whitequark 63547e4 - Deploying to main from @ amaranth-lang/rfcs@0ca51f2b774bdd33ba614ffc376ec6ba1666c740 🚀
<whitequark[cis]> the only thing I was interested in with RFC 45 is to make sure that everyone writes it out explicitly when they want the memory to be initialized
<whitequark[cis]> whether we make any or all of init=/uninit= a required parameter is something to be determined later, as well as the exact semantics of partially-initialized memories
<whitequark[cis]> (which is a thing one might well want to use to make smaller bitstreams, for example)
<galibert[m]> on cyclonev you can't not init and all-zero is the best compression-wise
<whitequark[cis]> if it turns out that the toolchains do insane things with partially initialized memories like warp your logic if you access the wrong element (I don't think they do, but I do know Xilinx has some memory optimizations for ROMs), we might even go for an explicit opt-in-only unsafe_uninit= or something
<galibert[m]> fwiw
<whitequark[cis]> it varies from FPGA to FPGA
<cr1901> What does late bound refer to specifically? "The var doesn't need to actually exist in memory at use"?
<galibert[m]> it's interesting too, because they disable the checksum on the bitstream rows where there's m10k ram
<galibert[m]> cr1901: domain names are solved late
<whitequark[cis]> ClockSignal() can refer to a signal that doesn't yet exist, but is expected to exist at _late_r point
<galibert[m]> a module has all its domain names "dangling" from the uses of m.d.mumble +=, and they're solved in-context later
<galibert[m]> DomainRenamer changes those dangling names, *Inserter pushes the signal in front, it's in fact quite weird to think about them, it's not really going top-to-bottom as you'd expect in a usual inheritance setup
<cr1901> Well, that's more intuitive than the C# focused answers I'm seeing on "late binding"
byteit101 has joined #amaranth-lang
Lord_Nightmare has quit [Quit: ZNC - http://znc.in]
<whitequark[cis]> "late binding" is a general programming language design concept
<whitequark[cis]> Python late binds everything so it's unremarkable
<_whitenotifier-3> [amaranth] wanda-phi commented on pull request #1077: Implement RFC 46: Change `Shape.cast(range(1))` to `unsigned(0)`. - https://github.com/amaranth-lang/amaranth/pull/1077#issuecomment-1927853732
<Wanda[cis]> ... github actions, are you okay
<galibert[m]> Mame use late binding too, but that's yet another (similar though) thing. We have delegates that allow to wrap a call to an object, often a device. When you create the delegate you may not have the object handy, only its name in the device tree. You create the delegate anyway, and at some point in the future all the objects are created and the names are solved in all the delegates so that the calls will work. That's late
<galibert[m]> binding too, binding the target object to the delegate after the delegate was actually created.
<whitequark[cis]> I restarted them
Lord_Nightmare has joined #amaranth-lang
<Wanda[cis]> and they failed again
<whitequark[cis]> hm, keyserver.ubuntu.com seems actually down from here too
<whitequark[cis]> galibert[m]: yep, that's the exact same basic principle as what's happening in Amaranth
<Wanda[cis]> anyhow
<Wanda[cis]> nice work today
<cr1901> >Python late binds everything so it's unremarkable <-- so Amaranth goes further, and allows ClockSignal/ResetSignal to not exist at point of use (whereas Signals, Arrays, etc, need to have a binding in scope when the function containing them is called)?
<galibert[m]> that was an efficient meeting
<Wanda[cis]> that is a bunch of stuff done
<galibert[m]> (and wtf is going on with groupxiv, that makes no sense)
<whitequark[cis]> idk, leaflet does weird things sometimes
<whitequark[cis]> it's intended for globes more than it's intended for flat sheets
<whitequark[cis]> hm, why should I not just embed the actual key in the repo?
<whitequark[cis]> relying on third party keyservers regularly results in this kind of mess
<_whitenotifier-3> [amaranth] whitequark opened issue #1084: Tracking issue for RFC 42: `Const` from shape-castable - https://github.com/amaranth-lang/amaranth/issues/1084
<_whitenotifier-3> [amaranth-lang/rfcs] whitequark pushed 2 commits to main [+2/-0/±0] https://github.com/amaranth-lang/rfcs/compare/0ca51f2b774b...3ba625b73ac1
<_whitenotifier-5> [amaranth-lang/rfcs] zyp 528969f - Add an RFC for `Const` from shape-castable.
<_whitenotifier-3> [amaranth-lang/rfcs] whitequark 3ba625b - RFC #42: `Const` from shape-castable
<_whitenotifier-3> [rfcs] whitequark closed pull request #42: Add an RFC for `Const` from shape-castable. - https://github.com/amaranth-lang/rfcs/pull/42
<_whitenotifier-5> [rfcs] whitequark commented on pull request #42: Add an RFC for `Const` from shape-castable. - https://github.com/amaranth-lang/rfcs/pull/42#issuecomment-1927880518
<_whitenotifier-5> [amaranth-lang/amaranth-lang.github.io] whitequark pushed 1 commit to main [+1/-0/±34] https://github.com/amaranth-lang/amaranth-lang.github.io/compare/63547e4b7474...6d44af915a79
<_whitenotifier-3> [amaranth-lang/amaranth-lang.github.io] whitequark 6d44af9 - Deploying to main from @ amaranth-lang/rfcs@3ba625b73ac13ae9b741d9a898348c5a9f120d23 🚀
<_whitenotifier-3> [rfcs] whitequark commented on pull request #16: A CSR register API for amaranth-soc - https://github.com/amaranth-lang/rfcs/pull/16#issuecomment-1927881268
<_whitenotifier-5> [amaranth] whitequark closed issue #1061: `Const(obj, shape)` should use RFC 9 to cast `obj` to `shape` - https://github.com/amaranth-lang/amaranth/issues/1061
<_whitenotifier-5> [amaranth] whitequark commented on issue #1061: `Const(obj, shape)` should use RFC 9 to cast `obj` to `shape` - https://github.com/amaranth-lang/amaranth/issues/1061#issuecomment-1927885462
<whitequark[cis]> keyserver still down!
<galibert[m]> I’m sure Ubuntu has been brought by Apple and closed down
<galibert[m]> It’s the only sane explanation
<whitequark[cis]> oh, launchpad is down
<whitequark[cis]> like, the entire thing
byteit101 has quit [Quit: http://quassel-irc.org - Chat comfortably. Anywhere.]
byteit101 has joined #amaranth-lang
<Wanda[cis]> seems back up
<Wanda[cis]> I don't think I can retrigger?
<crzwdjk> It's not inevitable that a CPU that uses SPRAM will ever read uninitialized memory. On reset I initialize SPRAM before anything can reach any state where that memory is read. Same idea as having some unsafe code in bare metal Rust to initialize the bss section or whatever.
<crzwdjk> But it probably makes sense to just support uninialized memory
<cr1901> Does yosys or Amaranth add "the guard circuit in front of a BRAM to prevent garbage from being read out for the first clock cycle after reset"?