Surelog is a super interesting project for parsing and elaborating SystemVerilog. Here is the blurb from their GitHub:

SystemVerilog 2017 Pre-processor, Parser, Elaborator, UHDM Compiler. Provides IEEE Design/TB C/C++ VPI and Python AST API.

What I found most interesting is that Surelog can dump UHDM, which is a standard database representation (think SNPS KDB)

Linter, Simulator, Synthesis tool, Formal tools can use this front-end. They either can be developed as plugins (linked with) or use this front-end as an intermediate step of their compilation flows using the on-disk serialized models (UHDM).

So, what is UHDM? It’s a library and APIs to create, process, and dump SystemVerilog. Apparently, it implements VPI interaction from 1800 SystemVerilog.

Auto generate a concrete C++ implementation of the SystemVerilog (VHDL in future) Object Model following the IEEE standard object model Auto generate a standard VPI interface as a facade to the C++ model Auto generate a serialization/deserialization of the data model Auto generate a Visitor (Walker) function that exercises the entire VPI interface (used in uhdm-dump executable) Auto generate a C++ Listener Design Pattern that traverses the entire VPI data model (used in uhdm-listener executable) Auto generate an Elaborator that uniquifies nets, variables… The generated Object Model can, for a given design, be: Populated by parsers like Surelog or Verible Consumed by tools like Yosys or Verilator

Compilation Link to heading

The first step is compiling Surelog and UHDM.

sudo apt-get install build-essential cmake git pkg-config tclsh swig uuid-dev libgoogle-perftools-dev python3 python3-orderedmultidict python3-psutil python3-dev default-jre lcov zlib1g-dev

git clone https://github.com/alainmarcel/Surelog.git
cd Surelog
export SURELOG=$PWD
git submodule update --init --recursive
make

git clone https://github.com/alainmarcel/UHDM.git
cd UHDM
export SURELOG=$UHDM
git submodule update --init --recursive

The binaries can be found at $SURELOG/build/bin and $UHDM/build/bin.

Surelog Link to heading

The first example uses a file list to run parse and force full UHDM elaboration.

surelog -f flist.f -parse -d uhdm -elabuhdm

This the documentation of the 2 options used to parse and elaborate the design. It’s also dumps uhdm.

-parse                Parse/Compile/Elaborate the files after

-elabuhdm             Forces UHDM/VPI Full Elaboration, default is the
                      Folded Model

This is simple enough verilog to show some serious stats from uhdm.

module top;
  wire a, b, c;
  assign a = 1'b0;
  assign b = 1'b1;

    // This is a simple AND gate instantiation
    and1 m(a, b, c);

    always @(*) begin
        $display("a = %b, b = %b, c = %b", a, b, c);
    end
endmodule

module and1(input wire a, input wire b, output wire c);
  assign c = a & b;
endmodule   

Finally, we have the output from Surelog command.

COMMAND: -f flist.f -parse -elabuhdm

[INF:CM0023] Creating log file "slpp_all/surelog.log".
[WRN:PA0205] top.sv:1:1: No timescale set for "top".
[WRN:PA0205] top.sv:14:1: No timescale set for "and1".
[INF:CP0300] Compilation...
[INF:CP0303] top.sv:14:1: Compile module "work@and1".
[INF:CP0303] top.sv:1:1: Compile module "work@top".
[INF:CP0302] Compile class "work@mailbox".
[INF:CP0302] Compile class "work@process".
[INF:CP0302] Compile class "work@semaphore".
[INF:EL0526] Design Elaboration...
[NTE:EL0503] top.sv:1:1: Top level module "work@top".
[NTE:EL0508] Nb Top level modules: 1.
[NTE:EL0509] Max instance depth: 2.
[NTE:EL0510] Nb instances: 2.
[NTE:EL0511] Nb leaf instances: 1.
[INF:UH0706] Creating UHDM Model...
[INF:UH0708] Writing UHDM DB: /slpp_all/surelog.uhdm ...
[  FATAL] : 0
[ SYNTAX] : 0
[  ERROR] : 0
[WARNING] : 2
[   NOTE] : 5

********************************************
*   End SURELOG SVerilog Compiler/Linter   *

UHDM Link to heading

Naturally, the next step is using UHDM APIs to load uhdm fille and print it’s statistics.

#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <iostream>
using namespace std;

#include <uhdm/ElaboratorListener.h>
#include <uhdm/VpiListener.h>
#include <uhdm/uhdm-version.h>
#include <uhdm/uhdm.h>
#include <uhdm/vpi_visitor.h>
#include <uhdm/Serializer.h>
using namespace UHDM;

int32_t main(int32_t argc, char **argv)
{
    if (argc < 2)
    {
        std::cerr << "Usage: " << argv[0] << " <uhdm_file>" << std::endl;
        return 1;
    }

    std::string uhdmFile = argv[1];

    std::unique_ptr<UHDM::Serializer> serializer(new UHDM::Serializer);
    std::vector<vpiHandle> designs = serializer->Restore(uhdmFile);
    serializer->PrintStats(std::cout, uhdmFile);

    return 0;
};

Compilation can be a little involved, but these are the required static libs.

g++ -I${UHDM}/build/generated/ read_uhdm.cc \
${UHDM}/build/lib/libuhdm.a \
${UHDM}/build/third_party/capnproto/c++/src/capnp/libcapnp.a \
${UHDM}/build/third_party/capnproto/c++/src/kj/libkj.a \
-o read_uhdm -ldl -lutil -lm -lrt -lpthread

./read_uhdm ./slpp_all/surelog.uhdm

Initially, I was confused why the stats have so many constructs such as class_typespec. Then I realized Surelog has some implementation for built-in classes (semaphore, etc).

=== UHDM Object Stats Begin (./slpp_all/surelog.uhdm) ===
always                                                 2
begin                                                  2
class_defn                                             8
class_typespec                                         3
class_var                                              3
constant                                               8
cont_assign                                            8
design                                                 1
enum_const                                            10
enum_typespec                                          2
enum_var                                               1
event_control                                          2
function                                              18
int_typespec                                           9
int_var                                                4
io_decl                                               17
logic_net                                             12
logic_typespec                                        13
logic_var                                              1
module_inst                                            4
operation                                              2
package                                                2
port                                                   6
ref_obj                                               27
ref_typespec                                          31
sys_func_call                                          2
task                                                   9
=== UHDM Object Stats End ===