Jump to content

need clarification: for...join_none issue


Recommended Posts

I have simplified my real code into following code example:

module top;

class test;

static bit _dummy = _dummy_func();

static function bit _dummy_func();

fork

$display("hello");

join_none

_dummy_func = 0;

endfunction: _dummy_func

endclass: test

endmodule: top

Since the function _dummy_func including a fork...join_none statement isn't called in any initial or always block, simulators don't handle it uniquely. As a result, my tb on the UVM isn't universal any longer.

So, I'm just wondering if it is legal against the LRM.

Link to comment
Share on other sites

It's not legal. Static initialization occurs before any initial or always processes start, there is no process to fork from. Also, there is no guaranteed ordering of static variable initialization.

A better solution is to have a an access function get_dummy that retrieves the value of _dummy and initializes it if is not the default value. In your case the initialization is the default value, so it serves no purpose.

Link to comment
Share on other sites

  • 2 weeks later...

IEEE 1800-2009 18.14.1 (On random stability):

"When a class object is created by a static declaration initializer, there is no active thread..."

I'm not sure that implies you can't do a fork though this section has no reference to it.

I'm curious which simulators have you tried.

One thing I see is you've got your class declared in a module. That could create a separate class definition for each instance of the module.

Link to comment
Share on other sites

13.4.4 Background processes spawned by function calls

Functions shall execute with no delay. Thus, a process calling a function shall return immediately.

Statements that do not block shall be allowed inside a function; specifically, nonblocking assignments, event

triggers, clocking drives, and fork-join_none constructs shall be allowed inside a function.

Calling a function that tries to schedule an event that cannot become active until after that function returns

shall be allowed provided that the thread calling the function is created by an initial procedure, always

procedure, or fork block from one of those procedures and in a context in which a side effect is allowed.

Implementations shall issue an error either at compile time or run time when these provisions have not been

met.

A fork/join_none is not allowed in this context because there is no thread calling the function from initial/always block.
Link to comment
Share on other sites

IEEE 1800-2009 18.14.1 (On random stability):

"When a class object is created by a static declaration initializer, there is no active thread..."

I'm not sure that implies you can't do a fork though this section has no reference to it.

I'm curious which simulators have you tried.

One thing I see is you've got your class declared in a module. That could create a separate class definition for each instance of the module.

I'm building up a UVM flow for my team working with the three simulators. The code I showed in this thread is just for describing the issue, not being the real code actually. The code was written on VCS initially and then ported to IUS and Questa. This kind of utility classes were designed to provide waveform dumpping and other service and they always are singleton classes. I hope its user wanting the service just needs to include the file class. When the class is "loaded" at the beginning of simulation a back-ground thread can be spawned. Obviously, there would be no "initial" block there.

Currently VCS and IUS support this coding style but Questa( latest 10.1d) doesn't.

I think Dave has pointed out the statements in the LRM. To make the code standard complaint I have to add "initial" blocks. But really I think it is handy coding style.

And thanks Dave and jadec for supporting this issue.

Link to comment
Share on other sites

Robert,

Although this style seems handy and works in some cases, there are a lot of issues around it that need to be resolved. What you are asking is for a static initialization to behave like an initial block, yet all static initializations are supposed to execute before any initial blocks. Regardless of any LRM issues, coding this way creates a problem for guaranteeing random stability for all classes constructed this way.

Link to comment
Share on other sites

  • 3 weeks later...

Hi Dave,

Sorry for the latency. Speaking of "random stability", I just review the "thread stability and object stability" section of the LRM. Since the static initialization of object in module, interface, program and package is allowed, making use of the initialization seed of the enclosing design element, static creation of "dynamic thread" can follow the same way. In some sense it is another flavor of "initial" and "always*" procedural.

Link to comment
Share on other sites

Yes, you could consider the initialization of all static variables as a separate "initial" procedural thread that executes before any other, but there is still no defined order of execution for the static initialization code within one design element. Not saying it couldn't be done; it just hasn't yet.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...