verilog: fix buf/not primitives with multiple outputs
authorXiretza <xiretza@xiretza.xyz>
Tue, 16 Mar 2021 23:18:36 +0000 (00:18 +0100)
committerZachary Snow <zachary.j.snow@gmail.com>
Wed, 17 Mar 2021 15:44:03 +0000 (11:44 -0400)
From IEEE1364-2005, section 7.3 buf and not gates:

> These two logic gates shall have one input and one or more outputs.
> The last terminal in the terminal list shall connect to the input of the
> logic gate, and the other terminals shall connect to the outputs of
> the logic gate.

yosys does not follow this and instead interprets the first argument as
the output, the second as the input and ignores the rest.

frontends/ast/simplify.cc
tests/simple/verilog_primitives.v [new file with mode: 0644]

index d9eae3a06128d9e6b5d9e6af0ca0d765ebe6193f..b9965ba99e2423ac32eb657741ed4790c5d407d1 100644 (file)
@@ -2223,6 +2223,21 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                        children.push_back(node);
                        did_something = true;
                }
+               else if (str == "buf" || str == "not")
+               {
+                       AstNode *input = children_list.back();
+                       if (str == "not")
+                               input = new AstNode(AST_BIT_NOT, input);
+
+                       newNode = new AstNode(AST_GENBLOCK);
+                       for (auto it = children_list.begin(); it != std::prev(children_list.end()); it++) {
+                               newNode->children.push_back(new AstNode(AST_ASSIGN, *it, input->clone()));
+                               newNode->children.back()->was_checked = true;
+                       }
+                       delete input;
+
+                       did_something = true;
+               }
                else
                {
                        AstNodeType op_type = AST_NONE;
@@ -2240,10 +2255,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                                op_type = AST_BIT_XOR;
                        if (str == "xnor")
                                op_type = AST_BIT_XOR, invert_results = true;
-                       if (str == "buf")
-                               op_type = AST_POS;
-                       if (str == "not")
-                               op_type = AST_POS, invert_results = true;
                        log_assert(op_type != AST_NONE);
 
                        AstNode *node = children_list[1];
diff --git a/tests/simple/verilog_primitives.v b/tests/simple/verilog_primitives.v
new file mode 100644 (file)
index 0000000..0ee0739
--- /dev/null
@@ -0,0 +1,15 @@
+module verilog_primitives (
+       input wire in1, in2, in3,
+       output wire out_buf0, out_buf1, out_buf2, out_buf3, out_buf4,
+       output wire out_not0, out_not1, out_not2,
+       output wire out_xnor
+);
+
+buf u_buf0 (out_buf0, in1);
+buf u_buf1 (out_buf1, out_buf2, out_buf3, out_buf4, in2);
+
+not u_not0 (out_not0, out_not1, out_not2, in1);
+
+xnor u_xnor0 (out_xnor, in1, in2, in3);
+
+endmodule