1800-2009 and $fatal

J

Jared Casper

Guest
There appears to be an inconsistency in 1800-2009. In 20.9 it says that
the first argument to $fatal shall be consistent with the first argument
to $finish, namely, an integer 0, 1, or 2 (as defined in 20.2).

However, the examples on pages 315 and 405 use '$fatal("Sorry");'

Is the first argument to $fatal optional, or is the example code buggy?
Did I miss something? Nothing came up in a quick search of the mantis
db on eda.org.

Jared
 
On Mon, 08 Mar 2010 20:33:41 -0800, Jared Casper wrote:

There appears to be an inconsistency in 1800-2009. In 20.9 it says that
the first argument to $fatal shall be consistent with the first argument
to $finish, namely, an integer 0, 1, or 2 (as defined in 20.2).

However, the examples on pages 315 and 405 use '$fatal("Sorry");'

Is the first argument to $fatal optional, or is the example code buggy?
Did I miss something?
No, I don't think you did. This looks like a good catch;
it's clear that the examples are buggy [but see below!!].
The first argument to $fatal is an error code, not a message.
$fatal, like $finish, is happy with no arguments; the
exit code then defaults to 1.

Nothing came up in a quick search of the mantis db on eda.org.
Do you want to raise a Mantis ticket? If you don't have
write access, yell here and I'll do it.

By the way: the examples aren't wrong, just silly. The string
literal "Sorry" has a perfectly good numeric value, which will
go to $finish as the exit code. It's only supposed to be one
of 0, 1, 2 but the LRM doesn't say what happens if you use a
different value.

$display("%0d", "Sorry"); => 358352056953 :)
--
Jonathan Bromley
 
On 03/09/2010 08:34 AM, Jonathan Bromley wrote:
Do you want to raise a Mantis ticket? If you don't have
write access, yell here and I'll do it.
I do not have write access, but will raise a ticket if given access.

By the way: the examples aren't wrong, just silly. The string
literal "Sorry" has a perfectly good numeric value, which will
go to $finish as the exit code. It's only supposed to be one
of 0, 1, 2 but the LRM doesn't say what happens if you use a
different value.

$display("%0d", "Sorry"); => 358352056953 :)
Makes sense, thanks for the explanation.

Jared Casper
 
On Tue, 09 Mar 2010 12:11:23 -0800, Jared Casper wrote:

Do you want to raise a Mantis ticket? If you don't have
write access, yell here and I'll do it.
Logged as Mantis 3015.

I do not have write access, but will raise a ticket if given access.
Not in my gift, I'm afraid :-(
--
Jonathan Bromley
 
Jonathan Bromley wrote:

By the way: the examples aren't wrong, just silly. The string
literal "Sorry" has a perfectly good numeric value, which will
go to $finish as the exit code. It's only supposed to be one
of 0, 1, 2 but the LRM doesn't say what happens if you use a
different value.

$display("%0d", "Sorry"); => 358352056953 :)
This may be syntactically valid, but from the users standpoint this is
certainly semantically invalid and in my opinion should be flagged as
such. Yes strings have a numeric representation, but that's not how this
task is used. My guess is that the person who wrote the code was
expecting it to print a message with the "Sorry" text just like the
other severity tasks. An appropriate error message quickly sets them
straight at compile time vs waiting/deciphering odd results during a
simulation run.

Cary
 
On Mon, 15 Mar 2010 09:46:43 -0700, "Cary R." wrote:

[ $fatal or $finish with a string as its first argument ]
... may be syntactically valid, but from the users
standpoint this is certainly semantically invalid
and in my opinion should be flagged as such.
My opinion too, but I was just pointing out the LRM situation.

My guess is that the person who wrote the code was
expecting it to print a message with the "Sorry" text
just like the other severity tasks.
Sure, that's evidently the intent. So much so that the smart
folk (*very* smart folk) who wrote the assertions part of the
LRM were able to slip up on it.

If they had supplied a SystemVerilog string-type variable, or
a string-valued expression, as the argument then they *would*
have gotten a compile error. But a literal string, in double
quotes, is nothing more than a number in drag; I can't see how
it could possibly yield a syntax error. Maybe a warning, if
you have a very proactive and programmer-friendly compiler; but
no-one reads warnings, do they?

An appropriate error message quickly sets them
straight at compile time vs waiting/deciphering odd
results during a simulation run.
Or, worse still, at the tail end of a long run. Sure.
But - once again - the "Sorry" argument is just a number;
even if the LRM said that such a huge number is an illegal
argument value (which it doesn't, not explicitly anyway)
the error would not surface until the system task was called.

##############

Ooooh, second thoughts: When you call a PLI app with a
string argument, it's handled differently - the string is
stored somewhere and the PLI code gets a C-string style
pointer to it, if I'm not mistaken. Given that $finish
and $fatal have the syntactic form of PLI calls, perhaps
the compiler *could* tell the difference? Hmmm. Not sure.
--
Jonathan Bromley
 
Jonathan Bromley wrote:

....

If they had supplied a SystemVerilog string-type variable, or
a string-valued expression, as the argument then they *would*
have gotten a compile error. But a literal string, in double
quotes, is nothing more than a number in drag; I can't see how
it could possibly yield a syntax error. Maybe a warning, if
you have a very proactive and programmer-friendly compiler; but
no-one reads warnings, do they?
As you allude to later the PLI is your friend and yes warnings are
usually ignored which is why an error is much more elegant.

An appropriate error message quickly sets them
straight at compile time vs waiting/deciphering odd
results during a simulation run.

Or, worse still, at the tail end of a long run. Sure.
But - once again - the "Sorry" argument is just a number;
even if the LRM said that such a huge number is an illegal
argument value (which it doesn't, not explicitly anyway)
the error would not surface until the system task was called.
Not so, in the compile routine you have all the type information to
catch this one. If you have either a parameter or a constant that is a
StringConst complain with an error at compile time. Now if you assign a
string to a variable and pass that as the first argument, well you get
what you deserve!

Ooooh, second thoughts: When you call a PLI app with a
string argument, it's handled differently - the string is
stored somewhere and the PLI code gets a C-string style
pointer to it, if I'm not mistaken. Given that $finish
and $fatal have the syntactic form of PLI calls, perhaps
the compiler *could* tell the difference? Hmmm. Not sure.
Actually it's usually stored in the same place, but you have the type
information I mentioned above to decode it.

As a point of reference one enlightened simulator does not consider
string constants to be numeric for the system calls, so things like this
are caught at the beginning of the simulation.

$fdisplay("I'm not gonna print as expected!");

This does prevent things like.

$fdisplay("\001", "OK this should work.");

from running, but in my opinion that's a pretty poor coding practice and
as a user I'd prefer to know that I accidentally dropped a numeric value
vs being able to do some obfuscated string as a number trick.

Cary
 
On Mon, 15 Mar 2010 19:54:29 -0700, "Cary R." wrote:

But - once again - the "Sorry" argument is just a number;
even if the LRM said that such a huge number is an illegal
argument value (which it doesn't, not explicitly anyway)
the error would not surface until the system task was called.

Not so, in the compile routine you have all the type information to
catch this one.
Yes, for sure; but it is far from obvious that you are
entitled to use that information at compile time.

If you have either a parameter or a constant that is a
StringConst complain with an error at compile time.
But it's not that simple. For a non-$system subprogram,
my original statement that there is no difference between
a literal string and a literal number is absolutely true
and the compiler simply must not complain. For a $system
or $pli call, the compiler certainly can use the type
information - but only to store what-have-I-got-here
info for later interrogation by the subprogram when it
is called. A well-written PLI app will, of course,
have a checktf to verify at elaboration time that it
has been called with appropriate arguments; one might
reasonably hope that $finish could behave similarly
(for example, $display certainly does a lot of sanity
checking in every tool I've ever used). So, with
hindsight, I agree with you that it's disappointing
that some tools don't provide this check. However,
it is not a *compiler* function in any real sense.

Of course, it is plausible for tools to treat the
well-known system calls as special cases. But - and
here my PLI knowledge is insufficiently deep to be sure -
isn't it the case that I could, if I felt so perverse,
write my own PLI version of $finish and supplant the
system's version? In which case it would be quite
wrong for the compiler to flag an error for *any*
arguments to $finish!!!! Only the elab-time checktf
is entitled to do that.

[Argument type checking]
... does prevent things like
$fdisplay("\001", "OK this should work.");
from running, but in my opinion that's a pretty poor coding practice
No disagreement there :)
--
Jonathan Bromley
 
Jonathan Bromley wrote:
On Mon, 15 Mar 2010 19:54:29 -0700, "Cary R." wrote:

But - once again - the "Sorry" argument is just a number; even if
the LRM said that such a huge number is an illegal argument value
(which it doesn't, not explicitly anyway) the error would not
surface until the system task was called.
Not so, in the compile routine you have all the type information to
catch this one.

Yes, for sure; but it is far from obvious that you are entitled to
use that information at compile time.
I think there is some confusion here, so lets clear that up first. In
the VPI world there are four phases. The register phase is first and it
should not use more than the vpi_register_cb or vpi_register_systf
calls. The sizetf is called next and should only return a value to
indicate the size of a function when it is not defined in the previous
vpi_register_systf. For the most part no VPI routines are expected to work.

After this we have the compiletf. This is what I have been talking
about. At this point you should be able to call everything, but
vpi_get_value, etc. should return the unpropagated T0 values (the
simulation has not started yet). This routine is the only place that you
should need to do type checking and you should do it well to reduce the
burden on the calltf routine. I've never tried to use a put routine
here, but I'm guessing using one is a bad idea.

So in summary I expect complete type information and I use it freely
in the compiletf routine.

If you have either a parameter or a constant that is a StringConst
complain with an error at compile time.

But it's not that simple. For a non-$system subprogram, my original
statement that there is no difference between a literal string and a
literal number is absolutely true and the compiler simply must not
complain. For a $system or $pli call, the compiler certainly can use
the type information - but only to store what-have-I-got-here info
for later interrogation by the subprogram when it is called.
Yes, but this is a discussion on system functions so I don't see how
that point is relevant. Not true, you can use the type information to
flag an error during the compiletf routine, but you should not use the
value because that will not be valid until the calltf routine. So for
the fatal example you can verify that the argument could return a
numeric value, but you can not determine if the value is in range. You
could restrict this to be a constant numeric value or only a variable,
etc. It's all in how you code the compiletf routine. In the end they all
can return a numeric value, but you can define what types are acceptable.

A well-written PLI app will, of course, have a checktf to verify at
elaboration time that it has been called with appropriate arguments;
one might reasonably hope that $finish could behave similarly (for
example, $display certainly does a lot of sanity checking in every
tool I've ever used). So, with hindsight, I agree with you that it's
disappointing that some tools don't provide this check. However, it
is not a *compiler* function in any real sense.
It's a compiletf routine. For tools that have a separate compiler and
run time I agree this may not be checked in the compiler, but it is
still referred to as a compiletf routine. I believe this is the root of
our misunderstanding, we're using different names for the same
functionality.

Of course, it is plausible for tools to treat the well-known system
calls as special cases. But - and here my PLI knowledge is
insufficiently deep to be sure - isn't it the case that I could, if I
felt so perverse, write my own PLI version of $finish and supplant
the system's version? In which case it would be quite wrong for the
compiler to flag an error for *any* arguments to $finish!!!! Only
the elab-time checktf is entitled to do that.
compiletf !== compiler check. Yes, you can override any system function
with your own. You could even change the arguments or the return type of
a function you could even change a function into a task, but you better
know exactly what you're doing if you go down any of these paths! Part
of overriding the function is overriding the compieltf routine so you
get your checking not the original routines checking. As a point of
reference all the system task can be written in straight VPI code.

Cary
 
On Thu, 18 Mar 2010 09:49:56 -0700, "Cary R." wrote:

Not so, in the compile routine you have all the type information to
catch this one.

Yes, for sure; but it is far from obvious that you are entitled to
use that information at compile time.

I think there is some confusion here, so lets clear that up first. In
the VPI world there are four phases. The register phase is first and it
should not use more than the vpi_register_cb or vpi_register_systf
calls. The sizetf is called next and should only return a value to
indicate the size of a function when it is not defined in the previous
vpi_register_systf. For the most part no VPI routines are expected to work.

After this we have the compiletf. This is what I have been talking
about.
OK!!!! I guess I'm still stuck in the dinosaur world of
PLI tf/acc terminology (I've done very little with VPI)
where "checktf" was the common name for that. Actually,
"compiletf" is a damn silly name, isn't it? It happens
nowhere near compile time. Anyway, that aside: when you
first responded, I misunderstood and thought you were
talking about the Verilog compiler proper, parsing the
source code before elaboration. Thanks for spotting
my confusion.

So, thanks for all the discussion. I think we basically
agree: a tool whose $finish implementation doesn't check
its first argument for non-stringiness is unnecessarily
doing its users a disservice.

cheers
--
Jonathan Bromley
 

Welcome to EDABoard.com

Sponsor

Back
Top