Using Function Inside Constraint - is this LRM Compliant?

I am looking at the SV2012 LRM section 18.5.12, specifically the text: “Functions shall be called before constraints are solved, and their return values shall be treated as state variables.” The background is that I am trying to generate a random string of bits (output_string) with a fixed hamming distance to another string of bits (input string). I am able to successfully do this in Questa and VCS using the $countones system function. However this seems to be in violation of the LRM statement above. If I wrap the $countones system function in a function the simulator produces an assertion error, as I would expect.

There are two questions that arise from this:

  1. Is using the $countones function as shown below LRM compliant?
  2. Are the simulators treating system functions differently than user-made functions in the constraint solver?

Thanks

-Steven

parameter LENGTH = 10;
typedef logic [LENGTH - 1:0] vector_t;

function int count_ones (vector_t input_string);
    count_ones = $countones(input_string);
endfunction : count_ones

module testbench;
    int hamming_distance;
    vector_t input_string;
    vector_t output_string;

    initial
    begin
        input_string = 10'b0001110101;
        hamming_distance = 3;

        // This works in Questa and VCS.
        assert(std::randomize(output_string) with {($countones(input_string ^ output_string)) == hamming_distance;});         
        $display ("%b", input_string);
        $display ("%b", output_string);
        
        // This does not work; assertion error.
        assert(std::randomize(output_string) with {(count_ones(input_string ^ output_string)) == hamming_distance;});
        $display ("%b", input_string);
        $display ("%b", output_string);        
    end
endmodule : testbench

In reply to sbellock:

The LRM makes an exception for certain built-in functions. The array reduction are explicitly mentioned in the LRM. Allowing other built-in functions are extensions that have been requested as enhancements: https://accellera.mantishub.com/view.php?id=3054

In reply to sbellock:
Avoid using the assert in the randomize because a $assertoff will kill the randomize. Thus,


// Instead of 
assert(std::randomize(output_string) with // AVOID THIS
   {($countones(input_string ^ output_string)) == hamming_distance;});

// DO THIS
if(!randomize(output_string) with 
 {($countones(input_string ^ output_string)) == hamming_distance;})
    `uvm_error("MYERR", "This is a randomize error")

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us

  • SystemVerilog Assertions Handbook 4th Edition, 2016 ISBN 978-1518681448
  • A Pragmatic Approach to VMM Adoption 2006 ISBN 0-9705394-9-5
  • Using PSL/SUGAR for Formal and Dynamic Verification 2nd Edition, 2004, ISBN 0-9705394-6-0
  • Real Chip Design and Verification Using Verilog and VHDL, 2002 isbn 0-9705394-2-8
  • Component Design by Example ", 2001 ISBN 0-9705394-0-1
  • VHDL Coding Styles and Methodologies, 2nd Edition, 1999 ISBN 0-7923-8474-1
  • VHDL Answers to Frequently Asked Questions, 2nd Edition ISBN 0-7923-8115