<cr1901>
Okay, then I would err towards "yes, keep it in stdlib"
<adamgreig[m]>
it's possible to use a lut on an fpga, but every time I've tried I've regretted it: generally higher latency, plus uses up 1+ BRAMs
<adamgreig[m]>
since it's hardware, you can just instantiate the CRC circuit, and there's an obvious extension to the 1-bit-serial circuit you see on wikipedia to an a m-bits-parallel circuit
<galibert[m]>
it's a little annoying it can't do dual sizes (32+8)
<adamgreig[m]>
yea, that's in the rfc as a possible extension/future work
<adamgreig[m]>
it would be nice but I think it's somewhat more niche and it wasn't clear to me how to do it optimally; naively it seems like it requires a lot of logic
<adamgreig[m]>
you might be able to do some clever sharing though
<whitequark[cis]>
adamgreig: do you have appetite for handling PRBSes? (or just LFSRs in general)
<adamgreig[m]>
I have an 80% written RFC
<whitequark[cis]>
nice!
<adamgreig[m]>
and then other things jumped on the priority list
<adamgreig[m]>
and it hasn't seen an edit in a few months
<whitequark[cis]>
I would be quite happy to have it both personally and as a maintainer
<adamgreig[m]>
so a huge appetite, I really want it
<adamgreig[m]>
not least because it would be another entire module I can delete from my existing codebase and replace with an import from amaranth :P
<adamgreig[m]>
doing that for crc was great
<cr1901>
adamgreig[m]: Yea, I can't visualize it and would have to see, tbh. Ross' paper discusses the 1-bit serial version in software and segues to the LUT approach. I treat those as two different methods
<adamgreig[m]>
once that's done and if you want I'll also write up my 8b10b encoder/decoder :P
<whitequark[cis]>
adamgreig: yeah, I'll similarly remove some code from Glasgow *and* there will be a really easy way to write SERDES tests in Amaranth now
<whitequark[cis]>
or memory tests, or...
<cr1901>
it wasn't clear to me that 1-bit-at-a-time CRC can be extended to n-bit-at-a-time CRC in a natural way. But if it does, then "there's only one way to do it" sounds reasonable
<adamgreig[m]>
cr1901: are you familiar with linear algebra in general like y=Ax sort of thing?
<cr1901>
yes
<adamgreig[m]>
CRCs are linear codes, there's some generator matrix A for a given CRC where y is a codeword and x is a data word
<cr1901>
n-bit CRC is linear combos of 1-bit-at-a-time CRC or something
<adamgreig[m]>
yea exactly
<cr1901>
It took me _hours_ looking at that damn paper to convince myself that "it works in software" tho
<adamgreig[m]>
because it's linear you get superposition, so you work out the 1-bit CRC for each input bit position and add them, basically
<adamgreig[m]>
I think the software LUT is philosophically the same
<cr1901>
Also, linear combos of previous bits can affect what the next value to XOR is
<galibert[m]>
yeah, software LUT is the same idea
<whitequark[cis]>
adamgreig: for the 8b10b decoder, I think we need to think about how much scope this can potentially expand to. do we want to handle HDMI 8b10b? do we handle 64b66b and 128b130b? how much customizability (word width for example, which is fairly easy for 8b10b with just running disparity, but more complex for 64b66b) we want?
<adamgreig[m]>
Catherine: I will try and get the LFSR/PRBS done soon, if nothing else it would be useful to get feedback
<whitequark[cis]>
it is possible there is a reasonable way to handle 8b10b, it is possible there isn't. I genuinely don't know
<adamgreig[m]>
it looks so much like the CRC one because of the split into a sort of set of parameters and the actual implementation, and you can have a catalogue of PRBSs
<whitequark[cis]>
yes, I think that would be a really good way to design LFSR/PRBS
<adamgreig[m]>
64b66b and 128b130b are really really different to 8b10b
<cr1901>
HDMI2USB used a LUT for 8b10b (I know it's a different 8b10b)
<whitequark[cis]>
yeah, I know that they use a completely different architecture
<adamgreig[m]>
well I mean, under the hood
<whitequark[cis]>
my question is that of scope: how do we decide which line codes to add and which to omit?
<adamgreig[m]>
but yes I think the answer is if you decide 8b10b can be included, why not 64b66b
<adamgreig[m]>
complexity of implementation is a fair reason...
<whitequark[cis]>
I think we can potentially decide that 8b10b has "one correct way to do it" and 64b66b does not
<adamgreig[m]>
even for 8b10b I've seen multiple fpga implementations used, but I could believe some were strictly inferior tbh
<whitequark[cis]>
based on how the implementation looks like and how they can be used
<adamgreig[m]>
a lot comes down to "do you want to use a bram for this, plus take the latency hit, or do you want to do it in logic"
<galibert[m]>
Catherine: that would smell a little of BS though. Just saying that one makes sense on current fpgas and the other not so much could be better understood
<whitequark[cis]>
I'm not actually sure when you'd want to use a BRAM for 8b10b
<adamgreig[m]>
bram probably higher fmax
<adamgreig[m]>
(untested statement)
<whitequark[cis]>
galibert: sure, what I mean is that there is a lot of uncertainty
<adamgreig[m]>
but i've seen someone use it in some open source migen or amaranth or something, maybe artiq?
<whitequark[cis]>
artiq did use that implementation, yes
<adamgreig[m]>
my implementation is just the set of logic equations
<adamgreig[m]>
I also tried feeding them to a logic minimiser to take out common terms. and it made it worse obviously
<whitequark[cis]>
I'm actually not sure whether there is ever any reason to use software 8b10b on a Xilinx device
<adamgreig[m]>
naming is the other problem :p my module is called b8b10
<whitequark[cis]>
if I remember the rationale for the use of software 8b10b in ARTIQ correctly, then with more experience including specifically with Xilinx transceivers, I think my response to that is "it's a skill issue"
<adamgreig[m]>
at least it's very easy to fully verify
<adamgreig[m]>
not very many possible input/output pairs :P
<whitequark[cis]>
adamgreig: that's certainly an implementation
<adamgreig[m]>
it's maybe 25% of a decoder :P
<adamgreig[m]>
anyway, I think you can easily write "a good and demonstratably correct pure-logic encoder/decoder" with a fairly uncontroversial (hopefully...) interface, but I'm sure people out there have different implementations, like a bram lut
<whitequark[cis]>
what is the interface like? just a stream of inputs + a stream of outputs? what about decoding errors? what about resetting disparity?
<whitequark[cis]>
do we add a barrel shifter that detects alignment within an input bit stream?
<adamgreig[m]>
so on my current implementation:
<adamgreig[m]>
encoder is 8-bit data input, rdi input (current RD), k input (data/special code groups), 10-bit code output, rdo output (new RD, feed back to input)
<adamgreig[m]>
decoder is 10-bit code input, rdi input, 8-bit data output, k output, rdo output, disparity-error-detected, coding-error-detected outputs
<whitequark[cis]>
parameterized for width, right?
<whitequark[cis]>
or, hm, is it just fully combinational?
<adamgreig[m]>
it's fully combinatorial. you put 8-bit words in and get 10-bit words out, and vv
<whitequark[cis]>
I think we definitely need a way to wrap it and get a pair of streams
<whitequark[cis]>
but this might be a general thing to offer in lib.stream
<adamgreig[m]>
I have output registers, so it's not strictly speaking combinatorial
<whitequark[cis]>
I think the 8b10b decoder would have a good place in amaranth-stdio, but probably not in amaranth core
<adamgreig[m]>
but it could be if you wanted it to be
<whitequark[cis]>
encoder/decoder
<whitequark[cis]>
it's only really ever used for IO anyways
<whitequark[cis]>
this makes several answers obvious
<whitequark[cis]>
do we have one for HDMI: yeah sure why not
<adamgreig[m]>
I handled alignment separately, since the 8b10b is word-at-a-time anyway, I have a separate barrel shifter that detects either of the comma patterns
<whitequark[cis]>
what do we do about it being kinda implementation specific: stdio does not have the same constraints as stdlib
<adamgreig[m]>
yea, stdio seems a good place for some line codes
<whitequark[cis]>
do we add 64b66b and friends: sure, whenever people want that and someone can maintain it
<adamgreig[m]>
sounds nice, I agree it's not needed in stdlib
<anuejn>
I also always did bram 8b10b (for HDMI)
<anuejn>
just out of curiosity: is your implementation really faster adamgreig[m]?
<whitequark[cis]>
re naming, IBM8b10b is probably an okay one
<whitequark[cis]>
and then we could have HDMI8b10b
<adamgreig[m]>
anuejn: I was saying BRAM is probably higher fmax but that I haven't tested
<anuejn>
that sounds like really good naming
<anuejn>
okay
<anuejn>
but then the question of implementation is there again?
<adamgreig[m]>
but it's also typically higher latency and uses up bram resources
<anuejn>
true
<whitequark[cis]>
if both implementations are registered (and @adamgreig's is, I think) then they have compatible interfaces, between BRAM and not
<anuejn>
(also I think "what feels right" is not too bad of an inclusion criterion - I do not have strong feelings about core inclusions in most cases)
<whitequark[cis]>
and we can pass that as a parameter in the constructor or something
<adamgreig[m]>
if the bram is registered input + registered output it's one more cycle, right?
<anuejn>
apart from "I definitely dont want to see the sync fifo going away" :D
<whitequark[cis]>
adamgreig: I was thinking just registered output
<anuejn>
what I asked myself recently: would we change the signature of the current fifos when we have streams in amaranth?
<anuejn>
or would we add seperate StreamFIFO variants?
<whitequark[cis]>
if it's registered input + registered output, how would you even do eg 4 at a time?
<whitequark[cis]>
anuejn: I think the signature should be changed and the existing methods to be maintained as an aliases to the relevant stream members
<whitequark[cis]>
otherwise we'll end up with an explosion of FIFO classes
<omnitechnomancer>
Alignment state machines for line codes are not necessarily all the same for every use of the code AFAIK
<galibert[m]>
Nothing is ever always the same, it shouldn’t prevent from covering 90%
<whitequark[cis]>
omnitechnomancer: hard IP usually gives you some configuration opportunities
<whitequark[cis]>
we could also do that
<cr1901>
whitequark[cis]: Do you want me to include a dummy publish-python job ("if: false"), or put "skip py" in every commit going forward until I xfer the repo :P?
<whitequark[cis]>
former, don't want to risk it
<cr1901>
Yea, prob for the best. Also taking bets over/under for how many times I have to force-push CI before I get green
<cr1901>
(don't actually send $, I will keep it)
<omnitechnomancer>
Certainly but does potentially mean it should not be baked into the decoder part inseperably
Degi_ has joined #amaranth-lang
Degi has quit [Ping timeout: 268 seconds]
Degi_ is now known as Degi
<cr1901>
whitequark[cis]: What's the difference between "pip3 install ." and "python -m build -w"?
<cr1901>
err, "python3 setup.py build", sorry
<tpw_rules>
setup.py is in some sense deprecated, pip will use the pyproject.toml
<whitequark[cis]>
cr1901: um, which two again?
<cr1901>
"python3 setup.py build" and "python -m build -w"
<cr1901>
From what I can gather, pip can't do the equivalent of "pdm build" by itself
<cr1901>
If that is further confusing, just answer this: "what is the build package, and why is it not specific as part of build-system.requires"?
<whitequark[cis]>
the latter does an isolated build
<whitequark[cis]>
and it's not specified there because it's not a package build system
<cr1901>
ahhh
<cr1901>
python build systems are complicated; an analogy I've been using is that "pyproject.toml for Python" is like "Cargo.toml for Rust, if 'cargo' wasn't the only build system in use in Rust land".
<cr1901>
.oO (Don't say it's the number of death... DON'T say it's the number of death)
<cr1901>
I think everything you requested is done except for submitting upstream patches
<cr1901>
(build backend now uses setuptools, not PDM. README.md was updated. Empty test dir removed. CI scripts added.)
<whitequark[cis]>
thanks!
<cr1901>
I'll submit the patches in the next few minutes, but do you object if I just let the repo "sit tight" in the interim until you're ready for xfer/things are less busy? I doubt things will change much, except maybe my patches getting in.
<whitequark[cis]>
sure. we can do the transfer tomorrow
<cr1901>
ack, thanks
nates93[m] has joined #amaranth-lang
<nates93[m]>
Thinking to place `return DomainRenamer({"sync" : self.cd_other.name})(m)` in `elaborate()` (where `cd_other` is passed in as a parameter) to avoid having to remember to rename the domain later on. This helps to keep it simple with `m.d.sync` , altho it seems a bit nefarious to quietly rename a module's sync domain (a counterargument to this would be that, well, cd_other is passed in as an argument to the module). Thoughts?
<whitequark[cis]>
that is fine, however we do not tend to pass around ClockDomain objects, but rather domain names
<whitequark[cis]>
the standard library uses this pattern in a few places, AsyncFIFO being a big one
<nates93[m]>
I see, thanks. In my case I have a handful of clock domains and have been tacking on a .freq to my ClockDomain objects to reduce the number of cd_1_freq, cd_2_freq, etc. variables laying around, which can be a bit error prone / redundant. It feels wrong but is p convenient
<nates93[m]>
(mainly just using ClockDomain objects within modules to do error checking of frequencies, and to use DomainRenamer at the end). V curious if there are other pitfalls I'm not seeing (happy to read up on this somewhere)
notgull has joined #amaranth-lang
notgull has quit [Ping timeout: 252 seconds]
<whitequark[cis]>
I have a naming question
<whitequark[cis]>
in CXXRTL, I have the ability already to pass a context object into commit(), which has a callback for whenever a value is updated. this object is called "observer"
<whitequark[cis]>
in CXXRTL, I am working on the ability to pass a context object into eval(), which will have a callback for whenever a $print cell prints something, or a $check cell fails an assertion, and methods to get the current Verilog $time/$realtime for formatting in either. how should it be called? the name needs to be unique within CXXRTL
<galibert[m]>
Well, for something somewhat equivalent in Mame we use the names watchpoint in the debugger and tap at the memory space level
<whitequark[cis]>
hm, this is fairly specific to "this produces an observable effect but not directly influencing the netlist"
<galibert[m]>
it's more equivalent to the observer though
<whitequark[cis]>
yea
<galibert[m]>
the eval one is more like i/o bindings in fact
<whitequark[cis]>
performer/observer
<galibert[m]>
io_adapter?
<whitequark[cis]>
it's not really handling any inpu
<whitequark[cis]>
s/inpu/input/
<galibert[m]>
time/realtime is kind of an input
<whitequark[cis]>
i guess? it only ever echoes that back to the callback, so it's not really an input in a true sense
<galibert[m]>
I'm kinda thinking i/o from the POV of the simulation core
<whitequark[cis]>
yes, exactly
<galibert[m]>
which inputs times, outputs strings...
<whitequark[cis]>
the simulated core cannot be influenced by $time/$realtime values provided
<galibert[m]>
yes and no
<galibert[m]>
what it is going to print can be
<galibert[m]>
it's not part of the netlist sure, but it's part of the sim
<whitequark[cis]>
not really interested in this discussion
<galibert[m]>
ok
<whitequark[cis]>
input/output have a specific name in CXXRTL context which is not this
<whitequark[cis]>
s/name/meaning/
<galibert[m]>
oh yeah, it's better to avoid misunderstandings there
<galibert[m]>
system_adapter?
<whitequark[cis]>
"performer" is probably good enough tbh
<galibert[m]>
you sure? Getting the time or printing a string is a little weak as a performance
<galibert[m]>
you may need that name in the future for say blackboxed sim instances
<whitequark[cis]>
will i?
<galibert[m]>
dunno, no idea what your ideas are in that area
<whitequark[cis]>
i don't think black boxes need any new names at all (they're already implemented, though the current implementation isn't really suitable for I/O blackboxes)
<galibert[m]>
they are? Cool!
<whitequark[cis]>
have been for many years
<whitequark[cis]>
it's even in the documentation for the pass
<galibert[m]>
you mean I can Instance a pile of altsyncram or dsp blocks and I have a way to write code to sim them in cxxrtl?
<whitequark[cis]>
yeah
<galibert[m]>
I didn't think that was pssible, cool
<galibert[m]>
Last time I asked it wasn't, but that was a while ago
<whitequark[cis]>
there are some issues there which mean you may hit a race condition
<galibert[m]>
annoyingly usual problem
<whitequark[cis]>
same as for write_cxxrtl -noflatten, actually, it's just that no one ever uses non-flattened designs unless they use black boxes
<whitequark[cis]>
we have a design for CXXRTL 2, which will eliminate that problem while making it even faster, but other things have taken priority for now
<_whitenotifier-3>
[amaranth-lang/amaranth-lang.github.io] github-merge-queue[bot] 3c60685 - Deploying to main from @ amaranth-lang/amaranth@2fecd1c78bfe240540e21a607e71304c2f28abda 🚀
<whitequark[cis]>
that warning doesn't necessarily mean a problem with the design
<whitequark[cis]>
unless you find that your design doesn't do anything after you synthesize it, this is just Vivado sometimes emitting diagnostics with little to negative value
<johnnyfisher[m]>
after the synthesize,two modules are removed in schematic, but in simulation i have all modules,running and connected
<whitequark[cis]>
Wanda: yeah sure
<whitequark[cis]>
johnnyfisher.: it's difficult to say why that happened with just a few screenshots; you'll need to prepare a way for others on the channel to reproduce your issue