Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for system tasks #276

Open
wants to merge 16 commits into
base: master
Choose a base branch
from

Conversation

sifferman
Copy link
Contributor

Fixes #273

@sifferman sifferman marked this pull request as ready for review January 25, 2024 07:50
@sifferman
Copy link
Contributor Author

I'm not currently sure how to include the filename, line number, and hierarchical scope, so I left it out. I can look into it later, but I may wait for guidance.

Copy link
Owner

@zachjs zachjs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this contribution! Although in theory downstream tools can mostly handle these tasks, there is a great opportunity for sv2v to help: we can at least output a SystemVerilog source location, whereas downstream tools cannot. This is worth pursuing.

  1. I think we'll want to add an --exclude flag (SeverityTasks) allowing this conversion to be skipped.
  2. We can get the hierarchical information from the Scoper framework, though its semantics are esoteric. I can do this if necessary.
  3. We could get source information while parsing, adding the string into the AST immediately. I can give some pointers if you'd like.

src/Convert.hs Outdated Show resolved Hide resolved
@@ -138,6 +138,8 @@ instance Show Expr where
showString " : " .
shows f .
showChar ')'
showsPrec _ (Call (Ident e) (Args [] [])) | "$" `isPrefixOf` e =
shows (Ident e)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this purely a stylistic change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, icarus was getting mad at $time() vs $time. Icarus seems to be accurate with the LRM:

From 3.7.3 and A.8.2

system_function_call ::= system_function_identifier
    [ ( expression { , expression } ) ]

system_task_enable ::=
    system_task_identifier [ ( [ expression ] { , [ expression ] } ) ] ;
function_call ::= hierarchical_function_identifier{ attribute_instance }
    ( expression { , expression } )

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand. system_function_call has square brackets around the argument list including the parens, meaning it should be optional. What am I missing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verilog has square brackets around the parentheses, but not around the first expression. So if parentheses exist, they must have at least 1 expression

(Subroutine (Ident "$write") (Args [(String "[%0t] Fatal: "), timeCall] [])),
(Subroutine (Ident "$display") (Args displayArgs [])),
(Subroutine (Ident "$finish") (Args [finishArgs] []))
]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if some helper functions could make this conversion a bit more succinct and maintainable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering the same thing. When I tried making helper functions, I just made the code less readable. But this is the first time I've written Haskell, so I'm sure I'm missing something. Though I can give it another shot!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did my best. Could you take a look?

src/Convert/SystemTasks.hs Outdated Show resolved Hide resolved
test/core/elab_task.v Outdated Show resolved Hide resolved
test/core/elab_task.sv Outdated Show resolved Hide resolved
@@ -354,9 +354,7 @@ instance Show Number where
show (UnbasedUnsized bit) =
'\'' : show bit
show (Decimal (-32) True value) =
if value < 0
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why this check is needed, but I couldn't get RawNum (-1) to work with it. So I just removed it

Comment on lines 21 to 19
initial begin
#0;
if (_sv2v_elaboration_fatal != -1)
$finish(_sv2v_elaboration_fatal);
end
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized that having a bunch of initial $finish; statements everywhere causes a race condition. Now, if a $fatal elaboration task is found, this block is included which will check if $finish should be run due to a$fatal elaboration.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate on this race condition? Commercial frontends I tested all seem to stop on the "first" $fatal they encounter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The race condition is on the elaboration messages. I would expect all elaboration messages to be printed before exiting. I can retest this on commercial tools if you'd like

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it's all over the place.

  • Modelsim and VCS print all elaboration messages.
  • Xcelium and DC stop on the "first" $fatal.
  • Vivado is broken. It stops on the first $fatal with an custom error message. It ignores $fatals with no custom error message.
  • Genus does not support elaboration severity tasks.

SystemVerilog:

module tb; // or test
    $fatal;
    $fatal(0);
    $fatal(0, "%b", 4);
    $info;
    $info("%b", 1);
    $warning;
    $warning("%b", 2);
    $error;
    $error("%b", 3);
endmodule

Modelsim:

# ** Fatal: 
#    Scope: tb File: tb.sv Line: 2
# ** Fatal: 
#    Scope: tb File: tb.sv Line: 3
# ** Fatal: 00000000000000000000000000000100
#    Scope: tb File: tb.sv Line: 4
# ** Info: 
#    Scope: tb File: tb.sv Line: 5
# ** Info: 00000000000000000000000000000001
#    Scope: tb File: tb.sv Line: 6
# ** Warning: 
#    Scope: tb File: tb.sv Line: 7
# ** Warning: 00000000000000000000000000000010
#    Scope: tb File: tb.sv Line: 8
# ** Error: 
#    Scope: tb File: tb.sv Line: 9
# ** Error: 00000000000000000000000000000011
#    Scope: tb File: tb.sv Line: 10

VCS:

Error-[FEST] $fatal elaboration system task
  msg:  
  location: file tb.sv line 2
  path: tb                                       


Error-[FEST] $fatal elaboration system task
  msg:  
  location: file tb.sv line 3
  path: tb                                       


Error-[FEST] $fatal elaboration system task
  msg: 100
  location: file tb.sv line 4
  path: tb                                       

Info-[IEST]  msg:  
  location: file tb.sv line 5
  path: tb                                       
Info-[IEST]  msg: 1
  location: file tb.sv line 6
  path: tb                                       

Warning-[WEST] $warning elaboration system task
  msg:  
  location: file tb.sv line 7
  path: tb                                       


Warning-[WEST] $warning elaboration system task
  msg: 10
  location: file tb.sv line 8
  path: tb                                       


Error-[EEST] $error elaboration system task
  msg:  
  location: file tb.sv line 9
  path: tb                                       


Error-[EEST] $error elaboration system task
  msg: 11
  location: file tb.sv line 10
  path: tb

Xcelium:

    $fatal;
         |
xmelab: *F,FATALE (./tb.sv,2|9): Elaboration exited via $fatal(1) at tb.

DC:

Error:  test.sv:2: $fatal() output:  (ELAB-2050)

Vivado:

INFO: [Synth 8-6157] synthesizing module 'test' [test.sv:1]
ERROR: [Synth 8-6058] Synth Error: 32'sb00000000000000000000000000000100  [test.sv:4]
ERROR: [Synth 8-6156] failed synthesizing module 'test' [test.sv:1]

Genus:

Error   : System task illegal format specifier encountered. [CDFG-912] [elaborate]

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd prefer to fail immediately because it seems like acceptable behavior and makes this conversion quite a bit simpler. The Verilog output is a bit more intuitive, too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that conversion is simpler and more intuitive, but I do like having all error messages available immediately. And it makes simulations more deterministic.

But it's not a universal feature, and it looks like both are within spec:

If $fatal is executed then after outputting the message the elaboration may be aborted, and in no case shall simulation be executed. Some of the elaboration system task calls may not be executed either. The finish_number may be used in an implementation-specific manner.

Up to you! Happy with either. Do you want to revert this feature, or should I?

@sifferman
Copy link
Contributor Author

Thanks for the code review!

  1. I added --exclude=SeverityTasks
  2. I've thought about the hierarchical scope more, and I'm not sure including it is important since it's not guaranteed the simulation will follow the same hierarchy as what was passed to sv2v. I think this could just be skipped.
  3. I'm not certain the best way to do this. Pointers would be helpful! 😃

@sifferman sifferman force-pushed the system_tasks branch 2 times, most recently from 65c4a7e to ca8626b Compare March 11, 2024 18:34
@sifferman
Copy link
Contributor Author

Just fixed the merge conflicts. Happy to make changes as needed!

@zachjs
Copy link
Owner

zachjs commented Apr 30, 2024

Scope and location information should be available via the Scoper module, the it's not super well documented, so I can take a stab at that if you'd like.

@sifferman
Copy link
Contributor Author

Scope and location information should be available via the Scoper module, the it's not super well documented, so I can take a stab at that if you'd like.

Up to you. These were my further thoughts:

I'm not sure including it is important since it's not guaranteed the simulation will follow the same hierarchy as what was passed to sv2v. I think this could just be skipped.

Also, what if a module is called multiple times? It may be better just to have the module name and that's it

@zachjs
Copy link
Owner

zachjs commented Jun 9, 2024

I'm sorry for the continued delay in getting this PR in. I want to reiterate that I think this is a great contribution! I'm working on getting my IR changes merged now. Probably the AST should have used a representation like this for these tasks from the beginning. Then I'll iterate a bit on the items above: A) adding scope and location information if appropriate; and B) simplifying the $fatal elaboration.

@zachjs
Copy link
Owner

zachjs commented Jun 16, 2024

I think this is now pretty close to complete. @sifferman, what do you think of the current implementation? Please feel free to suggest any changes. I have no particular attachment to the current message format.

Copy link
Contributor Author

@sifferman sifferman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Sorry for the delay)

Thanks! The scope and filename feature looks great! I left a possible suggestion for the message format

return $ Block Seq "" [] [stmtDisplay, stmtFinish]
where
msg scope file = severityToString severity ++ " [" ++ prefixStr ++ "] "
++ file ++ " - " ++ scope ++ if null displayArgs then "" else " - "
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be a bit overwhelming having everything be on one line. Maybe the message should be on the next line like this?

Suggested change
++ file ++ " - " ++ scope ++ if null displayArgs then "" else " - "
++ file ++ " - " ++ scope ++ if null displayArgs then "" else "\\n msg: "
module a;
    $info("Parameters properly configured and verified.");
    initial begin : A_INITIAL
        $info("Initialized to state IDLE");
    end
endmodule

before:

Info [elaboration] test.sv:3:5 - a - Parameters properly configured and verified.
Info [0] test.sv:5:9 - a.A_INITIAL - Initialized to state IDLE

after:

Info [elaboration] test.sv:3:5 - a
 msg: Parameters properly configured and verified.
Info [0] test.sv:5:9 - a.A_INITIAL
 msg: Initialized to state IDLE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Convert severity tasks to Verilog
2 participants