diff --git a/kernel/constids.inc b/kernel/constids.inc index 4fdbb3dc8..df7b75269 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -284,3 +284,4 @@ X(A_WIDTHS) X(B_WIDTHS) X(C_WIDTHS) X(C_SIGNED) +X(raise_error) diff --git a/passes/tests/Makefile.inc b/passes/tests/Makefile.inc index 531943d78..25e11967c 100644 --- a/passes/tests/Makefile.inc +++ b/passes/tests/Makefile.inc @@ -2,4 +2,5 @@ OBJS += passes/tests/test_autotb.o OBJS += passes/tests/test_cell.o OBJS += passes/tests/test_abcloop.o +OBJS += passes/tests/raise_error.o diff --git a/passes/tests/raise_error.cc b/passes/tests/raise_error.cc new file mode 100644 index 000000000..edc42de65 --- /dev/null +++ b/passes/tests/raise_error.cc @@ -0,0 +1,61 @@ +#include "kernel/yosys.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct RaiseErrorPass : public Pass { + RaiseErrorPass() : Pass("raise_error", "raise errors from attributes") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" raise_error [selection]\n"); + log("\n"); + log("Test error handling by raising arbitrary errors. This pass iterates over the\n"); + log("design (or selection of it) checking for objects with the 'raise_error'\n"); + log("attribute set.\n"); + log("\n"); + } + void execute(vector args, RTLIL::Design *design) override + { + log_header(design, "Executing RAISE_ERROR pass.\n"); + + extra_args(args, 1, design, true); + + RTLIL::NamedObject *err_obj = nullptr; + + for (auto mod : design->all_selected_modules()) { + if (mod->has_attribute(ID::raise_error)) { + err_obj = mod->clone(); + break; + } + for (auto memb : mod->selected_members()) { + if (memb->has_attribute(ID::raise_error)) { + err_obj = memb; + break; + } + } + if (err_obj != nullptr) break; + } + + if (err_obj != nullptr) { + log("Raising error from '%s'.\n", log_id(err_obj)); + auto err_no = err_obj->attributes[ID::raise_error].as_int(); + if (err_no < 256) { + log_flush(); + #if defined(_MSC_VER) + _exit(err_no); + #else + _Exit(err_no); + #endif + } else { + auto err_msg = err_obj->get_string_attribute(ID::raise_error); + log_error("%s\n", err_msg.c_str()); + } + } else { + log("'raise_error' attribute not found\n"); + } + } +} RaiseErrorPass; + +PRIVATE_NAMESPACE_END diff --git a/tests/bugpoint/.gitignore b/tests/bugpoint/.gitignore new file mode 100644 index 000000000..072ed1097 --- /dev/null +++ b/tests/bugpoint/.gitignore @@ -0,0 +1,2 @@ +*.il +*.log \ No newline at end of file diff --git a/tests/bugpoint/err.ys b/tests/bugpoint/err.ys new file mode 100644 index 000000000..d6a152144 --- /dev/null +++ b/tests/bugpoint/err.ys @@ -0,0 +1,27 @@ +read_verilog -noblackbox << EOF +(* raise_error=7 *) +module top(); +endmodule + +(* raise_error="help me" *) +module other(); +endmodule + +module zzy(); +endmodule +EOF +select -assert-mod-count 3 =* +design -stash read + +# raise_error with int exits with status +design -load read +bugpoint -yosys ../../yosys -command raise_error -expect-return 7 +select -assert-mod-count 1 =* +select -assert-mod-count 1 top + +# raise_error with string prints message +design -load read +rename top abc +bugpoint -yosys ../../yosys -command raise_error -grep "help me" +select -assert-mod-count 1 =* +select -assert-mod-count 1 other