futarisIRCcloud has quit [Quit: Connection closed for inactivity]
proteusguy has joined #m-labs
<cr1901_modern>
whitequark: For my own peace of mind... even from the very beginning of the compat layer in nmigen, "self.sync" was _not_ an alias for the "sys" clock domain, correct?
<cr1901_modern>
I have no idea why I wrote it (and it's not required in omigen)
Getorix has quit [Ping timeout: 248 seconds]
<_whitenotifier-3>
[m-labs/nmigen] whitequark pushed 1 commit to master [+0/-0/±1] https://git.io/fjPxC
<_whitenotifier-3>
[m-labs/nmigen] whitequark ee15538 - back.pysim: correctly add gtkwave traces for signals with decoders.
<whitequark>
cr1901_modern: yes, from the very first commit with compat it uses "sync"
<whitequark>
cr1901_modern: as for what you wrote, that's actually still required?
<cr1901_modern>
Have not tested in a few days, but as of a few days ago, yes. If I don't include this line _and route the clock_ a bit further down, my design will be optimized away. >>
<cr1901_modern>
Note that this commit uses edalize; I used create_clock_domains=True to avoid needing the clock routing back then
<whitequark>
this will be needed until #57 is fixed
<cr1901_modern>
Even in the compat layer, "self.sync" internally isn't special? I.e. I could do a sed replace with say "self.my_clock" and things would work just fine?
<cr1901_modern>
Or is "self.sync" still special in the compat layer?
<whitequark>
no, in the compat layer, it *is* special
<whitequark>
because it's the compat layer.
<whitequark>
it's just oMigen code ported
<cr1901_modern>
So in omigen, if I were routing the clock manually, I would expect line 20 that I linked (most recent commit) to look like this:
<cr1901_modern>
Sure, I'm not arguing with that. But many omigen designs use implicit "sys". Was there no way to make only "sys" special to the compat layer? Considering "m.d.sync" in nmigen isn't special anyway in the first place
<cr1901_modern>
in nmigen proper*
<whitequark>
that'd probably just make the inevitable mismatches worse
<cr1901_modern>
I'll take your word for it. Anyways, clock domains could get very screwy in omigen. They are less so in nmigen once you understand them, but I am still thrown off by the rules when mentally keeping track of the differences between omigen, the compat layer, and nmigen. (Cont)
<cr1901_modern>
From what I can tell, you using self.d.sync is a _convention_, a decent default clock domain name. You then chose to make "self.sync" in the compat layer as an alias to "self.sync.sync" for symmetry, based on the convention you chose for the a default clock domain name.
<whitequark>
yes
<whitequark>
well, it's more than just a convention
<whitequark>
it's the default in many places. ClockDomain() itself, ResetInserter(), Memory.write_port()...
<cr1901_modern>
>more than just a convention <-- the "standardized default go-to domain name". I need a better one-word description for this.
<cr1901_modern>
Anyways, I think that answers my questions re: the compat layer naming. And #57 will take care of the rest.
<cr1901_modern>
Will #57 attempt to create a vendor-agnostic CRG like omigen?
<whitequark>
probably not
<whitequark>
the board is responsible for this
<cr1901_modern>
Fine. I think a default vendor-agnostic CRG should be included in nmigen though- it's common enough, and while it's not a lot of code, it's mildly easy to mess up.
<cr1901_modern>
Or maybe put it in nmigen_boards
<whitequark>
there's no vendor-agnostic CRG.
<whitequark>
for example on ice40 you *have* to ensure that you give BRAMs sufficient time to initialize
<cr1901_modern>
Sure there is, if you wait long enough with a counter before releasing reset :)
<whitequark>
so how long is long enough?
<whitequark>
one hour?
<whitequark>
you chose a reasonable value and then some board clocks itself from SB_LFOSC and it breaks.
<whitequark>
no, that should be an assertion
<cr1901_modern>
Idk the BRAM ice40 rules. It's actual time based and not cycle based?
<whitequark>
yes.
<cr1901_modern>
What's wrong w/ calculating a minimum bound to wait based on your chosen clock?
<cr1901_modern>
I guess it's not that important to autogenerate a CRG. Just mildly irritating to write one out each time.
<whitequark>
you can't do that in a vendor-independent way
<whitequark>
so the choice of CRG to be included on a board is a conscious one, to be made by the board file author
<cr1901_modern>
At least in general, a CRG is as simple as adding a submodule and nothing else (since all the I/O will be clocks and reset, there's no need to route it out into your IP- it can stay isolated in the submodule)
<whitequark>
nMigen will never create a ClockDomain() object by itself
<whitequark>
instead it will call you back if a design uses a nonexistent one
<cr1901_modern>
Right, the CRG will create two clock domains- a reset_less "actual clock pin" clock domain, and the clock domain you actually want to propogate to the rest of your design (default to "sync" by convention)
<whitequark>
yeah
<cr1901_modern>
in between you have logic to hold clock domain "sync" in reset however you need to. But those signals never need to propogate to the rest of your design
<cr1901_modern>
So I _assume_ adding a CRG in practice is as simple as adding a submodule from your platform's board file
<cr1901_modern>
(which declares the CRG)
<whitequark>
you don't need to do anything unless you have weird requirements
<whitequark>
Fragment.prepare() in Platform will call back into Platform
<whitequark>
and Platform will create the domain(s) that are inherent to the board
<cr1901_modern>
ooooooooh... alright.
<cr1901_modern>
overload your platform file if you have weird requirements?
<cr1901_modern>
wow
<cr1901_modern>
I mean subclass*
<whitequark>
no just create the sync domain yourself
<whitequark>
then that code would never kick in
<cr1901_modern>
ohhh right
<cr1901_modern>
Well, that answers all my qs about clock domains right now. Good to know it's logged now when I forget in a week :P
mumptai has joined #m-labs
<cr1901_modern>
whitequark: Do changes look okay to mercury now? I changed the names
<whitequark>
sorry, busy atm
<cr1901_modern>
sure
rohitksingh has joined #m-labs
tweakoz has joined #m-labs
proteusguy has quit [Remote host closed the connection]
tweakoz has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
tweakoz has joined #m-labs
tweakoz has quit [Client Quit]
tweakoz has joined #m-labs
tweakoz has quit [Client Quit]
tweakoz has joined #m-labs
tweakoz has quit [Client Quit]
tweakoz has joined #m-labs
tweakoz has quit [Client Quit]
tweakoz has joined #m-labs
tweakoz has quit [Client Quit]
tweakoz has joined #m-labs
tweakoz has quit [Client Quit]
tweakoz has joined #m-labs
tweakoz has quit [Client Quit]
tweakoz has joined #m-labs
tweakoz has quit [Client Quit]
forrestv has quit [Ping timeout: 252 seconds]
rohitksingh has quit [Ping timeout: 268 seconds]
forrestv has joined #m-labs
X-Scale has joined #m-labs
mumptai has quit [Quit: Verlassend]
<_whitenotifier-3>
[nmigen] Wren6991 commented on pull request #40: WIP: Expand and document lib.cdc - https://git.io/fjXTi
<cr1901_modern>
whitequark: I am doing something very cursed. You have been warned.
<cr1901_modern>
http://ix.io/1Oji I'm trying to force a dlatch, but "q" gets a reset value even when it's reset_less
<whitequark>
(without looking at code) nope. nmigen *never* infers latches.
<whitequark>
in fact it is not possible to express a latch in nmigen.
cedric has quit [Ping timeout: 272 seconds]
<whitequark>
(you could instantiate a yosys primitive for it, if you *really* need one for some reason)
<cr1901_modern>
Well, I'm trying to and it's not working, so good job :P
<cr1901_modern>
I don't need a latch.
<cr1901_modern>
I was playing around
<whitequark>
of course it's not working, I'm not using the Yosys feature that recognizes latches at all
<whitequark>
you have to opt into that
<cr1901_modern>
that doesn't matter if I run proc_dlatch later
cedric has joined #m-labs
cedric has quit [Changing host]
cedric has joined #m-labs
<cr1901_modern>
which is what I was doing to test
<whitequark>
nope.
<whitequark>
proc_dlatch recognizes the use of the said feature and converts it into actual latches.
<whitequark>
but there's nothing for it to recognize. it's a no-op.
<whitequark>
on any code nmigen can possibly emit.
<cr1901_modern>
what yosys feature?
<whitequark>
`sync always`
<whitequark>
absolutely no combination of yosys operations on any nmigen code will produce a latch.
<cr1901_modern>
If I remove "assign \q 1'0", nothing changes. I would've figured yosys could infer a latch from that (since there's no default for q, the process "looks like" a latch)
<cr1901_modern>
Weird
<whitequark>
nope.
<whitequark>
has to use `sync always`
<cr1901_modern>
Yes I get that, I don't understand why
<whitequark>
if you remove the initial assign it just becomes 1'x
<whitequark>
the thing is that yosys does not support combinatorial loops at all, *even if they form a latch*
<whitequark>
so the frontend has to deliberately break all possible combinatorial loops that it wants to end up as latches
<whitequark>
`sync always` works the same way as `sync posedge` except, well, without a clock
<cr1901_modern>
Why does it become 1'x?
<cr1901_modern>
just the "default"?
<whitequark>
any not explicitly initialized signal becomes 1'x
<whitequark>
that's kind of what 'x is
<whitequark>
"value you do not know"
<cr1901_modern>
Is that an RTLIL thing? Because if you do
<cr1901_modern>
q <= data;
<cr1901_modern>
"always @ ( en or data)
<cr1901_modern>
if (en) begin
<cr1901_modern>
end" in Verilog, there is combinatorial feedback when "en" isn't asserted. Wouldn't initializing to 1'x implicitly at the top of a block break that?
<cr1901_modern>
or "once you know the value, the 1'x doesn't matter"?
<whitequark>
I don't understand the question
<whitequark>
I suggest looking at the RTLIL for the snippet you posted
<cr1901_modern>
I am asking when you say "any not explicitly initialized signal becomes 1'x", does this apply to Verilog always blocks as well as RTLIL processes?
<whitequark>
I was talking about RTLIL signals
<whitequark>
the Verilog semantics is more complex, of course
<jcreedon15>
Is there a way in nmigen to include a verilog file? I have some existing code that I want to convert over one module at a time. Is this a bad idea?
<whitequark>
are you already using nmigen.build?
<jcreedon15>
I am not
<whitequark>
then it probably makes more sense to emit nmigen output to a verilog file, and use it together with your existing code
<whitequark>
you can use an Instance() to refer to any of your existing verilog modules
<whitequark>
and vice versa
<cr1901_modern>
what does it mean to "break up a combinatorial loop" in practice in yosys?
<cr1901_modern>
I can see in RTLIL that a signal "a" will never directly connect to signal "a"
<whitequark>
directly or through any combinatorial cell like $and
<whitequark>
if you ever have a loop in the graph, you have to break it with a sync something
<whitequark>
it could be a sync cell like $dff, or it could be a sync action in a process
<cr1901_modern>
but will have an intermediate signal that connects the two within a process
<whitequark>
but having loops in the graph that only include combinatorial elements is invalid and will generally lead to incorrect synthesis
<whitequark>
or flat out error
<whitequark>
I think there are some restricted circumstances where you can use them
<cr1901_modern>
At this point, "sync always" feels like it's cheating- it's a way around yosys' "no combinatorial loops" restriction with the semantics that match... well, a signal that instantly propogates from input to output unconditionally.
<cr1901_modern>
which, in the context of a latch, would be connecting a signal to itself
<whitequark>
yes
<whitequark>
it's not cheating; it's breaking the combinatorial loop in a way that's meaningful for further synthesis
<jcreedon15>
whitequark: ah, okay thanks!
<cr1901_modern>
Will the yosys code that breaks comb loops ever generate something besides "sync always" to break the loop?
<cr1901_modern>
latch is one of the few legit cases for comb feedback
<cr1901_modern>
can't think of many others
<whitequark>
cr1901_modern: yosys verilog frontend always generates sync always for all always @(*) blocks
<whitequark>
even when there is no latch
<whitequark>
if there's no latch it's a no-op
<whitequark>
if there is, proc_dlatch will add a latch
<cr1901_modern>
ahh
<cr1901_modern>
>if you ever have a loop in the graph, you have to break it with a sync something
<cr1901_modern>
>it could be a sync cell like $dff, or it could be a sync action in a process
<cr1901_modern>
^Was referring to this. Thought maybe yosys did something else for comb loops that aren't latches (even if it's bad form, likely to fail synthesis etc)
<whitequark>
nope, it errors out in some passes
<whitequark>
and others will likely silently do bad things
<cr1901_modern>
So, basically, yosys _could_ break comb loops using stuff besides "sync always", but in practice, 1. it doesn't, and 2. expect bad things to happen in general if you're not inferring a latch?
<whitequark>
define could
<cr1901_modern>
>it _could_ be a sync cell like $dff, or it could be a sync action in a process <-- these were your words
<cr1901_modern>
emphasis mine
<whitequark>
a combinatorial loop made from logic cells is a) ambiguous (there's no single obvious place to break it), and b) can oscillate
<whitequark>
whereas with sync always, the frontend explicitly gives the backend the points at where it should insert latches, if it turns out there is a loop
<cr1901_modern>
(by logic cells you mean "and", "or", etc?)
<whitequark>
any other design would not work reliably