diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | backends/rtlil/rtlil_backend.cc | 2 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 2 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 2 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 7 | ||||
-rw-r--r-- | kernel/rtlil.cc | 11 | ||||
-rw-r--r-- | kernel/rtlil.h | 1 | ||||
-rw-r--r-- | passes/fsm/fsm_detect.cc | 29 | ||||
-rw-r--r-- | passes/techmap/bmuxmap.cc | 36 | ||||
-rw-r--r-- | tests/svtypes/typedef_struct.sv | 4 | ||||
-rw-r--r-- | tests/svtypes/union_simple.sv | 16 | ||||
-rw-r--r-- | tests/techmap/bmuxmap_pmux.ys | 45 | ||||
-rw-r--r-- | tests/various/rtlil_z_bits.ys | 9 |
13 files changed, 149 insertions, 17 deletions
@@ -141,7 +141,7 @@ LDLIBS += -lrt endif endif -YOSYS_VER := 0.25+86 +YOSYS_VER := 0.25+94 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo diff --git a/backends/rtlil/rtlil_backend.cc b/backends/rtlil/rtlil_backend.cc index 7c7e26a93..574eb3aaa 100644 --- a/backends/rtlil/rtlil_backend.cc +++ b/backends/rtlil/rtlil_backend.cc @@ -51,7 +51,7 @@ void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi } } f << stringf("%d'", width); - if (data.is_fully_undef()) { + if (data.is_fully_undef_x_only()) { f << "x"; } else { for (int i = offset+width-1; i >= offset; i--) { diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 9327b34ee..1016ef636 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -877,7 +877,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1; if (children.size() > 1) range = children[1]; - } else if (id_ast->type == AST_STRUCT_ITEM || id_ast->type == AST_STRUCT) { + } else if (id_ast->type == AST_STRUCT_ITEM || id_ast->type == AST_STRUCT || id_ast->type == AST_UNION) { AstNode *tmp_range = make_struct_member_range(this, id_ast); this_width = tmp_range->range_left - tmp_range->range_right + 1; delete tmp_range; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 71a26983b..2dbabca28 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2063,7 +2063,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (name_has_dot(str, sname)) { if (current_scope.count(str) > 0) { auto item_node = current_scope[str]; - if (item_node->type == AST_STRUCT_ITEM || item_node->type == AST_STRUCT) { + if (item_node->type == AST_STRUCT_ITEM || item_node->type == AST_STRUCT || item_node->type == AST_UNION) { // structure member, rewrite this node to reference the packed struct wire auto range = make_struct_member_range(this, item_node); newNode = new AstNode(AST_IDENTIFIER, range); diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 70ee47561..87b50438a 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -173,6 +173,13 @@ static bool isInLocalScope(const std::string *name) static AstNode *getTypeDefinitionNode(std::string type_name) { + // check package types + if (type_name.find("::") != std::string::npos && pkg_user_types.count(type_name) > 0) { + auto typedef_node = pkg_user_types[type_name]; + log_assert(typedef_node->type == AST_TYPEDEF); + return typedef_node->children[0]; + } + // check current scope then outer scopes for a name for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) { if (it->count(type_name) > 0) { diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index eee014c54..7f3508b2f 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -370,6 +370,17 @@ bool RTLIL::Const::is_fully_undef() const return true; } +bool RTLIL::Const::is_fully_undef_x_only() const +{ + cover("kernel.rtlil.const.is_fully_undef_x_only"); + + for (const auto &bit : bits) + if (bit != RTLIL::State::Sx) + return false; + + return true; +} + bool RTLIL::Const::is_onehot(int *pos) const { cover("kernel.rtlil.const.is_onehot"); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 42bb66da8..7c7669caa 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -686,6 +686,7 @@ struct RTLIL::Const bool is_fully_ones() const; bool is_fully_def() const; bool is_fully_undef() const; + bool is_fully_undef_x_only() const; bool is_onehot(int *pos = nullptr) const; inline RTLIL::Const extract(int offset, int len = 1, RTLIL::State padding = RTLIL::State::S0) const { diff --git a/passes/fsm/fsm_detect.cc b/passes/fsm/fsm_detect.cc index 5378ec89e..86d654cc4 100644 --- a/passes/fsm/fsm_detect.cc +++ b/passes/fsm/fsm_detect.cc @@ -118,7 +118,7 @@ static bool check_state_users(RTLIL::SigSpec sig) return true; } -static void detect_fsm(RTLIL::Wire *wire) +static void detect_fsm(RTLIL::Wire *wire, bool ignore_self_reset=false) { bool has_fsm_encoding_attr = wire->attributes.count(ID::fsm_encoding) > 0 && wire->attributes.at(ID::fsm_encoding).decode_string() != "none"; bool has_fsm_encoding_none = wire->attributes.count(ID::fsm_encoding) > 0 && wire->attributes.at(ID::fsm_encoding).decode_string() == "none"; @@ -199,7 +199,7 @@ static void detect_fsm(RTLIL::Wire *wire) } SigSpec sig_y = sig_d, sig_undef; - if (ce.eval(sig_y, sig_undef)) + if (!ignore_self_reset && ce.eval(sig_y, sig_undef)) is_self_resetting = true; } @@ -261,12 +261,15 @@ struct FsmDetectPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" fsm_detect [selection]\n"); + log(" fsm_detect [options] [selection]\n"); log("\n"); log("This pass detects finite state machines by identifying the state signal.\n"); log("The state signal is then marked by setting the attribute 'fsm_encoding'\n"); log("on the state signal to \"auto\".\n"); log("\n"); + log(" -ignore-self-reset\n"); + log(" Mark FSMs even if they are self-resetting\n"); + log("\n"); log("Existing 'fsm_encoding' attributes are not changed by this pass.\n"); log("\n"); log("Signals can be protected from being detected by this pass by setting the\n"); @@ -276,16 +279,28 @@ struct FsmDetectPass : public Pass { log("before this pass to prepare the design for fsm_detect.\n"); log("\n"); #ifdef YOSYS_ENABLE_VERIFIC - log("The Verific frontend may merge multiplexers in a way that interferes with FSM\n"); + log("The Verific frontend may optimize the design in a way that interferes with FSM\n"); log("detection. Run 'verific -cfg db_infer_wide_muxes_post_elaboration 0' before\n"); - log("reading the source, and 'bmuxmap' after 'proc' for best results.\n"); + log("reading the source, and 'bmuxmap -pmux' after 'proc' for best results.\n"); log("\n"); #endif } void execute(std::vector<std::string> args, RTLIL::Design *design) override { log_header(design, "Executing FSM_DETECT pass (finding FSMs in design).\n"); - extra_args(args, 1, design); + + bool ignore_self_reset = false; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-ignore-self-reset") { + ignore_self_reset = true; + continue; + } + break; + } + extra_args(args, argidx, design); CellTypes ct; ct.setup_internals(); @@ -321,7 +336,7 @@ struct FsmDetectPass : public Pass { sig_at_port.add(assign_map(wire)); for (auto wire : module->selected_wires()) - detect_fsm(wire); + detect_fsm(wire, ignore_self_reset); } assign_map.clear(); diff --git a/passes/techmap/bmuxmap.cc b/passes/techmap/bmuxmap.cc index 03673c278..15b149239 100644 --- a/passes/techmap/bmuxmap.cc +++ b/passes/techmap/bmuxmap.cc @@ -36,10 +36,16 @@ struct BmuxmapPass : public Pass { } void execute(std::vector<std::string> args, RTLIL::Design *design) override { + bool pmux_mode = false; + log_header(design, "Executing BMUXMAP pass.\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-pmux") { + pmux_mode = true; + continue; + } break; } extra_args(args, argidx, design); @@ -53,18 +59,36 @@ struct BmuxmapPass : public Pass { SigSpec sel = cell->getPort(ID::S); SigSpec data = cell->getPort(ID::A); int width = GetSize(cell->getPort(ID::Y)); + int s_width = GetSize(cell->getPort(ID::S)); - for (int idx = 0; idx < GetSize(sel); idx++) { - SigSpec new_data = module->addWire(NEW_ID, GetSize(data)/2); - for (int i = 0; i < GetSize(new_data); i += width) { - RTLIL::Cell *mux = module->addMux(NEW_ID, + if(pmux_mode) + { + int num_cases = 1 << s_width; + SigSpec new_a = SigSpec(State::Sx, width); + SigSpec new_s = module->addWire(NEW_ID, num_cases); + SigSpec new_data = module->addWire(NEW_ID, width); + for (int val = 0; val < num_cases; val++) + { + module->addEq(NEW_ID, sel, SigSpec(val, GetSize(sel)), new_s[val]); + } + RTLIL::Cell *pmux = module->addPmux(NEW_ID, new_a, data, new_s, new_data); + pmux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + data = new_data; + } + else + { + for (int idx = 0; idx < GetSize(sel); idx++) { + SigSpec new_data = module->addWire(NEW_ID, GetSize(data)/2); + for (int i = 0; i < GetSize(new_data); i += width) { + RTLIL::Cell *mux = module->addMux(NEW_ID, data.extract(i*2, width), data.extract(i*2+width, width), sel[idx], new_data.extract(i, width)); - mux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + mux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); + } + data = new_data; } - data = new_data; } module->connect(cell->getPort(ID::Y), data); diff --git a/tests/svtypes/typedef_struct.sv b/tests/svtypes/typedef_struct.sv index 7ae007952..8df8e32b0 100644 --- a/tests/svtypes/typedef_struct.sv +++ b/tests/svtypes/typedef_struct.sv @@ -16,6 +16,7 @@ module top; bit a; logic[7:0] b; t_t t; + p::p_t ps; } s_t; s_t s; @@ -29,6 +30,7 @@ module top; assign s1 = s; assign ps.a = 8'hAA; assign ps.b = 8'h55; + assign s.ps = ps; always_comb begin assert(s.a == 1'b1); @@ -37,6 +39,8 @@ module top; assert(s1.t == 8'h55); assert(ps.a == 8'hAA); assert(ps.b == 8'h55); + assert(s.ps.a == 8'hAA); + assert(s.ps.b == 8'h55); end endmodule diff --git a/tests/svtypes/union_simple.sv b/tests/svtypes/union_simple.sv index 12e4b376f..a55df4d0a 100644 --- a/tests/svtypes/union_simple.sv +++ b/tests/svtypes/union_simple.sv @@ -48,14 +48,30 @@ module top; U_t u; } instruction_t; + typedef struct packed { + instruction_t ir; + logic [3:0] state; + } s_t; + instruction_t ir1; + s_t s1; + assign ir1 = 32'h0AA01EB7; // lui t4,0xAA01 + assign s1.ir = ir1; + assign s1.state = '1; + always_comb begin assert(ir1.u.opcode == 'h37); assert(ir1.r.opcode == 'h37); assert(ir1.u.rd == 'd29); assert(ir1.r.rd == 'd29); assert(ir1.u.imm == 'hAA01); + assert(s1.ir.u.opcode == 'h37); + assert(s1.ir.r.opcode == 'h37); + assert(s1.ir.u.rd == 'd29); + assert(s1.ir.r.rd == 'd29); + assert(s1.ir.u.imm == 'hAA01); + assert(s1.state == 4'b1111); end union packed { diff --git a/tests/techmap/bmuxmap_pmux.ys b/tests/techmap/bmuxmap_pmux.ys new file mode 100644 index 000000000..c75d981e7 --- /dev/null +++ b/tests/techmap/bmuxmap_pmux.ys @@ -0,0 +1,45 @@ +read_ilang << EOT + +module \top + wire width 4 input 0 \S + wire width 5 output 1 \Y + + cell $bmux $0 + parameter \WIDTH 5 + parameter \S_WIDTH 4 + connect \A 80'10110100011101110001110010001110101010111000110011111111111110100000110100111000 + connect \S \S + connect \Y \Y + end +end + +EOT + +hierarchy -auto-top +equiv_opt -assert bmuxmap -pmux + +### +design -reset + +read_ilang << EOT + +module \top + wire width 10 input 0 \A + wire input 1 \S + wire width 5 output 2 \Y + + cell $bmux $0 + parameter \WIDTH 5 + parameter \S_WIDTH 1 + connect \A \A + connect \S \S + connect \Y \Y + end +end + +EOT + +hierarchy -auto-top +equiv_opt -assert bmuxmap -pmux + + diff --git a/tests/various/rtlil_z_bits.ys b/tests/various/rtlil_z_bits.ys new file mode 100644 index 000000000..c38669159 --- /dev/null +++ b/tests/various/rtlil_z_bits.ys @@ -0,0 +1,9 @@ +! mkdir -p temp +read_rtlil <<EOT +module \test + wire output 1 \a + connect \a 1'z +end +EOT +write_rtlil temp/rtlil_z_bits.il +! grep -F -q "connect \\a 1'z" temp/rtlil_z_bits.il |