ChanServ changed the topic of #nmigen to: nMigen hardware description language · code at · logs at · IRC meetings each Monday at 1800 UTC · next meeting August 17th
jaseg has quit [Ping timeout: 246 seconds]
jaseg has joined #nmigen
Degi has quit [Ping timeout: 260 seconds]
Degi has joined #nmigen
PyroPeter has quit [Ping timeout: 260 seconds]
PyroPeter has joined #nmigen
_whitelogger has joined #nmigen
jeanthom has quit [Ping timeout: 256 seconds]
emeb_mac has quit [Ping timeout: 256 seconds]
emeb_mac has joined #nmigen
cr1901_modern has quit [Quit: Leaving.]
cr1901_modern has joined #nmigen
cr1901_modern has quit [Client Quit]
cr1901_modern has joined #nmigen
proteus-guy has joined #nmigen
cr1901_modern1 has joined #nmigen
<_whitenotifier-3> [nmigen-boards] awygle commented on pull request #104: Add OLED connector to -
proteus-guy has quit [Remote host closed the connection]
cr1901_modern has quit [Ping timeout: 240 seconds]
proteus-guy has joined #nmigen
<_whitenotifier-3> [nmigen-boards] awygle commented on pull request #103: Add GPDI pins to -
<_whitenotifier-3> [nmigen-boards] awygle edited a comment on pull request #104: Add OLED connector to -
<awygle> i really thought i'd submitted a pr to fix #328... but apparently not
<_whitenotifier-3> [nmigen] awygle opened pull request #472: Add r_level and w_level to all FIFOs -
<_whitenotifier-3> [nmigen] awygle synchronize pull request #472: Add r_level and w_level to all FIFOs -
<_whitenotifier-3> [nmigen] awygle commented on pull request #472: Add r_level and w_level to all FIFOs -
<awygle> i wrote it and just... never submitted
<awygle> i wonder hwy
proteus-guy has quit [Remote host closed the connection]
zignig has quit [*.net *.split]
trabucayre has quit [*.net *.split]
anuejn has quit [*.net *.split]
agg has quit [*.net *.split]
zignig has joined #nmigen
agg has joined #nmigen
anuejn has joined #nmigen
trabucayre has joined #nmigen
jaseg has quit [Ping timeout: 246 seconds]
jaseg has joined #nmigen
electronic_eel has quit [Ping timeout: 240 seconds]
electronic_eel has joined #nmigen
PyroPeter_ has joined #nmigen
PyroPeter has quit [Ping timeout: 240 seconds]
PyroPeter_ is now known as PyroPeter
cr1901_modern1 has quit [Quit: Leaving.]
cr1901_modern has joined #nmigen
_whitelogger has joined #nmigen
_whitelogger has joined #nmigen
hitomi2507 has joined #nmigen
Asu has joined #nmigen
emeb_mac has quit [Quit: Leaving.]
<pepijndevos> awygle, interesting coincience
<pepijndevos> Now I wonder why LiteX and nMigen both have their own unique boards repo...
<pepijndevos> It contains a lot of the same info, right?
<whitequark> the board interface was completely redesigned for nmigen
<whitequark> in a somewhat more ambitious way
<whitequark> and will probably be redesigned again, looking at feedback from LUNA and beyond
<pepijndevos> I see. yea I learned that LiteX is using old Migen actually
<pepijndevos> uh... is cipo the new miso? what does that stand for...
<pepijndevos> What is the minimum wage of a peripheral?
proteus-guy has joined #nmigen
<_whitenotifier-3> [nmigen] whitequark commented on pull request #472: Add r_level and w_level to all FIFOs -
<_whitenotifier-3> [nmigen] awygle synchronize pull request #472: Add r_level and w_level to all FIFOs -
<_whitenotifier-3> [nmigen] awygle synchronize pull request #472: Add r_level and w_level to all FIFOs -
<_whitenotifier-3> [nmigen] awygle commented on pull request #472: Add r_level and w_level to all FIFOs -
* awygle loves git with all his heart
<awygle> `git push remote branch` should push your currently checked out commit to remote as branch, not randomly grab your local branch named "branch" (which isn't checked out) and push it
<_whitenotifier-3> [nmigen] whitequark commented on pull request #472: Add r_level and w_level to all FIFOs -
<whitequark> the tragic thing is that i have the exact kind of brain damage that makes git easy to understand for me
<whitequark> i mean, it still drives me mad sometimes, but i find it positive overall, so i'm quite certain about the brain damage part
<whitequark> i remember looking at SVN in school and thinking "if this is what version control is like, i will never use it" (and then i discovered git)
<_whitenotifier-3> [nmigen] awygle commented on pull request #472: Add r_level and w_level to all FIFOs -
<whitequark> seems to be the exact opposite of the usual experience
<awygle> in my mind git is (at least) two things
<_whitenotifier-3> [nmigen] whitequark commented on pull request #472: Add r_level and w_level to all FIFOs -
<awygle> the like... general model of verison control, the data structures, etc
<awygle> and the command line tool
<awygle> i quite like the former
<awygle> and i detest the latter
<awygle> someday i'll bother to try like, pijul or hg or something, but for now i just uh... get stuff wrong occasionally
<awygle> also thank you for commenting on that PR so that i stopped obsessively planning to build an additional wall in my apartment at 1am
<whitequark> uhm
<whitequark> why
<awygle> because it is a bad shape
<awygle> i have a giant useless undifferentiated room, instead of like, "a living room" and "a studio"
<pepijndevos> my day barely started and already confusing things happening
<whitequark> oic
<awygle> and i just resigned my lease for another 18 mo
<proteus-guy> awygle, you mean re-signed I presume? Otherwise your intent is to be homeless for 18 months. ;-)
<awygle> and as astonishing as it seems, "frame and drywall a new temporary wall" is somehow the cheapest way to solve this problem
<awygle> (about half the price of "build a divider out of PVC and cloth" and about a third the price of "buy one of the products nominally for this exact use case")
<whitequark> huh
<whitequark> are you going to like... fix it to the house structure?
<awygle> na. compression fit it between ceiling and floor with that foam stuff. something seal
<awygle> sill seal
<whitequark> ohh
<awygle> i _probably_ won't actually do this.... but it does make sense on several axes, and i do have the required skills. it would just probably piss off the apartment people and do bad things to airflow (which already kinda sucks here)
<pepijndevos> ahhhhh I was actually installing m-labs nmigen dog
<pepijndevos> *dohh
<_whitenotifier-3> [nmigen-boards] GuzTech commented on pull request #103: Add GPDI pins to -
<pepijndevos> uh... which AST classes are supposed to have a signed attribute? Not Operator apparently. I can use share, just wondering if this in intentional.
<pepijndevos> *shape
jeanthom has joined #nmigen
proteus-guy has quit [Ping timeout: 264 seconds]
<pepijndevos> uhoh... I might have some weird... bug... or not...
<whitequark> pepijndevos: only the ones which have it themselves
<whitequark> Const, Signal
<pepijndevos> right, if you want to deal with any value you have to use shape().signed
<whitequark> yep
<d1b2> <edbordin> In hindsight I got used to svn because I didn't know any better. Maybe git has infected my mind the same way. The CLI is definitely terrible though imo
<pepijndevos> what is going on???
<pepijndevos> It seems abs wraps my Cat in a mux and then nonesense comes out
<pepijndevos> Of course an identity cast does not *need* to add slices and padding, but it should still work.
<pepijndevos> They still have the same shaped and resolve to the same value, but when I abs them, they behave differently
<lkcl> pepijndevos: there are operator overloads in nmigen
<lkcl> it would help to provide the source code as well
<pepijndevos> lkcl, working on it...
<lkcl> in this particular case, you need these lines (1 sec sending link...)
<lkcl> so when you call abs()
<lkcl> this generates an Abstract Syntax Tree (AST) which, when handed to yosys, will create the hardware needed based on what you "asked for"
<lkcl> which in this case depends on whether the "number" (it's not a number, it's a Signal) is signed or unsigned
<pepijndevos> right right that's what I want... but abs() on my signal vs abs() on my signal wrapped in a no-op Cat does different things
<lkcl> yes - because Cat() knows nothing about signed.
<lkcl> look again at line 245.
<lkcl> if signal is signed, return a Mux
<pepijndevos> look again at line 4 of my paste, which wraps it in a signed
<lkcl> if signal is not signed, do nothing.
<pepijndevos> -16571328 is not exactly "do nothing" either
<lkcl> i really need some source code rather than pdb debug output
<pepijndevos> yea, pushing now...
<pepijndevos> commenting out those lines will break the test_abs test
<pepijndevos> in that case cast will do some useless slicing and padding, which breaks the test.
<lkcl> mmm... brain-melted, to be honest :)
<pepijndevos> I'll try to make a minimal example
<lkcl> the source code of class Cat simply stores the list it is passed. there's nothing saying it should be signed, so i think it's safe to assume that it'll be "unsigned"
<lkcl> ah hang on
<lkcl> can i recommend creating an intermediary signal, there?
<lkcl> or
<lkcl> then return that?
<pepijndevos> uh, sure, but why?
<lkcl> just to see what happens
<lkcl> the AST that is generated has no "analysis" done on it.
<lkcl> what AST you create, that's what gets literally thrown at yosys.
<pepijndevos> try this
<lkcl> if you accumulate an AST that's thousands of objects and pass copies of it around (i've seen people do for-loops like that), then thousands of copies end up being given to yosys
<lkcl> so this is a good example
<lkcl> print(abs(sig2), resolve(abs(sig2)))
<lkcl> (m (>= (s (cat (const 0'd0) (const 9'sd-153))) (const 1'd0)) (s (cat (const 0'd0) (const 9'sd-153))) (- (s (cat (const 0'd0) (const 9'sd-153))))) -359
<lkcl> which is like, whoaaaa.... :)
<lkcl> can you read that? i can't! :)
<pepijndevos> sure, but what can you do? Most of that is just abs()
<pepijndevos> and... it's still wrong
<pepijndevos> you don't even need the empty const btw
<lkcl> put the Cat()'d value into another signal prior to running abs
<pepijndevos> Cat(sig).as_signed() is enough to break it
<lkcl> yes i just tried that, too
* lkcl trying a few things
<pepijndevos> also just - rather than abs
<pepijndevos> this... is informative...
<pepijndevos> I think it has to do with nesting signed values
<lkcl> yeah i made some modifications, set a 5-bit Signal to -2
<lkcl> the answer came up as -30
<lkcl> which in binary is -b11110
<pepijndevos> like... it does the correct invert+1 thing except the sign bit is somehow wrong
<lkcl> this needs reporting as a bug
<pepijndevos> right, will do
<lkcl> gimme 1 sec to copy the modified file online
<lkcl> i modified resolve() so that it can be used to set a value into the target Signal
<lkcl> where abs(some Signal) is done, the answer is correct
<lkcl> however Cat(exact_same_signal), yes the answer goes haywire
<lkcl> the "solution" as i suggested is to copy the Cat()ed thing into a target Signal
<pepijndevos> but that needs an eq that needs to be assigned to some comb/sync thing, right?
<lkcl> and only call abs() on that
<pepijndevos> Not exactly ergonomic in this case
<lkcl> indeed it does
<lkcl> can i recommend looking at a yosys graphviz diagram (show {insertmodule}) on the output from any example that you're doing?
<lkcl> generate a .il file and then examine it
<pepijndevos> sure, I can imagine what that will look like
<lkcl> even on the simplest examples, the graphviz - the use of ASTs that compound like this - should, how can i put it, "freak you out" :)
<lkcl> if yosys was capable of optimising the (repeated) expressions away correctly, i would not mention it
<pepijndevos> uh... wat...
<lkcl> however in complex cases it simply cannot cope
<pepijndevos> okay that sucks.
<pepijndevos> I think the only case where it'll repeat statements is in the mux, but yea... not great
<lkcl> there exists commands _to_ optimise away repeated expressions
<lkcl> daveshah and others more familiar with yosys know what those are, and they typically get called in all synth commands
<daveshah> opt_merge; opt_clean would be a starting point
<daveshah> opt -full for a more aggressive optimisatio
<daveshah> *n
<lkcl> however you need to bear in mind that even if it's successful, the approach in the code you're designing places a huge processing burden on yosys... and you have to trust that it will be successful
<lkcl> thx daveshah
<pepijndevos> right, well... I'll try to minimize my AST a bit later if it becomes a problem.
<lkcl> imagine someone setting up an array of 1,000 objects, in a python for-loop, that do "abs" followed by some more math followed by another Mux followed by...
<lkcl> what's the code designed to do, btw? :)
<pepijndevos> well, I don't see how I'd implement fixed point math without at least generating some AST... it's up to the user to not go crazy haha (i.e. me)
<lkcl> it's a FP system where you can specify arbitrary precision?
<lkcl> (sounds pretty useful)
<pepijndevos> yea, it builds a fixed point type that does the book keeping and casting with arithmic operations.
<lkcl> nice.
<pepijndevos> so if you add two different types obviously it will need some padding and slicing to make it work
<pepijndevos> Best I can do is not do any *useless* padding and slicing.
<lkcl> i did an ieee754fp library in nmigen, parameterised to do FP16, FP32 and FP64
<lkcl> yeah been thinking about how to do transparent (dynamic) SIMD, which needs something similar
<lkcl> we have a class that can do dynamic partitioning of integer operations
<lkcl> however, using it to do partitioned IEEE754 is doing my head in
<lkcl> yes, it comes down to when you want to shift / slice something that is now 16 bits wide (or 11 bit in the case of the FP16 mantissa) and the next cycle you're processing something 32-bit wide (23-bit mantissa)
<lkcl> in your case, you're quite lucky, because (i hope!) it's a static analysis
<lkcl> a "cast" function would be the obvious thing to try to do
<lkcl> however it'd need calling in each of the __add__, __sub__, __ge__ etc. etc. functions to make it "transparent"
<lkcl> hmm...
<pepijndevos> yea, I call cast in each operator
<pepijndevos> And try weakly to avoid doing the cast.
<lkcl> the @operator decorator. nice.
<lkcl> remember to also implement __radd__
<_whitenotifier-3> [nmigen] pepijndevos opened issue #473: Signed math on Cat gives incorrect results -
<lkcl> etc.
<lkcl> you miiight not need them... it depends on whether you're expecting people (you :) ) to do things such as add Const() or add straight Signal() to this
<pepijndevos> lkcl, I don't support adding with ordinary python numbers, so radd is not used
<lkcl> ok. sensible
<lkcl> anyway. nice work.
<pepijndevos> thanks
<lkcl> are you planning to do a formal correctness proof for it?
<lkcl> that'd be interesting
<pepijndevos> lkcl, maaaybe? Would you just load it in yosys and run symbiyosys on it?
<pepijndevos> Or use a python based quickcheck-like tool
<lkcl> pepijndevos: use this;a=blob;f=src/nmutil/;h=dca64ca493c886fd95790b35a38bd2cd3407024e;hb=HEAD
<lkcl> and here's an example
<lkcl> so you can fire everything up from nmigen, using absolutely standard python unittest infrastructure
<lkcl> you don't have to manually walk down all the way to yosys / symbiyosys yourself.
<pepijndevos> though I remember ZipCPU saying formal doesn't deal well with very arithmatic-heavy code, in particular multiplication. But we'll see...
<lkcl> FHDLTestCase was originally in nmigen however whitequark removed it
<pepijndevos> oh... why?
<lkcl> yes we found that the shift formal proof takes... a looong tiiiime
<lkcl> you'll have to ask her when she's back from holiday
<lkcl> we're just in the process of adding a formal proof for the libresoc POWER9 MUL pipeline at the moment.
<lkcl> look forward to the CPU load it causes :)
<pepijndevos> lol
<lkcl> this one's absolutely fine. completes in a perfectly reasonable time
<lkcl> ok. breakfast. at midday.
<pepijndevos> brunch, very fancy
<lkcl> if you can call fish fingers and veg fancy :)
<pepijndevos> Put it on a piece of wood.
<lkcl> ha, i deduce from this (and your first name) that you are from the netherlands? :)
<pepijndevos> lkcl, you are correct, but Charcuterie sounds french to me, why Dutch besides my name?
<lkcl> i lived in den haag for 4 years, i learned that it's become a habit there to post a really nice picture of a meal, to your friends, before eating it
<anuejn> pepijndevos: nice :)
<jeanthom> pepijndevos, FHDLTestCase was meant to be an internal class for testing nMigen IIRC
<lkcl> jeanthom: it turns out to be exactly what is needed - generally and widely - for the purposes of all and any formal correctness proofs. "nmigen internal testing" happens to be a subset of that general purpose need
<lkcl> we have over 30 formal correctness proof unit tests in libresoc.
<lkcl> and that's only going to go up.
<jeanthom> while I agree that we need an easy way to do formal assertions in nMigen, the FHDLTestCase had its quirks that made it too confusing to be used by an end-user
<jeanthom> like having to do python ./ instead of python and probably other things like that
<lkcl> jeanthom: we fixed that.
<lkcl> it was a one-line error.
<jeanthom> has it been fixed in nmigen or in libresoc code?
<lkcl> in the duplicated copy that we were forced to put into libresoc's nmutil.
<lkcl> s/forced/had no option other than/
_whitelogger has joined #nmigen
jeanthom has quit [Ping timeout: 240 seconds]
emeb has joined #nmigen
<_whitenotifier-3> [nmigen] mglb synchronize pull request #463: Add initial support for Symbiflow toolchain for Xilinx 7-series -
<_whitenotifier-3> [nmigen] mglb commented on pull request #463: Add initial support for Symbiflow toolchain for Xilinx 7-series -
hitomi2507 has quit [Quit: Nettalk6 -]
<_whitenotifier-3> [nmigen-boards] GuzTech commented on pull request #104: Add OLED connector to -
emeb_mac has joined #nmigen
emeb_mac has quit [Quit: Leaving.]
<_whitenotifier-3> [nmigen-boards] awygle commented on pull request #104: Add OLED connector to -
<_whitenotifier-3> [nmigen-boards] awygle commented on pull request #103: Add GPDI pins to -
<_whitenotifier-3> [nmigen-boards] GuzTech commented on pull request #103: Add GPDI pins to -
Yehowshua has joined #nmigen
<Yehowshua> whitequark, I remember we discussed how to replace records
<_whitenotifier-3> [nmigen-boards] awygle commented on pull request #103: Add GPDI pins to -
<Yehowshua> I'm about to write some new record like code
<Yehowshua> What do you suggest?
<awygle> wq is on vacation until monday (i believe, certainly no later than that)
<awygle> record isn't going anywhere in the short term, and we're not going to have the design of packed structs and interfaces worked out for probably at least a couple of months
<awygle> i'd say run with record for now, just don't use .connect() or directions if you can avoid it
<d1b2> <286Tech> @awygle: I'm working on the HMDI connector PR for the ULX3S, but I have a question.
<awygle> shoot
<Yehowshua> awygle Thanks!
<d1b2> <286Tech> I need to explicitly get the _p signals for the data pins, since I'm instantiating ODDR primitives by hand. When each pins or diffpair was it's own resource, I could simply do hdmi_red = platform.request('hdmi_red', 0, dir='-').
<d1b2> <286Tech> But now all the signals are subsignals, and I don't know how to access or request the _p signals now.
<d1b2> <286Tech> Is that still possible?
<awygle> hm. good question. let me look into it for a moment
<awygle> 286Tech: you can pass a dictionary to dir= for resources which have subsignals
<awygle> dir={'d': '-'} should work i believe
<d1b2> <286Tech> Ok, but I need it for both the clock and data, so then it would be something like this? dir={'clk':'-', 'd':'-'}
<awygle> yes
<d1b2> <286Tech> Oof, I get a nextpnr assertion :S
<d1b2> <286Tech> Let me see what it actually generates.
<d1b2> <286Tech> Hmm, it generates some buffers for the cec, sda, and scl pins which are not used in my design, but other than that it looks normal.
<awygle> make sure you're not instantiating an illegal topology with the ODDR primitives, i think the routing in that section is pretty particular
<awygle> did this work before you collected the resources together?
<d1b2> <286Tech> Yup
Yehowshua has quit [Ping timeout: 245 seconds]
<d1b2> <286Tech> There is a get_oddr type function in the platform, but it maps the function parameters in a weird way, so I just do it by hand.
<d1b2> <286Tech> But it works just fine when I use my own Resource without subsignals.
<d1b2> <286Tech> I've updated nextpnr so let me try again. Dave fixed something recently (I don't know if it's related to this).
<awygle> if you can dump the verilog from the working and non-working versions i can try to figure something out
<d1b2> <286Tech> Funny enough, I get extra warnings about nextpnr not recognizing IO_STANDARD. It should be IO_TYPE, but the platform file has IO_STANDARD for the leds for some reason.
<d1b2> <286Tech> Non-working: Working:
<awygle> mk, i'm in a meeting right now but i'll take a look over lunch
<d1b2> <286Tech> Sure, thanks 🙂
<miek> i don't think you need to deal with grabbing the _p signal yourself, it's handled somewhere down the stack. i just hook up the ODDR output directly to the subsignal
<_whitenotifier-3> [nmigen-boards] GuzTech opened pull request #105: Use correct IO attribute for ECP5 FPGAs -
<d1b2> <286Tech> @awygle: Just asked Dave if IO_STANDARD is incorrect, and the response was that ECP5 only supports IO_TYPE, hence the new PR.
<awygle> that sounds good. i can't actually merge that PR since i don't have a commit bit but it looks right to me
<awygle> oh 286Tech i forgot, can you also post the nextpnr error you're getting?
<d1b2> <286Tech> Ah yes, here you go:
<d1b2> <286Tech> And here's the generated lpf file:
<daveshah> This should be a nicer error, but the problem is because you are trying to use a pseudo-differential top-bank LVCMOS33D pin as something other than an output, which isn't supported by the hardware
<daveshah> It's probably the 'eth' channel (which is a dubious name, as afaik actual HDMI ethernet would need more passive components and pins or a PHY) that is causing the problem
<d1b2> <286Tech> But I do use it as an ouput. I instantiate ODDR primitives by hand.
<d1b2> <286Tech> Hmm
<d1b2> <286Tech> Let me check
<daveshah> You don't for the 'eth' pins at a glance
<daveshah> The main TMDS pins using an ODDR should be fine, I would say
<d1b2> <286Tech> Yup, you are right. When I remove the eth pins from the platform, then it works.
<d1b2> <286Tech> The thing is, is that I don't even use the eth pins.
<daveshah> nMigen is still adding an inout pin and associated BB
<d1b2> <286Tech> nMigen probably instantiates something for them I guess.
<awygle> 286Tech what does your Resource definition look like right now?
<awygle> you might want to make `eth` have `dir='o'` in the Resource if it can only be an output
<d1b2> <286Tech> Sure, but from what I understand, the GPDI port is just an HDMI connector, with the pins connected to the FPGA. You don't have to use it as an HDMI peripheral.
<awygle> i think that won't affect the case where you grab it with '-' anyway
<d1b2> <286Tech> All right.
<awygle> you could define it as a Connector, i suppose, but if it's got a physical HDMI connector it probably makes more sense to leave it as an HDMI definition
<d1b2> <286Tech> Yeah, I'll leave it as it is.
<awygle> you might want to default "d" to 'o' also, since it's also LVCMOS33D and presumably in the top-bank as well
<awygle> and then confirm that '-' still works as expected
<d1b2> <286Tech> Yeah, the only reason why it works right now is because I've instantiated the ODDR primitives myself.
<d1b2> <286Tech> Same for clk too then.
<awygle> ah, yes
<d1b2> <286Tech> So that would mean that I cannot use it as an HDMI in then.
<awygle> missed that somehow
<d1b2> <286Tech> daveshah: Is there no IDDR like primitive?
<daveshah> There is
<daveshah> The problem is not to do with DDR
<daveshah> The problem is that the top bank doesn't support differential inputs
<d1b2> <286Tech> Ah ok. So then it's not possible to use it as an HDMI input.
<daveshah> Nope
<d1b2> <286Tech> In that case, it should definitely be defined as an output.
<daveshah> Yeah
<_whitenotifier-3> [nmigen-boards] GuzTech synchronize pull request #103: Add GPDI pins to -
<d1b2> <286Tech> Cool, thanks 🙂
<_whitenotifier-3> [nmigen-boards] awygle commented on pull request #103: Add GPDI pins to -
emeb_mac has joined #nmigen
jeanthom has joined #nmigen
emeb_mac has quit [Ping timeout: 264 seconds]
emeb has quit [Ping timeout: 260 seconds]
emeb_mac has joined #nmigen
emeb has joined #nmigen
jeanthom has quit [Ping timeout: 264 seconds]
Asu has quit [Quit: Konversation terminated!]
TiltMeSenpai has joined #nmigen
emeb has quit [Ping timeout: 264 seconds]
emeb has joined #nmigen
lkcl has quit [Ping timeout: 240 seconds]
lkcl has joined #nmigen
jeanthom has joined #nmigen
jeanthom has quit [Ping timeout: 260 seconds]