<mcc111[m]>
say I have a wide (like… 100bits) register.
<mcc111[m]>
is the most sensible way to initialize its value to give it a python bignum, or can I give it like, a bytes value or something?
<whitequark[cis]>
you cannot give it a bytes value; it has to be a python int
<whitequark[cis]>
but you can do int.from_bytes
<galibert[m]>
Catherine: not bytes so you don't have to care about endianness?
<whitequark[cis]>
yeah, or sub-octet alignment
<galibert[m]>
true that
jjsuperpower has quit [Ping timeout: 244 seconds]
jjsuperpower has joined #amaranth-lang
jjsuperpower has quit [Ping timeout: 258 seconds]
pbsds has quit [Ping timeout: 245 seconds]
<mcc111[m]>
How "efficient" (I'm not sure in which sense I mean this) is a rotate_right on N where N is a dynamic (runtime) value?
<mcc111[m]>
I was told that "indexing" a large register dynamically is probably pretty inefficient. Do dynamic rotates do better?
<mcc111[m]>
or bitshifts for that matter
<whitequark[cis]>
> Rotate operations with variable rotate amounts cannot be efficiently synthesized for non-power-of-2 widths of the rotated value. Because of that, the rotate operations are only provided for constant rotate amounts, specified as Python ints.
<whitequark[cis]>
(from the manual)
<galibert[m]>
Count the number on inputs for a given output and you’ll see the problem immediately
<mcc111[m]>
Thanks.
<mcc111[m]>
One more thing I think I've seen discussed in here— is a 0-length Signal allowed, and what things are allowed to be done on it?
<mcc111[m]>
EG if I create a 0-length signal but don't attach anything to it (eg it doesn't take part in any comb or sync) do I have a legal program?
<whitequark[cis]>
it is allowed insofar as it is unsigned
<whitequark[cis]>
in fact any use of a value with the unsigned(0) shape is valid, anywhere in the program at all
<whitequark[cis]>
if you manage to break Amaranth like this, which is unlikely, that is a bug
<mcc111[m]>
So it is an unsigned value which always has value 0?
<Wanda[cis]>
evaluate to another 0-width 0, in fact
<galibert[m]>
BTW, that makes me think, is there a recommended way to write the mantissa alignment for an addition in floating point in amaranth/on a fpga?
<mcc111[m]>
<Wanda[cis]> "evaluate to another 0-width 0..." <- *thinks* okay actually i meant to say "evaluate to 1" but I guess this is just a different right thing
<galibert[m]>
Not sure it's ok to say it evaluates to 1 because that would imply it's at least one bit
<galibert[m]>
I think adding 0 evaluates to (0, unsigned(1)) for instance
<whitequark[cis]>
... is that a bug
<galibert[m]>
No, I'm pretty sure ~(0, unsigned(0)) should be (0, unsigned(0))
<galibert[m]>
it's the only thing that makes sense
<galibert[m]>
So no bug
<mcc111[m]>
"Although Python integers have unlimited precision and Amaranth values are represented with a finite amount of bits, arithmetics on Amaranth values never overflows because the width of the arithmetic expression is always sufficient to represent all possible results."
<mcc111[m]>
So it depends on whether ~ is an arithmetic expression. If ~ is an arithmetic expression, ~(0, unsigned(0)) should be 1. Otherwise, 0 is fine.
<galibert[m]>
No? Because ~(0, unsigned(16) = (0xffff, unsigned(16)), not (1, unsigned(16))
<mcc111[m]>
That makes sense
<galibert[m]>
~ is defined as inverting whatever bits there are
<galibert[m]>
there's nothing to invert
<mcc111[m]>
This said, it feels like a gotcha, since it didn't match my intuition. Might be worth it to mention this case in the docs and give a "if you want ~v where v is 0 length, instead use [???]" (I guess ??? is x == 0? that's waht i used in my code)
<galibert[m]>
Note that if you use (0, unsigned(0)) outside of generated code/generics-equivalent, you probably have a problem
<whitequark[cis]>
Ohh right ~ not -. Tired
<whitequark[cis]>
Oh no I should stop talking forreal
<whitequark[cis]>
Really tired.
zyp[m] has joined #amaranth-lang
<zyp[m]>
what does foo.eq(~bar) do in the general case where foo is wider than bar with regard to the upper bits?
<galibert[m]>
Sign-extension at eq time
<galibert[m]>
Going to bed early from time to time can be real nice
<zyp[m]>
so foo = Signal(8); m.comb += foo.eq(~C(0, 4)) results in foo being 0x0f?
<mcc111[m]>
<galibert[m]> "Note that if you use (0..." <- In my case, I have a counter whose number of bits is parameterized on the component. Making it "behave properly" for 0 (timer is of 0 length, and continuously fires) would have required a bunch of special logic, but the fact 0 bit signals have a specific behavior means I could just write my logic so it does the right thing when bits=0, no special casing needed really…
<mcc111[m]>
…but that's generated code, so…
<galibert[m]>
Yeah, your kind of code is exactly why it’s possible
<jfng[m]>
zyp[m]: yes, but `foo.eq(~C(0, signed(4))` will result in `foo` being `0xff`
<zyp[m]>
makes sense
<zyp[m]>
in that case it makes total sense for ~C(0, 0) to evaluate to C(0, 0)