diff options
31 files changed, 362 insertions, 148 deletions
diff --git a/.gitignore b/.gitignore index 76f53cd06..0460c7c13 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ __pycache__ /yosys /yosys.exe /yosys.js +/yosys.wasm /yosys-abc /yosys-abc.exe /yosys-config @@ -128,7 +128,7 @@ bumpversion: # is just a symlink to your actual ABC working directory, as 'make mrproper' # will remove the 'abc' directory and you do not want to accidentally # delete your work on ABC.. -ABCREV = 71f2b40 +ABCREV = ed90ce2 ABCPULL = 1 ABCURL ?= https://github.com/berkeley-abc/abc ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 @@ -237,7 +237,8 @@ ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DABC_MEMALIGN=8" EMCCFLAGS := -Os -Wno-warn-absolute-paths EMCCFLAGS += --memory-init-file 0 --embed-file share -s NO_EXIT_RUNTIME=1 EMCCFLAGS += -s EXPORTED_FUNCTIONS="['_main','_run','_prompt','_errmsg']" -EMCCFLAGS += -s TOTAL_MEMORY=128*1024*1024 +EMCCFLAGS += -s TOTAL_MEMORY=134217728 +EMCCFLAGS += -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' # https://github.com/kripken/emscripten/blob/master/src/settings.js CXXFLAGS += $(EMCCFLAGS) LDFLAGS += $(EMCCFLAGS) @@ -256,10 +257,10 @@ viz.js: wget -O viz.js.part https://github.com/mdaines/viz.js/releases/download/0.0.3/viz.js mv viz.js.part viz.js -yosysjs-$(YOSYS_VER).zip: yosys.js viz.js misc/yosysjs/* +yosysjs-$(YOSYS_VER).zip: yosys.js yosys.wasm viz.js misc/yosysjs/* rm -rf yosysjs-$(YOSYS_VER) yosysjs-$(YOSYS_VER).zip mkdir -p yosysjs-$(YOSYS_VER) - cp viz.js misc/yosysjs/* yosys.js yosysjs-$(YOSYS_VER)/ + cp viz.js misc/yosysjs/* yosys.js yosys.wasm yosysjs-$(YOSYS_VER)/ zip -r yosysjs-$(YOSYS_VER).zip yosysjs-$(YOSYS_VER) yosys.html: misc/yosys.html @@ -668,7 +669,8 @@ ifneq ($(ABCREV),default) $(Q) if ( cd abc 2> /dev/null && ! git diff-index --quiet HEAD; ); then \ echo 'REEBE: NOP pbagnvaf ybpny zbqvsvpngvbaf! Frg NOPERI=qrsnhyg va Lbflf Znxrsvyr!' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; false; \ fi - $(Q) if test "`cd abc 2> /dev/null && git rev-parse --short HEAD`" != "$(ABCREV)"; then \ +# set a variable so the test fails if git fails to run - when comparing outputs directly, empty string would match empty string + $(Q) if ! (cd abc && rev="`git rev-parse $(ABCREV)`" && test "`git rev-parse HEAD`" == "$$rev"); then \ test $(ABCPULL) -ne 0 || { echo 'REEBE: NOP abg hc gb qngr naq NOPCHYY frg gb 0 va Znxrsvyr!' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; exit 1; }; \ echo "Pulling ABC from $(ABCURL):"; set -x; \ test -d abc || git clone $(ABCURL) abc; \ @@ -765,7 +767,7 @@ clean-unit-test: install: $(TARGETS) $(EXTRA_TARGETS) $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR) - $(INSTALL_SUDO) cp $(TARGETS) $(DESTDIR)$(BINDIR) + $(INSTALL_SUDO) cp $(filter-out libyosys.so,$(TARGETS)) $(DESTDIR)$(BINDIR) ifneq ($(filter yosys,$(TARGETS)),) $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/yosys endif @@ -895,6 +897,7 @@ config-emcc: clean echo 'ENABLE_ABC := 0' >> Makefile.conf echo 'ENABLE_PLUGINS := 0' >> Makefile.conf echo 'ENABLE_READLINE := 0' >> Makefile.conf + echo 'ENABLE_ZLIB := 0' >> Makefile.conf config-mxe: clean echo 'CONFIG := mxe' > Makefile.conf @@ -929,6 +932,9 @@ echo-yosys-ver: echo-git-rev: @echo "$(GIT_REV)" +echo-abc-rev: + @echo "$(ABCREV)" + -include libs/*/*.d -include frontends/*/*.d -include passes/*/*.d diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 402f41597..cde6d066a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -174,11 +174,12 @@ struct XAigerWriter undriven_bits.insert(bit); unused_bits.insert(bit); - bool keep = wire->get_bool_attribute(ID::keep); - if (wire->port_input || keep) + bool scc = wire->attributes.count(ID(abc9_scc)); + if (wire->port_input || scc) input_bits.insert(bit); - if (wire->port_output || keep) { + bool keep = wire->get_bool_attribute(ID::keep); + if (wire->port_output || keep || scc) { if (bit != wirebit) alias_map[wirebit] = bit; output_bits.insert(wirebit); @@ -223,8 +224,6 @@ struct XAigerWriter alias_map[Q] = D; auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell)); log_assert(r.second); - if (input_bits.erase(Q)) - log_assert(Q.wire->attributes.count(ID::keep)); continue; } @@ -378,11 +377,6 @@ struct XAigerWriter alias_map[O] = b; ci_bits.emplace_back(b); undriven_bits.erase(O); - // If PI and CI, then must be a (* keep *) wire - if (input_bits.erase(O)) { - log_assert(output_bits.count(O)); - log_assert(O.wire->get_bool_attribute(ID::keep)); - } } } @@ -467,8 +461,8 @@ struct XAigerWriter for (const auto &bit : output_bits) { ordered_outputs[bit] = aig_o++; int aig; - // Unlike bit2aig() which checks aig_map first, for - // inout/keep bits, since aig_map will point to + // Unlike bit2aig() which checks aig_map first for + // inout/scc bits, since aig_map will point to // the PI, first attempt to find the NOT/AND driver // before resorting to an aig_map lookup (which // could be another PO) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 87db0edf7..22aa686a7 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -25,7 +25,6 @@ #include "kernel/log.h" #include <algorithm> #include <string> -#include <regex> #include <vector> #include <cmath> diff --git a/frontends/rpc/Makefile.inc b/frontends/rpc/Makefile.inc index 9af505098..7b270b6fe 100644 --- a/frontends/rpc/Makefile.inc +++ b/frontends/rpc/Makefile.inc @@ -1,2 +1,3 @@ - +ifneq ($(CONFIG),emcc) OBJS += frontends/rpc/rpc_frontend.o +endif diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 0a7c34ec0..d22a18458 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -113,8 +113,10 @@ extern int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param); %x SYNOPSYS_TRANSLATE_OFF %x SYNOPSYS_FLAGS %x IMPORT_DPI +%x BASED_CONST %% + int comment_caller; <INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_push "[^\n]* { fn_stack.push_back(current_filename); @@ -273,9 +275,21 @@ extern int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param); return TOK_CONSTVAL; } -[0-9]*[ \t]*\'[sS]?[bodhBODH]?[ \t\r\n]*[0-9a-fA-FzxZX?_]+ { +\'[01zxZX] { yylval->string = new std::string(yytext); - return TOK_CONSTVAL; + return TOK_UNBASED_UNSIZED_CONSTVAL; +} + +\'[sS]?[bodhBODH] { + BEGIN(BASED_CONST); + yylval->string = new std::string(yytext); + return TOK_BASE; +} + +<BASED_CONST>[0-9a-fA-FzxZX?][0-9a-fA-FzxZX?_]* { + BEGIN(0); + yylval->string = new std::string(yytext); + return TOK_BASED_CONSTVAL; } [0-9][0-9_]*\.[0-9][0-9_]*([eE][-+]?[0-9_]+)? { @@ -478,16 +492,17 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { return TOK_SPECIFY_AND; } -"/*" { BEGIN(COMMENT); } +<INITIAL,BASED_CONST>"/*" { comment_caller=YY_START; BEGIN(COMMENT); } <COMMENT>. /* ignore comment body */ <COMMENT>\n /* ignore comment body */ -<COMMENT>"*/" { BEGIN(0); } +<COMMENT>"*/" { BEGIN(comment_caller); } -[ \t\r\n] /* ignore whitespaces */ -\\[\r\n] /* ignore continuation sequence */ -"//"[^\r\n]* /* ignore one-line comments */ +<INITIAL,BASED_CONST>[ \t\r\n] /* ignore whitespaces */ +<INITIAL,BASED_CONST>\\[\r\n] /* ignore continuation sequence */ +<INITIAL,BASED_CONST>"//"[^\r\n]* /* ignore one-line comments */ -. { return *yytext; } +<INITIAL>. { return *yytext; } +<*>. { BEGIN(0); return *yytext; } %% diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index be8b39e9f..1132e97ae 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -166,6 +166,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 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 @@ -188,7 +189,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 +%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number %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 @@ -593,13 +594,15 @@ non_opt_range: } | '[' expr TOK_POS_INDEXED expr ']' { $$ = new AstNode(AST_RANGE); - $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, $2->clone(), $4), AstNode::mkconst_int(1, true))); - $$->children.push_back(new AstNode(AST_ADD, $2, AstNode::mkconst_int(0, true))); + AstNode *expr = new AstNode(AST_CONCAT, $2); + $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr->clone(), $4), AstNode::mkconst_int(1, true))); + $$->children.push_back(new AstNode(AST_ADD, expr, AstNode::mkconst_int(0, true))); } | '[' expr TOK_NEG_INDEXED expr ']' { $$ = new AstNode(AST_RANGE); - $$->children.push_back(new AstNode(AST_ADD, $2, AstNode::mkconst_int(0, true))); - $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, $2->clone(), AstNode::mkconst_int(1, true)), $4)); + AstNode *expr = new AstNode(AST_CONCAT, $2); + $$->children.push_back(new AstNode(AST_ADD, expr, AstNode::mkconst_int(0, true))); + $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr->clone(), AstNode::mkconst_int(1, true)), $4)); } | '[' expr ']' { $$ = new AstNode(AST_RANGE); @@ -2111,18 +2114,22 @@ simple_behavioral_stmt: lvalue '=' delay expr { AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $4); ast_stack.back()->children.push_back(node); + SET_AST_NODE_LOC(node, @1, @4); } | lvalue TOK_INCREMENT { AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_ADD, $1->clone(), AstNode::mkconst_int(1, true))); ast_stack.back()->children.push_back(node); + SET_AST_NODE_LOC(node, @1, @2); } | lvalue TOK_DECREMENT { AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_SUB, $1->clone(), AstNode::mkconst_int(1, true))); ast_stack.back()->children.push_back(node); + SET_AST_NODE_LOC(node, @1, @2); } | lvalue OP_LE delay expr { AstNode *node = new AstNode(AST_ASSIGN_LE, $1, $4); ast_stack.back()->children.push_back(node); + SET_AST_NODE_LOC(node, @1, @4); }; // this production creates the obligatory if-else shift/reduce conflict @@ -2180,6 +2187,7 @@ behavioral_stmt: } behavioral_stmt { SET_AST_NODE_LOC(ast_stack.back(), @13, @13); ast_stack.pop_back(); + SET_AST_NODE_LOC(ast_stack.back(), @2, @13); ast_stack.pop_back(); } | attr TOK_WHILE '(' expr ')' { @@ -2333,6 +2341,7 @@ gen_case_item: ast_stack.push_back(node); } case_select { case_type_stack.push_back(0); + SET_AST_NODE_LOC(ast_stack.back(), @2, @2); } gen_stmt_or_null { case_type_stack.pop_back(); ast_stack.pop_back(); @@ -2344,10 +2353,14 @@ case_select: case_expr_list: TOK_DEFAULT { - ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT)); + AstNode *node = new AstNode(AST_DEFAULT); + SET_AST_NODE_LOC(node, @1, @1); + ast_stack.back()->children.push_back(node); } | TOK_SVA_LABEL { - ast_stack.back()->children.push_back(new AstNode(AST_IDENTIFIER)); + AstNode *node = new AstNode(AST_IDENTIFIER); + SET_AST_NODE_LOC(node, @1, @1); + ast_stack.back()->children.push_back(node); ast_stack.back()->children.back()->str = *$1; delete $1; } | @@ -2494,6 +2507,7 @@ expr: $$->children.push_back($1); $$->children.push_back($4); $$->children.push_back($6); + SET_AST_NODE_LOC($$, @1, @$); append_attr($$, $3); }; @@ -2501,7 +2515,7 @@ basic_expr: rvalue { $$ = $1; } | - '(' expr ')' TOK_CONSTVAL { + '(' expr ')' integral_number { if ($4->compare(0, 1, "'") != 0) frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. (<expr>)<constval> , while %s is not a sized constant.", $4->c_str()); AstNode *bits = $2; @@ -2511,11 +2525,12 @@ basic_expr: $$ = new AstNode(AST_TO_BITS, bits, val); delete $4; } | - hierarchical_id TOK_CONSTVAL { + hierarchical_id integral_number { if ($2->compare(0, 1, "'") != 0) frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. <ID>\'d0, while %s is not a sized constant.", $2->c_str()); AstNode *bits = new AstNode(AST_IDENTIFIER); bits->str = *$1; + SET_AST_NODE_LOC(bits, @1, @1); AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); if (val == NULL) log_error("Value conversion failed: `%s'\n", $2->c_str()); @@ -2523,14 +2538,7 @@ basic_expr: delete $1; delete $2; } | - TOK_CONSTVAL TOK_CONSTVAL { - $$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); - if ($$ == NULL || (*$2)[0] != '\'') - log_error("Value conversion failed: `%s%s'\n", $1->c_str(), $2->c_str()); - delete $1; - delete $2; - } | - TOK_CONSTVAL { + integral_number { $$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); if ($$ == NULL) log_error("Value conversion failed: `%s'\n", $1->c_str()); @@ -2543,6 +2551,7 @@ basic_expr: if ((*$1)[j] != '_') p[i++] = (*$1)[j], p[i] = 0; $$->realvalue = strtod(p, &q); + SET_AST_NODE_LOC($$, @1, @1); log_assert(*q == 0); delete $1; free(p); @@ -2556,6 +2565,7 @@ basic_expr: node->str = *$1; delete $1; ast_stack.push_back(node); + SET_AST_NODE_LOC(node, @1, @1); append_attr(node, $2); } '(' arg_list optional_comma ')' { $$ = ast_stack.back(); @@ -2585,148 +2595,185 @@ basic_expr: } | '~' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_BIT_NOT, $3); + SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | basic_expr '&' attr basic_expr { $$ = new AstNode(AST_BIT_AND, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_NAND attr basic_expr { $$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_AND, $1, $4)); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '|' attr basic_expr { $$ = new AstNode(AST_BIT_OR, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_NOR attr basic_expr { $$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_OR, $1, $4)); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '^' attr basic_expr { $$ = new AstNode(AST_BIT_XOR, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_XNOR attr basic_expr { $$ = new AstNode(AST_BIT_XNOR, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | '&' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_REDUCE_AND, $3); + SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | OP_NAND attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_REDUCE_AND, $3); + SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); $$ = new AstNode(AST_LOGIC_NOT, $$); } | '|' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_REDUCE_OR, $3); + SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | OP_NOR attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_REDUCE_OR, $3); + SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); $$ = new AstNode(AST_LOGIC_NOT, $$); + SET_AST_NODE_LOC($$, @1, @3); } | '^' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_REDUCE_XOR, $3); + SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | OP_XNOR attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_REDUCE_XNOR, $3); + SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | basic_expr OP_SHL attr basic_expr { $$ = new AstNode(AST_SHIFT_LEFT, $1, new AstNode(AST_TO_UNSIGNED, $4)); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_SHR attr basic_expr { $$ = new AstNode(AST_SHIFT_RIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4)); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_SSHL attr basic_expr { $$ = new AstNode(AST_SHIFT_SLEFT, $1, new AstNode(AST_TO_UNSIGNED, $4)); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_SSHR attr basic_expr { $$ = new AstNode(AST_SHIFT_SRIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4)); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '<' attr basic_expr { $$ = new AstNode(AST_LT, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_LE attr basic_expr { $$ = new AstNode(AST_LE, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_EQ attr basic_expr { $$ = new AstNode(AST_EQ, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_NE attr basic_expr { $$ = new AstNode(AST_NE, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_EQX attr basic_expr { $$ = new AstNode(AST_EQX, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_NEX attr basic_expr { $$ = new AstNode(AST_NEX, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_GE attr basic_expr { $$ = new AstNode(AST_GE, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '>' attr basic_expr { $$ = new AstNode(AST_GT, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '+' attr basic_expr { $$ = new AstNode(AST_ADD, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '-' attr basic_expr { $$ = new AstNode(AST_SUB, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '*' attr basic_expr { $$ = new AstNode(AST_MUL, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '/' attr basic_expr { $$ = new AstNode(AST_DIV, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr '%' attr basic_expr { $$ = new AstNode(AST_MOD, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_POW attr basic_expr { $$ = new AstNode(AST_POW, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | '+' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_POS, $3); + SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | '-' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_NEG, $3); + SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); } | basic_expr OP_LAND attr basic_expr { $$ = new AstNode(AST_LOGIC_AND, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | basic_expr OP_LOR attr basic_expr { $$ = new AstNode(AST_LOGIC_OR, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); append_attr($$, $3); } | '!' attr basic_expr %prec UNARY_OPS { $$ = new AstNode(AST_LOGIC_NOT, $3); + SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); }; @@ -2738,3 +2785,18 @@ concat_list: $$ = $3; $$->children.push_back($1); }; + +integral_number: + TOK_CONSTVAL { $$ = $1; } | + TOK_UNBASED_UNSIZED_CONSTVAL { $$ = $1; } | + TOK_BASE TOK_BASED_CONSTVAL { + $1->append(*$2); + $$ = $1; + delete $2; + } | + TOK_CONSTVAL TOK_BASE TOK_BASED_CONSTVAL { + $1->append(*$2).append(*$3); + $$ = $1; + delete $2; + delete $3; + }; diff --git a/kernel/driver.cc b/kernel/driver.cc index 398c89e03..5f0959776 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -413,22 +413,13 @@ int main(int argc, char **argv) scriptfile_tcl = true; break; case 'W': - log_warn_regexes.push_back(std::regex(optarg, - std::regex_constants::nosubs | - std::regex_constants::optimize | - std::regex_constants::egrep)); + log_warn_regexes.push_back(YS_REGEX_COMPILE(optarg)); break; case 'w': - log_nowarn_regexes.push_back(std::regex(optarg, - std::regex_constants::nosubs | - std::regex_constants::optimize | - std::regex_constants::egrep)); + log_nowarn_regexes.push_back(YS_REGEX_COMPILE(optarg)); break; case 'e': - log_werror_regexes.push_back(std::regex(optarg, - std::regex_constants::nosubs | - std::regex_constants::optimize | - std::regex_constants::egrep)); + log_werror_regexes.push_back(YS_REGEX_COMPILE(optarg)); break; case 'D': vlog_defines.push_back(optarg); diff --git a/kernel/log.cc b/kernel/log.cc index 72181ebe8..d84a4381e 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -41,8 +41,8 @@ YOSYS_NAMESPACE_BEGIN std::vector<FILE*> log_files; std::vector<std::ostream*> log_streams; std::map<std::string, std::set<std::string>> log_hdump; -std::vector<std::regex> log_warn_regexes, log_nowarn_regexes, log_werror_regexes; -std::vector<std::pair<std::regex,LogExpectedItem>> log_expect_log, log_expect_warning, log_expect_error; +std::vector<YS_REGEX_TYPE> log_warn_regexes, log_nowarn_regexes, log_werror_regexes; +std::vector<std::pair<YS_REGEX_TYPE,LogExpectedItem>> log_expect_log, log_expect_warning, log_expect_error; std::set<std::string> log_warnings, log_experimentals, log_experimentals_ignored; int log_warnings_count = 0; int log_warnings_count_noexpect = 0; @@ -177,11 +177,11 @@ void logv(const char *format, va_list ap) if (!linebuffer.empty() && linebuffer.back() == '\n') { for (auto &re : log_warn_regexes) - if (std::regex_search(linebuffer, re)) + if (YS_REGEX_NS::regex_search(linebuffer, re)) log_warning("Found log message matching -W regex:\n%s", str.c_str()); for (auto &item : log_expect_log) - if (std::regex_search(linebuffer, item.first)) + if (YS_REGEX_NS::regex_search(linebuffer, item.first)) item.second.current_count++; linebuffer.clear(); @@ -238,7 +238,7 @@ static void logv_warning_with_prefix(const char *prefix, bool suppressed = false; for (auto &re : log_nowarn_regexes) - if (std::regex_search(message, re)) + if (YS_REGEX_NS::regex_search(message, re)) suppressed = true; if (suppressed) @@ -251,12 +251,12 @@ static void logv_warning_with_prefix(const char *prefix, log_make_debug = 0; for (auto &re : log_werror_regexes) - if (std::regex_search(message, re)) + if (YS_REGEX_NS::regex_search(message, re)) log_error("%s", message.c_str()); bool warning_match = false; for (auto &item : log_expect_warning) - if (std::regex_search(message, item.first)) { + if (YS_REGEX_NS::regex_search(message, item.first)) { item.second.current_count++; warning_match = true; } @@ -349,7 +349,7 @@ static void logv_error_with_prefix(const char *prefix, log_error_atexit(); for (auto &item : log_expect_error) - if (std::regex_search(log_last_error, item.first)) + if (YS_REGEX_NS::regex_search(log_last_error, item.first)) item.second.current_count++; if (check_expected_logs) @@ -695,7 +695,6 @@ void log_check_expected() log_warn_regexes.clear(); log("Expected error pattern '%s' found !!!\n", item.second.pattern.c_str()); #ifdef EMSCRIPTEN - log_files = backup_log_files; throw 0; #elif defined(_MSC_VER) _exit(0); diff --git a/kernel/log.h b/kernel/log.h index 603938f4c..cd0e8185c 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -23,7 +23,25 @@ #define LOG_H #include <time.h> -#include <regex> + +// In GCC 4.8 std::regex is not working correctlty, in order to make features +// using regular expressions to work replacement regex library is used +#if defined(__GNUC__) && !defined( __clang__) && ( __GNUC__ == 4 && __GNUC_MINOR__ <= 8) + #include <boost/xpressive/xpressive.hpp> + #define YS_REGEX_TYPE boost::xpressive::sregex + #define YS_REGEX_NS boost::xpressive + #define YS_REGEX_COMPILE(param) boost::xpressive::sregex::compile(param, \ + boost::xpressive::regex_constants::nosubs | \ + boost::xpressive::regex_constants::optimize) +# else + #include <regex> + #define YS_REGEX_TYPE std::regex + #define YS_REGEX_NS std + #define YS_REGEX_COMPILE(param) std::regex(param, \ + std::regex_constants::nosubs | \ + std::regex_constants::optimize | \ + std::regex_constants::egrep) +#endif #ifndef _WIN32 # include <sys/time.h> @@ -49,7 +67,7 @@ struct log_cmd_error_exception { }; extern std::vector<FILE*> log_files; extern std::vector<std::ostream*> log_streams; extern std::map<std::string, std::set<std::string>> log_hdump; -extern std::vector<std::regex> log_warn_regexes, log_nowarn_regexes, log_werror_regexes; +extern std::vector<YS_REGEX_TYPE> log_warn_regexes, log_nowarn_regexes, log_werror_regexes; extern std::set<std::string> log_warnings, log_experimentals, log_experimentals_ignored; extern int log_warnings_count; extern int log_warnings_count_noexpect; @@ -151,7 +169,7 @@ struct LogExpectedItem std::string pattern; }; -extern std::vector<std::pair<std::regex,LogExpectedItem>> log_expect_log, log_expect_warning, log_expect_error; +extern std::vector<std::pair<YS_REGEX_TYPE,LogExpectedItem>> log_expect_log, log_expect_warning, log_expect_error; void log_check_expected(); const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true); diff --git a/kernel/register.cc b/kernel/register.cc index e59d59654..af8c1b8e8 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -400,6 +400,18 @@ void ScriptPass::run(std::string command, std::string info) } } +void ScriptPass::run_nocheck(std::string command, std::string info) +{ + if (active_design == nullptr) { + if (info.empty()) + log(" %s\n", command.c_str()); + else + log(" %s %s\n", command.c_str(), info.c_str()); + } else { + Pass::call(active_design, command); + } +} + void ScriptPass::run_script(RTLIL::Design *design, std::string run_from, std::string run_to) { help_mode = false; diff --git a/kernel/register.h b/kernel/register.h index 4622845b6..3d89386b7 100644 --- a/kernel/register.h +++ b/kernel/register.h @@ -84,6 +84,7 @@ struct ScriptPass : Pass bool check_label(std::string label, std::string info = std::string()); void run(std::string command, std::string info = std::string()); + void run_nocheck(std::string command, std::string info = std::string()); void run_script(RTLIL::Design *design, std::string run_from = std::string(), std::string run_to = std::string()); void help_script(); }; diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 8190d8902..7694fc9b6 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -341,7 +341,11 @@ int run_command(const std::string &command, std::function<void(const std::string if (!process_line) return system(command.c_str()); +#ifdef EMSCRIPTEN + FILE *f = nullptr; +#else FILE *f = popen(command.c_str(), "r"); +#endif if (f == nullptr) return -1; diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc index dd05ac81f..7b76f3d4a 100644 --- a/passes/cmds/add.cc +++ b/passes/cmds/add.cc @@ -22,26 +22,61 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +static bool is_formal_celltype(const std::string &celltype) +{ + if(celltype == "assert" || celltype == "assume" || celltype == "live" || celltype == "fair" || celltype == "cover") + return true; + else + return false; +} + +static void add_formal(RTLIL::Module *module, const std::string &celltype, const std::string &name, const std::string &enable_name) +{ + std::string escaped_name = RTLIL::escape_id(name); + std::string escaped_enable_name = (enable_name != "") ? RTLIL::escape_id(enable_name) : ""; + RTLIL::Wire *wire = module->wire(escaped_name); + log_assert(is_formal_celltype(celltype)); + + if (wire == nullptr) { + log_error("Could not find wire with name \"%s\".\n", name.c_str()); + } + else { + RTLIL::Cell *formal_cell = module->addCell(NEW_ID, "$" + celltype); + formal_cell->setPort(ID(A), wire); + if(enable_name == "") { + formal_cell->setPort(ID(EN), State::S1); + log("Added $%s cell for wire \"%s.%s\"\n", celltype.c_str(), module->name.str().c_str(), name.c_str()); + } + else { + RTLIL::Wire *enable_wire = module->wire(escaped_enable_name); + if(enable_wire == nullptr) + log_error("Could not find enable wire with name \"%s\".\n", enable_name.c_str()); + + formal_cell->setPort(ID(EN), enable_wire); + log("Added $%s cell for wire \"%s.%s\" enabled by wire \"%s.%s\".\n", celltype.c_str(), module->name.str().c_str(), name.c_str(), module->name.str().c_str(), enable_name.c_str()); + } + } +} + static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output, bool flag_global) { - RTLIL::Wire *wire = NULL; + RTLIL::Wire *wire = nullptr; name = RTLIL::escape_id(name); if (module->count_id(name) != 0) { - if (module->wires_.count(name) > 0) - wire = module->wires_.at(name); + wire = module->wire(name); - if (wire != NULL && wire->width != width) - wire = NULL; + if (wire != nullptr && wire->width != width) + wire = nullptr; - if (wire != NULL && wire->port_input != flag_input) - wire = NULL; + if (wire != nullptr && wire->port_input != flag_input) + wire = nullptr; - if (wire != NULL && wire->port_output != flag_output) - wire = NULL; + if (wire != nullptr && wire->port_output != flag_output) + wire = nullptr; - if (wire == NULL) + if (wire == nullptr) log_cmd_error("Found incompatible object with same name in module %s!\n", module->name.c_str()); log("Module %s already has such an object.\n", module->name.c_str()); @@ -53,7 +88,6 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n wire->port_output = flag_output; if (flag_input || flag_output) { - wire->port_id = module->wires_.size(); module->fixup_ports(); } @@ -63,21 +97,20 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n if (!flag_global) return; - for (auto &it : module->cells_) + for (auto cell : module->cells()) { - if (design->modules_.count(it.second->type) == 0) + RTLIL::Module *mod = design->module(cell->type); + if (mod == nullptr) continue; - - RTLIL::Module *mod = design->modules_.at(it.second->type); if (!design->selected_whole_module(mod->name)) continue; if (mod->get_blackbox_attribute()) continue; - if (it.second->hasPort(name)) + if (cell->hasPort(name)) continue; - it.second->setPort(name, wire); - log("Added connection %s to cell %s.%s (%s).\n", name.c_str(), module->name.c_str(), it.first.c_str(), it.second->type.c_str()); + cell->setPort(name, wire); + log("Added connection %s to cell %s.%s (%s).\n", name.c_str(), module->name.c_str(), cell->name.c_str(), cell->type.c_str()); } } @@ -106,6 +139,12 @@ struct AddPass : public Pass { log("selected modules.\n"); log("\n"); log("\n"); + log(" add {-assert|-assume|-live|-fair|-cover} <name1> [-if <name2>]\n"); + log("\n"); + log("Add an $assert, $assume, etc. cell connected to a wire named name1, with its\n"); + log("enable signal optionally connected to a wire named name2 (default: 1'b1).\n"); + log("\n"); + log("\n"); log(" add -mod <name[s]>\n"); log("\n"); log("Add module[s] with the specified name[s].\n"); @@ -115,6 +154,7 @@ struct AddPass : public Pass { { std::string command; std::string arg_name; + std::string enable_name = ""; bool arg_flag_input = false; bool arg_flag_output = false; bool arg_flag_global = false; @@ -144,6 +184,17 @@ struct AddPass : public Pass { argidx++; break; } + if (arg.length() > 0 && arg[0] == '-' && is_formal_celltype(arg.substr(1))) { + if (argidx + 1 >= args.size()) + break; + command = arg.substr(1); + arg_name = args[++argidx]; + if (argidx + 2 < args.size() && args[argidx + 1] == "-if") { + enable_name = args[argidx + 2]; + argidx += 2; + } + continue; + } break; } @@ -155,15 +206,17 @@ struct AddPass : public Pass { extra_args(args, argidx, design); - for (auto &mod : design->modules_) + for (auto module : design->modules()) { - RTLIL::Module *module = mod.second; + log_assert(module != nullptr); if (!design->selected_whole_module(module->name)) continue; if (module->get_bool_attribute("\\blackbox")) continue; - if (command == "wire") + if (is_formal_celltype(command)) + add_formal(module, command, arg_name, enable_name); + else if (command == "wire") add_wire(design, module, arg_name, arg_width, arg_flag_input, arg_flag_output, arg_flag_global); } } diff --git a/passes/cmds/logger.cc b/passes/cmds/logger.cc index bd1038a7e..9a27952d4 100644 --- a/passes/cmds/logger.cc +++ b/passes/cmds/logger.cc @@ -96,12 +96,9 @@ struct LoggerPass : public Pass { if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); try { log("Added regex '%s' for warnings to warn list.\n", pattern.c_str()); - log_warn_regexes.push_back(std::regex(pattern, - std::regex_constants::nosubs | - std::regex_constants::optimize | - std::regex_constants::egrep)); + log_warn_regexes.push_back(YS_REGEX_COMPILE(pattern)); } - catch (const std::regex_error& e) { + catch (const YS_REGEX_NS::regex_error& e) { log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str()); } continue; @@ -111,12 +108,9 @@ struct LoggerPass : public Pass { if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); try { log("Added regex '%s' for warnings to nowarn list.\n", pattern.c_str()); - log_nowarn_regexes.push_back(std::regex(pattern, - std::regex_constants::nosubs | - std::regex_constants::optimize | - std::regex_constants::egrep)); + log_nowarn_regexes.push_back(YS_REGEX_COMPILE(pattern)); } - catch (const std::regex_error& e) { + catch (const YS_REGEX_NS::regex_error& e) { log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str()); } continue; @@ -126,12 +120,9 @@ struct LoggerPass : public Pass { if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2); try { log("Added regex '%s' for warnings to werror list.\n", pattern.c_str()); - log_werror_regexes.push_back(std::regex(pattern, - std::regex_constants::nosubs | - std::regex_constants::optimize | - std::regex_constants::egrep)); + log_werror_regexes.push_back(YS_REGEX_COMPILE(pattern)); } - catch (const std::regex_error& e) { + catch (const YS_REGEX_NS::regex_error& e) { log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str()); } continue; @@ -168,22 +159,13 @@ struct LoggerPass : public Pass { log("Added regex '%s' for warnings to expected %s list.\n", pattern.c_str(), type.c_str()); try { if (type=="error") - log_expect_error.push_back(std::make_pair(std::regex(pattern, - std::regex_constants::nosubs | - std::regex_constants::optimize | - std::regex_constants::egrep), LogExpectedItem(pattern, count))); + log_expect_error.push_back(std::make_pair(YS_REGEX_COMPILE(pattern), LogExpectedItem(pattern, count))); else if (type=="warning") - log_expect_warning.push_back(std::make_pair(std::regex(pattern, - std::regex_constants::nosubs | - std::regex_constants::optimize | - std::regex_constants::egrep), LogExpectedItem(pattern, count))); + log_expect_warning.push_back(std::make_pair(YS_REGEX_COMPILE(pattern), LogExpectedItem(pattern, count))); else - log_expect_log.push_back(std::make_pair(std::regex(pattern, - std::regex_constants::nosubs | - std::regex_constants::optimize | - std::regex_constants::egrep), LogExpectedItem(pattern, count))); + log_expect_log.push_back(std::make_pair(YS_REGEX_COMPILE(pattern), LogExpectedItem(pattern, count))); } - catch (const std::regex_error& e) { + catch (const YS_REGEX_NS::regex_error& e) { log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str()); } continue; diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 581652a41..e6c189c3e 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1553,6 +1553,11 @@ struct AbcPass : public Pass { show_tempdir = design->scratchpad_get_bool("abc.showtmp", show_tempdir); markgroups = design->scratchpad_get_bool("abc.markgroups", markgroups); + if (design->scratchpad_get_bool("abc.debug")) { + cleanup = false; + show_tempdir = true; + } + size_t argidx, g_argidx; bool g_arg_from_cmd = false; char pwd [PATH_MAX]; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5e650230d..212e0692d 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -332,9 +332,9 @@ struct Abc9Pass : public ScriptPass tempdir_name = make_temp_dir(tempdir_name); if (!lut_mode) - run(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str())); - run(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str())); - run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); + run_nocheck(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str())); + run_nocheck(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str())); + run_nocheck(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs"); @@ -350,9 +350,9 @@ struct Abc9Pass : public ScriptPass if (!lut_mode) abc9_exe_cmd += stringf(" -lut %s/input.lut", tempdir_name.c_str()); abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str()); - run(abc9_exe_cmd); - run(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name.c_str(), tempdir_name.c_str())); - run("abc9_ops -reintegrate"); + run_nocheck(abc9_exe_cmd); + run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name.c_str(), tempdir_name.c_str())); + run_nocheck("abc9_ops -reintegrate"); } else log("Don't call ABC as there is nothing to map.\n"); @@ -361,7 +361,7 @@ struct Abc9Pass : public ScriptPass log("Removing temp directory.\n"); remove_directory(tempdir_name); } - + mod->check(); active_design->selection().selected_modules.clear(); log_pop(); } diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index b0bd81698..e1baf4e3d 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -93,9 +93,10 @@ void check(RTLIL::Design *design) void mark_scc(RTLIL::Module *module) { // For every unique SCC found, (arbitrarily) find the first - // cell in the component, and convert all wires driven by - // its output ports into a new PO, and drive its previous - // sinks with a new PI + // cell in the component, and replace its output connections + // with a new wire driven by the old connection but with a + // special (* abc9_scc *) attribute set (which is used by + // write_xaiger to break this wire into PI and POs) pool<RTLIL::Const> ids_seen; for (auto cell : module->cells()) { auto it = cell->attributes.find(ID(abc9_scc_id)); @@ -109,15 +110,13 @@ void mark_scc(RTLIL::Module *module) for (auto &c : cell->connections_) { if (c.second.is_fully_const()) continue; if (cell->output(c.first)) { - SigBit b = c.second.as_bit(); - Wire *w = b.wire; - w->set_bool_attribute(ID::keep); - w->attributes[ID(abc9_scc_id)] = id.as_int(); + Wire *w = module->addWire(NEW_ID, GetSize(c.second)); + w->set_bool_attribute(ID(abc9_scc)); + module->connect(w, c.second); + c.second = w; } } } - - module->fixup_ports(); } void prep_dff(RTLIL::Module *module) @@ -967,10 +966,8 @@ void reintegrate(RTLIL::Module *module) RTLIL::Wire *mapped_wire = mapped_mod->wire(port); RTLIL::Wire *wire = module->wire(port); log_assert(wire); - if (wire->attributes.erase(ID(abc9_scc_id))) { - auto r YS_ATTRIBUTE(unused) = wire->attributes.erase(ID::keep); - log_assert(r); - } + wire->attributes.erase(ID(abc9_scc)); + RTLIL::Wire *remap_wire = module->wire(remap_name(port)); RTLIL::SigSpec signal(wire, 0, GetSize(remap_wire)); log_assert(GetSize(signal) >= GetSize(remap_wire)); diff --git a/passes/techmap/deminout.cc b/passes/techmap/deminout.cc index b976b401b..35d43b106 100644 --- a/passes/techmap/deminout.cc +++ b/passes/techmap/deminout.cc @@ -121,8 +121,7 @@ struct DeminoutPass : public Pass { goto tribuf_bit; } else { tribuf_bit: - if (bits_used.count(bit)) - new_input = true; + new_input = true; } } diff --git a/techlibs/common/gate2lut.v b/techlibs/common/gate2lut.v index 99c123f4a..15cea3d8d 100644 --- a/techlibs/common/gate2lut.v +++ b/techlibs/common/gate2lut.v @@ -79,7 +79,7 @@ module _90_lut_mux (A, B, S, Y); // A 1010 1010 // B 1100 1100 // S 1111 0000 - .LUT(8'b_1100_1010) + .LUT(8'b 1100_1010) ) lut ( .A(AA), .Y(Y) diff --git a/techlibs/ecp5/brams_map.v b/techlibs/ecp5/brams_map.v index 310aedaf2..edda17c02 100644 --- a/techlibs/ecp5/brams_map.v +++ b/techlibs/ecp5/brams_map.v @@ -137,8 +137,6 @@ module \$__ECP5_PDPW16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN localparam CLKWMUX = CLKPOL2 ? "CLKA" : "INV"; localparam CLKRMUX = CLKPOL3 ? "CLKB" : "INV"; - localparam WRITEMODE_A = TRANSP2 ? "WRITETHROUGH" : "READBEFOREWRITE"; - PDPW16KD #( `include "bram_init_9_18_36.vh" .DATA_WIDTH_W(36), diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 17fe2ec99..aa1d7aa86 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -2350,16 +2350,19 @@ module SB_SPRAM256KA ( if (off) begin DATAOUT <= 0; end else - if (CHIPSELECT && !STANDBY && !WREN) begin - DATAOUT <= mem[ADDRESS]; - end else begin - if (CHIPSELECT && !STANDBY && WREN) begin + if (STANDBY) begin + DATAOUT <= 'bx; + end else + if (CHIPSELECT) begin + if (!WREN) begin + DATAOUT <= mem[ADDRESS]; + end else begin if (MASKWREN[0]) mem[ADDRESS][ 3: 0] = DATAIN[ 3: 0]; if (MASKWREN[1]) mem[ADDRESS][ 7: 4] = DATAIN[ 7: 4]; if (MASKWREN[2]) mem[ADDRESS][11: 8] = DATAIN[11: 8]; if (MASKWREN[3]) mem[ADDRESS][15:12] = DATAIN[15:12]; + DATAOUT <= 'bx; end - DATAOUT <= 'bx; end end `endif diff --git a/tests/simple/partsel.v b/tests/simple/partsel.v index 7461358ad..83493fcb0 100644 --- a/tests/simple/partsel.v +++ b/tests/simple/partsel.v @@ -60,3 +60,7 @@ always @(posedge clk) begin end endmodule + +module partsel_test003(input [2:0] a, b, input [31:0] din, output [3:0] dout); +assign dout = din[a*b +: 2]; +endmodule diff --git a/tests/various/bug1745.ys b/tests/various/bug1745.ys new file mode 100644 index 000000000..2e5b8c2d4 --- /dev/null +++ b/tests/various/bug1745.ys @@ -0,0 +1,8 @@ +logger -expect error "syntax error, unexpected TOK_CONSTVAL" 1 +read_verilog <<EOT +module inverter(input a, output y); + + assign y = (a == 1'b0? 1'b1 : 1'b0); + +endmodule // inverter +EOT diff --git a/tests/various/constcomment.ys b/tests/various/constcomment.ys new file mode 100644 index 000000000..f4f2e75d8 --- /dev/null +++ b/tests/various/constcomment.ys @@ -0,0 +1,16 @@ +read_verilog <<EOT +module top1; + localparam a = 8 /*foo*/ 'h ab; + localparam b = 8 'h /*foo*/ cd; + generate + if (a != 8'b10101011) $error("a incorrect!"); + if (b != 8'b11001101) $error("b incorrect!"); + endgenerate +endmodule +EOT +logger -expect error "syntax error, unexpected TOK_BASE" 1 +read_verilog <<EOT +module top2; + localparam a = 12'h4 /*foo*/'b0; +endmodule +EOT diff --git a/tests/various/deminout_unused.ys b/tests/various/deminout_unused.ys new file mode 100644 index 000000000..5ed00509d --- /dev/null +++ b/tests/various/deminout_unused.ys @@ -0,0 +1,14 @@ +read_verilog <<EOT +module top(input clk, inout [7:0] x); + +reg [3:0] ctr; +always @(posedge clk) ctr <= ctr + 1'b1; + +assign x[7:4] = ctr; +endmodule +EOT +proc +tribuf +deminout +select -assert-count 1 i:x o:x %i + diff --git a/tests/various/logger_error.ys b/tests/various/logger_error.ys new file mode 100644 index 000000000..46fe7f506 --- /dev/null +++ b/tests/various/logger_error.ys @@ -0,0 +1,6 @@ +logger -werror "is implicitly declared." -expect error "is implicitly declared." 1 +read_verilog << EOF +module top(...); + assign b = w; +endmodule +EOF diff --git a/tests/various/logger_nowarning.ys b/tests/various/logger_nowarning.ys new file mode 100644 index 000000000..87cbbc644 --- /dev/null +++ b/tests/various/logger_nowarning.ys @@ -0,0 +1,6 @@ +logger -expect-no-warnings -nowarn "is implicitly declared." +read_verilog << EOF +module top(...); + assign b = w; +endmodule +EOF diff --git a/tests/various/logger_warn.ys b/tests/various/logger_warn.ys new file mode 100644 index 000000000..2316ae4c6 --- /dev/null +++ b/tests/various/logger_warn.ys @@ -0,0 +1,6 @@ +logger -warn "Successfully finished Verilog frontend." -expect warning "Successfully finished Verilog frontend." 1 +read_verilog << EOF +module top(...); + assign b = w; +endmodule +EOF diff --git a/tests/various/logger_warning.ys b/tests/various/logger_warning.ys new file mode 100644 index 000000000..642b1b97b --- /dev/null +++ b/tests/various/logger_warning.ys @@ -0,0 +1,6 @@ +logger -expect warning "is implicitly declared." 2 +read_verilog << EOF +module top(...); + assign b = w; +endmodule +EOF diff --git a/tests/various/src.ys b/tests/various/src.ys new file mode 100644 index 000000000..89d6700ca --- /dev/null +++ b/tests/various/src.ys @@ -0,0 +1,8 @@ +logger -expect warning "wire '\\o' is assigned in a block at <<EOT:2.11-2.17" 1 +logger -expect warning "wire '\\p' is assigned in a block at <<EOT:3.11-3.16" 1 +read_verilog <<EOT +module top(input i, output o, p); +always @* o <= i; +always @* p = i; +endmodule +EOT |