whitequark[cis] changed the topic of #amaranth-lang to: Amaranth hardware definition language · weekly meetings: Amaranth each Mon 1700 UTC, Amaranth SoC each Fri 1700 UTC · code https://github.com/amaranth-lang · logs https://libera.irclog.whitequark.org/amaranth-lang · Matrix #amaranth-lang:matrix.org
Degi has quit [Ping timeout: 240 seconds]
Degi_ has joined #amaranth-lang
Degi_ is now known as Degi
<_whitenotifier-f> [YoWASP/yosys] whitequark pushed 1 commit to develop [+0/-0/±1] https://github.com/YoWASP/yosys/compare/3767b1d481cd...8488c46fb34a
<_whitenotifier-f> [YoWASP/yosys] whitequark 8488c46 - Update dependencies.
<_whitenotifier-f> [YoWASP/runtime] whitequark pushed 1 commit to develop [+0/-0/±0] https://github.com/YoWASP/runtime/compare/2d89db49c29a...68a33e6521c3
<_whitenotifier-f> [YoWASP/runtime] whitequark 68a33e6 - [autorelease] Rebuild for wasmtime-py 13.0.1.
<_whitenotifier-f> [amaranth-lang/amaranth-yosys] amaranth-lang-bot pushed 1 commit to develop [+0/-0/±1] https://github.com/amaranth-lang/amaranth-yosys/compare/083ae3da24cd...61e1807df772
<_whitenotifier-f> [amaranth-lang/amaranth-yosys] whitequark 61e1807 - [autorelease] Update wasmtime version requirement from <13 to <14.
<cr1901> Is there a twos-complement operator?
<whitequark[cis]> what would that do?
<cr1901> well, I'm using def twoscomp(x): return ~x + 1. I don't mind doing that, I was just wondering if I was missing something
<tpw_rules> i mean why not -x
<_whitenotifier-f> [amaranth-lang/amaranth-yosys] amaranth-lang-bot pushed 1 commit to release [+0/-0/±1] https://github.com/amaranth-lang/amaranth-yosys/compare/083ae3da24cd...61e1807df772
<_whitenotifier-f> [amaranth-lang/amaranth-yosys] whitequark 61e1807 - [autorelease] Update wasmtime version requirement from <13 to <14.
<cr1901> >i mean why not -x <-- that was what I was missing
<cr1901> because I didn't realized that worked
<tpw_rules> i am fairly certain it does
<tpw_rules> (in regular python too)
<cr1901> It does work
<cr1901> I'm just a dumbass
cr1901_ has joined #amaranth-lang
cr1901 has quit [Read error: Connection reset by peer]
<crzwdjk> I just ported my arbiter component to use connect, and the code became a whole lot more compact and more generic, it's pretty great. Big win for the wiring module.
<whitequark[cis]> sweet, got a diff to show off?
cr1901_ is now known as cr1901
<cr1901> Is there an ergonomic way to set the reset value of an ArrayLayout? This uhhh... did not work :P https://github.com/cr1901/smolarith/blob/main/src/smolarith/mul.py#L139-L141
<cr1901> Btw, I merged the signed, unsigned and signed-unsigned multipliers into one, so now it's possible to pipeline all three types of multiply
<whitequark[cis]> ohh, you found a bug
<whitequark[cis]> well, it's not in your snippet
<whitequark[cis]> you did find it but you probably didn't realize yet what bug it is. hm.
<whitequark[cis]> so basically, in Signal(some_layout, reset=X), X could be something like {"field": 1}, right?
<cr1901> yes
<whitequark[cis]> however if you later grab that signal (by extracting it via as_value()), you can't set the reset value to a complex constant directly
<whitequark[cis]> which is inconsistent
<whitequark[cis]> you'd have to do something like
<whitequark[cis]> s.as_value().reset = some_layout.const({"field": 1})
<whitequark[cis]> which is a mouthful
<whitequark[cis]> i am thinking that it should probably be more like s.as_value().reset = {"field": 1}
<whitequark[cis]> but i'm also on vacation so i'm not going to file or fix it
<cr1901> I don't even have the StructLayout used as a binding anywhere
<cr1901> Well, yea, that's fair lol
<cr1901> Also, it's not gonna matter soon. I'll need an INVALID enum value soon, and INVALID/0 is a reasonable default
<cr1901> INVALID variant*
<galibert[m]> Catherine: alternatively, wouldn't `s.reset = ["field", 1}` be easier to implement?
<galibert[m]> s/[/{/
<whitequark[cis]> no
<whitequark[cis]> this precludes you from having a field called "reset"
<whitequark[cis]> what's next, s.decoder? s.reset_less? who is going to spend time making sure all this crap functions exactly as it does on signals?
<galibert[m]> Ah
<whitequark[cis]> and it doesn't even work if your layout is wrapping a non-Signal, which is explicitly supported
<galibert[m]> s is a View derivative, right?
<galibert[m]> Following that logic (or not), s.eq(...) or s.as_value().eq(...) ?
<whitequark[cis]> there is a fixed list of the things that are directly supported; it is "everything defined by ValueCastable", plus eq
<galibert[m]> Ok, makes sense
<galibert[m]> Honestly I'm ambivalent w.r.t reset because it needs to go through an interpretation by whatever class the ValueCastable actually is. So you're going to need some kind of explicit support anyway... maybe
<galibert[m]> The classes relationships are complicated :-)
<galibert[m]> Anyway, enjoy your vacation
SpaceCoaster has quit [Ping timeout: 246 seconds]
SpaceCoaster has joined #amaranth-lang
crzwdjk has quit [Ping timeout: 246 seconds]
crzwdjk has joined #amaranth-lang
cyrozap has quit [Quit: ZNC 1.8.2+deb3.1 - https://znc.in]
mwk has quit [Ping timeout: 246 seconds]
mwk has joined #amaranth-lang
cyrozap has joined #amaranth-lang
skipwich has quit [Ping timeout: 252 seconds]
skipwich has joined #amaranth-lang
cyrozap has quit [Quit: ZNC 1.8.2+deb3.1 - https://znc.in]
cyrozap has joined #amaranth-lang
cyrozap has quit [Remote host closed the connection]
cyrozap has joined #amaranth-lang
cyrozap has quit [Quit: ZNC 1.8.2+deb3.1 - https://znc.in]
cyrozap has joined #amaranth-lang
jjsuperpower has joined #amaranth-lang
jjsuperpower has quit [Ping timeout: 244 seconds]
cyrozap has quit [Quit: ZNC 1.8.2+deb3.1 - https://znc.in]
cyrozap has joined #amaranth-lang
GenTooMan has quit [Ping timeout: 258 seconds]
GenTooMan has joined #amaranth-lang
cyrozap has quit [Quit: ZNC 1.8.2+deb3.1 - https://znc.in]
cyrozap has joined #amaranth-lang
<crzwdjk> whitequark[cis]: no diff but this is the new code, ported from an earlier, never-released version: https://github.com/crzwdjk/uniterm/blob/main/gateware/flasharb.py#L13
<crzwdjk> I didn't bother to make it fully generic but I probably should at some point as I might need this for other resources.
<mcc111[m]> <adamgreig[m]> "it might be better to just run..." <- So I want to return to this series of comments by adam... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/ETOTjKJvtLnPivFHQlNRzEHo>)
<crzwdjk> EnableInserter seems to be completely undocumented, your best bet might be to try to find some code that uses it. But I think it takes an "enable" Signal and only enables the logic you call it on when that signal is high.
<mcc111[m]> Does Amaranth have a list of which parts of the API are currently undocumented, and if I were willing to volunteer in writing docs for currently undocumented classes/features, would that be helpful?
zyp[m] has quit [Quit: Idle timeout reached: 172800s]
<adamgreig[m]> mcc111: sorry, I was explaining it on my phone I think and didn't get to write much detail, let me try and clarify a bit
<adamgreig[m]> the abstract machine I like to imagine I'm targetting with an fpga is synchronous digital logic, where there's one clock that's not really a signal so much as driving how all the signals move through the design, and if you can avoid thinking of the clock as just another signal (or a signal as perhaps being usable as a clock) it tends to keep you out of trouble
<adamgreig[m]> in the actual fpga, you have LUTs that are just combinatorial and don't interact with the clock, and FFs that typically have a clock input, a clock enable input (or just "enable"), a data input, and a data output, and they are what make things "synchronous"; ideally they all receive the clock edge at the same time everywhere in your design and that causes them to move the data input to the data output iff the enable is asserted
<adamgreig[m]> too, otherwise the clock edge is ignored
<adamgreig[m]> the clock signals are distributed to all the FFs using special clock routing hardware, which aims to minimise the difference in clock arrival times at all FFs to maintain the abstraction, so in a practical sense the clock signals are "special"
<adamgreig[m]> (that's not always true, and you can usually wire a logic signal into the clock input, and you can also wire a logic signal into that global clock distribution network, and sometimes you use that global network for other low-skew global signals like reset or enables, but it's maybe a convenient thing to think about)
<adamgreig[m]> creating a new clock out of logic then is a bit troublesome: it's hard to control exactly what the delay is between the edge in your generated clock and the edge of the global clock, especially once your new signal has been routed into the global logic and such (some fpgas have programmable delay blocks and things to help with this too...), and the generated clock might have glitches (because for example LUT outputs can glitch as
<adamgreig[m]> this
<adamgreig[m]> their inputs change, they're just correct once they've "settled" before the next clock edge), so while you can generate a new clock out of logic and feed it to the clock input of a bunch of FFs, it requires extra care to get right, and if you don't get it right, it's not always obvious until it causes extremely hard-to-debug problems later on, and the tooling (especially the open-source tooling) doesn't have much to help with
<adamgreig[m]> so, in the simplest case, you could instead just run all your logic off one clock, but if you want some parts to be slower, you can change their enable inputs: if you turn enable off on every other clock cycle, it's just as though that logic is running at half the clock freq, since it only sees every other clock pulse, but the clock edges it does see are exactly in-sync with the clock running the rest of your logic, so there's no
<adamgreig[m]> problems
<adamgreig[m]> the downside here is that the tooling doesn't know you're only running this logic every other clock, so it still needs to be sure the logic is fast enough to run every clock, so if you're slowing logic down because it's gotten too complicated to keep up at the fast clock, you can't go this route
<adamgreig[m]> instead of running the enable every-other-clock, you can run it any m-in-n clocks, e.g. have it on-on-on-off to get a 3/4 clock, which gets you whatever rational division you want
<adamgreig[m]> you could express this by just having "with m.If(enable): m.d.sync += bla,bla,bla" in amaranth, but as a convenience to wrap an entire submodule in an enable signal, EnableInserter wraps the provided module in a big "with m.If(enable)" block; you give it an "enable" signal (any signal) and it makes all the contained logic only run when that enable is high
<adamgreig[m]> in verilog people really like to write "@(posedge whatever foo bar)" and the synthesis tooling will go out of its way to sort of make that work, but when what you want to express is "this part of my synchronous logic should react to this external signal falling high to low", it's not the right tool/expression/abstraction, you want "sample the signal using my main clock, respond when the sampled value was high and is now low",
<adamgreig[m]> instead you're asking it to synthesise "this flipflop should be clocked by this external signal" with no sound way to get that event into the rest of your logic
<mcc111[m]> Okay. So "If" and "Enable" are in some sense two totally different things, even though they both have the ultimate effect of making something happen or not happen. Hm.
<adamgreig[m]> I don't think that's what I meant
<adamgreig[m]> EnableInserter is just a handy wrapper to avoid having to write a lot of m.If() yourself, in some sense. both could ultimately give you the exact same synthesised design
<adamgreig[m]> (If also expressed combinatorial things that don't involve an enable signal, though)