diff options
-rw-r--r-- | frontends/ast/ast.cc | 1 | ||||
-rw-r--r-- | frontends/ast/ast.h | 1 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 24 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 14 | ||||
-rw-r--r-- | frontends/verific/verific.cc | 5 | ||||
-rw-r--r-- | frontends/verilog/verilog_lexer.l | 2 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 33 | ||||
-rw-r--r-- | passes/sat/expose.cc | 30 | ||||
-rw-r--r-- | passes/sat/qbfsat.cc | 89 | ||||
-rw-r--r-- | passes/sat/sim.cc | 5 | ||||
-rw-r--r-- | passes/techmap/techmap.cc | 5 | ||||
-rw-r--r-- | passes/tests/test_cell.cc | 8 | ||||
-rw-r--r-- | techlibs/common/gen_fine_ffs.py | 2 | ||||
-rw-r--r-- | techlibs/common/simcells.v | 8 | ||||
-rw-r--r-- | tests/svtypes/static_cast_negative.ys | 4 | ||||
-rw-r--r-- | tests/svtypes/static_cast_nonconst.ys | 4 | ||||
-rw-r--r-- | tests/svtypes/static_cast_simple.sv | 64 | ||||
-rw-r--r-- | tests/svtypes/static_cast_verilog.ys | 4 | ||||
-rw-r--r-- | tests/svtypes/static_cast_zero.ys | 4 | ||||
-rw-r--r-- | tests/various/const_func.v | 75 | ||||
-rw-r--r-- | tests/various/const_func.ys | 1 | ||||
-rw-r--r-- | tests/various/signed.ys | 28 |
22 files changed, 369 insertions, 42 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 03fd272da..9520ae32c 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -95,6 +95,7 @@ std::string AST::type2str(AstNodeType type) X(AST_TO_SIGNED) X(AST_TO_UNSIGNED) X(AST_SELFSZ) + X(AST_CAST_SIZE) X(AST_CONCAT) X(AST_REPLICATE) X(AST_BIT_NOT) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 46864a4e1..9a5aa15f9 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -76,6 +76,7 @@ namespace AST AST_TO_SIGNED, AST_TO_UNSIGNED, AST_SELFSZ, + AST_CAST_SIZE, AST_CONCAT, AST_REPLICATE, AST_BIT_NOT, diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 9546558aa..e878d0dd2 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -814,6 +814,16 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun children.at(0)->detectSignWidthWorker(sub_width_hint, sign_hint); break; + case AST_CAST_SIZE: + while (children.at(0)->simplify(true, false, false, 1, -1, false, false)) { } + if (children.at(0)->type != AST_CONSTANT) + log_file_error(filename, location.first_line, "Static cast with non constant expression!\n"); + children.at(1)->detectSignWidthWorker(width_hint, sign_hint); + width_hint = children.at(0)->bitsAsConst().as_int(); + if (width_hint <= 0) + log_file_error(filename, location.first_line, "Static cast with zero or negative size!\n"); + break; + case AST_CONCAT: for (auto child : children) { sub_width_hint = 0; @@ -1289,6 +1299,20 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) return sig; } + // changing the size of signal can be done directly using RTLIL::SigSpec + case AST_CAST_SIZE: { + RTLIL::SigSpec size = children[0]->genRTLIL(); + RTLIL::SigSpec sig = children[1]->genRTLIL(); + if (!size.is_fully_const()) + log_file_error(filename, location.first_line, "Static cast with non constant expression!\n"); + int width = size.as_int(); + if (width <= 0) + log_file_error(filename, location.first_line, "Static cast with zero or negative size!\n"); + sig.extend_u0(width, sign_hint); + is_signed = sign_hint; + return sig; + } + // concatenation of signals can be done directly using RTLIL::SigSpec case AST_CONCAT: { RTLIL::SigSpec sig; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 55e7da0aa..c4df5c0a0 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -950,6 +950,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, case AST_TO_SIGNED: case AST_TO_UNSIGNED: case AST_SELFSZ: + case AST_CAST_SIZE: case AST_CONCAT: case AST_REPLICATE: case AST_REDUCE_AND: @@ -1126,6 +1127,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, bool in_param_here = in_param; if (i == 0 && (type == AST_REPLICATE || type == AST_WIRE)) const_fold_here = true, in_param_here = true; + if (i == 0 && (type == AST_GENIF || type == AST_GENCASE)) + in_param_here = true; + if (i == 1 && (type == AST_FOR || type == AST_GENFOR)) + in_param_here = true; if (type == AST_PARAMETER || type == AST_LOCALPARAM) const_fold_here = true; if (i == 0 && (type == AST_ASSIGN || type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE)) @@ -1942,7 +1947,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, continue; buf = child->clone(); - while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + while (buf->simplify(true, false, false, stage, width_hint, sign_hint, true)) { } if (buf->type != AST_CONSTANT) { // for (auto f : log_files) // dumpAst(f, "verilog-ast> "); @@ -3483,6 +3488,13 @@ replace_fcall_later:; } } break; + case AST_CAST_SIZE: + if (children.at(0)->type == AST_CONSTANT && children.at(1)->type == AST_CONSTANT) { + int width = children[0]->bitsAsConst().as_int(); + RTLIL::Const val = children[1]->bitsAsConst(width); + newNode = mkconst_bits(val.bits, children[1]->is_signed); + } + break; case AST_CONCAT: string_op = !children.empty(); for (auto it = children.begin(); it != children.end(); it++) { diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index ba631475f..9785b8eff 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -53,7 +53,7 @@ USING_YOSYS_NAMESPACE # error "Only Symbiotic EDA flavored Verific is supported. Please contact office@symbioticeda.com for commercial support for Yosys+Verific." #endif -#if SYMBIOTIC_VERIFIC_API_VERSION < 1 +#if SYMBIOTIC_VERIFIC_API_VERSION < 202006 # error "Please update your version of Symbiotic EDA flavored Verific." #endif @@ -1111,7 +1111,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se wire->start_offset = min(netbus->LeftIndex(), netbus->RightIndex()); MapIter mibus; FOREACH_NET_OF_NETBUS(netbus, mibus, net) { - import_attributes(wire->attributes, net, nl); + if (net) + import_attributes(wire->attributes, net, nl); break; } diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 028106381..f2241066f 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -517,6 +517,8 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { "<<<" { return OP_SSHL; } ">>>" { return OP_SSHR; } +"'" { return OP_CAST; } + "::" { return TOK_PACKAGESEP; } "++" { return TOK_INCREMENT; } "--" { return TOK_DECREMENT; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 96d9299fe..656910c0c 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -299,6 +299,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %left '+' '-' %left '*' '/' '%' %left OP_POW +%left OP_CAST %right UNARY_OPS %define parse.error verbose @@ -746,7 +747,7 @@ module_body: module_body_stmt: task_func_decl | specify_block | param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | enum_decl | struct_decl | - always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block; + always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block | /* empty statement */ ';'; checker_decl: TOK_CHECKER TOK_ID ';' { @@ -1330,6 +1331,8 @@ ignspec_id: param_signed: TOK_SIGNED { astbuf1->is_signed = true; + } | TOK_UNSIGNED { + astbuf1->is_signed = false; } | /* empty */; param_integer: @@ -1340,14 +1343,14 @@ param_integer: astbuf1->children.back()->children.push_back(AstNode::mkconst_int(31, true)); astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true)); astbuf1->is_signed = true; - } | /* empty */; + } param_real: TOK_REAL { if (astbuf1->children.size() != 1) frontend_verilog_yyerror("Parameter already declared as integer, cannot set to real."); astbuf1->children.push_back(new AstNode(AST_REALVALUE)); - } | /* empty */; + } param_range: range { @@ -1358,8 +1361,12 @@ param_range: } }; +param_integer_type: param_integer param_signed +param_range_type: type_vec param_signed param_range +param_implicit_type: param_signed param_range + param_type: - param_signed param_integer param_real param_range | + param_integer_type | param_real | param_range_type | param_implicit_type | hierarchical_type_id { astbuf1->is_custom_type = true; astbuf1->children.push_back(new AstNode(AST_WIRETYPE)); @@ -3042,6 +3049,24 @@ basic_expr: $$ = new AstNode(AST_LOGIC_NOT, $3); SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); + } | + TOK_SIGNED OP_CAST '(' expr ')' { + if (!sv_mode) + frontend_verilog_yyerror("Static cast is only supported in SystemVerilog mode."); + $$ = new AstNode(AST_TO_SIGNED, $4); + SET_AST_NODE_LOC($$, @1, @4); + } | + TOK_UNSIGNED OP_CAST '(' expr ')' { + if (!sv_mode) + frontend_verilog_yyerror("Static cast is only supported in SystemVerilog mode."); + $$ = new AstNode(AST_TO_UNSIGNED, $4); + SET_AST_NODE_LOC($$, @1, @4); + } | + basic_expr OP_CAST '(' expr ')' { + if (!sv_mode) + frontend_verilog_yyerror("Static cast is only supported in SystemVerilog mode."); + $$ = new AstNode(AST_CAST_SIZE, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); }; concat_list: diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc index 5fe7efc34..2c65821cf 100644 --- a/passes/sat/expose.cc +++ b/passes/sat/expose.cc @@ -281,11 +281,15 @@ struct ExposePass : public Pass { flag_dff = true; continue; } - if (args[argidx] == "-cut" && !flag_input) { + if (args[argidx] == "-cut") { + if (flag_input) + log_cmd_error("Options -cut and -input are mutually exclusive.\n"); flag_cut = true; continue; } - if (args[argidx] == "-input" && !flag_cut) { + if (args[argidx] == "-input") { + if (flag_cut) + log_cmd_error("Options -cut and -input are mutually exclusive.\n"); flag_input = true; continue; } @@ -445,6 +449,8 @@ struct ExposePass : public Pass { SigMap out_to_in_map; + std::map<RTLIL::Wire*, RTLIL::IdString> wire_map; + for (auto w : module->wires()) { if (flag_shared) { @@ -462,8 +468,7 @@ struct ExposePass : public Pass { if (!w->port_input) { w->port_input = true; log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name)); - RTLIL::Wire *in_wire = module->addWire(NEW_ID, GetSize(w)); - out_to_in_map.add(w, in_wire); + wire_map[w] = NEW_ID; } } else @@ -474,15 +479,19 @@ struct ExposePass : public Pass { } if (flag_cut) { - RTLIL::Wire *in_wire = add_new_wire(module, w->name.str() + sep + "i", w->width); - in_wire->port_input = true; - out_to_in_map.add(sigmap(w), in_wire); + wire_map[w] = w->name.str() + sep + "i"; } } } if (flag_input) { + for (auto &wm : wire_map) + { + RTLIL::Wire *in_wire = module->addWire(wm.second, GetSize(wm.first)); + out_to_in_map.add(wm.first, in_wire); + } + for (auto cell : module->cells()) { if (!ct.cell_known(cell->type)) continue; @@ -497,6 +506,13 @@ struct ExposePass : public Pass { if (flag_cut) { + for (auto &wm : wire_map) + { + RTLIL::Wire *in_wire = add_new_wire(module, wm.second, wm.first->width); + in_wire->port_input = true; + out_to_in_map.add(sigmap(wm.first), in_wire); + } + for (auto cell : module->cells()) { if (!ct.cell_known(cell->type)) continue; diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc index f4624ab3b..136259558 100644 --- a/passes/sat/qbfsat.cc +++ b/passes/sat/qbfsat.cc @@ -51,6 +51,7 @@ struct QbfSolveOptions { bool nooptimize, nobisection; bool sat, unsat, show_smtbmc; enum Solver{Z3, Yices, CVC4} solver; + enum OptimizationLevel{O0, O1, O2} oflag; int timeout; std::string specialize_soln_file; std::string write_soln_soln_file; @@ -59,7 +60,7 @@ struct QbfSolveOptions { QbfSolveOptions() : specialize(false), specialize_from_file(false), write_solution(false), nocleanup(false), dump_final_smt2(false), assume_outputs(false), assume_neg(false), nooptimize(false), nobisection(false), sat(false), unsat(false), show_smtbmc(false), - solver(Yices), timeout(0), argidx(0) {}; + solver(Yices), oflag(O0), timeout(0), argidx(0) {}; }; std::string get_solver_name(const QbfSolveOptions &opt) { @@ -147,6 +148,9 @@ void recover_solution(QbfSolutionType &sol) { dict<std::pair<pool<std::string>, int>, RTLIL::SigBit> get_hole_loc_idx_sigbit_map(RTLIL::Module *module, const QbfSolutionType &sol) { dict<std::pair<pool<std::string>, int>, RTLIL::SigBit> hole_loc_idx_to_sigbit; + pool<RTLIL::SigBit> anyconst_sigbits; + dict<RTLIL::SigBit, RTLIL::SigBit> anyconst_sigbit_to_wire_sigbit; + for (auto cell : module->cells()) { pool<std::string> cell_src = cell->get_strpool_attribute(ID::src); auto pos = sol.hole_to_value.find(cell_src); @@ -154,10 +158,30 @@ dict<std::pair<pool<std::string>, int>, RTLIL::SigBit> get_hole_loc_idx_sigbit_m RTLIL::SigSpec port_y = cell->getPort(ID::Y); for (int i = GetSize(port_y) - 1; i >= 0; --i) { hole_loc_idx_to_sigbit[std::make_pair(pos->first, i)] = port_y[i]; + anyconst_sigbits.insert(port_y[i]); + } + } + } + + for (auto &conn : module->connections()) { + auto lhs = conn.first; + auto rhs = conn.second; + for (auto i = 0; i < GetSize(rhs); ++i) { + if (anyconst_sigbits[rhs[i]]) { + auto pos = anyconst_sigbit_to_wire_sigbit.find(rhs[i]); + if (pos != anyconst_sigbit_to_wire_sigbit.end()) + log_cmd_error("conflicting names for hole $anyconst sigbit %s\n", log_signal(rhs[i])); + anyconst_sigbit_to_wire_sigbit[rhs[i]] = lhs[i]; } } } + for (auto &it : hole_loc_idx_to_sigbit) { + auto pos = anyconst_sigbit_to_wire_sigbit.find(it.second); + if (pos != anyconst_sigbit_to_wire_sigbit.end()) + it.second = pos->second; + } + return hole_loc_idx_to_sigbit; } @@ -274,8 +298,7 @@ void specialize_from_file(RTLIL::Module *module, const std::string &file) { pool<std::string> hole_loc_pool(locs.begin(), locs.end()); auto hole_cell_it = anyconst_loc_to_cell.find(hole_loc_pool); if (hole_cell_it == anyconst_loc_to_cell.end()) - YS_DEBUGTRAP; - //log_cmd_error("cannot find matching wire name or $anyconst cell location for hole spec \"%s\"\n", buf.c_str()); + log_cmd_error("cannot find matching wire name or $anyconst cell location for hole spec \"%s\"\n", buf.c_str()); RTLIL::Cell *hole_cell = hole_cell_it->second; hole_sigbit = hole_cell->getPort(ID::Y)[hole_bit]; @@ -438,8 +461,7 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { RTLIL::Module *module = mod; RTLIL::Design *design = module->design; std::string module_name = module->name.str(); - RTLIL::Wire *wire_to_optimize = nullptr; - RTLIL::IdString wire_to_optimize_name; + RTLIL::IdString wire_to_optimize_name = ""; bool maximize = false; log_assert(module->design != nullptr); @@ -452,19 +474,30 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { assume_miter_outputs(module, opt); //Find the wire to be optimized, if any: - for (auto wire : module->wires()) - if (wire->get_bool_attribute("\\maximize") || wire->get_bool_attribute("\\minimize")) - wire_to_optimize = wire; - if (wire_to_optimize != nullptr) { - wire_to_optimize_name = wire_to_optimize->name; - maximize = wire_to_optimize->get_bool_attribute("\\maximize"); + for (auto wire : module->wires()) { + if (wire->get_bool_attribute("\\maximize") || wire->get_bool_attribute("\\minimize")) { + wire_to_optimize_name = wire->name; + maximize = wire->get_bool_attribute("\\maximize"); + if (opt.nooptimize) { + if (maximize) + wire->set_bool_attribute("\\maximize", false); + else + wire->set_bool_attribute("\\minimize", false); + } + } } - if (opt.nobisection || opt.nooptimize || wire_to_optimize == nullptr) { - if (wire_to_optimize != nullptr && opt.nooptimize) { - wire_to_optimize->set_bool_attribute("\\maximize", false); - wire_to_optimize->set_bool_attribute("\\minimize", false); - } + //If -O1 or -O2 was specified, use ABC to simplify the problem: + if (opt.oflag == opt.OptimizationLevel::O1) + Pass::call(module->design, "abc -g AND,NAND,OR,NOR,XOR,XNOR,MUX,NMUX -script +print_stats;strash;print_stats;drwsat;print_stats;fraig;print_stats;refactor,-N,10,-lz;print_stats;&get,-n;&dch,-pem;&nf;&put " + mod->name.str()); + else if (opt.oflag == opt.OptimizationLevel::O2) + Pass::call(module->design, "abc -g AND,NAND,OR,NOR,XOR,XNOR,MUX,NMUX -script +print_stats;strash;print_stats;drwsat;print_stats;dch,-S,1000000,-C,100000,-p;print_stats;fraig;print_stats;refactor,-N,15,-lz;print_stats;dc2,-pbl;print_stats;drwsat;print_stats;&get,-n;&dch,-pem;&nf;&put " + mod->name.str()); + if (opt.oflag != opt.OptimizationLevel::O0) { + Pass::call(module->design, "techmap"); + Pass::call(module->design, "opt"); + } + + if (opt.nobisection || opt.nooptimize || wire_to_optimize_name == "") { ret = call_qbf_solver(module, opt, tempdir_name, false, 0); } else { //Do the iterated bisection method: @@ -473,8 +506,9 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { unsigned int failure = 0; unsigned int cur_thresh = 0; - log_assert(wire_to_optimize != nullptr); - log("%s wire \"%s\".\n", (maximize? "Maximizing" : "Minimizing"), log_signal(wire_to_optimize)); + log_assert(wire_to_optimize_name != ""); + log_assert(module->wire(wire_to_optimize_name) != nullptr); + log("%s wire \"%s\".\n", (maximize? "Maximizing" : "Minimizing"), wire_to_optimize_name.c_str()); //If maximizing, grow until we get a failure. Then bisect success and failure. while (failure == 0 || difference(success, failure) > 1) { @@ -607,6 +641,22 @@ QbfSolveOptions parse_args(const std::vector<std::string> &args) { } continue; } + else if (args[opt.argidx].substr(0, 2) == "-O" && args[opt.argidx].size() == 3) { + switch (args[opt.argidx][2]) { + case '0': + opt.oflag = opt.OptimizationLevel::O0; + break; + case '1': + opt.oflag = opt.OptimizationLevel::O1; + break; + case '2': + opt.oflag = opt.OptimizationLevel::O2; + break; + default: + log_cmd_error("unknown argument %s\n", args[opt.argidx].c_str()); + } + continue; + } else if (args[opt.argidx] == "-sat") { opt.sat = true; continue; @@ -721,6 +771,9 @@ struct QbfSatPass : public Pass { log(" -timeout <value>\n"); log(" Set the per-iteration timeout in seconds.\n"); log("\n"); + log(" -O0, -O1, -O2\n"); + log(" Control the use of ABC to simplify the QBF-SAT problem before solving.\n"); + log("\n"); log(" -sat\n"); log(" Generate an error if the solver does not return \"sat\".\n"); log("\n"); diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 1ab082b09..fb496ff87 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -163,7 +163,10 @@ struct SimInstance mem_database[cell] = mem; } - + if (cell->type.in(ID($memwr),ID($memrd))) + { + log_error("$memrd and $memwr cells have to be merged to stand-alone $mem cells (execute memory_collect pass)\n"); + } if (cell->type.in(ID($assert), ID($cover), ID($assume))) { formal_database.insert(cell); } diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 1cee51d06..f98d1564a 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -328,8 +328,9 @@ struct TechmapWorker for (auto tpl_cell : tpl->cells()) { IdString c_name = tpl_cell->name; + bool techmap_replace_cell = (c_name == ID::_TECHMAP_REPLACE_); - if (c_name == ID::_TECHMAP_REPLACE_) + if (techmap_replace_cell) c_name = orig_cell_name; else if (tpl_cell->name.begins_with("\\_TECHMAP_REPLACE_.")) c_name = stringf("%s%s", orig_cell_name.c_str(), c_name.c_str() + strlen("\\_TECHMAP_REPLACE_")); @@ -384,7 +385,7 @@ struct TechmapWorker if (c->attributes.count(ID::src)) c->add_strpool_attribute(ID::src, extra_src_attrs); - if (c_name == ID::_TECHMAP_REPLACE_) + if (techmap_replace_cell) for (auto attr : cell->attributes) if (!c->attributes.count(attr.first)) c->attributes[attr.first] = attr.second; diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 942468e29..bdb475d3b 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -264,6 +264,10 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, cell->setPort(ID::Y, wire); } + if (cell_type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) { + cell->parameters[ID::B_SIGNED] = false; + } + if (muxdiv && cell_type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor))) { auto b_not_zero = module->ReduceBool(NEW_ID, cell->getPort(ID::B)); auto div_out = module->addWire(NEW_ID, GetSize(cell->getPort(ID::Y))); @@ -905,7 +909,7 @@ struct TestCellPass : public Pass { if (!ilang_file.empty()) { if (!selected_cell_types.empty()) log_cmd_error("Do not specify any cell types when using -f.\n"); - selected_cell_types.push_back("ilang"); + selected_cell_types.push_back(ID(ilang)); } if (selected_cell_types.empty()) @@ -917,7 +921,7 @@ struct TestCellPass : public Pass { for (int i = 0; i < num_iter; i++) { RTLIL::Design *design = new RTLIL::Design; - if (cell_type == "ilang") + if (cell_type == ID(ilang)) Frontend::frontend_call(design, NULL, std::string(), "ilang " + ilang_file); else create_gold_module(design, cell_type, cell_types.at(cell_type), constmode, muxdiv); diff --git a/techlibs/common/gen_fine_ffs.py b/techlibs/common/gen_fine_ffs.py index e92d58f40..5d331e767 100644 --- a/techlibs/common/gen_fine_ffs.py +++ b/techlibs/common/gen_fine_ffs.py @@ -300,7 +300,7 @@ module \$_DLATCH_{E:N|P}{R:N|P}{V:0|1}_ (E, R, D, Q); input E, R, D; output reg Q; always @* begin - if (R == {E:0|1}) + if (R == {R:0|1}) Q <= {V:0|1}; else if (E == {E:0|1}) Q <= D; diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v index 01b5bdfa6..27ef44232 100644 --- a/techlibs/common/simcells.v +++ b/techlibs/common/simcells.v @@ -2986,7 +2986,7 @@ module \$_DLATCH_NP0_ (E, R, D, Q); input E, R, D; output reg Q; always @* begin - if (R == 0) + if (R == 1) Q <= 0; else if (E == 0) Q <= D; @@ -3009,7 +3009,7 @@ module \$_DLATCH_NP1_ (E, R, D, Q); input E, R, D; output reg Q; always @* begin - if (R == 0) + if (R == 1) Q <= 1; else if (E == 0) Q <= D; @@ -3032,7 +3032,7 @@ module \$_DLATCH_PN0_ (E, R, D, Q); input E, R, D; output reg Q; always @* begin - if (R == 1) + if (R == 0) Q <= 0; else if (E == 1) Q <= D; @@ -3055,7 +3055,7 @@ module \$_DLATCH_PN1_ (E, R, D, Q); input E, R, D; output reg Q; always @* begin - if (R == 1) + if (R == 0) Q <= 1; else if (E == 1) Q <= D; diff --git a/tests/svtypes/static_cast_negative.ys b/tests/svtypes/static_cast_negative.ys new file mode 100644 index 000000000..4f9e8cf6e --- /dev/null +++ b/tests/svtypes/static_cast_negative.ys @@ -0,0 +1,4 @@ +logger -expect error "Static cast with zero or negative size" 1 +read_verilog -sv <<EOT +module top; wire [7:0] a = (-1)'(a); endmodule +EOT diff --git a/tests/svtypes/static_cast_nonconst.ys b/tests/svtypes/static_cast_nonconst.ys new file mode 100644 index 000000000..72d8f9910 --- /dev/null +++ b/tests/svtypes/static_cast_nonconst.ys @@ -0,0 +1,4 @@ +logger -expect error "Static cast with non constant expression" 1 +read_verilog -sv <<EOT +module top; wire [7:0] a, b = (a)'(0); endmodule +EOT diff --git a/tests/svtypes/static_cast_simple.sv b/tests/svtypes/static_cast_simple.sv new file mode 100644 index 000000000..2e4ad7d2b --- /dev/null +++ b/tests/svtypes/static_cast_simple.sv @@ -0,0 +1,64 @@ +module top; + wire [7:0] a, b, c, d; + assign a = 8'd16; + assign b = 8'd16; + assign c = (a * b) >> 8; + assign d = (16'(a) * b) >> 8; + + parameter P = 16; + + wire signed [7:0] s0, s1, s2; + wire [7:0] u0, u1, u2, u3, u4, u5, u6; + assign s0 = -8'd1; + assign s1 = 4'(s0); + assign s2 = 4'(unsigned'(s0)); + assign u0 = -8'd1; + assign u1 = 4'(u0); + assign u2 = 4'(signed'(u0)); + assign u3 = 8'(4'(s0)); + assign u4 = 8'(4'(u0)); + assign u5 = 8'(4'(signed'(-8'd1))); + assign u6 = 8'(4'(unsigned'(-8'd1))); + + wire [8:0] n0, n1, n2, n3, n4, n5, n6, n7, n8, n9; + assign n0 = s1; + assign n1 = s2; + assign n2 = 9'(s1); + assign n3 = 9'(s2); + assign n4 = 9'(unsigned'(s1)); + assign n5 = 9'(unsigned'(s2)); + assign n6 = 9'(u0); + assign n7 = 9'(u1); + assign n8 = 9'(signed'(u0)); + assign n9 = 9'(signed'(u1)); + + always_comb begin + assert(c == 8'b0000_0000); + assert(d == 8'b0000_0001); + + assert((P + 1)'(a) == 17'b0_0000_0000_0001_0000); + assert((P + 1)'(d - 2) == 17'b1_1111_1111_1111_1111); + + assert(s0 == 8'b1111_1111); + assert(s1 == 8'b1111_1111); + assert(s2 == 8'b0000_1111); + assert(u0 == 8'b1111_1111); + assert(u1 == 8'b0000_1111); + assert(u2 == 8'b1111_1111); + assert(u3 == 8'b1111_1111); + assert(u4 == 8'b0000_1111); + assert(u5 == 8'b1111_1111); + assert(u6 == 8'b0000_1111); + + assert(n0 == 9'b1_1111_1111); + assert(n1 == 9'b0_0000_1111); + assert(n2 == 9'b1_1111_1111); + assert(n3 == 9'b0_0000_1111); + assert(n4 == 9'b0_1111_1111); + assert(n5 == 9'b0_0000_1111); + assert(n6 == 9'b0_1111_1111); + assert(n7 == 9'b0_0000_1111); + assert(n8 == 9'b1_1111_1111); + assert(n9 == 9'b0_0000_1111); + end +endmodule diff --git a/tests/svtypes/static_cast_verilog.ys b/tests/svtypes/static_cast_verilog.ys new file mode 100644 index 000000000..fa3680b68 --- /dev/null +++ b/tests/svtypes/static_cast_verilog.ys @@ -0,0 +1,4 @@ +logger -expect error "Static cast is only supported in SystemVerilog mode" 1 +read_verilog <<EOT +module top; wire [7:0] a = 1'(a); endmodule +EOT diff --git a/tests/svtypes/static_cast_zero.ys b/tests/svtypes/static_cast_zero.ys new file mode 100644 index 000000000..d8335ca1b --- /dev/null +++ b/tests/svtypes/static_cast_zero.ys @@ -0,0 +1,4 @@ +logger -expect error "Static cast with zero or negative size" 1 +read_verilog -sv <<EOT +module top; wire [7:0] a = 0'(a); endmodule +EOT diff --git a/tests/various/const_func.v b/tests/various/const_func.v new file mode 100644 index 000000000..76cdc385d --- /dev/null +++ b/tests/various/const_func.v @@ -0,0 +1,75 @@ +module Example(outA, outB, outC, outD); + parameter OUTPUT = "FOO"; + output wire [23:0] outA; + output wire [23:0] outB; + output reg outC, outD; + function automatic [23:0] flip; + input [23:0] inp; + flip = ~inp; + endfunction + + generate + if (flip(OUTPUT) == flip("BAR")) + assign outA = OUTPUT; + else + assign outA = 0; + + case (flip(OUTPUT)) + flip("FOO"): assign outB = OUTPUT; + flip("BAR"): assign outB = 0; + flip("BAZ"): assign outB = "HI"; + endcase + + genvar i; + initial outC = 0; + for (i = 0; i != flip(flip(OUTPUT[15:8])); i = i + 1) + if (i + 1 == flip(flip("O"))) + initial outC = 1; + endgenerate + + integer j; + initial begin + outD = 1; + for (j = 0; j != flip(flip(OUTPUT[15:8])); j = j + 1) + if (j + 1 == flip(flip("O"))) + outD = 0; + end +endmodule + +module top(out); + wire [23:0] a1, a2, a3, a4; + wire [23:0] b1, b2, b3, b4; + wire c1, c2, c3, c4; + wire d1, d2, d3, d4; + Example e1(a1, b1, c1, d1); + Example #("FOO") e2(a2, b2, c2, d2); + Example #("BAR") e3(a3, b3, c3, d3); + Example #("BAZ") e4(a4, b4, c4, d4); + + output wire [24 * 8 - 1 + 4 :0] out; + assign out = { + a1, a2, a3, a4, + b1, b2, b3, b4, + c1, c2, c3, c4, + d1, d2, d3, d4}; + +// `define VERIFY +`ifdef VERIFY + assert property (a1 == 0); + assert property (a2 == 0); + assert property (a3 == "BAR"); + assert property (a4 == 0); + assert property (b1 == "FOO"); + assert property (b2 == "FOO"); + assert property (b3 == 0); + assert property (b4 == "HI"); + assert property (c1 == 1); + assert property (c2 == 1); + assert property (c3 == 0); + assert property (c4 == 0); + assert property (d1 == 0); + assert property (d2 == 0); + assert property (d3 == 1); + assert property (d4 == 1); +`endif +endmodule diff --git a/tests/various/const_func.ys b/tests/various/const_func.ys new file mode 100644 index 000000000..5e3c04105 --- /dev/null +++ b/tests/various/const_func.ys @@ -0,0 +1 @@ +read_verilog const_func.v diff --git a/tests/various/signed.ys b/tests/various/signed.ys new file mode 100644 index 000000000..2319a5da1 --- /dev/null +++ b/tests/various/signed.ys @@ -0,0 +1,28 @@ +# SV LRM A2.2.1 + +read_verilog -sv <<EOT +module test_signed(); +parameter integer signed a = 0; +parameter integer unsigned b = 0; + +endmodule +EOT + +design -reset +read_verilog -sv <<EOT +module test_signed(); +parameter logic signed [7:0] a = 0; +parameter logic unsigned [7:0] b = 0; + +endmodule +EOT + +design -reset +logger -expect error "syntax error, unexpected TOK_INTEGER" 1 +read_verilog -sv <<EOT +module test_signed(); +parameter signed integer a = 0; +parameter unsigned integer b = 0; + +endmodule +EOT |