aboutsummaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
Diffstat (limited to 'frontends')
-rw-r--r--frontends/ast/ast.h2
-rw-r--r--frontends/ast/simplify.cc311
-rw-r--r--frontends/ilang/.gitignore4
-rw-r--r--frontends/ilang/Makefile.inc19
-rw-r--r--frontends/rpc/rpc_frontend.cc2
-rw-r--r--frontends/rtlil/.gitignore4
-rw-r--r--frontends/rtlil/Makefile.inc19
-rw-r--r--frontends/rtlil/rtlil_frontend.cc (renamed from frontends/ilang/ilang_frontend.cc)61
-rw-r--r--frontends/rtlil/rtlil_frontend.h (renamed from frontends/ilang/ilang_frontend.h)22
-rw-r--r--frontends/rtlil/rtlil_lexer.l (renamed from frontends/ilang/ilang_lexer.l)24
-rw-r--r--frontends/rtlil/rtlil_parser.y (renamed from frontends/ilang/ilang_parser.y)42
-rw-r--r--frontends/verific/verific.cc255
12 files changed, 564 insertions, 201 deletions
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 9a5aa15f9..203b50021 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -250,7 +250,7 @@ namespace AST
// it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL()
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param);
AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init);
- void expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map);
+ void expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map, bool original_scope = true);
void replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules);
void mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg_places,
dict<AstNode*, uint32_t> &mem2reg_flags, dict<AstNode*, uint32_t> &proc_flags, uint32_t &status_flags);
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 66f22e113..153a42e19 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -89,7 +89,7 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg
case 'S':
case 'd':
case 'D':
- if (got_len)
+ if (got_len && len_value != 0)
goto unsupported_format;
YS_FALLTHROUGH
case 'x':
@@ -110,6 +110,12 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg
goto unsupported_format;
break;
+ case 'l':
+ case 'L':
+ if (got_len)
+ goto unsupported_format;
+ break;
+
default:
unsupported_format:
log_file_error(filename, location.first_line, "System task `%s' called with invalid/unsupported format specifier.\n", str.c_str());
@@ -155,6 +161,11 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg
sout += log_id(current_module->name);
break;
+ case 'l':
+ case 'L':
+ sout += log_id(current_module->name);
+ break;
+
default:
log_abort();
}
@@ -380,31 +391,66 @@ static int size_packed_struct(AstNode *snode, int base_offset)
static AstNode *node_int(int ival)
{
- // maybe mkconst_int should have default values for the common integer case
- return AstNode::mkconst_int(ival, true, 32);
+ return AstNode::mkconst_int(ival, true);
+}
+
+static AstNode *multiply_by_const(AstNode *expr_node, int stride)
+{
+ return new AstNode(AST_MUL, expr_node, node_int(stride));
}
-static AstNode *offset_indexed_range(int offset_right, int stride, AstNode *left_expr, AstNode *right_expr)
+static AstNode *offset_indexed_range(int offset, int stride, AstNode *left_expr, AstNode *right_expr)
{
// adjust the range expressions to add an offset into the struct
// and maybe index using an array stride
auto left = left_expr->clone();
auto right = right_expr->clone();
- if (stride == 1) {
- // just add the offset
- left = new AstNode(AST_ADD, node_int(offset_right), left);
- right = new AstNode(AST_ADD, node_int(offset_right), right);
+ if (stride > 1) {
+ // newleft = (left + 1) * stride - 1
+ left = new AstNode(AST_SUB, multiply_by_const(new AstNode(AST_ADD, left, node_int(1)), stride), node_int(1));
+ // newright = right * stride
+ right = multiply_by_const(right, stride);
+ }
+ // add the offset
+ if (offset) {
+ left = new AstNode(AST_ADD, node_int(offset), left);
+ right = new AstNode(AST_ADD, node_int(offset), right);
+ }
+ return new AstNode(AST_RANGE, left, right);
+}
+
+static AstNode *make_struct_index_range(AstNode *node, AstNode *rnode, int stride, int offset)
+{
+ // generate a range node to perform either bit or array indexing
+ if (rnode->children.size() == 1) {
+ // index e.g. s.a[i]
+ return offset_indexed_range(offset, stride, rnode->children[0], rnode->children[0]);
+ }
+ else if (rnode->children.size() == 2) {
+ // slice e.g. s.a[i:j]
+ return offset_indexed_range(offset, stride, rnode->children[0], rnode->children[1]);
}
else {
- // newleft = offset_right - 1 + (left + 1) * stride
- left = new AstNode(AST_ADD, new AstNode(AST_SUB, node_int(offset_right), node_int(1)),
- new AstNode(AST_MUL, node_int(stride), new AstNode(AST_ADD, left, node_int(1))));
- // newright = offset_right + right * stride
- right = new AstNode(AST_ADD, node_int(offset_right), new AstNode(AST_MUL, right, node_int(stride)));
+ struct_op_error(node);
}
+}
+
+static AstNode *slice_range(AstNode *rnode, AstNode *snode)
+{
+ // apply the bit slice indicated by snode to the range rnode
+ log_assert(rnode->type==AST_RANGE);
+ auto left = rnode->children[0];
+ auto right = rnode->children[1];
+ log_assert(snode->type==AST_RANGE);
+ auto slice_left = snode->children[0];
+ auto slice_right = snode->children[1];
+ auto width = new AstNode(AST_SUB, slice_left->clone(), slice_right->clone());
+ right = new AstNode(AST_ADD, right->clone(), slice_right->clone());
+ left = new AstNode(AST_ADD, right->clone(), width);
return new AstNode(AST_RANGE, left, right);
}
+
static AstNode *make_struct_member_range(AstNode *node, AstNode *member_node)
{
// Work out the range in the packed array that corresponds to a struct member
@@ -414,27 +460,26 @@ static AstNode *make_struct_member_range(AstNode *node, AstNode *member_node)
int range_right = member_node->range_right;
if (node->children.empty()) {
// no range operations apply, return the whole width
+ return make_range(range_left, range_right);
}
- else if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
- auto rnode = node->children[0];
- int stride = get_struct_array_width(member_node);
- if (rnode->children.size() == 1) {
- // index e.g. s.a[i]
- return offset_indexed_range(range_right, stride, rnode->children[0], rnode->children[0]);
- }
- else if (rnode->children.size() == 2) {
- // slice e.g. s.a[i:j]
- return offset_indexed_range(range_right, stride, rnode->children[0], rnode->children[1]);
- }
- else {
- struct_op_error(node);
- }
+ int stride = get_struct_array_width(member_node);
+ if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
+ // bit or array indexing e.g. s.a[2] or s.a[1:0]
+ return make_struct_index_range(node, node->children[0], stride, range_right);
+ }
+ else if (node->children.size() == 1 && node->children[0]->type == AST_MULTIRANGE) {
+ // multirange, i.e. bit slice after array index, e.g. s.a[i][p:q]
+ log_assert(stride > 1);
+ auto mrnode = node->children[0];
+ auto element_range = make_struct_index_range(node, mrnode->children[0], stride, range_right);
+ // then apply bit slice range
+ auto range = slice_range(element_range, mrnode->children[1]);
+ delete element_range;
+ return range;
}
else {
- // TODO multirange, i.e. bit slice after array index s.a[i][p:q]
struct_op_error(node);
}
- return make_range(range_left, range_right);
}
static void add_members_to_scope(AstNode *snode, std::string name)
@@ -1478,7 +1523,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
for (int i = 0; 2*i < GetSize(id2ast->multirange_dimensions); i++)
{
- if (GetSize(children[0]->children) < i)
+ if (GetSize(children[0]->children) <= i)
log_file_error(filename, location.first_line, "Insufficient number of array indices for %s.\n", log_id(str));
AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone();
@@ -1563,6 +1608,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_IDENTIFIER) {
if (current_scope.count(str) == 0) {
AstNode *current_scope_ast = (current_ast_mod == nullptr) ? current_ast : current_ast_mod;
+ const std::string& mod_scope = current_scope_ast->str;
+ if (str[0] == '\\' && str.substr(0, mod_scope.size()) == mod_scope) {
+ std::string new_str = "\\" + str.substr(mod_scope.size() + 1);
+ if (current_scope.count(new_str)) {
+ str = new_str;
+ }
+ }
for (auto node : current_scope_ast->children) {
//log("looking at mod scope child %s\n", type2str(node->type).c_str());
switch (node->type) {
@@ -1807,7 +1859,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_GENFOR) {
for (size_t i = 0; i < buf->children.size(); i++) {
- buf->children[i]->simplify(false, false, false, stage, -1, false, false);
+ buf->children[i]->simplify(const_fold, false, false, stage, -1, false, false);
current_ast_mod->children.push_back(buf->children[i]);
}
} else {
@@ -1883,7 +1935,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
for (size_t i = 0; i < children.size(); i++) {
- children[i]->simplify(false, false, false, stage, -1, false, false);
+ children[i]->simplify(const_fold, false, false, stage, -1, false, false);
current_ast_mod->children.push_back(children[i]);
}
@@ -1920,7 +1972,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
for (size_t i = 0; i < buf->children.size(); i++) {
- buf->children[i]->simplify(false, false, false, stage, -1, false, false);
+ buf->children[i]->simplify(const_fold, false, false, stage, -1, false, false);
current_ast_mod->children.push_back(buf->children[i]);
}
@@ -1999,7 +2051,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
for (size_t i = 0; i < buf->children.size(); i++) {
- buf->children[i]->simplify(false, false, false, stage, -1, false, false);
+ buf->children[i]->simplify(const_fold, false, false, stage, -1, false, false);
current_ast_mod->children.push_back(buf->children[i]);
}
@@ -3052,7 +3104,7 @@ skip_dynamic_range_lvalue_expansion:;
bool all_args_const = true;
for (auto child : children) {
while (child->simplify(true, false, false, 1, -1, false, true)) { }
- if (child->type != AST_CONSTANT)
+ if (child->type != AST_CONSTANT && child->type != AST_REALVALUE)
all_args_const = false;
}
@@ -3177,14 +3229,15 @@ skip_dynamic_range_lvalue_expansion:;
if (wire_cache.count(child->str))
{
wire = wire_cache.at(child->str);
- if (wire->children.empty()) {
+ bool contains_value = wire->type == AST_LOCALPARAM;
+ if (wire->children.size() == contains_value) {
for (auto c : child->children)
wire->children.push_back(c->clone());
} else if (!child->children.empty()) {
while (child->simplify(true, false, false, stage, -1, false, false)) { }
- if (GetSize(child->children) == GetSize(wire->children)) {
+ if (GetSize(child->children) == GetSize(wire->children) - contains_value) {
for (int i = 0; i < GetSize(child->children); i++)
- if (*child->children.at(i) != *wire->children.at(i))
+ if (*child->children.at(i) != *wire->children.at(i + contains_value))
goto tcall_incompatible_wires;
} else {
tcall_incompatible_wires:
@@ -3711,8 +3764,11 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
}
// annotate the names of all wires and other named objects in a generate block
-void AstNode::expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map)
+void AstNode::expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map, bool original_scope)
{
+ // `original_scope` defaults to false, and is used to prevent the premature
+ // prefixing of items in named sub-blocks
+
if (!index_var.empty() && type == AST_IDENTIFIER && str == index_var) {
if (children.empty()) {
current_scope[index_var]->children[0]->cloneInto(this);
@@ -3725,53 +3781,85 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
}
}
- if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) && name_map.count(str) > 0)
- str = name_map[str];
+ if (type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) {
+ if (name_map.count(str) > 0) {
+ str = name_map[str];
+ } else {
+ // remap the prefix of this ident if it is a local generate scope
+ size_t pos = str.rfind('.');
+ if (pos != std::string::npos) {
+ std::string existing_prefix = str.substr(0, pos);
+ if (name_map.count(existing_prefix) > 0) {
+ str = name_map[existing_prefix] + str.substr(pos);
+ }
+ }
+ }
+ }
std::map<std::string, std::string> backup_name_map;
+ auto prefix_node = [&](AstNode* child) {
+ if (backup_name_map.size() == 0)
+ backup_name_map = name_map;
+
+ // if within a nested scope
+ if (!original_scope) {
+ // this declaration shadows anything in the parent scope(s)
+ name_map[child->str] = child->str;
+ return;
+ }
+
+ std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
+ size_t pos = child->str.rfind('.');
+ if (pos == std::string::npos)
+ pos = child->str[0] == '\\' && prefix[0] == '\\' ? 1 : 0;
+ else
+ pos = pos + 1;
+ new_name = child->str.substr(0, pos) + new_name + child->str.substr(pos);
+ if (new_name[0] != '$' && new_name[0] != '\\')
+ new_name = prefix[0] + new_name;
+
+ name_map[child->str] = new_name;
+ if (child->type == AST_FUNCTION)
+ replace_result_wire_name_in_function(child, child->str, new_name);
+ else
+ child->str = new_name;
+ current_scope[new_name] = child;
+ };
+
for (size_t i = 0; i < children.size(); i++) {
AstNode *child = children[i];
- if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM ||
- child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF || child->type == AST_ENUM_ITEM) {
- if (backup_name_map.size() == 0)
- backup_name_map = name_map;
- std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
- size_t pos = child->str.rfind('.');
- if (pos == std::string::npos)
- pos = child->str[0] == '\\' && prefix[0] == '\\' ? 1 : 0;
- else
- pos = pos + 1;
- new_name = child->str.substr(0, pos) + new_name + child->str.substr(pos);
- if (new_name[0] != '$' && new_name[0] != '\\')
- new_name = prefix[0] + new_name;
- name_map[child->str] = new_name;
- if (child->type == AST_FUNCTION)
- replace_result_wire_name_in_function(child, child->str, new_name);
- else
- child->str = new_name;
- current_scope[new_name] = child;
- }
- if (child->type == AST_ENUM){
+
+ switch (child->type) {
+ case AST_WIRE:
+ case AST_MEMORY:
+ case AST_PARAMETER:
+ case AST_LOCALPARAM:
+ case AST_FUNCTION:
+ case AST_TASK:
+ case AST_CELL:
+ case AST_TYPEDEF:
+ case AST_ENUM_ITEM:
+ case AST_GENVAR:
+ prefix_node(child);
+ break;
+
+ case AST_BLOCK:
+ case AST_GENBLOCK:
+ if (!child->str.empty())
+ prefix_node(child);
+ break;
+
+ case AST_ENUM:
current_scope[child->str] = child;
for (auto enode : child->children){
log_assert(enode->type == AST_ENUM_ITEM);
- if (backup_name_map.size() == 0)
- backup_name_map = name_map;
- std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
- size_t pos = enode->str.rfind('.');
- if (pos == std::string::npos)
- pos = enode->str[0] == '\\' && prefix[0] == '\\' ? 1 : 0;
- else
- pos = pos + 1;
- new_name = enode->str.substr(0, pos) + new_name + enode->str.substr(pos);
- if (new_name[0] != '$' && new_name[0] != '\\')
- new_name = prefix[0] + new_name;
- name_map[enode->str] = new_name;
-
- enode->str = new_name;
- current_scope[new_name] = enode;
+ prefix_node(enode);
}
+ break;
+
+ default:
+ break;
}
}
@@ -3781,8 +3869,14 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
// still needs to recursed-into
if (type == AST_PREFIX && i == 1 && child->type == AST_IDENTIFIER)
continue;
- if (child->type != AST_FUNCTION && child->type != AST_TASK)
- child->expand_genblock(index_var, prefix, name_map);
+ // functions/tasks may reference wires, constants, etc. in this scope
+ if (child->type == AST_FUNCTION || child->type == AST_TASK)
+ child->expand_genblock(index_var, prefix, name_map, false);
+ // continue prefixing if this child block is anonymous
+ else if (child->type == AST_GENBLOCK || child->type == AST_BLOCK)
+ child->expand_genblock(index_var, prefix, name_map, original_scope && child->str.empty());
+ else
+ child->expand_genblock(index_var, prefix, name_map, original_scope);
}
@@ -4370,27 +4464,9 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
size_t argidx = 0;
for (auto child : children)
{
- if (child->type == AST_WIRE)
- {
- while (child->simplify(true, false, false, 1, -1, false, true)) { }
- if (!child->range_valid)
- log_file_error(child->filename, child->location.first_line, "Can't determine size of variable %s\n%s:%d.%d-%d.%d: ... called from here.\n",
- child->str.c_str(), fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
- variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1);
- variables[child->str].offset = min(child->range_left, child->range_right);
- variables[child->str].is_signed = child->is_signed;
- if (child->is_input && argidx < fcall->children.size())
- variables[child->str].val = fcall->children.at(argidx++)->bitsAsConst(variables[child->str].val.bits.size());
- backup_scope[child->str] = current_scope[child->str];
- current_scope[child->str] = child;
- continue;
- }
-
block->children.push_back(child->clone());
}
- log_assert(variables.count(str) != 0);
-
while (!block->children.empty())
{
AstNode *stmt = block->children.front();
@@ -4402,6 +4478,47 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
stmt->dumpAst(NULL, "stmt> ");
#endif
+ if (stmt->type == AST_WIRE)
+ {
+ while (stmt->simplify(true, false, false, 1, -1, false, true)) { }
+ if (!stmt->range_valid)
+ log_file_error(stmt->filename, stmt->location.first_line, "Can't determine size of variable %s\n%s:%d.%d-%d.%d: ... called from here.\n",
+ stmt->str.c_str(), fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
+ variables[stmt->str].val = RTLIL::Const(RTLIL::State::Sx, abs(stmt->range_left - stmt->range_right)+1);
+ variables[stmt->str].offset = min(stmt->range_left, stmt->range_right);
+ variables[stmt->str].is_signed = stmt->is_signed;
+ if (stmt->is_input && argidx < fcall->children.size()) {
+ int width = variables[stmt->str].val.bits.size();
+ auto* arg_node = fcall->children.at(argidx++);
+ if (arg_node->type == AST_CONSTANT) {
+ variables[stmt->str].val = arg_node->bitsAsConst(width);
+ } else {
+ log_assert(arg_node->type == AST_REALVALUE);
+ variables[stmt->str].val = arg_node->realAsConst(width);
+ }
+ }
+ if (!backup_scope.count(stmt->str))
+ backup_scope[stmt->str] = current_scope[stmt->str];
+ current_scope[stmt->str] = stmt;
+
+ block->children.erase(block->children.begin());
+ continue;
+ }
+
+ log_assert(variables.count(str) != 0);
+
+ if (stmt->type == AST_LOCALPARAM)
+ {
+ while (stmt->simplify(true, false, false, 1, -1, false, true)) { }
+
+ if (!backup_scope.count(stmt->str))
+ backup_scope[stmt->str] = current_scope[stmt->str];
+ current_scope[stmt->str] = stmt;
+
+ block->children.erase(block->children.begin());
+ continue;
+ }
+
if (stmt->type == AST_ASSIGN_EQ)
{
if (stmt->children.at(0)->type == AST_IDENTIFIER && stmt->children.at(0)->children.size() != 0 &&
diff --git a/frontends/ilang/.gitignore b/frontends/ilang/.gitignore
deleted file mode 100644
index f586b33c7..000000000
--- a/frontends/ilang/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-ilang_lexer.cc
-ilang_parser.output
-ilang_parser.tab.cc
-ilang_parser.tab.hh
diff --git a/frontends/ilang/Makefile.inc b/frontends/ilang/Makefile.inc
deleted file mode 100644
index 6f1f0e8fc..000000000
--- a/frontends/ilang/Makefile.inc
+++ /dev/null
@@ -1,19 +0,0 @@
-
-GENFILES += frontends/ilang/ilang_parser.tab.cc
-GENFILES += frontends/ilang/ilang_parser.tab.hh
-GENFILES += frontends/ilang/ilang_parser.output
-GENFILES += frontends/ilang/ilang_lexer.cc
-
-frontends/ilang/ilang_parser.tab.cc: frontends/ilang/ilang_parser.y
- $(Q) mkdir -p $(dir $@)
- $(P) $(BISON) -o $@ -d -r all -b frontends/ilang/ilang_parser $<
-
-frontends/ilang/ilang_parser.tab.hh: frontends/ilang/ilang_parser.tab.cc
-
-frontends/ilang/ilang_lexer.cc: frontends/ilang/ilang_lexer.l
- $(Q) mkdir -p $(dir $@)
- $(P) flex -o frontends/ilang/ilang_lexer.cc $<
-
-OBJS += frontends/ilang/ilang_parser.tab.o frontends/ilang/ilang_lexer.o
-OBJS += frontends/ilang/ilang_frontend.o
-
diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc
index 6d72cbff5..5a40001cb 100644
--- a/frontends/rpc/rpc_frontend.cc
+++ b/frontends/rpc/rpc_frontend.cc
@@ -378,7 +378,7 @@ struct RpcFrontend : public Pass {
log(" -> {\"method\": \"derive\", \"module\": \"<module-name\">, \"parameters\": {\n");
log(" \"<param-name>\": {\"type\": \"[unsigned|signed|string|real]\",\n");
log(" \"value\": \"<param-value>\"}, ...}}\n");
- log(" <- {\"frontend\": \"[ilang|verilog|...]\",\"source\": \"<source>\"}}\n");
+ log(" <- {\"frontend\": \"[rtlil|verilog|...]\",\"source\": \"<source>\"}}\n");
log(" <- {\"error\": \"<error-message>\"}\n");
log(" request for the module <module-name> to be derived for a specific set of\n");
log(" parameters. <param-name> starts with \\ for named parameters, and with $\n");
diff --git a/frontends/rtlil/.gitignore b/frontends/rtlil/.gitignore
new file mode 100644
index 000000000..d4a322756
--- /dev/null
+++ b/frontends/rtlil/.gitignore
@@ -0,0 +1,4 @@
+rtlil_lexer.cc
+rtlil_parser.output
+rtlil_parser.tab.cc
+rtlil_parser.tab.hh
diff --git a/frontends/rtlil/Makefile.inc b/frontends/rtlil/Makefile.inc
new file mode 100644
index 000000000..d0c0cfcf8
--- /dev/null
+++ b/frontends/rtlil/Makefile.inc
@@ -0,0 +1,19 @@
+
+GENFILES += frontends/rtlil/rtlil_parser.tab.cc
+GENFILES += frontends/rtlil/rtlil_parser.tab.hh
+GENFILES += frontends/rtlil/rtlil_parser.output
+GENFILES += frontends/rtlil/rtlil_lexer.cc
+
+frontends/rtlil/rtlil_parser.tab.cc: frontends/rtlil/rtlil_parser.y
+ $(Q) mkdir -p $(dir $@)
+ $(P) $(BISON) -o $@ -d -r all -b frontends/rtlil/rtlil_parser $<
+
+frontends/rtlil/rtlil_parser.tab.hh: frontends/rtlil/rtlil_parser.tab.cc
+
+frontends/rtlil/rtlil_lexer.cc: frontends/rtlil/rtlil_lexer.l
+ $(Q) mkdir -p $(dir $@)
+ $(P) flex -o frontends/rtlil/rtlil_lexer.cc $<
+
+OBJS += frontends/rtlil/rtlil_parser.tab.o frontends/rtlil/rtlil_lexer.o
+OBJS += frontends/rtlil/rtlil_frontend.o
+
diff --git a/frontends/ilang/ilang_frontend.cc b/frontends/rtlil/rtlil_frontend.cc
index 973e62f2c..00c34175e 100644
--- a/frontends/ilang/ilang_frontend.cc
+++ b/frontends/rtlil/rtlil_frontend.cc
@@ -18,30 +18,30 @@
* ---
*
* A very simple and straightforward frontend for the RTLIL text
- * representation (as generated by the 'ilang' backend).
+ * representation.
*
*/
-#include "ilang_frontend.h"
+#include "rtlil_frontend.h"
#include "kernel/register.h"
#include "kernel/log.h"
-void rtlil_frontend_ilang_yyerror(char const *s)
+void rtlil_frontend_yyerror(char const *s)
{
- YOSYS_NAMESPACE_PREFIX log_error("Parser error in line %d: %s\n", rtlil_frontend_ilang_yyget_lineno(), s);
+ YOSYS_NAMESPACE_PREFIX log_error("Parser error in line %d: %s\n", rtlil_frontend_yyget_lineno(), s);
}
YOSYS_NAMESPACE_BEGIN
-struct IlangFrontend : public Frontend {
- IlangFrontend() : Frontend("ilang", "read modules from ilang file") { }
+struct RTLILFrontend : public Frontend {
+ RTLILFrontend() : Frontend("rtlil", "read modules from RTLIL file") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" read_ilang [filename]\n");
+ log(" read_rtlil [filename]\n");
log("\n");
- log("Load modules from an ilang file to the current design. (ilang is a text\n");
+ log("Load modules from an RTLIL file to the current design. (RTLIL is a text\n");
log("representation of a design in yosys's internal format.)\n");
log("\n");
log(" -nooverwrite\n");
@@ -58,27 +58,27 @@ struct IlangFrontend : public Frontend {
}
void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
{
- ILANG_FRONTEND::flag_nooverwrite = false;
- ILANG_FRONTEND::flag_overwrite = false;
- ILANG_FRONTEND::flag_lib = false;
+ RTLIL_FRONTEND::flag_nooverwrite = false;
+ RTLIL_FRONTEND::flag_overwrite = false;
+ RTLIL_FRONTEND::flag_lib = false;
- log_header(design, "Executing ILANG frontend.\n");
+ log_header(design, "Executing RTLIL frontend.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
std::string arg = args[argidx];
if (arg == "-nooverwrite") {
- ILANG_FRONTEND::flag_nooverwrite = true;
- ILANG_FRONTEND::flag_overwrite = false;
+ RTLIL_FRONTEND::flag_nooverwrite = true;
+ RTLIL_FRONTEND::flag_overwrite = false;
continue;
}
if (arg == "-overwrite") {
- ILANG_FRONTEND::flag_nooverwrite = false;
- ILANG_FRONTEND::flag_overwrite = true;
+ RTLIL_FRONTEND::flag_nooverwrite = false;
+ RTLIL_FRONTEND::flag_overwrite = true;
continue;
}
if (arg == "-lib") {
- ILANG_FRONTEND::flag_lib = true;
+ RTLIL_FRONTEND::flag_lib = true;
continue;
}
break;
@@ -87,12 +87,27 @@ struct IlangFrontend : public Frontend {
log("Input filename: %s\n", filename.c_str());
- ILANG_FRONTEND::lexin = f;
- ILANG_FRONTEND::current_design = design;
- rtlil_frontend_ilang_yydebug = false;
- rtlil_frontend_ilang_yyrestart(NULL);
- rtlil_frontend_ilang_yyparse();
- rtlil_frontend_ilang_yylex_destroy();
+ RTLIL_FRONTEND::lexin = f;
+ RTLIL_FRONTEND::current_design = design;
+ rtlil_frontend_yydebug = false;
+ rtlil_frontend_yyrestart(NULL);
+ rtlil_frontend_yyparse();
+ rtlil_frontend_yylex_destroy();
+ }
+} RTLILFrontend;
+
+struct IlangFrontend : public Frontend {
+ IlangFrontend() : Frontend("ilang", "(deprecated) alias of read_rtlil") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log("See `help read_rtlil`.\n");
+ log("\n");
+ }
+ void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ RTLILFrontend.execute(f, filename, args, design);
}
} IlangFrontend;
diff --git a/frontends/ilang/ilang_frontend.h b/frontends/rtlil/rtlil_frontend.h
index f8a152841..a420778b0 100644
--- a/frontends/ilang/ilang_frontend.h
+++ b/frontends/rtlil/rtlil_frontend.h
@@ -18,18 +18,18 @@
* ---
*
* A very simple and straightforward frontend for the RTLIL text
- * representation (as generated by the 'ilang' backend).
+ * representation.
*
*/
-#ifndef ILANG_FRONTEND_H
-#define ILANG_FRONTEND_H
+#ifndef RTLIL_FRONTEND_H
+#define RTLIL_FRONTEND_H
#include "kernel/yosys.h"
YOSYS_NAMESPACE_BEGIN
-namespace ILANG_FRONTEND {
+namespace RTLIL_FRONTEND {
extern std::istream *lexin;
extern RTLIL::Design *current_design;
extern bool flag_nooverwrite;
@@ -39,13 +39,13 @@ namespace ILANG_FRONTEND {
YOSYS_NAMESPACE_END
-extern int rtlil_frontend_ilang_yydebug;
-int rtlil_frontend_ilang_yylex(void);
-void rtlil_frontend_ilang_yyerror(char const *s);
-void rtlil_frontend_ilang_yyrestart(FILE *f);
-int rtlil_frontend_ilang_yyparse(void);
-int rtlil_frontend_ilang_yylex_destroy(void);
-int rtlil_frontend_ilang_yyget_lineno(void);
+extern int rtlil_frontend_yydebug;
+int rtlil_frontend_yylex(void);
+void rtlil_frontend_yyerror(char const *s);
+void rtlil_frontend_yyrestart(FILE *f);
+int rtlil_frontend_yyparse(void);
+int rtlil_frontend_yylex_destroy(void);
+int rtlil_frontend_yyget_lineno(void);
#endif
diff --git a/frontends/ilang/ilang_lexer.l b/frontends/rtlil/rtlil_lexer.l
index 3362ed641..295455f53 100644
--- a/frontends/ilang/ilang_lexer.l
+++ b/frontends/rtlil/rtlil_lexer.l
@@ -18,7 +18,7 @@
* ---
*
* A very simple and straightforward frontend for the RTLIL text
- * representation (as generated by the 'ilang' backend).
+ * representation.
*
*/
@@ -30,20 +30,20 @@
#endif
#include <cstdlib>
-#include "frontends/ilang/ilang_frontend.h"
-#include "ilang_parser.tab.hh"
+#include "frontends/rtlil/rtlil_frontend.h"
+#include "rtlil_parser.tab.hh"
USING_YOSYS_NAMESPACE
#define YY_INPUT(buf,result,max_size) \
- result = readsome(*ILANG_FRONTEND::lexin, buf, max_size)
+ result = readsome(*RTLIL_FRONTEND::lexin, buf, max_size)
%}
%option yylineno
%option noyywrap
%option nounput
-%option prefix="rtlil_frontend_ilang_yy"
+%option prefix="rtlil_frontend_yy"
%x STRING
@@ -84,11 +84,11 @@ USING_YOSYS_NAMESPACE
[a-z]+ { return TOK_INVALID; }
-"\\"[^ \t\r\n]+ { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_ID; }
-"$"[^ \t\r\n]+ { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_ID; }
-"."[0-9]+ { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_ID; }
+"\\"[^ \t\r\n]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; }
+"$"[^ \t\r\n]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; }
+"."[0-9]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; }
-[0-9]+'[01xzm-]* { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_VALUE; }
+[0-9]+'[01xzm-]* { rtlil_frontend_yylval.string = strdup(yytext); return TOK_VALUE; }
-?[0-9]+ {
char *end = nullptr;
errno = 0;
@@ -98,7 +98,7 @@ USING_YOSYS_NAMESPACE
return TOK_INVALID; // literal out of range of long
if (value < INT_MIN || value > INT_MAX)
return TOK_INVALID; // literal out of range of int (relevant mostly for LP64 platforms)
- rtlil_frontend_ilang_yylval.integer = value;
+ rtlil_frontend_yylval.integer = value;
return TOK_INT;
}
@@ -131,7 +131,7 @@ USING_YOSYS_NAMESPACE
yystr[j++] = yystr[i++];
}
yystr[j] = 0;
- rtlil_frontend_ilang_yylval.string = yystr;
+ rtlil_frontend_yylval.string = yystr;
return TOK_STRING;
}
<STRING>. { yymore(); }
@@ -145,6 +145,6 @@ USING_YOSYS_NAMESPACE
%%
// this is a hack to avoid the 'yyinput defined but not used' error msgs
-void *rtlil_frontend_ilang_avoid_input_warnings() {
+void *rtlil_frontend_avoid_input_warnings() {
return (void*)&yyinput;
}
diff --git a/frontends/ilang/ilang_parser.y b/frontends/rtlil/rtlil_parser.y
index 879ef4af9..646489196 100644
--- a/frontends/ilang/ilang_parser.y
+++ b/frontends/rtlil/rtlil_parser.y
@@ -18,15 +18,15 @@
* ---
*
* A very simple and straightforward frontend for the RTLIL text
- * representation (as generated by the 'ilang' backend).
+ * representation.
*
*/
%{
#include <list>
-#include "frontends/ilang/ilang_frontend.h"
+#include "frontends/rtlil/rtlil_frontend.h"
YOSYS_NAMESPACE_BEGIN
-namespace ILANG_FRONTEND {
+namespace RTLIL_FRONTEND {
std::istream *lexin;
RTLIL::Design *current_design;
RTLIL::Module *current_module;
@@ -40,12 +40,12 @@ namespace ILANG_FRONTEND {
bool flag_nooverwrite, flag_overwrite, flag_lib;
bool delete_current_module;
}
-using namespace ILANG_FRONTEND;
+using namespace RTLIL_FRONTEND;
YOSYS_NAMESPACE_END
USING_YOSYS_NAMESPACE
%}
-%define api.prefix {rtlil_frontend_ilang_yy}
+%define api.prefix {rtlil_frontend_yy}
/* The union is defined in the header, so we need to provide all the
* includes it requires
@@ -53,7 +53,7 @@ USING_YOSYS_NAMESPACE
%code requires {
#include <string>
#include <vector>
-#include "frontends/ilang/ilang_frontend.h"
+#include "frontends/rtlil/rtlil_frontend.h"
}
%union {
@@ -87,7 +87,7 @@ input:
attrbuf.clear();
} design {
if (attrbuf.size() != 0)
- rtlil_frontend_ilang_yyerror("dangling attribute");
+ rtlil_frontend_yyerror("dangling attribute");
};
EOL:
@@ -111,7 +111,7 @@ module:
log("Ignoring blackbox re-definition of module %s.\n", $2);
delete_current_module = true;
} else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) {
- rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of module %s.", $2).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of module %s.", $2).c_str());
} else if (flag_nooverwrite) {
log("Ignoring re-definition of module %s.\n", $2);
delete_current_module = true;
@@ -129,7 +129,7 @@ module:
free($2);
} module_body TOK_END {
if (attrbuf.size() != 0)
- rtlil_frontend_ilang_yyerror("dangling attribute");
+ rtlil_frontend_yyerror("dangling attribute");
current_module->fixup_ports();
if (delete_current_module)
delete current_module;
@@ -172,12 +172,12 @@ autoidx_stmt:
wire_stmt:
TOK_WIRE {
- current_wire = current_module->addWire("$__ilang_frontend_tmp__");
+ current_wire = current_module->addWire("$__rtlil_frontend_tmp__");
current_wire->attributes = attrbuf;
attrbuf.clear();
} wire_options TOK_ID EOL {
if (current_module->wire($4) != nullptr)
- rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of wire %s.", $4).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of wire %s.", $4).c_str());
current_module->rename(current_wire, $4);
free($4);
};
@@ -187,7 +187,7 @@ wire_options:
current_wire->width = $3;
} |
wire_options TOK_WIDTH TOK_INVALID {
- rtlil_frontend_ilang_yyerror("ilang error: invalid wire width");
+ rtlil_frontend_yyerror("RTLIL error: invalid wire width");
} |
wire_options TOK_UPTO {
current_wire->upto = true;
@@ -222,7 +222,7 @@ memory_stmt:
attrbuf.clear();
} memory_options TOK_ID EOL {
if (current_module->memories.count($4) != 0)
- rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of memory %s.", $4).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of memory %s.", $4).c_str());
current_memory->name = $4;
current_module->memories[$4] = current_memory;
free($4);
@@ -243,7 +243,7 @@ memory_options:
cell_stmt:
TOK_CELL TOK_ID TOK_ID EOL {
if (current_module->cell($3) != nullptr)
- rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell %s.", $3).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of cell %s.", $3).c_str());
current_cell = current_module->addCell($3, $2);
current_cell->attributes = attrbuf;
attrbuf.clear();
@@ -271,7 +271,7 @@ cell_body:
} |
cell_body TOK_CONNECT TOK_ID sigspec EOL {
if (current_cell->hasPort($3))
- rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell port %s.", $3).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of cell port %s.", $3).c_str());
current_cell->setPort($3, *$4);
delete $4;
free($3);
@@ -281,7 +281,7 @@ cell_body:
proc_stmt:
TOK_PROCESS TOK_ID EOL {
if (current_module->processes.count($2) != 0)
- rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of process %s.", $2).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of process %s.", $2).c_str());
current_process = new RTLIL::Process;
current_process->name = $2;
current_process->attributes = attrbuf;
@@ -342,7 +342,7 @@ case_body:
assign_stmt:
TOK_ASSIGN sigspec sigspec EOL {
if (attrbuf.size() != 0)
- rtlil_frontend_ilang_yyerror("dangling attribute");
+ rtlil_frontend_yyerror("dangling attribute");
case_stack.back()->actions.push_back(RTLIL::SigSig(*$2, *$3));
delete $2;
delete $3;
@@ -438,19 +438,19 @@ sigspec:
} |
TOK_ID {
if (current_module->wire($1) == nullptr)
- rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: wire %s not found", $1).c_str());
$$ = new RTLIL::SigSpec(current_module->wire($1));
free($1);
} |
sigspec '[' TOK_INT ']' {
if ($3 >= $1->size() || $3 < 0)
- rtlil_frontend_ilang_yyerror("bit index out of range");
+ rtlil_frontend_yyerror("bit index out of range");
$$ = new RTLIL::SigSpec($1->extract($3));
delete $1;
} |
sigspec '[' TOK_INT ':' TOK_INT ']' {
if ($3 >= $1->size() || $3 < 0 || $3 < $5)
- rtlil_frontend_ilang_yyerror("invalid slice");
+ rtlil_frontend_yyerror("invalid slice");
$$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1));
delete $1;
} |
@@ -477,7 +477,7 @@ sigspec_list: sigspec_list_reversed {
conn_stmt:
TOK_CONNECT sigspec sigspec EOL {
if (attrbuf.size() != 0)
- rtlil_frontend_ilang_yyerror("dangling attribute");
+ rtlil_frontend_yyerror("dangling attribute");
current_module->connect(*$2, *$3);
delete $2;
delete $3;
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc
index 632dc51fd..7bbda9d49 100644
--- a/frontends/verific/verific.cc
+++ b/frontends/verific/verific.cc
@@ -54,7 +54,7 @@ USING_YOSYS_NAMESPACE
# error "Only Symbiotic EDA flavored Verific is supported. Please contact office@symbioticeda.com for commercial support for Yosys+Verific."
#endif
-#if SYMBIOTIC_VERIFIC_API_VERSION < 202006
+#if SYMBIOTIC_VERIFIC_API_VERSION < 20200801
# error "Please update your version of Symbiotic EDA flavored Verific."
#endif
@@ -199,12 +199,17 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
attributes.emplace(stringf("\\enum_value_%s", p+2), RTLIL::escape_id(k));
}
else if (nl->IsFromVhdl()) {
- // Expect "<binary>"
+ // Expect "<binary>" or plain <binary>
auto p = v;
if (p) {
- if (*p != '"')
- p = nullptr;
- else {
+ if (*p != '"') {
+ auto l = strlen(p);
+ auto q = (char*)malloc(l+1);
+ strncpy(q, p, l);
+ q[l] = '\0';
+ for(char *ptr = q; *ptr; ++ptr )*ptr = tolower(*ptr);
+ attributes.emplace(stringf("\\enum_value_%s", q), RTLIL::escape_id(k));
+ } else {
auto *q = p+1;
for (; *q != '"'; q++)
if (*q != '0' && *q != '1') {
@@ -213,16 +218,20 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
}
if (p && *(q+1) != '\0')
p = nullptr;
+
+ if (p != nullptr)
+ {
+ auto l = strlen(p);
+ auto q = (char*)malloc(l+1-2);
+ strncpy(q, p+1, l-2);
+ q[l-2] = '\0';
+ attributes.emplace(stringf("\\enum_value_%s", q), RTLIL::escape_id(k));
+ free(q);
+ }
}
}
if (p == nullptr)
- log_error("Expected TypeRange value '%s' to be of form \"<binary>\".\n", v);
- auto l = strlen(p);
- auto q = (char*)malloc(l+1-2);
- strncpy(q, p+1, l-2);
- q[l-2] = '\0';
- attributes.emplace(stringf("\\enum_value_%s", q), RTLIL::escape_id(k));
- free(q);
+ log_error("Expected TypeRange value '%s' to be of form \"<binary>\" or <binary>.\n", v);
}
}
}
@@ -2158,6 +2167,70 @@ struct VerificPass : public Pass {
log(" Dump the Verific netlist as a verilog file.\n");
log("\n");
log("\n");
+ log(" verific [-work <libname>] -pp [options] <filename> [<module>]..\n");
+ log("\n");
+ log("Pretty print design (or just module) to the specified file from the\n");
+ log("specified library. (default library when -work is not present: \"work\")\n");
+ log("\n");
+ log("Pretty print options:\n");
+ log("\n");
+ log(" -verilog\n");
+ log(" Save output for Verilog/SystemVerilog design modules (default).\n");
+ log("\n");
+ log(" -vhdl\n");
+ log(" Save output for VHDL design units.\n");
+ log("\n");
+ log("\n");
+ log(" verific -app <application>..\n");
+ log("\n");
+ log("Execute SEDA formal application on loaded Verilog files.\n");
+ log("\n");
+ log("Application options:\n");
+ log("\n");
+ log(" -blacklist <filename[:lineno]>\n");
+ log(" Do not run application on modules from files that match the filename\n");
+ log(" or filename and line number if provided in such format.\n");
+ log(" Parameter can also contain comma separated list of file locations.\n");
+ log("\n");
+ log(" -blfile <file>\n");
+ log(" Do not run application on locations specified in file, they can represent filename\n");
+ log(" or filename and location in file.\n");
+ log("\n");
+ log("Applications:\n");
+ log("\n");
+#ifdef YOSYS_ENABLE_VERIFIC
+ VerificFormalApplications vfa;
+ log("%s\n",vfa.GetHelp().c_str());
+#else
+ log(" WARNING: Applications only available in commercial build.\n");
+
+#endif
+ log("\n");
+ log("\n");
+ log(" verific -template <name> <top_module>..\n");
+ log("\n");
+ log("Generate template for specified top module of loaded design.\n");
+ log("\n");
+ log("Template options:\n");
+ log("\n");
+ log(" -out\n");
+ log(" Specifies output file for generated template, by default output is stdout\n");
+ log("\n");
+ log(" -chparam name value \n");
+ log(" Generate template using this parameter value. Otherwise default parameter\n");
+ log(" values will be used for templat generate functionality. This option\n");
+ log(" can be specified multiple times to override multiple parameters.\n");
+ log(" String values must be passed in double quotes (\").\n");
+ log("\n");
+ log("Templates:\n");
+ log("\n");
+#ifdef YOSYS_ENABLE_VERIFIC
+ VerificTemplateGenerator vfg;
+ log("%s\n",vfg.GetHelp().c_str());
+#else
+ log(" WARNING: Templates only available in commercial build.\n");
+ log("\n");
+#endif
log("Use Symbiotic EDA Suite if you need Yosys+Verifc.\n");
log("https://www.symbioticeda.com/seda-suite\n");
log("\n");
@@ -2202,6 +2275,9 @@ struct VerificPass : public Pass {
RuntimeFlags::SetVar("veri_preserve_assignments", 1);
RuntimeFlags::SetVar("vhdl_preserve_assignments", 1);
+ RuntimeFlags::SetVar("veri_preserve_comments",1);
+ //RuntimeFlags::SetVar("vhdl_preserve_comments",1);
+
// Workaround for VIPER #13851
RuntimeFlags::SetVar("veri_create_name_for_unnamed_gen_block", 1);
@@ -2399,6 +2475,161 @@ struct VerificPass : public Pass {
goto check_error;
}
+ if (argidx+1 < GetSize(args) && args[argidx] == "-app")
+ {
+ VerificFormalApplications vfa;
+ auto apps = vfa.GetApps();
+ std::string app = args[++argidx];
+ std::vector<std::string> blacklists;
+ if (apps.find(app) == apps.end())
+ log_cmd_error("Application '%s' does not exist.\n", app.c_str());
+
+ for (argidx++; argidx < GetSize(args); argidx++) {
+ if (args[argidx] == "-blacklist" && argidx+1 < GetSize(args)) {
+ std::string line = args[++argidx];
+ std::string p;
+ while (!(p = next_token(line, ",\t\r\n ")).empty())
+ blacklists.push_back(p);
+ continue;
+ }
+ if (args[argidx] == "-blfile" && argidx+1 < GetSize(args)) {
+ std::string fn = args[++argidx];
+ std::ifstream f(fn);
+ if (f.fail())
+ log_cmd_error("Can't open blacklist file '%s'!\n", fn.c_str());
+
+ std::string line,p;
+ while (std::getline(f, line)) {
+ while (!(p = next_token(line, ",\t\r\n ")).empty())
+ blacklists.push_back(p);
+ }
+ continue;
+ }
+ break;
+ }
+ if (argidx < GetSize(args))
+ cmd_error(args, argidx, "unknown option/parameter");
+ MapIter mi;
+ VeriModule *module ;
+ VeriLibrary *veri_lib = veri_file::GetLibrary(work.c_str(), 1);
+ log("Running formal application '%s'.\n", app.c_str());
+ FOREACH_VERILOG_MODULE_IN_LIBRARY(veri_lib, mi, module) {
+ vfa.Run(module,apps[app],blacklists);
+ }
+ goto check_error;
+ }
+
+ if (argidx < GetSize(args) && args[argidx] == "-pp")
+ {
+ const char* filename = nullptr;
+ const char* module = nullptr;
+ bool mode_vhdl = false;
+ for (argidx++; argidx < GetSize(args); argidx++) {
+ if (args[argidx] == "-vhdl") {
+ mode_vhdl = true;
+ continue;
+ }
+ if (args[argidx] == "-verilog") {
+ mode_vhdl = false;
+ continue;
+ }
+
+ if (args[argidx].compare(0, 1, "-") == 0) {
+ cmd_error(args, argidx, "unknown option");
+ goto check_error;
+ }
+
+ if (!filename) {
+ filename = args[argidx].c_str();
+ continue;
+ }
+ if (module)
+ log_cmd_error("Only one module can be specified.\n");
+ module = args[argidx].c_str();
+ }
+
+ if (argidx < GetSize(args))
+ cmd_error(args, argidx, "unknown option/parameter");
+
+ if (!filename)
+ log_cmd_error("Filname must be specified.\n");
+
+ if (mode_vhdl)
+ vhdl_file::PrettyPrint(filename, module, work.c_str());
+ else
+ veri_file::PrettyPrint(filename, module, work.c_str());
+ goto check_error;
+ }
+
+ if (argidx < GetSize(args) && args[argidx] == "-template")
+ {
+ if (!(argidx < GetSize(args)))
+ cmd_error(args, argidx, "No template type specified.\n");
+
+ VerificTemplateGenerator vfg;
+ auto gens = vfg.GetGenerators();
+ std::string app = args[++argidx];
+ if (gens.find(app) == gens.end())
+ log_cmd_error("Template generator '%s' does not exist.\n", app.c_str());
+ TemplateGenerator *generator = gens[app];
+ if (!(argidx < GetSize(args)))
+ cmd_error(args, argidx, "No top module specified.\n");
+
+ std::string module = args[++argidx];
+ VeriLibrary* veri_lib = veri_file::GetLibrary(work.c_str(), 1);
+ VeriModule *veri_module = veri_lib ? veri_lib->GetModule(module.c_str(), 1) : nullptr;
+ if (!veri_module) {
+ log_error("Can't find module/unit '%s'.\n", module.c_str());
+ }
+
+ log("Template '%s' is running for module '%s'.\n", app.c_str(),module.c_str());
+
+ Map parameters(STRING_HASH);
+ const char *out_filename = nullptr;
+
+ for (argidx++; argidx < GetSize(args); argidx++) {
+ if (generator->checkParams(args, argidx))
+ continue;
+ if (args[argidx] == "-chparam" && argidx+2 < GetSize(args)) {
+ const std::string &key = args[++argidx];
+ const std::string &value = args[++argidx];
+ unsigned new_insertion = parameters.Insert(key.c_str(), value.c_str(),
+ 1 /* force_overwrite */);
+ if (!new_insertion)
+ log_warning_noprefix("-chparam %s already specified: overwriting.\n", key.c_str());
+ continue;
+ }
+
+ if (args[argidx] == "-out" && argidx+1 < GetSize(args)) {
+ out_filename = args[++argidx].c_str();
+ continue;
+ }
+
+ break;
+ }
+ if (argidx < GetSize(args))
+ cmd_error(args, argidx, "unknown option/parameter");
+
+ const char *err = generator->validate();
+ if (err)
+ cmd_error(args, argidx, err);
+
+ std::string val = generator->generate(veri_module, &parameters);
+
+ FILE *of = stdout;
+ if (out_filename) {
+ of = fopen(out_filename, "w");
+ if (of == nullptr)
+ log_error("Can't open '%s' for writing: %s\n", out_filename, strerror(errno));
+ log("Writing output to '%s'\n",out_filename);
+ }
+ fprintf(of, "%s\n",val.c_str());
+ fflush(of);
+ if (of!=stdout)
+ fclose(of);
+ goto check_error;
+ }
+
if (GetSize(args) > argidx && args[argidx] == "-import")
{
std::set<Netlist*> nl_todo, nl_done;