riscv-v-spec icon indicating copy to clipboard operation
riscv-v-spec copied to clipboard

Clarify the relationship between extensions.

Open kito-cheng opened this issue 3 years ago • 27 comments

Update:

2021/9/6: Add zvamo and zvlsseg.


  • V extension require F and D, does it means implies? current ISA spec[1] only use implies and didn't appear any require, so I would like having more explicitly clarification for that word.

  • Can Zvl*b use without V, zve32* or zve64*?

  • Are these valid combinations? or it's valid but just meaningless, because it won't effect the minimal VLEN?

    • V with zvl32b, zvl64b
    • Zve64 with zvl32b
  • Are these valid combinations?

    • V with zve32* or zve64*
    • Any combination two different zve* extensions .
  • Can zvamo and zvlsseg use without V, zve32* or zve64*?

[1] https://github.com/riscv/riscv-isa-manual/blob/draft-20210825-d068b76/src/naming.tex#L148

kito-cheng avatar Aug 26 '21 06:08 kito-cheng

Few more thing want to clarify:

  • Are these valid combinations?
    • V with zve32* or zve64*
    • Any combination two different zve* extensions .

kito-cheng avatar Aug 26 '21 06:08 kito-cheng

Does V extension passed to -march should imply at least Zvl128b? (The V vector extension requires that VLEN ≥ 128.)

zakk0610 avatar Sep 01 '21 08:09 zakk0610

Can Zvlb use without V, zve32 or zve64*?

In other words, the question is "Does Zvl*b passed to -march should imply the V extension?"

zakk0610 avatar Sep 01 '21 08:09 zakk0610

Yes, I think V should imply Zvl128b.

aswaterman avatar Sep 01 '21 20:09 aswaterman


Changes: 2021/9/8: Update note for ELF attribute.

Hmmm...toolchain still need clarification, but before we got a formal clarification, I written down my understanding and my guess, and we gonna to implement that on toolchain.

  • zvl<x>b implied zvl<y>b if x > y, e.g. zvl256b implied zvl128b, zvl64b and zvl32b.
  • v implied zvl128b, Zve64* implied zvl64b and Zve32* implied zvl32b.
  • v with zvl32b is valid combination but minimal VLEN still 128 due to v implied zvl128b.
  • Zve64 with zvl32b is valid combination but minimal VLEN still 64 due to Zve64 implied zvl64b.
  • v with any zve* extension is valid combination is valid, but still same as v, e.g. v + zve32x = v
  • Different Zve* extension can be appear in arch string, but we only take the info from the biggest extension, e.g.
    • zve64x + zve32x = zve64x
    • zve64d + zve32f = zve64d
    • zve64d + zve64f = zve64d
  • require means toolchain will report error and abort if the requirement not satisfied, e.g. toolchain will report error for rv32iv rather than interpret that as rv32ifdv
  • Zvl*b require either v or zve* extension, otherwise it's invalid arch, toolchain will report error.

Note for ELF attribute:

  • Tag_RISCV_arch always emit fully expanded form, e.g. v will expand to v1p0_zvl128b1p0_zvl64b1p0_zvl32b1p0_zvlsseg1p0_zve64d1p0_zve64f1p0_zve64x1p0_zve32f1p0_zve32x1p0.

kito-cheng avatar Sep 03 '21 07:09 kito-cheng

Hmmm...toolchain still need clarification, but before we got a formal clarification, I written down my understanding and my guess, and we gonna to implement that on toolchain.

  • zvl<x>b implied zvl<y>b if x > y, e.g. zvl256b implied zvl128b, zvl64b and zvl32b.

  • v implied zvl128b, Zve64* implied zvl64b and Zve32* implied zvl32b.

  • v with zvl32b is valid combination but minimal VLEN still 128 due to v implied zvl128b.

  • Zve64 with zvl32b is valid combination but minimal VLEN still 64 due to Zve64 implied zvl64b.

  • v with any zve* extension is valid combination is valid, but still same as v, e.g. v + zve32x = v

  • Different Zve* extension can be appear in arch string, but we only take the info from the biggest extension, e.g.

    • zve64x + zve32x = zve64x
    • zve64d + zve32f = zve64d
    • zve64d + zve64f = zve64d
  • require means toolchain will report error and abort if the requirement not satisfied, e.g. toolchain will report error fr rv32iv rather than interpret that as rv32ifdv

  • Zvl*b require either v or zve* extension, otherwise it's invalid arch, toolchain will report error.

Addition rule for ELF attribute:

  • zvl*b extension must present at Tag_RISCV_arch attribute if v or zve* extension there.
  • Only emit largest zvl*b to Tag_RISCV_arch attribute, e.g. zvl256b + zvl128b, then we only emit zvl256 to attribute.
  • For v and zve*, only emit biggest extension to Tag_RISCV_arch.

My understanding is the same, especially agree with that we only need to take the information from the biggest/largest zve/zvl extensions.

Nelson1225 avatar Sep 03 '21 07:09 Nelson1225

Oh forgot to mention that - the linker should have the same reduced architecture string for zve and zvl. For example, there are two objects, one has zve64x, and another has zve32x. If we link the two objects, then the output architecture string should only have zve64x, since zve32x is covered by it.

Nelson1225 avatar Sep 03 '21 08:09 Nelson1225

If the canonical form of Zfoo32b + Zfoo64b is Zfoo64b only then things don't work, because then you risk a kernel or run-time linker seeing it has Zfoo64b and not thinking that satisfies a Zfoo32b binary because it doesn't also see Zfoo32b, and you'd need to bake in extra logic to teach it about all those special cases.

The canonical (exploded) form for Zfoo32b + Zfoo64b should be Zfoo32b_Zfoo64b. Just as the canonical (exploded) form for F+D is FD. This is longer but things "just work"; having implicit extensions in the machine-processed arch strings just causes headaches. That's for the human-facing strings only.

jrtc27 avatar Sep 05 '21 21:09 jrtc27

Updated: Add one more item:

  • Can zvamo and zvlsseg use without V, zve32* or zve64*?

kito-cheng avatar Sep 06 '21 13:09 kito-cheng

Also add one more item to toolchain implementation note:

  • zvamo and zvlsseg require either v or zve* extension, otherwise it's invalid arch, toolchain will report error.

kito-cheng avatar Sep 06 '21 13:09 kito-cheng

Also add one more item to toolchain implementation note:

  • zvamo and zvlsseg require either v or zve* extension, otherwise it's invalid arch, toolchain will report error.

According to the previous implementation and comments, https://github.com/riscv/riscv-binutils-gdb/pull/219

The zvamo and zvlsseg can be used without v, so I think v shouldn't be required to be specified for them.

Nelson1225 avatar Sep 07 '21 03:09 Nelson1225

The question here is does zvamo require v, or does it imply v. I think it is simpler if it requires v. Likewise with zvlsseg.

jim-wilson avatar Sep 07 '21 17:09 jim-wilson

Hmmm...toolchain still need clarification, but before we got a formal clarification, I written down my understanding and my guess, and we gonna to implement that on toolchain.

  • zvl<x>b implied zvl<y>b if x > y, e.g. zvl256b implied zvl128b, zvl64b and zvl32b.

  • v implied zvl128b, Zve64* implied zvl64b and Zve32* implied zvl32b.

  • v with zvl32b is valid combination but minimal VLEN still 128 due to v implied zvl128b.

  • Zve64 with zvl32b is valid combination but minimal VLEN still 64 due to Zve64 implied zvl64b.

  • v with any zve* extension is valid combination is valid, but still same as v, e.g. v + zve32x = v

  • Different Zve* extension can be appear in arch string, but we only take the info from the biggest extension, e.g.

    • zve64x + zve32x = zve64x
    • zve64d + zve32f = zve64d
    • zve64d + zve64f = zve64d
  • require means toolchain will report error and abort if the requirement not satisfied, e.g. toolchain will report error fr rv32iv rather than interpret that as rv32ifdv

I don't agree with it. Extension should be able to be specified stand alone. For example, users could specify rv64id without f. Why are we not able to specify v only? That means the only way to specify v is fdv.

  • Zvl*b require either v or zve* extension, otherwise it's invalid arch, toolchain will report error.

Addition rule for ELF attribute:

  • zvl*b extension must present at Tag_RISCV_arch attribute if v or zve* extension there.
  • Only emit largest zvl*b to Tag_RISCV_arch attribute, e.g. zvl256b + zvl128b, then we only emit zvl256 to attribute.
  • For v and zve*, only emit biggest extension to Tag_RISCV_arch.

Hsiangkai avatar Sep 08 '21 05:09 Hsiangkai

I don't agree with it. Extension should be able to be specified stand alone. For example, users could specify rv32id without f. Why are we not able to specify v only? That means the only way to specify v is fdv.

F and D extension are both floating point extension, one for single precision and one for double precision, which is highly related.

But for the case of vector operation, it's not obviously relationship between vector and floating point like single precision and double precision.

That behavior will result -march=rv64ifvequal to -march=rv64ifdv, rv64ifv have no d, that means user didn't want d extension, but toolchain implied enabled d because v, in this case, user should either use zve64f or explicitly enabled d , both are possible expected behavior for user, but we never known which one is user's intention, just report error to let user explicitly choose the right way is better IMO.

My intention to prevent require those non-trivial and not obvious knowledge for toolchain user, just like we are trying to release the canonical order hell for the -march option.

kito-cheng avatar Sep 08 '21 08:09 kito-cheng

@jrtc27

If the canonical form of Zfoo32b + Zfoo64b is Zfoo64b only then things don't work, because then you risk a kernel or run-time linker seeing it has Zfoo64b and not thinking that satisfies a Zfoo32b binary because it doesn't also see Zfoo32b, and you'd need to bake in extra logic to teach it about all those special cases.

The canonical (exploded) form for Zfoo32b + Zfoo64b should be Zfoo32b_Zfoo64b. Just as the canonical (exploded) form for F+D is FD. This is longer but things "just work"; having implicit extensions in the machine-processed arch strings just causes headaches. That's for the human-facing strings only.

My intention was want to reduce the size of Tag_RISCV_arch, but after I write down a arch string with all ratified ext. with crypto, vector and bitmanip, it seems reduce size seems not so useful - it's still long but introduce too many rule need to handle, so I think let keep full expanded version to keep the rule simple.

Full expanded version: "rv64i2p1_m2p0_a2p0_f2p0_d2p0_c2p0_v1p0_zicsr2p0_zifencei2p0_zba1p0_zbb1p0_zbc1p0_zvl128b1p0_zvl64b1p0_zvl32b1p0_zvlsseg1p0_zve64d_zve64f_zve64x_zve32f_zve32x_zbkb1p0_zbkc1p0_zbkx1p0_zknd1p0_zkne1p0_zknh1p0_zksed1p0_zksh1p0_zkr1p0_zkm1p0_zks1p0_zk1p0_zkt1p0"

Reduced version: "rv64i2p1_m2p0_a2p0_f2p0_d2p0_c2p0_v1p0_zicsr2p0_zifencei2p0_zba1p0_zbb1p0_zbc1p0_zvl128b1p0_zvlsseg1p0_zkn1p0_zkn1p0_zks1p0"

kito-cheng avatar Sep 08 '21 15:09 kito-cheng

@kito-cheng

Can zvamo and zvlsseg use without V, zve32* or zve64*?

I don't see Zvamo mentioned anywhere in the v1.0-rc1 spec. I don't think we need to support it.

I don't know what to say about "standalone Zvlsseg". I can't imagine that is an intended design point.

On a related note, I think the spec should just drop the Zvlsseg ISA string: I see no need to standardize a name for this subset. It certainly made sense when it was optional, but nowadays it is included in all the standard extensions. However, I've suggested this multiple times to the task group and it's never been changed, so I suppose its persistence is intentional.

nick-knight avatar Sep 08 '21 16:09 nick-knight

@kito-cheng

Can zvamo and zvlsseg use without V, zve32* or zve64*?

I don't see Zvamo mentioned anywhere in the v1.0-rc1 spec. I don't think we need to support it.

@nick-knight

I don't know what to say about "standalone Zvlsseg". I can't imagine that is an intended design point.

On a related note, I think the spec should just drop the Zvlsseg ISA string: I see no need to standardize a name for this subset. It certainly made sense when it was optional, but nowadays it is included in all the standard extensions. However, I've suggested this multiple times to the task group and it's never been changed, so I suppose its persistence is intentional.

Oh, thanks for point out that, that actually give me wrong impression is: Zvlsseg is a standalone subset...

Read the spec again, zve* and v both has this sentence, so yes, that should be gone on the toolchain side since all extension are support...

The V extension supports all vector load and store instructions (Section Vector Loads and Stores), except the V extension does not support EEW=64 for index values when XLEN=32.

kito-cheng avatar Sep 08 '21 17:09 kito-cheng

I don't agree with it. Extension should be able to be specified stand alone. For example, users could specify rv32id without f. Why are we not able to specify v only? That means the only way to specify v is fdv.

F and D extension are both floating point extension, one for single precision and one for double precision, which is highly related.

But for the case of vector operation, it's not obviously relationship between vector and floating point like single precision and double precision.

That behavior will result -march=rv64ifvequal to -march=rv64ifdv, rv64ifv have no d, that means user didn't want d extension, but toolchain implied enabled d because v, in this case, user should either use zve64f or explicitly enabled d , both are possible expected behavior for user, but we never known which one is user's intention, just report error to let user explicitly choose the right way is better IMO.

The worry is based on the assumption that v implies f and d. What if v does not imply f and d in the tool implementation? Users will specify what users want explicitly and there is no confusion. So,

If users only use integer vector operations, they could specify rv64iv without error messages. If users use single-floating point vector operations, they will specify rv64ifv without error messages. If users use double-floating point vector operations, they will specify rv64idv without error messages.

To enforce users to specify fdv for vector extension, it causes confusion from users' perspective, especially when users only use integer vector operations and see the error messages for rv64iv.

I think arch string is already complex. We have no need to add additional rules on it.

My intention to prevent require those non-trivial and not obvious knowledge for toolchain user, just like we are trying to release the canonical order hell for the -march option.

Hsiangkai avatar Sep 09 '21 01:09 Hsiangkai

In 1.0, I think users should use rv64i_zve*x if they only want to use integer vector operation. I guess it's why the requirement The V extension requires the scalar processor to implement the F and D extensions, and implements all vector floating-point instructions and Zve*x are in the same commit https://github.com/riscv/riscv-v-spec/commit/808a6f83b72d92757ef4c93fcdf076ed99bbecae.

zakk0610 avatar Sep 09 '21 02:09 zakk0610

There is already considerable momentum in this regard. Table 27.1 in Vol. 1 defines an "implies" relation on various extensions, for example, Q => D => F => Zicsr. In this case we might add V => D.

I note that toolchains implement a superset of this relation. For example, Clang/LLVM happily assembles this:

void foo(void) { asm ("csrrs x1, 17, x0"); }

with -march=rv32i, despite csrrs being part of the Zicsr extension [godbolt link].

EDIT: the toolchain folks have informed us below that this behavior is due to a backwards-incompatible change between i2p0 and i2p1 which is still being addressed.

nick-knight avatar Sep 09 '21 02:09 nick-knight

@nick-knight the fact is LLVM still implement i ext 2.0, which base extension still include zicsr and zifencei, you can try -march=rv32i_zcisr for clang, that result unsupported standard user-level extension 'zcisr', split zicsr and zifencei from baseline ISA is really annoying backward incompatible change...

kito-cheng avatar Sep 09 '21 02:09 kito-cheng

For GNU toolchain, @Nelson1225 and me has implement that on upstream for a while, which included in GCC 11, but that not available on https://godbolt.org/ :(

kito-cheng avatar Sep 09 '21 02:09 kito-cheng

There is already considerable momentum in this regard. Table 27.1 in Vol. 1 defines an "implies" relation on various extensions, for example, Q => D => F => Zicsr. In this case we might add V => D.

Yeah, but I am prefer to make sure this write down to the implies column, before that I treat require and implies are different.

kito-cheng avatar Sep 09 '21 02:09 kito-cheng

Changes:

2021/9/8: Update note for ELF attribute. Hmmm...toolchain still need clarification, but before we got a formal clarification, I written down my understanding and my guess, and we gonna to implement that on toolchain.

  • zvl<x>b implied zvl<y>b if x > y, e.g. zvl256b implied zvl128b, zvl64b and zvl32b.

  • v implied zvl128b, Zve64* implied zvl64b and Zve32* implied zvl32b.

  • v with zvl32b is valid combination but minimal VLEN still 128 due to v implied zvl128b.

  • Zve64 with zvl32b is valid combination but minimal VLEN still 64 due to Zve64 implied zvl64b.

  • v with any zve* extension is valid combination is valid, but still same as v, e.g. v + zve32x = v

  • Different Zve* extension can be appear in arch string, but we only take the info from the biggest extension, e.g.

    • zve64x + zve32x = zve64x
    • zve64d + zve32f = zve64d

A question about the rule. Why not emit an error message for the case. You do not know what the users want if they specify both zve* extensions in the arch string. I think the situation is similar to rv64if_zve64d or rv64id_zve64f. I agree we should expand it in the ELF attributes, but for human-facing string, should we restrict users to only specify v or one of zve* extensions?

  • zve64d + zve64f = zve64d
  • require means toolchain will report error and abort if the requirement not satisfied, e.g. toolchain will report error for rv32iv rather than interpret that as rv32ifdv
  • Zvl*b require either v or zve* extension, otherwise it's invalid arch, toolchain will report error.

Note for ELF attribute:

  • Tag_RISCV_arch always emit fully expanded form, e.g. v will expand to v1p0_zvl128b1p0_zvl64b1p0_zvl32b1p0_zvlsseg1p0_zve64d1p0_zve64f1p0_zve64x1p0_zve32f1p0_zve32x1p0.

Hsiangkai avatar Sep 16 '21 03:09 Hsiangkai

General rule is that extension names imply the things they require, and we take union of all implied features. This simplifies model when string is built up in pieces in different places, with multiple repeated additions of same extension. After vector spec isout, plan to revisit the naming chapter to clear this up.

kasanovic avatar Sep 18 '21 01:09 kasanovic

RISC-V specs use the verb "depend" to describe the relationship between e.g. D and F. The Naming chapter makes it clear that dependence relationships can be used to shorten ISA strings: https://github.com/riscv/riscv-isa-manual/blob/399c9a759eb4540a65c60e2cc236164821ff2346/src/naming.tex#L46

This thread demonstrates that using the alternate verb "require" is causing confusion, so I've fixed the spec to use the standard verb. e8594a7b9f4c22d3c02e2cdf81ad5db8d0bb8c01 and 6fedb869e213da03f36092d661d14911a2f9d2c6

aswaterman avatar Oct 22 '21 11:10 aswaterman

Did anyone try to estimate the number of different combinations that require separate libraries in the embedded toolchain?

In the latest release, the xPack GNU RISC-V Embedded GCC supports roughly 100 libraries and the compressed archive has more than 500 MB.

ilg-ul avatar Nov 15 '21 18:11 ilg-ul