From ac10e7d96da4965751fd60a8dd42a8998c011c39 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Fri, 3 May 2019 03:10:43 +0300 Subject: [PATCH 01/15] Initial implementation of elaboration system tasks (IEEE1800-2017 section 20.11) This PR allows us to use $info/$warning/$error/$fatal **at elaboration time** within a generate block. This is very useful to stop a synthesis of a parametrized block when an illegal combination of parameters is chosen. --- frontends/ast/ast.cc | 1 + frontends/ast/ast.h | 4 ++- frontends/ast/genrtlil.cc | 1 + frontends/ast/simplify.cc | 47 ++++++++++++++++++++++++++++-- frontends/verilog/verilog_lexer.l | 5 ++++ frontends/verilog/verilog_parser.y | 11 ++++++- kernel/log.cc | 11 +++++++ kernel/log.h | 1 + tests/various/elab_sys_tasks.sv | 30 +++++++++++++++++++ tests/various/elab_sys_tasks.ys | 1 + 10 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 tests/various/elab_sys_tasks.sv create mode 100644 tests/various/elab_sys_tasks.ys diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 9f88b08c1..d28345503 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -154,6 +154,7 @@ std::string AST::type2str(AstNodeType type) X(AST_GENIF) X(AST_GENCASE) X(AST_GENBLOCK) + X(AST_TECALL) X(AST_POSEDGE) X(AST_NEGEDGE) X(AST_EDGE) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 281cbe086..b3e6fbaa0 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -137,7 +137,8 @@ namespace AST AST_GENIF, AST_GENCASE, AST_GENBLOCK, - + AST_TECALL, + AST_POSEDGE, AST_NEGEDGE, AST_EDGE, @@ -233,6 +234,7 @@ namespace AST bool mem2reg_check(pool &mem2reg_set); void mem2reg_remove(pool &mem2reg_set, vector &delnodes); void meminfo(int &mem_width, int &mem_size, int &addr_bits); + bool check_elab_tasks(void); // additional functionality for evaluating constant functions struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; }; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index b3a2a84be..d5e7d94ab 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -856,6 +856,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_GENVAR: case AST_GENFOR: case AST_GENBLOCK: + case AST_TECALL: case AST_GENIF: case AST_GENCASE: case AST_PACKAGE: diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 4d4b9dfe1..e6132995d 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1146,7 +1146,8 @@ 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); + if (!buf->children[i]->check_elab_tasks()) + buf->children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(buf->children[i]); } } else { @@ -1261,7 +1262,8 @@ 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); + if (!buf->children[i]->check_elab_tasks()) + buf->children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(buf->children[i]); } @@ -1340,7 +1342,8 @@ 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); + if (!buf->children[i]->check_elab_tasks()) + buf->children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(buf->children[i]); } @@ -2969,6 +2972,44 @@ static void mark_memories_assign_lhs_complex(dict> & } } +// handle $info(), $warning(), $error(), $fatal() +// we don't do that in simplify() because we don't know +bool AstNode::check_elab_tasks(void) +{ + if (type == AST_TECALL) { + int sz = children.size(); + if (str == "$info") { + if (sz > 0) + log_file_info(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_info(filename, linenum, "\n"); + } else if (str == "$warning") { + if (sz > 0) + log_file_warning(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_warning(filename, linenum, "\n"); + } else if (str == "$error") { + if (sz > 0) + log_file_error(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_error(filename, linenum, "\n"); + } else if (str == "$fatal") { + // TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish() + // if no parameter is given, default value is 1 + // dollar_finish(sz ? children[0] : 1); + // perhaps create & use log_file_fatal() + if (sz > 0) + log_file_error(filename, linenum, "FATAL: %s.\n", children[0]->str.c_str()); + else + log_file_error(filename, linenum, "FATAL.\n"); + } else { + log_file_error(filename, linenum, "Unknown elabortoon system task '%s'.\n", str.c_str()); + } + return true; + } + return false; + +} // find memories that should be replaced by registers void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg_places, dict &mem2reg_candidates, dict &proc_flags, uint32_t &flags) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 6ef38252a..1c6810b47 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -301,6 +301,11 @@ supply1 { return TOK_SUPPLY1; } return TOK_ID; } +"$"(info|warning|error|fatal) { + frontend_verilog_yylval.string = new std::string(yytext); + return TOK_ELAB_TASK; +} + "$signed" { return TOK_TO_SIGNED; } "$unsigned" { return TOK_TO_UNSIGNED; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 40968d17a..1965f090e 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -105,7 +105,7 @@ static void free_attr(std::map *al) bool boolean; } -%token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE TOK_SVA_LABEL +%token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE TOK_SVA_LABEL TOK_ELAB_TASK %token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM @@ -1869,6 +1869,15 @@ gen_stmt: if ($6 != NULL) delete $6; ast_stack.pop_back(); + } | + TOK_ELAB_TASK { + AstNode *node = new AstNode(AST_TECALL); + node->str = *$1; + delete $1; + ast_stack.back()->children.push_back(node); + ast_stack.push_back(node); + } opt_arg_list ';'{ + ast_stack.pop_back(); }; gen_stmt_block: diff --git a/kernel/log.cc b/kernel/log.cc index 9a9104e26..d2a661bb0 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -278,6 +278,17 @@ void log_file_warning(const std::string &filename, int lineno, va_end(ap); } +void log_file_info(const std::string &filename, int lineno, + const char *format, ...) +{ + va_list ap; + va_start(ap, format); + std::string prefix = stringf("%s:%d: Info: ", + filename.c_str(), lineno); + logv_warning_with_prefix(prefix.c_str(), format, ap); + va_end(ap); +} + YS_ATTRIBUTE(noreturn) static void logv_error_with_prefix(const char *prefix, const char *format, va_list ap) diff --git a/kernel/log.h b/kernel/log.h index e6afae716..3e1facae8 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -80,6 +80,7 @@ void log_warning(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); // Log with filename to report a problem in a source file. void log_file_warning(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4)); +void log_file_info(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4)); void log_warning_noprefix(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn); diff --git a/tests/various/elab_sys_tasks.sv b/tests/various/elab_sys_tasks.sv new file mode 100644 index 000000000..774d85b32 --- /dev/null +++ b/tests/various/elab_sys_tasks.sv @@ -0,0 +1,30 @@ +module test; +localparam X=1; +genvar i; +generate +if (X == 1) + $info("X is 1"); +if (X == 1) + $warning("X is 1"); +else + $error("X is not 1"); +case (X) + 1: $info("X is 1 in a case statement"); +endcase +//case (X-1) +// 1: $warn("X is 2"); +// default: $warn("X might be anything in a case statement"); +//endcase +for (i = 0; i < 3; i = i + 1) +begin + case(i) + 0: $info; + 1: $warning; + default: $info("default case statemnent"); + endcase +end + +$info("This is a standalone $info(). Next $info has no parameters"); +$info; +endgenerate +endmodule diff --git a/tests/various/elab_sys_tasks.ys b/tests/various/elab_sys_tasks.ys new file mode 100644 index 000000000..45bee3a60 --- /dev/null +++ b/tests/various/elab_sys_tasks.ys @@ -0,0 +1 @@ +read_verilog -sv elab_sys_tasks.sv From 88f59770932720cfc1e987c98e53faedd7388ed8 Mon Sep 17 00:00:00 2001 From: tux3 Date: Wed, 5 Jun 2019 00:47:54 +0200 Subject: [PATCH 02/15] SystemVerilog support for implicit named port connections This is the `foo foo(.port1, .port2);` SystemVerilog syntax introduced in IEEE1800-2005. --- frontends/verilog/verilog_parser.y | 26 +++++++++++++++++--------- tests/simple/run-test.sh | 3 ++- tests/tools/autotest.sh | 15 +++++++++++++-- tests/various/implicit_ports.sv | 19 +++++++++++++++++++ tests/various/implicit_ports.ys | 8 ++++++++ 5 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 tests/various/implicit_ports.sv create mode 100644 tests/various/implicit_ports.ys diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 8244a8f44..983445011 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -154,7 +154,7 @@ struct specify_rise_fall { %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int -%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list +%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list named_port %type opt_label opt_sva_label tok_prim_wrapper hierarchical_id %type opt_signed opt_property unique_case_attr %type attr case_attr @@ -1541,18 +1541,26 @@ cell_port: astbuf2->children.push_back(node); node->children.push_back($1); } | - '.' TOK_ID '(' expr ')' { - AstNode *node = new AstNode(AST_ARGUMENT); - node->str = *$2; - astbuf2->children.push_back(node); - node->children.push_back($4); - delete $2; + named_port '(' ')' | // not connected + named_port '(' expr ')' { + ($1)->children.push_back($3); } | - '.' TOK_ID '(' ')' { + named_port { + // SV implied port + if (!sv_mode) + frontend_verilog_yyerror("Implicit .name port connection in port list (%s). This is not supported unless read_verilog is called with -sv!", $1->str.c_str()); + auto id_node = new AstNode(AST_IDENTIFIER); + id_node->str = ($1)->str; + ($1)->children.push_back(id_node); + }; + +named_port: + '.' TOK_ID { AstNode *node = new AstNode(AST_ARGUMENT); node->str = *$2; - astbuf2->children.push_back(node); delete $2; + astbuf2->children.push_back(node); + $$ = node; }; always_stmt: diff --git a/tests/simple/run-test.sh b/tests/simple/run-test.sh index aaa1cf940..967ac49f2 100755 --- a/tests/simple/run-test.sh +++ b/tests/simple/run-test.sh @@ -17,4 +17,5 @@ if ! which iverilog > /dev/null ; then exit 1 fi -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v +shopt -s nullglob +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.{sv,v} diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 920474a84..0a511f29c 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -89,6 +89,13 @@ done compile_and_run() { exe="$1"; output="$2"; shift 2 + ext=${1##*.} + if [ "$ext" == "sv" ]; then + language_gen="-g2012" + else + language_gen="-g2005" + fi + if $use_modelsim; then altver=$( ls -v /opt/altera/ | grep '^[0-9]' | tail -n1; ) /opt/altera/$altver/modelsim_ase/bin/vlib work @@ -99,7 +106,7 @@ compile_and_run() { /opt/Xilinx/Vivado/$xilver/bin/xvlog $xinclude_opts -d outfile=\"$output\" "$@" /opt/Xilinx/Vivado/$xilver/bin/xelab -R work.testbench else - iverilog $include_opts -Doutfile=\"$output\" -s testbench -o "$exe" "$@" + iverilog $language_gen $include_opts -Doutfile=\"$output\" -s testbench -o "$exe" "$@" vvp -n "$exe" fi } @@ -110,7 +117,7 @@ for fn do bn=${fn%.*} ext=${fn##*.} - if [[ "$ext" != "v" ]] && [[ "$ext" != "aag" ]] && [[ "$ext" != "aig" ]]; then + if [[ "$ext" != "v" ]] && [[ "$ext" != "sv" ]] && [[ "$ext" != "aag" ]] && [[ "$ext" != "aig" ]]; then echo "Invalid argument: $fn" >&2 exit 1 fi @@ -123,6 +130,10 @@ do echo -n "Test: $bn " fi + if [ "$ext" == sv ]; then + frontend="$frontend -sv" + fi + rm -f ${bn}.{err,log,skip} mkdir -p ${bn}.out rm -rf ${bn}.out/* diff --git a/tests/various/implicit_ports.sv b/tests/various/implicit_ports.sv new file mode 100644 index 000000000..6a766bd51 --- /dev/null +++ b/tests/various/implicit_ports.sv @@ -0,0 +1,19 @@ +// Test implicit port connections +module alu (input [2:0] a, input [2:0] b, input cin, output cout, output [2:0] result); + assign cout = cin; + assign result = a + b; +endmodule + +module named_ports(output [2:0] alu_result, output cout); + wire [2:0] a = 3'b010, b = 3'b100; + wire cin = 1; + + alu alu ( + .a(a), + .b, // Implicit connection is equivalent to .b(b) + .cin(), // Explicitely unconnected + .cout(cout), + .result(alu_result) + ); +endmodule + diff --git a/tests/various/implicit_ports.ys b/tests/various/implicit_ports.ys new file mode 100644 index 000000000..7b4764921 --- /dev/null +++ b/tests/various/implicit_ports.ys @@ -0,0 +1,8 @@ +read_verilog -sv implicit_ports.sv +proc; opt + +flatten +select -module named_ports + +sat -verify -prove alu_result 6 +sat -verify -set-all-undef cout From d018e026142b9903a6f51b0a76ab109e86c4c59b Mon Sep 17 00:00:00 2001 From: Stefan Biereigel Date: Fri, 7 Jun 2019 09:47:33 +0200 Subject: [PATCH 03/15] remove boost/log/exceptions.hpp from wrapper generator --- misc/py_wrap_generator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py index 9f2c72915..9e5727499 100644 --- a/misc/py_wrap_generator.py +++ b/misc/py_wrap_generator.py @@ -2026,7 +2026,6 @@ def gen_wrappers(filename, debug_level_ = 0): #include #include #include -#include USING_YOSYS_NAMESPACE From a0b57f2a6ffae3b5770e38bf5a9af0df50db8522 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Jun 2019 11:46:16 +0200 Subject: [PATCH 04/15] Cleanup tux3-implicit_named_connection Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 2 +- tests/{various => simple}/implicit_ports.sv | 5 +---- tests/various/implicit_ports.ys | 8 -------- 3 files changed, 2 insertions(+), 13 deletions(-) rename tests/{various => simple}/implicit_ports.sv (78%) delete mode 100644 tests/various/implicit_ports.ys diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 2fffc7536..6d3afed0e 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -154,7 +154,7 @@ struct specify_rise_fall { %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int -%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list named_port +%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list %type opt_label opt_sva_label tok_prim_wrapper hierarchical_id %type opt_signed opt_property unique_case_attr %type attr case_attr diff --git a/tests/various/implicit_ports.sv b/tests/simple/implicit_ports.sv similarity index 78% rename from tests/various/implicit_ports.sv rename to tests/simple/implicit_ports.sv index 6a766bd51..8b0a6f386 100644 --- a/tests/various/implicit_ports.sv +++ b/tests/simple/implicit_ports.sv @@ -4,10 +4,8 @@ module alu (input [2:0] a, input [2:0] b, input cin, output cout, output [2:0] r assign result = a + b; endmodule -module named_ports(output [2:0] alu_result, output cout); - wire [2:0] a = 3'b010, b = 3'b100; +module named_ports(input [2:0] a, b, output [2:0] alu_result, output cout); wire cin = 1; - alu alu ( .a(a), .b, // Implicit connection is equivalent to .b(b) @@ -16,4 +14,3 @@ module named_ports(output [2:0] alu_result, output cout); .result(alu_result) ); endmodule - diff --git a/tests/various/implicit_ports.ys b/tests/various/implicit_ports.ys deleted file mode 100644 index 7b4764921..000000000 --- a/tests/various/implicit_ports.ys +++ /dev/null @@ -1,8 +0,0 @@ -read_verilog -sv implicit_ports.sv -proc; opt - -flatten -select -module named_ports - -sat -verify -prove alu_result 6 -sat -verify -set-all-undef cout From 211d85cfcc1ae701bb9392347bcbb9750e3045b0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Jun 2019 12:41:09 +0200 Subject: [PATCH 05/15] Fixes and cleanups in AST_TECALL handling Signed-off-by: Clifford Wolf --- frontends/ast/ast.h | 1 - frontends/ast/genrtlil.cc | 32 +++++++++++++++++++++++++- frontends/ast/simplify.cc | 47 +++------------------------------------ kernel/log.cc | 8 +++---- 4 files changed, 38 insertions(+), 50 deletions(-) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 93997ab86..b8cde060e 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -234,7 +234,6 @@ namespace AST bool mem2reg_check(pool &mem2reg_set); void mem2reg_remove(pool &mem2reg_set, vector &delnodes); void meminfo(int &mem_width, int &mem_size, int &addr_bits); - bool check_elab_tasks(void); // additional functionality for evaluating constant functions struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; }; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 60a087282..32ed401eb 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -858,7 +858,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_GENVAR: case AST_GENFOR: case AST_GENBLOCK: - case AST_TECALL: case AST_GENIF: case AST_GENCASE: case AST_PACKAGE: @@ -1576,6 +1575,37 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) delete always; } break; + case AST_TECALL: { + int sz = children.size(); + if (str == "$info") { + if (sz > 0) + log_file_info(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_info(filename, linenum, "\n"); + } else if (str == "$warning") { + if (sz > 0) + log_file_warning(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_warning(filename, linenum, "\n"); + } else if (str == "$error") { + if (sz > 0) + log_file_error(filename, linenum, "%s.\n", children[0]->str.c_str()); + else + log_file_error(filename, linenum, "\n"); + } else if (str == "$fatal") { + // TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish() + // if no parameter is given, default value is 1 + // dollar_finish(sz ? children[0] : 1); + // perhaps create & use log_file_fatal() + if (sz > 0) + log_file_error(filename, linenum, "FATAL: %s.\n", children[0]->str.c_str()); + else + log_file_error(filename, linenum, "FATAL.\n"); + } else { + log_file_error(filename, linenum, "Unknown elabortoon system task '%s'.\n", str.c_str()); + } + } break; + case AST_FCALL: { if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") { diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 66fd243d3..e947125bf 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1146,8 +1146,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++) { - if (!buf->children[i]->check_elab_tasks()) - buf->children[i]->simplify(false, false, false, stage, -1, false, false); + buf->children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(buf->children[i]); } } else { @@ -1260,8 +1259,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++) { - if (!buf->children[i]->check_elab_tasks()) - buf->children[i]->simplify(false, false, false, stage, -1, false, false); + buf->children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(buf->children[i]); } @@ -1340,8 +1338,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++) { - if (!buf->children[i]->check_elab_tasks()) - buf->children[i]->simplify(false, false, false, stage, -1, false, false); + buf->children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(buf->children[i]); } @@ -2971,44 +2968,6 @@ static void mark_memories_assign_lhs_complex(dict> & } } -// handle $info(), $warning(), $error(), $fatal() -// we don't do that in simplify() because we don't know -bool AstNode::check_elab_tasks(void) -{ - if (type == AST_TECALL) { - int sz = children.size(); - if (str == "$info") { - if (sz > 0) - log_file_info(filename, linenum, "%s.\n", children[0]->str.c_str()); - else - log_file_info(filename, linenum, "\n"); - } else if (str == "$warning") { - if (sz > 0) - log_file_warning(filename, linenum, "%s.\n", children[0]->str.c_str()); - else - log_file_warning(filename, linenum, "\n"); - } else if (str == "$error") { - if (sz > 0) - log_file_error(filename, linenum, "%s.\n", children[0]->str.c_str()); - else - log_file_error(filename, linenum, "\n"); - } else if (str == "$fatal") { - // TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish() - // if no parameter is given, default value is 1 - // dollar_finish(sz ? children[0] : 1); - // perhaps create & use log_file_fatal() - if (sz > 0) - log_file_error(filename, linenum, "FATAL: %s.\n", children[0]->str.c_str()); - else - log_file_error(filename, linenum, "FATAL.\n"); - } else { - log_file_error(filename, linenum, "Unknown elabortoon system task '%s'.\n", str.c_str()); - } - return true; - } - return false; - -} // find memories that should be replaced by registers void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg_places, dict &mem2reg_candidates, dict &proc_flags, uint32_t &flags) diff --git a/kernel/log.cc b/kernel/log.cc index 9ce952cae..a7820950c 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -277,7 +277,7 @@ void log_file_warning(const std::string &filename, int lineno, va_list ap; va_start(ap, format); std::string prefix = stringf("%s:%d: Warning: ", - filename.c_str(), lineno); + filename.c_str(), lineno); logv_warning_with_prefix(prefix.c_str(), format, ap); va_end(ap); } @@ -287,9 +287,9 @@ void log_file_info(const std::string &filename, int lineno, { va_list ap; va_start(ap, format); - std::string prefix = stringf("%s:%d: Info: ", - filename.c_str(), lineno); - logv_warning_with_prefix(prefix.c_str(), format, ap); + std::string fmt = stringf("%s:%d: Info: %s", + filename.c_str(), lineno, format); + logv(fmt.c_str(), ap); va_end(ap); } From f01a61f093528e5111e5dac8aedbf8c7c468be1c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 7 Jun 2019 13:12:25 +0200 Subject: [PATCH 06/15] Rename implicit_ports.sv test to implicit_ports.v Signed-off-by: Clifford Wolf --- tests/simple/{implicit_ports.sv => implicit_ports.v} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/simple/{implicit_ports.sv => implicit_ports.v} (100%) diff --git a/tests/simple/implicit_ports.sv b/tests/simple/implicit_ports.v similarity index 100% rename from tests/simple/implicit_ports.sv rename to tests/simple/implicit_ports.v From 1b113a05742377f5b18d52bc5bf50b1991e88c19 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:05:25 -0700 Subject: [PATCH 07/15] Add symbols to AIGER test inputs for ABC --- tests/aiger/and.aig | 3 --- tests/aiger/{and.aag => and_.aag} | 3 +++ tests/aiger/and_.aig | 5 +++++ tests/aiger/buffer.aag | 2 ++ tests/aiger/buffer.aig | 2 ++ tests/aiger/cnt1.aag | 1 + tests/aiger/cnt1.aig | 1 + tests/aiger/cnt1e.aag | 1 + tests/aiger/cnt1e.aig | 3 ++- tests/aiger/false.aag | 1 + tests/aiger/false.aig | 1 + tests/aiger/inverter.aag | 2 ++ tests/aiger/inverter.aig | 2 ++ tests/aiger/notcnt1e.aag | 1 + tests/aiger/notcnt1e.aig | 3 ++- tests/aiger/or.aig | 3 --- tests/aiger/{or.aag => or_.aag} | 3 +++ tests/aiger/or_.aig | 5 +++++ tests/aiger/toggle.aag | 2 ++ tests/aiger/toggle.aig | 2 ++ tests/aiger/true.aag | 1 + tests/aiger/true.aig | 1 + 22 files changed, 40 insertions(+), 8 deletions(-) delete mode 100644 tests/aiger/and.aig rename tests/aiger/{and.aag => and_.aag} (55%) create mode 100644 tests/aiger/and_.aig delete mode 100644 tests/aiger/or.aig rename tests/aiger/{or.aag => or_.aag} (55%) create mode 100644 tests/aiger/or_.aig diff --git a/tests/aiger/and.aig b/tests/aiger/and.aig deleted file mode 100644 index da0fa0719..000000000 --- a/tests/aiger/and.aig +++ /dev/null @@ -1,3 +0,0 @@ -aig 3 2 0 1 1 -6 - \ No newline at end of file diff --git a/tests/aiger/and.aag b/tests/aiger/and_.aag similarity index 55% rename from tests/aiger/and.aag rename to tests/aiger/and_.aag index d1ef2c5a5..cadd505f0 100644 --- a/tests/aiger/and.aag +++ b/tests/aiger/and_.aag @@ -3,3 +3,6 @@ aag 3 2 0 1 1 4 6 6 2 4 +i0 pi0 +i1 pi1 +o0 po0 diff --git a/tests/aiger/and_.aig b/tests/aiger/and_.aig new file mode 100644 index 000000000..13c7a0c17 --- /dev/null +++ b/tests/aiger/and_.aig @@ -0,0 +1,5 @@ +aig 3 2 0 1 1 +6 +i0 pi0 +i1 pi1 +o0 po0 diff --git a/tests/aiger/buffer.aag b/tests/aiger/buffer.aag index 94a6fb1ed..211106ed6 100644 --- a/tests/aiger/buffer.aag +++ b/tests/aiger/buffer.aag @@ -1,3 +1,5 @@ aag 1 1 0 1 0 2 2 +i0 pi0 +o0 po0 diff --git a/tests/aiger/buffer.aig b/tests/aiger/buffer.aig index 0c715fdeb..01df6f1cf 100644 --- a/tests/aiger/buffer.aig +++ b/tests/aiger/buffer.aig @@ -1,2 +1,4 @@ aig 1 1 0 1 0 2 +i0 pi0 +o0 po0 diff --git a/tests/aiger/cnt1.aag b/tests/aiger/cnt1.aag index ce4f28fcb..75598862c 100644 --- a/tests/aiger/cnt1.aag +++ b/tests/aiger/cnt1.aag @@ -1,3 +1,4 @@ aag 1 0 1 0 0 1 2 3 2 +b0 po0 diff --git a/tests/aiger/cnt1.aig b/tests/aiger/cnt1.aig index 8d0ba13b1..6fcf62522 100644 --- a/tests/aiger/cnt1.aig +++ b/tests/aiger/cnt1.aig @@ -1,3 +1,4 @@ aig 1 0 1 0 0 1 3 2 +b0 po0 diff --git a/tests/aiger/cnt1e.aag b/tests/aiger/cnt1e.aag index 6db3f0ffd..35cd5a482 100644 --- a/tests/aiger/cnt1e.aag +++ b/tests/aiger/cnt1e.aag @@ -6,3 +6,4 @@ aag 5 1 1 0 3 1 8 4 2 10 9 7 b0 AIGER_NEVER +i0 po0 diff --git a/tests/aiger/cnt1e.aig b/tests/aiger/cnt1e.aig index d8d159f11..7284dd42a 100644 --- a/tests/aiger/cnt1e.aig +++ b/tests/aiger/cnt1e.aig @@ -1,4 +1,5 @@ aig 5 1 1 0 3 1 10 4 -b0 AIGER_NEVER +i0 po0 +b0 AIGER_NEVER diff --git a/tests/aiger/false.aag b/tests/aiger/false.aag index 421e64a91..bab4a06a6 100644 --- a/tests/aiger/false.aag +++ b/tests/aiger/false.aag @@ -1,2 +1,3 @@ aag 0 0 0 1 0 0 +o0 po0 diff --git a/tests/aiger/false.aig b/tests/aiger/false.aig index ad7d039fa..4dc442d7b 100644 --- a/tests/aiger/false.aig +++ b/tests/aiger/false.aig @@ -1,2 +1,3 @@ aig 0 0 0 1 0 0 +o0 po0 diff --git a/tests/aiger/inverter.aag b/tests/aiger/inverter.aag index ff7c28542..428bad9e4 100644 --- a/tests/aiger/inverter.aag +++ b/tests/aiger/inverter.aag @@ -1,3 +1,5 @@ aag 1 1 0 1 0 2 3 +i0 pi0 +o0 po0 diff --git a/tests/aiger/inverter.aig b/tests/aiger/inverter.aig index 525d82392..5bec90ae3 100644 --- a/tests/aiger/inverter.aig +++ b/tests/aiger/inverter.aig @@ -1,2 +1,4 @@ aig 1 1 0 1 0 3 +i0 pi0 +o0 po0 diff --git a/tests/aiger/notcnt1e.aag b/tests/aiger/notcnt1e.aag index 141c864f7..2ed645d84 100644 --- a/tests/aiger/notcnt1e.aag +++ b/tests/aiger/notcnt1e.aag @@ -6,3 +6,4 @@ aag 5 1 1 0 3 1 8 4 2 10 9 7 b0 AIGER_NEVER +i0 pi0 diff --git a/tests/aiger/notcnt1e.aig b/tests/aiger/notcnt1e.aig index 7c85a7290..fd7e94508 100644 --- a/tests/aiger/notcnt1e.aig +++ b/tests/aiger/notcnt1e.aig @@ -1,4 +1,5 @@ aig 5 1 1 0 3 1 10 5 -b0 AIGER_NEVER +i0 pi0 +b0 AIGER_NEVER diff --git a/tests/aiger/or.aig b/tests/aiger/or.aig deleted file mode 100644 index 75c9e4480..000000000 --- a/tests/aiger/or.aig +++ /dev/null @@ -1,3 +0,0 @@ -aig 3 2 0 1 1 -7 - \ No newline at end of file diff --git a/tests/aiger/or.aag b/tests/aiger/or_.aag similarity index 55% rename from tests/aiger/or.aag rename to tests/aiger/or_.aag index f780e339f..0f619dba3 100644 --- a/tests/aiger/or.aag +++ b/tests/aiger/or_.aag @@ -3,3 +3,6 @@ aag 3 2 0 1 1 4 7 6 3 5 +i0 pi0 +i1 pi1 +o0 po0 diff --git a/tests/aiger/or_.aig b/tests/aiger/or_.aig new file mode 100644 index 000000000..051687512 --- /dev/null +++ b/tests/aiger/or_.aig @@ -0,0 +1,5 @@ +aig 3 2 0 1 1 +7 +i0 pi0 +i1 pi1 +o0 po0 diff --git a/tests/aiger/toggle.aag b/tests/aiger/toggle.aag index 09651012d..b1a1582d7 100644 --- a/tests/aiger/toggle.aag +++ b/tests/aiger/toggle.aag @@ -2,3 +2,5 @@ aag 1 0 1 2 0 2 3 2 3 +o0 po0 +o1 po1 diff --git a/tests/aiger/toggle.aig b/tests/aiger/toggle.aig index b69e21aaf..68b41763f 100644 --- a/tests/aiger/toggle.aig +++ b/tests/aiger/toggle.aig @@ -2,3 +2,5 @@ aig 1 0 1 2 0 3 2 3 +o0 po0 +o1 po1 diff --git a/tests/aiger/true.aag b/tests/aiger/true.aag index 366893648..66a9eab46 100644 --- a/tests/aiger/true.aag +++ b/tests/aiger/true.aag @@ -1,2 +1,3 @@ aag 0 0 0 1 0 1 +o0 po0 diff --git a/tests/aiger/true.aig b/tests/aiger/true.aig index 10086f389..f9bad6000 100644 --- a/tests/aiger/true.aig +++ b/tests/aiger/true.aig @@ -1,2 +1,3 @@ aig 0 0 0 1 0 1 +o0 po0 From ebe29b66593414d0317879359d1f1d1f61a9ecc4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:05:36 -0700 Subject: [PATCH 08/15] Use ABC to convert AIGER to Verilog, then sat against Yosys --- tests/aiger/run-test.sh | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh index e0a34f023..70300d305 100755 --- a/tests/aiger/run-test.sh +++ b/tests/aiger/run-test.sh @@ -1,24 +1,18 @@ #!/bin/bash -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac +set -e +for aig in *.aig; do + ../../yosys-abc -c "read -c $aig; write ${aig%.*}_ref.v" + ../../yosys -p " +read_verilog ${aig%.*}_ref.v +prep +design -stash gold +read_aiger -clk_name clock $aig +prep +design -stash gate +design -import gold -as gold +design -import gate -as gate +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -verify -prove-asserts -show-ports -seq 16 miter +" done -shift "$((OPTIND-1))" - -# check for Icarus Verilog -if ! which iverilog > /dev/null ; then - echo "$0: Error: Icarus Verilog 'iverilog' not found." - exit 1 -fi - -echo "===== AAG ======" -${MAKE:-make} -f ../tools/autotest.mk $seed *.aag EXTRA_FLAGS="-f aiger" - -echo "===== AIG ======" -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.aig EXTRA_FLAGS="-f aiger" From abc40924ed5dc4aba91c7f1e83ca90f54e9eb455 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:06:57 -0700 Subject: [PATCH 09/15] Use ABC to convert from AIGER to Verilog --- tests/tools/autotest.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 0a511f29c..23964a751 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -146,9 +146,10 @@ do rm -f ${bn}_ref.fir if [[ "$ext" == "v" ]]; then egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} + elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then + "$toolsdir"/../../yosys-abc -c "read_aiger ../${fn}; write ${bn}_ref.v" else - "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "verilog" -o ${bn}_ref.v ../${fn} - frontend="verilog -noblackbox" + cp ../${fn} ${bn}_ref.${ext} fi if [ ! -f ../${bn}_tb.v ]; then From a04521c6b70396a590f0ddb3081c4c5d6b01671e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:07:15 -0700 Subject: [PATCH 10/15] Fix read_aiger -- create zero driver, fix init width, parse 'b' --- frontends/aiger/aigerparse.cc | 64 ++++++++++++++++++++++++++++------- frontends/aiger/aigerparse.h | 1 + 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 38348cd65..26b101e4c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -81,11 +81,26 @@ end_of_header: else log_abort(); + RTLIL::Wire* n0 = module->wire("\\n0"); + if (n0) + module->connect(n0, RTLIL::S0); + + for (unsigned i = 0; i < outputs.size(); ++i) { + RTLIL::Wire *wire = outputs[i]; + if (wire->port_input) { + RTLIL::Wire *o_wire = module->addWire(wire->name.str() + "_o"); + o_wire->port_output = true; + wire->port_output = false; + module->connect(o_wire, wire); + outputs[i] = o_wire; + } + } + // Parse footer (symbol table, comments, etc.) unsigned l1; std::string s; for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { - if (c == 'i' || c == 'l' || c == 'o') { + if (c == 'i' || c == 'l' || c == 'o' || c == 'b') { f.ignore(1); if (!(f >> l1 >> s)) log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); @@ -97,11 +112,12 @@ end_of_header: if (c == 'i') wire = inputs[l1]; else if (c == 'l') wire = latches[l1]; else if (c == 'o') wire = outputs[l1]; + else if (c == 'b') wire = bad_properties[l1]; else log_abort(); module->rename(wire, stringf("\\%s", s.c_str())); } - else if (c == 'b' || c == 'j' || c == 'f') { + else if (c == 'j' || c == 'f') { // TODO } else if (c == 'c') { @@ -153,7 +169,7 @@ void AigerReader::parse_aiger_ascii() unsigned l1, l2, l3; // Parse inputs - for (unsigned i = 0; i < I; ++i, ++line_count) { + for (unsigned i = 1; i <= I; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an input!\n", line_count); log_debug("%d is an input\n", l1); @@ -187,8 +203,10 @@ void AigerReader::parse_aiger_ascii() if (!(f >> l3)) log_error("Line %u cannot be interpreted as a latch!\n", line_count); - if (l3 == 0 || l3 == 1) - q_wire->attributes["\\init"] = RTLIL::Const(l3); + if (l3 == 0) + q_wire->attributes["\\init"] = RTLIL::S0; + else if (l3 == 1) + q_wire->attributes["\\init"] = RTLIL::S1; else if (l3 == l1) { //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); } @@ -197,7 +215,7 @@ void AigerReader::parse_aiger_ascii() } else { // AIGER latches are assumed to be initialized to zero - q_wire->attributes["\\init"] = RTLIL::Const(0); + q_wire->attributes["\\init"] = RTLIL::S0; } latches.push_back(q_wire); } @@ -214,8 +232,17 @@ void AigerReader::parse_aiger_ascii() } std::getline(f, line); // Ignore up to start of next line - // TODO: Parse bad state properties - for (unsigned i = 0; i < B; ++i, ++line_count) + // Parse bad properties + for (unsigned i = 0; i < B; ++i, ++line_count) { + if (!(f >> l1)) + log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); + + log_debug("%d is a bad state property\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + bad_properties.push_back(wire); + } + if (B > 0) std::getline(f, line); // Ignore up to start of next line // TODO: Parse invariant constraints @@ -290,8 +317,10 @@ void AigerReader::parse_aiger_binary() if (!(f >> l3)) log_error("Line %u cannot be interpreted as a latch!\n", line_count); - if (l3 == 0 || l3 == 1) - q_wire->attributes["\\init"] = RTLIL::Const(l3); + if (l3 == 0) + q_wire->attributes["\\init"] = RTLIL::S0; + else if (l3 == 1) + q_wire->attributes["\\init"] = RTLIL::S1; else if (l3 == l1) { //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); } @@ -300,7 +329,7 @@ void AigerReader::parse_aiger_binary() } else { // AIGER latches are assumed to be initialized to zero - q_wire->attributes["\\init"] = RTLIL::Const(0); + q_wire->attributes["\\init"] = RTLIL::S0; } latches.push_back(q_wire); } @@ -317,8 +346,17 @@ void AigerReader::parse_aiger_binary() } std::getline(f, line); // Ignore up to start of next line - // TODO: Parse bad state properties - for (unsigned i = 0; i < B; ++i, ++line_count) + // Parse bad properties + for (unsigned i = 0; i < B; ++i, ++line_count) { + if (!(f >> l1)) + log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); + + log_debug("%d is a bad state property\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + bad_properties.push_back(wire); + } + if (B > 0) std::getline(f, line); // Ignore up to start of next line // TODO: Parse invariant constraints diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index c49cd152d..0e3719cc4 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -39,6 +39,7 @@ struct AigerReader std::vector inputs; std::vector latches; std::vector outputs; + std::vector bad_properties; AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name); void parse_aiger(); From 65924fd12f48b4ec5a4d51efeea977992d033ecf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:28:05 -0700 Subject: [PATCH 11/15] Test *.aag too, by using *.aig as reference --- tests/aiger/run-test.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh index 70300d305..e56d0fa80 100755 --- a/tests/aiger/run-test.sh +++ b/tests/aiger/run-test.sh @@ -1,6 +1,25 @@ #!/bin/bash set -e + +for aag in *.aag; do + # Since ABC cannot read *.aag, read the *.aig instead + # (which would have been created by the reference aig2aig utility) + ../../yosys-abc -c "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" + ../../yosys -p " +read_verilog ${aag%.*}_ref.v +prep +design -stash gold +read_aiger -clk_name clock $aag +prep +design -stash gate +design -import gold -as gold +design -import gate -as gate +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -verify -prove-asserts -show-ports -seq 16 miter +" +done + for aig in *.aig; do ../../yosys-abc -c "read -c $aig; write ${aig%.*}_ref.v" ../../yosys -p " From d00ae1d6a8c0a1e147599ee27f6a4ea68f43267e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:28:25 -0700 Subject: [PATCH 12/15] Remove unnecessary std::getline() for ASCII --- frontends/aiger/aigerparse.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 26b101e4c..d0338e45d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -230,7 +230,6 @@ void AigerReader::parse_aiger_ascii() wire->port_output = true; outputs.push_back(wire); } - std::getline(f, line); // Ignore up to start of next line // Parse bad properties for (unsigned i = 0; i < B; ++i, ++line_count) { @@ -242,8 +241,6 @@ void AigerReader::parse_aiger_ascii() wire->port_output = true; bad_properties.push_back(wire); } - if (B > 0) - std::getline(f, line); // Ignore up to start of next line // TODO: Parse invariant constraints for (unsigned i = 0; i < C; ++i, ++line_count) From 6934f4bdd53cb226d0c8631eff691d9a96aebbce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:30:36 -0700 Subject: [PATCH 13/15] Fix spacing (entire file is wrong anyway, will fix later) --- frontends/aiger/aigerparse.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index d0338e45d..32be4cf6c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -81,9 +81,9 @@ end_of_header: else log_abort(); - RTLIL::Wire* n0 = module->wire("\\n0"); - if (n0) - module->connect(n0, RTLIL::S0); + RTLIL::Wire* n0 = module->wire("\\n0"); + if (n0) + module->connect(n0, RTLIL::S0); for (unsigned i = 0; i < outputs.size(); ++i) { RTLIL::Wire *wire = outputs[i]; From f48c6920b7aa777c0c569f444e3db88211835cec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 13:12:48 -0700 Subject: [PATCH 14/15] Add read_aiger to CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 36b64e111..839fefcf1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "gate2lut.v" techmap rule - Added "rename -src" - Added "equiv_opt" pass + - Added "read_aiger" frontend - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" From 2b350401c4577d54c0d460240e2d2847d2eeadc4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 15:44:57 -0700 Subject: [PATCH 15/15] Fix spacing from spaces to tabs --- frontends/aiger/aigerparse.cc | 634 +++++++++++++++++----------------- 1 file changed, 317 insertions(+), 317 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 32be4cf6c..68552fd06 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -34,389 +34,389 @@ YOSYS_NAMESPACE_BEGIN AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name) - : design(design), f(f), clk_name(clk_name) + : design(design), f(f), clk_name(clk_name) { - module = new RTLIL::Module; - module->name = module_name; - if (design->module(module->name)) - log_error("Duplicate definition of module %s!\n", log_id(module->name)); + module = new RTLIL::Module; + module->name = module_name; + if (design->module(module->name)) + log_error("Duplicate definition of module %s!\n", log_id(module->name)); } void AigerReader::parse_aiger() { - std::string header; - f >> header; - if (header != "aag" && header != "aig") - log_error("Unsupported AIGER file!\n"); + std::string header; + f >> header; + if (header != "aag" && header != "aig") + log_error("Unsupported AIGER file!\n"); - // Parse rest of header - if (!(f >> M >> I >> L >> O >> A)) - log_error("Invalid AIGER header\n"); + // Parse rest of header + if (!(f >> M >> I >> L >> O >> A)) + log_error("Invalid AIGER header\n"); - // Optional values - B = C = J = F = 0; - if (f.peek() != ' ') goto end_of_header; - if (!(f >> B)) log_error("Invalid AIGER header\n"); - if (f.peek() != ' ') goto end_of_header; - if (!(f >> C)) log_error("Invalid AIGER header\n"); - if (f.peek() != ' ') goto end_of_header; - if (!(f >> J)) log_error("Invalid AIGER header\n"); - if (f.peek() != ' ') goto end_of_header; - if (!(f >> F)) log_error("Invalid AIGER header\n"); + // Optional values + B = C = J = F = 0; + if (f.peek() != ' ') goto end_of_header; + if (!(f >> B)) log_error("Invalid AIGER header\n"); + if (f.peek() != ' ') goto end_of_header; + if (!(f >> C)) log_error("Invalid AIGER header\n"); + if (f.peek() != ' ') goto end_of_header; + if (!(f >> J)) log_error("Invalid AIGER header\n"); + if (f.peek() != ' ') goto end_of_header; + if (!(f >> F)) log_error("Invalid AIGER header\n"); end_of_header: - std::string line; - std::getline(f, line); // Ignore up to start of next line, as standard - // says anything that follows could be used for - // optional sections + std::string line; + std::getline(f, line); // Ignore up to start of next line, as standard + // says anything that follows could be used for + // optional sections - log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F); + log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F); - line_count = 1; + line_count = 1; - if (header == "aag") - parse_aiger_ascii(); - else if (header == "aig") - parse_aiger_binary(); - else - log_abort(); + if (header == "aag") + parse_aiger_ascii(); + else if (header == "aig") + parse_aiger_binary(); + else + log_abort(); - RTLIL::Wire* n0 = module->wire("\\n0"); - if (n0) - module->connect(n0, RTLIL::S0); + RTLIL::Wire* n0 = module->wire("\\n0"); + if (n0) + module->connect(n0, RTLIL::S0); - for (unsigned i = 0; i < outputs.size(); ++i) { - RTLIL::Wire *wire = outputs[i]; - if (wire->port_input) { - RTLIL::Wire *o_wire = module->addWire(wire->name.str() + "_o"); - o_wire->port_output = true; - wire->port_output = false; - module->connect(o_wire, wire); - outputs[i] = o_wire; - } - } + for (unsigned i = 0; i < outputs.size(); ++i) { + RTLIL::Wire *wire = outputs[i]; + if (wire->port_input) { + RTLIL::Wire *o_wire = module->addWire(wire->name.str() + "_o"); + o_wire->port_output = true; + wire->port_output = false; + module->connect(o_wire, wire); + outputs[i] = o_wire; + } + } - // Parse footer (symbol table, comments, etc.) - unsigned l1; - std::string s; - for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { - if (c == 'i' || c == 'l' || c == 'o' || c == 'b') { - f.ignore(1); - if (!(f >> l1 >> s)) - log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); + // Parse footer (symbol table, comments, etc.) + unsigned l1; + std::string s; + for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { + if (c == 'i' || c == 'l' || c == 'o' || c == 'b') { + f.ignore(1); + if (!(f >> l1 >> s)) + log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); - if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) - log_error("Line %u has invalid symbol position!\n", line_count); + if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) + log_error("Line %u has invalid symbol position!\n", line_count); - RTLIL::Wire* wire; - if (c == 'i') wire = inputs[l1]; - else if (c == 'l') wire = latches[l1]; - else if (c == 'o') wire = outputs[l1]; - else if (c == 'b') wire = bad_properties[l1]; - else log_abort(); + RTLIL::Wire* wire; + if (c == 'i') wire = inputs[l1]; + else if (c == 'l') wire = latches[l1]; + else if (c == 'o') wire = outputs[l1]; + else if (c == 'b') wire = bad_properties[l1]; + else log_abort(); - module->rename(wire, stringf("\\%s", s.c_str())); - } - else if (c == 'j' || c == 'f') { - // TODO - } - else if (c == 'c') { - f.ignore(1); - if (f.peek() == '\n') - break; - // Else constraint (TODO) - } - else - log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); - std::getline(f, line); // Ignore up to start of next line - } + module->rename(wire, stringf("\\%s", s.c_str())); + } + else if (c == 'j' || c == 'f') { + // TODO + } + else if (c == 'c') { + f.ignore(1); + if (f.peek() == '\n') + break; + // Else constraint (TODO) + } + else + log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); + std::getline(f, line); // Ignore up to start of next line + } - module->fixup_ports(); - design->add(module); + module->fixup_ports(); + design->add(module); } static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal) { - const unsigned variable = literal >> 1; - const bool invert = literal & 1; - RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? - RTLIL::Wire *wire = module->wire(wire_name); - if (wire) return wire; - log_debug("Creating %s\n", wire_name.c_str()); - wire = module->addWire(wire_name); - if (!invert) return wire; - RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); - RTLIL::Wire *wire_inv = module->wire(wire_inv_name); - if (wire_inv) { - if (module->cell(wire_inv_name)) return wire; - } - else { - log_debug("Creating %s\n", wire_inv_name.c_str()); - wire_inv = module->addWire(wire_inv_name); - } + const unsigned variable = literal >> 1; + const bool invert = literal & 1; + RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? + RTLIL::Wire *wire = module->wire(wire_name); + if (wire) return wire; + log_debug("Creating %s\n", wire_name.c_str()); + wire = module->addWire(wire_name); + if (!invert) return wire; + RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); + RTLIL::Wire *wire_inv = module->wire(wire_inv_name); + if (wire_inv) { + if (module->cell(wire_inv_name)) return wire; + } + else { + log_debug("Creating %s\n", wire_inv_name.c_str()); + wire_inv = module->addWire(wire_inv_name); + } - log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); - module->addNotGate(stringf("\\n%d_not", variable), wire_inv, wire); // FIXME: is "_not" the right suffix? + log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); + module->addNotGate(stringf("\\n%d_not", variable), wire_inv, wire); // FIXME: is "_not" the right suffix? - return wire; + return wire; } void AigerReader::parse_aiger_ascii() { - std::string line; - std::stringstream ss; + std::string line; + std::stringstream ss; - unsigned l1, l2, l3; + unsigned l1, l2, l3; - // Parse inputs - for (unsigned i = 1; i <= I; ++i, ++line_count) { - if (!(f >> l1)) - log_error("Line %u cannot be interpreted as an input!\n", line_count); - log_debug("%d is an input\n", l1); - log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? - RTLIL::Wire *wire = createWireIfNotExists(module, l1); - wire->port_input = true; - inputs.push_back(wire); - } + // Parse inputs + for (unsigned i = 1; i <= I; ++i, ++line_count) { + if (!(f >> l1)) + log_error("Line %u cannot be interpreted as an input!\n", line_count); + log_debug("%d is an input\n", l1); + log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_input = true; + inputs.push_back(wire); + } - // Parse latches - RTLIL::Wire *clk_wire = nullptr; - if (L > 0) { - clk_wire = module->wire(clk_name); - log_assert(!clk_wire); - log_debug("Creating %s\n", clk_name.c_str()); - clk_wire = module->addWire(clk_name); - clk_wire->port_input = true; - } - for (unsigned i = 0; i < L; ++i, ++line_count) { - if (!(f >> l1 >> l2)) - log_error("Line %u cannot be interpreted as a latch!\n", line_count); - log_debug("%d %d is a latch\n", l1, l2); - log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? - RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); - RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); + // Parse latches + RTLIL::Wire *clk_wire = nullptr; + if (L > 0) { + clk_wire = module->wire(clk_name); + log_assert(!clk_wire); + log_debug("Creating %s\n", clk_name.c_str()); + clk_wire = module->addWire(clk_name); + clk_wire->port_input = true; + } + for (unsigned i = 0; i < L; ++i, ++line_count) { + if (!(f >> l1 >> l2)) + log_error("Line %u cannot be interpreted as a latch!\n", line_count); + log_debug("%d %d is a latch\n", l1, l2); + log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? + RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); - module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire); + module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire); - // Reset logic is optional in AIGER 1.9 - if (f.peek() == ' ') { - if (!(f >> l3)) - log_error("Line %u cannot be interpreted as a latch!\n", line_count); + // Reset logic is optional in AIGER 1.9 + if (f.peek() == ' ') { + if (!(f >> l3)) + log_error("Line %u cannot be interpreted as a latch!\n", line_count); - if (l3 == 0) - q_wire->attributes["\\init"] = RTLIL::S0; - else if (l3 == 1) - q_wire->attributes["\\init"] = RTLIL::S1; - else if (l3 == l1) { - //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); - } - else - log_error("Line %u has invalid reset literal for latch!\n", line_count); - } - else { - // AIGER latches are assumed to be initialized to zero - q_wire->attributes["\\init"] = RTLIL::S0; - } - latches.push_back(q_wire); - } + if (l3 == 0) + q_wire->attributes["\\init"] = RTLIL::S0; + else if (l3 == 1) + q_wire->attributes["\\init"] = RTLIL::S1; + else if (l3 == l1) { + //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); + } + else + log_error("Line %u has invalid reset literal for latch!\n", line_count); + } + else { + // AIGER latches are assumed to be initialized to zero + q_wire->attributes["\\init"] = RTLIL::S0; + } + latches.push_back(q_wire); + } - // Parse outputs - for (unsigned i = 0; i < O; ++i, ++line_count) { - if (!(f >> l1)) - log_error("Line %u cannot be interpreted as an output!\n", line_count); + // Parse outputs + for (unsigned i = 0; i < O; ++i, ++line_count) { + if (!(f >> l1)) + log_error("Line %u cannot be interpreted as an output!\n", line_count); - log_debug("%d is an output\n", l1); - RTLIL::Wire *wire = createWireIfNotExists(module, l1); - wire->port_output = true; - outputs.push_back(wire); - } + log_debug("%d is an output\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + outputs.push_back(wire); + } - // Parse bad properties - for (unsigned i = 0; i < B; ++i, ++line_count) { - if (!(f >> l1)) - log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); + // Parse bad properties + for (unsigned i = 0; i < B; ++i, ++line_count) { + if (!(f >> l1)) + log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); - log_debug("%d is a bad state property\n", l1); - RTLIL::Wire *wire = createWireIfNotExists(module, l1); - wire->port_output = true; - bad_properties.push_back(wire); - } + log_debug("%d is a bad state property\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + bad_properties.push_back(wire); + } - // TODO: Parse invariant constraints - for (unsigned i = 0; i < C; ++i, ++line_count) - std::getline(f, line); // Ignore up to start of next line + // TODO: Parse invariant constraints + for (unsigned i = 0; i < C; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line - // TODO: Parse justice properties - for (unsigned i = 0; i < J; ++i, ++line_count) - std::getline(f, line); // Ignore up to start of next line + // TODO: Parse justice properties + for (unsigned i = 0; i < J; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line - // TODO: Parse fairness constraints - for (unsigned i = 0; i < F; ++i, ++line_count) - std::getline(f, line); // Ignore up to start of next line + // TODO: Parse fairness constraints + for (unsigned i = 0; i < F; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line - // Parse AND - for (unsigned i = 0; i < A; ++i) { - if (!(f >> l1 >> l2 >> l3)) - log_error("Line %u cannot be interpreted as an AND!\n", line_count); + // Parse AND + for (unsigned i = 0; i < A; ++i) { + if (!(f >> l1 >> l2 >> l3)) + log_error("Line %u cannot be interpreted as an AND!\n", line_count); - log_debug("%d %d %d is an AND\n", l1, l2, l3); - log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? - RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); - RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); - RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - module->addAndGate(NEW_ID, i1_wire, i2_wire, o_wire); - } - std::getline(f, line); // Ignore up to start of next line + log_debug("%d %d %d is an AND\n", l1, l2, l3); + log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? + RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); + module->addAndGate(NEW_ID, i1_wire, i2_wire, o_wire); + } + std::getline(f, line); // Ignore up to start of next line } static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) { - unsigned x = 0, i = 0; - unsigned char ch; - while ((ch = f.get()) & 0x80) - x |= (ch & 0x7f) << (7 * i++); - return ref - (x | (ch << (7 * i))); + unsigned x = 0, i = 0; + unsigned char ch; + while ((ch = f.get()) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + return ref - (x | (ch << (7 * i))); } void AigerReader::parse_aiger_binary() { - unsigned l1, l2, l3; - std::string line; + unsigned l1, l2, l3; + std::string line; - // Parse inputs - for (unsigned i = 1; i <= I; ++i) { - RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); - wire->port_input = true; - inputs.push_back(wire); - } + // Parse inputs + for (unsigned i = 1; i <= I; ++i) { + RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); + wire->port_input = true; + inputs.push_back(wire); + } - // Parse latches - RTLIL::Wire *clk_wire = nullptr; - if (L > 0) { - clk_wire = module->wire(clk_name); - log_assert(!clk_wire); - log_debug("Creating %s\n", clk_name.c_str()); - clk_wire = module->addWire(clk_name); - clk_wire->port_input = true; - } - l1 = (I+1) * 2; - for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) { - if (!(f >> l2)) - log_error("Line %u cannot be interpreted as a latch!\n", line_count); - log_debug("%d %d is a latch\n", l1, l2); - RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); - RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); + // Parse latches + RTLIL::Wire *clk_wire = nullptr; + if (L > 0) { + clk_wire = module->wire(clk_name); + log_assert(!clk_wire); + log_debug("Creating %s\n", clk_name.c_str()); + clk_wire = module->addWire(clk_name); + clk_wire->port_input = true; + } + l1 = (I+1) * 2; + for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) { + if (!(f >> l2)) + log_error("Line %u cannot be interpreted as a latch!\n", line_count); + log_debug("%d %d is a latch\n", l1, l2); + RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); - module->addDff(NEW_ID, clk_wire, d_wire, q_wire); + module->addDff(NEW_ID, clk_wire, d_wire, q_wire); - // Reset logic is optional in AIGER 1.9 - if (f.peek() == ' ') { - if (!(f >> l3)) - log_error("Line %u cannot be interpreted as a latch!\n", line_count); + // Reset logic is optional in AIGER 1.9 + if (f.peek() == ' ') { + if (!(f >> l3)) + log_error("Line %u cannot be interpreted as a latch!\n", line_count); - if (l3 == 0) - q_wire->attributes["\\init"] = RTLIL::S0; - else if (l3 == 1) - q_wire->attributes["\\init"] = RTLIL::S1; - else if (l3 == l1) { - //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); - } - else - log_error("Line %u has invalid reset literal for latch!\n", line_count); - } - else { - // AIGER latches are assumed to be initialized to zero - q_wire->attributes["\\init"] = RTLIL::S0; - } - latches.push_back(q_wire); - } + if (l3 == 0) + q_wire->attributes["\\init"] = RTLIL::S0; + else if (l3 == 1) + q_wire->attributes["\\init"] = RTLIL::S1; + else if (l3 == l1) { + //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); + } + else + log_error("Line %u has invalid reset literal for latch!\n", line_count); + } + else { + // AIGER latches are assumed to be initialized to zero + q_wire->attributes["\\init"] = RTLIL::S0; + } + latches.push_back(q_wire); + } - // Parse outputs - for (unsigned i = 0; i < O; ++i, ++line_count) { - if (!(f >> l1)) - log_error("Line %u cannot be interpreted as an output!\n", line_count); + // Parse outputs + for (unsigned i = 0; i < O; ++i, ++line_count) { + if (!(f >> l1)) + log_error("Line %u cannot be interpreted as an output!\n", line_count); - log_debug("%d is an output\n", l1); - RTLIL::Wire *wire = createWireIfNotExists(module, l1); - wire->port_output = true; - outputs.push_back(wire); - } - std::getline(f, line); // Ignore up to start of next line + log_debug("%d is an output\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + outputs.push_back(wire); + } + std::getline(f, line); // Ignore up to start of next line - // Parse bad properties - for (unsigned i = 0; i < B; ++i, ++line_count) { - if (!(f >> l1)) - log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); + // Parse bad properties + for (unsigned i = 0; i < B; ++i, ++line_count) { + if (!(f >> l1)) + log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); - log_debug("%d is a bad state property\n", l1); - RTLIL::Wire *wire = createWireIfNotExists(module, l1); - wire->port_output = true; - bad_properties.push_back(wire); - } - if (B > 0) - std::getline(f, line); // Ignore up to start of next line + log_debug("%d is a bad state property\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + bad_properties.push_back(wire); + } + if (B > 0) + std::getline(f, line); // Ignore up to start of next line - // TODO: Parse invariant constraints - for (unsigned i = 0; i < C; ++i, ++line_count) - std::getline(f, line); // Ignore up to start of next line + // TODO: Parse invariant constraints + for (unsigned i = 0; i < C; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line - // TODO: Parse justice properties - for (unsigned i = 0; i < J; ++i, ++line_count) - std::getline(f, line); // Ignore up to start of next line + // TODO: Parse justice properties + for (unsigned i = 0; i < J; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line - // TODO: Parse fairness constraints - for (unsigned i = 0; i < F; ++i, ++line_count) - std::getline(f, line); // Ignore up to start of next line + // TODO: Parse fairness constraints + for (unsigned i = 0; i < F; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line - // Parse AND - l1 = (I+L+1) << 1; - for (unsigned i = 0; i < A; ++i, ++line_count, l1 += 2) { - l2 = parse_next_delta_literal(f, l1); - l3 = parse_next_delta_literal(f, l2); + // Parse AND + l1 = (I+L+1) << 1; + for (unsigned i = 0; i < A; ++i, ++line_count, l1 += 2) { + l2 = parse_next_delta_literal(f, l1); + l3 = parse_next_delta_literal(f, l2); - log_debug("%d %d %d is an AND\n", l1, l2, l3); - log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? - RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); - RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); - RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); + log_debug("%d %d %d is an AND\n", l1, l2, l3); + log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? + RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); - and_cell->setPort("\\A", i1_wire); - and_cell->setPort("\\B", i2_wire); - and_cell->setPort("\\Y", o_wire); - } + RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); + and_cell->setPort("\\A", i1_wire); + and_cell->setPort("\\B", i2_wire); + and_cell->setPort("\\Y", o_wire); + } } struct AigerFrontend : public Frontend { - AigerFrontend() : Frontend("aiger", "read AIGER file") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" read_aiger [options] [filename]\n"); - log("\n"); - log("Load module from an AIGER file into the current design.\n"); - log("\n"); - log(" -module_name \n"); - log(" Name of module to be created (default: )" + AigerFrontend() : Frontend("aiger", "read AIGER file") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" read_aiger [options] [filename]\n"); + log("\n"); + log("Load module from an AIGER file into the current design.\n"); + log("\n"); + log(" -module_name \n"); + log(" Name of module to be created (default: " #ifdef _WIN32 - "top" // FIXME + "top" // FIXME #else - "" + "" #endif - ")\n"); - log("\n"); - log(" -clk_name \n"); - log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); - log(" this name (default: clk)\n"); - log("\n"); - } - void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing AIGER frontend.\n"); + ")\n"); + log("\n"); + log(" -clk_name \n"); + log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); + log(" this name (default: clk)\n"); + log("\n"); + } + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing AIGER frontend.\n"); - RTLIL::IdString clk_name = "\\clk"; - RTLIL::IdString module_name; + RTLIL::IdString clk_name = "\\clk"; + RTLIL::IdString module_name; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -433,19 +433,19 @@ struct AigerFrontend : public Frontend { } extra_args(f, filename, args, argidx); - if (module_name.empty()) { + if (module_name.empty()) { #ifdef _WIN32 - module_name = "top"; // FIXME: basename equivalent on Win32? + module_name = "top"; // FIXME: basename equivalent on Win32? #else - char* bn = strdup(filename.c_str()); - module_name = RTLIL::escape_id(bn); - free(bn); + char* bn = strdup(filename.c_str()); + module_name = RTLIL::escape_id(bn); + free(bn); #endif - } + } - AigerReader reader(design, *f, module_name, clk_name); + AigerReader reader(design, *f, module_name, clk_name); reader.parse_aiger(); - } + } } AigerFrontend; YOSYS_NAMESPACE_END