From: whitequark Date: Wed, 2 Dec 2020 19:41:00 +0000 (+0000) Subject: cxxrtl: use CXXRTL_ASSERT for RTL contract violations instead of assert. X-Git-Tag: working-ls180~175^2 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=aa0a15a42cf7513697b3d93457a69ecf2d8b9e05;p=yosys.git cxxrtl: use CXXRTL_ASSERT for RTL contract violations instead of assert. RTL contract violations and C++ contract violations are different: the former depend on the netlist and will never violate memory safety whereas the latter may. When loading a CXXRTL simulation into another process, RTL contract violations should generally not crash it, while C++ contract violations should. --- diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h index 41089a153..7d3a8485c 100644 --- a/backends/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/cxxrtl.h @@ -53,6 +53,20 @@ #define CXXRTL_ALWAYS_INLINE inline #endif +// CXXRTL uses assert() to check for C++ contract violations (which may result in e.g. undefined behavior +// of the simulation code itself), and CXXRTL_ASSERT to check for RTL contract violations (which may at +// most result in undefined simulation results). +// +// Though by default, CXXRTL_ASSERT() expands to assert(), it may be overridden e.g. when integrating +// the simulation into another process that should survive violating RTL contracts. +#ifndef CXXRTL_ASSERT +#ifndef CXXRTL_NDEBUG +#define CXXRTL_ASSERT(x) assert(x) +#else +#define CXXRTL_ASSERT(x) +#endif +#endif + namespace cxxrtl { // All arbitrary-width values in CXXRTL are backed by arrays of unsigned integers called chunks. The chunk size diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index a48ea5b23..23ea57b5a 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -1154,7 +1154,7 @@ struct CxxrtlWorker { // larger program) will never crash the code that calls into it. // // If assertions are disabled, out of bounds reads are defined to return zero. - f << indent << "assert(" << valid_index_temp << ".valid && \"out of bounds read\");\n"; + f << indent << "CXXRTL_ASSERT(" << valid_index_temp << ".valid && \"out of bounds read\");\n"; f << indent << "if(" << valid_index_temp << ".valid) {\n"; inc_indent(); if (writable_memories[memory]) { @@ -1211,7 +1211,7 @@ struct CxxrtlWorker { // See above for rationale of having both the assert and the condition. // // If assertions are disabled, out of bounds writes are defined to do nothing. - f << indent << "assert(" << valid_index_temp << ".valid && \"out of bounds write\");\n"; + f << indent << "CXXRTL_ASSERT(" << valid_index_temp << ".valid && \"out of bounds write\");\n"; f << indent << "if (" << valid_index_temp << ".valid) {\n"; inc_indent(); f << indent << mangle(memory) << ".update(" << valid_index_temp << ".index, ";