diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc index b15e91edb..af7e1bca6 100644 --- a/passes/cmds/Makefile.inc +++ b/passes/cmds/Makefile.inc @@ -54,3 +54,4 @@ OBJS += passes/cmds/portarcs.o OBJS += passes/cmds/wrapcell.o OBJS += passes/cmds/setenv.o OBJS += passes/cmds/abstract.o +OBJS += passes/cmds/test_select.o diff --git a/passes/cmds/test_select.cc b/passes/cmds/test_select.cc new file mode 100644 index 000000000..0076500ce --- /dev/null +++ b/passes/cmds/test_select.cc @@ -0,0 +1,172 @@ +#include "kernel/yosys.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct TestSelectPass : public Pass { + TestSelectPass() : Pass("test_select", "call internal selection methods on design for testing purposes") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" test_select [options]\n"); + log("\n"); + log("Test semantics of internal 'RTLIL::Design::selected_modules()' by modifying the\n"); + log("current selection to only include the results of the call.\n"); + log("\n"); + log("Includes partially selected modules by default, use one of the following options\n"); + log("to remove them instead:\n"); + log("\n"); + log(" -whole_only\n"); + log("\n"); + log(" -whole_warn\n"); + log(" -whole_err\n"); + log(" -whole_cmderr\n"); + log(" remove partially selected modules, raising warning, error, or cmd error\n"); + log("\n"); + log(" test_select -unboxed_only [options]\n"); + log("\n"); + log("Remove boxed modules from selection.\n"); + log("\n"); + log(" -include_wb\n"); + log(" don't remove white boxes from selection\n"); + log("\n"); + log(" -warn_boxes\n"); + log(" -err_boxes\n"); + log(" -cmderr_boxes\n"); + log(" raise warning, error, or cmd error if a box is removed\n"); + log("\n"); + } + void execute(vector args, RTLIL::Design *design) override + { + log_header(design, "Executing TEST_SELECTION pass.\n"); + bool whole_only = false; + bool whole_warn = false; + bool whole_err = false; + bool whole_cmderr = false; + int whole_opts = 0; + + bool warn_boxes = false; + bool err_boxes = false; + bool cmderr_boxes = false; + int box_level = 0; + + bool unboxed_only = false; + bool include_wb = false; + + int argidx; + for (argidx = 1; argidx < GetSize(args); argidx++) + { + if (args[argidx] == "-whole_only") { + whole_only = true; + whole_opts++; + continue; + } + if (args[argidx] == "-whole_warn") { + whole_warn = true; + whole_opts++; + continue; + } + if (args[argidx] == "-whole_err") { + whole_err = true; + whole_opts++; + continue; + } + if (args[argidx] == "-whole_cmderr") { + whole_cmderr = true; + whole_opts++; + continue; + } + if (args[argidx] == "-warn_boxes") { + warn_boxes = true; + box_level++; + continue; + } + if (args[argidx] == "-err_boxes") { + err_boxes = true; + box_level++; + continue; + } + if (args[argidx] == "-cmderr_boxes") { + cmderr_boxes = true; + box_level++; + continue; + } + if (args[argidx] == "-unboxed_only") { + unboxed_only = true; + continue; + } + if (args[argidx] == "-include_wb") { + include_wb = true; + continue; + } + break; + } + + if (whole_opts > 1) + log_cmd_error("Only one of -whole_only, -whole_warn, -whole_err, or -whole_cmderr may be selected.\n"); + + if (include_wb && !unboxed_only) + log_cmd_error("-include_wb option requires -unboxed_only.\n"); + + if (box_level > 0 && !unboxed_only) + log_cmd_error("-*_boxes options require -unboxed_only.\n"); + + if (box_level > 1) + log_cmd_error("Only one of -warn_boxes, -err_boxes, or -cmderr_boxes may be selected.\n"); + + extra_args(args, argidx, design, false); + + // construct enums + RTLIL::SelectPartials partials; + if (whole_only) + partials = RTLIL::SELECT_WHOLE_ONLY; + else if (whole_warn) + partials = RTLIL::SELECT_WHOLE_WARN; + else if (whole_err) + partials = RTLIL::SELECT_WHOLE_ERR; + else if (whole_cmderr) + partials = RTLIL::SELECT_WHOLE_CMDERR; + else + partials = RTLIL::SELECT_ALL; + + char boxes = RTLIL::SB_ALL; + if (warn_boxes) boxes |= RTLIL::SB_WARN; + if (err_boxes) boxes |= RTLIL::SB_ERR; + if (cmderr_boxes) boxes |= RTLIL::SB_CMDERR; + if (unboxed_only) boxes |= RTLIL::SB_UNBOXED_ONLY; + if (include_wb) boxes |= RTLIL::SB_INCL_WB; + + // get sub selection and store the results + auto sub_sel = design->selected_modules(partials, (RTLIL::SelectBoxes)boxes); + pool selected_modules; + dict> selected_members; + + for (auto *mod : sub_sel) { + if (mod->is_selected_whole()) { + log_debug(" Adding %s.\n", id2cstr(mod->name)); + selected_modules.insert(mod->name); + } else for (auto *memb : mod->selected_members()) { + log_debug(" Adding %s.%s.\n", id2cstr(mod->name), id2cstr(memb->name)); + selected_members[mod->name].insert(memb); + } + } + + // fully reset current selection + design->selection() = RTLIL::Selection::EmptySelection(design); + + // add back sub selection + for (auto modname : selected_modules) + design->selection().select(design->module(modname)); + for (auto &it : selected_members) { + auto mod = design->module(it.first); + for (auto memb : it.second) + design->selection().select(mod, memb); + } + + // optimize + design->selection().optimize(design); + } +} TestSelectPass; + +PRIVATE_NAMESPACE_END diff --git a/tests/select/internal_selects.ys b/tests/select/internal_selects.ys new file mode 100644 index 000000000..67b7cf63f --- /dev/null +++ b/tests/select/internal_selects.ys @@ -0,0 +1,165 @@ +read_verilog boxes.v + +## base case, no warnings ## +logger -expect-no-warnings + +select =* +select -assert-count 13 % +select -assert-mod-count 3 % +test_select # SELECT_ALL && SB_ALL +select -assert-count 13 % +select -assert-mod-count 3 % + +select =* +select -assert-mod-count 3 % +test_select -whole_only # SELECT_WHOLE_ONLY +select -assert-mod-count 3 % + +select =* +select -assert-count 13 % +test_select -unboxed_only -include_wb # SB_EXCL_BB_ONLY +select -assert-count 10 % + +select =* +select -assert-count 13 % +test_select -unboxed_only # SB_UNBOXED_ONLY +select -assert-count 5 % + +logger -check-expected + +## don't add to selection ## +select * +select -assert-count 5 % +select -assert-mod-count 1 % +test_select # SELECT_ALL && SB_ALL +select -assert-count 5 % +select -assert-mod-count 1 % + +select =wb/a %n +select -assert-mod-count 3 % +test_select -whole_only # SELECT_WHOLE_ONLY +select -assert-mod-count 2 % + +select =w:* +select -assert-mod-count 3 % +test_select -whole_only # SELECT_WHOLE_ONLY +select -assert-mod-count 1 % + +select =w:* +select -assert-mod-count 3 % +test_select -whole_only -unboxed_only # SELECT_WHOLE_ONLY && SB_UNBOXED_ONLY +select -assert-none % + +select =w:* %n +select -assert-mod-count 2 % +test_select -whole_only # SELECT_WHOLE_ONLY +select -assert-none % + +select =?b +select -assert-count 8 % +test_select -unboxed_only -include_wb # SB_EXCL_BB_ONLY +select -assert-count 5 % + +select =?b +select -assert-count 8 % +test_select -unboxed_only # SB_UNBOXED_ONLY +select -assert-none % + +select =wb %n +select -assert-count 8 % +test_select -unboxed_only -include_wb # SB_EXCL_BB_ONLY +select -assert-count 5 % + +select =top/a %n +select -assert-count 12 % +select -assert-mod-count 3 % +test_select -whole_only -unboxed_only -include_wb # SELECT_WHOLE_ONLY && SB_EXCL_BB_ONLY +select -assert-count 5 % +select -assert-mod-count 1 % + +## warnings work ## +logger -expect warning "Ignoring blackbox module bb." 1 +select =* +test_select -unboxed_only -include_wb -warn_boxes # SB_EXCL_BB_WARN +logger -check-expected + +logger -expect warning "Ignoring boxed module .b." 2 +select =* +test_select -unboxed_only -warn_boxes # SB_UNBOXED_WARN +logger -check-expected + +logger -expect warning "Ignoring partially selected module [wb|top]." 2 +select =w:* +test_select -whole_warn # SELECT_WHOLE_WARN +logger -check-expected + +logger -expect warning "Ignoring partially selected module [wb|top]." 2 +logger -expect warning "Ignoring blackbox module bb." 1 +select =w:* +test_select -whole_warn -unboxed_only -include_wb -warn_boxes # SELECT_WHOLE_WARN && SB_EXCL_BB_WARN +logger -check-expected + +logger -expect warning "Ignoring partially selected module [wb|top]." 2 +logger -expect warning "Ignoring boxed module bb." 1 +select =w:* +test_select -whole_warn -unboxed_only -warn_boxes # SELECT_WHOLE_WARN && SB_UNBOXED_WARN +logger -check-expected + +## partials warn before boxes ## +logger -expect warning "Ignoring partially selected module wb." 1 +select =wb/a +test_select -whole_warn -unboxed_only -warn_boxes # SELECT_WHOLE_WARN && SB_UNBOXED_WARN +logger -check-expected + +## boxes won't warn if they've been removed because of partial selection ## +logger -expect-no-warnings +select =wb/a +test_select -whole_only -unboxed_only -warn_boxes # SELECT_WHOLE_ONLY && SB_UNBOXED_WARN +logger -check-expected + +## boxes still warn if they're not partially selected +logger -expect warning "Ignoring boxed module wb." 1 +select =bb %n +test_select -whole_only -unboxed_only -warn_boxes # SELECT_WHOLE_ONLY && SB_UNBOXED_WARN +logger -check-expected + +## don't warn if it's not selected ## +logger -expect-no-warnings +select =bb %n +test_select -unboxed_only -include_wb -warn_boxes # SB_EXCL_BB_WARN +logger -check-expected + +logger -expect-no-warnings +select * +test_select -unboxed_only -warn_boxes # SB_UNBOXED_WARN +logger -check-expected + +logger -expect warning "Ignoring boxed module bb." 1 +select =wb %n +test_select -unboxed_only -warn_boxes # SB_UNBOXED_WARN +logger -check-expected + +## don't error if it's not selected ## +logger -expect-no-warnings + +select =bb %n +test_select -unboxed_only -include_wb -err_boxes # SB_EXCL_BB_ERR + +select =bb %n +test_select -unboxed_only -include_wb -cmderr_boxes # SB_EXCL_BB_CMDERR + +select * +test_select -unboxed_only -err_boxes # SB_UNBOXED_ERR + +select * +test_select -unboxed_only -cmderr_boxes # SB_UNBOXED_CMDERR + +select * +test_select -whole_err # SELECT_WHOLE_ERR + +select * +test_select -whole_cmderr # SELECT_WHOLE_CMDERR + +logger -check-expected + +##