Coder Social home page Coder Social logo

sv-parser's Introduction

sv-parser

SystemVerilog parser library fully compliant with IEEE 1800-2017.

Actions Status Crates.io Docs.rs

Tools using sv-parser

  • morty: A SystemVerilog source file pickler
  • svinst: Determines the modules declared and instantiated in a SystemVerilog file
  • svlint: SystemVerilog linter
  • svls: SystemVerilog language server

Usage

[dependencies]
sv-parser = "0.13.3"

sv-parser provides parse_sv function which returns SyntaxTree. SyntaxTree shows Concrete Syntax Tree. It has the preprocessed string and the parsed tree.

RefNode shows a reference to any node of SyntaxTree. You can get RefNode through an iterator of SyntaxTree. Variant names of RefNode follows "Annex A Formal syntax" of IEEE 1800-2017.

Locate shows a position of token. All leaf node of SyntaxTree is Locate. You can get string from Locate by get_str.

Example

The following example parses a SystemVerilog source file and shows module names.

use std::collections::HashMap;
use std::env;
use std::path::PathBuf;
use sv_parser::{parse_sv, unwrap_node, Locate, RefNode};

fn main() {
    let args: Vec<String> = env::args().collect();

    // The path of SystemVerilog source file
    let path = PathBuf::from(&args[1]);
    // The list of defined macros
    let defines = HashMap::new();
    // The list of include paths
    let includes: Vec<PathBuf> = Vec::new();

    // Parse
    let result = parse_sv(&path, &defines, &includes, false, false);

    if let Ok((syntax_tree, _)) = result {
        // &SyntaxTree is iterable
        for node in &syntax_tree {
            // The type of each node is RefNode
            match node {
                RefNode::ModuleDeclarationNonansi(x) => {
                    // unwrap_node! gets the nearest ModuleIdentifier from x
                    let id = unwrap_node!(x, ModuleIdentifier).unwrap();

                    let id = get_identifier(id).unwrap();

                    // Original string can be got by SyntaxTree::get_str(self, locate: &Locate)
                    let id = syntax_tree.get_str(&id).unwrap();
                    println!("module: {}", id);
                }
                RefNode::ModuleDeclarationAnsi(x) => {
                    let id = unwrap_node!(x, ModuleIdentifier).unwrap();
                    let id = get_identifier(id).unwrap();
                    let id = syntax_tree.get_str(&id).unwrap();
                    println!("module: {}", id);
                }
                _ => (),
            }
        }
    } else {
        println!("Parse failed");
    }
}

fn get_identifier(node: RefNode) -> Option<Locate> {
    // unwrap_node! can take multiple types
    match unwrap_node!(node, SimpleIdentifier, EscapedIdentifier) {
        Some(RefNode::SimpleIdentifier(x)) => {
            return Some(x.nodes.0);
        }
        Some(RefNode::EscapedIdentifier(x)) => {
            return Some(x.nodes.0);
        }
        _ => None,
    }
}

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

sv-parser's People

Contributors

barabadzhi avatar dalance avatar davemcewan avatar dependabot-preview[bot] avatar dependabot[bot] avatar lovesegfault avatar minseongg avatar rfdonnelly avatar seanmcloughlin avatar shashankvm avatar skjdbg avatar wendajiang avatar zarubaf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sv-parser's Issues

Task with no direction and datatype seems to generate wrong SyntaxTree

Hello!

Given

task sum(a);endtask

I get the SyntaxTree

SourceText
 Description
  DescriptionPackageItem
   PackageItem
    PackageOrGenerateItemDeclaration
     TaskDeclaration
      Keyword
       Token @line:1: task
       WhiteSpace
        SpaceToken @line:1: <<<<< >>>>>
      TaskBodyDeclaration
       TaskBodyDeclarationWithPort
        TaskIdentifier
         Identifier
          SimpleIdentifier
           Token @line:1: sum
        Symbol
         Token @line:1: (
        TfPortList
         TfPortItem
          DataTypeOrImplicit
           DataType
            ClassType
             PsClassIdentifier
              ClassIdentifier
               Identifier
                SimpleIdentifier
                 Token @line:1: a
        Symbol
         Token @line:1: )
        Symbol
         Token @line:1: ;
        Keyword
         Token @line:1: endtask

But from what I can understand by reading the "Annex A Formal syntax" of IEEE 1800-2017, it should not give a PsClassIdentifier? It should be a PortIdentifier?

Unable to parse out comments

If I try to parse a file with only a comment in it like /* comment */, I don't see any WhiteSpace::Comment nodes only WhiteSpace::Space.

Bug: Incorrect spelling of "assertion".

  • "Asset" should be "Assert"
  • Applies to ImmediateAssetionStatement and DeferredImmediateAssetionItem.
  • Should be fixable with sed, but will require a new minor version to be released.

parse error in "foreach" with two-dimentional array

Thank you for the useful tool.
I noticed that I am using svls in VS Code, so let me know.
I was getting a parse error in multiple foreach of a 2D array. Below is the sample code.

module example_foreach;

  int a[2][3] = '{'{1,2,3}, '{4,5,6}};

initial begin
    foreach(a[i]) foreach(a[i][j]) $display("%d", a[i][j]);
end

endmodule

Question: Help getting started using parser.

Hello.

I am trying to use this parser to find all ports declared in a module. This is the file I am using (very basic).

SystemVerilog file.

module adc(input rst_n);
endmodule

My match statement:

RefNode::AnsiPortDeclarationNet(x) => {
      println!("{:?}", x);
      let id = unwrap_node!(x, PortIdentifier).unwrap();
      let id = get_identifier(id).unwrap();
      let id = syntax_tree.get_str(&id).unwrap();
      println!("port_name: {}", id);
  }

So inside x, I have all the information I need about the port. The direction, type, and name. With the code, I can get the name of the port. But I don't know which identifier to use with unwrap_node to get the direction for example?

When I print x I get: AnsiPortDeclarationNet { nodes: (Some(NetPortHeader(NetPortHeader { nodes: (Some(Input(Keyword { nodes: (Locate { offset: 11, line: 1, len: 5 }, [Space(Locate { offset: 16, line: 1, len: 1 })]) })), DataType(NetPortTypeDataType { nodes: (None, ImplicitDataType(ImplicitDataType { nodes: (None, []) })) })) })), PortIdentifier { nodes: (SimpleIdentifier(SimpleIdentifier { nodes: (Locate { offset: 17, line: 1, len: 5 }, []) }),) }, [], None) }

Instance name defined in a text macro

Thanks again for the great work on this project. I ran into an issue when using a text macro to define an instance name. Considering these two files, I would expect the syntax trees to be the same after pre-processing:

Example 1

`define MOD_INST u_mysubmod
module mymod;
mysubmod `MOD_INST (); 
endmodule

Example 2 (add extra line at the beginning to get line numbers to match)

module mymod;
mysubmod u_mysubmod (); 
endmodule

However, the syntax trees do not match, as show in these two attached files. In particular, the syntax tree in Example 1 does not include the two parentheses in the module instantiation. This makes me think that sv-parser is treating the module instantiation as a macro call.
example_1.txt
example_2.txt

It does seem that the syntax is a bit ambiguous in this case, but both examples do appear to behave the same way when simulated by Icarus Verilog, at least.

By the way, I am using sv-parser 0.8.2.

Compilation Speed

Compilation of this crate is extremely slow to the point of not being able to use an on-the-fly linter at all, making working with this crate difficult.

I've run some profiling using this unstable feature. Below is a screenshot of the report:
Screenshot_20210428_210925

Running self-profiling shows that the longest sections of compilation time have to do with proc_macro expansion. For sv-parser-parser, this is definitely due to the macros for packrat parsing/tracing. For sv-parser-syntaxtree, it's due to all of the derive macros.

I know this is a difficult problem to solve, but I'm curious if there's been any thought on how to improve the compilation speeds of these crates.

Inline comment in preprocessor macro consumes next line

The support for inline comments is great! However, I was observing that it breaks with our codebase when comment stripping is disabled. In particular, the inline comment would also consume the next line comment.

We do use pragma's relatively often:

  // Assumptions and assertions
`ifndef VERILATOR
// pragma translate_off
.. 
// pragma translate_on
`endif

sv-parser would correctly remove the VERILATOR define (as it isn't set) but would also strip the //pragma translate_on from the next line. The pragma, therefore, becomes unbalanced and the result is an incorrect code block.

Do you see an easy chance to resolve this i.e., only strip comments until the end of the line? Thanks.

Parse error bug

{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"}

This bug appeaes when i use snap to install svls, and use "svls" in terminal.

A few fails while parsing ivtest in the sv-tests environment

I noticed sv-parser does an excellent job of parsing most of the code in the sv-tests test bench (https://github.com/SymbiFlow/sv-tests). While working to get ivtest clean I noticed there are a few of our test that sv-parser is failing. One actually looks like a crash. If you were not aware of this TB I wanted to let you know. As one of the developers on Icarus Verilog I am interested in getting it and our regressions as clean as possible. This includes finding things we may have done incorrectly in our regressions so when I see a tool that is parsing most thing I want to know if it is something at our end our a miss on your end. Unfortunately the output they are showing does not indicate why the parse is failing so it's hard for me to know what the issue is.

Help with writing a graph walker

I am trying to write a very simple program that gets the name of all the modules present in the file. The example provided in the README iters over all the nodes to find the module declaration node, which may not be necessary. Is there a more efficient way to do this?

Thanks

support macro in the files

The file list is like blew shown:

define.sv
top.sv
undefine.sv

define.sv:
`define WIDTH 32

top.sv:
module test;
reg [`WIDTH-1:0] cnt;
reg clk=0;
always @(posedge clk) begin
cnt <= cnt + 1;
end
end

undefine.sv
`undefine WIDTH

sv-parser can't support this style.

defines and compile order

Posted this question in the morty project pulp-platform/morty#39 , but probably is more related to this project.
Is it possible to add support for in-order/global defines?

#mydefines.sv:

// This would take presedence until undef, or new value defined by a file that is compiled later
`define DW=32

#mymodule.sv

// Define from previous compiles are available, unless undef. Requires control of compilation order.
module mymodule (
 input [`DW-1:0] data
);
endmodule

morty mydefine.sv mymodule.sv

Parse error for multiple wildcard imports

When trying to parse the snitch IP I get a parse error, I guess due to the multiple import statements?

Error: parse error
   --> /tmp/snitch/hw/ip/snitch/src/snitch.sv:13:60
   |
13 | module snitch import snitch_pkg::*; import riscv_instr::*; #(
   |                                                            ^
Error: Parse error: Some(("/tmp/snitch/hw/ip/snitch/src/snitch.sv", 490))

Steps to reproduce

  • sv-parser: 0.11.3
git clone --depth=1 [email protected]:pulp-platform/snitch.git
cd snitch/hw/ip/snitch
bender sources -f > sources.tcl
morty -f sources.tcl

[Feature Request] Option to Disable Preprocessor

I'm building a tool that operates on the source text, prior to any build processes, and need to have some way to bypass the preprocessed text.

A specific example I have is this:

case (foo)
    STATE1: foo <= bar[1];
    STATE2: foo <= bar[2]'
    `ifdef OPTIONAL_STATES
    OPTIONAL1: foo <= bar[3];
    OPTIONAL2: foo <= bar[4];
    `endif
endcase

Adding text to the second state fails in my case, I believe, because extra whitespace from the ifdef effects the length of the last case's text. (i.e. tree.get_str(case_node).len() is longer than it would be without preprocessing). For my use case it would add extra information to be able to disable the preprocessor and traverse with the preprocessor statements in the tree as well.

Parse failure on parameter assignment

I'm writing a utility based on this crate, and I've run into a bit of a snag with this bit of verilog:

package new_pkg;
        parameter [48*8-1:0] NAME = {<<32{ {<<8{"MODULE NAME", {(48-11){8'h00}}}}}};
endpackage

(editorialized to protect the innocent, obviously, but that definitely fails parsing)

From what I can tell, this is valid SystemVerilog, and both Vivado and Verilator parse it without error.

Compiler directives not printed via syntax_tree.to_string()

It looks as if the compiler directives are implemented as whitespaces in the parser. That seems to prevent them from getting printed.

This code

    #[test]
    fn test_module() {
        let src = r##"
        `timescale 10ns/1ns
        "##;

        let (syntax_tree, _) = parse_sv_str(src, PathBuf::from(""), &HashMap::new(), &[""], false, false).unwrap();
        let mut ela = ElaborationUnit::new();
        ela.elaborate(&syntax_tree);

        print!("{}", syntax_tree.to_string());

    }

yields the following print out, which forgets about the compiler directive:

SourceText
   UnsignedNumber
    Token: '10' @ line:2
   TimeUnit
    Keyword
     Token: 'ns' @ line:2
   Symbol
    Token: '/' @ line:2
   UnsignedNumber
    Token: '1' @ line:2
   TimeUnit
    Keyword
     Token: 'ns' @ line:2

Parsing files in parallel

Does this crate support concurrent parsing of files? If no, is it possible to parse files in parallel in the code using this crate, or is there some blocker?

Feature request

Thank you for this awesome project. I was wondering if the following either or both of the following features can be supported:

  • `define tokens can be added to the syntax tree. I would like to use your parser to generate tag files (SV support in universal-ctags is inadequate).

[https://github.com/google/verible] project supports this feature.

E.g. Verible output producing a `define token

Parse Tree:
Node (tag: kDescriptionList) {
  Node (tag: kPreprocessorDefine) {
    (#"`define" @4-11: "`define")
    (#PP_Identifier @12-16: "ABCD")
    (#"<<`define-tokens>>" @17-18: "1")
  }
...
....
  • Support an option to return the incomplete syntax tree even if there are syntax errors

Thanks again!

Verilog feature

sv-parser aims to be fully compliant with IEEE1800-2017 standard. But if someone wants to use this parser to parse Verilog 2001 file, which is subset of SystemVerilog, there is no need to collect all SystemVerilog nodes in this parser. Is this reasonable to add features into this parser to exactly down-compatible with older IEEE standard ?

ie

sv-parser = { version = "x.x.x", features = ["verilog-2001"] }

`IFDEFs and such cause incorrect line numbers

Placing this on top of code:

`ifndef AN_IF_DEF
logic [1:0] someVar;
`endif

will cause the line numbers of the original file to be shifted 1 up (equivalent to minus 1) more than what it currently is. More lines within the IF_DEF that are not executed will shift it even further, making the lines almost completely useless with large Verilog files and many IF DEFs. This is very hard to work around since the line numbers are critical for my tool.

Any help is appreciated.

Serialize an AST (question, not issue)

I need to modify gate level netlists by changing the input and output of individual gates. Currently, I'm doing this using PCRE. This is an inelegant and haphazard solution. I'd like to instead manipulate the AST generated by your parser, and then reserialize it. Is this currently supported? It does not seem to be.

If not, what do you think the best way to go about serializing the AST would be? My plan is to create tuple structs for each AST node struct which contains references to the the AST and to the node, and then implement the Display trait for these tuple structs.

I apologize if this was the wrong place to ask this question, but I did not see reference to mailing list, discord, etc.

Incorrect syntax error on generate begin-end block

Having a begin-end block around a generate block causes an error. This is very difficult to avoid because it is common to have named begin-end blocks for readability.

Any help is appreciated.

generate 
         begin
     // begin: with_name_no_work_too
         genvar i;
         for (i = 1; i <= 4; i = i + 1)
           begin 
              temp[i]= 1;
           end
      end
   endgenerate

Error:
|
18 | begin
|

Incorrect line numbers with some preprocessor directives

Some preprocessor directives seem to give wrong line numbers.

`default_nettype none
module Mod();
endmodule

The default_nettype get the correct line number, but everything after have line number offset by 1.

SourceText
   DefaultNettypeValue
    Keyword
     Token: 'none' @ line:1
 Description
  ModuleDeclaration
   ModuleDeclarationAnsi
    ModuleAnsiHeader
     ModuleKeyword
      Keyword
       Token: 'module' @ line:3
     ModuleIdentifier
      Identifier
       SimpleIdentifier
        Token: 'Mod' @ line:3
     ListOfPortDeclarations
      Symbol
       Token: '(' @ line:3
      Symbol
       Token: ')' @ line:3
     Symbol
      Token: ';' @ line:3
    Keyword
     Token: 'endmodule' @ line:4

Using include seems to offset the line number with the number of lines in the included file.
inc.vh:

// Line 1
// Line 2
// Line 3
// Line 4
// Line 5
// Line 6
`include "inc.vh"
module Mod();
endmodule
SourceText
 Description
  ModuleDeclaration
   ModuleDeclarationAnsi
    ModuleAnsiHeader
     ModuleKeyword
      Keyword
       Token: 'module' @ line:8
     ModuleIdentifier
      Identifier
       SimpleIdentifier
        Token: 'Mod' @ line:8
     ListOfPortDeclarations
      Symbol
       Token: '(' @ line:8
      Symbol
       Token: ')' @ line:8
     Symbol
      Token: ';' @ line:8
    Keyword
     Token: 'endmodule' @ line:9

Is there some why to get the line number of the source-file (and in case of includes which source/include-file) and not (what I guess) the preprocessed file? Or is this a bug?

"Declaraton" typo

Declaration is misspelled as Declaraton in the name of this enum and in it's members

pub enum ModportPortsDeclaraton {
    Simple(Box<ModportPortsDeclaratonSimple>),
    Tf(Box<ModportPortsDeclaratonTf>),
    Clocking(Box<ModportPortsDeclaratonClocking>),
}

Bug: Pure virtual methods are allowed in non-virtual classes

Methods declared like pure virtual function foo or pure virtual task foo are only allowed inside a virtual class (declared like virtual class foo) or an interface class (declared like interface class foo).
IEEE1800-2017 doesn't phrase this particularly well and it isn't stated as a footnote to Annex A, but it looks clear enough from clause 8.21 (page 186).

This test shows the problem:
https://chipsalliance.github.io/sv-tests-results/?v=sv_parser+uvm-req+class_member_test_5

Syntax issues not being caught

Some syntax issues are not being caught by this parser.
e.g.
Data declaration outside a module:
logic a_var;
this line inside a module:
some_var;
an incorrect data type:
wir a_wire;

This tool can not be used as a syntax linter with these errors. Any suggests are appreciated.

Stack overflow

When parsing very long statements in SystemVerilog, the parser can cause a stack overflow of the rust application. This issue has been noticed several times when using morty, and while parallelization in morty was not helping, extremely long statements cause an issue within the parser. I have attached an excerpt of a generated file used in the pulp_platform group with the critical section causing a stack overflow as a minimal example.
clic_reg_top.zip

Public access to identifier, text, and origin of processed Defines

I am currently trying to extend a SystemVerilog language server based on sv-parser with better define handling. In particular, I want to implement hover tool tips that show the value of a define and also want to support goto definition for defines.

For that, I need access to the value of a define and also the position where it has been defined. However, as far as I can tell, accessing the content of the Defines that are returned by the preprocessor is currently not supported because the struct members are not public. Is this a deliberate limitation or did I simply miss how it can be done?

Any hint is much appreciated. Thank you!

`define with inline comment

If a `define has a C++ style inline comment, sv-parser treats it as part of the value:

`define NAME 42 // Comment

This results in a parse error when the define is used in a parameter:

interface foo #(WIDTH = `NAME) ();
endinterface

Other tools seem to ignore the comment and accept the define.

`cargo doc` fails on `sv_parser_pp`

When I try to run cargo doc on my project it fails once sv_parser_pp is reached with this message:

Documenting sv-parser-pp v0.11.2
error[E0275]: overflow evaluating the requirement `(sv_parser_syntaxtree::Symbol, sv_parser_syntaxtree::CycleDelayConstRangeExpression, sv_parser_syntaxtree::Symbol): std::marker::Sync`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`sv_parser_pp`)

Parse fails for assign statement with intra-delays

For the following module, the parser is unable to parse this. In your example from the README, it just outputs "Parse failed". I'm running version 0.12.0. It looks like it fails when using assign but is ok with always_comb. This is legal syntax as far as I can tell from IEEE Std 1800-2017. It's discussed in 9.4.5 on Intra-assignment timing controls. I believe it'll have to handle the # (delay) and @ (event) timing controls and even if it's also combined with repeat().

`define DLY #10ps

module wire_with_delay (
   input logic clk,
   input logic a,
   output logic y
);

   assign y = #1 a;  // fails
   assign y = `DLY a;  // fails
   assign y = @(posedge clk) a;  // fails
   assign y = repeat(2) @(posedge clk) a; // fails
   always_comb y = `DLY a;  // works

endmodule

function parameter not correctly parsed

Consider following verilog:

    function [7:0] my_function (input [9:0] a, b, inout c [0:5]);
    endfunction

the parse_sv gives following result for port b:

              TfPortItem
               DataTypeOrImplicit
                DataType
                 ClassType
                  PsClassIdentifier
                   ClassIdentifier
                    Identifier
                     SimpleIdentifier
                      Token: 'b' @ line:56

Enable comments in preprocessor

Thanks for this really nice parser. I know that a complete SV parser is a huge undertaking.

I would be interested in similar behavior to #4. I can see that the preprocessor strips comments so they don't appear in the AST later.

When adding (preprocessor.rs:258):

NodeEvent::Enter(RefNode::Comment(x)) => {
                let locate: Locate = x.try_into().unwrap();
                let range = Range::new(locate.offset, locate.offset + locate.len);
                ret.push(locate.str(&s), Some((path.as_ref(), range)));
            }

I see comments after preprocessing, but I get weird behaviour after a macro expansion:
Input:

`define IMPORT(__pkg)  \
    import __pkg::*;
    
module lala;
    // pragma translate_off
    // Test run
    `IMPORT(body2_import_pkg) // this is a macro
    always_comb begin
        a <= b;
    end
    // pragma translate_on
endmodule

Expected:

    
module lala;
    // pragma translate_off
    // Test run
    import body2_import_pkg::*;  // this is a macro
    always_comb begin
        a <= b;
    end
    // pragma translate_on
endmodule

Observed:

 
    
module lala;
    // pragma translate_off
    // Test run
    import body2_import_pkg::*; // this is a macroalways_comb begin
        a <= b;
    end
    // pragma translate_on
endmodule

Even without comments, the indentation becomes strange after macro expansion but it never triggers any illegal behavior, only when line comments (//) are enabled this becomes problematic.

Operation precedence not being followed when creating parse tree

Maybe I'm wrong to expect this, but shouldn't the parse-tree being generated respect System Verilog operation precedence?

I'm using sc-parser visa py-sv-parser 0.3.0. I'm trying to parse the simple module:

module _non();

assign a = 2 * 8 - 1;

endmodule

(never mind, I think, that a is not defined here, as I'm just trying to get the parse tree for the RHS expression - 2 * 8 - 1).

The parse tree (of the RHS expression only, not the entire module) looks like this:

+-------------------------------------------------+-------------+
| Node                                            | Text        |
+-------------------------------------------------+-------------+
| +- Expression                                   | '2 * 8 - 1' |
|    +- ExpressionBinary                          | '2 * 8 - 1' |
|       +- Expression                             | '2'         |
|       |  +- Primary                             | '2'         |
|       |     +- PrimaryLiteral                   | '2'         |
|       |        +- Number                        | '2'         |
|       |           +- IntegralNumber             | '2'         |
|       |              +- DecimalNumber           | '2'         |
|       |                 +- UnsignedNumber       | '2'         |
|       |                    +- Locate            | '2'         |
|       |                    +- WhiteSpace        | ''          |
|       |                       +- Locate         | ''          |
|       +- BinaryOperator                         | '*'         |
|       |  +- Symbol                              | '*'         |
|       |     +- Locate                           | '*'         |
|       |     +- WhiteSpace                       | ''          |
|       |        +- Locate                        | ''          |
|       +- Expression                             | '8 - 1'     |
|          +- ExpressionBinary                    | '8 - 1'     |
|             +- Expression                       | '8'         |
|             |  +- Primary                       | '8'         |
|             |     +- PrimaryLiteral             | '8'         |
|             |        +- Number                  | '8'         |
|             |           +- IntegralNumber       | '8'         |
|             |              +- DecimalNumber     | '8'         |
|             |                 +- UnsignedNumber | '8'         |
|             |                    +- Locate      | '8'         |
|             |                    +- WhiteSpace  | ''          |
|             |                       +- Locate   | ''          |
|             +- BinaryOperator                   | '-'         |
|             |  +- Symbol                        | '-'         |
|             |     +- Locate                     | '-'         |
|             |     +- WhiteSpace                 | ''          |
|             |        +- Locate                  | ''          |
|             +- Expression                       | '1'         |
|                +- Primary                       | '1'         |
|                   +- PrimaryLiteral             | '1'         |
|                      +- Number                  | '1'         |
|                         +- IntegralNumber       | '1'         |
|                            +- DecimalNumber     | '1'         |
|                               +- UnsignedNumber | '1'         |
|                                  +- Locate      | '1'         |
+-------------------------------------------------+-------------+

You can see that the top binary operator (lowest precedence) is the *, and the - operator appears in a mode internal tree node (i.e., higher precedence). This is contrary to the SystemVerilog standard (IEEE P1800โ„ข/D6), which specifies that * should be higher precedence than - (section 11.3.2).

I tested this with several pairs of operators, and it seems that the parser consistently evaluates from left to right, ignoring the precedence. If I use parenthesis, I can enforce precedence on the generated parse tree.

Parse Error

I have the following code that make sv-parser fail.

// it's for test

`ifndef ABCD
`define ABCD

package my_package;
	import uvm_pkg::*;
	import internal_pkg::*;

	// include
	`include "local.sv"
	`include "another_local.sv"

	// end of include
	
endpackage : my_package

`endif

It cause preprocess fail but I don't know how to locate location that causes parse error.

Preprocessor issue with empty ifdef

Using "parse_sv -p" to parse the following code:

module A;
`ifdef OPT_1
  //wire a = 1'b1;
`else
  wire a = 1'b0;
`endif
`ifdef DEBUG
  `ifdef OPT_2
  //wire b = 1'b1;
  `else
  wire b = 1'b0;
  `endif
`endif
endmodule

results in the following output:

module A;
wire a = 1'b0;
wire b = 1'b0;
  endmodule

The line wire b = 1'b0; should not be there as DEBUG is not defined.

Please note: To see the issue we need both lines in OPT_1 and OPT_2 to be commented out as seen in the code above. When enabling the commented out lines, everything works as expected.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.