1

Question:

Why does yosys mark used sub-modules as unused?

Background:

I am trying to find a rough estimate of the area of a circuit. Some years ago, during my bachelor's, I have used a synthesis tool. IIRC, it was Synopsys. I don't have access to it anymore, so I am using an open source alternative, qflow. This is the first time I have ever used it, or any of its sub-tools, so I do not know its intrinsics. Note, though, that I am open to using other open source tools.

Ultimate Goal:

Compare the area of two modules, A and B. A is composed of 7 (slightly different) instances of module C, and an instance of (an extremely simple) module D. B is composed of 16 (slightly different) instances of module C. It is expected that A is smaller than B.

Detailed description of the problem

I have tried building (synthesizing+placing+routing) A and B, as described in qflow's documentation: qflow build A and qflow build B. Each module was built in its own complete project - i.e., C's source code has been explicitly duplicated. I have located an area dump similar to the one in this question (in place.log); however, the results did not make sense: A had roughly the same "total cell area" as B.

I had my suspicions that the sub-modules were not present in the final synthesis of the top modules; thus, I have built module C by itself (qflow build C). C was an order of magnitude larger than A and B, which confirmed my suspicions that A and B were being built without C. Parsing synth.log confirmed that the instances of C have been removed during the synthesis step (yosys) (for each C* variation of C there was a "Removing unused module C*"). Nonetheless, D had not been removed from A (i.e., it is used). I have no idea why: my testbench files confirm that both modules A and B make use of C to correctly generate output (tested using iverilog).

  • synthesis tools might "inline" your module at a higher level. flatten designs can be optimized more aggressively, result in a smaller design. haven't worked with yosys, but some tools have switches to prevent flattening -> have you viewed the result at gate level? – schnedan Oct 05 '20 at 15:47
  • No, I haven't, but it was indeed removing code, not flattening modules. I do not fully understand why it would decide to remove that code (it should at least trigger a warning), but the reason was that I had two always blocks modifying the same register. I will add an "answer" shortly. – Daniel Carvalho Oct 05 '20 at 15:55

1 Answers1

0

The compiler decided to optimize away some code it did not like without triggering an error or warning. Basically, there were two always blocks operating on the same register.

always @(posedge clock) begin
  if (resetn) begin
    state <= 0;
  end
end

always @(posedge clock) begin
  if (!resetn) begin
    case (state)
      0: begin
        if (change_to_state_1) begin
          state <= 1;
          output <= output_from_d;
        end
      end
      1: begin
        state <= 0;
        output <= output_from_c;
      end
    endcase
  end
end

Since it did not like state being assigned a value on both always blocks, it seems to have removed all assignments to state in the second always block; therefore, state could only be 0. All non-0 states became unreachable; thus, they were optimized away. Since all references to C were unreachable, it was marked as unused, and, thus, removed. D was used as a temporary output in state 0, so it was marked as used.

The solution is to make sure no two instances of always blocks that occur on the same condition modify the same variable. For example, in this case one can merge the always blocks using an if-else statement on resetn.