diff --git a/Makefile b/Makefile index d68fdfdad..7fd7516e0 100644 --- a/Makefile +++ b/Makefile @@ -886,6 +886,7 @@ MK_TEST_DIRS += tests/arch/xilinx MK_TEST_DIRS += tests/bugpoint MK_TEST_DIRS += tests/opt MK_TEST_DIRS += tests/sat +MK_TEST_DIRS += tests/scripts MK_TEST_DIRS += tests/sim MK_TEST_DIRS += tests/svtypes MK_TEST_DIRS += tests/techmap diff --git a/examples/smtbmc/glift/mux2.ys b/examples/smtbmc/glift/mux2.ys index a8e99912b..e844e96e3 100644 --- a/examples/smtbmc/glift/mux2.ys +++ b/examples/smtbmc/glift/mux2.ys @@ -1,9 +1,9 @@ logger -expect log "SAT proof finished - no model found: SUCCESS!" 1 -logger -expect log "Number of cells:.*[\t ]12" 1 -logger -expect log "Number of cells:.*[\t ]20" 1 -logger -expect log "Problem is satisfiable with \\gate.__glift_weight = 11." 1 -logger -expect log "Problem is NOT satisfiable with \\gate.__glift_weight <= 10." 1 -logger -expect log "Wire \\gate.__glift_weight is minimized at 11." 1 +logger -expect log 'Number of cells:.*[\t ]12' 1 +logger -expect log 'Number of cells:.*[\t ]20' 1 +logger -expect log 'Problem is satisfiable with \\gate.__glift_weight = 11.' 1 +logger -expect log 'Problem is NOT satisfiable with \\gate.__glift_weight <= 10.' 1 +logger -expect log 'Wire \\gate.__glift_weight is minimized at 11.' 1 logger -expect log "Specializing .* from file with .* = 1." 2 logger -expect log "Specializing .* from file with .* = 0." 4 read_verilog < #include +#include #if !defined(WIN32) #include @@ -37,15 +38,16 @@ std::string next_token(std::string &text, const char *sep, bool long_strings) if (pos_begin == std::string::npos) pos_begin = text.size(); - if (long_strings && pos_begin != text.size() && text[pos_begin] == '"') { + if (long_strings && pos_begin != text.size() && (text[pos_begin] == '"' || text[pos_begin] == '\'')) { std::string sep_string = sep; for (size_t i = pos_begin+1; i < text.size(); i++) { - if (text[i] == '"' && (i+1 == text.size() || sep_string.find(text[i+1]) != std::string::npos)) { + bool close_quote = (text[i] == text[pos_begin]) && (text[i-1] != '\\' || text[pos_begin] == '\''); + if (close_quote && (i+1 == text.size() || sep_string.find(text[i+1]) != std::string::npos)) { std::string token = text.substr(pos_begin, i-pos_begin+1); text = text.substr(i+1); return token; } - if (i+1 < text.size() && text[i] == '"' && text[i+1] == ';' && (i+2 == text.size() || sep_string.find(text[i+2]) != std::string::npos)) { + if (i+1 < text.size() && close_quote && text[i+1] == ';' && (i+2 == text.size() || sep_string.find(text[i+2]) != std::string::npos)) { std::string token = text.substr(pos_begin, i-pos_begin+1); text = text.substr(i+2); return token + ";"; @@ -592,4 +594,34 @@ void format_emit_void_ptr(std::string &result, std::string_view spec, int *dynam format_emit_stringf(result, spec, dynamic_ints, num_dynamic_ints, arg); } +bool needs_quote(const std::string &s) { + for (auto c : {' ', '\\', '#', ';', '"', '\''}) { + if (s.find(c) != std::string::npos) return true; + } + return false; +} + +std::string quote(const std::string &s) { + std::ostringstream ss; + if (s.find('\'') != std::string::npos) + ss << std::quoted(s); + else + ss << '\'' << s << '\''; + return ss.str(); +} + +std::string unquote(const std::string &s) { + if (s.length() >= 2) { + if (s.front() == '\'' && s.back() == '\'') + return s.substr(1, s.length()-2); + else if (s.front() == '"' && s.back() == '"') { + std::string result; + std::istringstream ss(s); + ss >> std::quoted(result); + return result; + } + } + return s; +} + YOSYS_NAMESPACE_END diff --git a/kernel/io.h b/kernel/io.h index 2ad0a6466..64caae078 100644 --- a/kernel/io.h +++ b/kernel/io.h @@ -470,6 +470,10 @@ void remove_directory(std::string dirname); bool create_directory(const std::string& dirname); std::string escape_filename_spaces(const std::string& filename); +bool needs_quote(const std::string &s); +std::string quote(const std::string &s); +std::string unquote(const std::string &s); + YOSYS_NAMESPACE_END #endif // YOSYS_IO_H diff --git a/kernel/register.cc b/kernel/register.cc index bd12dcc38..a255c4805 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -222,7 +222,7 @@ void Pass::call(RTLIL::Design *design, std::string command) while (!tok.empty() && tok.back() == ';') tok.resize(tok.size()-1), num_semikolon++; if (!tok.empty()) - args.push_back(tok); + args.push_back(unquote(tok)); call(design, args); args.clear(); if (num_semikolon == 2) @@ -230,7 +230,7 @@ void Pass::call(RTLIL::Design *design, std::string command) if (num_semikolon == 3) call(design, "clean -purge"); } else - args.push_back(tok); + args.push_back(unquote(tok)); bool found_nl = false; for (auto c : cmd_buf) { if (c == ' ' || c == '\t') @@ -256,8 +256,10 @@ void Pass::call(RTLIL::Design *design, std::vector args) if (echo_mode) { log("%s", create_prompt(design, 0)); - for (size_t i = 0; i < args.size(); i++) - log("%s%s", i ? " " : "", args[i]); + for (size_t i = 0; i < args.size(); i++) { + auto maybe_quoted = needs_quote(args[i]) ? quote(args[i]) : args[i]; + log("%s%s", i ? " " : "", maybe_quoted); + } log("\n"); } diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc index 897dd8459..9df254513 100644 --- a/passes/cmds/bugpoint.cc +++ b/passes/cmds/bugpoint.cc @@ -149,9 +149,6 @@ struct BugpointPass : public Pass { if (grep.empty()) return true; - if (grep.size() > 2 && grep.front() == '"' && grep.back() == '"') - grep = grep.substr(1, grep.size() - 2); - string bugpoint_file = "bugpoint-case"; if (suffix.size()) bugpoint_file += stringf(".%.8s", suffix); @@ -471,13 +468,13 @@ struct BugpointPass : public Pass { if (args[argidx] == "-script" && argidx + 1 < args.size()) { if (!yosys_arg.empty()) log_cmd_error("A -script or -command option can be only provided once!\n"); - yosys_arg = stringf("-s %s", args[++argidx]); + yosys_arg = stringf("-s %s", quote(args[++argidx])); continue; } if (args[argidx] == "-command" && argidx + 1 < args.size()) { if (!yosys_arg.empty()) log_cmd_error("A -script or -command option can be only provided once!\n"); - yosys_arg = stringf("-p %s", args[++argidx]); + yosys_arg = stringf("-p %s", quote(args[++argidx])); continue; } if (args[argidx] == "-grep" && argidx + 1 < args.size()) { @@ -550,18 +547,10 @@ struct BugpointPass : public Pass { } if (args[argidx] == "-runner" && argidx + 1 < args.size()) { runner = args[++argidx]; - if (runner.size() && runner.at(0) == '"') { - log_assert(runner.back() == '"'); - runner = runner.substr(1, runner.size() - 2); - } continue; } if (args[argidx] == "-suffix" && argidx + 1 < args.size()) { suffix = args[++argidx]; - if (suffix.size() && suffix.at(0) == '"') { - log_assert(suffix.back() == '"'); - suffix = suffix.substr(1, suffix.size() - 2); - } continue; } break; diff --git a/passes/cmds/logger.cc b/passes/cmds/logger.cc index cab4ab81c..1e3f5e821 100644 --- a/passes/cmds/logger.cc +++ b/passes/cmds/logger.cc @@ -106,7 +106,6 @@ struct LoggerPass : public Pass { } if (args[argidx] == "-warn" && argidx+1 < args.size()) { std::string pattern = args[++argidx]; - if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); try { log("Added regex '%s' for warnings to warn list.\n", pattern); log_warn_regexes.push_back(YS_REGEX_COMPILE(pattern)); @@ -118,7 +117,6 @@ struct LoggerPass : public Pass { } if (args[argidx] == "-nowarn" && argidx+1 < args.size()) { std::string pattern = args[++argidx]; - if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); try { log("Added regex '%s' for warnings to nowarn list.\n", pattern); log_nowarn_regexes.push_back(YS_REGEX_COMPILE(pattern)); @@ -130,7 +128,6 @@ struct LoggerPass : public Pass { } if (args[argidx] == "-werror" && argidx+1 < args.size()) { std::string pattern = args[++argidx]; - if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); try { log("Added regex '%s' for warnings to werror list.\n", pattern); log_werror_regexes.push_back(YS_REGEX_COMPILE(pattern)); @@ -164,7 +161,6 @@ struct LoggerPass : public Pass { if ((type=="error" || type=="prefix-error") && log_expect_error.size()>0) log_cmd_error("Only single error message can be expected !\n"); std::string pattern = args[++argidx]; - if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); int count = atoi(args[++argidx].c_str()); if (count<=0) log_cmd_error("Number of expected messages must be higher then 0 !\n"); diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc index f64ce943c..671e1382b 100644 --- a/passes/cmds/scratchpad.cc +++ b/passes/cmds/scratchpad.cc @@ -89,7 +89,6 @@ struct ScratchpadPass : public Pass { if (RTLIL::constpad.count(identifier)) log_error("scratchpad entry \"%s\" is a global constant\n", identifier); string value = args[++argidx]; - if (value.front() == '\"' && value.back() == '\"') value = value.substr(1, value.size() - 2); design->scratchpad_set_string(identifier, value); continue; } @@ -116,7 +115,6 @@ struct ScratchpadPass : public Pass { if (args[argidx] == "-assert" && argidx+2 < args.size()) { string identifier = args[++argidx]; string expected = args[++argidx]; - if (expected.front() == '\"' && expected.back() == '\"') expected = expected.substr(1, expected.size() - 2); if (design->scratchpad.count(identifier) == 0) log_error("scratchpad entry '%s' is not defined\n", identifier); string value = design->scratchpad_get_string(identifier); diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc index 25d8fd34c..85105bed8 100644 --- a/passes/cmds/setattr.cc +++ b/passes/cmds/setattr.cc @@ -32,10 +32,10 @@ struct setunset_t setunset_t(std::string unset_name) : name(RTLIL::escape_id(unset_name)), value(), unset(true) { } - setunset_t(std::string set_name, std::string set_value) : name(RTLIL::escape_id(set_name)), value(), unset(false) + setunset_t(std::string set_name, std::string set_value, bool is_str) : name(RTLIL::escape_id(set_name)), value(), unset(false) { - if (set_value.compare(0, 1, "\"") == 0 && set_value.compare(GetSize(set_value)-1, std::string::npos, "\"") == 0) { - value = RTLIL::Const(set_value.substr(1, GetSize(set_value)-2)); + if (is_str) { + value = RTLIL::Const(set_value); } else { RTLIL::SigSpec sig_value; if (!RTLIL::SigSpec::parse(sig_value, nullptr, set_value)) @@ -60,13 +60,22 @@ struct SetattrPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" setattr [ -mod ] [ -set name value | -unset name ]... [selection]\n"); + log(" setattr [options] [selection]\n"); log("\n"); - log("Set/unset the given attributes on the selected objects. String values must be\n"); - log("passed in double quotes (\").\n"); + log("Set/unset attributes on the selected objects.\n"); log("\n"); - log("When called with -mod, this command will set and unset attributes on modules\n"); - log("instead of objects within modules.\n"); + log(" -mod\n"); + log(" apply changes to modules instead of objects within modules\n"); + log("\n"); + log(" -set \n"); + log(" -setstr \n"); + log(" set the named attribute to the given value, string values must use\n"); + log(" the -setstr option\n"); + log("\n"); + log(" -unset \n"); + log(" unset the named attribute\n"); + log("\n"); + log("The options -setstr, -set, and -unset can be specified multiple times.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) override @@ -78,10 +87,10 @@ struct SetattrPass : public Pass { for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; - if (arg == "-set" && argidx+2 < args.size()) { + if ((arg == "-set" || arg == "-setstr") && argidx+2 < args.size()) { string set_key = args[++argidx]; string set_val = args[++argidx]; - setunset_list.push_back(setunset_t(set_key, set_val)); + setunset_list.push_back(setunset_t(set_key, set_val, arg == "-setstr")); continue; } if (arg == "-unset" && argidx+1 < args.size()) { @@ -147,12 +156,22 @@ struct SetparamPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" setparam [ -type cell_type ] [ -set name value | -unset name ]... [selection]\n"); + log(" setparam [options] [selection]\n"); log("\n"); - log("Set/unset the given parameters on the selected cells. String values must be\n"); - log("passed in double quotes (\").\n"); + log("Set/unset parameters on the selected cells.\n"); log("\n"); - log("The -type option can be used to change the cell type of the selected cells.\n"); + log(" -type\n"); + log(" change the cell type of the selected cells\n"); + log("\n"); + log(" -set \n"); + log(" -setstr \n"); + log(" set the named parameter to the given value, string values must use\n"); + log(" the -setstr option\n"); + log("\n"); + log(" -unset \n"); + log(" unset the named parameter\n"); + log("\n"); + log("The options -setstr, -set, and -unset can be specified multiple times.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) override @@ -164,10 +183,10 @@ struct SetparamPass : public Pass { for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; - if (arg == "-set" && argidx+2 < args.size()) { + if ((arg == "-set" || arg == "-setstr") && argidx+2 < args.size()) { string set_key = args[++argidx]; string set_val = args[++argidx]; - setunset_list.push_back(setunset_t(set_key, set_val)); + setunset_list.push_back(setunset_t(set_key, set_val, arg == "-setstr")); continue; } if (arg == "-unset" && argidx+1 < args.size()) { @@ -199,10 +218,10 @@ struct ChparamPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" chparam [ -set name value ]... [selection]\n"); + log(" chparam [ -set[str] name value ]... [selection]\n"); log("\n"); - log("Re-evaluate the selected modules with new parameters. String values must be\n"); - log("passed in double quotes (\").\n"); + log("Re-evaluate the selected modules with new parameters. String values must use\n"); + log("the -setstr option.\n"); log("\n"); log("\n"); log(" chparam -list [selection]\n"); @@ -220,10 +239,10 @@ struct ChparamPass : public Pass { for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; - if (arg == "-set" && argidx+2 < args.size()) { + if ((arg == "-set" || arg == "-setstr") && argidx+2 < args.size()) { string set_key = args[++argidx]; string set_val = args[++argidx]; - setunset_list.push_back(setunset_t(set_key, set_val)); + setunset_list.push_back(setunset_t(set_key, set_val, arg == "-setstr")); continue; } if (arg == "-list") { diff --git a/passes/cmds/setenv.cc b/passes/cmds/setenv.cc index 90eeab702..39a6c73ca 100644 --- a/passes/cmds/setenv.cc +++ b/passes/cmds/setenv.cc @@ -46,7 +46,6 @@ struct SetenvPass : public Pass { std::string name = args[1]; std::string value = args[2]; - if (value.front() == '\"' && value.back() == '\"') value = value.substr(1, value.size() - 2); #if defined(_WIN32) _putenv_s(name.c_str(), value.c_str()); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 8b61a9299..d1315644e 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -321,7 +321,7 @@ struct Abc9Pass : public ScriptPass // then select all its fanins // then select all fanouts of all that // lastly remove $_DFF_[NP]_ cells - run("setattr -set submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d", " (only if -dff)"); + run("setattr -setstr submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d", " (only if -dff)"); run("submod", " (only if -dff)"); run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop", "(only if -dff)"); if (help_mode) { diff --git a/tests/arch/ecp5/memories.ys b/tests/arch/ecp5/memories.ys index f075182c8..904be565b 100644 --- a/tests/arch/ecp5/memories.ys +++ b/tests/arch/ecp5/memories.ys @@ -19,14 +19,14 @@ select -assert-count 9 t:TRELLIS_DPR16X4 design -reset; read_verilog -defer ../common/blockram.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp hierarchy -top sync_ram_sdp -setattr -set syn_ramstyle "block_ram" m:memory +setattr -setstr syn_ramstyle block_ram m:memory synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp select -assert-count 1 t:DP16KD design -reset; read_verilog -defer ../common/blockram.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp hierarchy -top sync_ram_sdp -setattr -set syn_ramstyle "Block_RAM" m:memory +setattr -setstr syn_ramstyle Block_RAM m:memory synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp select -assert-count 1 t:DP16KD # any case works @@ -41,7 +41,7 @@ select -assert-count 9 t:TRELLIS_DPR16X4 design -reset; read_verilog -defer ../common/blockram.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp hierarchy -top sync_ram_sdp -setattr -set syn_ramstyle "registers" m:memory +setattr -setstr syn_ramstyle registers m:memory synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp select -assert-count 0 t:DP16KD # requested FFRAM explicitly select -assert-count 180 t:TRELLIS_FF @@ -98,14 +98,14 @@ select -assert-count 5 t:TRELLIS_DPR16X4 design -reset; read_verilog -defer ../common/blockram.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp hierarchy -top sync_ram_sdp -setattr -set syn_ramstyle "block_ram" m:memory +setattr -setstr syn_ramstyle block_ram m:memory synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp select -assert-count 1 t:DP16KD design -reset; read_verilog -defer ../common/blockram.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp hierarchy -top sync_ram_sdp -setattr -set syn_ramstyle "Block_RAM" m:memory +setattr -setstr syn_ramstyle Block_RAM m:memory synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp select -assert-count 1 t:DP16KD # any case works @@ -120,7 +120,7 @@ select -assert-count 5 t:TRELLIS_DPR16X4 design -reset; read_verilog -defer ../common/blockram.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp hierarchy -top sync_ram_sdp -setattr -set syn_ramstyle "registers" m:memory +setattr -setstr syn_ramstyle registers m:memory synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp select -assert-count 0 t:DP16KD # requested FFRAM explicitly select -assert-count 90 t:TRELLIS_FF @@ -146,14 +146,14 @@ select -assert-count 1 t:TRELLIS_DPR16X4 design -reset; read_verilog -defer ../common/blockram.v chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp hierarchy -top sync_ram_sdp -setattr -set syn_ramstyle "distributed" m:memory +setattr -setstr syn_ramstyle distributed m:memory synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp select -assert-count 1 t:TRELLIS_DPR16X4 design -reset; read_verilog -defer ../common/blockram.v chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp hierarchy -top sync_ram_sdp -setattr -set syn_ramstyle "registers" m:memory +setattr -setstr syn_ramstyle registers m:memory synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp select -assert-count 0 t:TRELLIS_DPR16X4 # requested FFRAM explicitly select -assert-count 68 t:TRELLIS_FF @@ -187,7 +187,7 @@ select -assert-min 18 t:LUT4 design -reset; read_verilog -defer ../common/blockrom.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom hierarchy -top sync_rom -setattr -set syn_romstyle "ebr" m:memory +setattr -setstr syn_romstyle ebr m:memory synth_ecp5 -top sync_rom; cd sync_rom select -assert-count 1 t:DP16KD @@ -201,7 +201,7 @@ select -assert-count 1 t:DP16KD design -reset; read_verilog -defer ../common/blockrom.v chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom hierarchy -top sync_rom -setattr -set syn_romstyle "logic" m:memory +setattr -setstr syn_romstyle logic m:memory synth_ecp5 -top sync_rom; cd sync_rom select -assert-count 0 t:DP16KD # requested LUTROM explicitly select -assert-min 18 t:LUT4 @@ -234,7 +234,7 @@ select -assert-min 9 t:LUT4 design -reset; read_verilog -defer ../common/blockrom.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom hierarchy -top sync_rom -setattr -set syn_romstyle "ebr" m:memory +setattr -setstr syn_romstyle ebr m:memory synth_ecp5 -top sync_rom; cd sync_rom select -assert-count 1 t:DP16KD @@ -248,7 +248,7 @@ select -assert-count 1 t:DP16KD design -reset; read_verilog -defer ../common/blockrom.v chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom hierarchy -top sync_rom -setattr -set syn_romstyle "logic" m:memory +setattr -setstr syn_romstyle logic m:memory synth_ecp5 -top sync_rom; cd sync_rom select -assert-count 0 t:DP16KD # requested LUTROM explicitly select -assert-min 9 t:LUT4 diff --git a/tests/arch/ice40/memories.ys b/tests/arch/ice40/memories.ys index d480a3abe..c2eb5924d 100644 --- a/tests/arch/ice40/memories.ys +++ b/tests/arch/ice40/memories.ys @@ -37,14 +37,14 @@ select -assert-min 1 t:SB_DFFE design -reset; read_verilog -defer ../common/blockram.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp hierarchy -top sync_ram_sdp -setattr -set syn_ramstyle "block_ram" m:memory +setattr -setstr syn_ramstyle block_ram m:memory synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp select -assert-count 1 t:SB_RAM40_4K design -reset; read_verilog -defer ../common/blockram.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp hierarchy -top sync_ram_sdp -setattr -set syn_ramstyle "Block_RAM" m:memory +setattr -setstr syn_ramstyle Block_RAM m:memory synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp select -assert-count 1 t:SB_RAM40_4K # any case works @@ -58,7 +58,7 @@ select -assert-count 1 t:SB_RAM40_4K design -reset; read_verilog -defer ../common/blockram.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp hierarchy -top sync_ram_sdp -setattr -set syn_ramstyle "registers" m:memory +setattr -setstr syn_ramstyle registers m:memory synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp select -assert-count 0 t:SB_RAM40_4K # requested FFRAM explicitly select -assert-min 1 t:SB_DFFE @@ -110,7 +110,7 @@ select -assert-min 1 t:SB_LUT4 design -reset; read_verilog -defer ../common/blockrom.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom hierarchy -top sync_rom -setattr -set syn_romstyle "ebr" m:memory +setattr -setstr syn_romstyle ebr m:memory synth_ice40 -top sync_rom; cd sync_rom select -assert-count 1 t:SB_RAM40_4K @@ -124,7 +124,7 @@ select -assert-count 1 t:SB_RAM40_4K design -reset; read_verilog -defer ../common/blockrom.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom hierarchy -top sync_rom -setattr -set syn_romstyle "logic" m:memory +setattr -setstr syn_romstyle logic m:memory synth_ice40 -top sync_rom; cd sync_rom select -assert-count 0 t:SB_RAM40_4K # requested LUTROM explicitly select -assert-min 1 t:SB_LUT4 diff --git a/tests/arch/xilinx/abc9_dff.ys b/tests/arch/xilinx/abc9_dff.ys index 9101c6e4d..e0cf327ca 100644 --- a/tests/arch/xilinx/abc9_dff.ys +++ b/tests/arch/xilinx/abc9_dff.ys @@ -1,5 +1,5 @@ -logger -nowarn "Yosys has only limited support for tri-state logic at the moment\. .*" -logger -nowarn "Ignoring boxed module .*\." +logger -nowarn "Yosys has only limited support for tri-state logic at the moment. .*" +logger -nowarn "Ignoring boxed module .*." read_verilog < args, RTLIL::Design*) override { + int argidx; + for (argidx = 0; argidx < GetSize(args); argidx++) + { + log("%s\n", args[argidx]); + } + } +} TestArgsPass; + +struct TestArgsFrontend : public Frontend { + TestArgsFrontend() : Frontend("test_args", "dummy frontend to test arg parsing") { + internal(); + } + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *) override { + int argidx; + log("pass: %s\n", args[0]); + for (argidx = 1; argidx < GetSize(args); argidx++) { + if (args[argidx] == "-arg" && argidx+1 < GetSize(args)) { + log("arg: %s\n", args[++argidx]); + continue; + } + break; + } + extra_args(f, filename, args, argidx); + log("filename: %s\n", filename); + } +} TestArgsFrontend; + +struct TestArgsBackend : public Backend { + TestArgsBackend() : Backend("test_args", "dummy backend to test arg parsing") { + internal(); + } + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *) override { + int argidx; + log("pass: %s\n", args[0]); + for (argidx = 1; argidx < GetSize(args); argidx++) { + if (args[argidx] == "-arg" && argidx+1 < GetSize(args)) { + log("arg: %s\n", args[++argidx]); + continue; + } + break; + } + extra_args(f, filename, args, argidx); + log("filename: %s\n", filename); + } +} TestArgsBackend; + +PRIVATE_NAMESPACE_END diff --git a/tests/scripts/run-test.sh b/tests/scripts/run-test.sh new file mode 100755 index 000000000..70b282a9a --- /dev/null +++ b/tests/scripts/run-test.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -eu +source ../gen-tests-makefile.sh +generate_mk --bash diff --git a/tests/scripts/space_in_name.sh b/tests/scripts/space_in_name.sh new file mode 100755 index 000000000..ba3b97773 --- /dev/null +++ b/tests/scripts/space_in_name.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +set -eu + +yosys="$PWD/../../yosys" + +# these ones are fine because bash handles it +$yosys "file name.ys" +$yosys file\ name.ys + +$yosys "file name.v" -o "file name.out" -b verilog +$yosys file\ name.v -o file\ name.out -b verilog + +# these already have special handling in Yosys thanks to `extra_args` +$yosys -p 'read_verilog "file name.v"' +$yosys -p 'write_verilog "file name.out"' + +# this one works if passes get their arguments unquoted +$yosys -p 'script "file name.ys"' + +# these get split by space and treated as two separate filenames +# $yosys -p script\ "file name.ys" +# $yosys -p script\ file\ name.ys +# $yosys -p read_verilog\ "file name.v" +# $yosys -p read_verilog\ file\ name.v +# $yosys -p write_verilog\ file\ name.out +# $yosys -p write_verilog\ "file name.out" + +# what does test_args say +rm -f plugin.so +CXXFLAGS=$(../../yosys-config --cxxflags) +DATDIR=$(../../yosys-config --datdir) +DATDIR=${DATDIR//\//\\\/} +CXXFLAGS=${CXXFLAGS//$DATDIR/..\/..\/share} +../../yosys-config --exec --cxx ${CXXFLAGS} --ldflags -shared -o plugin.so plugin.cc +yosys_plugin="$yosys -m ./plugin.so" + +$yosys_plugin -p test_args\ "quoted spaces" +$yosys_plugin -p test_args\ escaped\ spaces +$yosys_plugin -p test_args\ \"escaped\ quotes\" +$yosys_plugin -p 'test_args "inner quotes"' +$yosys_plugin -p 'test_args "inner \"escaped quotes\""' + +$yosys_plugin -p 'read_test_args "file name.v" "file name.ys"' +$yosys_plugin -p 'write_test_args "file name.out"' + +# and as a script +$yosys_plugin space_in_name.ys diff --git a/tests/scripts/space_in_name.ys b/tests/scripts/space_in_name.ys new file mode 100755 index 000000000..18a715a5b --- /dev/null +++ b/tests/scripts/space_in_name.ys @@ -0,0 +1,105 @@ +logger -expect-no-warnings + +# quoted strings are a single argument to passes +logger -expect log "quoted space" 1 +logger -expect log "quoted" 2 +logger -expect log "space" 2 +logger -expect log '"escaped' 2 +logger -expect log 'quotes"' 2 + +test_args unquoted space +test_args "quoted space" +test_args "\"escaped quotes\"" +test_args '"escaped quotes"' + +logger -check-expected + +# empty strings can be arguments +logger -expect log "a b c" 2 + +log a " " b "" c +log a ' ' b '' c + +logger -check-expected + +# quotes can be arguments +logger -expect log '^"' 2 +logger -expect log "^'" 1 +test_args "'" '"' "\"" +logger -check-expected + +# whitespace (or a lack thereof) shouldn't break things +logger -expect log 'a. .b' 2 +log a" "b +log a' 'b + +logger -expect log '.a.b c' 2 +log "a"b c +log 'a'b c + +logger -check-expected + +# numeric literals don't need quotes (unless they include a space) +logger -expect log "1'd2" 1 +logger -expect log "3'b 011" 1 + +test_args 1'd2 +test_args "3'b 011" + +logger -check-expected + +# sidenote that apparently logger regexp ends with '\n$', but \n in the pattern is rejected +logger -expect log "^('|\").$" 2 +log " +log ' + +logger -check-expected + +# bonus test +test_args -opt "some value here" -b "some other \"escaped value\"" + +# special characters can appear in strings +logger -expect log "#no comment" 2 +logger -expect log ";" 1 +logger -warn "a comment" + +log "this is #no comment" +log this is #a comment +log "semicolon; "; log "#no comment" + +logger -check-expected + +# special characters are quoted in echo +logger -expect log "'#'" 1 +logger -expect log "';'" 1 +logger -expect log "' '" 1 +logger -expect log "\"'\"" 1 +logger -expect log "'\"'" 1 +logger -expect log '.\\.' 1 + +echo on +log '#' +log ';' +log ' ' +log "'" +log '"' +log '\' +echo off + +logger -check-expected + +# should this be a backslash or an escaped space? +log escaped\ space? + +# frontend/backend args also work as expected +logger -expect log "arg: inner \"escaped quotes\"" 3 +logger -expect log 'filename: file name\..{1,3}' 3 +logger -expect log "filename: " 1 +logger -expect log "arg: no_quotes" 2 + +read_test_args -arg "inner \"escaped quotes\"" "file name.v" "file name.ys" +write_test_args -arg "inner \"escaped quotes\"" "file name.out" +read_test_args -arg no_quotes plugin.cc +write_test_args -arg no_quotes + +logger -check-expected diff --git a/tests/select/boxes_import.ys b/tests/select/boxes_import.ys index d5b414e05..3d51d7cbd 100644 --- a/tests/select/boxes_import.ys +++ b/tests/select/boxes_import.ys @@ -24,6 +24,6 @@ select -assert-mod-count 2 =* logger -check-expected -logger -expect warning "Selection .wb. did not match any module\." 1 -logger -expect error "No top module found in source design\." 1 +logger -expect warning "Selection .wb. did not match any module." 1 +logger -expect error "No top module found in source design." 1 design -import read -as new_wb wb diff --git a/tests/select/unset.ys b/tests/select/unset.ys index 4f60781c2..8cde23a8c 100644 --- a/tests/select/unset.ys +++ b/tests/select/unset.ys @@ -6,5 +6,5 @@ EOT select -set foo w:* select -assert-any @foo select -unset foo -logger -expect error "Selection '\\foo' does not exist!" 1 +logger -expect error 'Selection .\\foo. does not exist!' 1 select -unset foo diff --git a/tests/svtypes/typedef_initial_and_assign.ys b/tests/svtypes/typedef_initial_and_assign.ys index 4563ca491..00f531ad4 100644 --- a/tests/svtypes/typedef_initial_and_assign.ys +++ b/tests/svtypes/typedef_initial_and_assign.ys @@ -1,12 +1,12 @@ logger -expect-no-warnings -logger -expect warning "reg '\\var_12' is assigned in a continuous assignment" 1 -logger -expect warning "reg '\\var_13' is assigned in a continuous assignment" 1 -logger -expect warning "reg '\\var_14' is assigned in a continuous assignment" 1 -logger -expect warning "reg '\\var_15' is assigned in a continuous assignment" 1 -logger -expect warning "reg '\\var_16' is assigned in a continuous assignment" 1 -logger -expect warning "reg '\\var_17' is assigned in a continuous assignment" 1 -logger -expect warning "reg '\\var_18' is assigned in a continuous assignment" 1 -logger -expect warning "reg '\\var_19' is assigned in a continuous assignment" 1 +logger -expect warning 'reg .\\var_12. is assigned in a continuous assignment' 1 +logger -expect warning 'reg .\\var_13. is assigned in a continuous assignment' 1 +logger -expect warning 'reg .\\var_14. is assigned in a continuous assignment' 1 +logger -expect warning 'reg .\\var_15. is assigned in a continuous assignment' 1 +logger -expect warning 'reg .\\var_16. is assigned in a continuous assignment' 1 +logger -expect warning 'reg .\\var_17. is assigned in a continuous assignment' 1 +logger -expect warning 'reg .\\var_18. is assigned in a continuous assignment' 1 +logger -expect warning 'reg .\\var_19. is assigned in a continuous assignment' 1 read_verilog -sv typedef_initial_and_assign.sv hierarchy; proc; opt; async2sync diff --git a/tests/techmap/clkbufmap.ys b/tests/techmap/clkbufmap.ys index abe830109..8cac96fc7 100644 --- a/tests/techmap/clkbufmap.ys +++ b/tests/techmap/clkbufmap.ys @@ -82,7 +82,7 @@ select -assert-count 0 w:clk2 %a %co t:clkbuf %i design -load ref setattr -set clkbuf_inhibit 1 w:clk1 -setattr -set buffer_type "bufg" w:clk2 +setattr -setstr buffer_type bufg w:clk2 clkbufmap -buf clkbuf o:i w:* a:buffer_type=none a:buffer_type=bufr %u %d select -assert-count 3 top/t:clkbuf select -assert-count 3 sub/t:clkbuf @@ -98,10 +98,10 @@ select -assert-count 1 @clk2 %x:+[o] %co c:s1 %i # And that one fanout is 's0 # ---------------------- design -load ref -setattr -set buffer_type "none" w:clk1 -setattr -set buffer_type "bufr" w:clk2 -setattr -set buffer_type "bufr" w:sclk4 -setattr -set buffer_type "bufr" w:sclk5 +setattr -setstr buffer_type none w:clk1 +setattr -setstr buffer_type bufr w:clk2 +setattr -setstr buffer_type bufr w:sclk4 +setattr -setstr buffer_type bufr w:sclk5 clkbufmap -buf clkbuf o:i w:* a:buffer_type=none a:buffer_type=bufr %u %d select -assert-count 0 w:clk1 %a %co t:clkbuf %i select -assert-count 0 w:clk2 %a %co t:clkbuf %i diff --git a/tests/various/printattr.ys b/tests/various/printattr.ys index afc6d8eb6..c838e1fac 100644 --- a/tests/various/printattr.ys +++ b/tests/various/printattr.ys @@ -1,5 +1,5 @@ logger -expect log ".*cells_not_processed=[01]* .*" 1 -logger -expect log ".*src=.<