Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix macro generation #902

Merged

Conversation

kr-sc
Copy link
Contributor

@kr-sc kr-sc commented Oct 10, 2023

  1. We need to add ULL modifier to all values to fix some issues with set_field and get_field OpenOCD macros (for example, when mask = 2 << 31, it leads to UB)

@kr-sc kr-sc force-pushed the kr-sc/fix-register-definitions-prefixes branch from 88cef97 to 20104f3 Compare October 10, 2023 16:45
@timsifive
Copy link
Contributor

Does this still let OpenOCD build using mingw32? ISTR that was the reason to add the extension.

@kr-sc kr-sc force-pushed the kr-sc/fix-register-definitions-prefixes branch from 20104f3 to 1664d36 Compare October 10, 2023 18:57
@kr-sc
Copy link
Contributor Author

kr-sc commented Oct 10, 2023

Does this still let OpenOCD build using mingw32? ISTR that was the reason to add the extension.

Yes, I successfully build OpenOCD with mingw32.

@kr-sc
Copy link
Contributor Author

kr-sc commented Oct 11, 2023

ISTR that was the reason to add the extension.

Just a double-check: what is extension are you talking about? And what does ISTR mean?

@kr-sc
Copy link
Contributor Author

kr-sc commented Oct 11, 2023

Upd: I have a problems with testing OpenOCD on riscv-tests with new debug_defines.h/c (ETrigger, ICount and ITrigger fail). I'm investigating.

@timsifive
Copy link
Contributor

Just a double-check: what is extension are you talking about? And what does ISTR mean?

By "extension" I meant "ULL". ISTR=I Seem To Recall

@kr-sc kr-sc force-pushed the kr-sc/fix-register-definitions-prefixes branch 2 times, most recently from e3c8b29 to 527662c Compare October 18, 2023 16:53
@kr-sc
Copy link
Contributor Author

kr-sc commented Oct 18, 2023

Previous version of this patch leads to failure on some (look above) riscv-tests. After I replace U with ULL, it was fixed.

Short reproduction of occured problem you can see here: https://godbolt.org/z/z6n7xd71s (change MASK from 0x3fULL to 0x3fU to see difference). When we try to set 1 with mask 0x3fU to 0x5800000000000000 , hight 32 bits of value become zero. It happened because ~(0x3fU) is a 0xffffffc0, so after conversion to uint64_t we lost hight 32 bits.

Copy link
Contributor

@timsifive timsifive left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall.

registers.py Outdated
return "-0x%x" % -expression
elif (expression > -2**32):
return "-0x%xU" % -expression
sufffix = "ULL" if unsigned else ""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
sufffix = "ULL" if unsigned else ""
suffix = "ULL" if unsigned else ""

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

1) We need to add ULL modifier to all values to fix some issues with `set_field` and `get_field` OpenOCD macros (for example, when `mask` = 1 << 31, it leads to UB becuase of signed overflow)
@kr-sc kr-sc force-pushed the kr-sc/fix-register-definitions-prefixes branch from 527662c to 44b8d86 Compare October 23, 2023 11:05
@timsifive timsifive merged commit f762968 into riscv:master Oct 23, 2023
@timsifive
Copy link
Contributor

I just tried to use the output of this with OpenOCD, and it fails to build because of a bunch of printf() using %d for what are now ULL values. How did you resolve that?

Looking at your godbolt example again, doesn't it make more sense to change the shift macro?

@kr-sc
Copy link
Contributor Author

kr-sc commented Nov 1, 2023

I just tried to use the output of this with OpenOCD, and it fails to build because of a bunch of printf() using %d for what are now ULL values. How did you resolve that?

I just replace %d with correct specifier in all such places.

Looking at your godbolt example again, doesn't it make more sense to change the shift macro?

We thoughr about it at internal discussion (with @aap-sc and @en-sc ) and came to conclusion that we need both changes: fix macro and update suffixes. I work on patch for shift macro now.

@timsifive
Copy link
Contributor

I just replace %d with correct specifier in all such places.

That seems like a lot of unnecessary churn. Here's an example of an OpenOCD build error if we use the latest version:

../src/helper/log.h:150:19: error: format '%lx' expects argument of type 'long unsigned int', but argument 7 has type 'long long unsigned int' [-Werror=format=]
  150 |         LOG_ERROR("[%s] " fmt_str, target_name(target), ##__VA_ARGS__)
      |                   ^~~~~~~
../src/helper/log.h:124:68: note: in definition of macro 'LOG_ERROR'
  124 |         log_printf_lf(LOG_LVL_ERROR, __FILE__, __LINE__, __func__, expr)
      |                                                                    ^~~~
../src/target/riscv/riscv-013.c:4952:9: note: in expansion of macro 'LOG_TARGET_ERROR'
 4952 |         LOG_TARGET_ERROR(target, "Unknown DCSR cause field: 0x%" PRIx64, get_field(dcsr, CSR_DCSR_CAUSE));
      |         ^~~~~~~~~~~~~~~~

Because the new definition of CSR_DCSR_CAUSE is:

#define CSR_DCSR_CAUSE                      0x1c0ULL

There is no reason for that constant to have any suffix at all. The original code only applied the suffix for large constants, which seems cleaner.

What specific bug did you originally encounter? Which fields were involved?

@kr-sc
Copy link
Contributor Author

kr-sc commented Nov 1, 2023

What specific bug did you originally encounter? Which fields were involved?

I catch UB on OpenOCD with Sanitizer on riscv-013.c:5064

dmcontrol = set_field(dmcontrol, DM_DMCONTROL_RESUMEREQ, 0);

@kr-sc
Copy link
Contributor Author

kr-sc commented Nov 1, 2023

There is no reason for that constant to have any suffix at all. The original code only applied the suffix for large constants, which seems cleaner.

As I write above, we decided to apply U suffixes to all such constants. At first version of patch I apply U or ULL depends on value, but get an error in riscv-test (comment above). So, after that we decided to make all such constants ULL.

@en-sc
Copy link
Contributor

en-sc commented Nov 1, 2023

The original issue was with undefined behavior due to integer overflow in operations like so:

dmcontrol = set_field(dmcontrol, DM_DMCONTROL_RESUMEREQ, 0);

set_field macro calculates DM_DMCONTROL_RESUMEREQ << 1 which does not fit an int.
(riscv013_step_or_resume_current_hart())

To mitigate this, such constants were made unsigned.

As for LL part:

#define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))

If val is an int and mask is unsigned int, (val) * ((mask) & ~((mask) << 1) can be 0 (unsigned overflow), so the result will be zero (The comment with an example).

An alternative approach is to use a direct cast to a fixed-length integer types for masks (depending on the size of the register):

#define CSR_DCSR_CAUSE                      (uint32_t)0x1c0

@timsifive
Copy link
Contributor

There are 3 types of values in debug_defines.h:

  1. Offsets, which cannot be negative so unsigned makes sense.
  2. Lengths, which also cannot be negative. Same.
  3. Masks, which also can't be negative. Same.

So I agree that every number should be unsigned. But masks of 32-bit registers (such as dmcontrol) shouldn't be 64-bit. Field offsets and lengths shouldn't be 64-bit either. It just feels off.

What if we use this function instead of the macro? Seems to work. Less messy than macros in any case, and the types are very explicit.

static inline uint64_t set_field(uint64_t reg, uint64_t mask, uint64_t val)
{
	/* Clear current value from field. */
	reg &= ~mask;
	uint64_t low_field_bit = mask & ~(mask << 1);
	reg |= (val * low_field_bit) & mask;
	return reg;
}

kr-sc added a commit to kr-sc/riscv-openocd that referenced this pull request Dec 4, 2023
Change-Id: Ie969866d1de83360a5f45e96e22108b58b8aa02f
Signed-off-by: Kirill Radkin <kirill.radkin@syntacore.com>
kr-sc added a commit to kr-sc/riscv-openocd that referenced this pull request Dec 6, 2023
Change-Id: Ie969866d1de83360a5f45e96e22108b58b8aa02f
Signed-off-by: Kirill Radkin <kirill.radkin@syntacore.com>
kr-sc added a commit to kr-sc/riscv-openocd that referenced this pull request Dec 6, 2023
Change-Id: Ie969866d1de83360a5f45e96e22108b58b8aa02f
Signed-off-by: Kirill Radkin <kirill.radkin@syntacore.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants