ChanServ changed the topic of #prjunnamed to: FPGA toolchain project · rule #0 of prjunnamed: no one should ever burn out building software · https://github.com/prjunnamed/prjunnamed · logs: https://libera.irclog.whitequark.org/prjunnamed
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+7/-1/±12] https://github.com/prjunnamed/prjunnamed/compare/b670b4a64b2c...63e5ff734e96
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 63e5ff7 - Implement memory cells.
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±2] https://github.com/prjunnamed/prjunnamed/compare/63e5ff734e96...0ae52cf4ad4b
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 0ae52cf - Implement printing and parsing for memory port relations.
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 2 commits to main [+0/-0/±6] https://github.com/prjunnamed/prjunnamed/compare/0ae52cf4ad4b...c6009530ae68
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark c4b465a - Implement printing and parsing for memory init values.
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi c600953 - Implement Yosys JSON import and export for memories.
widlarizerEmilJT has joined #prjunnamed
<widlarizerEmilJT> I think that the endgame digital hardware IR design would avoid writing cell input signal width validation code or rather would have constraints part of the cell definition. Not sure how feasible the software engineering of that would be though, even if Rust wasn't the language of choice
<whitequark[cis]> isn't MLIR trying that?
<whitequark[cis]> this is an obvious use case of dependent typing if we're putting it into the type system, but the experience of using dependent types tends to be so bad i can't imagine where it would be worth it
<whitequark[cis]> maybe if you're writing a toolchain in lean
<widlarizerEmilJT> Exactly
<whitequark[cis]> you could also write some cursed derive-style macro to autogenerate validation code but i don't feel like this ultimately achieves anything?
<whitequark[cis]> well, besides making your compile times worse and adding dtolnay into your dependency tree
<widlarizerEmilJT> Rewrite MLIR? Build in MLIR? In an academic language? Prrrobably not the best idea for actually pulling off a hardware toolchain that people want to contribute to
<whitequark[cis]> this is why we are not doing it
<whitequark[cis]> prjunnamed is also written in a pretty basic dialect of rust, we barely even use parametric polymorphism
<whitequark[cis]> you could go really wild with it and complicated type-safe graph representations and const generics and stuff and we just don't, because it's too hard to understand and work with
<widlarizerEmilJT> Yeah it looks friendly from what I've seen so far
<whitequark[cis]> there is a bunch of semi-obscure code that is basically required because of some questionable Rust design decisions, but it's utility code that's very formulaic, so i think it's not an issue (all the From impls for example)
<whitequark[cis]> and there is the pattern matching engine, which i've tried to keep really simple and i think mostly succeeded, but it does involve pretty... expansive types
<whitequark[cis]> works just as well as yosys!
<whitequark[cis]> works on both coarse and fine cells!
<widlarizerEmilJT> Yeah this rules
<whitequark[cis]> first it tries to match the flop as a whole, if that doesn't work--e.g. because it's connected to muxes that have incompatible select inputs--it bitblasts the flop and the mux
<whitequark[cis]> moreover it transparently handles cases like "a coarse flop's D input is connected to a concatenation of fine muxes with the same S input"
<whitequark[cis]> comparing prjunnamed/yosys running generic opt and following it by simplemap has prjunnamed beat yosys by a pretty significant margin
<whitequark[cis]> (this doesn't translate to optimization wins for siliconblue since our LUT mapper is a lot worse than abc area-wise, but it's something)
<whitequark[cis]> (area and delay, actually)
<widlarizerEmilJT> Does this bitblast the dff unconditionally even if no opt is done to it?
<whitequark[cis]> no, if the pattern or its guard fail the test, nothing is done to the dff
<widlarizerEmilJT> Nice
<whitequark[cis]> the pattern's .execute has an accumulator type deal where it constructs a virtual slice of the cell it's matching before passing it on, basically
<whitequark[cis]> this is because match_netlist! doesn't run on cells, it runs on values, which are just random nets you're given
<whitequark[cis]> we do have a few cases where a pattern only succeeds if it's being fed an entire cell in the right order, which is primarily adc
<whitequark[cis]> well and mul and friends
<whitequark[cis]> but the demorgan rule for example will match any netlist that looks right, and capture the right slices, no matter which combination of cells are actually present at the input; they just need to compute the right function
<whitequark[cis]> it will actually replace fine cells with coarse ones if you give it the right inputs
<whitequark[cis]> the whole fine/coarse distinction is treated as a transparent, mostly irrelevant detail throughout the flow, and i'm quite proud of how well this works
<whitequark[cis]> the merge pass (which is written similar to global value numbering) does a clever trick here too: for let's say and, it canonicalizes each output bit to a single-bit-wide cell and puts that into the database, which then causes (if it encounters a cell that computes the same value) it to canonicalize that cell to this one
<whitequark[cis]> it will never create any cells, and it will happily canonicalize a bunch of fine cells to reuse the outputs of a coarse one computing the same function (or the other way around, actually, currently this just depends on "which of these is first in the topological order")
<whitequark[cis]> the split pass, which is basically a bit-level DCE (the word-level DCE is the design.compact() function) will preserve coarseness where it can too. for example in from an and cell where each other output is unused, it will create another and cell that is half as wide
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±4] https://github.com/prjunnamed/prjunnamed/compare/c6009530ae68...8ecb7f225196
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 8ecb7f2 - Improve readability of generic lowering. NFC
<whitequark[cis]> if i look at the output of optimizing boneless, i don't think any of them is bitblasted
<whitequark[cis]> minerva does have some bitblasted dffs, specifically the largest (248, 202, and 142 bit ones)
<whitequark[cis]> i have no idea what it even does to get those. JTAG maybe?
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±1] https://github.com/prjunnamed/prjunnamed/compare/8ecb7f225196...8db9f525f9dd
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 8db9f52 - Improve readability of merge. NFC
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±5] https://github.com/prjunnamed/prjunnamed/compare/8db9f525f9dd...d62dfbce9459
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark d62dfbc - Implement printing and parsing for `match` cells.
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±5] https://github.com/prjunnamed/prjunnamed/compare/d62dfbce9459...38913bfaf0c8
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 38913bf - Implement printing and parsing for `assign` cells.
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+4/-1/±4] https://github.com/prjunnamed/prjunnamed/compare/38913bfaf0c8...051a6799ad58
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 051a679 - Reorganize prjunnamed-netlist.
<povikMartinPovie> Assign { value: Value, enable: Net, update: Value }, // insert non-X bits from updateintovalueifenable``
<povikMartinPovie> this semantics makes me worried as it violates the principle that X bit semantics are a superset of 0/1 semantics
<whitequark[cis]> we do not plan to perform any transformations on the assign cell
<povikMartinPovie> * Assign { value: Value, enable: Net, update: Value }, // insert non-X bits from update into value if enable
<whitequark[cis]> so i don't think that matters in practice. but yes, it's kind of weirdly designed
<povikMartinPovie> right
<whitequark[cis]> Wanda made the point that we're losing explicitly assigned X's
<whitequark[cis]> so i think i just need to redesign it
<povikMartinPovie> I think we could find other places where it matters in practice, if you do an assign from an operation which can result in all-X as an edge case, you don't mean to ignore the assign when that happens
<povikMartinPovie> if value were a parameter then I would say fine, but when it's not I hope you redesign it
<povikMartinPovie> is the match/assign duo meant to represent decision trees without loss of information?
<whitequark[cis]> yes
<whitequark[cis]> i based it on the amaranth nir and simplified it somewhat
<whitequark[cis]> (nir doesn't have X, for example, but it also splits match into two cells, and assign is more complex)
<povikMartinPovie> btw can I attach an attribute to a multiplier in your IR?
<Wanda[cis]> yeah the match cell is good
<Wanda[cis]> I'm going to try modifying NIR to use it
<Wanda[cis]> povikMartinPovie: we don't really have metadata just yet
<whitequark[cis]> we don't have attributes yet
<Wanda[cis]> some of this stuff is already planned
<povikMartinPovie> just planning-wise, the answer seems to be yes
<Wanda[cis]> mhm
<Wanda[cis]> we definitely need a metadata system
<Wanda[cis]> however, it's very non-obvious what the design should be
<Wanda[cis]> attaching a key-value dict with attributes identified by random strings displeases me greatly and I'd honestly prefer we not have this
<Wanda[cis]> though it's probably unavoidable for some use cases (involving integrating with foreign toolchains we dn't want to know too much about)
<whitequark[cis]> well we could (and should) quarantine them in a !n = foreign(k=v, k=v...) metadata key
<whitequark[cis]> * well we could (and should) quarantine them in a !n = foreign("k"=v, "k"=v...) metadata key
<povikMartinPovie> haha, building a long pole
<whitequark[cis]> but i'm also not sure how exactly to list our own metadata attached to our own cells
<whitequark[cis]> is that an idiom?
<Wanda[cis]> btw the plan is to stuff a verilog backend into unnamed, and use as amaranth backend for emitting verilog
<Wanda[cis]> so we do need to be able to just attach random shit to nodes
<povikMartinPovie> not sure; just that you want to distance yourself from the usual attribute mess
<Wanda[cis]> (at least some of them)
<Wanda[cis]> well
<Wanda[cis]> have you looked at the ram_style code in memory_libmap
<povikMartinPovie> yes
<Wanda[cis]> I want parsing this shit to be done in one place and I want the memory inference code to be able to just grab a proper metadata node with well-defined format
<Wanda[cis]> without wondering whether the fucking attribute is spelled syn_ram_style or ram_style or rAm_StYlE
<whitequark[cis]> i think that at the very least we need, rather than strings, to have a metadata enum
<whitequark[cis]> but then there's the question of how to handle ordering or retrieval from multiple metadatas or smth
<whitequark[cis]> we'll get there
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±4] https://github.com/prjunnamed/prjunnamed/compare/051a6799ad58...c1a707c1e8f6
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark c1a707c - Redesign `assign` cell to avoid violating undef semantics.
<whitequark[cis]> done
<povikMartinPovie> what's the value here vs a mux?
<whitequark[cis]> pattern matching on assign is unambiguous
<whitequark[cis]> if you see an assign it is a part of a decision tree and can be treated as such
<whitequark[cis]> if you have a normal mux it can come from anywhere in the frontend
<whitequark[cis]> (the same applies to match, actually, which has a trivial lowering to eq plus a one hot decoder-encoder)
<whitequark[cis]> they add no expressive power and in fact the point is the opposite: they delineate bits of a netlist where the expressive power is less than a random sea of gates
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±4] https://github.com/prjunnamed/prjunnamed/compare/c1a707c1e8f6...cc30bb9bc33a
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark cc30bb9 - Add or-pattern support to `match`.
<Wanda[cis]> mmm
<Wanda[cis]> I like the new match cell
<Wanda[cis]> it simplifies so much shit in NIR
<whitequark[cis]> nice
<Wanda[cis]> the new NIR passes tests
<whitequark[cis]> niiiice
<whitequark[cis]> NNIR
<whitequark[cis]> Peano number it
<Wanda[cis]> ... reminds me of my old rules-ng-ng project
<Wanda[cis]> I think I wanted to design a rules-ng-ng-ng too but I never got around to it
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi pushed 1 commit to main [+0/-0/±1] https://github.com/prjunnamed/prjunnamed/compare/cc30bb9bc33a...d0a276e134f9
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi d0a276e - siliconblue: Improve GND and VCC import.