<cr1901>
Also roughly: the "device, package, speed" class variables will be concatenated into a single string such that it "pleases" the vendor tools' CLI when amaranth subprocesses.open()s them
<mcc111[m]>
okay. so if i put 5CEBA4F23C8 in the device string and leave the other two blank will that do the right thing?
<cr1901>
As I haven't used Quartus CLI in 10 years, I don't know how you should split the device name you looked up into its constituent parts
<mcc111[m]>
or should i be more thoughtful
<mcc111[m]>
i see
<cr1901>
Yea, that's the bad news... I don't know how to split an Altera string
<mcc111[m]>
haha
<cr1901>
There is also a class variable called a connector. This is for FPGA pins that terminate at a breakout connector, probably a 40 pin "male" (less shitty term desired) header on a DE-10 board, for instance
<cr1901>
I don't know if the Pocket has any user-facing connectors?
<mcc111[m]>
there's a JTAG connector if you unscrew the back, if that's what you mean.
<mcc111[m]>
supposedly there's a certain number of "dev units" that just have a hole in the back of the case so you can reach the JTAG without using a screwdriver.
<mcc111[m]>
Looks like the current de10 board files were added by Dan Ravensloft and Yusuf Taiwo Hassan
<cr1901>
Yes, it's what I mean. You _can_ use the JTAG connector as FPGA I/O, but I wouldn't recommend it. I don't know of any board file that exposes the JTAG port as I/O.
<mcc111[m]>
I want to use the JTAG connector for JTAG.
<mcc111[m]>
like, debugging in quartus lite
<cr1901>
That is good practice :). I was giving an example of "exposed" I/O
<mcc111[m]>
"Cyclone V 110K LEs"
<mcc111[m]>
cr1901: Makes sense. The most important thing are a series of "buses" that the pocket exposes for communicating with the outside world
<mcc111[m]>
For the most part the Cyclone V does not communicate directly with things such as sound, video etc, there's a second FPGA (a cyclone 10) handling that, which are not available for third parties to reprogram
<cr1901>
Right now I think it's best to include the Verilog as a submodule or in your tree, and use amaranth.build to include the relevant Verilog files (this will prob change in the future)
<mcc111[m]>
agg23: "They (a and b) are on opposite sides of the chip. There are 4 PLLs, 2 on one side, and 2 on the other. 2 are fed by each reference clock
<mcc111[m]>
This is done because it actually takes a significant amount of time to cross the chip and you run out of slack, particularly on larger designs"
<mcc111[m]>
cr1901: The reason I ask is there are some existing modules for things like memory interaction, initialization etc
<charlottia>
mcc111[m]: Those exist but aren't specific to Verilog or anything as such.
<mcc111[m]>
No, sorry. I mean that the Pocket needs to be initialized a certain way, the SDRAM chip on the Pocket wants to be used a certain way
<charlottia>
Ahhh, right, I see what you mean.
<mcc111[m]>
And I'd like to reuse some of the existing code for that directly instead of rewriting it, if possible, but it seems like it could be easily compartmentalized into a submodule or whatever the abstraction is
<mcc111[m]>
Does that look right or am I missing something critical but obvious to a seasoned FPGA programmer about why the second one would say 1. V in the QSF?
<cr1901>
Resource("clk_74b", 0*,
kinnu_23461[m] has joined #amaranth-lang
<kinnu_23461[m]>
hi
<cr1901>
Based on agg23's response, they are literally two different oscillators
<cr1901>
mcc111[m]: Ignore the above, I don't know for sure
<mcc111[m]>
ok
<cr1901>
It's _possible_ that it's the same clock signal from the same component on the Pocket, level shifted down on one side of the FPGA, but I do not know for sure
<mcc111[m]>
i'll trust the qsf
<cr1901>
(the level shifting would add propogation delay, so that's why the two would be out of phase. But that is conjecture.)
<mcc111[m]>
So… I believe this can all be integrated with Amaranth's model… but there are some non obvious things, and I would prefer to do those non obvious things in an "idiomatic" way. Whatever's idiomatic.
<mcc111[m]>
I think the only hard parts are: What's the most sensible way for an author of a Amaranth-for-Pocket program to specify the JSONs? How would I communicate to amaranth "two types" of the program verb, and how would they be exposed in the interface? And is it going to be at all weird that the output of the build is a directory and not per se a single file?
<mcc111[m]>
In the short term, I think I can ignore all this because if I can just get IntelPlatform to build me a RBF I can install it onto the Pocket for testing "by hand
<mcc111[m]>
* "by hand"
<cr1901>
I'm not wq. But I predict something along the lines of "PocketPlatform in amaranth deals with none of those files" and you "subclass PocketPlatform with your extra logic that becomes a frontend for Pocket developers using Amaranth"
<mcc111[m]>
okay. and you think that doesn't live in amaranth-boards.
<cr1901>
That is what _I_ think _wq_ thinks, and so I don't think you should start putting that logic into boards only to be told "no" by a maintainer (wq). But it more-or-less aligns w/ my opinion here) :P.
<mcc111[m]>
the thing is openfpga is theoretically a "standard" and the standard actually does encompass the json files. in fact theoretically there will be future openfpga devices which use the json files but are using a different board. (i'm technically making an OpenFPGAPlatform() with the expectation at some point I'll find a reason to subclass that into an AnaloguePocketPlatform)
<mcc111[m]>
cr1901: Well. That plan aligns well with the easiest thing to do (implement no logic at all and do it in bash for now)
<cr1901>
There's precedent for "board class gets subclassed to automatically support another similar board", but those boards change literally one or two lines. And parent and child class live in the same source file.
<cr1901>
OpenFPGAPlatform() seems to be more encompassing than one or two lines. Defer to wq here.
<mcc111[m]>
OK. Then I'll wait to hear from Catherine.
<gatecat>
It might be better to come up with a different name than just OpenFPGAPlatform, because one day we might want to support https://github.com/lnis-uofu/OpenFPGA
<gatecat>
which I believe has actually been going for longer
<mcc111[m]>
The name of Analogue's platform is OpenFPGA. Theoretically the Pocket is just the first in a series of devices following the OpenFPGA standard, and other community resources/tooling for Analogue OpenFPGA assume this to be the case. Also Analogue's rhetoric/marketing seems to *strongly imply* companies other than... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/uOpdFolOtkYTkIGehpGLkjiA>)
<mcc111[m]>
<gatecat> "It might be better to come up..." <- The name of Analogue's platform is OpenFPGA. Theoretically the Pocket is just the first in a series of devices following the OpenFPGA standard, and other community resources/tooling for Analogue OpenFPGA assume this to be the case. Also Analogue's rhetoric/marketing... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/llunknHdGJiOACclHUjIzzPY>)
<whitequark[cis]1>
mcc111: I am opposed to having it be called "OpenFPGA". as the maintainer of amaranth-boards I will choose the name at my own discretion in this case
<mcc111[m]>
<whitequark[cis]1> "mcc111: I am opposed to having..." <- OK. Well the eventual PR you are going to get from me will have a class named that, and I ask only that you go with some name which is unambiguous to Analogue users
<mcc111[m]>
* only that any accepted version you go
<mcc111[m]>
* only that any accepted version you go, * go with use some name
<galibert[m]>
Honestly, since it's going to end up dependant on the e50f die, I don't see analogue's openfpga going anywhere
<Wanda[cis]>
what is it with people and naming shit openfpga
<galibert[m]>
Also, in 5CEBA4F23C8 "5CEBA4" is the model, F23 is the package (fire-pitch bga, 23mm to a side) and C8 is the speed (technically C = consumer temperature range, e.g. 0-85 and 8 is the actual speed rating, smaller being better)
<mcc111[m]>
<mcc111[m]> "OK. Well the eventual PR you are..." <- The previous question from my conversation with cr1901 (should the "additional" build steps for Analogue's platform, EG generation of json files and reversing all the bits in the output RBF, be handled in the boardfile/in code PRed into amaranth, or an extension bundled into my project / an Amaranth-Analogue-Pocket template project I publish) is more important because having a
<mcc111[m]>
sense of your thinking will help guide how I implement this in the code I write now
<mcc111[m]>
Although looking through amaranth/vendor/intel i'm struggling to figure out where the special intel/altera "invoke quartus lite" logic actually occurs, so maybe i'm forced to start off doing it as an addon for that reason, heh
<mcc111[m]>
galibert[m]: Okay, good. That's what I guessed in my draft but it's good to have confirmation lol
<mcc111[m]>
* Although looking through amaranth/vendor/intel i'm struggling to figure out where the special intel/altera "invoke quartus lite" logic actually occurs, so maybe i'm forced to start off doing the build systemas a project-resident addon for that reason, heh
<mcc111[m]>
* Although looking through amaranth/vendor/intel i'm struggling to figure out where the special intel/altera "invoke quartus lite" logic actually occurs, so maybe i'm forced to start off doing the build system as a project-resident addon for that reason, heh
<galibert[m]>
And the 5CEBA4 is the sku name for the die codenamed e50f in quartus' files
<mcc111[m]>
The Mister platform in amaranth-boards comments the device with "# Cyclone V 110K LEs" and the package with "UBGA-484" (the de10 packages have similar comments) but aside from "Cyclone V" I don't know what this means
<galibert[m]>
well, I noticed the "120" is sx120f is roughly the number of thousands of LEs
<galibert[m]>
codenames are gx25f, gt75f, gt150f, gt300f, sx50f, sx120f and e50f
<galibert[m]>
gx/gt have everything but the integrated arm (e.g. high speed serial interfaces, memory controllers...), sx have the arm in addition, and e50f has all that removed, which gives more space for LEs if you don't need the special hardware
<galibert[m]>
sx50f is very close to being a gt75f with the arm taking over a corner, and the sx120f a gt150f with in the same way an arm in the corner
<galibert[m]>
roughly 1/6th of the surface is the arm on the sx120f, 1/3rd on the sx50f
<mcc111[m]>
okay. and mister is an sx120f?
<galibert[m]>
yes
<galibert[m]>
the biggest with included arm
<mcc111[m]>
is an LE the same as a LUT?
<galibert[m]>
that's an annoyingly complicated question in fact
<mcc111[m]>
"No", "Sometimes", and "Sometimes, approximately" would be satisfying answers to me even if they're vague
<mcc111[m]>
I think I'll comment device with "Cyclone V 50k LEs / e50f"
<galibert[m]>
sx10f has 4191 labs or mlabs. Each lab is a set of 10 labcells. A labcell has 4 4-bits luts or 2 5-bit or one 6-bit
<mcc111[m]>
and not comment package unless you think some part of "fire-pitch bga, 23mm to a side" would be helpful to future readers
<galibert[m]>
s/sx10f/sx120f/
<galibert[m]>
saying it has 120K LEs puts it at ~30LE/lab.... whatever
<galibert[m]>
e50f has 1848, 1848*30 = 55k, so it's least it's around there
<mcc111[m]>
So I think I understand (after getting an explanation in here last week) the relationship between a Lab and a LUT, but LE is a new term to me
<Wanda[cis]>
mcc111: basically LE is a fake number
<galibert[m]>
because LE is a marketing term
<Wanda[cis]>
designated by vendor as "roughly equivalent power to a plain LUT"
<mcc111[m]>
oh no
<galibert[m]>
or yeah, that's a polite way to say fake number
<mcc111[m]>
well, i'm told this device has roughly 50k LUTs
<Wanda[cis]>
and they're defined to be "whatever puts us higher than xilinx"
<Wanda[cis]>
xilinx, in turn, has their own metric of "logic cells" which is likewise fake
<mcc111[m]>
but a little under that
<Wanda[cis]>
(fun fact: xilinx switched from "logic cells" to "system logic cells" in the middle of ultrascale era just so they could use a different conversion factor and top Intel's biggest offering)
<Wanda[cis]>
as for LUT count, that's also not a very well-defined number, particularly on modern intel and xilinx FPGAs
<Wanda[cis]>
because both of them have something called fracturable LUTs
<Wanda[cis]>
ie. they underlying primitive can be split into varying number of LUTs depending on how big and how... "similar" you want them
<Wanda[cis]>
the Xilinx primitive can do a 6-input LUT, or maybe two 5-input LUTs if they have the exact same 5 shared inputs
<Wanda[cis]>
Intel ... I forget the list of combinations, it's much more complicated
<whitequark[cis]1>
<mcc111[m]> "OK. Well the eventual PR you are..." <- sounds good
<galibert[m]>
yeah, a labcell has 64 bits of ram, 8 inputs, and a whole mess in the middle
<Wanda[cis]>
so there can be no direct comparison between LUT counts of different FPGA families and you have to rely on benchmarks to figure out the rough conversion factors on real-life loads
<Wanda[cis]>
which vendors helpfully supply with their "LE" or "LC" or whatever bullshit number, using benchmarks carefully tuned to get the most inflated counts
<Wanda[cis]>
(the basic Xilinx LC is nominally equivalent to 4-input LUT with no special wide-mux / carry-chain / whatever hard logic at all, which ... I don't think anyone ever actually manufactured as a serious offering)
<Wanda[cis]>
Lattice, Gowin, and other smaller vendors tend to use 4-input LUTs btw, which are markedly less powerful than 6-LUTs
<galibert[m]>
Cyclone V labcell internals, you see the 6 LUTs on the left
<whitequark[cis]1>
<mcc111[m]> "The previous question from my..." <- this sounds like something that could live in amaranth-boards
<galibert[m]>
Also, fine-pitch, not fire-pitch :-)
<whitequark[cis]1>
<Wanda[cis]> "because both of them have..." <- i call them frangible.
<whitequark[cis]1>
whitequark[cis]1: the idea is that the board file .py has everything you need to program the device, if at all feasible
<whitequark[cis]1>
bit reversion included
<whitequark[cis]1>
though, cannot quartus output a bit reversed file itself?
<galibert[m]>
no, it can't iirc
<Wanda[cis]>
wait, you're telling me that it's not just xilinx that cannot decide on one bit order for their damn bitstreams and keep to it?
<Wanda[cis]>
... why am I even surprised
<galibert[m]>
Wanda: I suspect it's obfuscation by Analogue
<whitequark[cis]1>
sounds unlikely
<mcc111[m]>
<whitequark[cis]1> "though, cannot quartus output..." <- I don't know. Analogue's documentation does not tell you to have quartus bit reverse the files; instead, they give you the C code for a program to bit reverse the file.
<mcc111[m]>
I think this is because *bit reversing is not required when programming the FPGA via JTAG*, only when the analogue itself loads the netlist from the SD card using the on-device menu.
<mcc111[m]>
At least, I was able to program via JTAG without performing the reversing step.
<mcc111[m]>
* via JTAG entirely internal to Quartus, without, * without ever manually performing the
<cr1901>
Wanda[cis]: I feel like I had a parse fail... " I don't think anyone ever actually manufactured [blank] as a serious offering" What is supposed to go in the blank?
<Wanda[cis]>
cr1901: an FPGA that is *only* LUT4 + FF, without any sort of hard carry chains or wide mux logic
<cr1901>
Yea, that sounds about right. It's not a bad first model for teaching/building upon. I think nextpnr-generic's default backend uses only LUT4+FF
omnitechnomancer has joined #amaranth-lang
<omnitechnomancer>
Lattice have the helpful "effectiveness factor" of 1.2 or something for their LUT counts
<jfng[m]>
i don't expect any further changes, and i plan to merge it as soon as amaranth 0.4 ships
<galibert[m]>
I’d like to try to make the arbiter do both rr and priority, any objections to that?
<galibert[m]>
(to make it suitable for Minerva)
<galibert[m]>
(rr between endpoints at the same priority level of course)
<jfng[m]>
hmm, i'm not against the idea (minerva uses a priority-based arbiter, for example), but i'd like to see how the changes fit with the current Arbiter implementation, before deciding
<jfng[m]>
if you can factor it in a way that's not too intrusive, maybe ?
Chips4MakersakaS has joined #amaranth-lang
<Chips4MakersakaS>
galibert[m]: Does it have hardware overhead when using solely rr and priority ?
<Chips4MakersakaS>
s/and/or/
<jfng[m]>
in the case of minerva's arbiter, no if there is only one priority level
<galibert[m]>
The idea would be not to have overhead. I didn’t start yet, hence “try”
<jfng[m]>
(but it is way worse than the upstream one, so it's not really a reference)
<galibert[m]>
But hopefully I can optimise the setup at the python level since it’s structurally static
<cr1901>
Would an arbiter with two ports A and B, where A can cancel a current transaction on B (signalled with RTY), be accepted?
<jfng[m]>
it's a bit like the scheduler discussion in amaranth.lib, there are so many possible implementations, we can't strive to cover them
<cr1901>
Actually scratch that
<jfng[m]>
that would be a fool's errand, imo
<galibert[m]>
We need an arbiter in -soc, and priority is really useful, but so is rr. If I can find a way to have both while staying readable it could be cool
<jfng[m]>
yeah, let's discuss this over an actual implementation
<jfng[m]>
worst case, you get a nice arbiter implementation for your own projects
<galibert[m]>
For sure. I wanted to check the lack of opposition on principle
<Chips4MakersakaS>
What's next for -soc ?
<jfng[m]>
i am going to begin work on the peripheral API next week, after which we should have enough functionality for an amaranth-soc 0.1 release !
<Chips4MakersakaS>
sounds exciting
<Chips4MakersakaS>
I do plan to take holiday in near future and one of the things I may look at is updating my JTAG code to new lib.wiring. No promise though.
<jfng[m]>
nice, mine will hopefully involve a refactoring minerva to interfaces, including using amaranth_soc.wishbone
<cr1901>
But it looks like you do all accesses through self.bus
<jfng[m]>
its through self.bus, indeed
<jfng[m]>
i guess the docstring could make it clearer by saying "Bus address width" for `addr_width`, instead of just "Address width"
<galibert[m]>
Shouldn't the "are those wishbone bus definitions compatible" code be put somewhere common?
<jfng[m]>
i don't understand
<galibert[m]>
all the tests in add, wouldn't that be useful in other places too? Like decoder
<jfng[m]>
they are similar to Decoder.add(), but subtly different
<galibert[m]>
or, alternatively, maybe add could return something you're supposed to connect() to?
<jfng[m]>
i didn't touch them, to limit the amount of breaking changes to what is needed for interfaces
<jfng[m]>
galibert[m]: it would just move the validation problem to the `add()` parameters, i think
<jfng[m]>
maybe we could just rely on Signature.is_compliant(), but i'm not sure if we can have good diagnostics like that
<galibert[m]>
I would have thought add() would lose its parameter instead, and return a flipped(/forward) version of the internal connection
<jfng[m]>
well not quite, e.g. the actual address width of a wishbone.Decoder bus interface may change as the result of adding a subordinate bus with extend=True
<jfng[m]>
so returning an interface would force us to commit to a given width
<galibert[m]>
oh, I didn't realize that
<jfng[m]>
this is actually something i'd like to change in the near future
<galibert[m]>
I'd have thought Catherine would have required an adapter in such a situation :-)
<galibert[m]>
but yeah, extension can't really be adapted
<galibert[m]>
weird feature though
<jfng[m]>
i don't think extend=True solves the right problem, and it would be better if the bus address width was decided top-down rather than bottom-up
<galibert[m]>
yeah, I can't really find of a situation where it would work out. Minerva is not suddendly going to output 64 bits addresses
<galibert[m]>
s/find/think/
<jfng[m]>
sure, once you know every subordinate bus interfaces, you can optimize the gateware accordingly, but this is an implementation detail in the end
<cr1901>
What does the path=("bus",) arg to Interface do again?
<jfng[m]>
also, if you have say, a 48-bit address width at the top-level of your interconnect, this is a hard requirement
<jfng[m]>
you don't want it to increase after adding a register in some random peripheral
<jfng[m]>
cr1901: it gives a name to the bus interface, e.g. the signal names would be "bus__cyc", etc
<cr1901>
as opposed to "_bus__cyc", since the Interface is attached to self._bus?
<jfng[m]>
_bus__cyc happened before because we created a Record with name=None
<cr1901>
Oh, so Interface(path=) corresponds to Signal(name=)
<jfng[m]>
so amaranth.tracer would give it a name from the python variable (self._bus)
<jfng[m]>
yeah, but with sequences of strings rather than just strings
<cr1901>
Yea I saw that. It's indeed more flexible, but I can't visualize a case where I'd use a tuple of strings to bulk rename some Signals right now.
<jfng[m]>
it corresponds to Record(name=) rather than Signal(name=)
<cr1901>
ah
<jfng[m]>
i guess we can wrap up today's meeting, thanks everyone !
<galibert[m]>
Thank you for the nice wiring work
<cr1901>
Anyways, the @property for "bus(self): ..." is good, and it seems to be the general way how to handle parametric Signatures where you know know the Signature until the object is created
<cr1901>
where you don't know*
<jfng[m]>
the rationale is that such bus interfaces have memory maps, which must first be populated
<jfng[m]>
by making bus a property, we can freeze the memory map as a side-effect of referencing the interface
<jfng[m]>
freeze() is idempotent, and doing it here too is a way of saying "by now, we assume the memory map is frozen"
<cr1901>
I can't envision a way you could run afoul of the frozen memory map between the explicit freeze() and the implicit one in the memory_map setter, but that doesn't mean it can't be done. So good catch :D
<jfng[m]>
in other words, if we use any attribute of a memory map (e.g. addr_width) for something that has side-effects, we freeze it first
<cr1901>
Also, I just realized that MemoryMap isn't a Signature. It just happens to have a method called freeze().
<cr1901>
But yes, makes sense
<cr1901>
The code looks good, it's just using more of the gamut of Amaranth than my code personally has :P
<cr1901>
so it's taking me longer to grok
<jfng[m]>
jfng[m]: this practice may be relaxed once `add_resource(extend=True)` or `add_window(extend=True)` is removed
<galibert[m]>
There’s never been a -Soc release right? Do it may be acceptable to just remove it and be done with it
<jfng[m]>
but work needs to be done to wishbone.Arbiter and Decoder too, before we can just remove extend=True from MemoryMap
chaoticryptidz has joined #amaranth-lang
<cr1901>
This should all be usable for my MachXO2 EFB work. I'll have to create a dummy class whose sole purpose is to connect EFB to amaranth_soc.wishbone tho;
<cr1901>
Lattice broke spec and doesn't include a SEL line (b/c 8-bit port, 8-bit granularity)
<jfng[m]>
many such cases, it seems every wishbone implementation out there has its quirks...