aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Brewfile1
-rw-r--r--backends/smt2/smt2.cc2
-rw-r--r--frontends/aiger/aigerparse.cc2
-rw-r--r--frontends/ast/ast.cc13
-rw-r--r--frontends/ast/simplify.cc3
-rw-r--r--frontends/verilog/Makefile.inc2
-rw-r--r--frontends/verilog/verilog_frontend.cc20
-rw-r--r--frontends/verilog/verilog_frontend.h6
-rw-r--r--frontends/verilog/verilog_lexer.l28
-rw-r--r--frontends/verilog/verilog_parser.y83
-rw-r--r--manual/command-reference-manual.tex2
-rw-r--r--passes/cmds/Makefile.inc1
-rw-r--r--passes/cmds/exec.cc203
-rw-r--r--passes/fsm/fsm_extract.cc6
-rw-r--r--passes/sat/miter.cc116
-rw-r--r--passes/techmap/iopadmap.cc24
-rw-r--r--techlibs/ice40/cells_sim.v4
-rw-r--r--techlibs/ice40/synth_ice40.cc1
-rw-r--r--techlibs/xilinx/cells_xtra.py2
-rw-r--r--techlibs/xilinx/cells_xtra.v1
-rw-r--r--tests/arch/xilinx/tribuf.sh6
-rw-r--r--tests/svtypes/enum_simple.sv5
-rw-r--r--tests/svtypes/typedef_memory.sv2
-rw-r--r--tests/svtypes/typedef_memory_2.sv2
-rw-r--r--tests/svtypes/typedef_package.sv4
-rw-r--r--tests/svtypes/typedef_param.sv10
-rw-r--r--tests/svtypes/typedef_scopes.sv18
-rw-r--r--tests/svtypes/typedef_simple.sv10
-rw-r--r--tests/various/bug1781.ys33
-rw-r--r--tests/various/exec.ys6
-rw-r--r--tests/various/ice40_mince_abc9.ys17
31 files changed, 504 insertions, 129 deletions
diff --git a/Brewfile b/Brewfile
index 8465d86f9..2a985f09e 100644
--- a/Brewfile
+++ b/Brewfile
@@ -8,3 +8,4 @@ brew "pkg-config"
brew "python3"
brew "tcl-tk"
brew "xdot"
+brew "bash"
diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc
index ea252b6b9..628765831 100644
--- a/backends/smt2/smt2.cc
+++ b/backends/smt2/smt2.cc
@@ -1394,7 +1394,7 @@ struct Smt2Backend : public Backend {
log("\n");
log("For this proof we create the following template (test.tpl).\n");
log("\n");
- log(" ; we need QF_UFBV for this poof\n");
+ log(" ; we need QF_UFBV for this proof\n");
log(" (set-logic QF_UFBV)\n");
log("\n");
log(" ; insert the auto-generated code here\n");
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index a42569301..50c2a3ce6 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -444,7 +444,7 @@ void AigerReader::parse_xaiger()
}
}
else if (c == 'r') {
- uint32_t dataSize = parse_xaiger_literal(f);
+ uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
flopNum = parse_xaiger_literal(f);
log_debug("flopNum = %u\n", flopNum);
log_assert(dataSize == (flopNum+1) * sizeof(uint32_t));
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 650c7a937..632a4d4f9 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -1179,12 +1179,13 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
for (auto n : design->verilog_globals)
(*it)->children.push_back(n->clone());
- for (auto n : design->verilog_packages){
- for (auto o : n->children) {
+ // append nodes from previous packages using package-qualified names
+ for (auto &n : design->verilog_packages) {
+ for (auto &o : n->children) {
AstNode *cloned_node = o->clone();
- log("cloned node %s\n", type2str(cloned_node->type).c_str());
- if (cloned_node->type == AST_ENUM){
- for (auto e : cloned_node->children){
+ // log("cloned node %s\n", type2str(cloned_node->type).c_str());
+ if (cloned_node->type == AST_ENUM) {
+ for (auto &e : cloned_node->children) {
log_assert(e->type == AST_ENUM_ITEM);
e->str = n->str + std::string("::") + e->str.substr(1);
}
@@ -1220,6 +1221,8 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
design->add(process_module(*it, defer));
}
else if ((*it)->type == AST_PACKAGE) {
+ // process enum/other declarations
+ (*it)->simplify(true, false, false, 1, -1, false, false);
design->verilog_packages.push_back((*it)->clone());
}
else {
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 04c02d893..743c7e18f 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -432,7 +432,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM))
did_something = true;
if (node->type == AST_ENUM) {
- for (auto enode : node->children){
+ for (auto enode YS_ATTRIBUTE(unused) : node->children){
log_assert(enode->type==AST_ENUM_ITEM);
while (node->simplify(true, false, false, 1, -1, false, in_param))
did_something = true;
@@ -1811,6 +1811,7 @@ skip_dynamic_range_lvalue_expansion:;
newNode->children.push_back(assign_en);
AstNode *assertnode = new AstNode(type);
+ assertnode->location = location;
assertnode->str = str;
assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
diff --git a/frontends/verilog/Makefile.inc b/frontends/verilog/Makefile.inc
index 6a8462b41..cf9b9531e 100644
--- a/frontends/verilog/Makefile.inc
+++ b/frontends/verilog/Makefile.inc
@@ -10,7 +10,7 @@ frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y
frontends/verilog/verilog_parser.tab.hh: frontends/verilog/verilog_parser.tab.cc
-frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l
+frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l frontends/verilog/verilog_parser.tab.cc
$(Q) mkdir -p $(dir $@)
$(P) flex -o frontends/verilog/verilog_lexer.cc $<
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc
index 42eabc02d..f2c1c227f 100644
--- a/frontends/verilog/verilog_frontend.cc
+++ b/frontends/verilog/verilog_frontend.cc
@@ -47,6 +47,22 @@ static void error_on_dpi_function(AST::AstNode *node)
error_on_dpi_function(child);
}
+static void add_package_types(std::map<std::string, AST::AstNode *> &user_types, std::vector<AST::AstNode *> &package_list)
+{
+ // prime the parser's user type lookup table with the package qualified names
+ // of typedefed names in the packages seen so far.
+ user_types.clear();
+ for (const auto &pkg : package_list) {
+ log_assert(pkg->type==AST::AST_PACKAGE);
+ for (const auto &node: pkg->children) {
+ if (node->type == AST::AST_TYPEDEF) {
+ std::string s = pkg->str + "::" + node->str.substr(1);
+ user_types[s] = node;
+ }
+ }
+ }
+}
+
struct VerilogFrontend : public Frontend {
VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { }
void help() YS_OVERRIDE
@@ -450,6 +466,9 @@ struct VerilogFrontend : public Frontend {
lexin = new std::istringstream(code_after_preproc);
}
+ // make package typedefs available to parser
+ add_package_types(pkg_user_types, design->verilog_packages);
+
frontend_verilog_yyset_lineno(1);
frontend_verilog_yyrestart(NULL);
frontend_verilog_yyparse();
@@ -468,6 +487,7 @@ struct VerilogFrontend : public Frontend {
AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches,
flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
+
if (!flag_nopp)
delete lexin;
diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h
index a2e06f0e4..73ea51e6c 100644
--- a/frontends/verilog/verilog_frontend.h
+++ b/frontends/verilog/verilog_frontend.h
@@ -45,6 +45,12 @@ namespace VERILOG_FRONTEND
// this function converts a Verilog constant to an AST_CONSTANT node
AST::AstNode *const2ast(std::string code, char case_type = 0, bool warn_z = false);
+ // names of locally typedef'ed types
+ extern std::map<std::string, AST::AstNode*> user_types;
+
+ // names of package typedef'ed types
+ extern std::map<std::string, AST::AstNode*> pkg_user_types;
+
// state of `default_nettype
extern bool default_nettype_wire;
diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l
index d22a18458..74e8dce7f 100644
--- a/frontends/verilog/verilog_lexer.l
+++ b/frontends/verilog/verilog_lexer.l
@@ -372,9 +372,33 @@ supply1 { return TOK_SUPPLY1; }
"$signed" { return TOK_TO_SIGNED; }
"$unsigned" { return TOK_TO_UNSIGNED; }
+[a-zA-Z_][a-zA-Z0-9_]*::[a-zA-Z_$][a-zA-Z0-9_$]* {
+ // package qualifier
+ auto s = std::string("\\") + yytext;
+ if (pkg_user_types.count(s) > 0) {
+ // found it
+ yylval->string = new std::string(s);
+ return TOK_USER_TYPE;
+ }
+ else {
+ // backup before :: just return first part
+ size_t len = strchr(yytext, ':') - yytext;
+ yyless(len);
+ yylval->string = new std::string(std::string("\\") + yytext);
+ return TOK_ID;
+ }
+}
+
[a-zA-Z_$][a-zA-Z0-9_$]* {
- yylval->string = new std::string(std::string("\\") + yytext);
- return TOK_ID;
+ auto s = std::string("\\") + yytext;
+ if (user_types.count(s) > 0) {
+ yylval->string = new std::string(s);
+ return TOK_USER_TYPE;
+ }
+ else {
+ yylval->string = new std::string(std::string("\\") + yytext);
+ return TOK_ID;
+ }
}
[a-zA-Z_$][a-zA-Z0-9_$\.]* {
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index d04b32509..f7e3afd13 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -54,6 +54,8 @@ namespace VERILOG_FRONTEND {
std::map<std::string, AstNode*> *attr_list, default_attr_list;
std::stack<std::map<std::string, AstNode*> *> attr_list_stack;
std::map<std::string, AstNode*> *albuf;
+ std::map<std::string, AstNode*> user_types;
+ std::map<std::string, AstNode*> pkg_user_types;
std::vector<AstNode*> ast_stack;
struct AstNode *astbuf1, *astbuf2, *astbuf3;
struct AstNode *current_function_or_task;
@@ -125,6 +127,26 @@ struct specify_rise_fall {
specify_triple fall;
};
+static void addTypedefNode(std::string *name, AstNode *node)
+{
+ log_assert(node);
+ // seems to be support for local scoped typedefs in simplify()
+ // and tests redefine types.
+ //if (user_types.count(*name) > 0) {
+ // frontend_verilog_yyerror("Type already defined.");
+ //}
+ auto *tnode = new AstNode(AST_TYPEDEF, node);
+ tnode->str = *name;
+ user_types[*name] = tnode;
+ if (current_ast_mod && current_ast_mod->type == AST_PACKAGE) {
+ // typedef inside a package so we need the qualified name
+ auto qname = current_ast_mod->str + "::" + (*name).substr(1);
+ pkg_user_types[qname] = tnode;
+ }
+ delete name;
+ ast_stack.back()->children.push_back(tnode);
+}
+
static AstNode *makeRange(int msb = 31, int lsb = 0, bool isSigned = true)
{
auto range = new AstNode(AST_RANGE);
@@ -167,6 +189,7 @@ static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned =
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
%token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_MSG_TASKS
%token <string> TOK_BASE TOK_BASED_CONSTVAL TOK_UNBASED_UNSIZED_CONSTVAL
+%token <string> TOK_USER_TYPE
%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
@@ -190,6 +213,7 @@ static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned =
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number
+%type <string> type_name
%type <ast> opt_enum_init
%type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff
%type <al> attr case_attr
@@ -330,7 +354,9 @@ hierarchical_id:
};
hierarchical_type_id:
- '(' hierarchical_id ')' { $$ = $2; };
+ TOK_USER_TYPE
+ | '(' TOK_USER_TYPE ')' { $$ = $2; } // non-standard grammar
+ ;
module:
attr TOK_MODULE TOK_ID {
@@ -352,6 +378,7 @@ module:
ast_stack.pop_back();
log_assert(ast_stack.size() == 1);
current_ast_mod = NULL;
+ user_types.clear();
};
module_para_opt:
@@ -465,6 +492,7 @@ package:
} ';' package_body TOK_ENDPACKAGE {
ast_stack.pop_back();
current_ast_mod = NULL;
+ user_types.clear();
};
package_body:
@@ -494,6 +522,7 @@ interface:
ast_stack.pop_back();
log_assert(ast_stack.size() == 1);
current_ast_mod = NULL;
+ user_types.clear();
};
interface_body:
@@ -1591,8 +1620,12 @@ assign_expr:
ast_stack.back()->children.push_back(node);
};
+type_name: TOK_ID // first time seen
+ | TOK_USER_TYPE // redefinition
+ ;
+
typedef_decl:
- TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' {
+ TOK_TYPEDEF wire_type range type_name range_or_multirange ';' {
astbuf1 = $2;
astbuf2 = $3;
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
@@ -1625,13 +1658,10 @@ typedef_decl:
}
astbuf1->children.push_back(rangeNode);
}
-
- ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
- ast_stack.back()->children.back()->str = *$4;
+ addTypedefNode($4, astbuf1);
} |
- TOK_TYPEDEF enum_type TOK_ID ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
- ast_stack.back()->children.back()->str = *$3;
+ TOK_TYPEDEF enum_type type_name ';' {
+ addTypedefNode($3, astbuf1);
}
;
@@ -1955,6 +1985,7 @@ assert:
delete $5;
} else {
AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -1967,6 +1998,7 @@ assert:
delete $5;
} else {
AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -1979,6 +2011,7 @@ assert:
delete $6;
} else {
AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6);
+ SET_AST_NODE_LOC(node, @1, @7);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -1991,6 +2024,7 @@ assert:
delete $6;
} else {
AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6);
+ SET_AST_NODE_LOC(node, @1, @7);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -2000,6 +2034,7 @@ assert:
} |
opt_sva_label TOK_COVER opt_property '(' expr ')' ';' {
AstNode *node = new AstNode(AST_COVER, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
if ($1 != nullptr) {
node->str = *$1;
delete $1;
@@ -2008,6 +2043,7 @@ assert:
} |
opt_sva_label TOK_COVER opt_property '(' ')' ';' {
AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
+ SET_AST_NODE_LOC(node, @1, @5);
if ($1 != nullptr) {
node->str = *$1;
delete $1;
@@ -2016,6 +2052,7 @@ assert:
} |
opt_sva_label TOK_COVER ';' {
AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
+ SET_AST_NODE_LOC(node, @1, @2);
if ($1 != nullptr) {
node->str = *$1;
delete $1;
@@ -2027,6 +2064,7 @@ assert:
delete $5;
} else {
AstNode *node = new AstNode(AST_ASSUME, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -2041,6 +2079,7 @@ assert:
delete $6;
} else {
AstNode *node = new AstNode(AST_FAIR, $6);
+ SET_AST_NODE_LOC(node, @1, @7);
if ($1 != nullptr)
node->str = *$1;
ast_stack.back()->children.push_back(node);
@@ -2053,35 +2092,45 @@ assert:
assert_property:
opt_sva_label TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5));
+ AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
opt_sva_label TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
+ AstNode *node = new AstNode(AST_ASSUME, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
opt_sva_label TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6));
+ AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6);
+ SET_AST_NODE_LOC(node, @1, @7);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
opt_sva_label TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
+ AstNode *node = new AstNode(AST_FAIR, $6);
+ SET_AST_NODE_LOC(node, @1, @7);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
}
} |
opt_sva_label TOK_COVER TOK_PROPERTY '(' expr ')' ';' {
- ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5));
+ AstNode *node = new AstNode(AST_COVER, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
@@ -2091,7 +2140,9 @@ assert_property:
if (norestrict_mode) {
delete $5;
} else {
- ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
+ AstNode *node = new AstNode(AST_ASSUME, $5);
+ SET_AST_NODE_LOC(node, @1, @6);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
@@ -2102,7 +2153,9 @@ assert_property:
if (norestrict_mode) {
delete $6;
} else {
- ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
+ AstNode *node = new AstNode(AST_FAIR, $6);
+ SET_AST_NODE_LOC(node, @1, @7);
+ ast_stack.back()->children.push_back(node);
if ($1 != nullptr) {
ast_stack.back()->children.back()->str = *$1;
delete $1;
diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex
index bed6326e2..4925defe3 100644
--- a/manual/command-reference-manual.tex
+++ b/manual/command-reference-manual.tex
@@ -5350,7 +5350,7 @@ never transition from a non-zero value to a zero value.
For this proof we create the following template (test.tpl).
- ; we need QF_UFBV for this poof
+ ; we need QF_UFBV for this proof
(set-logic QF_UFBV)
; insert the auto-generated code here
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index 20b38bf8e..60f20fa6d 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -1,4 +1,5 @@
+OBJS += passes/cmds/exec.o
OBJS += passes/cmds/add.o
OBJS += passes/cmds/delete.o
OBJS += passes/cmds/design.o
diff --git a/passes/cmds/exec.cc b/passes/cmds/exec.cc
new file mode 100644
index 000000000..399cb0ebb
--- /dev/null
+++ b/passes/cmds/exec.cc
@@ -0,0 +1,203 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 - 2020 Claire Wolf <claire@symbioticeda.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.
+ *
+ */
+
+#include "kernel/register.h"
+#include "kernel/log.h"
+#include <cstdio>
+
+#if defined(_WIN32)
+# define WIFEXITED(x) 1
+# define WIFSIGNALED(x) 0
+# define WIFSTOPPED(x) 0
+# define WEXITSTATUS(x) ((x) & 0xff)
+# define WTERMSIG(x) SIGTERM
+#else
+# include <sys/wait.h>
+#endif
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct ExecPass : public Pass {
+ ExecPass() : Pass("exec", "execute commands in the operating system shell") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" exec [options] -- [command]\n");
+ log("\n");
+ log("Execute a command in the operating system shell. All supplied arguments are\n");
+ log("concatenated and passed as a command to popen(3). Whitespace is not guaranteed\n");
+ log("to be preserved, even if quoted. stdin and stderr are not connected, while stdout is\n");
+ log("logged unless the \"-q\" option is specified.\n");
+ log("\n");
+ log("\n");
+ log(" -q\n");
+ log(" Suppress stdout and stderr from subprocess\n");
+ log("\n");
+ log(" -expect-return <int>\n");
+ log(" Generate an error if popen() does not return specified value.\n");
+ log(" May only be specified once; the final specified value is controlling\n");
+ log(" if specified multiple times.\n");
+ log("\n");
+ log(" -expect-stdout <regex>\n");
+ log(" Generate an error if the specified regex does not match any line\n");
+ log(" in subprocess's stdout. May be specified multiple times.\n");
+ log("\n");
+ log(" -not-expect-stdout <regex>\n");
+ log(" Generate an error if the specified regex matches any line\n");
+ log(" in subprocess's stdout. May be specified multiple times.\n");
+ log("\n");
+ log("\n");
+ log(" Example: exec -q -expect-return 0 -- echo \"bananapie\" | grep \"nana\"\n");
+ log("\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ std::string cmd = "";
+ char buf[1024] = {};
+ std::string linebuf = "";
+ bool flag_cmd = false;
+ bool flag_quiet = false;
+ bool flag_expect_return = false;
+ int expect_return_value = 0;
+ bool flag_expect_stdout = false;
+ struct expect_stdout_elem {
+ bool matched;
+ bool polarity; //true: this regex must match at least one line
+ //false: this regex must not match any line
+ std::string str;
+ YS_REGEX_TYPE re;
+
+ expect_stdout_elem() : matched(false), polarity(true), str(), re(){};
+ };
+ std::vector<expect_stdout_elem> expect_stdout;
+
+ if(args.size() == 0)
+ log_cmd_error("No command provided.\n");
+
+ for(size_t argidx = 1; argidx < args.size(); ++argidx) {
+ if (flag_cmd) {
+ cmd += args[argidx] + (argidx != (args.size() - 1)? " " : "");
+ } else {
+ if (args[argidx] == "--")
+ flag_cmd = true;
+ else if (args[argidx] == "-q")
+ flag_quiet = true;
+ else if (args[argidx] == "-expect-return") {
+ flag_expect_return = true;
+ ++argidx;
+ if (argidx >= args.size())
+ log_cmd_error("No expected return value specified.\n");
+
+ expect_return_value = atoi(args[argidx].c_str());
+ } else if (args[argidx] == "-expect-stdout") {
+ flag_expect_stdout = true;
+ ++argidx;
+ if (argidx >= args.size())
+ log_cmd_error("No expected regular expression specified.\n");
+
+ try{
+ expect_stdout_elem x;
+ x.str = args[argidx];
+ x.re = YS_REGEX_COMPILE(args[argidx]);
+ expect_stdout.push_back(x);
+ } catch (const YS_REGEX_NS::regex_error& e) {
+ log_cmd_error("Error in regex expression '%s' !\n", args[argidx].c_str());
+ }
+ } else if (args[argidx] == "-not-expect-stdout") {
+ flag_expect_stdout = true;
+ ++argidx;
+ if (argidx >= args.size())
+ log_cmd_error("No expected regular expression specified.\n");
+
+ try{
+ expect_stdout_elem x;
+ x.str = args[argidx];
+ x.re = YS_REGEX_COMPILE(args[argidx]);
+ x.polarity = false;
+ expect_stdout.push_back(x);
+ } catch (const YS_REGEX_NS::regex_error& e) {
+ log_cmd_error("Error in regex expression '%s' !\n", args[argidx].c_str());
+ }
+
+ } else
+ log_cmd_error("Unknown option \"%s\" or \"--\" doesn\'t precede command.", args[argidx].c_str());
+ }
+ }
+
+ log_header(design, "Executing command \"%s\".\n", cmd.c_str());
+ log_push();
+
+ fflush(stdout);
+ bool keep_reading = true;
+ int status = 0;
+ int retval = 0;
+
+#ifndef EMSCRIPTEN
+ FILE *f = popen(cmd.c_str(), "r");
+ if (f == nullptr)
+ log_cmd_error("errno %d after popen() returned NULL.\n", errno);
+ while (keep_reading) {
+ keep_reading = (fgets(buf, sizeof(buf), f) != nullptr);
+ linebuf += buf;
+ memset(buf, 0, sizeof(buf));
+
+ auto pos = linebuf.find('\n');
+ while (pos != std::string::npos) {
+ std::string line = linebuf.substr(0, pos);
+ linebuf.erase(0, pos + 1);
+ if (!flag_quiet)
+ log("%s\n", line.c_str());
+
+ if (flag_expect_stdout)
+ for(auto &x : expect_stdout)
+ if (YS_REGEX_NS::regex_search(line, x.re))
+ x.matched = true;
+
+ pos = linebuf.find('\n');
+ }
+ }
+ status = pclose(f);
+#endif
+
+ if(WIFEXITED(status)) {
+ retval = WEXITSTATUS(status);
+ }
+ else if(WIFSIGNALED(status)) {
+ retval = WTERMSIG(status);
+ }
+ else if(WIFSTOPPED(status)) {
+ retval = WSTOPSIG(status);
+ }
+
+ if (flag_expect_return && retval != expect_return_value)
+ log_cmd_error("Return value %d did not match expected return value %d.\n", retval, expect_return_value);
+
+ if (flag_expect_stdout)
+ for (auto &x : expect_stdout)
+ if (x.polarity ^ x.matched)
+ log_cmd_error("Command stdout did%s have a line matching given regex \"%s\".\n", (x.polarity? " not" : ""), x.str.c_str());
+
+ log_pop();
+ }
+} ExecPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc
index a85c3bec0..0f7b4d106 100644
--- a/passes/fsm/fsm_extract.cc
+++ b/passes/fsm/fsm_extract.cc
@@ -422,11 +422,7 @@ struct FsmExtractPass : public Pass {
log_header(design, "Executing FSM_EXTRACT pass (extracting FSM from design).\n");
extra_args(args, 1, design);
- CellTypes ct;
- ct.setup_internals();
- ct.setup_internals_mem();
- ct.setup_stdcells();
- ct.setup_stdcells_mem();
+ CellTypes ct(design);
for (auto &mod_it : design->modules_)
{
diff --git a/passes/sat/miter.cc b/passes/sat/miter.cc
index 49ef40061..742433935 100644
--- a/passes/sat/miter.cc
+++ b/passes/sat/miter.cc
@@ -66,50 +66,48 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
RTLIL::IdString gate_name = RTLIL::escape_id(args[argidx++]);
RTLIL::IdString miter_name = RTLIL::escape_id(args[argidx++]);
- if (design->modules_.count(gold_name) == 0)
+ if (design->module(gold_name) == nullptr)
log_cmd_error("Can't find gold module %s!\n", gold_name.c_str());
- if (design->modules_.count(gate_name) == 0)
+ if (design->module(gate_name) == nullptr)
log_cmd_error("Can't find gate module %s!\n", gate_name.c_str());
- if (design->modules_.count(miter_name) != 0)
+ if (design->module(miter_name) != nullptr)
log_cmd_error("There is already a module %s!\n", miter_name.c_str());
- RTLIL::Module *gold_module = design->modules_.at(gold_name);
- RTLIL::Module *gate_module = design->modules_.at(gate_name);
+ RTLIL::Module *gold_module = design->module(gold_name);
+ RTLIL::Module *gate_module = design->module(gate_name);
- for (auto &it : gold_module->wires_) {
- RTLIL::Wire *w1 = it.second, *w2;
- if (w1->port_id == 0)
+ for (auto gold_wire : gold_module->wires()) {
+ if (gold_wire->port_id == 0)
continue;
- if (gate_module->wires_.count(it.second->name) == 0)
+ RTLIL::Wire *gate_wire = gate_module->wire(gold_wire->name);
+ if (gate_wire == nullptr)
goto match_gold_port_error;
- w2 = gate_module->wires_.at(it.second->name);
- if (w1->port_input != w2->port_input)
+ if (gold_wire->port_input != gate_wire->port_input)
goto match_gold_port_error;
- if (w1->port_output != w2->port_output)
+ if (gold_wire->port_output != gate_wire->port_output)
goto match_gold_port_error;
- if (w1->width != w2->width)
+ if (gold_wire->width != gate_wire->width)
goto match_gold_port_error;
continue;
match_gold_port_error:
- log_cmd_error("No matching port in gate module was found for %s!\n", it.second->name.c_str());
+ log_cmd_error("No matching port in gate module was found for %s!\n", gold_wire->name.c_str());
}
- for (auto &it : gate_module->wires_) {
- RTLIL::Wire *w1 = it.second, *w2;
- if (w1->port_id == 0)
+ for (auto gate_wire : gate_module->wires()) {
+ if (gate_wire->port_id == 0)
continue;
- if (gold_module->wires_.count(it.second->name) == 0)
+ RTLIL::Wire *gold_wire = gold_module->wire(gate_wire->name);
+ if (gold_wire == nullptr)
goto match_gate_port_error;
- w2 = gold_module->wires_.at(it.second->name);
- if (w1->port_input != w2->port_input)
+ if (gate_wire->port_input != gold_wire->port_input)
goto match_gate_port_error;
- if (w1->port_output != w2->port_output)
+ if (gate_wire->port_output != gold_wire->port_output)
goto match_gate_port_error;
- if (w1->width != w2->width)
+ if (gate_wire->width != gold_wire->width)
goto match_gate_port_error;
continue;
match_gate_port_error:
- log_cmd_error("No matching port in gold module was found for %s!\n", it.second->name.c_str());
+ log_cmd_error("No matching port in gold module was found for %s!\n", gate_wire->name.c_str());
}
log("Creating miter cell \"%s\" with gold cell \"%s\" and gate cell \"%s\".\n", RTLIL::id2cstr(miter_name), RTLIL::id2cstr(gold_name), RTLIL::id2cstr(gate_name));
@@ -123,73 +121,71 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
RTLIL::SigSpec all_conditions;
- for (auto &it : gold_module->wires_)
+ for (auto gold_wire : gold_module->wires())
{
- RTLIL::Wire *w1 = it.second;
-
- if (w1->port_input)
+ if (gold_wire->port_input)
{
- RTLIL::Wire *w2 = miter_module->addWire("\\in_" + RTLIL::unescape_id(w1->name), w1->width);
- w2->port_input = true;
+ RTLIL::Wire *w = miter_module->addWire("\\in_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width);
+ w->port_input = true;
- gold_cell->setPort(w1->name, w2);
- gate_cell->setPort(w1->name, w2);
+ gold_cell->setPort(gold_wire->name, w);
+ gate_cell->setPort(gold_wire->name, w);
}
- if (w1->port_output)
+ if (gold_wire->port_output)
{
- RTLIL::Wire *w2_gold = miter_module->addWire("\\gold_" + RTLIL::unescape_id(w1->name), w1->width);
- w2_gold->port_output = flag_make_outputs;
+ RTLIL::Wire *w_gold = miter_module->addWire("\\gold_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width);
+ w_gold->port_output = flag_make_outputs;
- RTLIL::Wire *w2_gate = miter_module->addWire("\\gate_" + RTLIL::unescape_id(w1->name), w1->width);
- w2_gate->port_output = flag_make_outputs;
+ RTLIL::Wire *w_gate = miter_module->addWire("\\gate_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width);
+ w_gate->port_output = flag_make_outputs;
- gold_cell->setPort(w1->name, w2_gold);
- gate_cell->setPort(w1->name, w2_gate);
+ gold_cell->setPort(gold_wire->name, w_gold);
+ gate_cell->setPort(gold_wire->name, w_gate);
RTLIL::SigSpec this_condition;
if (flag_ignore_gold_x)
{
- RTLIL::SigSpec gold_x = miter_module->addWire(NEW_ID, w2_gold->width);
- for (int i = 0; i < w2_gold->width; i++) {
+ RTLIL::SigSpec gold_x = miter_module->addWire(NEW_ID, w_gold->width);
+ for (int i = 0; i < w_gold->width; i++) {
RTLIL::Cell *eqx_cell = miter_module->addCell(NEW_ID, "$eqx");
eqx_cell->parameters["\\A_WIDTH"] = 1;
eqx_cell->parameters["\\B_WIDTH"] = 1;
eqx_cell->parameters["\\Y_WIDTH"] = 1;
eqx_cell->parameters["\\A_SIGNED"] = 0;
eqx_cell->parameters["\\B_SIGNED"] = 0;
- eqx_cell->setPort("\\A", RTLIL::SigSpec(w2_gold, i));
+ eqx_cell->setPort("\\A", RTLIL::SigSpec(w_gold, i));
eqx_cell->setPort("\\B", RTLIL::State::Sx);
eqx_cell->setPort("\\Y", gold_x.extract(i, 1));
}
- RTLIL::SigSpec gold_masked = miter_module->addWire(NEW_ID, w2_gold->width);
- RTLIL::SigSpec gate_masked = miter_module->addWire(NEW_ID, w2_gate->width);
+ RTLIL::SigSpec gold_masked = miter_module->addWire(NEW_ID, w_gold->width);
+ RTLIL::SigSpec gate_masked = miter_module->addWire(NEW_ID, w_gate->width);
RTLIL::Cell *or_gold_cell = miter_module->addCell(NEW_ID, "$or");
- or_gold_cell->parameters["\\A_WIDTH"] = w2_gold->width;
- or_gold_cell->parameters["\\B_WIDTH"] = w2_gold->width;
- or_gold_cell->parameters["\\Y_WIDTH"] = w2_gold->width;
+ or_gold_cell->parameters["\\A_WIDTH"] = w_gold->width;
+ or_gold_cell->parameters["\\B_WIDTH"] = w_gold->width;
+ or_gold_cell->parameters["\\Y_WIDTH"] = w_gold->width;
or_gold_cell->parameters["\\A_SIGNED"] = 0;
or_gold_cell->parameters["\\B_SIGNED"] = 0;
- or_gold_cell->setPort("\\A", w2_gold);
+ or_gold_cell->setPort("\\A", w_gold);
or_gold_cell->setPort("\\B", gold_x);
or_gold_cell->setPort("\\Y", gold_masked);
RTLIL::Cell *or_gate_cell = miter_module->addCell(NEW_ID, "$or");
- or_gate_cell->parameters["\\A_WIDTH"] = w2_gate->width;
- or_gate_cell->parameters["\\B_WIDTH"] = w2_gate->width;
- or_gate_cell->parameters["\\Y_WIDTH"] = w2_gate->width;
+ or_gate_cell->parameters["\\A_WIDTH"] = w_gate->width;
+ or_gate_cell->parameters["\\B_WIDTH"] = w_gate->width;
+ or_gate_cell->parameters["\\Y_WIDTH"] = w_gate->width;
or_gate_cell->parameters["\\A_SIGNED"] = 0;
or_gate_cell->parameters["\\B_SIGNED"] = 0;
- or_gate_cell->setPort("\\A", w2_gate);
+ or_gate_cell->setPort("\\A", w_gate);
or_gate_cell->setPort("\\B", gold_x);
or_gate_cell->setPort("\\Y", gate_masked);
RTLIL::Cell *eq_cell = miter_module->addCell(NEW_ID, "$eqx");
- eq_cell->parameters["\\A_WIDTH"] = w2_gold->width;
- eq_cell->parameters["\\B_WIDTH"] = w2_gate->width;
+ eq_cell->parameters["\\A_WIDTH"] = w_gold->width;
+ eq_cell->parameters["\\B_WIDTH"] = w_gate->width;
eq_cell->parameters["\\Y_WIDTH"] = 1;
eq_cell->parameters["\\A_SIGNED"] = 0;
eq_cell->parameters["\\B_SIGNED"] = 0;
@@ -201,20 +197,20 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
else
{
RTLIL::Cell *eq_cell = miter_module->addCell(NEW_ID, "$eqx");
- eq_cell->parameters["\\A_WIDTH"] = w2_gold->width;
- eq_cell->parameters["\\B_WIDTH"] = w2_gate->width;
+ eq_cell->parameters["\\A_WIDTH"] = w_gold->width;
+ eq_cell->parameters["\\B_WIDTH"] = w_gate->width;
eq_cell->parameters["\\Y_WIDTH"] = 1;
eq_cell->parameters["\\A_SIGNED"] = 0;
eq_cell->parameters["\\B_SIGNED"] = 0;
- eq_cell->setPort("\\A", w2_gold);
- eq_cell->setPort("\\B", w2_gate);
+ eq_cell->setPort("\\A", w_gold);
+ eq_cell->setPort("\\B", w_gate);
eq_cell->setPort("\\Y", miter_module->addWire(NEW_ID));
this_condition = eq_cell->getPort("\\Y");
}
if (flag_make_outcmp)
{
- RTLIL::Wire *w_cmp = miter_module->addWire("\\cmp_" + RTLIL::unescape_id(w1->name));
+ RTLIL::Wire *w_cmp = miter_module->addWire("\\cmp_" + RTLIL::unescape_id(gold_wire->name));
w_cmp->port_output = true;
miter_module->connect(RTLIL::SigSig(w_cmp, this_condition));
}
@@ -285,9 +281,9 @@ void create_miter_assert(struct Pass *that, std::vector<std::string> args, RTLIL
IdString module_name = RTLIL::escape_id(args[argidx++]);
IdString miter_name = argidx < args.size() ? RTLIL::escape_id(args[argidx++]) : "";
- if (design->modules_.count(module_name) == 0)
+ if (design->module(module_name) == nullptr)
log_cmd_error("Can't find module %s!\n", module_name.c_str());
- if (!miter_name.empty() && design->modules_.count(miter_name) != 0)
+ if (!miter_name.empty() && design->module(miter_name) != nullptr)
log_cmd_error("There is already a module %s!\n", miter_name.c_str());
Module *module = design->module(module_name);
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index f63012d1a..8b1862237 100644
--- a/passes/techmap/iopadmap.cc
+++ b/passes/techmap/iopadmap.cc
@@ -308,7 +308,9 @@ struct IopadmapPass : public Pass {
{
log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, tinoutpad_celltype.c_str());
- Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(tinoutpad_celltype));
+ Cell *cell = module->addCell(
+ module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)),
+ RTLIL::escape_id(tinoutpad_celltype));
cell->setPort(RTLIL::escape_id(tinoutpad_portname_oe), en_sig);
cell->attributes[ID::keep] = RTLIL::Const(1);
@@ -328,7 +330,9 @@ struct IopadmapPass : public Pass {
} else {
log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, toutpad_celltype.c_str());
- Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(toutpad_celltype));
+ Cell *cell = module->addCell(
+ module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)),
+ RTLIL::escape_id(toutpad_celltype));
cell->setPort(RTLIL::escape_id(toutpad_portname_oe), en_sig);
cell->setPort(RTLIL::escape_id(toutpad_portname_i), data_sig);
@@ -406,7 +410,9 @@ struct IopadmapPass : public Pass {
SigBit wire_bit(wire, i);
- RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype));
+ RTLIL::Cell *cell = module->addCell(
+ module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))),
+ RTLIL::escape_id(celltype));
cell->setPort(RTLIL::escape_id(portname_int), wire_bit);
if (!portname_pad.empty())
@@ -420,12 +426,16 @@ struct IopadmapPass : public Pass {
}
else
{
- RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype));
+ RTLIL::Cell *cell = module->addCell(
+ module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))),
+ RTLIL::escape_id(celltype));
cell->setPort(RTLIL::escape_id(portname_int), RTLIL::SigSpec(wire));
if (!portname_pad.empty()) {
RTLIL::Wire *new_wire = NULL;
- new_wire = module->addWire(NEW_ID, wire);
+ new_wire = module->addWire(
+ module->uniquify(stringf("$iopadmap$%s", log_id(wire))),
+ wire);
module->swap_names(new_wire, wire);
wire->attributes.clear();
cell->setPort(RTLIL::escape_id(portname_pad), RTLIL::SigSpec(new_wire));
@@ -446,7 +456,9 @@ struct IopadmapPass : public Pass {
for (auto &it : rewrite_bits) {
RTLIL::Wire *wire = it.first;
- RTLIL::Wire *new_wire = module->addWire(NEW_ID, wire);
+ RTLIL::Wire *new_wire = module->addWire(
+ module->uniquify(stringf("$iopadmap$%s", log_id(wire))),
+ wire);
module->swap_names(new_wire, wire);
wire->attributes.clear();
for (int i = 0; i < wire->width; i++)
diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index aa1d7aa86..6a0e3031e 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -2382,9 +2382,9 @@ module SB_SPRAM256KA (
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13167
//$setup(negedge STANDBY, posedge CLOCK, 1715);
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13206
- $setup(WREN, posedge CLK, 289);
+ $setup(WREN, posedge CLOCK, 289);
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13207-L13222
- (posedge RCLK => (DATAOUT : 16'bx)) = 1821;
+ (posedge CLOCK => (DATAOUT : 16'bx)) = 1821;
// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13223-L13238
(posedge SLEEP => (DATAOUT : 16'b0)) = 1099;
endspecify
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index 80bd05a84..b8aedaadf 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -345,6 +345,7 @@ struct SynthIce40Pass : public ScriptPass
if (min_ce_use >= 0) {
run("opt_merge");
run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
+ run("simplemap t:$dff");
}
run("techmap -D NO_LUT -D NO_ADDER -map +/ice40/cells_map.v");
run("opt_expr -mux_undef");
diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py
index 749b1e0a7..f086291ab 100644
--- a/techlibs/xilinx/cells_xtra.py
+++ b/techlibs/xilinx/cells_xtra.py
@@ -302,7 +302,7 @@ CELLS = [
Cell('IOBUF_DCIEN', port_attrs={'IO': ['iopad_external_pin']}),
Cell('IOBUF_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin']}),
Cell('IOBUFE3', port_attrs={'IO': ['iopad_external_pin']}),
- Cell('IOBUFDS', port_attrs={'IO': ['iopad_external_pin']}),
+ Cell('IOBUFDS', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
Cell('IOBUFDS_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
Cell('IOBUFDS_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
Cell('IOBUFDS_DIFF_OUT', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index ac4ad4e36..3021f6b5a 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -7072,6 +7072,7 @@ module IOBUFDS (...);
output O;
(* iopad_external_pin *)
inout IO;
+ (* iopad_external_pin *)
inout IOB;
input I;
input T;
diff --git a/tests/arch/xilinx/tribuf.sh b/tests/arch/xilinx/tribuf.sh
index 636aed12a..bd44395cb 100644
--- a/tests/arch/xilinx/tribuf.sh
+++ b/tests/arch/xilinx/tribuf.sh
@@ -1,5 +1,5 @@
-! ../../../yosys ../common/tribuf.v -qp "synth_xilinx"
-../../../yosys ../common/tribuf.v -qp "synth_xilinx -iopad; \
+! ../../../yosys -qp "synth_xilinx" ../common/tribuf.v
+../../../yosys -qp "synth_xilinx -iopad; \
select -assert-count 2 t:IBUF; \
select -assert-count 1 t:INV; \
-select -assert-count 1 t:OBUFT"
+select -assert-count 1 t:OBUFT" ../common/tribuf.v
diff --git a/tests/svtypes/enum_simple.sv b/tests/svtypes/enum_simple.sv
index ccaf50da0..4e4d5871c 100644
--- a/tests/svtypes/enum_simple.sv
+++ b/tests/svtypes/enum_simple.sv
@@ -5,8 +5,9 @@ module enum_simple(input clk, input rst);
typedef enum logic [1:0] {
ts0, ts1, ts2, ts3
} states_t;
- (states_t) state;
- (states_t) enum_const = ts1;
+ states_t state;
+ (states_t) state1;
+ states_t enum_const = ts1;
always @(posedge clk) begin
if (rst) begin
diff --git a/tests/svtypes/typedef_memory.sv b/tests/svtypes/typedef_memory.sv
index 577e484ad..37e63c1d0 100644
--- a/tests/svtypes/typedef_memory.sv
+++ b/tests/svtypes/typedef_memory.sv
@@ -1,7 +1,7 @@
module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata);
typedef logic [3:0] ram16x4_t[0:15];
- (ram16x4_t) mem;
+ ram16x4_t mem;
always @(posedge clk) begin
if (wen) mem[addr] <= wdata;
diff --git a/tests/svtypes/typedef_memory_2.sv b/tests/svtypes/typedef_memory_2.sv
index f3089bf55..6d65131db 100644
--- a/tests/svtypes/typedef_memory_2.sv
+++ b/tests/svtypes/typedef_memory_2.sv
@@ -1,7 +1,7 @@
module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata);
typedef logic [3:0] nibble;
- (nibble) mem[0:15];
+ nibble mem[0:15];
always @(posedge clk) begin
if (wen) mem[addr] <= wdata;
diff --git a/tests/svtypes/typedef_package.sv b/tests/svtypes/typedef_package.sv
index b766f10cf..57a78c53a 100644
--- a/tests/svtypes/typedef_package.sv
+++ b/tests/svtypes/typedef_package.sv
@@ -5,8 +5,8 @@ endpackage
module top;
- (* keep *) (pkg::uint8_t) a = 8'hAA;
- (* keep *) (pkg::enum8_t) b_enum = pkg::bb;
+ (* keep *) pkg::uint8_t a = 8'hAA;
+ (* keep *) pkg::enum8_t b_enum = pkg::bb;
always @* assert(a == 8'hAA);
always @* assert(b_enum == 8'hBB);
diff --git a/tests/svtypes/typedef_param.sv b/tests/svtypes/typedef_param.sv
index ddbd471e0..d838dd828 100644
--- a/tests/svtypes/typedef_param.sv
+++ b/tests/svtypes/typedef_param.sv
@@ -6,12 +6,12 @@ module top;
typedef logic [1:0] uint2_t;
typedef logic signed [3:0] int4_t;
typedef logic signed [7:0] int8_t;
- typedef (int8_t) char_t;
+ typedef int8_t char_t;
- parameter (uint2_t) int2 = 2'b10;
- localparam (int4_t) int4 = -1;
- localparam (int8_t) int8 = int4;
- localparam (char_t) ch = int8;
+ parameter uint2_t int2 = 2'b10;
+ localparam int4_t int4 = -1;
+ localparam int8_t int8 = int4;
+ localparam char_t ch = int8;
`STATIC_ASSERT(int2 == 2'b10);
diff --git a/tests/svtypes/typedef_scopes.sv b/tests/svtypes/typedef_scopes.sv
index 1c45c7057..d41a58147 100644
--- a/tests/svtypes/typedef_scopes.sv
+++ b/tests/svtypes/typedef_scopes.sv
@@ -4,30 +4,30 @@ typedef enum logic {s0, s1} outer_enum_t;
module top;
- (outer_uint4_t) u4_i = 8'hA5;
- (outer_enum_t) enum4_i = s0;
+ outer_uint4_t u4_i = 8'hA5;
+ outer_enum_t enum4_i = s0;
always @(*) assert(u4_i == 4'h5);
always @(*) assert(enum4_i == 1'b0);
typedef logic [3:0] inner_type;
typedef enum logic [2:0] {s2=2, s3, s4} inner_enum_t;
- (inner_type) inner_i1 = 8'h5A;
- (inner_enum_t) inner_enum1 = s3;
+ inner_type inner_i1 = 8'h5A;
+ inner_enum_t inner_enum1 = s3;
always @(*) assert(inner_i1 == 4'hA);
always @(*) assert(inner_enum1 == 3'h3);
if (1) begin: genblock
typedef logic [7:0] inner_type;
- parameter (inner_type) inner_const = 8'hA5;
+ parameter inner_type inner_const = 8'hA5;
typedef enum logic [2:0] {s5=5, s6, s7} inner_enum_t;
- (inner_type) inner_gb_i = inner_const; //8'hA5;
- (inner_enum_t) inner_gb_enum1 = s7;
+ inner_type inner_gb_i = inner_const; //8'hA5;
+ inner_enum_t inner_gb_enum1 = s7;
always @(*) assert(inner_gb_i == 8'hA5);
always @(*) assert(inner_gb_enum1 == 3'h7);
end
- (inner_type) inner_i2 = 8'h42;
- (inner_enum_t) inner_enum2 = s4;
+ inner_type inner_i2 = 8'h42;
+ inner_enum_t inner_enum2 = s4;
always @(*) assert(inner_i2 == 4'h2);
always @(*) assert(inner_enum2 == 3'h4);
diff --git a/tests/svtypes/typedef_simple.sv b/tests/svtypes/typedef_simple.sv
index 7e760dee4..8f89910e5 100644
--- a/tests/svtypes/typedef_simple.sv
+++ b/tests/svtypes/typedef_simple.sv
@@ -3,12 +3,12 @@ module top;
typedef logic [1:0] uint2_t;
typedef logic signed [3:0] int4_t;
typedef logic signed [7:0] int8_t;
- typedef (int8_t) char_t;
+ typedef int8_t char_t;
- (* keep *) (uint2_t) int2 = 2'b10;
- (* keep *) (int4_t) int4 = -1;
- (* keep *) (int8_t) int8 = int4;
- (* keep *) (char_t) ch = int8;
+ (* keep *) uint2_t int2 = 2'b10;
+ (* keep *) int4_t int4 = -1;
+ (* keep *) int8_t int8 = int4;
+ (* keep *) char_t ch = int8;
always @* assert(int2 == 2'b10);
diff --git a/tests/various/bug1781.ys b/tests/various/bug1781.ys
new file mode 100644
index 000000000..60dcc0830
--- /dev/null
+++ b/tests/various/bug1781.ys
@@ -0,0 +1,33 @@
+read_verilog <<EOT
+
+module top(input clk, input rst);
+
+reg [1:0] state;
+
+always @(posedge clk, posedge rst) begin
+ if (rst)
+ state <= 0;
+ else
+ case (state)
+ 2'b00: state <= 2'b01;
+ 2'b01: state <= 2'b10;
+ 2'b10: state <= 2'b00;
+ endcase
+end
+
+sub sub_i(.i(state == 0));
+
+endmodule
+
+
+(* blackbox, keep *)
+module sub(input i);
+endmodule
+
+EOT
+
+proc
+fsm
+
+# Make sure there is a driver
+select -assert-any t:sub %ci %a w:* %i %ci c:* %i
diff --git a/tests/various/exec.ys b/tests/various/exec.ys
new file mode 100644
index 000000000..0eec00719
--- /dev/null
+++ b/tests/various/exec.ys
@@ -0,0 +1,6 @@
+exec -expect-return 0 -- exit 0
+exec -expect-return 27 -- exit 27
+exec -expect-stdout nana -expect-stdout api -not-expect-stdout giraffe -- echo "bananapie"
+
+logger -expect error "stdout did have a line" 1
+exec -not-expect-stdout giraffe -- echo "giraffe"
diff --git a/tests/various/ice40_mince_abc9.ys b/tests/various/ice40_mince_abc9.ys
new file mode 100644
index 000000000..408e16f05
--- /dev/null
+++ b/tests/various/ice40_mince_abc9.ys
@@ -0,0 +1,17 @@
+read_verilog <<EOT
+
+module top(input clk, ce, input [2:0] a, b, output reg [2:0] q);
+
+ reg [2:0] aa, bb;
+
+ always @(posedge clk) begin
+ if (ce) begin
+ aa <= a;
+ end
+ bb <= b;
+ q <= aa + bb;
+ end
+endmodule
+EOT
+
+synth_ice40 -abc9 -dffe_min_ce_use 4