<_whitenotifier-4>
[prjunnamed/amaranth] whitequark 046b32a - back.yosys_json: new backend.
<_whitenotifier-4>
[prjunnamed/amaranth] wanda-phi facc20f - back.unnamed: new backend.
<_whitenotifier-4>
[prjunnamed/amaranth] ... and 2 more commits.
<whitequark[cis]>
huh, we have a cursed kinda behavior; amaranth outputs instances of SB_IO and friends into the netlist as instances rather than target cells (which is fine) but we never call target.import after parsing from a string
<whitequark[cis]>
so they just... end up remaining instances until the end of the flow
<whitequark[cis]>
* up remaining those instances, * instances (with very limited set of ports) until the
<leocassarani[m]>
tbh I think your use of remain was grammatical, I can say "I remain myself", i.e. I haven't changed — and you were saying SB_IO etc remain those instances
<whitequark[cis]>
right, that was the idea at least
<galibert[m]>
Remain works less as transitive ( I remain the book)
<mei[m]>
oh, that's what the intended parse was!
<mei[m]>
(good morning! apparently my sleep schedule is in California)
<Wanda[cis]>
hi mei
<Wanda[cis]>
mei: btw, have I ever discussed the memory inference code with you?
<Wanda[cis]>
trying to think about it is giving me intense OI flashbacks so it sounds something you'd enjoy
<Wanda[cis]>
* it sounds like something you'd
<mei[m]>
you mentioned some stuff about memory inference as a concept
<mei[m]>
the coherence thingies, mostly
<mei[m]>
read before write etc
<Wanda[cis]>
... coherence?
<Wanda[cis]>
mmm
<Wanda[cis]>
so, yeah, there's some basic legalization like that, which needs to be performed before you can mp the memory to target primitives
<Wanda[cis]>
but that's not the really hard part
<Wanda[cis]>
the part that I was really struggling with the first time around (2021, when I was writing memory_libmap) was matching the geometry of the source cell to the target cell
<Wanda[cis]>
I think I understood whatever the hell was going on for just long enough to write the final part of the pass, then the whole thing has been completely erased from my memory
<Wanda[cis]>
now. it appears to actually work. or at least I never got any complaints. maybe because nobody actually understood this shit enough to complain.
<Wanda[cis]>
that said. memory_libmap is an absolutely batshit piece of code that should not ever be replicated. it has been made in a fit of clinical insanity. mostly OCD-induced.
<Wanda[cis]>
oh right, and I think the Wanda that designed all that stuff did so while going through a psychotic episode and kinda disintegrated not long afterwards. probably unrelated, but still.
<Wanda[cis]>
so. problem statement. you have a memory with some dimensions and read and write ports, and you have a target cell with some dimensions and read and write ports. you can assume that the number of ports and general attributes of the ports have already been matched up. all that remains is fixing up the dimensions.
<Wanda[cis]>
there are several things that can make a memory not match a target cell
<Wanda[cis]>
1. the memory can be too wide for target cell. that one's easy, you fix it by replicating the target cell as many times as needed and just spliting the data bits over the replicated cells.
<Wanda[cis]>
2. the memory can be too deep for target cell. you fix it by trimming however many address bits from the MSB side, replicating the target cell, then using the trimmed address bits to drive muxes / write enable decoders
<mei[m]>
do fpgas generally have a bunch of different types of memory cells, or like, 1 or 2 at most?
<Wanda[cis]>
--- here shit gets actually complicated ---
<Wanda[cis]>
3. the memory can have restrictions on write enable groupings. like, say, one write enable for every 9 bits. and the restrictions vary between selected port widths, so you have to pick a width and then maybe waste some data lanes entirely to pad the thing.
<Wanda[cis]>
4. you can have ports of varying widths, and have to match up with the target port widths by emitting muxes and write address decoders until you end up with something actually supported
<Wanda[cis]>
mei[m]: 3 types at most. however, the memory cells tend to be highly configurable.
<Wanda[cis]>
for one, you can select various port width combinations
<Wanda[cis]>
now. the major design mistake that I have made in memory_libmap is that I have decided to make a general solution that handles all possible memories.
<Wanda[cis]>
it involves a DSL where you specify exactly just what capabilities your memory cell has, in all possible configurations, and the pass will figure out a way to lower it or die trying.
<Wanda[cis]>
this includes arbitrarily complex cases with 5 different kinds of ports with completely mismatched capabilities and allowed port widths and whatnot.
<Wanda[cis]>
the result will be optimal btw.
<Wanda[cis]>
(optimal given a shitty heuristic cost function I made up on the spot in the hopes that someone more experienced would help me make a better one later, but uhh that never happened)
<Wanda[cis]>
anyway. the decision for unnamed is that there will be no generic pass. there will be some reusable bits and pieces that target-specific code can call into, but ultimately we'll have target-specific inference code.
<Wanda[cis]>
this greatly simplifies the whole thing, as we can just focus on the several specific kinds of memory that actually exist on FPGAs; a dozen of them or so
<gatecat[m]>
I guess that would make things like dealing with extra register stages easier, too?
widlarizerEmilJT has joined #prjunnamed
<widlarizerEmilJT>
Hmmm I just fixed a dangling pointer in memory_libmap this week but managed to avoid reading too much of the pass. Now it sounds kind of interesting though
<Wanda[cis]>
<gatecat[m]> "I guess that would make things..." <- yes, and not just that
<Wanda[cis]>
there's a bunch of stuff that was left off from memory_libmap because a) describing it in target-independent way was way too complex, b) the DSL and the pass were already ridiculously unwieldy
<Wanda[cis]>
pipeline registers at the outputs, fancier forms of cascading such as the ultraram stuff, hard CS lines like ECP* has that could just be wired straight to some address lines instead of requiring more multiplexers, etc.
<Wanda[cis]>
and the calculus for all of that changes completely when your memory lowering is driven by target-specific code. you can just write a few dozen lines to hook this stuff up directly instead of thinking of "generic ways"
<gatecat[m]>
yes, that all makes good sense
<Wanda[cis]>
oh, and pipeline registers also never happened because there was the opinion that this should be handled later in the flow, to have some opportunity for retiming
<Wanda[cis]>
except. well. retiming.
mupuf has quit [Remote host closed the connection]
mupuf has joined #prjunnamed
mupuf has quit [Remote host closed the connection]
mupuf has joined #prjunnamed
mupuf has quit [Remote host closed the connection]
mupuf has joined #prjunnamed
mupuf has quit [Remote host closed the connection]