mirror of
https://github.com/YosysHQ/yosys
synced 2025-07-18 10:30:45 +00:00
rename: add -unescape
This commit is contained in:
parent
513f0f16dd
commit
2b659626a3
4 changed files with 215 additions and 46 deletions
|
@ -28,12 +28,71 @@
|
||||||
#include "kernel/ff.h"
|
#include "kernel/ff.h"
|
||||||
#include "kernel/mem.h"
|
#include "kernel/mem.h"
|
||||||
#include "kernel/fmt.h"
|
#include "kernel/fmt.h"
|
||||||
|
#include "backends/verilog/verilog_backend.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
|
|
||||||
|
using namespace VERILOG_BACKEND;
|
||||||
|
|
||||||
|
const pool<string> VERILOG_BACKEND::verilog_keywords() {
|
||||||
|
static const pool<string> res = {
|
||||||
|
// IEEE 1800-2017 Annex B
|
||||||
|
"accept_on", "alias", "always", "always_comb", "always_ff", "always_latch", "and", "assert", "assign", "assume", "automatic", "before",
|
||||||
|
"begin", "bind", "bins", "binsof", "bit", "break", "buf", "bufif0", "bufif1", "byte", "case", "casex", "casez", "cell", "chandle",
|
||||||
|
"checker", "class", "clocking", "cmos", "config", "const", "constraint", "context", "continue", "cover", "covergroup", "coverpoint",
|
||||||
|
"cross", "deassign", "default", "defparam", "design", "disable", "dist", "do", "edge", "else", "end", "endcase", "endchecker",
|
||||||
|
"endclass", "endclocking", "endconfig", "endfunction", "endgenerate", "endgroup", "endinterface", "endmodule", "endpackage",
|
||||||
|
"endprimitive", "endprogram", "endproperty", "endsequence", "endspecify", "endtable", "endtask", "enum", "event", "eventually",
|
||||||
|
"expect", "export", "extends", "extern", "final", "first_match", "for", "force", "foreach", "forever", "fork", "forkjoin", "function",
|
||||||
|
"generate", "genvar", "global", "highz0", "highz1", "if", "iff", "ifnone", "ignore_bins", "illegal_bins", "implements", "implies",
|
||||||
|
"import", "incdir", "include", "initial", "inout", "input", "inside", "instance", "int", "integer", "interconnect", "interface",
|
||||||
|
"intersect", "join", "join_any", "join_none", "large", "let", "liblist", "library", "local", "localparam", "logic", "longint",
|
||||||
|
"macromodule", "matches", "medium", "modport", "module", "nand", "negedge", "nettype", "new", "nexttime", "nmos", "nor",
|
||||||
|
"noshowcancelled", "not", "notif0", "notif1", "null", "or", "output", "package", "packed", "parameter", "pmos", "posedge", "primitive",
|
||||||
|
"priority", "program", "property", "protected", "pull0", "pull1", "pulldown", "pullup", "pulsestyle_ondetect", "pulsestyle_onevent",
|
||||||
|
"pure", "rand", "randc", "randcase", "randsequence", "rcmos", "real", "realtime", "ref", "reg", "reject_on", "release", "repeat",
|
||||||
|
"restrict", "return", "rnmos", "rpmos", "rtran", "rtranif0", "rtranif1", "s_always", "s_eventually", "s_nexttime", "s_until",
|
||||||
|
"s_until_with", "scalared", "sequence", "shortint", "shortreal", "showcancelled", "signed", "small", "soft", "solve", "specify",
|
||||||
|
"specparam", "static", "string", "strong", "strong0", "strong1", "struct", "super", "supply0", "supply1", "sync_accept_on",
|
||||||
|
"sync_reject_on", "table", "tagged", "task", "this", "throughout", "time", "timeprecision", "timeunit", "tran", "tranif0", "tranif1",
|
||||||
|
"tri", "tri0", "tri1", "triand", "trior", "trireg", "type", "typedef", "union", "unique", "unique0", "unsigned", "until", "until_with",
|
||||||
|
"untyped", "use", "uwire", "var", "vectored", "virtual", "void", "wait", "wait_order", "wand", "weak", "weak0", "weak1", "while",
|
||||||
|
"wildcard", "wire", "with", "within", "wor", "xnor", "xor",
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VERILOG_BACKEND::char_is_verilog_escaped(char c) {
|
||||||
|
if ('0' <= c && c <= '9')
|
||||||
|
return false;
|
||||||
|
if ('a' <= c && c <= 'z')
|
||||||
|
return false;
|
||||||
|
if ('A' <= c && c <= 'Z')
|
||||||
|
return false;
|
||||||
|
if (c == '_')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VERILOG_BACKEND::id_is_verilog_escaped(const std::string &str) {
|
||||||
|
if ('0' <= str[0] && str[0] <= '9')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (int i = 0; str[i]; i++)
|
||||||
|
if (char_is_verilog_escaped(str[i]))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (verilog_keywords().count(str))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit, systemverilog, simple_lhs, noparallelcase;
|
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit, systemverilog, simple_lhs, noparallelcase;
|
||||||
|
@ -105,7 +164,6 @@ std::string next_auto_id()
|
||||||
std::string id(RTLIL::IdString internal_id, bool may_rename = true)
|
std::string id(RTLIL::IdString internal_id, bool may_rename = true)
|
||||||
{
|
{
|
||||||
const char *str = internal_id.c_str();
|
const char *str = internal_id.c_str();
|
||||||
bool do_escape = false;
|
|
||||||
|
|
||||||
if (may_rename && auto_name_map.count(internal_id) != 0)
|
if (may_rename && auto_name_map.count(internal_id) != 0)
|
||||||
return stringf("%s_%0*d_", auto_prefix.c_str(), auto_name_digits, auto_name_offset + auto_name_map[internal_id]);
|
return stringf("%s_%0*d_", auto_prefix.c_str(), auto_name_digits, auto_name_offset + auto_name_map[internal_id]);
|
||||||
|
@ -113,51 +171,7 @@ std::string id(RTLIL::IdString internal_id, bool may_rename = true)
|
||||||
if (*str == '\\')
|
if (*str == '\\')
|
||||||
str++;
|
str++;
|
||||||
|
|
||||||
if ('0' <= *str && *str <= '9')
|
if (id_is_verilog_escaped(str))
|
||||||
do_escape = true;
|
|
||||||
|
|
||||||
for (int i = 0; str[i]; i++)
|
|
||||||
{
|
|
||||||
if ('0' <= str[i] && str[i] <= '9')
|
|
||||||
continue;
|
|
||||||
if ('a' <= str[i] && str[i] <= 'z')
|
|
||||||
continue;
|
|
||||||
if ('A' <= str[i] && str[i] <= 'Z')
|
|
||||||
continue;
|
|
||||||
if (str[i] == '_')
|
|
||||||
continue;
|
|
||||||
do_escape = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const pool<string> keywords = {
|
|
||||||
// IEEE 1800-2017 Annex B
|
|
||||||
"accept_on", "alias", "always", "always_comb", "always_ff", "always_latch", "and", "assert", "assign", "assume", "automatic", "before",
|
|
||||||
"begin", "bind", "bins", "binsof", "bit", "break", "buf", "bufif0", "bufif1", "byte", "case", "casex", "casez", "cell", "chandle",
|
|
||||||
"checker", "class", "clocking", "cmos", "config", "const", "constraint", "context", "continue", "cover", "covergroup", "coverpoint",
|
|
||||||
"cross", "deassign", "default", "defparam", "design", "disable", "dist", "do", "edge", "else", "end", "endcase", "endchecker",
|
|
||||||
"endclass", "endclocking", "endconfig", "endfunction", "endgenerate", "endgroup", "endinterface", "endmodule", "endpackage",
|
|
||||||
"endprimitive", "endprogram", "endproperty", "endsequence", "endspecify", "endtable", "endtask", "enum", "event", "eventually",
|
|
||||||
"expect", "export", "extends", "extern", "final", "first_match", "for", "force", "foreach", "forever", "fork", "forkjoin", "function",
|
|
||||||
"generate", "genvar", "global", "highz0", "highz1", "if", "iff", "ifnone", "ignore_bins", "illegal_bins", "implements", "implies",
|
|
||||||
"import", "incdir", "include", "initial", "inout", "input", "inside", "instance", "int", "integer", "interconnect", "interface",
|
|
||||||
"intersect", "join", "join_any", "join_none", "large", "let", "liblist", "library", "local", "localparam", "logic", "longint",
|
|
||||||
"macromodule", "matches", "medium", "modport", "module", "nand", "negedge", "nettype", "new", "nexttime", "nmos", "nor",
|
|
||||||
"noshowcancelled", "not", "notif0", "notif1", "null", "or", "output", "package", "packed", "parameter", "pmos", "posedge", "primitive",
|
|
||||||
"priority", "program", "property", "protected", "pull0", "pull1", "pulldown", "pullup", "pulsestyle_ondetect", "pulsestyle_onevent",
|
|
||||||
"pure", "rand", "randc", "randcase", "randsequence", "rcmos", "real", "realtime", "ref", "reg", "reject_on", "release", "repeat",
|
|
||||||
"restrict", "return", "rnmos", "rpmos", "rtran", "rtranif0", "rtranif1", "s_always", "s_eventually", "s_nexttime", "s_until",
|
|
||||||
"s_until_with", "scalared", "sequence", "shortint", "shortreal", "showcancelled", "signed", "small", "soft", "solve", "specify",
|
|
||||||
"specparam", "static", "string", "strong", "strong0", "strong1", "struct", "super", "supply0", "supply1", "sync_accept_on",
|
|
||||||
"sync_reject_on", "table", "tagged", "task", "this", "throughout", "time", "timeprecision", "timeunit", "tran", "tranif0", "tranif1",
|
|
||||||
"tri", "tri0", "tri1", "triand", "trior", "trireg", "type", "typedef", "union", "unique", "unique0", "unsigned", "until", "until_with",
|
|
||||||
"untyped", "use", "uwire", "var", "vectored", "virtual", "void", "wait", "wait_order", "wand", "weak", "weak0", "weak1", "while",
|
|
||||||
"wildcard", "wire", "with", "within", "wor", "xnor", "xor",
|
|
||||||
};
|
|
||||||
if (keywords.count(str))
|
|
||||||
do_escape = true;
|
|
||||||
|
|
||||||
if (do_escape)
|
|
||||||
return "\\" + std::string(str) + " ";
|
return "\\" + std::string(str) + " ";
|
||||||
return std::string(str);
|
return std::string(str);
|
||||||
}
|
}
|
||||||
|
|
39
backends/verilog/verilog_backend.h
Normal file
39
backends/verilog/verilog_backend.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* A simple and straightforward Verilog backend.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VERILOG_BACKEND_H
|
||||||
|
#define VERILOG_BACKEND_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
YOSYS_NAMESPACE_BEGIN
|
||||||
|
namespace VERILOG_BACKEND {
|
||||||
|
|
||||||
|
const pool<string> verilog_keywords();
|
||||||
|
bool char_is_verilog_escaped(char c);
|
||||||
|
bool id_is_verilog_escaped(const std::string &str);
|
||||||
|
|
||||||
|
}; /* namespace VERILOG_BACKEND */
|
||||||
|
YOSYS_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif /* VERILOG_BACKEND_H */
|
|
@ -20,6 +20,7 @@
|
||||||
#include "kernel/register.h"
|
#include "kernel/register.h"
|
||||||
#include "kernel/rtlil.h"
|
#include "kernel/rtlil.h"
|
||||||
#include "kernel/log.h"
|
#include "kernel/log.h"
|
||||||
|
#include "backends/verilog/verilog_backend.h"
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
@ -186,6 +187,26 @@ static bool rename_witness(RTLIL::Design *design, dict<RTLIL::Module *, int> &ca
|
||||||
return has_witness_signals;
|
return has_witness_signals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string renamed_unescaped(const std::string& str)
|
||||||
|
{
|
||||||
|
std::string new_str = "";
|
||||||
|
|
||||||
|
if ('0' <= str[0] && str[0] <= '9')
|
||||||
|
new_str = '_' + new_str;
|
||||||
|
|
||||||
|
for (char c : str) {
|
||||||
|
if (VERILOG_BACKEND::char_is_verilog_escaped(c))
|
||||||
|
new_str += '_';
|
||||||
|
else
|
||||||
|
new_str += c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VERILOG_BACKEND::verilog_keywords().count(str))
|
||||||
|
new_str += "_";
|
||||||
|
|
||||||
|
return new_str;
|
||||||
|
}
|
||||||
|
|
||||||
struct RenamePass : public Pass {
|
struct RenamePass : public Pass {
|
||||||
RenamePass() : Pass("rename", "rename object in the design") { }
|
RenamePass() : Pass("rename", "rename object in the design") { }
|
||||||
void help() override
|
void help() override
|
||||||
|
@ -252,6 +273,12 @@ struct RenamePass : public Pass {
|
||||||
log("can be used to change the random number generator seed from the default, but it\n");
|
log("can be used to change the random number generator seed from the default, but it\n");
|
||||||
log("must be non-zero.\n");
|
log("must be non-zero.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log("\n");
|
||||||
|
log(" rename -unescape [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Rename all selected public wires and cells that have to be escaped.\n");
|
||||||
|
log("Replaces characters with underscores or adds additional underscores and numbers.\n");
|
||||||
|
log("\n");
|
||||||
}
|
}
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
{
|
{
|
||||||
|
@ -265,6 +292,7 @@ struct RenamePass : public Pass {
|
||||||
bool flag_top = false;
|
bool flag_top = false;
|
||||||
bool flag_output = false;
|
bool flag_output = false;
|
||||||
bool flag_scramble_name = false;
|
bool flag_scramble_name = false;
|
||||||
|
bool flag_unescape = false;
|
||||||
bool got_mode = false;
|
bool got_mode = false;
|
||||||
unsigned int seed = 1;
|
unsigned int seed = 1;
|
||||||
|
|
||||||
|
@ -312,6 +340,11 @@ struct RenamePass : public Pass {
|
||||||
got_mode = true;
|
got_mode = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (arg == "-unescape" && !got_mode) {
|
||||||
|
flag_unescape = true;
|
||||||
|
got_mode = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (arg == "-pattern" && argidx+1 < args.size() && args[argidx+1].find('%') != std::string::npos) {
|
if (arg == "-pattern" && argidx+1 < args.size() && args[argidx+1].find('%') != std::string::npos) {
|
||||||
int pos = args[++argidx].find('%');
|
int pos = args[++argidx].find('%');
|
||||||
pattern_prefix = args[argidx].substr(0, pos);
|
pattern_prefix = args[argidx].substr(0, pos);
|
||||||
|
@ -491,6 +524,48 @@ struct RenamePass : public Pass {
|
||||||
module->rename(it.first, it.second);
|
module->rename(it.first, it.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (flag_unescape)
|
||||||
|
{
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
for (auto module : design->selected_modules())
|
||||||
|
{
|
||||||
|
dict<RTLIL::Wire *, IdString> new_wire_names;
|
||||||
|
dict<RTLIL::Cell *, IdString> new_cell_names;
|
||||||
|
|
||||||
|
for (auto wire : module->selected_wires()) {
|
||||||
|
auto name = wire->name.str();
|
||||||
|
if (name[0] != '\\')
|
||||||
|
continue;
|
||||||
|
name = name.substr(1);
|
||||||
|
if (!VERILOG_BACKEND::id_is_verilog_escaped(name))
|
||||||
|
continue;
|
||||||
|
new_wire_names[wire] = module->uniquify("\\" + renamed_unescaped(name));
|
||||||
|
auto new_name = new_wire_names[wire].str().substr(1);
|
||||||
|
if (VERILOG_BACKEND::id_is_verilog_escaped(new_name))
|
||||||
|
log_error("Failed to rename wire %s -> %s\n", name.c_str(), new_name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto cell : module->selected_cells()) {
|
||||||
|
auto name = cell->name.str();
|
||||||
|
if (name[0] != '\\')
|
||||||
|
continue;
|
||||||
|
name = name.substr(1);
|
||||||
|
if (!VERILOG_BACKEND::id_is_verilog_escaped(name))
|
||||||
|
continue;
|
||||||
|
new_cell_names[cell] = module->uniquify("\\" + renamed_unescaped(name));
|
||||||
|
auto new_name = new_cell_names[cell].str().substr(1);
|
||||||
|
if (VERILOG_BACKEND::id_is_verilog_escaped(new_name))
|
||||||
|
log_error("Failed to rename cell %s -> %s\n", name.c_str(), new_name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &it : new_wire_names)
|
||||||
|
module->rename(it.first, it.second);
|
||||||
|
|
||||||
|
for (auto &it : new_cell_names)
|
||||||
|
module->rename(it.first, it.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (argidx+2 != args.size())
|
if (argidx+2 != args.size())
|
||||||
|
|
41
tests/various/rename_unescape.ys
Normal file
41
tests/various/rename_unescape.ys
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
read_verilog <<EOF
|
||||||
|
module top();
|
||||||
|
wire \a[0] ;
|
||||||
|
wire \0b ;
|
||||||
|
wire c;
|
||||||
|
wire d_;
|
||||||
|
wire d$;
|
||||||
|
wire \$e ;
|
||||||
|
wire \wire ;
|
||||||
|
wire add = c + d$;
|
||||||
|
endmodule
|
||||||
|
EOF
|
||||||
|
|
||||||
|
dump
|
||||||
|
# Replace brackets with _
|
||||||
|
select -assert-count 1 w:a[0]
|
||||||
|
# Prefix first character numeric with _
|
||||||
|
select -assert-count 1 w:\0b
|
||||||
|
# Do nothing to simple identifiers
|
||||||
|
select -assert-count 1 w:c
|
||||||
|
select -assert-count 1 w:d_
|
||||||
|
# Replace dollars with _
|
||||||
|
# and resolve conflict with existing d_
|
||||||
|
select -assert-count 1 w:d$
|
||||||
|
# Public but starts with dollar is legal
|
||||||
|
select -assert-count 1 w:$e
|
||||||
|
# Colliding with keyword
|
||||||
|
select -assert-count 1 w:wire
|
||||||
|
# Don't touch internal names
|
||||||
|
select -assert-count 1 w:$add$<<EOF:*$1_Y
|
||||||
|
|
||||||
|
rename -unescape
|
||||||
|
|
||||||
|
select -assert-count 1 w:a_0_
|
||||||
|
select -assert-count 1 w:_0b
|
||||||
|
select -assert-count 1 w:c
|
||||||
|
select -assert-count 1 w:d_
|
||||||
|
select -assert-count 1 w:d__1
|
||||||
|
select -assert-count 1 w:_e
|
||||||
|
select -assert-count 1 w:wire_
|
||||||
|
select -assert-count 1 w:$add$<<EOF:*$1_Y
|
Loading…
Add table
Add a link
Reference in a new issue