ChanServ changed the topic of #nmigen to: nMigen hardware description language · code at · logs at · IRC meetings each Monday at 1800 UTC · next meeting TBD
emeb has left #nmigen [#nmigen]
nfbraun has quit [Quit: leaving]
jeanthom has quit [Ping timeout: 256 seconds]
nelgau has quit [Remote host closed the connection]
lkcl has quit [Read error: Connection reset by peer]
lkcl has joined #nmigen
nelgau has joined #nmigen
<whitequark> awygle: er, sorry, got distracted
Degi has quit [Ping timeout: 240 seconds]
Degi has joined #nmigen
nelgau has quit [Remote host closed the connection]
nelgau has joined #nmigen
nelgau has quit [Ping timeout: 272 seconds]
peteut has quit [Ping timeout: 265 seconds]
<awygle> heh yeah we both failed at maintaining focus on that conversation
nelgau has joined #nmigen
sakirious has quit [Quit: The Lounge -]
<awygle> Oh just saw the tweet, congratulations!
<whitequark> :3
<whitequark> unfortunately, i forgot what it is i was procrastinating so hard on
<awygle> cxxsim/pysim inconsistencies?
<whitequark> hm. maybe, actually
<whitequark> you've read the entire infodump right?
<whitequark> did that make any sense?
<awygle> it did yeah
<whitequark> do you have any thoughts on the kind of execution model it should use?
<awygle> as i said, eval_comb+eval_sync is what i was going to suggest
<awygle> or at least float
<whitequark> mhm, yes, i mean more specific than that
<whitequark> let's see if i can coherently put that down...
<_whitenotifier> [nmigen] hansfbaier commented on issue #554: Strange simulator behavior: clock signal pausing while sync blocks are speeding up -
<_whitenotifier> [nmigen] whitequark commented on issue #554: Strange simulator behavior: clock signal pausing while sync blocks are speeding up -
<whitequark> awygle: so i think there's not much argument around the idea that we should treat comb and sync logic separately
<awygle> the other thought i have (which is really a thought and not a coherent proposal) is that the edge detector seems really fraught, and maybe something like a timer wheel would be a better fit, but it might require more knowledge of the domains than we have
<whitequark> hmm
<whitequark> that would kill any hope of cosimulation with verilog and vhdl, no?
<whitequark> i agree with you entirely that the edge detector stuff, at least as long as it looks anything like what it is now, is incredibly fragile
<awygle> mm, maybe. at least with the same event model. and you do still need something else in the cases of processes not clocked by a clock with a consistent frequency
<whitequark> we need *some* systematic approach to asynchronicity in pysim/cxxsim
<whitequark> migen more or less had a timer wheel
<awygle> yeah. so maybe timer wheel doesn't let you off the hook.
<whitequark> meant you couldn't test anything with an AsyncResetSyncrhonizer
<awygle> it might be a useful optimization down the line
<awygle> but we need to get the general case right first
<whitequark> (ok, not really a timer wheel, but something vaguely similar in concept and limitations)
<whitequark> awygle: something i think *might* be insightful is thinking about hierarchical cxxrtl simulations
<awygle> yeah it's almost backwards actually
<whitequark> tbh in general cxxrtl tends to expose future pain points in nmigen clocking
<whitequark> just a few days ago i tracked down an async bug that probably means a lot of cxxrtl code is running shifted 180 degrees by accident
<whitequark> well, i'm not even sure if it's strictly speaking a "bug", it's more of a model omission
<whitequark> this spring i was exploring the idea of formalizing cxxrtl's execution model
<awygle> yeah. unsurprising tbh
<whitequark> that's way above my pay grade obviously and i don't have time for that, but could still be useful to think about
<awygle> cross-language stuff is hard at the best of times
<whitequark> no no, talking about pure c++ here
<whitequark> or do you mean crossing c++/hdl?
<awygle> ah cxxrtl
<awygle> not cxxsim lol
<awygle> i mix those up _constantly_
<awygle> (a me problem entirely)
<whitequark> honestly in retrospect those names are kind of bad taken together
<whitequark> they're crystal clear. to me. and probably no one else
<awygle> they are clear imo, my brain is just lazy
<whitequark> but i also don't feel like renaming either of them, easier to use a few more words
<whitequark> ok so hear me out
<awygle> hearing
<whitequark> during the spring, i had this intense displeasure with the fact that neither verilog (obviously) nor vhdl (less obviously) actually deal with race conditions in sim
<whitequark> in vhdl, you can have causally linked events that happen in zero physical time
<whitequark> and when you inevitably hit that while adding some clock gating, you're supposed to manually balance the buffers until delta cycles match
<awygle> mhm, also oof
<whitequark> which is something that i would find offensive if verilog wasn't a thing
<whitequark> this came up while i complained at yet another verilog person about determinism. see, it can be productive
<whitequark> vhdl has a situation going on where it's deterministic, yes, but in the sense that, i dunno, an out of bounds memory write in a sandbox is deterministic. it almost misses the point in some ways
<whitequark> to be clear, this isn't to complain about vhdl but to provide context
<awygle> mhm got it
<whitequark> properly resolving that seems really hard and probably flat out impossible back when vhdl was young, so can't really hold that against it anyway
<whitequark> but one thing that seems reasonably doable is a race condition detector
<awygle> hdl-tsan, like you were talking about the other day?
<whitequark> yeah
<whitequark> now i don't think i'm remotely ready to consider that as a *product* (in the broad sense of the word), but i want to think about it as a concept
<awygle> okay, so how would that work?
<whitequark> in the context of an RTL simulator, the only condition that can be sensibly detected (beyond just static CDC analysis that is) is "two things happened in zero physical time but not in an appropriate way"
<whitequark> some of the most common pitfalls that come to mind are:
<whitequark> - you have two FFs with the same clock, but there's an explicit or implicit buffer in between, and they trigger out of phase but still in zero time
<whitequark> - you have a testbench and an FF, the testbench triggers the FF, then turns around and immediately samples the value
<whitequark> or the other way around, setting D and CLK at the same time
<whitequark> - you have a testbench that, in zero time, sets some signal to 0 then 1 then 0, which produces an impossibly looking VCD
<awygle> testbenches in general seem very fraught
<whitequark> yes, and the implicit Settle thing i finally made for mwk earlier is a good step in the right direction
<whitequark> the current behavior, which i regretfully borrowed from migen, is batshit insane in the context of writing testbenches
<whitequark> well, it's less bad because nmigen actually *has* Settle
<whitequark> (migen behaves that way for the same reason vhdl does, but vhdl isn't inexpressive to the point of severe user hostility, and migen's simulator is)
<whitequark> so, going back to pitfalls, i think an EE might look at those and say "hey, those are timing violations" and well, yes, sorta
<awygle> that's kind of what i was thinking, except maybe the clock gating one
<whitequark> but i view them more like causality issues in distributed systems
<whitequark> see, clock gating is a good example for this, because no one actually wants to construct elaborate clock buffer trees
<whitequark> what i *want* is to say "the input and output of this buffer must be precisely in-phase"
<whitequark> and then the simulator either makes sure that will be the case, or dies trying
<whitequark> (well, throws an error)
<whitequark> by "precisely in phase" i mean specifically that the output must change in the same delta cycle as the input.
<whitequark> this is the point where, as far as i understand, we have to depart from VHDL
<whitequark> my understanding is that where Verilog says about sim semantics "all bets are off", VHDL prescribes a very specific set of rules that pins down the simulation behavior down to the delta cycle.
<whitequark> both of which are bad if you only care about delta cycles in first place because you have some synchronous logic you want to run!
<whitequark> if i was strictly following that approach, neither pysim nor cxxrtl would have been of any use
<whitequark> pysim is ... ok, pysim is a bit weird, but cxxrtl is very clear on this: with one exception, the behavior of combinatorial logic inside of a module is completely unspecified. it can (and will) vary with compiler options, unimportant changes in the input netlist, etc
<whitequark> and really that's the only way in which cxxrtl can provide anything remotely like verilator's performance
<whitequark> (not coincidentally, verilator adopts a very similar execution model *and* delta cycle policy)
<whitequark> so really, if you are targeting cxxrtl, you *cannot* do the vhdl thing and balance clock trees, because cxxrtl doesn't really care about your clock trees in first place
<awygle> mhm
<whitequark> oh, the exception i mentioned. when you eval() a module, it can return a value that means "based on static analysis, the eval() you just did brought me to a fixpoint"
<whitequark> in practice it generally just means "no combinatorial loops or things that look like combinatorial loops" because that's what everyone cares about
<awygle> right
<whitequark> in cxxrtl specifically, i call both of those "feedback arcs"
<whitequark> no idea if it's commonly accepted
<whitequark> so, most of the cells that cxxrtl evaluates actually finish in 0 delta cycles
<whitequark> since there's many of those that get evaluated in a single one
<whitequark> getting the clock gating primitive to behave the same is actually not hard; i mean, most comb cells already do
<whitequark> problems start at the point where you have two nets, that are completely unrelated to each other as far as the simulator knows, but your design actually only works correctly if edges on those happen in the same delta cycle
<whitequark> (or not at all)
<awygle> right
<whitequark> verilog solves this with blocking comb assignment, which is a weirdly imperative way to control the passage of time. vhdl doesn't really solve this.
<whitequark> how should we? i can think of a few ways to attack this problem
<whitequark> first, we could look at it as a timing issue. statically verify that anything sampling anything else without precautions has the same async control set
<whitequark> that forces the designer to declare the intent upfront for the gated clock
<whitequark> once the intent is known to the simulator, it can simply keep track of the delta cycle in which the transitions happen, and if those don't match, error out.
<awygle> maeks sense
<whitequark> does nothing to help with testbench issues.
<whitequark> second, we could try and infer intent automatically
<whitequark> for example, suppose flop A samples the value of a flop B that changed in the previous delta cycle.
<whitequark> this seems like it would be never desirable period
<awygle> is there a straightforward way to detect cells which evaluate in 0 delta cycles?
<awygle> or will evaluate, rather?
<whitequark> the simulator knows which cells do, because it is the simulator's prerogative to schedule cells
<awygle> how does it find out ahead of time? seems NP
<whitequark> no, it's actually trivial
<whitequark> if a cell's output is double buffered (and no one is being naughty and reading from .next), the cell will need 1 delta cycle or more
<whitequark> if a cell's output is single buffered, it either evaluates in 0 delta cycles, or is unsound
<awygle> ah, i see
<whitequark> (it would be NP to detect unsoundness based on just the cell's internal netlist, that is true)
<whitequark> (but most of the unsoundness will come from explicit declarations in black boxes and similar stuff anyway)
<whitequark> there is a third approach i have in mind too
electronic_eel has quit [Ping timeout: 240 seconds]
electronic_eel has joined #nmigen
<whitequark> so, how do pysim/cxxrtl materially differ from vhdl? for the former, delta cycles are an implementation detail, albeit important to correctness. so quite a bit of the time they end up in a situation where they insert--or, I guess, remove--those as a side effect of something else that's going on.
<whitequark> for example, what determines where delta cycles go in pysim? basically my laziness.
<whitequark> pysim doesn't statically schedule RTL--because that's a lot of work, and partially also because it'd be slow--but it also doesn't just evaluate your entire netlist hundreds of times until it settles in some random order
<_whitenotifier> [yosys] kammoh opened issue #20: TCL support for yowasp-yosys -
<_whitenotifier> [yosys] whitequark commented on issue #20: TCL support for yowasp-yosys -
<whitequark> so it takes your netlist, slices and dices it into chunks based on a heuristic i picked because it seemed good enough, and lets the pieces dynamically schedule themselves.
<whitequark> barely anyone ever notices because nmigen doesn't give you a lot of opportunity to write code that would break if you got a wrong amount of delta cycles...
<whitequark> really, half the reason pysim uses two-phase commit in first place, is because without it, it would just fall apart
<awygle> mhm
<whitequark> as far as i know, any moderately complex design racks up many dozens of delta cycles each step, in a way that is totally unpredictable to the designer
<whitequark> on the flipside, the startup latency is super low! there's no way i know of to fix this that wouldn't severely impact startup latency.
<whitequark> even trivial AST postprocessing in the code emitter turned out far too slow, iirc
<whitequark> anyway.
sakirious has joined #nmigen
<whitequark> cxxrtl has a similar but less chaotic situation
<whitequark> each time a single net is driven by both comb and sync wires, you get delta cycles
<whitequark> each time you use non-trivial hierarchy (anything beyond "blackbox directly in top"), you need delta cycles when reading submodule outputs
<whitequark> (there's a bit of code that tries to statically determine whether it's safe to read directly from .next, and i think it's sound, but it's certainly not making things easier to reason about)
<whitequark> each time a cell gives feedback to itself
<whitequark> point being: neither pysim nor cxxrtl are really in a position to dictate the placement of delta cycles globally for the entire circuit
<whitequark> it would be practically intractable to change them in a way that would make that possible, although probably possible in theory
<whitequark> (and the other side of that coin is that
<whitequark> by refusing to specify it, we not only enable the simulators to evolve, but also make it harder to write code depending on such details, both intentionally and accidentally, and that might be a good thing)
<whitequark> but, can we still do something that wouldn't require redesigning them completely?
<whitequark> i came up with this idea while thinking about a hypothetical circuit where some signal is used both as a clock and as logic
<whitequark> let's consider the clock gating issue again. one way to look at it is that, traditionally, a clock gate would be simulated with a logic primitive, and then a clock propagating through that gate would race with any other logic that just happens to involve delta cycles for whatever reason
<whitequark> cxxrtl's hierachy issue is very similar to that, it's just that the delta cycles are inserted not by logic, but because of how module ports happen to be implemented
<whitequark> the idea boils down to not allowing this situation to happen. that is, during any given delta cycle, either it is data propagating through the circuit, or it is clocks.
<awygle> sounds appealing
<whitequark> i actually dislike it somewhat
<whitequark> feels very ad-hoc in a way that brings trouble later
<whitequark> it's also not entirely obvious how to implement this, but neither it is for any other proposal, so...
<whitequark> anyway, i think it's worth discussing this approach at least
<whitequark> how do we decide that something is "a clock"? well, a net connected to the CLK input is self-evidently a clock. anything from its fan-in is self-evidently a clock.
<whitequark> actually, i think i mean "input cone" rather than "fan-in"
<awygle> i'm not sure i follow
<awygle> isn't a net connected to the CLK input not going to have an input cone since it's driven directly from the CLK input?
<whitequark> er, i meant the CLK input of a sync primitive like an FF
<whitequark> unless i misunderstand something, a CLK input of a primitive would not be driving the net connected to it...
<awygle> oh ok
<awygle> i was imagining a clk input to like... a module/netlist
<awygle> at the top level
<whitequark> thought so
<whitequark> so. how would this actually work? it seems to me that the only sensible semantic (that doesn't rely on explicit declaration of intent) is to take the combined input cones of every async control signal in the design, since we don't really have anything else to anchor to
<whitequark> and then, once anything changes on the inputs of that part of the netlist, you evaluate that subgraph alone until it gets to fixpoint
<awygle> mhm
<whitequark> the one good aspect of this scheme is that data cannot race with clocks because you cannot race with something that evaluates faster than in 0 delta cycles
<whitequark> the bad aspects include, for example, a situation where "faster than 0 delta cycles" is something you have to seriously consider
<awygle> lol
<whitequark> ultimately it feels like it might end up recreating the exact same concurrency issues, except one level deeper so even more annoying to deal with
<whitequark> like... let's say you have a clock mux cell. that's a reasonable thing to want.
<whitequark> but now the controlling signal of the clock mux is in the input cone of the output clock
<whitequark> at least if it's a normal clock mux.
<awygle> yeah
<whitequark> if it's a glitchelss clock mux this gets even more complex
<whitequark> because whatever is your answer to that, it has to be the answer to "someone is driving a clock with an FF" too
JJJollyjim has joined #nmigen
<whitequark> this is clearly not going to work out without additional conditions.
<whitequark> oh also, it would also probably not be implementable in cxxrtl because black boxes don't exactly let you collect input cones of arbitrary nets
<whitequark> they're bound at runtime, so if you tried to solve that, you'd probably have to reimplement half of yosys badly
<whitequark> so. what if we include additional conditions?
<_whitenotifier> [nmigen] hansfbaier commented on issue #554: Strange simulator behavior: clock signal pausing while sync blocks are speeding up -
<awygle> Sounds like we're inching back towards declarations of intent
<whitequark> indeed. that's fine though. you can't really reliably infer intent from an untyped netlist
<whitequark> you might infer it well enough to build a sanitizer, but anything beyond that, which is to say most interesting things you could do, need something more concrete
<whitequark> declaration of intent here doesn't have to be ironclad clock domain segregation though. it doesn't even have to involve control sets
<_whitenotifier> [nmigen] hansfbaier edited a comment on issue #554: Strange simulator behavior: clock signal pausing while sync blocks are speeding up -
<whitequark> what you could do is take every primitive, module, and black box, and decide whether any given pin is a clock pin, or not a clock pin.
<_whitenotifier> [nmigen] hansfbaier edited a comment on issue #554: Strange simulator behavior: clock signal pausing while sync blocks are speeding up -
PyroPeter_ has joined #nmigen
<whitequark> crossing clocks and non-clocks becomes a hard error. this means that you cannot use a simple logic mux to switch clocks. but that actually seems like a good thing, since it prevents us from the catastrophic ambiguity we discussed just earlier.
PyroPeter has quit [Ping timeout: 256 seconds]
PyroPeter_ is now known as PyroPeter
<whitequark> on the other hand when you do use a dedicated clock mux, there is no ambiguity involved in extracting the clock tree
<awygle> Makes sense
<whitequark> it is also, counterintuitively, reduces the annotation burden
<whitequark> let's say you connect CLK of a flop to some port XXX of your module. well, either that port is a clock port, or you did something illegal.
<whitequark> might as well infer that it's a clock port. if you are in fact constructing an illegal netlist, it'll still blow up at some point
<whitequark> (this is effectively the same as doing whole-program type inference, which is in general a bad idea, but i think in this case it should be fine)
<whitequark> (it's not like people are going to build entire designs out of 100% clock tree)
<whitequark> awygle: another bit of background: the reason i lean towarads this solution rather than something more traditionally event-based is that the more i think about it, the more i doubt event-based approaches are compatible with cxxrtl at all
<whitequark> 1 sec
<whitequark> back
<whitequark> so i think i understood something important about cxxrtl
<whitequark> on one hand, it is not a target, but a substrate. no one will write RTL *specifically* for cxxrtl. consequently, cxxrtl is stuck interpreting netlists thrown at it, and also doesn't have much say in that interpretation
<awygle> sudden extreme temptation to build design out of entirely clocks
<whitequark> do it :p
<awygle> somebody shows up in the digital design discord enthused about async logic about twice a month, one of them will succeed eventually :-P
<whitequark> ha
<awygle> sorry, continue
<whitequark> so. cxxrtl. cxxrtl doesn't really get to decide how to interpret the netlists, at least not arbitrarily. i think the way it'll work out in practice is that people have an ideal expectation for it (which is "i throw random verilog i found in the ditch at it and it DWIMs") and they will tolerate it not being ideal to some extent
<whitequark> until the point where the amount of hacks necessary to get the design to work is higher than the effort to use something else, i guess?
<whitequark> but! at the same time, cxxrtl is not built to provide affordances to terrible ancient verilog. it is built to do the exact opposite, to be convenient to embed and drive
<awygle> I believe verilator has similar restrictions, doesn't it?
<whitequark> sorta
<whitequark> they're *really* not into saying it, but as far as i understand verilator, it has a lot in common with pysim and cxxrtl
<whitequark> an event-driven simulator heavily biased towards running synchronous logic but nevertheless capable of doing async stuff
<whitequark> stuff like this:
<whitequark> Sometimes it is quite dicult for Verilator to distinguish clock signals from other data signals. Occasionally the clock signals can end up in the checking list of signals which determines if further evaluation
<whitequark> is needed. This will heavily degrade the performance of a Verilated model.
<whitequark> or this, which causes some of the more unpleasant code in cxxrtl:
<whitequark> If clock signals are assigned to vectors and then later used individually, Verilator will attempt to
<whitequark> decompose the vector and connect the single-bit clock signals directly. This should be transparent to
<whitequark> the user.OM
<whitequark> ah yes
<whitequark> Verilator calls the "oops! all async" mode "UNOPTFLAT"
<whitequark> awygle: i think cxxrtl might be worse off than verilator, actually
<whitequark> since it attempts to support hierarchical designs directly
<whitequark> this was the other thing i was going to mention
<whitequark> on one hand, cxxrtl does not get much say in the kinds of RTL it will consume. on the other, instead of passing this burden onto the host/embedder, it tries to be extra flexible from that side as well, which means supporting hierarchy, or sticking to coarse grained modeling even when the netlist is directly at odds with that
<whitequark> sure, you'll have it run faster if you flatten, but you don't have to. and sure, you'll have it run faster if you don't drive the same one wire from both comb and sync while also interleaving the two signals like some sort of serpentine (iirc, actual request i encountered, someone wanted to ship that)
<whitequark> but you don't have to
<whitequark> i think that this strategy is incompatible with a naive event based scheduler that exists in isolation from the netlist
<whitequark> imagine being stuck in a situation where matching the verilog behavior requires you to split a wire (with a mixed comb/sync driver) into two to avoid adding a delta cycle, and at the same time, the embedding environment is not capable of handling the netlist after `splitnets`
<whitequark> it is fortunate that we have this discussion, because a naive event based scheduler was kinda what i was going to start implementing
Bertl_oO is now known as Bertl_zZ
cjearls has joined #nmigen
<whitequark> awygle: ok, i read through verilator's docs and scheduler once more
<whitequark> we have indeed spent the last several days successfully reinventing verilator
<whitequark> it even does the clock inference thing i suggested above!
chipmuenk has joined #nmigen
<awygle> ha! that's great
<awygle> I'm going to bed now, talk more tomorrow. Night.
emeb_mac has quit [Quit: Leaving.]
<whitequark> night!
jeanthom has joined #nmigen
chipmuenk has quit [Quit: chipmuenk]
miek has quit [Ping timeout: 260 seconds]
nelgau has quit [*.net *.split]
mwk has quit [*.net *.split]
miek has joined #nmigen
peteut has joined #nmigen
nelgau has joined #nmigen
mwk has joined #nmigen
peteut has quit [Ping timeout: 260 seconds]
abutter has joined #nmigen
abutter has quit [Remote host closed the connection]
cjearls has quit [Quit: Leaving]
FFY00 has quit [Ping timeout: 260 seconds]
FFY00 has joined #nmigen
miek has quit [Ping timeout: 264 seconds]
miek has joined #nmigen
miek has quit [Ping timeout: 260 seconds]
<d1b2> <dub_dub_11> I definitely didn't understand everything there, but having just learned some basics about how Verilog and vhdl simulate it's really interesting to see inside the thought process of writing a different simulator
peteut has joined #nmigen
futarisIRCcloud has joined #nmigen
peteut has quit [Remote host closed the connection]
peteut has joined #nmigen
chipmuenk has joined #nmigen
miek has joined #nmigen
futarisIRCcloud has quit [Quit: Connection closed for inactivity]
<mithro> @whitequark - is pretty epic!
<_whitenotifier> [yosys] kammoh commented on issue #20: TCL support for yowasp-yosys -
Bertl_zZ is now known as Bertl
emeb has joined #nmigen
XMPPwocky has quit [Ping timeout: 258 seconds]
XMPPwocky has joined #nmigen
cr1901_modern1 has joined #nmigen
cr1901_modern has quit [Ping timeout: 264 seconds]
<awygle> morning y'all
<tpw_rules> hello
Bertl is now known as Bertl_oO
<mwk> Domain 'async_ff' is used but not defined
<mwk> hrm....
<mwk> somehow it doesn't notice the async_ff domain defined in xilinx 7series platform if it happens to be local=True
<mwk> (get_async_ff)
<mwk> *get_async_ff_sync
chipmuenk has quit [Quit: chipmuenk]
peteut has quit [Ping timeout: 264 seconds]
ianloic_ has quit [Read error: Connection reset by peer]
sorear has quit [Read error: Connection reset by peer]
ianloic_ has joined #nmigen
sorear has joined #nmigen
davidlattimore has quit [Ping timeout: 264 seconds]
davidlattimore has joined #nmigen
peteut has joined #nmigen
cr1901_modern1 has quit [Quit: Leaving.]
cr1901_modern has joined #nmigen
emeb_mac has joined #nmigen
peteut has quit [Ping timeout: 240 seconds]
peteut has joined #nmigen
peteut has quit [Ping timeout: 264 seconds]
<_whitenotifier> [nmigen] RobertBaruch opened issue #562: Way to start register with "random" value? -
peteut has joined #nmigen
<d1b2> <benzn> curios if someone can explain how these two chunks of code are semantically different
<d1b2> <benzn> for i in range(length - 1): m.d.comb += thermometer[i + 1].eq(thermometer[i])
<d1b2> <benzn> m.d.comb += thermometer[1:].eq(thermometer[:-1])
<d1b2> <benzn> (nevermind that they're likely to be optimized out)
<d1b2> <benzn> the latter throws all sorts of Warning: found logic loop in module top: cell $flatten\dac.$procmux$252 ($mux) wire \dac.thermometer [99] when synthesizing
<d1b2> <benzn> I was under the assumption that assigning a slice to another slice would map the signals 1:1 between each bit (by index) in the slice
<d1b2> <benzn> is that not right?
<agg> are you sure you want 'comb' there?
<agg> what you've written is equivalent to setting all bits equal to the first bit
<d1b2> <benzn> this is a delay chain
<agg> i expect you want m.d.sync instead of m.d.comb in that case
<d1b2> <benzn> so yeah, everything will eventually settle to whatever is fed into the first bit
<agg> oh, I see
<agg> my bad
<d1b2> <benzn> no worries, i'm definitely doing atypical things
<agg> you might find you need some platform specific attributes to preserve your intent there, otherwise I could imagine the synthesiser quite happily optimising it out
<whitequark> benzn: semantically, comb assignments do not have a delay in synthesis
<whitequark> there is no platform-specific attribute that would change that; use explicit primitive instantiation
<d1b2> <benzn> right, yeah I'm gonna go break out my handy TRELLIS SLICE momentarily
<d1b2> <benzn> but was just curious why the two alternatives above don't yell in the same way
<whitequark> oh
<whitequark> that's because yosys (and nmigen, at least once it actually does that) detects comb loops with signal granularity
<whitequark> not bit granularity
<d1b2> <benzn> ah, that make sense
<d1b2> <benzn> so they mean the same thing, but they're represented differently in an intermediate stage which means (potentially) different warnings, right?
<whitequark> yep
<d1b2> <benzn> cool, thanks!
<awygle> i was thinking about this when we were talking yesterday but does nmigen even allow you to make comb feedback loops without using Instance?
<awygle> thought it was supposed to prevent that
<whitequark> unfortunately, it does
<awygle> huh guess i understood wrong
<whitequark> understood what?
<awygle> that nmigen doesn't allow comb feedback
<whitequark> sorry, let me rephrase more clearly
<whitequark> nmigen doesn't allow it, but it doesn't detect it either
<whitequark> it's UB but you can express it
<awygle> ah
<awygle> it seems pretty detectable, but maybe at a later stage
jeanthom has quit [Ping timeout: 246 seconds]
<whitequark> yeah, together with the CDC stuff
<awygle> I meant more like "maybe in Yosys instead of nmigen proper" but yeah that too
emeb has quit [Quit: Leaving.]
<whitequark> yosys is even worse at detecting comb loops
<whitequark> half the passes just segfault