<josuah>
from first looking at it, Amaranth did look complicated to me
<josuah>
I had a bit of trouble to understand where the execution starts
<josuah>
this shows how much verilog biased me toward thinking HDLs write programs
<josuah>
I was wondering why += was everywhere instead of having a more conventional approach like verilog using '=' assignments
<josuah>
but for a program that generates RTL, the real operation going on si really += which aggregates multiple unrelated logic circuit into a big array
<josuah>
a big array that is going to be placed and mapped to blocks on a silicon die or FPGA fabric
<josuah>
what a plot twist! even though I was well aware of Verilog's biased approach, I was still much under its bias
<josuah>
and then looking at amaranth code suddenly made sense!
<josuah>
feeling like a much thinner abstraction over HDL than Verilog-like languages
<d1b2>
<Olivier Galibert> Is there a way to know if sync has an enable inserted of it, and if yes get the base clock domain and the enable separately? The issue is how to generate 1-tick wide strobes in the StrobeGenerator even if the clock domain is gated, for instance if you cascade generators
<josuah>
whitequark: the language guide was a good part of that cluestick
<whitequark>
but I think you probably should let gating be
<whitequark>
there's a chapter in the manual waiting to be written on this...
<d1b2>
<Olivier Galibert> that means you can't cascade generators though. Not 100% it would be useful tbh
<d1b2>
<Olivier Galibert> It's irrelevant for my case but you may be interested to know that a cyclonev has roughly a hundred clock enables/gates, one for each clock dispatch network. At they point they seem to have decided it was important
<d1b2>
<Olivier Galibert> But yeah, there's some conceptual issue in there that are not entirely clear. An "enable" signal for me is a series of 1-clock-wide pulses that decide which edges of a global fast clock you actually want to do stuff on. Which is very nice because CDC is annoying. And amaranth rules because with EnableInserter it allows to do that transparently code-wise for a clock domain and have a module work on a reduced clock without
<d1b2>
changing the code. It just breaks down if, among other things, the module generates a new enable signal (it could be generate vsync from hsync for instance) because the enable width is going to be one reduced-clock tick long, which is more than one. There somehow somewhere needs to be a way to generate a pulse train that's actually pulses, bonus point if you can do it transparently without code change with and without a reduced clock
<d1b2>
<Olivier Galibert> It's a little different than the instance issue, but turns around the same "enables are different"
<d1b2>
<Olivier Galibert> I'll do an issue for future reference
<d1b2>
<Olivier Galibert> not sure what the answer should be, but heh
<d1b2>
<Olivier Galibert> Still learning my way around the language, but I keep liking it, at least we have some of the advances in software languages coming to hardware
<d1b2>
<Olivier Galibert> Abstraction is good damnit 🙂
<whitequark>
it is handy
<d1b2>
<Olivier Galibert> I have a neboulous feeling that amaranth should know/accept that some clock domains can be compatible, e.g. their phase will always be correct one w.r.t another so that there's no metastability risk. Clock vs. clock + enable, perhaps edges of a clock, perhaps multiple output of one pll with correct divider/phase parameters. And if it's the case, allow writing to the same register on those different domains. But I'm not sure
<d1b2>
whether it actually makes sense hardware-wise, not entirely convinced
dave_ has joined #amaranth-lang
<whitequark>
you're basically suggesting that Amaranth should replicate a part of the P&R tool timing engine
<d1b2>
<Olivier Galibert> Hmmmmm... no?
<d1b2>
<Olivier Galibert> Just a way for the module to explicitely say "those two clock signals are compatible". Why is not amaranth's problem, and if you lie you get to keep all 256 pieces
<d1b2>
<Olivier Galibert> And that EnableInserter generates a compatible domain, obviously
<d1b2>
<Olivier Galibert> But I'm not sure if would work out nicely at the P&R level afterwards, so I'm really not sure
daveberkeley has joined #amaranth-lang
daveberkeley has quit [Client Quit]
daveberkeley has joined #amaranth-lang
dave_ has quit [Quit: Leaving]
<d1b2>
<Olivier Galibert> not even sure it would be that useful, except when trying to directly convert schematics using multiple-phase clocks (the via6522 has three phases for instance)
<d1b2>
<Olivier Galibert> they sometimes do a thing like "bring the line to 1 on one phase, then optionally bring it down on the next one". Precharge-based pull-up simulation
<d1b2>
<Olivier Galibert> but amaranth has no reason to be a language to transcribe nmos/latch schematics
<whitequark>
EnableInserter doesn't actually create a new domain
<d1b2>
<Olivier Galibert> Ah, interesting
<d1b2>
<Olivier Galibert> But that's an implementation detail, right? Semantically, it does?
<whitequark>
no I wouldn't say so
<whitequark>
well, it depends on what you mean by "new domain"
<whitequark>
that's... another manual chapter waiting to be written
<d1b2>
<Olivier Galibert> huhuhu
<d1b2>
<Olivier Galibert> I'm not entirely sure what I mean either
<adamgreig[m]>
There's a lot of use cases for enableinserter which aren't around making a new slow clock by gating only some edges, which look less like making a new clock domain I guess
<whitequark>
^ yes
daveberkeley has quit [Quit: Client closed]
<d1b2>
<Olivier Galibert> if you have one clock domain with say a 2Mhz clock, then do two opposite pulse trains to split even/odd clocks into two EnableInserter-ed domains pclk and nclk, can you write to the same register from both in a submodule?
<d1b2>
<Olivier Galibert> For me a clock domain is something that decides when things actually happen in a m.d.mumble, and with the property that writes to a signal cannot be done some different domains (which is what characterizes them as different too)
<d1b2>
<Olivier Galibert> but I so may be missing stuff there 🙂
<whitequark>
arguably, a clock domain is something that requires CDC between it and other clock domains
<whitequark>
this is not the only possible definition, of course
<whitequark>
there is the concept of "control set", which unambiguously maps to what you are talking about
<whitequark>
i.e. same clock/reset/enable
<d1b2>
<Olivier Galibert> Yeah, while we know there are domains as in m.d that may not need a CDC
<d1b2>
<Olivier Galibert> that essentially what I meant by "compatible"
<d1b2>
<Olivier Galibert> honestly, not sure it's worth it as a concept though
<whitequark>
"control set" is an existing concept used by tools in this space
<whitequark>
so what EnableInserter() does is it rebinds the implicit control set
<whitequark>
instead of `old_enable`, it turns that into `old_enable&new_enable`
<whitequark>
and ResetInserter() turns old_reset (which by default is cd.rst) into old_reset|new_reset
<d1b2>
<Olivier Galibert> makes sense
<d1b2>
<Olivier Galibert> control set = clock + enable + reset then?
<d1b2>
<Olivier Galibert> more like tuple, but heh
<_whitenotifier-9>
[amaranth] VioletEternity opened issue #750: Installation instructions suggest deprecated pip commands that will stop working after pip 25.0 - https://github.com/amaranth-lang/amaranth/issues/750
<vup>
In the end this build a .zip containing the bitstream and all the python driver code, and running the zip with python programs the bitstream throws you into a repl that allows you to interact with the design hierarchy, read / write all your registers and call your driver scripts.
<tannewt>
nice! let me look
<whitequark>
we should have that upstream in -soc
<whitequark>
for sure
<whitequark>
so with a JTAG to AXI/Wishbone
<tannewt>
vup, you have to call `handle_read` and `handle_write` correct? I was using data descriptiors to use `__get__` and `__set__`
<_whitenotifier-9>
[amaranth-lang/amaranth-lang.github.io] whitequark 77d6363 - Deploying to main from @ amaranth-lang/amaranth@ca77de5ed3ae19ef241f07bc56765f414db4d968 🚀
<vup>
(This is called platform in our code). When a design is elaborated, anything that is a subclass of Peripheral (https://github.com/apertus-open-source-cinema/naps/blob/main/naps/soc/peripheral.py) is collected and given to this bus implementation, which then generates the gateware that routes reads and writes from a bus-specific bus master to the peripherals based on their address. The logic for reads and writes of a Peripheral are determined by the
<vup>
The way it works is, that the board you are using provides a "Bus" implementation.
<vup>
tannewt: its actually a lot more involved, handle_read and handle_write are parts of our (handrolled) bus agnostic "register" abstraction.
<vup>
Peripheral itself and the bus implementation inserts the peripheral specific implementation by inserting the handle_read and handle_write calls gated by the address that is read / written to the gateware. This makes it possible to implement some useful custom logic, like PulseReg, which is a Peripheral, that when written to generats a exactly one clock cycle long pulse.
<vup>
Finally this MemoryAccessor is then used with a generated python object hierarchy, that just mirrors the amaranth design hierarchy of modules and submodules with properties added for each Peripheral that was part of the original design hierarchy added to the generated object, that when accessed or is written to reads / writes to the correct address using the MemoryAccessor.
<_whitenotifier-9>
[amaranth-lang/amaranth] whitequark 12a81f2 - docs/install: pip>=23.0 is required.
<_whitenotifier-9>
[amaranth] whitequark closed issue #745: WARNING: Generating metadata for package amaranth produced metadata for project name unknown. Fix your #egg=amaranth fragments. - https://github.com/amaranth-lang/amaranth/issues/745
<_whitenotifier-9>
[amaranth-lang/amaranth-lang.github.io] whitequark 04193a9 - Deploying to main from @ amaranth-lang/amaranth@12a81f24bd7b435d2089cd522aece4c1c9733dbd 🚀