MikePopoloski / slang

SystemVerilog compiler and language services
MIT License
546 stars 114 forks source link

Compilation Errors with $countdrivers and Specify Block Conditions #979

Open vowstar opened 2 weeks ago

vowstar commented 2 weeks ago

Thank you so much for your hard work and dedication to the slang project. Your efforts in developing and maintaining this tool are greatly appreciated by the community. It's thanks to contributors like you that we can enjoy robust and efficient tools in our development processes. Your commitment to open source is truly inspiring.

Describe the bug

slang --version
slang version 6.0.0+0

Encountering compilation errors with the slang tool for Verilog files. The compiler throws errors related to the $countdrivers system function and conditions within specify blocks. The errors suggest that expressions within if statements in specify blocks are not recognized as valid.

To Reproduce Steps to reproduce the behavior:

  1. Create a Verilog file with the following content:
    
    /* pad_buffer_controller.v */
    module pad_buffer_controller (pad, output_enable, pull_up, pull_down, input_signal, drive_select0, drive_select1, control, input_enable);

output control; input output_enable, pull_up, pull_down, input_signal, drive_select0, drive_select1, input_enable; inout pad;

supply1 high; supply0 low; bufif0 (control_buffer, input_signal, output_enable); pmos (pad, control_buffer, low); and (control, pad, input_enable); rnmos #0.01 (control_buffer, high, pull_up); rnmos #0.01 (control_buffer, low, pull_down);

always @(pad) begin if (pad === 1'bx && !$test$plusargs("bus_conflict_off") && $countdrivers(pad)) $display("%t opps! bus conflict : %m", $realtime); end

ifdef functional else specify (pad => control) = (0,0); (input_enable => control) = (0,0); if(drive_select0 === 1'b0 && drive_select1 === 1'b0 ) (input_signal => pad) = (0,0); if(drive_select0 === 1'b1 && drive_select1 === 1'b0 ) (input_signal => pad) = (0,0); if(drive_select0 === 1'b0 && drive_select1 === 1'b1 ) (input_signal => pad) = (0,0); if(drive_select0 === 1'b1 && drive_select1 === 1'b1 ) (input_signal => pad) = (0,0); ifnone (input_signal => pad) = (0,0); if(drive_select0 === 1'b0 && drive_select1 === 1'b0 ) (output_enable => pad) = (0,0,0,0,0,0); if(drive_select0 === 1'b1 && drive_select1 === 1'b0 ) (output_enable => pad) = (0,0,0,0,0,0); if(drive_select0 === 1'b0 && drive_select1 === 1'b1 ) (output_enable => pad) = (0,0,0,0,0,0); if(drive_select0 === 1'b1 && drive_select1 === 1'b1 ) (output_enable => pad) = (0,0,0,0,0,0); ifnone (output_enable => pad) = (0,0,0,0,0,0); endspecify `endif

endmodule


3. Compile the file with slang using ``slang pad_buffer_controller.v``.
4. Observe the following errors indicating unknown system names and invalid expressions in specify blocks.
```bash
slang pad_buffer_controller.v 
Top level design units:
    pad_buffer_controller

pad_buffer_controller.v:17:10: error: unknown system name '$countdrivers' [-Wunknown-sys-name]
         $countdrivers(pad))
         ^~~~~~~~~~~~~
pad_buffer_controller.v:29:5: error: expression is not valid in a state-dependent path condition
 if(drive_select0 === 1'b0 && drive_select1 === 1'b0 ) (input_signal => pad) = (0,0);
    ^~~~~~~~~~~~~~~~~~~~~~
pad_buffer_controller.v:30:5: error: expression is not valid in a state-dependent path condition
 if(drive_select0 === 1'b1 && drive_select1 === 1'b0 ) (input_signal => pad) = (0,0);
    ^~~~~~~~~~~~~~~~~~~~~~
pad_buffer_controller.v:31:5: error: expression is not valid in a state-dependent path condition
 if(drive_select0 === 1'b0 && drive_select1 === 1'b1 ) (input_signal => pad) = (0,0);
    ^~~~~~~~~~~~~~~~~~~~~~
pad_buffer_controller.v:32:5: error: expression is not valid in a state-dependent path condition
 if(drive_select0 === 1'b1 && drive_select1 === 1'b1 ) (input_signal => pad) = (0,0);
    ^~~~~~~~~~~~~~~~~~~~~~
pad_buffer_controller.v:35:5: error: expression is not valid in a state-dependent path condition
 if(drive_select0 === 1'b0 && drive_select1 === 1'b0 ) (output_enable => pad) = (0,0,0,0,0,0);
    ^~~~~~~~~~~~~~~~~~~~~~
pad_buffer_controller.v:36:5: error: expression is not valid in a state-dependent path condition
 if(drive_select0 === 1'b1 && drive_select1 === 1'b0 ) (output_enable => pad) = (0,0,0,0,0,0);
    ^~~~~~~~~~~~~~~~~~~~~~
pad_buffer_controller.v:37:5: error: expression is not valid in a state-dependent path condition
 if(drive_select0 === 1'b0 && drive_select1 === 1'b1 ) (output_enable => pad) = (0,0,0,0,0,0);
    ^~~~~~~~~~~~~~~~~~~~~~
pad_buffer_controller.v:38:5: error: expression is not valid in a state-dependent path condition
 if(drive_select0 === 1'b1 && drive_select1 === 1'b1 ) (output_enable => pad) = (0,0,0,0,0,0);
    ^~~~~~~~~~~~~~~~~~~~~~

Build failed: 9 errors, 0 warnings

Expected behavior The compiler should recognize $countdrivers and the expressions within the specify block as valid, without throwing errors.

Additional context This issue appears in a standard setup without any modifications or unusual configurations. This might suggest a potential issue in handling certain Verilog constructs or a need for feature enhancements in the slang tool.

MikePopoloski commented 2 weeks ago

Thanks for the kind words.

There are two separate problems described here. The first is the $countdrivers function. This is not a standard SystemVerilog system function. It's described in Annex D of the LRM, which says:

The system tasks and system functions described in this annex are for informative purposes only and are not part of this standard.

That being said, I'm not against having slang support them anyway.

Second, state dependent path conditions are described in 30.4.4.1. There is a table there, Table 30-1, which lists the valid operators, and the triple-equals operator is not in the list, which is why slang is reporting an error. I assume some other tool is allowing this anyway as an extension. I can consider allowing this in slang for compatibility purposes.

For reference, here is Table 30-1:

Operator Description
~ bitwise negation
& reduction AND
& bitwise AND
| reduction OR
| bitwise OR
^ reduction XOR
^ bitwise XOR
~& reduction NAND
^~ ~^ bitwise XNOR
~| reduction NOR
== logical equality
^~ ~^ reduction XNOR
!= logical inequality
{} concatenation
&& logical AND
{ {} } replication
|| logical OR
?: conditional
! logical NOT
vowstar commented 2 weeks ago

Thank you for your detailed and informative response! I appreciate your willingness to consider extending slang's capabilities to include features like $countdrivers and state-dependent path conditions using the triple-equals operator. Indeed, my experiences are based on using the VCS simulator, which seems to allow these extensions.