<cr1901>
The Usage is fixed online (uses amaranth streams instead of my own bespoke sig): https://smolarith.readthedocs.io/en/latest/usage.html. Everything's ready except me ripping out the BCD stuff just for the release (it needs more TLC)
<cr1901>
wq: You might like sphinx_copybutton for the amaranth docs (lets you copy code snippets with a button)
frgo has joined #amaranth-lang
frgo has quit [Ping timeout: 252 seconds]
FFY00_ has joined #amaranth-lang
FFY00 has quit [Ping timeout: 264 seconds]
frgo has joined #amaranth-lang
<whitequark[cis]>
<cr1901> "wq: You might like sphinx_copybu..." <- I have that for Glasgow docs yea
<shadlock0133[m]>
uuuh, i thought it's amaranth matrix
<shadlock0133[m]>
oh no, whiteq*ark
<whitequark[cis]>
but it is amaranth matrix...
jfng[m] has joined #amaranth-lang
<jfng[m]>
rfc 68 mentions abstract buffers in its rationale for driving oe at the pin granularity
<jfng[m]>
does the `PinSignature` of the amaranth-soc gpio peripheral count as such ?
<jfng[m]>
each port has an array of pins, whose directions can be independently set from CSRs, and i wonder if it should be replaced by a lib.io primitive
<jfng[m]>
but i guess that is only until we are able to write them in python in the future
<whitequark[cis]>
I mean there's always value in writing cxxrtl models in C++
<whitequark[cis]>
the cxxrtl use case is actually closer to #69
<whitequark[cis]>
in that you could give the GPIO peripheral a bunch of ports, get back all the triples, and route them to whatever you like at the toplevel
<whitequark[cis]>
this actually makes me wonder if a pin multiplexer should rather be implemented as a custom PortLike with the platform knowing how to instantiate it
<whitequark[cis]>
so that we don't have to build all of the peripherals with the assumption of someone maybe possibly using a pin multiplexer later
<jfng[m]>
that's an interesting idea
<whitequark[cis]>
the proposed methodology for amaranth-stdio would involve passing ports into the peripheral toplevel
<whitequark[cis]>
(well, it's not proposed yet, I'm planning to propose it)
<whitequark[cis]>
meeting in a hour
notgull has quit [Ping timeout: 252 seconds]
<whitequark[cis]>
good evening everyone, it is time for our scheduled weekly meeting
<whitequark[cis]>
who is attending today?
<tpw_rules>
hello, i will be here
Wanda[cis] has joined #amaranth-lang
<Wanda[cis]>
meow
<jfng[m]>
o/
<mcc111[m]>
i am here
mcc111[m] has joined #amaranth-lang
<mcc111[m]>
[note: i have a non-meeting item i'm going to ask about, after the meeting ends. it concerns an incomplete RFC I am trying to write]
Chips4MakersakaS has joined #amaranth-lang
<Chips4MakersakaS>
o/
<zyp[m]>
I like #69 too, but would like an obvious extension path to xdr>2 as well, which I guess is asking too much at this point since real regs aren't even supported in any form yet with the new style
<whitequark[cis]>
#69 doesn't seem like it would change for xdr>2 since it's still going to be the same three fully async signals
<Wanda[cis]>
so the issue with xdr>2 is that it's too platform-specific
<whitequark[cis]>
in your high ratio gearboxes you can use it all the same, using the fast clock, a mux, and some registers to model it for example
<whitequark[cis]>
also what Wanda says (but it's less of a problem now that we have the buffer system)
notgull has joined #amaranth-lang
<Wanda[cis]>
the plan is to have per-platform things like XilinxSerdesBuffer
<Wanda[cis]>
now, we already have a problem in #69 of it not supporting DDR buffers
<Wanda[cis]>
the solution for that is, I believe, a way for elaboratables to inject processes into the simulator
<whitequark[cis]>
so, #69 was going to be the first agenda item
<Wanda[cis]>
so when we get a SimulationPort in DDRBuffer, we just implement the DDR reg via a sim process
<whitequark[cis]>
re DDR buffers, you could also use a mux dispatching based on clock
<Wanda[cis]>
but that depends on functionality we don't have yet, so it's not included in #69; same solution would presumably be involved for xdr>2
<Wanda[cis]>
heh
<Wanda[cis]>
or that, yeah; I suppose we can just cheat since it's sim anyway
<whitequark[cis]>
yes. I haven't required it in the RFC since it's unclear if we'll regret doing that
<whitequark[cis]>
but I think it's fine? since it's registered first, anyway
<Wanda[cis]>
I think there is a glitch on the mux
<Wanda[cis]>
but it's unclear if it matters in any way
<Wanda[cis]>
it might if you do an .edge() on it, actually
<whitequark[cis]>
if you drive a clock with it, glitches would matter
<Wanda[cis]>
well
<whitequark[cis]>
yes, I've hit issues with glitchy buffers
<Wanda[cis]>
driving a clock via DDRBuffer is well-established, so...
<whitequark[cis]>
so it remains unimplemented for the time being then
<cr1901>
I'm sorta here; I'm going to abstain from both today
<whitequark[cis]>
it doesn't seem like we'll need design changes to SimulationPort itself to handle this issue
<Wanda[cis]>
yes
<whitequark[cis]>
just to the buffer implementation, which is fine
<Wanda[cis]>
hm
<Wanda[cis]>
it'd be kinda nice to have the sim port show up as a three-valued (1/0/z) signal in VCD
<Wanda[cis]>
but not convinced it's worth it, or properly doable
<tpw_rules>
what happens if you pass it to DDRBuffer now?
<whitequark[cis]>
Wanda[cis]: we could add a custom formatter for it
<Wanda[cis]>
tpw_rules: failure with known port type
<tpw_rules>
ok
<Wanda[cis]>
s/known/unknown/
<Wanda[cis]>
(also DDRBuffer will just fail in general if used without a platform)
<whitequark[cis]>
the RFC inherently allows for i/o/oe to be Signal or Slice of Signal, so making it a single Signal with a magic formatter seems ok
<whitequark[cis]>
oh, it should probably mention what happens if you access .i of an output only signal
<whitequark[cis]>
(TypeError)
<cr1901>
What about the case where you accidentally drive .i and .o with different values while .oe is asserted at a given point in time?
<whitequark[cis]>
cr1901: you can have this happen on a real device too, if you drive 1 and then short the pin to ground
<whitequark[cis]>
I've actually seen it happen with some poor GPIO
<Wanda[cis]>
there is another question here though
<Wanda[cis]>
we don't have a concept of "driving" or "not driving" i, do we?
<Wanda[cis]>
what do you see on Buffer.i if you use a bidir buffer + simulation port, and set Buffer.oe to 1?
<Wanda[cis]>
does it forward o to i?
<Wanda[cis]>
because it's something that, in the absence of bus faults, gateware could be relying on
<cr1901>
isn't that what the wand/wor types in sysverilog handle?
<cr1901>
>you can have this happen on a real device too, if you drive 1 and then short the pin to ground <-- well yes, but I assume this is undesirable
<whitequark[cis]>
Wanda: imo `.i` should be treated as untrusted input
<whitequark[cis]>
so the answer is "don't rely on that, if you do, that's a bug"
<tpw_rules>
still, most simulation logic would expect to have looped it back, right?
<whitequark[cis]>
hm
<Wanda[cis]>
cr1901: this is a legit use for some cases
<cr1901>
besides OC?
<jfng[m]>
maybe the implementation could do this as a best effort, but we wouldn't specify it in the RFC ?
<Wanda[cis]>
(eg. Spartan 6 has the weird OPEN_DRAIN iostandard that explicitly allows you to do this)
<whitequark[cis]>
if we do loop it back somewhere, the right place to do that would be in the io.Buffer/io.FFBuffer impl, i think
<tpw_rules>
i wonder if there needs to be more intelligence in SimulationPort than just holding signals. have an interface for the device too. that would also make it more clear where to put a gearbox?
<Wanda[cis]>
hmm.
<whitequark[cis]>
I don't understand your comment
<whitequark[cis]>
i/o/oe are the interface for the device
<Wanda[cis]>
loopback in *Buffer would ... work, but have a little bit of duplication
<whitequark[cis]>
duplication?
<Wanda[cis]>
well you have to implement loopback in every buffer
<Wanda[cis]>
actually you know
<Wanda[cis]>
it's one mux
<whitequark[cis]>
so, two?
<Wanda[cis]>
it's not a problem
<whitequark[cis]>
it's literally two lines
<Wanda[cis]>
yeah
<tpw_rules>
they are from the fpga logic's perspective though. in a real circuit there would be a wire and then the device's own i/o/oe, which have i/o reversed
<whitequark[cis]>
tpw_rules: this is covered in the RFC
<whitequark[cis]>
if you're simulating two devices against each other you give them both a SimulationPort and then use something for the interconnect
<Wanda[cis]>
tpw_rules: the intereface is essentially the same as if you'd JTAG+INTEST'ed the FPGA
<tpw_rules>
Wanda[cis]: ok, if that's already a given, then my suggestion doesn't make sense
<mwk>
hrm
<mwk>
did matrix.org just... break
<tpw_rules>
maybe
whitequark has joined #amaranth-lang
<tpw_rules>
hello
<whitequark>
matrix.org is fucked again
<whitequark>
we'll have to wait until it's not
<tpw_rules>
how long does that usually take
<whitequark>
"Who Knows"
<cr1901>
Well, seeing that they've taken 3 years to bridge Libera and still haven't gotten it right... probably forever
jfng1 has joined #amaranth-lang
<cr1901>
If ".o and .i can have opposite values while .oe is asserted and it's not a bug (e.g. spartan6)", I guess we can punt on that for futures RFCs, and for now "don't do that/don't use those modes where it's allowed".
<whitequark>
please leave the discussion for until after people on matrix can rejoin
<Wanda[cis]>
(this is strictly better than emulating a wire since you can check the OEs are set properly)
<whitequark[cis]>
test
jfng1 has quit [Quit: Client closed]
<whitequark[cis]>
is this up?
<whitequark[cis]>
ok it is
whitequark has quit [Quit: leaving]
<Wanda[cis]>
moderately
<jfng[m]>
we've got 10mins left
<Wanda[cis]>
I still have an unsent message in UI?
<Wanda[cis]>
wtf
<Wanda[cis]>
okay I managed to clear this up
<whitequark[cis]>
yeah you have to reboot element every time this happens
<whitequark[cis]>
because their broken server message queue is also broken
<whitequark[cis]>
matrix moment
<whitequark[cis]>
anyway, we have 10 minutes left
<whitequark[cis]>
<tpw_rules> "i wonder if there needs to be..." <- i was going to say "if you're simulating two devices against each other you give them both a SimulationPort and then use something for the interconnect, and this [interconnect that pretends to be a bus] can't be in SimulationPort because how to handle that (and, potentially, which delays to add) is very testbench-specific"
<tpw_rules>
okay that makes sense
<whitequark[cis]>
i have some code that uses not-quite-SimulationPort (it really just pokes the buffer directly) in Glasgow and writing models this way seems fine
<mcc111[m]>
My impetus for working on this is, I was helping with the documentation, and m.d/m.domains are not fully documented. But when I try to write better documentation every possibility I come up with is so weird it makes me think we should just do something more straightforward.
<whitequark[cis]>
it was actually planned, by me
<mcc111[m]>
oh. were the names planned, however?
<whitequark[cis]>
yes. i just planned them poorly, lol
<mcc111[m]>
i.e. "domain" being readable and "domains" being writable
<mcc111[m]>
ah
<whitequark[cis]>
it's present in the initial commit iirc
<mcc111[m]>
* being readable-only and, * being writable-only
<whitequark[cis]>
you might be the first person i remember asking a question about it, so it can't be that confusing
<mcc111[m]>
It makes perfect sense as long as you don't try to think about it.
<mcc111[m]>
If you try to think about it, suddenly there are problems.
<jfng[m]>
TIL about "domain", i only knew of m.d and m.domains, so i wasn't confused
<jfng[m]>
now i am
<whitequark[cis]>
the thing with your proposal is that i don't believe there are any python shenanigans that allow implementing it at all
<whitequark[cis]>
which is why i asked how you intend to implement it
<mcc111[m]>
yes, i've thought about it, and you might be right
<whitequark[cis]>
the best we can do is to make m.domains["sync"] not return the same object that's assigned there via m.domains["sync"] = ClockDomain()
<mcc111[m]>
so, excuse the dumb question, but… doesn't "d" have a weird thing where if you ask for something that "doesn't exist", like m.d.feowjfa, it just returns a forwarding object that will correspond to the ClockDomain by that name later when it is created?
<tpw_rules>
i mean there is always the cursed ClockDomain subclass
<whitequark[cis]>
the what?
<tpw_rules>
that is a possible method of implementation
<mcc111[m]>
jfng[m]: Then maybe the solution is to remove "domain", and officially document "d" as expanding to something that is not "domain".
<whitequark[cis]>
mcc111[m]: `m.d.<whatever>` is *always* a proxy object
<whitequark[cis]>
and ClockDomain() doesn't have a += implementation on it at all
<mcc111[m]>
Or document "d" as "the domain readback object" or something.
<whitequark[cis]>
this isn't a question of "oh, it works out if the domain exists". it never works ou
<whitequark[cis]>
s/ou/out/
<jfng[m]>
`csr.Register` has a `fields` parameter to define fields, a `.field` attribute to access them, which is aliased to `.f`
<mcc111[m]>
an m.d/m.domains split feels more defensible than an m.domain/m.domains split, and m.domain is a typo trap waiting to happen
<jfng[m]>
jfng[m]: (oddly similar)
<whitequark[cis]>
is it a typo trap?
<whitequark[cis]>
if you make a typo in either direction you get a TypeError instantly
<Hoernchen>
it just was a reading trap right now for me...
<mcc111[m]>
imagining every line of amaranth beginning with m.f. and all the code just sounding real angry
<whitequark[cis]>
both m.domain.x = ClockDomain() and m.domains.sync += a.eq(b) instantly fail
<whitequark[cis]>
sure, they won't in dead code, but that's just Python
<mcc111[m]>
whitequark[cis]: i think i mean, what if someone means to type `m.domains["sync2"] = x` and they instead type `m.domain["sync2"] = x`. Will they get an error that clearly communicates they should have typed m.domains?
<mcc111[m]>
catherine, is it your opinion that "m.domain" existing as an alias for "m.d" is a good thing?
frgo has quit [Remote host closed the connection]
<whitequark[cis]>
considering that nobody as far as i'm aware has hit this issue in anger (you only discovered it while we were doing an exhaustive sweep of all code), it doesn't seem to be a bad thing at least
<whitequark[cis]>
it's kind of weird, i guess, but we've also explicitly approved, as a community, the exact same field/fields split for the CSR registers and nobody objected
<mcc111[m]>
i think the case i'm worried about is someone makes the m.domain typo for m.domains, go "oh! there's an m.domain object! what does it do?" and then looks it up in the documentation, which doesn't list it.
<jfng[m]>
so for the CSR case, there was actually a good reason (single-field registers)
<whitequark[cis]>
um
<mcc111[m]>
whitequark[cis]: oh. hm.
<mcc111[m]>
i misunderstood the point about fields earlier.
<whitequark[cis]>
i don't understand why the solution to an undocumented entity in the language is an RFC?
<whitequark[cis]>
surely that should be "document it"
frgo has joined #amaranth-lang
<whitequark[cis]>
we still have an open issue for documenting every single thing in amaranth.hdl, which we'll eventually close
<mcc111[m]>
because my preferred solution is not to document it, my preferred solution is to delete it.
<mcc111[m]>
if the community tells me "this is normal for this language and we should treat it as normal", then i delete my rfc and document it
<whitequark[cis]>
sorry, that doesn't follow
<whitequark[cis]>
if your worry is that it's undocumented then suggesting to document it makes sense. if your worry is that it's confusing then suggesting to change or remove it makes sense
<whitequark[cis]>
but i don't understand your reasoning as you lay it out
<mcc111[m]>
I am worried about both things. I think both those things are bad.
<mcc111[m]>
If you/the community agree it is confusing, then we should change or remove it— and then the documentation worry goes away, or is at least simpler to handle.
<mcc111[m]>
If the conclusion is I am *wrong* to consider it confusing, then ok, I *still* have the documentation worry, but yes in that case I can fix it with a simple doc PR rather than an RFC.
<whitequark[cis]>
you actually can't because Module as a whole has no reference documentation
<jfng[m]>
ah, i think i know why
<mcc111[m]>
So the question, which maybe I should have asked before posting the RFC: is this confusing? "read from domain, write to domains", I mean.
<whitequark[cis]>
but eventually yes that will become a possible avenue
<jfng[m]>
you can add multiple domains at once, right ?
<mcc111[m]>
whitequark[cis]: Is that intentional or is that because we never got to it
<whitequark[cis]>
as for the two options: I pick neither
<jfng[m]>
whereas, you can only read a single one at a time with `m.domain.<...>`
<whitequark[cis]>
I can see the argument that it's confusing, and I can see that nobody seems to get confused by it in actual real life usage, and I can also see churn that would result
<mcc111[m]>
jfng[m]: What would the syntax for tha tbe?
<whitequark[cis]>
mcc111[m]: it is because I haven't got to it, yes
<whitequark[cis]>
(and there's mountains of work before we get to minutae of Module)
<whitequark[cis]>
mcc111[m]: `m.domains += ClockDomain("sync"), ClockDomain("fast")` but multiple things happen to be accepted, like with `m.d.comb +=`
<whitequark[cis]>
s/things/syntaxes/
<mcc111[m]>
hm, okay.
<mcc111[m]>
i guess i learned a new python feature today
<whitequark[cis]>
it's just a tuple
<whitequark[cis]>
same behavior as m.domains += tuple(a, b)
<mcc111[m]>
anyway, from this conversation it appears unless i can come up with a magic python trick to make the unification work, the thing to do is nothing
<whitequark[cis]>
and yeah I guess the CSR field/fields split is actually not exactly the same since those would refer to the same object regardless of the <...>s
<whitequark[cis]>
mcc111[m]: yes. there are a few ways that make that work which include an invasive (API-surface-visible) change of some kind
<whitequark[cis]>
for example to make the object returned by `m.domains[<whatever>]` aka `m.domain[<whatever>]` aka m.d[<whatever>]` have fake `.clk` field that contains `ClockSignal(<whatever>)`
<mcc111[m]>
The making API surface is pretty nice. I'm not very interested in making user-visible changes to it.
<mcc111[m]>
s/making/existing/
<whitequark[cis]>
* for example to make the object returned by `m.domains[<whatever>]` aka `m.domain[<whatever>]` aka `m.d[<whatever>]` have fake`.clk`field that contains`ClockSignal(<whatever>)`
<whitequark[cis]>
so you'd be making a breaking change that removes existing ability to read a ClockDomain object out of m.domains
<mcc111[m]>
whitequark[cis]: that doesn't sound so bad… would that require modifying large amounts of code to add explicit `.clk` reads?
<whitequark[cis]>
I don't understand the question
<mcc111[m]>
`question withdrawn
<jfng[m]>
whitequark[cis]: `fields` and `field` are actually not the same objects, the former contains `csr.Field`s, the latter are field actions
<whitequark[cis]>
oh
<whitequark[cis]>
okay so it is the same situation then
<whitequark[cis]>
on the whole it doesn't seem like anyone would be seriously bitten by this if we improve diagnostics
<whitequark[cis]>
considering that nobody has complained in 5 years
<jfng[m]>
there may be survivorship bias, as early adopters have learned amaranth without documentation
<whitequark[cis]>
isn't it kind of vacuously true that early adopters are more tolerant of issues with a language?
<jfng[m]>
rather, more susceptible to submit bug reports, i'd say
<whitequark[cis]>
mcc111: so I'd encourage you to open an issue to improve diagnostics for typos in either direction
<mcc111[m]>
okay. that makes sense, i can do that.
<mcc111[m]>
and i'll assume any other projects can be deferred until the documentation process reaches Module.
<whitequark[cis]>
re: the faking ClockDomain in the proxy object solution, we are unlikely to consider it on its own without thinking about how it ties into wider clock domain rework still planned for this release cycle
<mcc111[m]>
s/projects/questions/
<mcc111[m]>
whitequark[cis]: I'll see if I can be present for that RFC discussion.
<mcc111[m]>
Whenever it happens.
<mcc111[m]>
I'm going to go see an animal about a well. Thanks for the explanations.
<whitequark[cis]>
there will be many pre-RFC discussions and probably many RFC discussions
<whitequark[cis]>
it's going to be probably the biggest change since interfaces
<mcc111[m]>
is that the thing about making domains be linked to something other than raw string names
<mcc111[m]>
* about making clock domains be, * than raw global-ish string names
<whitequark[cis]>
I'm not sure what you're referencing
<mcc111[m]>
ok, don't worry about it. ttyl.
<whitequark[cis]>
Wanda: bikeshed aside, what do you think of `oe` for `SimulationPort`?
<Wanda[cis]>
as in, granularity?
<whitequark[cis]>
yes
<whitequark[cis]>
I filed 68 and 69 together since that seemed related somehow
<whitequark[cis]>
well, it is related, it's both about oe granularity
<Wanda[cis]>
fulfilling the port contract requires the oe to be bit-granular
<Wanda[cis]>
otherwise it's not sliceable
<Wanda[cis]>
and peripherials can reasonably expect it to be
<whitequark[cis]>
so your view is that there is not really an alternative?
<Wanda[cis]>
yes
<whitequark[cis]>
thanks
<whitequark[cis]>
then I guess we're down to one unresolved question
<whitequark[cis]>
actually, if oe is not bit-granular, then simulation ports cannot be concatenated either
<whitequark[cis]>
which isn't a part of the port contract (maybe it should be), but something i'd expect almost as commonly as slicing
<Wanda[cis]>
yeah
<whitequark[cis]>
I have to say that I'm pretty happy how the new I/O has been working for Glasgow
<Wanda[cis]>
heh
<Wanda[cis]>
you may have mentioned it a few times, yes
<whitequark[cis]>
and the blocks I wrote for Glasgow should be easy to migrate to amaranth-stdio once we have SimulationPort
<whitequark[cis]>
especially if they are documented/versioned as black boxes of the "QSPIController: input is mode (X1/X2/X4) plus octet, output is octet" kind
nyanotech has quit [Remote host closed the connection]
<zyp[m]>
<Wanda[cis]> "so the issue with xdr>2 is..." <- yeah, I'm not asking for a full implementation of a simulated buffer in amaranth itself, just the ability to plug in a implementation that matches e.g. ECP5 IDDRX2/ODDRX2 timings
<zyp[m]>
I'm intending to write more code using IDDRX2/ODDRX2 buffers and I'm very interested in simulating it in particular to ensure all the latencies are accounted correctly for
frgo_ has joined #amaranth-lang
frgo has quit [Read error: Connection reset by peer]
frgo_ has quit [Remote host closed the connection]