Resolution func in the initialization

Discussion in 'VHDL' started by valtih1978, Jan 13, 2014.

  1. valtih1978

    valtih1978 Guest

    --- begin code ---

    architecture ARCH of TOP is

    type int_vector is array (integer range<>) of integer;
    function driver_counter( values : int_vector ) return integer is
    variable result : integer := 0;
    variable l: line;
    begin
    for index in values'range loop
    if values(index) /= 0 then
    result := result + 1;
    write (l, integer'image(values(index)) & ",");
    end if;
    end loop;
    report l.all & " count resolved => " & integer'image(result);
    return result;
    end function;

    signal S1: driver_counter integer := 6;

    begin
    -- s1 <= 1;
    end architecture;

    -- end code ---

    In Modelsim, the driver_counter does not print any reports, which means
    that resolution is not executed on S1, despite it is resolved and
    Ashenden says

    --- begin quote ---
    The resolution function for a resolved signal is also invoked to
    initialize the signal. At the start of a simulation, the drivers for the
    signal are initialized to the expression included in the signal
    declaration, or to the default initial value for the signal type if no
    initialization expression is given. The resolution function is then
    invoked using these driver values to determine the initial value for the
    signal. In this way, the signal always has a properly resolved value,
    right from the start of the simulation.

    --- end quote ---


    If, however, I uncomment the last line, assignment s1 <= 1, the
    driver_counter is executed twice, reporting that there is only one driver.

    Is everything ok? Why the resolution is not invoked when drivers are
    disconnected?
    valtih1978, Jan 13, 2014
    #1
    1. Advertising

  2. valtih1978

    Dio Gratia Guest

    The resolution function calls are caused by transactions on drivers.

    No drivers, no transactions.

    I added std.textio in a use clause, an entity declaration for top with no ports.

    The only way I know of to get two resolution function calls would be to have S1 be evaluated in an expression after it's active (and the default valuecauses a transaction, followed by the 0 time concurrent signal assignment):

    signal S1: driver_counter integer := 6;
    signal S2: driver_counter integer := 0;

    begin
    -- s1 <= 1 ;

    CONC_SIGNAL_ASSIGN_EQUIV:
    process
    begin
    s1 <= 1;
    wait; -- only a static expression on the right hand side, executes once.
    end process;
    s2 <= s1;

    ghdl -r top
    top.vhdl:19:17:mad:0ms:(report note): 6, count resolved => 1
    top.vhdl:19:17:mad:0ms:(report note): 1, count resolved => 1
    top.vhdl:19:17:mad:0ms:(report note): 1, count resolved => 1

    The first one is for S2 following the default value assignment to S1, the second one is S1 assigned 1, the third one is for S2 being assigned S1 after an S1 transaction.

    Otherwise there should be only one transaction during a simulation cycle, and without S1 appearing on the right hand side of an assignment (or in a sensitivity list) there would be only one time 0 delta cycle (and one transaction on S1, to 1).

    It sounds like Modelsim is doing something you've managed to catch them outat that wouldn't otherwise matter (an extra delta cycle just for default values), or what you've presented as the behavior isn't complete. With your architecture unmodified ghdl only reports one invocation of the resolution function. (One transaction for one simulation cycle at time 0, the resolved driver value of 1):

    ghdl -r top
    top.vhdl:19:17:mad:0ms:(report note): 1, count resolved => 1

    See IEEE Std 1076-1993, 12.4.4 (Elaboration) Other concurrent statements,
    12.6.1 Drivers (Execution of a model) Drivers, and 12.6.2 (Execution of a model) Propagation of signal values. (Or equivalent sections in -2008, -2002 should match -1993).

    This was done with ghdl-0.31 date stamped 20140108, gcc version.
    Dio Gratia, Jan 14, 2014
    #2
    1. Advertising

  3. valtih1978

    valtih1978 Guest

    Wait, I do not understand.

    Is Modelsim wrong generating a transaction with single assignment S1 <=
    1 but no S2 <= 1?

    I expected to catch the modelsim on the resolution invocation even
    without a transaction. I do not understand why do you refer me to the
    IEEE sections. Do you mean that Ashenden is wrong or not absolutely
    certain in the cited quote?



    On 14.01.2014 4:28, Dio Gratia wrote:
    > The resolution function calls are caused by transactions on drivers.
    >
    > No drivers, no transactions.
    >
    > I added std.textio in a use clause, an entity declaration for top with no ports.
    >
    > The only way I know of to get two resolution function calls would be to have S1 be evaluated in an expression after it's active (and the default value causes a transaction, followed by the 0 time concurrent signal assignment):
    >
    > signal S1: driver_counter integer := 6;
    > signal S2: driver_counter integer := 0;
    >
    > begin
    > -- s1 <= 1 ;
    >
    > CONC_SIGNAL_ASSIGN_EQUIV:
    > process
    > begin
    > s1 <= 1;
    > wait; -- only a static expression on the right hand side, executes once.
    > end process;
    > s2 <= s1;
    >
    > ghdl -r top
    > top.vhdl:19:17:mad:0ms:(report note): 6, count resolved => 1
    > top.vhdl:19:17:mad:0ms:(report note): 1, count resolved => 1
    > top.vhdl:19:17:mad:0ms:(report note): 1, count resolved => 1
    >
    > The first one is for S2 following the default value assignment to S1, the second one is S1 assigned 1, the third one is for S2 being assigned S1 after an S1 transaction.
    >
    > Otherwise there should be only one transaction during a simulation cycle, and without S1 appearing on the right hand side of an assignment (or in a sensitivity list) there would be only one time 0 delta cycle (and one transaction on S1, to 1).
    >
    > It sounds like Modelsim is doing something you've managed to catch them out at that wouldn't otherwise matter (an extra delta cycle just for default values), or what you've presented as the behavior isn't complete. With your architecture unmodified ghdl only reports one invocation of the resolution function. (One transaction for one simulation cycle at time 0, the resolved driver value of 1):
    >
    > ghdl -r top
    > top.vhdl:19:17:mad:0ms:(report note): 1, count resolved => 1
    >
    > See IEEE Std 1076-1993, 12.4.4 (Elaboration) Other concurrent statements,
    > 12.6.1 Drivers (Execution of a model) Drivers, and 12.6.2 (Execution of a model) Propagation of signal values. (Or equivalent sections in -2008, -2002 should match -1993).
    >
    > This was done with ghdl-0.31 date stamped 20140108, gcc version.
    >
    valtih1978, Jan 14, 2014
    #3
  4. valtih1978

    Dio Gratia Guest

    On Wednesday, January 15, 2014 4:01:08 AM UTC+13, valtih1978 wrote:
    > Wait, I do not understand.
    >
    >


    I can short circuit all this by stating my understanding was flawed (the standard is a bit big to hold entirely in your head).

    I did an email exchange with Tristan Gingold the author of ghdl overnight and he demonstrated fairly conclusively ghdl should have reported two resolution function calls:

    > Looks like this following patch fixes the issue:
    >
    > --- a/translate/grt/grt-signals.adb Tue Jan 14 04:28:23 2014 +0100
    > +++ b/translate/grt/grt-signals.adb Tue Jan 14 16:50:52 2014 +0100
    > @@ -3257,7 +3257,7 @@
    >
    > when Net_One_Resolved =>
    > Sig.Has_Active := True;
    > - if Sig.Nbr_Ports > 0 then
    > + if Sig.S.Nbr_Drivers + Sig.Nbr_Ports > 0 then
    > Compute_Resolved_Signal (Sig.S.Resolv);
    > Sig.Value := Sig.Driving_Value;
    > end if;
    >
    >
    > I now get:
    >
    > $ ghdl_mcode -c driver1.vhdl -r top
    > driver1.vhdl:18:5:mad:0ms:(report note): 6, count resolved => 1
    > driver1.vhdl:18:5:mad:0ms:(report note): 1, count resolved => 1


    He found there was a missing resolution function call during the initial transaction in procedure Init_Signals (in grt-signals.adb) ignoring drivers for a resolved signal unless they were ports.

    It would appear Modelsim is indeed correct reporting two resolution function call occurrences.

    (The fix will show up in in ghdl-0.32, and it would appear it takes multiple drivers or a resolution function that reports like driver_counter in top.vhdl to show the problem. You've contributed indirectly to making ghdl a better VHDL tool.)
    Dio Gratia, Jan 14, 2014
    #4
  5. valtih1978

    Andy Guest

    Many simulators will not call the resolution function if there is only one driver for a signal in the model. There are probably simulator settings to disable that optimization.

    Andy
    Andy, Jan 14, 2014
    #5
  6. valtih1978

    valtih1978 Guest

    My question was about "specified behaviour in case of no drivers". Can I
    remind you about that?
    valtih1978, Jan 15, 2014
    #6
  7. valtih1978

    valtih1978 Guest

    My question was about "specified behaviour in case of no drivers". Can I
    remind you about that?
    valtih1978, Jan 15, 2014
    #7
  8. valtih1978

    Andy Guest

    On Wednesday, January 15, 2014 5:08:54 AM UTC-6, valtih1978 wrote:
    > My question was about "specified behaviour in case of no drivers". Can I
    > remind you about that?


    Have you contacted Modelsim about this? If so, what did they say?

    While Ashenden is a recognized expert in VHDL, and IINM actually wrote partof the LRM, the LRM is the authoratative definition of the language, not Ashenden. Modelsim should follow the LRM, not Ashenden, if the two conflict.Therefore, we generally refer to the LRM when trying to figure out how a VHDL simulator should behave.

    My speculation (since I am only a user of Modelsim, that's all it is, speculation) is that with no drivers, there is no reason to call a resolution function. With what argument would it be called, a null vector?

    Given that your resolution function changes the value even if only one driver is used, does the signal actually get initialized to 6, or to 1 (with the concurrent assignment statement uncommented)?

    If the resolution function were called with no drivers, the resolved value would be 0, not 6. Would we expect the initial value of the signal to then be 0, or 6? LRM 6.4.2.3 indicates that the value provided by the initialization expression is the initial value of the signal, but later in the same section:

    "The default value associated with a scalar signal defines the value component of a transaction that is the initial contents of each driver (if any) of that signal. The time component of the transaction is not defined, but the transaction is understood to have already occurred by the start of simulation."

    For most cases (wierd resolution functions excluded), there is no difference.

    From the LRM descriptions, I might expect that with no drivers, the signal is initialized to 6. With one driver, the signal would have an initial value of 1 (regardless of the value assigned by the concurrent assignment, it is the resolved value of all drivers, which are initialized to 6).

    Interesting test case...

    Andy
    Andy, Jan 15, 2014
    #8
  9. valtih1978

    valtih1978 Guest

    > Have you contacted Modelsim about this? If so, what did they say?

    Here is a special group to ask details about VHDL. Why should we do it
    in private conversation with Modelsim? We may contract Modelsim only
    after we establish that their simulator is bad.


    > My speculation (since I am only a user of Modelsim, that's all it is,

    speculation) is that with no drivers, there is no reason to call a
    resolution function. With what argument would it be called, a null vector?

    Yes, the fact that VHDL specification mandates the default value,
    mentioned by Ashenden, means that there is no value for the function to
    operate on.


    > From the LRM descriptions, I might expect that with no drivers, the

    signal is initialized to 6.

    Why not null?

    > With one driver, the signal would have an initial value of 1


    That is clear. But why is the second call of the resolution function?

    > For most cases (wierd resolution functions excluded), there is no

    difference.

    I suspect that Ashenden precisely stipulates the wired cases that you
    exclude. If there is no differece, there is no need to make the
    stipulation made by Ashenden.
    valtih1978, Jan 15, 2014
    #9
  10. valtih1978

    valtih1978 Guest

    In the case of

    signal UResOfRes: (or_bits) bit_vector(1 to 4) := "0111";
    begin
    UResOfRes <= "1111";
    -- UResOfRes <= "0011";

    resolutions are not invoked even with single vector. I must to enable
    the second driver in order to for the resolutions to start invoking. I
    always call vsim with -nvopt.
    valtih1978, Jan 15, 2014
    #10
  11. valtih1978

    valtih1978 Guest

    Curiously,

    signal UResOfRes: (or_bits) bit_vector(1 to 1) := "0";
    begin
    UResOfRes <= "1";
    UResOfRes <= "0" after 2 ns;

    Calls the resolution twice, with (0,0) and (0,1) at time 0 ns whereas
    the same with init value := "0" in place of "1", calls the resolution
    with (1,1) at time 0 and (0,1) at time 2 ns.
    valtih1978, Jan 15, 2014
    #11
  12. valtih1978

    valtih1978 Guest

    Ok, this helped me to figure out the logic. No resolution function is
    called on the signal if there are no drivers. Otherwise, the resolution
    function is called to initialize the signal where the signal initial
    value is used as the initial driver value. This particularly means that
    resolution function

    function sum(integers: integer_array) return integer
    result := 0
    foreach I in integers, result += I

    for the signal s3 : sum integer := 3 will initialize the signal to 6
    instead of 3 if there are two drivers because we have two drivers and
    each contributes 3, and to 3 if there is one driver or no drivers.
    valtih1978, Jan 15, 2014
    #12
  13. valtih1978

    Andy Guest

    There is a difference between a null vector and "no value". No value would be an error since it violates the type check on the input parameter. Calling your driver_counter() function with a null vector is completely legal (but I doubt it happens as a resolution function). The function would return avalue of 0, because the result variable is initialized to 0, and never altered if the input argument is a null vector.

    > Why not null?


    Because null is not a legal integer value.

    > But why the second call of the resolution function?


    Because the transaction from the concurrent assignment statement happens attime 0 plus 1 delta, whereas the initialization call happens at 0+0.

    > I suspect that Ashenden precisely stipulates the wired cases that you

    exclude.

    Semantics: "stipulate" = "explicitly state". Ashenden did not explicitly state the wierd cases. Perhaps he had them in mind, since they are one of the few ways his case could be demonstrated.

    Andy
    Andy, Jan 16, 2014
    #13
  14. valtih1978

    Andy Guest

    On Wednesday, January 15, 2014 2:38:28 PM UTC-6, valtih1978 wrote:
    > ...will initialize the signal to 6 instead of 3 if there are two drivers because we have two drivers and each contributes 3, and to 3 if there is one driver or no drivers.


    Did you test this, or is this what you expect will happen?

    I believe you are correct, but I have not tried it.

    Thanks for the info.

    Andy
    Andy, Jan 16, 2014
    #14
  15. valtih1978

    valtih1978 Guest

    This is how Modelsim behaves and it seems reasonable to me.

    ---
    This email is free from viruses and malware because avast! Antivirus protection is active.
    http://www.avast.com
    valtih1978, Jan 16, 2014
    #15
  16. valtih1978 wrote:

    > --- begin code ---
    >
    > architecture ARCH of TOP is
    >
    > type int_vector is array (integer range<>) of integer;
    > function driver_counter( values : int_vector ) return integer is
    > variable result : integer := 0;
    > variable l: line;
    > begin
    > for index in values'range loop
    > if values(index) /= 0 then
    > result := result + 1;
    > write (l, integer'image(values(index)) & ",");
    > end if;
    > end loop;
    > report l.all & " count resolved => " & integer'image(result);
    > return result;
    > end function;


    When using access types (which "line" is), one always must be careful not to
    create a memory leak. The above code contains a memory leak. A string is
    allocated by calling "write". The return from the function where the
    allocation took place results in loss of the "pointer" (l) to the string.
    The memory used by the sting is not freed, there is no automatic garbage
    collection in VHDL.

    The solution is to place a deallocate statement between the report and
    return statement:

    deallocate(l);

    Even if the procedure writeline was used (instead of report), deallocate
    would be necessary. The writeline procedure leaves l pointing to an empty
    string. Even an empty string uses a non-zero amount of memory.

    --
    Paul Uiterlinden
    AimValley B.V.
    Paul Uiterlinden, Jan 20, 2014
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. CRON
    Replies:
    24
    Views:
    200,643
    Adrienne Boswell
    Jun 20, 2006
  2. Johnny
    Replies:
    3
    Views:
    453
    Robert Kern
    Aug 23, 2005
  3. Hari Sekhon
    Replies:
    0
    Views:
    501
    Hari Sekhon
    Jun 20, 2006
  4. Vinko Vrsalovic

    int func() v/s int func(void)

    Vinko Vrsalovic, Jan 21, 2005, in forum: C Programming
    Replies:
    14
    Views:
    1,303
    Villy Kruse
    Jan 24, 2005
  5. Alex Vinokur
    Replies:
    6
    Views:
    351
    Tor Rustad
    Nov 18, 2006
Loading...

Share This Page