ChanServ changed the topic of #nmigen to: nMigen hardware description language · code at · logs at
<whitequark> instances don't have domains
<whitequark> you can provide a clock to an instance with ClockSignal()
<whitequark> (or ClockSignal("domain"), sync is default as usual)
<awygle> ah, ok
<awygle> what about reset? ResetSignal?
<whitequark> yep
<whitequark> EnableSignal, unfortunately not yet
<whitequark> but it's a major omission.
<awygle> i read that bug lol
<awygle> oh okay, i just don't know how to use yosys
esden has joined #nmigen
<awygle> wish i could use coroutines for testbench processes in c++ :/ maybe in 2021
<awygle> hm. openocd (through't see my versa board even though linux sees it just fine.
<ktemkin> I got a couple of boards from Lattice without the expected descriptors programmed
<ktemkin> which made openocd not match them
<ktemkin> (I had meant to check if Diamond actually set the trellis-expected descriptors the first time, and these boards were just never-touched-by-Diamond)
<awygle> yep, i managed to communicate by dropping the descriptor from the file template
<awygle> now it seems like the clock is maybe stopped? at any rate i'm not getting what i expect from blinky which is not a good sign by and large
<awygle> K that sorted, let's try this out
_whitelogger has joined #nmigen
<Sarayan> *yawn* all
<Sarayan> Ok, I don't understand ram timings
<Sarayan> oh, maybe I do
<Sarayan> no I don't
<Sarayan> oh well
thinknok has joined #nmigen
kbeckmann has joined #nmigen
Asu has joined #nmigen
q3k has joined #nmigen
cr1901_modern has joined #nmigen
thinknok has quit [Ping timeout: 240 seconds]
thinknok has joined #nmigen
_whitelogger has joined #nmigen
thinknok has quit [Ping timeout: 260 seconds]
proteus-guy has joined #nmigen
<_whitenotifier-3> [nmigen/nmigen] whitequark pushed 1 commit to master [+0/-3/±1]
<_whitenotifier-3> [nmigen/nmigen] whitequark 4f17cb1 - doc: remove outdated files and references to them.
<_whitenotifier-3> [nmigen] Success. 82.30% (+0.11%) compared to 66f4510 -
<_whitenotifier-3> [nmigen] Success. Coverage not affected when comparing 66f4510...4f17cb1 -
<_whitenotifier-3> [nmigen] Success. 82.18% remains the same compared to 66f4510 -
ademski has joined #nmigen
ademski has quit [Remote host closed the connection]
loxodes has joined #nmigen
nihilant has joined #nmigen
hikari-chan has joined #nmigen
<_whitenotifier-3> [nmigen/nmigen] whitequark pushed 1 commit to master [+0/-0/±1]
Alain has joined #nmigen
<_whitenotifier-3> [nmigen/nmigen] whitequark 38aa9fb - setup: update project URLs.
<_whitenotifier-3> [nmigen/nmigen-boards] whitequark pushed 1 commit to master [+0/-0/±1]
<_whitenotifier-3> [nmigen/nmigen-boards] whitequark 781de38 - setup: update project URLs.
<_whitenotifier-3> [nmigen/nmigen-stdio] whitequark pushed 1 commit to master [+0/-0/±1]
<_whitenotifier-3> [nmigen/nmigen-stdio] whitequark b75ab14 - setup: update project URLs.
<_whitenotifier-3> [nmigen/nmigen-soc] whitequark pushed 1 commit to master [+0/-0/±1]
<_whitenotifier-3> [nmigen/nmigen-soc] whitequark 987aeb0 - setup: update project URLs.
<_whitenotifier-3> [nmigen] Success. 82.3% (+0.11%) compared to 4f17cb1 -
<_whitenotifier-3> [nmigen] Success. Coverage not affected when comparing 4f17cb1...38aa9fb -
<_whitenotifier-3> [nmigen] Success. 82.18% (+0.00%) compared to 4f17cb1 -
<_whitenotifier-3> [nmigen-soc] Success. 100% remains the same compared to f5b5cd5 -
<_whitenotifier-3> [nmigen-soc] Success. Coverage not affected when comparing f5b5cd5...987aeb0 -
Alain has left #nmigen [#nmigen]
peteut has joined #nmigen
peteut has quit [Ping timeout: 260 seconds]
proteus-guy has quit [Ping timeout: 272 seconds]
<awygle> it looks like the sync domain that gets created on the VersaECP5Platform doesn't have a reset line, but the class does have a default_rst... is that not supposed to automagically happen?
peteut has joined #nmigen
<whitequark> hm, it is; let me check
<awygle> also, is there a way to check if a domain has a reset signal? because ResetSignal() will happily return (rst sync) to explode later on, instead of throwing at the place where it's constructed
<awygle> ah, because the signal can be manipulated before the clock domain is constructed
<Sarayan> halp halp I don't understand how the Memory works :-)
<whitequark> yes, late binding is like that
<whitequark> awygle: try ResetSignal(allow_reset_less=True)
<whitequark> unless you specifically want to *check*
<Sarayan> when is data updated once I set addr?
<whitequark> Sarayan: are you asserting enable?
<awygle> ah no that's fine
<Sarayan> no
<Sarayan> but I'm not dis-asserting it either, and data is updated
<whitequark> hm
<Sarayan> I'm not sure I understand the interaction with the associated clock domain
<whitequark> so you get a write port, and you do port.en.eq(1) somewhere, right?
<whitequark> can you show me code?
<Sarayan> in fact I'm sure I'm not
<Sarayan> I only do read for now
<Sarayan> I will do write later, it happens to be a ram, but later
<whitequark> wait
<whitequark> data updated, not memory content updated
<whitequark> sorry
<Sarayan> yeah
<Sarayan> It's ambiguous
<whitequark> ok, yeah
<whitequark> is the memory synchronous or asynchronous?
<whitequark> i.e. which arguments do you pass to read_port() ?
<whitequark> domain="sync"? domain=None?
<Sarayan> domain="sync"
<Sarayan> I'm interested in both cases
<Sarayan> I'm not sure async read/write is sane or reliable in a fpga
<Sarayan> async rom, sure
<Sarayan> it's just a risk of delay, but nothing more
<whitequark> one moment, just found a yosys bug
<whitequark> let me send a PR
<Sarayan> sure
<Sarayan> beautiful, using comb or sync on setting addr makes no difference
<Sarayan> there's something fundamental I'm missig
<Sarayan> missing
<Sarayan> 17 commits, nice push
<whitequark> where?
<whitequark> oh, yours
<whitequark> so, memories
<whitequark> think of it this way
<whitequark> an async memory is implemented similar to:
<whitequark> m.d.comb +=[rd_port.addr])
<whitequark> and a synchronous one:
<whitequark> m.d.sync +=[rd_port.addr])
<whitequark> (add If(en) as appropriate if you use the enable signal)
<Sarayan> 21:49 -_whitenotifier-3:##whitequark- [whitequark/yosys] whitequark pushed 17 commits to write_verilog-empty-sigspec [+7/-1/±32]
<Sarayan> these 17
<Sarayan> ok, that's what I thought it was, but that's not really what my traces say
<awygle> it's quite easy to wrap verilog modules in nmigen once you get the hang of it and make a few nice vim macros
<awygle> tempted to write a little python script to just do it for me...
<whitequark> Sarayan: oh, it's not my commits
<whitequark> awygle: maybe we should make an API for it or a CLI tool or something
<awygle> that would be nice
<Sarayan> in particular, if I do a m.d.comb += rdport.addr.eq(xxx) I get addr and data updated at the next sync
<Sarayan> and if I do m.d.sync += rdport.addr.eq(xxx) I get exactly the same thing
<Sarayan> while I'd have expected to get addr at the next sync and data at the following one
<Sarayan> it feels like the memory acts async even when I put read_port(domain = 'sync')
<Sarayan> m.d.comb += self.o_xcp.eq(self.xcp)
<Sarayan> m.d.comb += self.o_vramadr.eq(rdportl.addr)
<Sarayan> m.d.comb += self.o_ycp.eq(self.ycp)
<Sarayan> m.submodules.rdporth = rdporth = self.vramh.read_port(domain = 'sync')
<Sarayan> m.d.comb += self.o_rdata[8:].eq(
<Sarayan> m.d.comb += self.o_rdata[:8].eq(
<Sarayan> with m.If(self.i_clk2):
<Sarayan> m.d.sync += self.pnhsy.eq(self.i_nhsy)
<Sarayan> m.d.sync += self.pnhbk.eq(self.i_nhbk)
<Sarayan> cx = Signal(24)
<Sarayan> cy = Signal(24)
<Sarayan> with m.If((~self.pnhsy) & self.i_nhsy):
<Sarayan> m.d.sync += self.pnvsy.eq(self.i_nvsy)
<whitequark> hmm
<whitequark> give me a sec
<whitequark> can you push the code meanwhile?
<Sarayan> it is pushed, in the k051316
peteut has quit [Ping timeout: 265 seconds]
<whitequark> looking
<Sarayan> my difficulty is with rdportl/rdporth
<awygle> it's wild how exhausting zero-thought "hook this wire to that wire" copy paste work can be
<Sarayan> nothing changes whether I set the addr with comb or sync, and I think it should
<whitequark> awygle: we really should automate that
<whitequark> i'm not quite sure how
<Sarayan> what I'm eventually trying to do is that I have a 12MHz clock (sync) and a 6MHz clk2, and I want to alternate optional access from the cpu and mandatory access for the video, with the main computations done on the "cpu" access time
adamgreig has quit [*.net *.split]
cr1901_modern has quit [*.net *.split]
<whitequark> hm
<whitequark> try pyyosys?
<whitequark> read the verilog, look which ports it instantiates, query with pyyosys
<whitequark> hacky and not really upstreamable, but should help you meanwhile
cr1901_modern has joined #nmigen
adamgreig has joined #nmigen
<awygle> na i'm past that bit presently, copying the sump2 icestick design instead
<awygle> good idea for next time tho
nihilant has quit [*.net *.split]
nihilant has joined #nmigen
mwk has quit [*.net *.split]
jfng has quit [*.net *.split]
esden has quit [*.net *.split]
_florent_ has quit [*.net *.split]
esden has joined #nmigen
jfng has joined #nmigen
mwk has joined #nmigen
_florent_ has joined #nmigen
ZirconiumX has quit [*.net *.split]
Sarayan has quit [*.net *.split]
miek has quit [*.net *.split]
ZirconiumX has joined #nmigen
Sarayan has joined #nmigen
miek has joined #nmigen
jfng has quit [Ping timeout: 248 seconds]
emily has quit [Ping timeout: 252 seconds]
anuejn has quit [*.net *.split]
vup has quit [*.net *.split]
_whitenotifier-3 has quit [*.net *.split]
hikari-chan has quit [*.net *.split]
hikari-chan has joined #nmigen
_whitenotifier-3 has joined #nmigen
anuejn has joined #nmigen
vup has joined #nmigen
kbeckmann has quit [*.net *.split]
Ekho has quit [*.net *.split]
kbeckmann has joined #nmigen
Asu has quit [*.net *.split]
Ekho has joined #nmigen
Asu has joined #nmigen
q3k has quit [*.net *.split]
loxodes has quit [*.net *.split]
whitequark has quit [*.net *.split]
ktemkin has quit [*.net *.split]
key2 has quit [*.net *.split]
awygle has quit [*.net *.split]
loxodes has joined #nmigen
whitequark has joined #nmigen
q3k has joined #nmigen
ktemkin has joined #nmigen
awygle has joined #nmigen
key2 has joined #nmigen
hikari-chan has quit [Ping timeout: 260 seconds]
<whitequark> Sarayan: how do I simulate it?
<Sarayan> are you on linux? If yes make then ./overdrive first 1
<whitequark> hm
<Sarayan> I've put the roms and LA captures in the git, which is bad, but heh
<whitequark> from k053252 import k053252
<whitequark> er
<whitequark> ImportError: No module named k053252
<whitequark> did you set up PYTHONPATH or something?
<Sarayan> are you in the overdrive directory?
<whitequark> yeah
<whitequark> wait, hm, it seems to work now
<Sarayan> look at the start of the script, it's supposed to handle the path
<Sarayan> because that it hasn't generated an empty yosys.cmd
<Sarayan> s/because/beware/
<whitequark> hm ok
<whitequark> so this is a problem with cxxrtl, right?
<whitequark> have you tried reproducing it with pysim?
<Sarayan> I don't know
<Sarayan> pysim explodes with my rom sizes
<whitequark> I meant, you observe this when you use cxxrtl, right?
<whitequark> ah ok
<Sarayan> I actually thought it was a problem with my understanding of Memory
<whitequark> it sounds like a bug from your description
<Sarayan> I guess
hikari-chan has joined #nmigen
peteut has joined #nmigen
<Sarayan> but yes, I observe this with cxxrtl
<ktemkin> re: plumbing exhaustion: it'd be nice if there was a sane equivalent to `.connect`, though I have no idea what its semantics would be
<whitequark> ktemkin: regarding streams? yeah
<whitequark> Sarayan: i think i found the place where cxxrtl might have a bug
<whitequark> i'm still building yosys
<whitequark> could you try using `write_cxxrtl -O0` and check if the behavior is still the same?
<Sarayan> sure
<ktemkin> or even around "I want to naively wire up this record to another one"; if that existed, one could e.g. stack a convenience wrapper around Instance that coalesced groups of signals into records
<whitequark> ktemkin: right, i'm in the same place re: semantics
<whitequark> i've tried to think of something nice and so far couldn't
<whitequark> it feels like maybe we should just make writing bespoke connect implementations easier
<whitequark> i've avoided touching that API so far because i'm really unconvinced that any replacement will be better
<awygle> hm i should perhaps start using records...
<ktemkin> putting a method on `Record` itself seems like it'd definitely be wrong, anyway
<Sarayan> errr, it goes into infinite loop with -O0
<whitequark> Sarayan: with -O0 you need to use the "more compatible" snippet to drive it
<Sarayan> ahhh ok
<Sarayan> yep, I'm getting correct behaviour with -O0
<whitequark> ok, gotcha
<whitequark> let me write a patch
<whitequark> Sarayan: try
<Sarayan> ok, lemme sync, patch and rebuild
<ktemkin> whitequark: there's too much cognitive baggage in any syntax that parallels `x.eq(y)`; I'd assume any sane semantics would have to either have to look like `splice(x, y)`, or have some kind of `Bus` object that you added connections to _very_ explicitly
<whitequark> ktemkin: agreed, and i think this ties into the current trouble with factoring out chunks of modules into functions
<whitequark> the Module object maintains state that's really lexical in nature, but it only looks lexical because of the whole `with` thing
<ktemkin> yeah; and there's a "dsl cliff" -- a point after which it stops feeling like you're explicitly building thing _with_ python -- that really limits what can be done semantically to provide convenience
<whitequark> yeah
<awygle> is building the thing with python that critical?
<whitequark> i think a lot of these problems can be solved by using a higher level abstraction
<whitequark> like the flow graph stuff
<whitequark> awygle: just to check, what do you understand as "building [it] with python" here?
<awygle> whitequark: (as you probably guessed, i was following up on ktemkin's comment) the circuit, i suppose? whatever you're attempting to describe in HDL
<whitequark> right, i'm trying to nail down the context
<awygle> me too, honestly. the train of thought basically went like this: "i would like a convenient way to connect modules together" "(perceived) you can't have it because then it wouldn't be python" "(preconceived notion that python is bad) so what who cares about python?"
* whitequark nods
<awygle> thinking about the _operation_ i want to perform, it would be "connect all inputs of module X which have the same name as an output of module Y to those outputs"
<whitequark> oh, so the .* systemverilog feature?
<whitequark> (I forgot how it's called exactly)
<awygle> i did not know systemverilog had that
<adamgreig> fwiw, i've ended up with reasonably nice-looking code despite calling methods inside what looks like lexical scope blocks etc
<whitequark> lemme dig it out
<whitequark> adamgreig: ooh, can you show those?
<whitequark> awygle: "wildcard port connections"
<awygle> whitequark: yes, essentially that
<adamgreig> those methods know they're to be called inside a "with m.FSM()" context, and add states
<whitequark> adamgreig: oh, that's really nice actually; i was long going to do something like it for Glasgow, but kept putting it away because i couldn't quite come up with a perfect design
<awygle> although that requires a higher level hierarchy (`wire connection` at the top level) whereas i was imagining module-to-module (`mod_x.connect(mod_y)`)
<adamgreig> i guess it makes a sort of fsm dsl, but it ended up being powerful enough for everything i needed
<whitequark> awygle: ok, i see; so the main problem here is that the notion of "port" doesn't exist in nmigen
<awygle> preference for the latter only slight
<whitequark> this is actually really unfortunate, but i did end up with this historically so that nmigen.compat could exist
<awygle> <-- this, right? ish?
<whitequark> ZirconiumX has raised the issue about it long ago, and it was on my roadmap even before that
<whitequark> yeah
<whitequark> for example, take a look at nmigen-rpc
<whitequark> it's doing some gross stuff:
<whitequark> # By convention, any public attribute that is a Signal or a Record is
<whitequark> # considered a port.
<awygle> yep
<awygle> and there's the `ports()` method but that's clearly convention and doesn't specify direction anyway
<ktemkin> adamgreig: when I've done things like that, I've created the relevant pieces declaratively, and then elaborated them into e.g. the FSM DSL in elaborate(); I'm not sure which feels better
<whitequark> it's not even quite convention
<whitequark> i just recommend it as a workaround
<whitequark> e.g. i don't use it in my code
<awygle> ah
<whitequark> the main issue here is that a lot (everything in stdlib) of modules are parametric, and some could be even higher order
<whitequark> basically, #243 is asking for a type system
<awygle> heh. yes.
<whitequark> and i think that's totally cool.
<adamgreig> ktemkin: i'm not sure i follow, or rather, i don't see how you'd do it except in the context of having a module and being in the FSM context. do you generate the states beforehand and just add them all in elaborate?
<whitequark> a type system for nmigen though would at least assign signals to clock domains (which is *another* thing that it really ought to have)
<Sarayan> whitequark: It works, thanks. cxxrtl/nmigen may have some bugs remaining, but the support is more than top notch :-)
<whitequark> excellent!
<whitequark> let me push that to my repo
<ktemkin> adamgreig: when it's made sense (e.g. when building a collection of special-function registers with different behaviors), I've captured descriptions into a collection pre-elaboration; and then expanded the behaviors by strumming along e.g. the FSM abstraction during elaborate()
<Sarayan> bedtime for now, good night all
<ktemkin> adamgreig: that's mostly been so whatever is instantiating the relevant object can do things like call methods on an instance to customize the generated code
<whitequark> Sarayan: pushed
<ZirconiumX> Sleep well, Sarayan
<awygle> whitequark: something that just occurred to me - why the i_, o_ convention on Instance arguments if nmigen can't distinguish inputs and outputs anyway?
<awygle> future-proofing?
<whitequark> awygle: Instance is different
<adamgreig> ktemkin: ah, thanks, I think I understand. In my case it would maybe look like the subclasses defining their fields in a regular python data structure first, and then elaborate() could probably be just a parent class default that turns the python object into the relevant nmigen hdl?
<whitequark> it's not a convention; it's actually semantically meaningful
<ktemkin> adamgreig: yep; that'd be one way of doing it
<adamgreig> basically move the DSL out of elaborate() so it can more meaningfully interact with other things at creation
<awygle> i see how it's meaningful on the e.g. verilog side but that meaning is lost as soon as you assign it to an nmigen signal
<whitequark> awygle: there are two issues here
<whitequark> first, there is no way to make an inout signal in pure nMigen (other than adding it to a Fragment manually, but that's pretty unsupported)
<whitequark> (we might want to support direct manipulation of Fragments later, but not just yet)
<ktemkin> adamgreig: mhm. for something that's "I'm building exactly one type of thing", what you have is probably nicer
<whitequark> awygle: second, nmigen actually has to know the direction of the ports of the Instance to emit correct RTLIL
<whitequark> iirc if I don't do that it just won't elaborate
<whitequark> third, even if the previous issue didn't exist, it's still inherently ambiguous
<whitequark> consider a design with an Instance and exactly one signal, connected to a (non-directional) port of this instance
<whitequark> you put this signal into convert(ports=[...])
<whitequark> does it become a toplevel input? output? inout?
<whitequark> I guess you could say "this is an inout, and it's the synthesis toolchain's job to figure out which direction it goes now"
<whitequark> (I'm not sure if this actually works in every case)
<mwk> I did try to get top-level inouts working automagically for yosys flows involving iopadmap
<mwk> I'm not entirely sure I've actually succeeded, though
<mwk> and I'm pretty sure that would break for flows that insert I/O buffers in nextpnr
<mwk> (ie. ice40 and ecp5)
<whitequark> yup, that's exactly the kind of thing I'm trying to avoid
<whitequark> awygle: in other words, even if this could be technically made to work without any directions (by defaulting to inout everywhere), i suspect it would actually be just impractical
<awygle> sure. you're talking about pushing it the opposite way of what i'd want lol
<whitequark> heh
<whitequark> in a way, Instances kind of forced my hand here, to implement this sort of thing earlier
<whitequark> in fact, the same thing will happen with the CDC checker
<whitequark> nMigen can simply observe all code defined in Python, but it doesn't know which domains are instance pins driven with
<whitequark> driven frmo*
nihilant has quit [Remote host closed the connection]
<awygle> yeah that's exactly what i was getting at - the logic exists to support Instances, so it seems (to an ignorant layman) that it ought to be pushed out to all Signals/modules
<whitequark> it is pushed to all modules, sort of
<whitequark> this happens automatically in Fragment.prepare
<whitequark> it *has* to happen automatically at least as an option for nmigen.compat to be possible
<whitequark> adamgreig: i do quite like what you're doing with FSMs
<awygle> possibly related to the current conversation - if i get "AssertionError: assert defs[sig] is self" is that because i've hooked an input to an input or an output to an output?
<whitequark> adamgreig: one thing that you're not doing quite as i intended is mutating the elaboratable in the elaborate() method
<whitequark> awygle: any AssertionError is an nmigen bug (it should be a proper diagnostic)
<whitequark> but I think it's the latter
<whitequark> adamgreig: is `self.m` used just so you don't need to pass it into every method individually?
<adamgreig> yes
<whitequark> right, ok
<adamgreig> but self._fsm_ctr is mutated
<adamgreig> which is used to label the states
<whitequark> i would probably make an object that contains all state related to the FSM builder
<whitequark> maybe even a context manager, since you have start_fsm/end_fsm
<whitequark> similar to Module itself
<whitequark> that's something to mention in the manual
<adamgreig> just to avoid elaborate() having side-effects?
<whitequark> yes
<whitequark> well, no
<whitequark> elaborate() isn't supposed to have side effects, yes, but in this case they're fairly harmless by themselves
<whitequark> (you can call it multiple times just fine, which means you avoid the worst issues)
<mwk> tmux at
<mwk> er.
<whitequark> what i see though is that elaborate() having side effects suggests that it could be written a bit more elegantly
<adamgreig> ah, sure. I think changing start_fsm and end_fsm into a single context manager would be much nicer
<ktemkin> hmm; I think I might like the pattern of having a nested class inside your module that provides your elaboration helpers
<adamgreig> possibly the classes wouldn't need to be subclasses at all at that point
<whitequark> yes!
<whitequark> classic "composition over inheritance" case
<whitequark> it's pretty minor tho.
<whitequark> another thing i was thinking of, is making it possible for users to extend Module with their own helpers
<whitequark> but that seems hard to do reliably in Python
<whitequark> right now there's If/Elif/Else, Switch+Case, and FSM+State
<whitequark> and they're pretty intertwined together
<whitequark> internally, that is
<ktemkin> I wonder if there's a nice way to cleanly create a proxy around your module object
<whitequark> in principle, it should be possible to somehow factor them out to make it possible to do "DSL-on-demand", with Module as it is just being the default
<whitequark> but i'm still not really sure if it's a good idea
<whitequark> ktemkin: i feel like it'd end up being too fragile and/or too magical
<whitequark> given that all it replaces is x.m.* with x.*
<ktemkin> probably, yeah
<whitequark> i've seen people struggle somewhat with our current amount of magic
* awygle raises hand
<whitequark> i think the magic budget should be spent really carefully
<whitequark> right :)
<ktemkin> yeah; I started thinking about converting some of my old FPGA courses to nMigen and have been gradually realizing that people coming in to it kind of have to be a bit more than _reasonably_ proficient at Python
<awygle> ugh i'm so goddamn close to a full test of this design but also it's 3pm and all i've eaten today is a single yogurt. should probably stop racing my stomach and get food...
<ZirconiumX> Go eat, awygle
<awygle> yes ~~mom~~ ZirconiumX
<ZirconiumX> :P
<whitequark> ktemkin: hmm, can we improve that?
<whitequark> for me learning a new language is so ordinary i've completely lost track of how it actually feels
<whitequark> which is probably an inherent problem with doing language design
<ktemkin> I've been trying to think of ways to improve that -- but honestly, a lot of it comes from that most people need to learn via inferential steps; and having to learn the way logic behaves while you learn how Python behaves is already a challenge
<whitequark> right
<whitequark> i think it's still less bad than Verilog, which on one hand--we're saving someone a lot of trouble, on the other--very low bar
<mwk> hmm right
<ktemkin> yeah
<whitequark> Sarayan had a lot less trouble with nMigen I think
<mwk> one or two of my students said they'd try out nmigen for their assignments instead of verilog, I wonder how that'll work out
<ktemkin> I've historically started with schematic capture in those courses and then moved to VHDL
<whitequark> mwk: I gotta speed up with those docs
<mwk> yes, those would be useful
<whitequark> I'll try getting something together starting like.. tomorrow
Asu has quit [Remote host closed the connection]
<ktemkin> the former because I wanted to firmly plant the idea of "I'm thinking about creating networks of parallel logic hardware" before they get to anything that looks like programming
<whitequark> one thing i'm not sure about is
<ktemkin> and the latter because at least VHDL often tells you to fuck off; where Verilog is just like "okay, yeah, sure, whatever" and then shoots you in the foot
<whitequark> so, it's pretty foundational that when writing portable logic, we're programming the, uhm, yosys abstract machine
<whitequark> (you see the parallel i'm drawing, right?)
<ktemkin> not enough to be sure I'm seeing it
<ktemkin> beyond the implications of inference
<whitequark> synthesis produces equivalent netlist in the same way a C compiler produces equivalent machine code, both modulo some abstract semantics
<ktemkin> mhm
<whitequark> there is no nmigen construct that synthesizes to a DFFE
<whitequark> and there cannot possibly be
<whitequark> but... this seems the kind of thing course authors are writing, from past discussions of teaching nmigen
<whitequark> i know i'm technically right, but am i *pedagogically* right?
<whitequark> is explaining this actually a good way to teach a HDL?
<ktemkin> honestly, I think most people do pedagogy of this stuff _wrong_
<whitequark> thing is i'm not really a teacher and i know people (and perhaps *especially* language designers) suck at teaching
<whitequark> i know in the past my most clear, obvious explanation appeared incoherent to someone who wasn't one
<whitequark> more than once
<whitequark> i have a perspective that's biased towards seeing use/misuse of features, but that doesn't necessarily translate to teaching them well
<ktemkin> I actually don't think that particular limitation hurts pedagogically
<whitequark> mhm
<whitequark> s/people/programmers/ above
<ktemkin> no, I agree with "people suck at teaching"
<whitequark> heh
<whitequark> heheheh
<whitequark> fine
<ktemkin> like, I learned to teach by observing everything that my teachers fucked up and resolving not to do that
<ktemkin> (basically started teaching out of an irritation at how badly the faculty were doing it, and eventually the university was just like... fuck, well, if you're not going to stop, we'll give you a faculty position)
<whitequark> in the past i felt like a lot of my arguments were just too abstract
<whitequark> or rather, they relied on (a) knowing many languages and their approaches and (b) seeing how languages fail in practice
<ktemkin> anyway, the way I taught digital logic involved teaching _why_ we model things synchronously the way we do by leading them up to the problem, and then moving to synchronous logic as a -solution- that made things easier
<whitequark> right
<whitequark> this doesn't quite seem like it'd work for an nmigen tutorial though, would it?
<ktemkin> the way I have it structured, I'd start with a schematic capture tool (leaning towards icestudio) until we get to the point where we're doing synchronous sequential logic
<whitequark> do you want to participate in the documentation project?
<whitequark> sub-project i guess
<ktemkin> as long as it's implied that I am perpetually completely overwhelmed and thus should be assumed unreliable, sure
<whitequark> gotcha
<mwk> have my unreliable axe as well...
<mwk> and btw, about schematic capture and teaching courses
<mwk> is there a foss tool for that?
<whitequark> for schematic capture?
<mwk> yes
<whitequark> have you looked at icestudio?
<mwk> last year, I started directly with verilog and this was a bad mistake, too many students using it as if it was an imperative programming language
<whitequark> yes
<whitequark> that's *the* classic verilog problem, isn't it
<whitequark> it even sort of works in simulation!
<mwk> this year, I still started with verilog but made sure to run every single early example through yosys -p "prep; show" to hammer the point home that we're making schematics here, not code
<mwk> which helped a bit, I guess
<mwk> (well, not "executable code", if you know what I mean)
<whitequark> yup
<whitequark> actually, the way I started with FPGAs was Claire's workshop at EHSM 2014
<whitequark> three things blew my mind: the yosys show command; formal verification; and that yosys had a perfectly normal compiler IR and pass pipeline
<whitequark> at that point i knew i *had* to get into FPGAs, and here we are :)
<mwk> huh, the icestudio thing looks interesting
<mwk> whitequark: hehe
<mwk> yes... having a proper foss tool to hack on changes everything
<whitequark> what really changed things for me was seeing this tool as a non-blackbox. a whitebox if you will
<whitequark> RTLIL just *made sense*
<mwk> yep
<mwk> the show command is awesome
<whitequark> it kinda falls apart at really large designs, but it still goes such a long way
<ktemkin> I got _back_ into FPGA's because of Claire's toolchain
<mwk> ... same-ish
<whitequark> here's an incredibly obscure fact: i'm indirectly responsible for the very first OSS FPGA P&R, which incidentally isn't icestorm
<whitequark> apparently a very long time ago i linked azonenberg the greenpak4 datasheet with full bitstream docs on twitter, pretty much by accident
<whitequark> and gp4par is older than icestorm
<mwk> I actually tried reverse-engineering some FPGA bitstream in 2012, I think it was cyclone 2 or something
<whitequark> there were quite a few bitstream RE projects
<whitequark> wolfspraul did a lot of S6 work i think
<mwk> but quickly gave up after I realized that, even if I were to succeed, I couldn't do much with it
<mwk> too much required infrastructure that just did not exist back then
<whitequark> (to be clear, i don't consider that tweet much of an achievement; it's just an amusing story)
<mwk> whitequark: ... isn't VPR older? or are we only counting ones that actually work :p
<whitequark> lol, harsh
<whitequark> did VPR target any real FPGA at the time?
<whitequark> like, netlist to bitstream?
<mwk> *shrug* no idea
peteut has quit [Ping timeout: 248 seconds]
<mwk> I didn't really get into FPGA toolchains until 2018, and by then yosys/icestorm was the only thing worth looking at
<whitequark> right
<awygle> ktemkin: what you describe as your teaching methodology is exactly what was missing from almost my entire education - "why do we care about this thing? what problem was it created to solve?"
<awygle> whitequark: the idea that RTLIL made things _clearer_ must *surely* be a result of your language designer background :p
<whitequark> awygle: hahahaha
<whitequark> at the time i was pretty bad at it; mostly, excessively dogmatic
<whitequark> i did like LLVM a lot though, and RTLIL looked a lot like LLVM IR
<whitequark> i mean
<whitequark> ok i guess that sentence already implies what you said
<whitequark> but
<awygle> RTLIL to me doesn't look like an intermediate language at all. i think of "LLVM IR" as "the weird pseudo-assembly-language thing", while people who actually work in that domain seem to look at the C++ library as the "true" IR with the text bits an almost incidental serialization format (i did not learn about ilang for quite some time after learning about RTLIL).
<whitequark> right, so to me, the parallels between SSA IR and digital netlists are obvious
<whitequark> in fact, the main thing LLVM IR adds is glue
<whitequark> (ok, technically LLVM IR doesn't have glue, SelectionDAG does)
<whitequark> (SelectionDAG looks even more like RTLIL)
<awygle> yes
<whitequark> i actually have a pass to replace proc_mux that is based on ideas from the SSA world
<ktemkin> eventually it all just feels like building little chains of computational atoms
<whitequark> except i can't quite fit it to this problem domain
<awygle> someday i'd like to actually write some language/compiler stuff
<whitequark> it's fun :3
<awygle> it seems fun
<awygle> but between my two jobs (work and sleep) idk how i'll ever have the time
<ktemkin> like, assembly instructions are conceptually the same as little encapsulations of register transfers
<whitequark> i think GCC even has an "RTL IR"
<awygle> yeah it does
<ktemkin> eventually the different levels of abstraction start feeling samey to you, and saying things like "I need to create this FSM in order to get gateware to do the thing I want" feels pretty much like saying "I'm going to create an application-specific processor with essentially these instructions"
<whitequark> yup!
<whitequark> one of my goals with nmigen is to make going up and down this abstraction ladder as painless as possible
<awygle> yeah the graph is very tightly coupled, it's really just a matter of where you enter it i think
<ktemkin> and then all the time-space tradeoffs start seeming roughly equivalent in your head, and then you can't talk to anyone about anything because they don't know what the hell a directed acyclic graph is or why it's relevant to a conversation that up until now seemed like it was about writing PIC assembly
<whitequark> hahah
<awygle> lol
<mwk> hey don't make fun of me like that
<whitequark> did i ever link you a FIFO for 8051 that i designed based on Cliff Cummings' one?
<awygle> and then the ones who say "huh never heard of that, what is it?" become your friends and the ones who say "what the fuck are you talking about' become your enemies?
<whitequark> the chief advantage is that there's no lost element, yet you can still use atomics
<whitequark> and in the power-of-2 case, advancing the pointer doesn't involve a modulo operation
<whitequark> it's a bit silly because most of the time, one lost slot isn't that bad, but i think it's really elegant