├── .gitignore ├── .gitmodules ├── .travis.yml ├── CMakeLists.txt ├── README.md ├── bin └── project.sh ├── src ├── CMakeLists.txt ├── main.c ├── verilog-ast-walk.c ├── verilog-ast-walk.h ├── verilog-dot-emit.c ├── verilog-dot-emit.h ├── verilog-dot.h ├── verilog-module-inherit.c └── verilog-module-inherit.h └── tests ├── simple.png ├── simple.v └── sparc_exu.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.vim 3 | 4 | build/ 5 | tests/*.dot 6 | tests/*.svg 7 | 8 | 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/verilog-parser"] 2 | path = src/verilog-parser 3 | url = https://github.com/ben-marshall/verilog-parser.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: 2 | - cpp 3 | 4 | compiler: 5 | - gcc 6 | 7 | os: 8 | - linux 9 | 10 | install: 11 | - sudo apt-get update -qq 12 | - sudo apt-get install -qq flex build-essential lcov 13 | - wget http://mirrors.kernel.org/ubuntu/pool/main/b/bison/bison_3.0.4.dfsg-1_amd64.deb 14 | - wget http://ftp.us.debian.org/debian/pool/main/b/bison/libbison-dev_3.0.4.dfsg-1_amd64.deb 15 | - sudo dpkg -i libbison-dev_3.0.4.dfsg-1_amd64.deb 16 | - sudo dpkg -i bison_3.0.4.dfsg-1_amd64.deb 17 | - sudo pip install cpp-coveralls 18 | 19 | before_script: 20 | - ./bin/project.sh 21 | 22 | script: 23 | - cd ./build/ 24 | - make verilog-dot 25 | 26 | after_failure: 27 | - echo "Failure" 28 | 29 | after_script: 30 | - echo "Script Finished." 31 | 32 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | cmake_minimum_required(VERSION 2.6) 3 | 4 | project (verilog-dot) 5 | 6 | add_subdirectory(./src) 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Verilog Dot 3 | 4 | [![Build Status](https://travis-ci.org/ben-marshall/verilog-dot.svg?branch=master)](https://travis-ci.org/ben-marshall/verilog-dot) 5 | 6 | A simple program for generating DOT file representations (graphs) expressing 7 | the syntax tree of a Verilog file. This project is a simple demonstration 8 | of my [Verilog Parser](https://github.com/ben-marshall/verilog-parser). 9 | 10 | --- 11 | 12 | ### Getting started 13 | 14 | Simply run the following commands to get started and build the library 15 | and the dot file generator. 16 | 17 | ```sh 18 | $> ./bin/project.sh 19 | $> cd ./build 20 | $> make verilog-dot 21 | ``` 22 | 23 | This creates the CMake `./build/` directory, and checks out the verilog 24 | parser library as a submodule from Github into `./src/verilog-parser`. 25 | 26 | ### Example usage 27 | 28 | After building, you can use the dot file generator thusly: 29 | 30 | ```sh 31 | $> ./src/verilog-dot --help 32 | 33 | Usage: ./verilog-dot [args] [input files] 34 | Options: 35 | --ast - Draw the abstract syntax tree. 36 | --hierarchy - Draw the module instance hierarchy. 37 | -h, --help - Print this message and quit. 38 | -v, --verbose - Print verbose information messages. 39 | [-o | --output] 40 | - Specifiy the output file path. By default, 41 | is the input path, with .dot appended. 42 | 43 | Example: 44 | ./verilog-dot -v -o module-graph.dot my_module.v 45 | 46 | $> ./src/verilog-dot -v -o my-new-graph.v ../tests/simple.v 47 | Input File: ../tests/simple.v 48 | Output File: my-new-graph.dot 49 | Parsing of input file successful. 50 | Dot file writing complete! 51 | $> 52 | $> dot -Tsvg ../tests/my-new-graph.dot > my-new-graph.svg 53 | ``` 54 | 55 | You can now view my-new-graph.svg, and it will show a rudimentary syntax tree 56 | of the example test file. I say rudimentary because walking the entire tree 57 | is not yet supported, but enough is there to get the idea. 58 | 59 | Running the above example on [./tests/simple.v](./tests/simple.v) will give 60 | the following graph as output: 61 | 62 | ![Example graph output](tests/simple.png) 63 | 64 | This graph shows the module hierarchy of the SPARCT1 microprocessors 65 | execution unit, or EXU. 66 | 67 | ![Example graph output](tests/sparc_exu.png) 68 | -------------------------------------------------------------------------------- /bin/project.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "------------------- Setting Up Verilog-Dot Workspace -----------------" 4 | 5 | git submodule update --remote src/verilog-parser/ 6 | 7 | mkdir -p ./build/ 8 | cd ./build 9 | cmake .. 10 | cd - 11 | 12 | echo "----------------------- Workspace setup complete ---------------------" 13 | 14 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | cmake_minimum_required(VERSION 2.8) 3 | 4 | project (verilog-dot-exe) 5 | 6 | add_subdirectory(./verilog-parser) 7 | 8 | set(VERILOG_DOT_SRC main.c 9 | verilog-dot-emit.c 10 | verilog-ast-walk.c 11 | verilog-module-inherit.c) 12 | 13 | set(VERILOG_DOT_EXE verilog-dot) 14 | 15 | set(VERILOG_PARSER_LIB verilogparser) 16 | 17 | SET(CMAKE_C_FLAGS_DEBUG "-g -O0 -Wall -W -fprofile-arcs -ftest-coverage") 18 | SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "-fprofile-arcs -ftest-coverage") 19 | 20 | SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") 21 | SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 22 | 23 | add_executable(${VERILOG_DOT_EXE} ${VERILOG_DOT_SRC}) 24 | target_link_libraries(${VERILOG_DOT_EXE} verilogparser) 25 | 26 | 27 | add_custom_target(dots 28 | COMMAND ${VERILOG_DOT_EXE} -v ../tests/simple.v 29 | COMMAND dot -Tsvg ../tests/simple.v.dot > ../tests/simple.svg 30 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 31 | DEPENDS ${VERILOG_DOT_EXE} 32 | COMMENT "Testing Dot Exe" 33 | VERBATIM 34 | ) 35 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /*! 2 | @file main.c 3 | @brief Contains the main entry point of the program. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "verilog-dot.h" 11 | #include "verilog-ast-walk.h" 12 | #include "verilog-dot-emit.h" 13 | #include "verilog-module-inherit.h" 14 | #include "verilog-parser/src/verilog_parser.h" 15 | #include "verilog-parser/src/verilog_ast_util.h" 16 | 17 | /*! 18 | @brief Prints the help text and exists, depending on the parameters. 19 | */ 20 | void print_help(boolean and_exit) 21 | { 22 | printf("Usage: ./verilog-dot [args] [input files]\n"); 23 | printf("Options:\n"); 24 | printf("--ast - Draw the abstract syntax tree.\n"); 25 | printf("--hierarchy - Draw the module instance hierarchy.\n"); 26 | printf("-h, --help - Print this message and quit.\n"); 27 | printf("-v, --verbose - Print verbose information messages.\n"); 28 | printf("[-o | --output] \n"); 29 | printf(" - Specifiy the output file path. By default, \n"); 30 | printf(" is the input path, with .dot appended.\n"); 31 | printf("\n"); 32 | printf("Example:\n"); 33 | printf(" ./verilog-dot -v -o module-graph.dot my_module.v\n"); 34 | printf("\n"); 35 | 36 | if(and_exit){ 37 | exit(0); 38 | } 39 | } 40 | 41 | /*! 42 | @brief Responsible for parsing all of the command line arguments. 43 | @returns A shell_args pointer 44 | */ 45 | shell_args * parse_args(int argc, char ** argv) 46 | { 47 | if(argc == 1) 48 | { 49 | print_help(BOOL_TRUE); 50 | } 51 | 52 | shell_args * tr = calloc(1,sizeof(shell_args)); 53 | 54 | int i; 55 | for(i = 1; i < argc; i++) 56 | { 57 | if(strcmp(argv[i], "-v") == 0 || 58 | strcmp(argv[i], "--verbose") == 0) 59 | { 60 | tr -> verbose = BOOL_TRUE; 61 | } 62 | else if(strcmp(argv[i], "--ast") == 0) 63 | { 64 | tr -> draw_ast = BOOL_TRUE; 65 | } 66 | else if(strcmp(argv[i], "--hierarchy") == 0) 67 | { 68 | tr -> module_hierarchy = BOOL_TRUE; 69 | } 70 | else if(strcmp(argv[i], "-h") == 0 || 71 | strcmp(argv[i], "--help") == 0) 72 | { 73 | free(tr); 74 | print_help(BOOL_TRUE); 75 | } 76 | else if(strcmp(argv[i], "-o") == 0 || 77 | strcmp(argv[i], "--output") == 0) 78 | { 79 | if(i < argc - 2) 80 | { 81 | i++; 82 | tr -> output_file_path = argv[i]; 83 | } 84 | } 85 | else 86 | { 87 | tr -> input_files_start = i; 88 | break; 89 | } 90 | } 91 | 92 | if(tr -> output_file_path == NULL) 93 | { 94 | tr -> output_file_path = "graph.dot"; 95 | } 96 | 97 | return tr; 98 | } 99 | 100 | int main(int argc, char ** argv) 101 | { 102 | shell_args * args = parse_args(argc,argv); 103 | if(args -> draw_ast == BOOL_FALSE && 104 | args -> module_hierarchy == BOOL_FALSE){ 105 | free(args); 106 | print_help(BOOL_TRUE); 107 | } 108 | 109 | if(args -> verbose) 110 | { 111 | printf("Output File: %s\n", args -> output_file_path); 112 | } 113 | 114 | // Open and validate the output file. 115 | args -> output_file = fopen(args -> output_file_path, "w"); 116 | if(args -> output_file == NULL) 117 | { 118 | printf("ERROR: Unable to open output file for writing:\n"); 119 | printf("\t%s\n",args -> output_file_path); 120 | free(args); 121 | return 1; 122 | } 123 | 124 | // Initialise the parser. 125 | verilog_parser_init(); 126 | 127 | int F; 128 | for(F = args -> input_files_start; F < argc; F++) 129 | { 130 | FILE * input_file = fopen(argv[F],"r"); 131 | if(input_file) 132 | { 133 | // Parse our input file. 134 | int result = verilog_parse_file(input_file); 135 | 136 | // If the parse didn't work, print an error message and quit. 137 | if(result != 0) 138 | { 139 | printf("ERROR: Failed to parse input file:"); 140 | printf("\t%s\n",argv[F]); 141 | } 142 | else if(args -> verbose) 143 | { 144 | printf("%s\n", argv[F]); 145 | } 146 | } 147 | else 148 | { 149 | printf("ERROR Could not open file for reading: %s\n", argv[F]); 150 | free(args); 151 | return 1; 152 | } 153 | fclose(input_file); 154 | } 155 | 156 | // This is how we access the parsed source tree. 157 | verilog_source_tree * ast = yy_verilog_source_tree; 158 | 159 | // Resolve all of the names in the syntax tree. 160 | verilog_resolve_modules(ast); 161 | 162 | // Create a dot file we will dump the AST into. 163 | dot_file * graph = dot_file_new(args -> output_file); 164 | 165 | if(args -> draw_ast == BOOL_TRUE){ 166 | // Walk the syntax tree, generating the graph 167 | walk_syntax_tree(graph, ast); 168 | } 169 | 170 | if(args -> module_hierarchy == BOOL_TRUE){ 171 | //! Draw the module inheritance hierarchy. 172 | dot_draw_module_hierarchy(ast,graph); 173 | } 174 | 175 | // Clean up the output file and close it. 176 | dot_file_finish(graph); 177 | 178 | if(args -> verbose) 179 | { 180 | printf("Dot file writing complete!\n"); 181 | } 182 | 183 | return 0; 184 | } 185 | -------------------------------------------------------------------------------- /src/verilog-ast-walk.c: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog-ast-walk.c 3 | @brief Contains definitions of functions and structures used to walk the 4 | verilog source tree. 5 | */ 6 | 7 | #include "verilog-ast-walk.h" 8 | 9 | /*! 10 | @brief Walks over a module declaration, emiting nodes as appropriate. 11 | */ 12 | void walk_port_declaration( 13 | dot_file * graph, //!< The graph to emit to. 14 | dot_node parent, //!< parent node of the module. 15 | ast_port_declaration * port //!< The port to walk. 16 | ){ 17 | int P; 18 | char *params[2]; 19 | params[0] = "Direction:"; 20 | params[1] = "Width:"; 21 | char *values[2]; 22 | 23 | switch(port -> direction) 24 | { 25 | case PORT_INPUT : values[0] = "input"; break; 26 | case PORT_OUTPUT: values[0] = "output";break; 27 | case PORT_INOUT : values[0] = "inout";break; 28 | case PORT_NONE : values[0] = "unknown"; break; 29 | default : values[0] = "unknown"; break; 30 | } 31 | 32 | if(port -> range == NULL){ 33 | values[1] = "1 Bit"; 34 | } 35 | else{ 36 | values[1] = "Range"; 37 | } 38 | 39 | for(P = 0; P < port -> port_names -> items; P++) 40 | { 41 | dot_node id = dot_new_node(graph); 42 | ast_identifier name = ast_list_get(port -> port_names, P); 43 | 44 | dot_emit_record_node(graph, id, name -> identifier, 45 | params, values, 2); 46 | dot_emit_edge(graph, parent, id); 47 | } 48 | } 49 | 50 | /*! 51 | @brief Handles net declarations. 52 | */ 53 | void walk_net_declaration( 54 | dot_file * graph, //!< The graph to emit to. 55 | dot_node parent, //!< parent node of the module. 56 | ast_type_declaration * item //!< The item to walk. 57 | ){ 58 | dot_node id = dot_new_node(graph); 59 | 60 | char * params[3]; 61 | params[0] = "Identifier"; 62 | params[1] = "Net Type"; 63 | params[2] = "Width"; 64 | 65 | char * values[3]; 66 | 67 | char * type; 68 | switch(item -> type) 69 | { 70 | case DECLARE_NET: 71 | if(item -> net_type == NET_TYPE_WIRE){ 72 | values[1] = "Wire"; 73 | } else { 74 | values[1] = "Something exotic..."; 75 | } 76 | break; 77 | 78 | case DECLARE_REG: 79 | values[1] = "Reg"; 80 | break; 81 | 82 | default: 83 | break; 84 | } 85 | 86 | if(item -> range == NULL){ 87 | values[2] = "1 Bit"; 88 | } else{ 89 | values[2] = "Bit Range"; 90 | } 91 | 92 | ast_identifier net_name = ast_list_get(item -> identifiers,0); 93 | values[0] = net_name->identifier; 94 | 95 | dot_emit_record_node(graph,id,"Declaration",params,values,3); 96 | dot_emit_edge(graph,parent,id); 97 | } 98 | 99 | /*! 100 | @brief Creates and emits nodes representing a continous assignment. 101 | */ 102 | void walk_continuous_assignment( 103 | dot_file * graph, //!< The graph to emit to. 104 | dot_node parent, //!< parent node of the module. 105 | ast_continuous_assignment * item //!< The item to walk. 106 | ){ 107 | dot_node super = dot_new_node(graph); 108 | 109 | assert(item -> assignments != NULL); 110 | 111 | char * sparams[2]; 112 | sparams[0] = "Delay"; 113 | sparams[1] = "Drive Strength"; 114 | char * svalues[2]; 115 | svalues[0] = " . "; 116 | svalues[1] = " . "; 117 | 118 | dot_emit_record_node(graph,super,"Continuous Assignments", 119 | sparams,svalues,2); 120 | dot_emit_edge(graph, parent,super); 121 | 122 | int i; 123 | for(i = 0; i < item -> assignments -> items; i ++) 124 | { 125 | dot_node said = dot_new_node(graph); 126 | 127 | char * params[2]; 128 | params[0] = "L-Value"; 129 | params[1] = "Assign To"; 130 | char * values[2]; 131 | values[0]; 132 | values[1] = " . "; 133 | 134 | ast_single_assignment * sa = ast_list_get(item -> assignments,i); 135 | values[0] = sa -> lval -> data.identifier -> identifier; 136 | 137 | dot_emit_record_node(graph,said,"Single Assignment", 138 | params,values,2); 139 | dot_emit_edge(graph,super, said); 140 | } 141 | } 142 | 143 | /*! 144 | @brief Walks over a module declaration, emiting nodes as appropriate. 145 | */ 146 | dot_node walk_module_declaration( 147 | dot_file * graph, //!< The graph to emit to. 148 | dot_node parent, //!< parent node of the module. 149 | ast_module_declaration * module //!< The module to walk. 150 | ){ 151 | dot_node newModule = dot_new_node(graph); 152 | 153 | dot_emit_node(graph,newModule, module -> identifier->identifier); 154 | dot_emit_edge(graph, parent, newModule); 155 | 156 | dot_node portsParent = dot_new_node(graph); 157 | dot_emit_node(graph, portsParent, "Ports"); 158 | dot_emit_edge(graph, newModule, portsParent); 159 | 160 | int p; 161 | for(p = 0; p < module -> module_ports -> items; p ++) 162 | { 163 | ast_port_declaration * port = ast_list_get(module->module_ports,p); 164 | walk_port_declaration(graph,portsParent,port); 165 | } 166 | return newModule; 167 | } 168 | 169 | /*! 170 | @brief Recursively walks the module declaration and instantiation hierarcy. 171 | */ 172 | void walk_module_hierarchy( 173 | dot_file * graph, //!< The graph to emit to. 174 | dot_node parent, //!< parent node of the module. 175 | ast_module_declaration * module //!< The module to walk. 176 | ) 177 | { 178 | dot_node dec = walk_module_declaration(graph, parent, module); 179 | 180 | int m; 181 | for(m = 0; m < module -> module_instantiations -> items; m ++) 182 | { 183 | ast_module_instantiation * inst = 184 | ast_list_get(module->module_instantiations,m); 185 | 186 | char * sparams[2]; 187 | sparams[0] = "Module Name:"; 188 | sparams[1] = "Instance ID:"; 189 | char * svalues[1]; 190 | svalues[0] = ast_identifier_tostring(inst -> module_identifer); 191 | svalues[1] = " "; 192 | 193 | dot_node instanced = dot_new_node(graph); 194 | dot_emit_record_node(graph,instanced,"Module Instantiation", 195 | sparams,svalues,2); 196 | dot_emit_edge(graph,dec,instanced); 197 | 198 | } 199 | } 200 | 201 | /*! 202 | @brief Recursively decends the syntax tree, emiting the dot graph as it goes. 203 | */ 204 | void walk_syntax_tree( 205 | dot_file * graph, //!< The graph to emit to. 206 | verilog_source_tree * tree //!< The source tree to walk. 207 | ){ 208 | dot_node root = dot_new_node(graph); 209 | 210 | dot_emit_node(graph,root,"Tree Root"); 211 | 212 | dot_node mod_hier = dot_new_node(graph); 213 | dot_emit_node(graph, mod_hier, "Module Hierarchy"); 214 | dot_emit_edge(graph,root,mod_hier); 215 | 216 | int m; 217 | for(m = 0; m < tree -> modules -> items; m ++) 218 | { 219 | ast_module_declaration * module = ast_list_get(tree->modules,m); 220 | walk_module_hierarchy( 221 | graph, 222 | mod_hier, 223 | module 224 | ); 225 | } 226 | } 227 | 228 | -------------------------------------------------------------------------------- /src/verilog-ast-walk.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog-ast-walk.h 3 | @brief Contains declarations of functions and structures used to walk the 4 | verilog source tree. 5 | */ 6 | 7 | #include "verilog-dot.h" 8 | #include "verilog-dot-emit.h" 9 | 10 | #include "verilog-parser/src/verilog_parser.h" 11 | 12 | #ifndef VERILOG_AST_WALK_H 13 | #define VERILOG_AST_WALK_H 14 | 15 | /*! 16 | @brief Recursively decends the syntax tree, emiting the dot graph as it goes. 17 | */ 18 | void walk_syntax_tree( 19 | dot_file * graph, //!< The graph to emit to. 20 | verilog_source_tree * tree //!< The source tree to walk. 21 | ); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/verilog-dot-emit.c: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog-dot-emit.c 3 | @brief Contains definitions of functions and structures used to emit dot file 4 | data. 5 | */ 6 | 7 | #include "verilog-dot-emit.h" 8 | 9 | /*! 10 | @details 11 | Creates and returns a new dot file object which can be written to. 12 | This function also writes the preamble to the graph. After calling dot_file_new 13 | one must also call dot_file_close, which writes the postamble, and finishes 14 | the file. 15 | */ 16 | dot_file * dot_file_new(FILE * writable) 17 | { 18 | dot_file * tr = calloc(1,sizeof(dot_file)); 19 | 20 | tr -> node_count = 0; 21 | tr -> file = writable; 22 | 23 | fprintf(tr -> file, "\ndigraph verilog_dot_graph{\n"); 24 | fprintf(tr -> file, "graph [pad=0,ranksep=3,nodesep=5];\n"); 25 | 26 | return tr; 27 | } 28 | 29 | /*! 30 | @brief Finishes off the output file, writing any extra syntax. 31 | @post The output file is closed, and is a valid .dot file, ready to be 32 | viewed. 33 | */ 34 | void dot_file_finish(dot_file * graph) 35 | { 36 | fprintf(graph -> file, "}\n"); 37 | fclose(graph -> file); 38 | } 39 | 40 | /*! 41 | @brief Emits a simple node to the graph, with a given ID and label. 42 | */ 43 | void dot_emit_node(dot_file * graph, dot_node id, char * label) 44 | { 45 | fprintf(graph -> file,"\t%d [shape=box,label=\"%s\"];\n",id,label); 46 | } 47 | 48 | 49 | /*! 50 | @brief Emits a record node to the graph, with a given ID, label and set of 51 | characteristics. 52 | */ 53 | void dot_emit_record_node( 54 | dot_file * graph, 55 | dot_node id, 56 | char * label, 57 | char ** parameters, 58 | char ** values, 59 | int num_params 60 | ){ 61 | fprintf(graph -> file,"\t%d [shape=none,label=<\n",id,num_params,label); 62 | 63 | int i; 64 | for(i = 0; i < num_params; i++){ 65 | fprintf(graph->file,""); 66 | fprintf(graph -> file, "",parameters[i]); 67 | fprintf(graph -> file, "",values[i]); 68 | fprintf(graph->file,""); 69 | } 70 | fprintf(graph->file,"
%s
%s%s
>];"); 71 | } 72 | 73 | /*! 74 | @brief Emits an edge between two pre-defined nodes. 75 | */ 76 | void dot_emit_edge(dot_file * graph, dot_node id1, dot_node id2) 77 | { 78 | fprintf(graph -> file, "\t %d -> %d\n", id1,id2); 79 | } 80 | 81 | /*! 82 | @brief Emits a directed edge between two pre-defined nodes. 83 | */ 84 | void dot_emit_directed_edge(dot_file * graph, dot_node id1, dot_node id2) 85 | { 86 | fprintf(graph -> file, "\t %d -> %d\n", id1,id2); 87 | } 88 | 89 | /*! 90 | @brief Generates a new node ID for the graph and returns it. 91 | */ 92 | dot_node dot_new_node(dot_file * graph) 93 | { 94 | graph -> node_count ++; 95 | return graph -> node_count; 96 | } 97 | -------------------------------------------------------------------------------- /src/verilog-dot-emit.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog-dot-emit.h 3 | @brief Contains declarations of functions and structures used to emit dot file 4 | data. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #ifndef VERILOG_DOT_EMIT_H 11 | #define VERILOG_DOT_EMIT_H 12 | 13 | /*! 14 | @brief A container for all information on a single dot file being emitted. 15 | */ 16 | typedef struct dot_file_t{ 17 | FILE * file; //!< Output file handle. 18 | unsigned int node_count; //!< Internal node counter. 19 | } dot_file; 20 | 21 | //! Represents the unique ID of a node. 22 | typedef unsigned int dot_node; 23 | 24 | /*! 25 | @brief Creates and returns a new dot file object which can be written to. 26 | @param [in] writable - The opened and writiable output file. 27 | @returns A pointer to a new dot_file instance, which can be passed to 28 | the various output functions to write data to the output file. 29 | */ 30 | dot_file * dot_file_new(FILE * writable); 31 | 32 | /*! 33 | @brief Finishes off the output file, writing any extra syntax. 34 | @post The output file is closed, and is a valid .dot file, ready to be 35 | viewed. 36 | */ 37 | void dot_file_finish(dot_file * graph); 38 | 39 | /*! 40 | @brief Generates a new node ID for the graph and returns it. 41 | */ 42 | dot_node dot_new_node(dot_file * graph); 43 | 44 | /*! 45 | @brief Emits a simple node to the graph, with a given ID and label. 46 | */ 47 | void dot_emit_node(dot_file * graph, dot_node id, char * label); 48 | 49 | /*! 50 | @brief Emits a record node to the graph, with a given ID, label and set of 51 | characteristics. 52 | */ 53 | void dot_emit_record_node( 54 | dot_file * graph, 55 | dot_node id, 56 | char * label, 57 | char ** parameters, 58 | char ** values, 59 | int num_params 60 | ); 61 | 62 | /*! 63 | @brief Emits an edge between two pre-defined nodes. 64 | */ 65 | void dot_emit_edge(dot_file * graph, dot_node id1, dot_node id2); 66 | 67 | /*! 68 | @brief Emits a directed edge between two pre-defined nodes. 69 | */ 70 | void dot_emit_directed_edge(dot_file * graph, dot_node id1, dot_node id2); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /src/verilog-dot.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog-dot.h 3 | @brief Contains common data structures and functions used by the program 4 | */ 5 | 6 | #include 7 | 8 | #ifndef VERILOG_DOT_H 9 | #define VERILOG_DOT_H 10 | 11 | //! A simple boolean type. 12 | typedef enum boolean_e{ 13 | BOOL_TRUE = 1, 14 | BOOL_FALSE = 0 15 | } boolean; 16 | 17 | /*! 18 | @brief Stores all of the command line arguments to the program 19 | @see parse_args 20 | */ 21 | typedef struct shell_args_t{ 22 | int input_files_start; //!< From which command line argument do input files start. 23 | char * output_file_path; //!< Where to put the output. 24 | FILE * output_file; //!< Output file handle. 25 | boolean verbose; //!< Be verbose in printing information messages. 26 | boolean draw_ast; //!< Whether to draw the AST. 27 | boolean module_hierarchy; //!< Whether to draw the module heirarchy. 28 | } shell_args; 29 | 30 | /*! 31 | @brief Responsible for parsing all of the command line arguments. 32 | @returns A shell_args pointer 33 | */ 34 | shell_args * parse_args(int argc, char ** argv); 35 | 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/verilog-module-inherit.c: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog-module-inherit.c 3 | @brief Contains definitions of functions and structures used to draw the 4 | module inheritance hierarchy of a set of files 5 | */ 6 | 7 | #include "verilog-module-inherit.h" 8 | #include "verilog-dot-emit.h" 9 | 10 | void dot_module_hierarchy_visit_module( 11 | dot_file * graph, 12 | dot_node parent, 13 | ast_module_declaration * module 14 | ) 15 | { 16 | dot_node moduleID = dot_new_node(graph); 17 | dot_emit_node(graph, moduleID, 18 | ast_identifier_tostring(module -> identifier)); 19 | dot_emit_edge(graph, moduleID, parent); 20 | 21 | int sub; 22 | for(sub = 0; sub < module -> module_instantiations -> items; sub++) 23 | { 24 | ast_module_instantiation * submod = ast_list_get( 25 | module->module_instantiations,sub); 26 | 27 | if(submod -> resolved) 28 | { 29 | dot_module_hierarchy_visit_module(graph, moduleID, 30 | submod -> declaration); 31 | } 32 | } 33 | } 34 | 35 | /*! 36 | @brief Draws the module inheritance hierarchy of a source tree. 37 | */ 38 | void dot_draw_module_hierarchy( 39 | verilog_source_tree * source, 40 | dot_file * graph 41 | ){ 42 | 43 | int m; 44 | for(m = 0; m < source -> modules -> items ; m++) 45 | { 46 | ast_module_declaration * module = ast_list_get(source -> modules, m); 47 | 48 | dot_node moduleID = dot_new_node(graph); 49 | dot_emit_node(graph, moduleID, 50 | ast_identifier_tostring(module->identifier)); 51 | 52 | int sub; 53 | for(sub = 0; sub < module -> module_instantiations -> items; sub++) 54 | { 55 | ast_module_instantiation * submod = ast_list_get( 56 | module->module_instantiations,sub); 57 | 58 | if(submod -> resolved) 59 | { 60 | dot_module_hierarchy_visit_module(graph, moduleID, 61 | submod -> declaration); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/verilog-module-inherit.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog-module-inherit.h 3 | @brief Contains declarations of functions and structures used to draw the 4 | module inheritance hierarchy of a set of files 5 | */ 6 | 7 | #include "verilog-dot.h" 8 | #include "verilog-dot-emit.h" 9 | #include "verilog-ast-walk.h" 10 | #include "verilog-parser/src/verilog_parser.h" 11 | 12 | #ifndef VERILOG_MODULE_INHERIT_H 13 | #define VERILOG_MODULE_INHERIT_H 14 | 15 | /*! 16 | @brief Draws the module inheritance hierarchy of a source tree. 17 | */ 18 | void dot_draw_module_hierarchy( 19 | verilog_source_tree * source, 20 | dot_file * graph 21 | ); 22 | 23 | #endif 24 | 25 | -------------------------------------------------------------------------------- /tests/simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben-marshall/verilog-dot/59dd2b0396007d99695ae8c192329b3f85ef6501/tests/simple.png -------------------------------------------------------------------------------- /tests/simple.v: -------------------------------------------------------------------------------- 1 | 2 | module full_adder_1bit( 3 | input a, 4 | input b, 5 | input cin, 6 | output sum, 7 | output carry 8 | ); 9 | 10 | wire a_xor_b; 11 | 12 | assign a_xor_b = a ^ b, sum=a_xor_b ^ cin; 13 | 14 | assign carry = (cin && a_xor_b) || (a && b); 15 | 16 | endmodule 17 | 18 | 19 | 20 | module adder_8bit( 21 | input [7:0] a, 22 | input [7:0] b, 23 | input cin, 24 | output [7:0] sum, 25 | output carry 26 | ); 27 | 28 | wire b0_carry; 29 | 30 | full_adder_1bit b0( 31 | .a(a[0]), 32 | .b(b[0]), 33 | .cin(cin), 34 | .sum(sum[0]), 35 | .carry(b0_carry) 36 | ); 37 | 38 | 39 | endmodule 40 | -------------------------------------------------------------------------------- /tests/sparc_exu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben-marshall/verilog-dot/59dd2b0396007d99695ae8c192329b3f85ef6501/tests/sparc_exu.png --------------------------------------------------------------------------------