File indexing completed on 2025-09-18 09:09:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #pragma once
0014
0015 #include <stdexcept>
0016 #include <string>
0017 #if defined(__HIP__)
0018 # include <hip/hip_runtime.h>
0019 #elif defined(__CUDA_ARCH__)
0020
0021 #else
0022 # include <ostream> // IWYU pragma: export
0023 # include <sstream> // IWYU pragma: keep
0024 #endif
0025
0026 #include "corecel/Config.hh"
0027
0028 #include "Macros.hh"
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142 #if !defined(__HIP__) && !defined(__CUDA_ARCH__)
0143
0144 # define CELER_DEBUG_THROW_(MSG, WHICH) \
0145 throw ::celeritas::DebugError( \
0146 {::celeritas::DebugErrorType::WHICH, MSG, __FILE__, __LINE__})
0147 #elif defined(__CUDA_ARCH__) && !defined(NDEBUG)
0148
0149 # define CELER_DEBUG_THROW_(MSG, WHICH) \
0150 assert(false && sizeof(#WHICH ": " MSG))
0151 #else
0152
0153
0154
0155 # define CELER_DEBUG_THROW_(MSG, WHICH) \
0156 ::celeritas::device_debug_error( \
0157 ::celeritas::DebugErrorType::WHICH, MSG, __FILE__, __LINE__)
0158 #endif
0159
0160 #define CELER_DEBUG_ASSERT_(COND, WHICH) \
0161 do \
0162 { \
0163 if (CELER_UNLIKELY(!(COND))) \
0164 { \
0165 CELER_DEBUG_THROW_(#COND, WHICH); \
0166 } \
0167 } while (0)
0168 #define CELER_NDEBUG_ASSUME_(COND) \
0169 do \
0170 { \
0171 if (CELER_UNLIKELY(!(COND))) \
0172 { \
0173 ::celeritas::unreachable(); \
0174 } \
0175 } while (0)
0176 #define CELER_NOASSERT_(COND) \
0177 do \
0178 { \
0179 if (false && (COND)) {} \
0180 } while (0)
0181
0182
0183 #define CELER_DEBUG_FAIL(MSG, WHICH) \
0184 do \
0185 { \
0186 CELER_DEBUG_THROW_(MSG, WHICH); \
0187 ::celeritas::unreachable(); \
0188 } while (0)
0189
0190 #if !CELER_DEVICE_COMPILE
0191 # define CELER_RUNTIME_THROW(WHICH, WHAT, COND) \
0192 throw ::celeritas::RuntimeError({ \
0193 WHICH, \
0194 WHAT, \
0195 COND, \
0196 __FILE__, \
0197 __LINE__, \
0198 })
0199 #elif CELERITAS_DEBUG
0200 # define CELER_RUNTIME_THROW(WHICH, WHAT, COND) \
0201 CELER_DEBUG_FAIL("Runtime errors cannot be thrown from device code", \
0202 unreachable);
0203 #else
0204
0205 # define CELER_RUNTIME_THROW(WHICH, WHAT, COND) ::celeritas::unreachable()
0206 #endif
0207
0208 #if (CELERITAS_DEBUG && !CELER_DEVICE_COMPILE) \
0209 || (CELERITAS_DEVICE_DEBUG && CELER_DEVICE_COMPILE)
0210 # define CELER_EXPECT(COND) CELER_DEBUG_ASSERT_(COND, precondition)
0211 # define CELER_ASSERT(COND) CELER_DEBUG_ASSERT_(COND, internal)
0212 # define CELER_ENSURE(COND) CELER_DEBUG_ASSERT_(COND, postcondition)
0213 # define CELER_ASSUME(COND) CELER_DEBUG_ASSERT_(COND, assumption)
0214 # define CELER_ASSERT_UNREACHABLE() \
0215 CELER_DEBUG_FAIL("unreachable code point encountered", unreachable)
0216 #else
0217 # define CELER_EXPECT(COND) CELER_NOASSERT_(COND)
0218 # define CELER_ASSERT(COND) CELER_NOASSERT_(COND)
0219 # define CELER_ENSURE(COND) CELER_NOASSERT_(COND)
0220 # define CELER_ASSUME(COND) CELER_NDEBUG_ASSUME_(COND)
0221 # define CELER_ASSERT_UNREACHABLE() ::celeritas::unreachable()
0222 #endif
0223
0224 #if !CELER_DEVICE_COMPILE
0225 # define CELER_VALIDATE(COND, MSG) \
0226 do \
0227 { \
0228 if (CELER_UNLIKELY(!(COND))) \
0229 { \
0230 std::ostringstream celer_runtime_msg_; \
0231 celer_runtime_msg_ MSG; \
0232 CELER_RUNTIME_THROW( \
0233 ::celeritas::RuntimeError::validate_err_str, \
0234 celer_runtime_msg_.str(), \
0235 #COND); \
0236 } \
0237 } while (0)
0238 #else
0239 # define CELER_VALIDATE(COND, MSG) CELER_RUNTIME_THROW(nullptr, "", #COND)
0240 #endif
0241
0242 #define CELER_NOT_CONFIGURED(WHAT) \
0243 CELER_RUNTIME_THROW( \
0244 ::celeritas::RuntimeError::not_config_err_str, WHAT, {})
0245 #define CELER_NOT_IMPLEMENTED(WHAT) \
0246 CELER_RUNTIME_THROW(::celeritas::RuntimeError::not_impl_err_str, WHAT, {})
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270 #if CELERITAS_USE_CUDA || CELERITAS_USE_HIP
0271 # define CELER_DEVICE_API_CALL(STMT) \
0272 do \
0273 { \
0274 using ErrT_ = CELER_DEVICE_API_SYMBOL(Error_t); \
0275 ErrT_ result_ = CELER_DEVICE_API_SYMBOL(STMT); \
0276 if (CELER_UNLIKELY(result_ != CELER_DEVICE_API_SYMBOL(Success))) \
0277 { \
0278 result_ = CELER_DEVICE_API_SYMBOL(GetLastError)(); \
0279 CELER_RUNTIME_THROW( \
0280 CELER_DEVICE_PLATFORM_UPPER_STR, \
0281 CELER_DEVICE_API_SYMBOL(GetErrorString)(result_), \
0282 #STMT); \
0283 } \
0284 } while (0)
0285 #else
0286 # define CELER_DEVICE_API_CALL(STMT) \
0287 do \
0288 { \
0289 CELER_NOT_CONFIGURED("CUDA or HIP"); \
0290 CELER_DISCARD(CorecelDeviceRuntimeApiHh) \
0291 } while (0)
0292 #endif
0293
0294
0295 #define CELER_DEVICE_PREFIX(STMT) CELER_DEVICE_API_SYMBOL(STMT)
0296 #define CELER_DEVICE_CALL_PREFIX(STMT) CELER_DEVICE_API_CALL(STMT)
0297 #define CELER_DEVICE_CHECK_ERROR() CELER_DEVICE_API_CALL(PeekAtLastError())
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308 #if CELERITAS_USE_MPI
0309 # define CELER_MPI_CALL(STATEMENT) \
0310 do \
0311 { \
0312 int mpi_result_ = (STATEMENT); \
0313 if (CELER_UNLIKELY(mpi_result_ != MPI_SUCCESS)) \
0314 { \
0315 CELER_RUNTIME_THROW( \
0316 "MPI", mpi_error_to_string(mpi_result_), #STATEMENT); \
0317 } \
0318 } while (0)
0319 #else
0320 # define CELER_MPI_CALL(STATEMENT) \
0321 do \
0322 { \
0323 CELER_NOT_CONFIGURED("MPI"); \
0324 } while (0)
0325 #endif
0326
0327
0328
0329
0330
0331 namespace celeritas
0332 {
0333
0334
0335
0336 enum class DebugErrorType
0337 {
0338 precondition,
0339 internal,
0340 unreachable,
0341 postcondition,
0342 assumption,
0343 };
0344
0345
0346 struct DebugErrorDetails
0347 {
0348 DebugErrorType which;
0349 char const* condition;
0350 char const* file;
0351 int line;
0352 };
0353
0354
0355 struct RuntimeErrorDetails
0356 {
0357 char const* which{nullptr};
0358 std::string what{};
0359 std::string condition{};
0360 std::string file{};
0361 int line{0};
0362 };
0363
0364
0365
0366
0367
0368
0369 [[noreturn]] inline CELER_FUNCTION void unreachable()
0370 {
0371 CELER_UNREACHABLE;
0372 }
0373
0374
0375 char const* to_cstring(DebugErrorType which);
0376
0377
0378 std::string mpi_error_to_string(int);
0379
0380
0381
0382
0383
0384 struct JsonPimpl;
0385
0386
0387
0388
0389
0390 class DebugError : public std::logic_error
0391 {
0392 public:
0393
0394 explicit DebugError(DebugErrorDetails&&);
0395 CELER_DEFAULT_COPY_MOVE(DebugError);
0396
0397
0398 ~DebugError() override;
0399
0400
0401 DebugErrorDetails const& details() const { return details_; }
0402
0403 private:
0404 DebugErrorDetails details_;
0405 };
0406
0407
0408
0409
0410
0411 class RuntimeError : public std::runtime_error
0412 {
0413 public:
0414
0415 explicit RuntimeError(RuntimeErrorDetails&&);
0416 CELER_DEFAULT_COPY_MOVE(RuntimeError);
0417
0418
0419 ~RuntimeError() override;
0420
0421
0422 RuntimeErrorDetails const& details() const { return details_; }
0423
0424
0425
0426 static char const validate_err_str[];
0427 static char const not_config_err_str[];
0428 static char const not_impl_err_str[];
0429
0430
0431 private:
0432 RuntimeErrorDetails details_;
0433 };
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444 class RichContextException : public std::exception
0445 {
0446 public:
0447
0448 virtual void output(JsonPimpl*) const = 0;
0449
0450
0451 virtual char const* type() const = 0;
0452 };
0453
0454
0455
0456
0457
0458 #if defined(__CUDA_ARCH__) && defined(NDEBUG)
0459
0460 inline __attribute__((noinline)) __host__ __device__ void device_debug_error(
0461 DebugErrorType, char const* condition, char const* file, int line)
0462 {
0463 printf("%s:%u:\nceleritas: internal assertion failed: %s\n",
0464 file,
0465 line,
0466 condition);
0467 __trap();
0468 }
0469 #elif defined(__HIP__)
0470
0471 inline __host__ void device_debug_error(DebugErrorType which,
0472 char const* condition,
0473 char const* file,
0474 int line)
0475 {
0476 throw DebugError({which, condition, file, line});
0477 }
0478
0479
0480
0481 inline __attribute__((noinline)) __device__ void device_debug_error(
0482 DebugErrorType, char const* condition, char const* file, int line)
0483 {
0484 printf("%s:%u:\nceleritas: internal assertion failed: %s\n",
0485 file,
0486 line,
0487 condition);
0488 abort();
0489 }
0490 #endif
0491
0492
0493 }