chipsalliance / verible

Verible is a suite of SystemVerilog developer tools, including a parser, style-linter, formatter and language server
https://chipsalliance.github.io/verible/
Other
1.34k stars 204 forks source link

makedepend-style output #221

Open jdanders opened 4 years ago

jdanders commented 4 years ago

I found verible searching for something to help me in my make-based build system. I'm looking for something that can function similarly to gcc -M.

Consider this file, testcase.sv:

module test (input wire clk, input wire data, output logic result);
  `include "my_incl.svh"
  import pkg1::*;
  typedef logic [1:0] pipe_t;
  pipe_t my_pipe;
  always_ff @(posedge clk) my_pipe <= pkg2::data_to_pipe(data);
  submod1 #(.DELAY(33)) mod1 (.in(my_pipe), .out(out), .clk(clk));
  submod2 mod2 (out, result);
endmodule

If I ran verilog_syntax -printmakedepend test.sv, the result would be something like this:

test.o test.d : my_incl.svh pkg1 pkg2 submod1 submod2

The format of the output isn't terribly important, as I can munge it to what I need, but the difficult problem without a full parser is identifying the module name(s) and dependencies. I think it is sufficient (in my style of SV coding at least) to classify includes, packages, and module/interface instances as dependencies.

I might be able to figure something out from the output of verilog_syntax -printtokens and I may even take a look and see if I can contribute here, but I thought I'd get the idea out there.

Here's a helpful page describing the general make architecture I'm creating.

fangism commented 4 years ago

Hi, thanks for pitching your idea. Summarizing the problem, it sounds like you just want `include dependency information (happens to be in make form). In C/C++ compiler toolchains, this information is available through preprocessing (evaluating command-line defines -I/incdirs, ifdef conditionals, recursive includes, etc). SystemVerilog is a little crazier in letting you synthesize file names from creating macro expansions and late-evaluation string-literals. If you had such a fully-featured standard-compliant preprocessor today, that would be your best bet for attaining that information, and it would be perfect and precise.

Verible doesn't have a proper preprocessor yet (we are looking for one, see #183 ), and there is a start of what I call a pseudo-preprocessor here: https://github.com/google/verible/tree/master/verilog/preprocessor. You might be able to find a suitable fully-featured preprocessor through tools like Verilator.

That said, if you're able to tolerate imperfect information from Verible's unpreprocessed token stream, you might be able to create something "good enough". If you limit/assume includes to examine constant string literals, that will get you pretty far. If you can tolerate false-but-conservative dependencies (such as those that require evaluation of conditionals), your makedepend file will still be usable, just occasionally trigger unnecessary rebuilds. Currently verilog_syntax doesn't expand includes, so you will miss recursive include dependencies, however, you could analyze your included files in a recursive worklist in a similar fashion.

Idea:

jdanders commented 4 years ago

Maybe the reference to gcc confused things a bit because this does not need to be done like gcc does it. The example doesn't require any preprocessing, just identification that there was an included file, but not processing that included file. If I want the dependencies of "my_incl.svh" I would run verilog_syntax on my_incl.svh in a subsequent step (the recursive worklist you mention). To put it another way, I would want this a standalone command that works on just the input file without any expansion to other files. Part of the motivation for that is that this step is part of discovering the entire project, so that information isn't even available yet. The goal of the build system is to auto-discover both dependencies and the files so you don't have to maintain file lists.

This likely means the best I could hope for is "good enough" because it would not be able to apply any preprocessor define or if statements, unless maybe those were passed in as part of the command. So, yes, I am okay with the limitations you've called out.

I am afraid I don't understand your idea steps though. If you remove everything unrelated to preprocessing, then you would remove all the module instances and package calls. It looks like the idea would only get the include files.

fangism commented 4 years ago

Ah, so beyond includes you want to build up symbolic dependencies (e.g. provides/requires/defines/uses). For that, we're looking at #185 . This isn't done yet, but there is a lot of interest in this (for linter analyses, code indexing, dependency extraction, design crawling).

One way to get started is to build up (per source file) definition and reference information (akin to a symbol database). You might even ignore preprocessing and evaluate all branches, or some other pseudo preprocessing strategy. You could walk the concrete syntax tree of every parsed file to extract this information.