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
<Wanda[cis]> not to mention the shit that'd have to happen on writes
<Wanda[cis]> (also consider that the same rule applies to reading/writing memories when an X address is involved)
<leocassarani[m]> Right, whereas a ? b : c is just going to select c if a is X — so it won't propagate it
<Wanda[cis]> X ? a : a is always a
<Wanda[cis]> which is actually the rule that allows safe transformation of or/and to mux
<Wanda[cis]> and, by extension, to LUTs
<leocassarani[m]> Isn't whatever ? a : a always a tautologically? Or did you mean a : b?
<Wanda[cis]> it is
<Wanda[cis]> that's the whole point
<Wanda[cis]> tautologies are a tricky thing when X is involved
<leocassarani[m]> Right, I've just found this
<Wanda[cis]> (X ? a : a) === a is a rule that allows useful transformations with muxes
<Wanda[cis]> but also.
<Wanda[cis]> consider that it also makes `a ? b : c` → `(a & b) | (~a & c)` an invalid transformation
<leocassarani[m]> Right, of course
<Wanda[cis]> which is very annoying because that's a very useful transformation when lowering multiplexer trees to LUT-based architectures
<Wanda[cis]> (it allows you to break down the mux into three gates, and then pack the three gates into different LUTs where there's space)
<galibert[m]> makes me think you need to de-xify early and often
<galibert[m]> because a lot of what would make sense blows up in the presence of x
<Wanda[cis]> you don't understand.
<galibert[m]> I probably don't
<galibert[m]> feels to me a lot like pointer aliasing, a thing that's uesful 1% of the time and pessimizes a lot of stuff the other 99%
<whitequark[cis]> what
<Wanda[cis]> <Wanda[cis]> "consider that it also makes `a ?..." <- this is not just a weird mathematical oddity.
<Wanda[cis]> it is, in fact, going to fuck you over in hardware when there's asynchronous logic involved
<Wanda[cis]> also known as glitches
<Wanda[cis]> actual, physical wires have states that are not 0 or 1.
<whitequark[cis]> i'm actually not fully convinced that these weird states can be represented with the same X as our don't-care-for-optimization X
<whitequark[cis]> back when thinking about the topic for Amaranth reasons, i've thought that Verilog's X hides three concepts within: 0/1-but-not-known X1 (uninitialized memory), don't-care-for-optimization X2 (explicitly inserted don't cares), and not-binary-at-runtime X3 (invalid states)
<whitequark[cis]> obviously X1 and X2 are incompatible: optimizations legal under X2 are breaking your design when in reality you have X1
<Wanda[cis]> mhm.
<galibert[m]> X3 requires propagation, while X2 can be removed whenever you feel like it
<Wanda[cis]> that's all incredibly tricky to model properly
<galibert[m]> and X1 is somewhere in between
<whitequark[cis]> whether X3 and X2 produce the same result depends entirely on your precise definition for both, so it can't be said apriori which transformations preserve X2≡X3 and which do not
<galibert[m]> X1= don't know, X2=don't care, X3=what a mess
<whitequark[cis]> the choices i've made for Amaranth were: X3 isn't possible because Amaranth is a purely digital simulator; X1 should be introduced; X2 is arbitrarily excluded because it's too difficult to model
<whitequark[cis]> * to model within the context of that particular language
<Wanda[cis]> X3 has the nice property that you can forget about it while you're within a nice synchronous clock domain
<galibert[m]> could synth-level optimization passes introduce X2s?
<Wanda[cis]> computing stuff over things that came out of Qs and will end up at Ds
<whitequark[cis]> introduce how? they can introduce X2's because you can replace-all-uses-with of a buf X with X and there might be quite many uses
<Wanda[cis]> ie. the mux-to-and/or transformation above is valid if there's no async logic involved
<whitequark[cis]> hm. right, that's true
<whitequark[cis]> having transformations that are valid iff they don't involve PIs in the fanin is weird but I guess?
<galibert[m]> Can you actually write a CDC if you have X3 introduced by the clock difference? Or is that fundamentally unfixable?
<whitequark[cis]> i don't understand the question
<galibert[m]> If something notices that two signals are not in the same clock domain and turns a ff output on the wrong clock into X3, that can't be fixed, right?
<Wanda[cis]> do you understand how an FF synchronizer works?
<galibert[m]> probabilistically, is what I understand
<whitequark[cis]> i think turning X3 into an X2 is probably not a transformation i want to have in my toolchain
<Wanda[cis]> yes, there's a small probability that the X3 state will propagate into your domain and fuck you over
<whitequark[cis]> probabilistically, yes! but we don't really want to model this in a synthesis toolchain, so we assert that "two FFs is enough" and there will be no X3 at the 2nd Q
<Wanda[cis]> but in practice a synchronizer is a device that turns X3 into... well, kinda X1
<galibert[m]> with the probability going down with easy successive ff
<whitequark[cis]> in any case i can't imagine why you would want to statically detect X3 and turn it into X1/X2 in the synthesizer. feels like that's something you should print a diagnostic on
<galibert[m]> s/easy/each
<whitequark[cis]> unless you have verilog-induced brain damage
<galibert[m]> I have fpga-induced brain damage, my zeros and ones are well-defined
<whitequark[cis]> like that's my whole point about having three separate X semantics: they should be treated quite differently!
<galibert[m]> no asics schenanigans for me
<whitequark[cis]> i'm pretty sure FPGAs also exist in the physical world and as such feature voltages between 0 and vdd
<whitequark[cis]> i even have one on my desk here!
<whitequark[cis]> ok fine it's a lot more than one
<galibert[m]> Nah nah nah I can't heaaaaaaaaaaaaaaar you :-)
<Wanda[cis]> ... 7 FPGAs on desk apparently
<whitequark[cis]> why'd you need synchronizers if voltages were always exactly 0 or vdd?
<galibert[m]> the outside world is bad mmm'kay? I don't wanna go there
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±3] https://github.com/prjunnamed/prjunnamed/compare/c7d3187a07ba...46ab3db7b4f2
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 46ab3db - Update netlist parser to use voids.
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi pushed 1 commit to main [+0/-0/±4] https://github.com/prjunnamed/prjunnamed/compare/46ab3db7b4f2...ce0ae2c83255
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi ce0ae2c - Flip concatenation order to keep everyone on their toes.
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi pushed 1 commit to main [+3/-0/±1] https://github.com/prjunnamed/prjunnamed/compare/ce0ae2c83255...f6adb815ff1f
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi f6adb81 - siliconblue: move tests to `tests` directory. NFCI
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±2] https://github.com/prjunnamed/prjunnamed/compare/f6adb815ff1f...7ba0a1665c59
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 7ba0a16 - Fix up remaining concatenations after ce0ae2c8.
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi pushed 1 commit to main [+0/-0/±1] https://github.com/prjunnamed/prjunnamed/compare/7ba0a1665c59...df64a7299461
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi df64a72 - Implement more detailed statistics for memories.
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±2] https://github.com/prjunnamed/prjunnamed/compare/df64a7299461...a4ca7a487e6c
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark a4ca7a4 - Fix up remaining concatenations after ce0ae2c8.
sajattack[m]1 has quit [Quit: Idle timeout reached: 172800s]
sdomi has quit [Ping timeout: 276 seconds]
sdomi has joined #prjunnamed
<mei[m]> <whitequark[cis]> "obviously X1 and X2 are incompat..." <- could you give a concrete example of this? i'm struggling to see why this is the case
<whitequark[cis]> imagine a %0:1 = buf X
<whitequark[cis]> under our model, you can replace every use of %0 with X. then, under our model, you can treat that new X as 1 in one place and 0 in another
<mei[m]> what's buf?
<whitequark[cis]> cell whose output is the same as the input
<whitequark[cis]> it works the same with %0:1 = not X
<whitequark[cis]> whitequark[cis]: this transformation is semantics-preserving if `%0` is `X`, and semantics-breaking if `%0` is "either `1` or `0` but you don't know which"
<mei[m]> okay, hmm
<mei[m]> so the use-case of X1 is representing flip flops without a reset value?
<whitequark[cis]> sort of but i feel the way you state it is a bit backwards?
<whitequark[cis]> it's not a concept i'm introducing because it has uses; it's a concept i'm introducing because verilog's model is confusing
<whitequark[cis]> like, "i would not use X to represent that but now that we're already doing it, i would split off this one aspect of Verilog's X that does this so that i can name it independently"
<whitequark[cis]> i suppose unnamed does actually use X to represent uninitialized memory locations (and also don't cares in patterns), both of which is somewhat displeasing conceptually because it feels like a similar muddying of waters
<whitequark[cis]> but at least we can define the semantics of memory reads to "never create an X regardless of what the init value is" for example
<whitequark[cis]> like if we do some sort of optimization that inlines memory contents into the netlist (i believe Vivado does this) then X's in init value should just become 0's (or 1's, i suppose, at the discretion of the pass, but a specific value)
<whitequark[cis]> actually, thinking about it, we already do flop optimizations which propagate X's in reset value into the netlist (which is different from the init value, so not the same thing)
<whitequark[cis]> (a dff whose reset is always asserted, or... hold on. i found a bug i think
<whitequark[cis]> no, i did not find a bug, nevermind)
<whitequark[cis]> i was looking for an optimization that replaces a never-clocked, never-cleared flip-flop with its init value, and we don't have one
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±1] https://github.com/prjunnamed/prjunnamed/compare/a4ca7a487e6c...b2cb222f0a3f
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark b2cb222 - Reimplement decision in terms of modifying match matrices. NFCI
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 2 commits to main [+0/-0/±2] https://github.com/prjunnamed/prjunnamed/compare/b2cb222f0a3f...6ecec98f84b8
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 26ca425 - Use an actual heuristic for column selection while lowering decision trees.
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 6ecec98 - Do not slice match matrices per-output when emitting decision trees.
<whitequark[cis]> okay, i think this should be an improvement on yosys
<povikMartinPovie> you mean what proc_mux does? looking forward to try it out
<whitequark[cis]> yeah
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±1] https://github.com/prjunnamed/prjunnamed/compare/6ecec98f84b8...d79d9c6969c6
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark d79d9c6 - Simplify lowering of shifts. NFCI
<whitequark[cis]> it's still not very smart and definitely not optimal
<whitequark[cis]> but it's at least trying to pick the best column
<whitequark[cis]> I'm also wondering if translating it to a SOP more explicitly would help...
<povikMartinPovie> I was thinking I would try it on some flows I care about, but for that we are missing a yosys-slang -> match/assign path
<povikMartinPovie> I don't think you import yosys processes
<whitequark[cis]> it's not possible to do that from Yosys JSON
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±1] https://github.com/prjunnamed/prjunnamed/compare/d79d9c6969c6...12a38f070444
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 12a38f0 - Simplify decision pass. NFCI
<whitequark[cis]> translating it to SOP made it worse
<galibert[m]> what's SOP?
<whitequark[cis]> sum of products
<whitequark[cis]> well, really the decision pass produces a sum of products, conceptually speaking, no matter what you do
<whitequark[cis]> but i've tried going from "the eq cell multiplies the inputs" to "the and and not cells are emitted directly" and it made things worse for unclear reason
<whitequark[cis]> theoretically, the latter will produce smaller netlists because the tests in the decision tree that are closer to the root are reused
<whitequark[cis]> i.e. if you have five cases that depend on some three bits being 111, the current main branch will create three eq cells testing all of those bits, and the code I just wrote would make two and cells and then and them with the rest of the tests
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+1/-1/±3] https://github.com/prjunnamed/prjunnamed/compare/12a38f070444...172a909e7102
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 172a909 - Put `Trit` and `Const` together, as well as `Net` and `Value`. NFC
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi pushed 1 commit to main [+1/-0/±2] https://github.com/prjunnamed/prjunnamed/compare/172a909e7102...900d5ddbf306
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi 900d5dd - Add last-resort memory lowering pass.
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi pushed 1 commit to main [+0/-0/±1] https://github.com/prjunnamed/prjunnamed/compare/900d5ddbf306...7adb158205c3
<_whitenotifier-4> [prjunnamed/prjunnamed] wanda-phi 7adb158 - lower_memory: fix up wide write ports.
cr1901 has quit [Read error: Connection reset by peer]
cr1901 has joined #prjunnamed
<whitequark[cis]> just ran a few glasgow applets using prjunnamed
<whitequark[cis]> works fine, although some of them don't really pass timing
<galibert[m]> You have the full chain or you pass stuff to nextpnr ?
<whitequark[cis]> nextpnr of course
<galibert[m]> Wasn’t sure, you two are making fast progress
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±1] https://github.com/prjunnamed/prjunnamed/compare/7adb158205c3...88212c351cdb
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 88212c3 - siliconblue: lower all memories to DFFs.
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark pushed 1 commit to main [+0/-0/±2] https://github.com/prjunnamed/prjunnamed/compare/88212c351cdb...644ede6be149
<_whitenotifier-4> [prjunnamed/prjunnamed] whitequark 644ede6 - netlist: improve value chunk printing.
<leocassarani[m]> In your textual IR representation, is it an error to skip cell indices, or does it set those bits to X? For a contrived example, %0:1 = buf 0\n%2:1 = buf %1+0 (I may have misunderstood though)
<whitequark[cis]> neither
<whitequark[cis]> you can skip them but it's an error to refer to the skipped ones
<whitequark[cis]> i.e. your example is invalid but it could be made valid with %0:1 = buf 0\n%2:1 = buf %0
<leocassarani[m]> That sounds nice I think, better than silently having unexpected Xs all over the place
<whitequark[cis]> (and actually while they're currently required to be monotonically increasing, i'll relax that)
<leocassarani[m]> Oh right, the +0 is optional
anuejn_ has joined #prjunnamed
anuejn has quit [Ping timeout: 252 seconds]