├── .codedocs ├── .github ├── issue_template.md └── pull_request_template.md ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── CONTRIBUTING.md ├── LICENSE.txt ├── Makefile ├── README.md ├── bin ├── .gitignore ├── install-bison-flex.sh ├── leakcheck-report.sh ├── project.sh ├── run-tests.sh ├── setup-tests.sh ├── sparct1.zip └── test-coverage.sh ├── docs ├── .gitignore ├── CMakeLists.txt ├── Doxyfile ├── Makefile ├── ast-construction.dox ├── ast-nodes.dox ├── ast-utility.dox ├── ast.dox ├── footer.html ├── header.html ├── layout.xml ├── project-organisation-structure.dox ├── project-organisation.dox └── stylesheet.css ├── scratchpad.md ├── src ├── CMakeLists.txt ├── main.c ├── verilog_ast.c ├── verilog_ast.h ├── verilog_ast_common.c ├── verilog_ast_common.h ├── verilog_ast_mem.c ├── verilog_ast_mem.h ├── verilog_ast_util.c ├── verilog_ast_util.h ├── verilog_parser.h ├── verilog_parser.y ├── verilog_parser_wrapper.c ├── verilog_preprocessor.c ├── verilog_preprocessor.h └── verilog_scanner.l └── tests ├── .gitignore ├── attributes.v ├── casez.v ├── cd-missed.v ├── expression_tostring.v ├── forever-disable.v ├── functions.v ├── generate.v ├── ifdef-1.v ├── ifdef-2.v ├── inc-1.h ├── inc-2.v ├── loops.v ├── macros.v ├── mod-param-dec.v ├── module-instance.v ├── net_type_directive.v ├── operators.v ├── primitives.v ├── primitives2.v ├── reg-data-types.v ├── simple_task.v ├── std-2.6.2.v ├── std-3.10.3.1.1-array-declaration.v ├── std-3.11.1-parameters.v ├── std-3.11.1-specparam.v ├── std-4.4.3-expressions.v ├── std-6.1.2-contassign.v ├── std-6.1.2-contassign2.v ├── std-7.1.6-primitives.v ├── timescale.v └── unconnected_drive.v /.codedocs: -------------------------------------------------------------------------------- 1 | DOXYFILE = ./docs/Doxyfile 2 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | 2 | Please delete or fill out each section as appropriate: 3 | 4 | --- 5 | 6 | ## Issue Description 7 | 8 | What problem / feature / issue are you raising? Describe in as much detail 9 | as possible. 10 | 11 | ### What should happen: 12 | 13 | What should normal behaviour for the given input be? 14 | 15 | ### What actually happens: 16 | 17 | What actually occurs? 18 | 19 | ## Steps to re-create: 20 | 21 | Describe exactly how to re-create the bug. 22 | 23 | ```sh 24 | $> make clean 25 | $> make all 26 | $> [what now ...] 27 | ``` 28 | 29 | --- 30 | 31 | #### People to Notify: 32 | 33 | - @ben-marshall 34 | 35 | #### Related Issues: 36 | 37 | 38 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 2 | ## Purpose 3 | 4 | What does this pull request do? 5 | 6 | ### List of changes 7 | 8 | - What have you changed? 9 | - What does this fix? 10 | - What does this break? 11 | 12 | ## Fixes: 13 | 14 | - Which issues does this affect or fix? 15 | 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.vim 3 | build/ 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+b1_amd64.deb 15 | - sudo dpkg -i libbison-dev_3.0.4.dfsg-1+b1_amd64.deb 16 | - sudo dpkg --ignore-depends=libbison-dev -i bison_3.0.4.dfsg-1_amd64.deb 17 | - sudo pip install cpp-coveralls 18 | 19 | before_script: 20 | - make setup 21 | 22 | script: 23 | - make debug 24 | - make release 25 | - make coverage 26 | - make test-debug 27 | - make test-release 28 | - make test-coverage 29 | 30 | after_success: 31 | - echo "Success" 32 | - coveralls -b ./build/coverage/src/CMakeFiles/verilogparser.dir/ 33 | 34 | after_failure: 35 | - echo "Failure" 36 | 37 | after_script: 38 | - echo "Script Finished." 39 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(verilog-parser) 4 | 5 | enable_testing() 6 | 7 | add_subdirectory(./src) 8 | add_subdirectory(./docs) 9 | 10 | add_custom_target(verilogparser-test 11 | COMMAND ./bin/run-tests.sh 12 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 13 | DEPENDS ${EXECUTABLE_NAME} 14 | COMMENT "Running Test Suite" 15 | VERBATIM 16 | ) 17 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributing 3 | 4 | This document contains some useful tips on how to help contribute to this 5 | repository. 6 | 7 | --- 8 | 9 | ## Useful Stuff 10 | 11 | - [Documentation](https://codedocs.xyz/ben-marshall/verilog-parser/) is hosted 12 | on codedocs.xyz. This is generated automatically with every commit to master 13 | from the internal documentation in `doc/` and throughout the code in `src/` 14 | - [Flex](http://flex.sourceforge.net/manual/) Lexical Analyser Manual. 15 | - [Bison](http://dinosaur.compilertools.net/bison/index.html) Parser 16 | generator manual. 17 | 18 | ## Submitting Bugs 19 | 20 | You can use the issue template to submit bugs. This includes: 21 | 22 | - A description of where in the program the bug occurs (if known) 23 | - Sample input which triggers the bug. This can also be submitted in a 24 | pull request. 25 | - A clear description of what *should* happen and what *actually* happens. 26 | - In the case of a segmentation fault, a debug trace from valgrind is also 27 | very useful, along with the build log. 28 | 29 | ## Fixing Bugs 30 | 31 | If you find a bug and want to fix it yourself, thats super! You can use 32 | the pull request template: 33 | 34 | - Always describe clearly the bug you are fixing, it is worth raising an 35 | issue even if you are fixing it straight away. This means there will be a 36 | record of the bug. 37 | - Always add a test in `tests/` which triggers the bug prior to your fix, 38 | and which passes after your fix. 39 | 40 | ## New Features 41 | 42 | Raise these as an issue and tag them as a feature request. They can then be 43 | discussed in depth in terms of feasability and appropriateness. 44 | 45 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ben Marshall 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # This is a simple top-level wrapper makefile for the rest of the project. 4 | # 5 | 6 | all: setup docs debug release coverage 7 | 8 | .PHONY: docs setup clean 9 | 10 | setup: 11 | ./bin/project.sh 12 | 13 | docs: 14 | $(MAKE) -C ./build/debug -B verilogparser-docs 15 | 16 | debug: 17 | $(MAKE) -C ./build/debug parser 18 | 19 | release: 20 | $(MAKE) -C ./build/release parser 21 | 22 | coverage: 23 | $(MAKE) -C ./build/coverage parser 24 | 25 | clean: 26 | $(MAKE) -C ./build/coverage clean 27 | $(MAKE) -C ./build/debug clean 28 | $(MAKE) -C ./build/release clean 29 | rm -rf ./build/docs 30 | 31 | 32 | test-all: test-debug test-release test-coverage 33 | 34 | test-debug: debug 35 | $(MAKE) -C ./build/debug test 36 | 37 | test-release: release 38 | $(MAKE) -C ./build/release test 39 | 40 | test-coverage: coverage 41 | $(MAKE) -C ./build/coverage test 42 | 43 | test-coverage-report: test-coverage 44 | cd ./build/coverage/src/CMakeFiles/verilogparser.dir/ ; \ 45 | gcov -abcf *.o ; \ 46 | lcov --directory . -c -o cov.info -t "verilogparser" ; \ 47 | genhtml -o ../../../../cov-report -t "verilogparser" --num-spaces 4 cov.info 48 | @echo "Coverage report available in:" 49 | @echo "./build/cov-report/index.html" 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Verilog Parser 3 | 4 | [![Documentation](https://codedocs.xyz/ben-marshall/verilog-parser.svg)](https://codedocs.xyz/ben-marshall/verilog-parser/) 5 | [![Build Status](https://travis-ci.org/ben-marshall/verilog-parser.svg?branch=master)](https://travis-ci.org/ben-marshall/verilog-parser/branches) 6 | [![Coverage Status](https://coveralls.io/repos/github/ben-marshall/verilog-parser/badge.svg?branch=master)](https://coveralls.io/github/ben-marshall/verilog-parser?branch=master) 7 | ![Licence: MIT](https://img.shields.io/badge/License-MIT-blue.svg) 8 | 9 | This repository contains a flex / bison parser for the IEEE 1364-2001 Verilog 10 | Standard. 11 | 12 | - [Getting Started](#getting-started) 13 | - [Testing](#testing) 14 | - [Contributing](#contributing) 15 | - [Design Choices](#design-choices) 16 | - [Todo List](#todo) 17 | - [Tool Wishlist](#wishlist) 18 | 19 | --- 20 | 21 | ## Getting Started 22 | 23 | This will get you going workspace wise. 24 | 25 | ```sh 26 | $> make all 27 | $> make test-all 28 | ``` 29 | 30 | This will download the test suite files, setup the build directory, and 31 | compile the parser, library and test app. 32 | 33 | To start using the parser in your own code, take a look at 34 | [main.c](./src/main.c) which is a simple demonstration app used for testing 35 | and coverage. The basic code which you need is something like this: 36 | 37 | ```C 38 | // Initialise the parser. 39 | verilog_parser_init(); 40 | 41 | // Open A File handle to read data in. 42 | FILE * fh = fopen("my_verilog_file.v", "r"); 43 | 44 | // Parse the file and store the result. 45 | int result = verilog_parse_file(fh); 46 | 47 | if(result == 0) 48 | printf("Parse successful\n"); 49 | else 50 | printf("Parse failed\n"); 51 | 52 | fclose(fh); 53 | ``` 54 | 55 | You can keep calling `verilog_parse_file(fh)` on as many different file 56 | handles as you like to build up a multi-file project AST representation. 57 | The parser will automatically follow any `include` directives it finds. 58 | 59 | For an example of using the library in a real*ish* situation, the 60 | [verilog-dot](https://github.com/ben-marshall/verilog-dot) project shows how 61 | the library can be integrated into an existing project and used. 62 | 63 | ## Testing 64 | 65 | The test suite is comprised of example code taken from 66 | the fantastic [ASIC World](http://www.asic-world.com/) tutorial on Verilog. 67 | The idea being that by using a well-known and comprehensive set of 68 | tutorial examples, almost all of the syntactic features of the language can be 69 | hit very easily with little effort. 70 | 71 | The repository also contains an archive of verilog source code taken from the 72 | [OpenSPARCT1](http://www.oracle.com/technetwork/systems/opensparc/opensparc-t1-page-1444609.html) 73 | microprocessor from Oracle. This archive is unpacked into the `tests/` 74 | directory when `make setup` is run, and ensures that the parser is able to 75 | handle a *real-life* source base in terms of scale and complexity. The full 76 | workspace environment required to run or analyse the OpenSPARCT1 is not 77 | provided, the files only demonstrate the ability to correctly parse a large 78 | project, and handle the various internal header files and preprocessor 79 | definitions. 80 | 81 | ## Contributing 82 | 83 | Of-course, the current test suite does not test **everything** and I expect 84 | there to be awkward bugs. This is the first time I have written a parser of 85 | this size and complexity. I have set up automatic coverage collection after 86 | each CI build, this gives a good indication of which parts of the code are 87 | tested and dependable. Hitting 100% coverage for a parser is a *pain*, but 88 | hopefully over time it will tend that way. The current situation is that 89 | all of the verilog language features that are used commonly are tested for. 90 | The main missing bits are due to a lack of test cases for user defined 91 | primitives (UDPs). 92 | 93 | If you find a bug, or otherwise want to contribute, then please don't 94 | hesitate to file a pull request. If you have found a bug, please add a test 95 | for the bug in the `tests/` folder. This should trigger the bug in the original 96 | code, and ideally, not trigger in you're submitted fix! I'm open to people 97 | just submitting bugs as well, but it might take longer for me to get round to 98 | fixing it! 99 | 100 | There is more information on how to help in the [contributing](CONTRIBUTING.md) 101 | guide. 102 | 103 | ## Design Choices 104 | 105 | ### Why C, why not something more modern? 106 | 107 | This comes down to who will use this tool, and who will develop this tool. 108 | Ideally, these are the same people. The current demographic of people working 109 | in ASIC / RTL design is that of (please excuse my generalising) electronic 110 | engineers, with (again, sorry) little experience of recent programming language 111 | technologies like Haskell (great for parsing and formal/state-based assertions) 112 | and Python (perl is still king in ASIC design flows, but this is changing). 113 | Further, the size and complexity of many RTL designs means you need a language 114 | that has lots of low-level acceleration potential, as well as being 115 | tried-and-tested. C meets most of these points, while also being something that 116 | electronics engineers are more likely to be familiar with and comfortable using. 117 | 118 | ### Why flex/bison, why not Boost::Sprint, ANTLR, or something custom? 119 | 120 | Similar to the above answer. These are tools that are *very* old, and *very* 121 | stable. They are more likely to be available and supported for the kinds 122 | of development environments RTL designers work in which are often at least 123 | a decade old. What flex and bison loose in terms of nice features, syntactic 124 | sugar, and, sadly, ease of use - they make up for in stability and 125 | likelihood of familiarity for the people I hope will use this project. 126 | Many of the design decisions around this project have been equal parts 127 | social and engineering in their justification. 128 | 129 | ### Why not adapt an existing parser? 130 | 131 | Good question. I looked at the parsers found in [Icarus 132 | Verilog](http://iverilog.icarus.com/) and 133 | [yosys](http://www.clifford.at/yosys/) but found that while they were 134 | excellent in and of themselves, they were too well adapted to their end use to 135 | be made into a general purpose parser. They did inform me well on how to parse 136 | the trickier parts of the grammar though, and I certainly cannot fault them in 137 | any other way! This parser has been written to correspond very closely to the 138 | IEEE Verilog 2001 Syntax specification. This means it is longer (by line 139 | count) but much easier to understand and relate to the original specification. 140 | For example, each grammar rule in the [Bison file](./verilog_parser.y) matches 141 | almost exactly with it's namesake in the IEEE spec. 142 | 143 | --- 144 | 145 | 146 | ## Todo 147 | 148 | There are some things that the parser does not support: 149 | 150 | - System-Verilog. Sorry folks, its another language completely. This parser 151 | should serve as a very good starting point if you want to build one though, 152 | since Verilog is a subset of System-Verilog. 153 | - System timing checks. See Annex 7.5.1 of the specification for what this 154 | omits. It hopefully won't be long before I get round to adding it though. 155 | 156 | ## Wishlist 157 | 158 | This is a wishlist of tools that I would like to use the parser in. If 159 | anyone else would like to use the parser as the basis for their own tools 160 | like this, I am more than happy to help! 161 | 162 | - A code indenter / style format checker. 163 | - A pre-processed source checker (expand macros and parameters, etc) for easy 164 | browsing of generic logic blocks and cores. 165 | - Something to highlight when signals cross clock domains. 166 | - Critical path identifier (something which doesn't take 20 minuets to run on 167 | a grid engine) 168 | - A switching probability analysis tool. 169 | - This could even feed into a rough power & energy estimation tool. 170 | - A simple hierarchy visualiser, which you can feed all your project files into 171 | and which will spit out a digested view of the module hierarchy. 172 | - Proper Doxygen support for Verilog, or failing that, a 173 | [Doxygen like tool](https://github.com/ben-marshall/verilog-doc) for Verilog 174 | -------------------------------------------------------------------------------- /bin/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben-marshall/verilog-parser/753ffee1248b72269d5181aefc5ad4bd54c85662/bin/.gitignore -------------------------------------------------------------------------------- /bin/install-bison-flex.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Installing flex and bison" 4 | echo " " 5 | 6 | echo "Installing Flex..." 7 | apt-get install -qq flex 8 | 9 | echo "Installing Bison..." 10 | apt-get install -qq bison 11 | 12 | echo "Done" 13 | -------------------------------------------------------------------------------- /bin/leakcheck-report.sh: -------------------------------------------------------------------------------- 1 | 2 | LOGFILE=./build/valgrind-log.txt 3 | BINARY=./build/debug/src/parser 4 | TESTS=`find ./tests/ -name *sparc*.v` 5 | 6 | echo ">> Building Library..." 7 | 8 | cd ./build/debug 9 | make 10 | cd - 11 | 12 | echo ">> Running Valgrind..." 13 | 14 | CMD="valgrind --track-origins=yes --leak-check=full --leak-resolution=high \ 15 | --show-leak-kinds=all --log-file=$LOGFILE $BINARY $TESTS" 16 | $CMD &> ./build/log.txt 17 | 18 | 19 | echo ">> Invalid Reads: `egrep "Invalid read of size" -c $LOGFILE`" 20 | echo ">> Leaked Blocks: `egrep "blocks are still reachable" -c $LOGFILE`" 21 | echo ">> Indirectly Lost Blocks: `egrep "blocks are indirectly lost" -c $LOGFILE`" 22 | echo ">> Definitely Lost Blocks: `egrep "blocks are definitely lost" -c $LOGFILE`" 23 | 24 | tail -n 10 $LOGFILE 25 | 26 | echo ">> END" 27 | -------------------------------------------------------------------------------- /bin/project.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "----------------- Setup Project Workspace ---------------------------" 4 | 5 | # Remove any remnant of the old work environment 6 | rm -rf ./build 7 | 8 | # Create build directory structure. 9 | mkdir -p build/release 10 | mkdir -p build/debug 11 | mkdir -p build/coverage 12 | mkdir -p build/docs 13 | 14 | # Download tests - must happen before CMake is run. 15 | cd tests 16 | source ../bin/setup-tests.sh 17 | cd ../ 18 | 19 | echo "----------------- Setup Debug Build Environment ---------------------" 20 | 21 | cd ./build/debug 22 | cmake -DCMAKE_BUILD_TYPE=Debug ../../ 23 | cd - 24 | 25 | echo "----------------- Setup Release Build Environment -------------------" 26 | 27 | cd ./build/release 28 | cmake -DCMAKE_BUILD_TYPE=Release ../../ 29 | cd - 30 | 31 | echo "----------------- Setup Coverage Build Environment ------------------" 32 | 33 | cd ./build/coverage 34 | cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_COVERAGE=YES ../../ 35 | cd - 36 | 37 | 38 | echo " " 39 | echo "----------------- Setup Coverage Build Environment ------------------" 40 | -------------------------------------------------------------------------------- /bin/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | black='\E[30m' 4 | red='\E[31m' 5 | green='\E[32m' 6 | yellow='\E[33m' 7 | blue='\E[34m' 8 | magenta='\E[35m' 9 | cyan='\E[36m' 10 | white='\E[37m' 11 | clrc='\E[0m' 12 | 13 | echo "------------------------- Running Test Script -------------------------" 14 | 15 | rm -rf build/tests.log 16 | 17 | EXE=./build/debug/src/parser 18 | TEST_FILES=`find tests/ -name *.v | sort` 19 | 20 | FAILED_TESTS=" " 21 | PASSED_TESTS=" " 22 | 23 | for FILE in $TEST_FILES 24 | do 25 | # run the program and store the result. 26 | $EXE $FILE 2>> build/tests.log 1>> build/tests.log 27 | RESULT=$? 28 | 29 | if [ "0" -eq "$RESULT" ]; then 30 | PASSED_TESTS="$PASSED_TESTS $FILE" 31 | echo -n -e "$green $FILE $clrc" 32 | else 33 | FAILED_TESTS="$FAILED_TESTS $FILE" 34 | echo -n -e "$red $FILE $clrc" 35 | fi 36 | 37 | 38 | done 39 | 40 | echo " " 41 | echo " " 42 | echo "--------------------------- Testing Complete --------------------------" 43 | 44 | echo " " 45 | echo " " 46 | echo -e "$green Passing Tests: $clrc" 47 | printf "%30s %30s %30s %30s\n" $PASSED_TESTS 48 | 49 | echo " " 50 | echo -e "$red Failing Tests: $clrc" 51 | printf "%30s %30s %30s %30s\n" $FAILED_TESTS 52 | 53 | echo " " 54 | echo "------------------------- Finished Test Script ------------------------" 55 | echo " " 56 | echo "Passing: `echo $PASSED_TESTS | wc -w` \t Failing: "`echo $FAILED_TESTS | wc -w` 57 | echo " " 58 | 59 | exit `echo "$FAILED_TESTS" | wc -w` 60 | -------------------------------------------------------------------------------- /bin/setup-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MODEL_PREFIX=http://www.asic-world.com/code/hdl_models 4 | TUTORIAL_PREFIX=http://www.asic-world.com/code/verilog_tutorial 5 | 6 | WGET_OPTS=" -c -q " 7 | 8 | function downloadTutorialTest { 9 | if [ ! -e $1 ] 10 | then 11 | echo -n "Fetching $TUTORIAL_PREFIX/$1 " 12 | wget $WGET_OPTS $TUTORIAL_PREFIX/$1 13 | echo "[DONE]" 14 | fi 15 | } 16 | 17 | function downloadModelTest { 18 | if [ ! -e $1 ] 19 | then 20 | echo -n "Fetching $MODEL_PREFIX/$1 " 21 | wget $WGET_OPTS $MODEL_PREFIX/$1 22 | echo "[DONE]" 23 | fi 24 | } 25 | 26 | echo "Unzipping SPARC test set..." 27 | unzip -o ../bin/sparct1.zip -d ./ 28 | 29 | echo "Downloading Tests..." 30 | 31 | downloadModelTest arbiter_tb.v 32 | downloadModelTest clk_div_45.v 33 | downloadModelTest concatenation.v 34 | downloadModelTest d_latch_gates.v 35 | downloadModelTest d_latch_switch.v 36 | downloadModelTest decoder_2to4_gates.v 37 | downloadModelTest decoder_using_assign.v 38 | downloadModelTest decoder_using_case.v 39 | downloadModelTest delay_example.v 40 | downloadModelTest dff_udp.v 41 | downloadModelTest dlatch_reset.v 42 | downloadModelTest encoder_4to2_gates.v 43 | downloadModelTest encoder_using_case.v 44 | downloadModelTest full_adder_gates.v 45 | downloadModelTest jkff_udp.v 46 | downloadModelTest latch_udp.v 47 | downloadModelTest lfsr.v 48 | downloadModelTest lfsr_updown.v 49 | downloadModelTest lfsr_updown_tb.v 50 | downloadModelTest misc1.v 51 | downloadModelTest mux21_switch.v 52 | downloadModelTest mux_21_udp.v 53 | downloadModelTest mux_using_assign.v 54 | downloadModelTest mux_using_case.v 55 | downloadModelTest mux_using_if.v 56 | downloadModelTest n_in_primitive.v 57 | downloadModelTest nand_switch.v 58 | downloadModelTest not_switch.v 59 | downloadModelTest parity_using_assign.v 60 | downloadModelTest port_declaration.v 61 | downloadModelTest pri_encoder_using_assign.v 62 | downloadModelTest pri_encoder_using_if.v 63 | downloadModelTest primitives.v 64 | downloadModelTest ram_dp_ar_aw.v 65 | downloadModelTest ram_dp_sr_sw.v 66 | downloadModelTest ram_sp_ar_aw.v 67 | downloadModelTest rom.v 68 | downloadModelTest serial_crc.v 69 | downloadModelTest srff_udp.v 70 | downloadModelTest syn_fifo.v 71 | downloadModelTest t_gate_switch.v 72 | downloadModelTest uart.v 73 | downloadModelTest xor2_input.v 74 | downloadModelTest xor_switch.v 75 | downloadTutorialTest addbit.v 76 | downloadTutorialTest adder_hier.v 77 | downloadTutorialTest and_from_nand.v 78 | downloadTutorialTest ansiport_example.v 79 | downloadTutorialTest arbiter.v 80 | downloadTutorialTest avoid_latch_else.v 81 | downloadTutorialTest bitwise_operators.v 82 | downloadTutorialTest buf_gate.v 83 | downloadTutorialTest buf_gate1.v 84 | downloadTutorialTest bus_wr_rd_task.v 85 | downloadTutorialTest casex_example.v 86 | downloadTutorialTest comma_example.v 87 | downloadTutorialTest concatenation_operator.v 88 | downloadTutorialTest conditional_operator.v 89 | downloadTutorialTest counterMonitor.v 90 | downloadTutorialTest counterTestGen.v 91 | downloadTutorialTest decoder.v 92 | downloadTutorialTest decoder_always.v 93 | downloadTutorialTest defparam_example.v 94 | downloadTutorialTest delay.v 95 | downloadTutorialTest delay_example.v 96 | downloadTutorialTest dff_async_reset_async_preset.v 97 | downloadTutorialTest dff_from_nand.v 98 | downloadTutorialTest dff_sync_reset_sync_preset.v 99 | downloadTutorialTest fifo_tb.v 100 | downloadTutorialTest first_counter.v 101 | downloadTutorialTest first_counter_tb.v 102 | downloadTutorialTest flip_flop.v 103 | downloadTutorialTest fsm_full_tb.v 104 | downloadTutorialTest gates.v 105 | downloadTutorialTest hello_pli.v 106 | downloadTutorialTest hello_world.v 107 | downloadTutorialTest implicit.v 108 | downloadTutorialTest initial_fork_join.v 109 | downloadTutorialTest logical_operators.v 110 | downloadTutorialTest multi_array.v 111 | downloadTutorialTest mux.v 112 | downloadTutorialTest mux_from_gates.v 113 | downloadTutorialTest mux_from_gates.v 114 | downloadTutorialTest n_in_primitive 115 | downloadTutorialTest n_out_primitive.v 116 | downloadTutorialTest named_block_disable.v 117 | downloadTutorialTest parallel.v 118 | downloadTutorialTest param_more_then_one.v 119 | downloadTutorialTest param_more_then_one1.v 120 | downloadTutorialTest param_overide_instance_example.v 121 | downloadTutorialTest quest_for_in.v 122 | downloadTutorialTest quest_for_out.v 123 | downloadTutorialTest switch_primitives.v 124 | downloadTutorialTest syn_fifo_psl.v 125 | downloadTutorialTest task_calling.v 126 | downloadTutorialTest task_global.v 127 | downloadTutorialTest test_tri.v 128 | downloadTutorialTest test_trireg.v 129 | downloadTutorialTest test_wor.v 130 | downloadTutorialTest transmission_gates.v 131 | downloadTutorialTest udp_body_tb.v 132 | downloadTutorialTest which_clock.v 133 | -------------------------------------------------------------------------------- /bin/sparct1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben-marshall/verilog-parser/753ffee1248b72269d5181aefc5ad4bd54c85662/bin/sparct1.zip -------------------------------------------------------------------------------- /bin/test-coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | echo "----------------------- Running Coverage Tests ------------------------" 5 | 6 | make clean 7 | make app-with-coverage 8 | 9 | IWD=`pwd` 10 | 11 | EXE=build/bin/verilog-app 12 | TEST_FILES=tests/*.v 13 | 14 | 15 | echo "$EXE $TEST_FILES" 16 | $EXE $TEST_FILES 17 | 18 | echo "---------------------- Coverage Results Summary -----------------------" 19 | 20 | cd build/ 21 | 22 | rm -rf coverage/* 23 | mkdir -p coverage/ 24 | 25 | gcov -f -b -c -o ./obj -s ./gen/*.c ./gen/*.tab.c ../src/*.c 26 | 27 | mv ./obj/*.gcno ./coverage/. 28 | mv ./obj/*.gcda ./coverage/. 29 | mv ./*.gcov ./coverage/. 30 | touch "" 31 | 32 | cd coverage 33 | 34 | lcov --directory . -c -o coverage.info -t "Verilog Parser" 35 | genhtml -o ../cov-report -t "Verilog Parser Test Coverage" --num-spaces 4 coverage.info 36 | 37 | 38 | cd $IWD # return to initial working directory. 39 | rm -f "build/" 40 | 41 | echo " " 42 | echo "Coverage Report Written To:" 43 | echo " ./build/cov-report/index.html" 44 | echo " " 45 | 46 | echo "-----------------------Coverage Tests Complete ------------------------" 47 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | html/ 2 | -------------------------------------------------------------------------------- /docs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(verilog-parser-docs) 4 | 5 | find_package(Doxygen) 6 | if(DOXYGEN_FOUND) 7 | add_custom_target(verilogparser-docs 8 | ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile 9 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 10 | COMMENT "Generating API documentation with Doxygen" VERBATIM 11 | ) 12 | endif(DOXYGEN_FOUND) 13 | -------------------------------------------------------------------------------- /docs/Doxyfile: -------------------------------------------------------------------------------- 1 | # Doxyfile 1.8.6 2 | 3 | #--------------------------------------------------------------------------- 4 | # Project related configuration options 5 | #--------------------------------------------------------------------------- 6 | DOXYFILE_ENCODING = UTF-8 7 | PROJECT_NAME = "Verilog Parser" 8 | PROJECT_NUMBER = 9 | PROJECT_BRIEF = 10 | PROJECT_LOGO = 11 | OUTPUT_DIRECTORY = ../build/docs 12 | CREATE_SUBDIRS = NO 13 | OUTPUT_LANGUAGE = English 14 | BRIEF_MEMBER_DESC = YES 15 | REPEAT_BRIEF = YES 16 | ABBREVIATE_BRIEF = 17 | ALWAYS_DETAILED_SEC = NO 18 | INLINE_INHERITED_MEMB = NO 19 | FULL_PATH_NAMES = NO 20 | STRIP_FROM_PATH = 21 | STRIP_FROM_INC_PATH = 22 | SHORT_NAMES = NO 23 | JAVADOC_AUTOBRIEF = NO 24 | QT_AUTOBRIEF = NO 25 | MULTILINE_CPP_IS_BRIEF = NO 26 | INHERIT_DOCS = YES 27 | SEPARATE_MEMBER_PAGES = NO 28 | TAB_SIZE = 4 29 | ALIASES = 30 | TCL_SUBST = 31 | OPTIMIZE_OUTPUT_FOR_C = YES 32 | OPTIMIZE_OUTPUT_JAVA = NO 33 | OPTIMIZE_FOR_FORTRAN = NO 34 | OPTIMIZE_OUTPUT_VHDL = NO 35 | EXTENSION_MAPPING = 36 | MARKDOWN_SUPPORT = YES 37 | AUTOLINK_SUPPORT = YES 38 | BUILTIN_STL_SUPPORT = NO 39 | CPP_CLI_SUPPORT = NO 40 | SIP_SUPPORT = NO 41 | IDL_PROPERTY_SUPPORT = YES 42 | DISTRIBUTE_GROUP_DOC = YES 43 | SUBGROUPING = YES 44 | INLINE_GROUPED_CLASSES = NO 45 | INLINE_SIMPLE_STRUCTS = YES 46 | TYPEDEF_HIDES_STRUCT = YES 47 | LOOKUP_CACHE_SIZE = 0 48 | #--------------------------------------------------------------------------- 49 | # Build related configuration options 50 | #--------------------------------------------------------------------------- 51 | EXTRACT_ALL = YES 52 | EXTRACT_PRIVATE = NO 53 | EXTRACT_PACKAGE = NO 54 | EXTRACT_STATIC = NO 55 | EXTRACT_LOCAL_CLASSES = YES 56 | EXTRACT_LOCAL_METHODS = NO 57 | EXTRACT_ANON_NSPACES = NO 58 | HIDE_UNDOC_MEMBERS = NO 59 | HIDE_UNDOC_CLASSES = NO 60 | HIDE_FRIEND_COMPOUNDS = NO 61 | HIDE_IN_BODY_DOCS = NO 62 | INTERNAL_DOCS = YES 63 | CASE_SENSE_NAMES = YES 64 | HIDE_SCOPE_NAMES = NO 65 | SHOW_INCLUDE_FILES = YES 66 | SHOW_GROUPED_MEMB_INC = NO 67 | FORCE_LOCAL_INCLUDES = NO 68 | INLINE_INFO = YES 69 | SORT_MEMBER_DOCS = YES 70 | SORT_BRIEF_DOCS = YES 71 | SORT_MEMBERS_CTORS_1ST = NO 72 | SORT_GROUP_NAMES = YES 73 | SORT_BY_SCOPE_NAME = YES 74 | STRICT_PROTO_MATCHING = NO 75 | GENERATE_TODOLIST = YES 76 | GENERATE_TESTLIST = YES 77 | GENERATE_BUGLIST = YES 78 | GENERATE_DEPRECATEDLIST= YES 79 | ENABLED_SECTIONS = 80 | MAX_INITIALIZER_LINES = 30 81 | SHOW_USED_FILES = YES 82 | SHOW_FILES = YES 83 | SHOW_NAMESPACES = YES 84 | FILE_VERSION_FILTER = 85 | LAYOUT_FILE = layout.xml 86 | CITE_BIB_FILES = 87 | #--------------------------------------------------------------------------- 88 | # Configuration options related to warning and progress messages 89 | #--------------------------------------------------------------------------- 90 | QUIET = NO 91 | WARNINGS = 92 | WARN_IF_UNDOCUMENTED = 93 | WARN_IF_DOC_ERROR = 94 | WARN_NO_PARAMDOC = YES 95 | WARN_FORMAT = "$file:$line: $text" 96 | WARN_LOGFILE = 97 | #--------------------------------------------------------------------------- 98 | # Configuration options related to the input files 99 | #--------------------------------------------------------------------------- 100 | INPUT = ../src/ ../README.md ../docs 101 | INPUT_ENCODING = UTF-8 102 | FILE_PATTERNS = *.c *.cpp *.h *.hpp *.y *.dox 103 | RECURSIVE = YES 104 | EXCLUDE = 105 | EXCLUDE_SYMLINKS = NO 106 | EXCLUDE_PATTERNS = 107 | EXCLUDE_SYMBOLS = 108 | EXAMPLE_PATH = 109 | EXAMPLE_PATTERNS = 110 | EXAMPLE_RECURSIVE = NO 111 | IMAGE_PATH = 112 | INPUT_FILTER = 113 | FILTER_PATTERNS = 114 | FILTER_SOURCE_FILES = NO 115 | FILTER_SOURCE_PATTERNS = 116 | USE_MDFILE_AS_MAINPAGE = ../README.md 117 | #--------------------------------------------------------------------------- 118 | # Configuration options related to source browsing 119 | #--------------------------------------------------------------------------- 120 | SOURCE_BROWSER = YES 121 | INLINE_SOURCES = NO 122 | STRIP_CODE_COMMENTS = NO 123 | REFERENCED_BY_RELATION = YES 124 | REFERENCES_RELATION = YES 125 | REFERENCES_LINK_SOURCE = YES 126 | SOURCE_TOOLTIPS = YES 127 | USE_HTAGS = NO 128 | VERBATIM_HEADERS = YES 129 | #--------------------------------------------------------------------------- 130 | # Configuration options related to the alphabetical class index 131 | #--------------------------------------------------------------------------- 132 | ALPHABETICAL_INDEX = YES 133 | COLS_IN_ALPHA_INDEX = 5 134 | IGNORE_PREFIX = 135 | #--------------------------------------------------------------------------- 136 | # Configuration options related to the HTML output 137 | #--------------------------------------------------------------------------- 138 | GENERATE_HTML = YES 139 | HTML_OUTPUT = html 140 | HTML_FILE_EXTENSION = .html 141 | HTML_HEADER = header.html 142 | HTML_FOOTER = footer.html 143 | HTML_STYLESHEET = stylesheet.css 144 | HTML_EXTRA_STYLESHEET = 145 | HTML_EXTRA_FILES = 146 | HTML_COLORSTYLE_HUE = 240 147 | HTML_COLORSTYLE_SAT = 20 148 | HTML_COLORSTYLE_GAMMA = 40 149 | HTML_TIMESTAMP = YES 150 | HTML_DYNAMIC_SECTIONS = YES 151 | HTML_INDEX_NUM_ENTRIES = 100 152 | GENERATE_DOCSET = NO 153 | DOCSET_FEEDNAME = "Doxygen generated docs" 154 | DOCSET_BUNDLE_ID = uk.org.bmarshall.verilog-parser 155 | DOCSET_PUBLISHER_ID = uk.org.bmarshall 156 | DOCSET_PUBLISHER_NAME = Ben Marshall 157 | GENERATE_HTMLHELP = NO 158 | CHM_FILE = 159 | HHC_LOCATION = 160 | GENERATE_CHI = NO 161 | CHM_INDEX_ENCODING = 162 | BINARY_TOC = YES 163 | TOC_EXPAND = YES 164 | GENERATE_QHP = NO 165 | QCH_FILE = 166 | QHP_NAMESPACE = org.doxygen.Project 167 | QHP_VIRTUAL_FOLDER = doc 168 | QHP_CUST_FILTER_NAME = 169 | QHP_CUST_FILTER_ATTRS = 170 | QHP_SECT_FILTER_ATTRS = 171 | QHG_LOCATION = 172 | GENERATE_ECLIPSEHELP = NO 173 | ECLIPSE_DOC_ID = org.doxygen.Project 174 | DISABLE_INDEX = NO 175 | GENERATE_TREEVIEW = YES 176 | ENUM_VALUES_PER_LINE = 4 177 | TREEVIEW_WIDTH = 350 178 | EXT_LINKS_IN_WINDOW = YES 179 | FORMULA_FONTSIZE = 10 180 | FORMULA_TRANSPARENT = YES 181 | USE_MATHJAX = NO 182 | MATHJAX_FORMAT = HTML-CSS 183 | MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest 184 | MATHJAX_EXTENSIONS = 185 | MATHJAX_CODEFILE = 186 | SEARCHENGINE = YES 187 | SERVER_BASED_SEARCH = NO 188 | EXTERNAL_SEARCH = NO 189 | SEARCHENGINE_URL = 190 | SEARCHDATA_FILE = searchdata.xml 191 | EXTERNAL_SEARCH_ID = 192 | EXTRA_SEARCH_MAPPINGS = 193 | #--------------------------------------------------------------------------- 194 | # Configuration options related to the LaTeX output 195 | #--------------------------------------------------------------------------- 196 | GENERATE_LATEX = NO 197 | LATEX_OUTPUT = latex 198 | LATEX_CMD_NAME = latex 199 | MAKEINDEX_CMD_NAME = makeindex 200 | COMPACT_LATEX = NO 201 | PAPER_TYPE = a4 202 | EXTRA_PACKAGES = 203 | LATEX_HEADER = 204 | LATEX_FOOTER = 205 | LATEX_EXTRA_FILES = 206 | PDF_HYPERLINKS = YES 207 | USE_PDFLATEX = YES 208 | LATEX_BATCHMODE = NO 209 | LATEX_HIDE_INDICES = NO 210 | LATEX_SOURCE_CODE = NO 211 | LATEX_BIB_STYLE = plain 212 | #--------------------------------------------------------------------------- 213 | # Configuration options related to the RTF output 214 | #--------------------------------------------------------------------------- 215 | GENERATE_RTF = NO 216 | RTF_OUTPUT = rtf 217 | COMPACT_RTF = NO 218 | RTF_HYPERLINKS = NO 219 | RTF_STYLESHEET_FILE = 220 | RTF_EXTENSIONS_FILE = 221 | #--------------------------------------------------------------------------- 222 | # Configuration options related to the man page output 223 | #--------------------------------------------------------------------------- 224 | GENERATE_MAN = NO 225 | MAN_OUTPUT = man 226 | MAN_EXTENSION = .3 227 | MAN_LINKS = NO 228 | #--------------------------------------------------------------------------- 229 | # Configuration options related to the XML output 230 | #--------------------------------------------------------------------------- 231 | GENERATE_XML = NO 232 | XML_OUTPUT = xml 233 | XML_PROGRAMLISTING = YES 234 | #--------------------------------------------------------------------------- 235 | # Configuration options related to the DOCBOOK output 236 | #--------------------------------------------------------------------------- 237 | GENERATE_DOCBOOK = NO 238 | DOCBOOK_OUTPUT = docbook 239 | #--------------------------------------------------------------------------- 240 | # Configuration options for the AutoGen Definitions output 241 | #--------------------------------------------------------------------------- 242 | GENERATE_AUTOGEN_DEF = NO 243 | #--------------------------------------------------------------------------- 244 | # Configuration options related to the Perl module output 245 | #--------------------------------------------------------------------------- 246 | GENERATE_PERLMOD = NO 247 | PERLMOD_LATEX = NO 248 | PERLMOD_PRETTY = YES 249 | PERLMOD_MAKEVAR_PREFIX = 250 | #--------------------------------------------------------------------------- 251 | # Configuration options related to the preprocessor 252 | #--------------------------------------------------------------------------- 253 | ENABLE_PREPROCESSING = YES 254 | MACRO_EXPANSION = NO 255 | EXPAND_ONLY_PREDEF = NO 256 | SEARCH_INCLUDES = YES 257 | INCLUDE_PATH = 258 | INCLUDE_FILE_PATTERNS = 259 | PREDEFINED = 260 | EXPAND_AS_DEFINED = 261 | SKIP_FUNCTION_MACROS = YES 262 | #--------------------------------------------------------------------------- 263 | # Configuration options related to external references 264 | #--------------------------------------------------------------------------- 265 | TAGFILES = 266 | GENERATE_TAGFILE = 267 | ALLEXTERNALS = NO 268 | EXTERNAL_GROUPS = YES 269 | EXTERNAL_PAGES = YES 270 | PERL_PATH = /usr/bin/perl 271 | #--------------------------------------------------------------------------- 272 | # Configuration options related to the dot tool 273 | #--------------------------------------------------------------------------- 274 | CLASS_DIAGRAMS = YES 275 | MSCGEN_PATH = 276 | DIA_PATH = 277 | HIDE_UNDOC_RELATIONS = YES 278 | HAVE_DOT = YES 279 | DOT_NUM_THREADS = 0 280 | DOT_FONTNAME = Helvetica 281 | DOT_FONTSIZE = 10 282 | DOT_FONTPATH = 283 | CLASS_GRAPH = YES 284 | COLLABORATION_GRAPH = YES 285 | GROUP_GRAPHS = YES 286 | UML_LOOK = NO 287 | UML_LIMIT_NUM_FIELDS = 10 288 | TEMPLATE_RELATIONS = NO 289 | INCLUDE_GRAPH = YES 290 | INCLUDED_BY_GRAPH = YES 291 | CALL_GRAPH = YES 292 | CALLER_GRAPH = YES 293 | GRAPHICAL_HIERARCHY = YES 294 | DIRECTORY_GRAPH = YES 295 | DOT_IMAGE_FORMAT = svg 296 | INTERACTIVE_SVG = YES 297 | DOT_PATH = 298 | DOTFILE_DIRS = 299 | MSCFILE_DIRS = 300 | DIAFILE_DIRS = 301 | DOT_GRAPH_MAX_NODES = 50 302 | MAX_DOT_GRAPH_DEPTH = 0 303 | DOT_TRANSPARENT = NO 304 | DOT_MULTI_TARGETS = YES 305 | GENERATE_LEGEND = YES 306 | DOT_CLEANUP = YES 307 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ##------------------------------------------------------------------------ 3 | ## Auxiliary Rules and Actions 4 | ##------------------------------------------------------------------------ 5 | 6 | .PHONY : docs 7 | 8 | all: docs 9 | 10 | docs: 11 | doxygen Doxyfile 12 | egrep --color "((W|w)arning)|^" ../build/doxygen-warnings.log 13 | 14 | clean: 15 | rm -rf ../build/docs 16 | 17 | -------------------------------------------------------------------------------- /docs/ast-construction.dox: -------------------------------------------------------------------------------- 1 | /*! 2 | @defgroup ast-construction AST Construction Functions 3 | @ingroup ast 4 | 5 | @brief This page describes all of the functions used to construct the AST 6 | representation of the input code, along with the corresponding data 7 | structures. 8 | 9 | @details 10 | All functions and data structures are grouped depending on which syntactic 11 | feature of the language you are trying to represent. 12 | 13 | */ 14 | -------------------------------------------------------------------------------- /docs/ast-nodes.dox: -------------------------------------------------------------------------------- 1 | /*! 2 | @defgroup ast-nodes AST Nodes 3 | @ingroup ast 4 | 5 | @brief Notes and todo list for the AST nodes. 6 | 7 | @section ast-todo AST Todo List 8 | 9 | - Proper number representation node. 10 | - Completely deprecate the @ref ast_node type. 11 | - Types and assertions for the @ref ast_list construct. 12 | 13 | */ 14 | -------------------------------------------------------------------------------- /docs/ast-utility.dox: -------------------------------------------------------------------------------- 1 | /*! 2 | @defgroup ast-utility AST Utility Functions 3 | @ingroup ast 4 | 5 | @brief Contains utility data structures and functions which are used to 6 | help represent portions of the AST, but which are not specific to a 7 | particular node. 8 | 9 | */ 10 | -------------------------------------------------------------------------------- /docs/ast.dox: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | @defgroup ast Abstract Syntax Tree 4 | 5 | @brief Functions and data structures which build and represent the AST. 6 | 7 | @details 8 | This page describes the structure of the abstract syntax tree that the 9 | parser constructs. It includes the various root nodes, and how their 10 | child nodes are structured. 11 | 12 | */ 13 | -------------------------------------------------------------------------------- /docs/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | $projectname: $title 9 | $title 10 | 11 | 12 | 13 | $treeview 14 | $search 15 | $mathjax 16 | 17 | $extrastylesheet 18 | 19 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /docs/project-organisation-structure.dox: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | @page project-organisation-code Code Structure & Architecture 4 | 5 | @brief This page describes how the code is structured and related. It also 6 | tries to map this to the file structure. 7 | 8 | @tableofcontents 9 | 10 | @section poc-api API Access & High Level 11 | 12 | The code representing the "user facing" side of the parser library is 13 | located in src/verilog_parser.h and the corresponding 14 | src/verilog_parser_wrapper.c files. 15 | 16 | The API functions themselves documented in @ref parser-api 17 | 18 | It is also useful to look at the datastructures in src/verilog_ast.h, since 19 | it is a collection of these which is ultimately returned to the programmer 20 | after parsing a collection of source codes. 21 | 22 | @section poc-lexing Lexical Analysis 23 | 24 | Lexical analysis is done mainly using the src/verilog_scanner.l flex 25 | file. Accompanying this is the @ref verilog_preprocessor_context object, 26 | found in verilog_preprocessor.h/c. All of the preprocessing and macro 27 | expansion is done at the lexical analysis stage of the parser, before it 28 | gets to the syntax analysis stage. 29 | 30 | The preprocessor is available to the user via the @ref yy_preproc global 31 | variable. 32 | 33 | @section poc-parsing Parsing 34 | 35 | Parsing is split across several large files, and forms the bulk of the 36 | source code in the project. 37 | 38 | @subsection poc-parsing-grammar Parser Grammar 39 | 40 | The verilog grammar definition is found in the src/verilog_parser.y Bison 41 | file. This has been written to very closely mirror the syntax specification in 42 | the IEEE Verilog 2001 standard. While this means that the code is more verbose 43 | than is strictly required, it is much easier to read and relate to the 44 | specification. 45 | 46 | @subsection poc-parsing-ast Abstract Syntax Tree 47 | 48 | Construction of the AST is done *during* parsing, with post-grammar-rule 49 | calls to functions in src/verilog_ast.h/c. Each rule will usually create an 50 | AST node or object representing it's sub-rules or terminals, and then pass 51 | this up to the next level of the parser. 52 | 53 | The AST is available to the user via the @ref yy_verilog_source_tree global 54 | variable. 55 | 56 | */ 57 | -------------------------------------------------------------------------------- /docs/project-organisation.dox: -------------------------------------------------------------------------------- 1 | /*! 2 | @page project-organisation Project Organisation 3 | @subpage project-organisation-code 4 | 5 | @brief This page descibes how the project file tree and build system are 6 | organised. 7 | 8 | @tableofcontents 9 | 10 | @section source-tree Source Tree 11 | 12 | The source tree is split into four main sections: documentation tests, tools 13 | and source code. 14 | 15 | - All of the tests live in the `tests/` subfolder. These are tests which 16 | have been added in order to highlight bugs, or otherwise make sure that 17 | proper test coverage is hit. 18 | - Tools live in the `bin/` folder. These include project setup scripts, and 19 | the script to download the main test source file suite. 20 | - Source code lives in the `src/` folder. This includes all header files, 21 | source files, and flex/bison grammars and token descriptors. 22 | - Documentation lives in the `docs/` folder. Here is all of the plain text 23 | documentation for the project, along with the Doxygen configuration file. 24 | 25 | @section build-system Build System 26 | 27 | The build system uses CMake, and is split into debug and release builds. 28 | These are setup by the `bin/project.sh` script, and are found in the 29 | `build/debug` or `build/release` directories. 30 | 31 | From either of those directories, we can run the following commands: 32 | 33 | - `make all` 34 | - `make parser` - Builds the library and a small tester app 35 | - `make test` - Runs the test suite against the most recent build. 36 | - `make coverage-report` - Runs the coverage suite against the most recent 37 | build, and puts the results in `./build/coverage/` 38 | 39 | @section memory-leaks Memory Leaks 40 | 41 | There is a tool script in `bin/` called `leakcheck-report.sh` which should be 42 | run from the project root directory. 43 | 44 | It runs a subset of the tests through the parser, assisted by valgrind. It 45 | checks for all memory leaks and their origins, putting the resulting log 46 | into the `build` folder. 47 | 48 | @section ci-tool Continuous Integration 49 | 50 | This project uses the Travis-CI tool for continuous integration. This is 51 | a service that plugs into github, meaning that every commit, fork and 52 | pull request automatically triggers a build. This build is configured using 53 | the `.travis.yml` file in the root of the project. As a minium, all builds 54 | must complete successfully, and all of the test should be run without errors. 55 | 56 | */ 57 | -------------------------------------------------------------------------------- /docs/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* The standard CSS for doxygen 1.8.6 */ 2 | 3 | body, table, div, p, dl { 4 | font: 400 14px/22px Roboto,sans-serif; 5 | } 6 | 7 | #navrow1{display:none;} 8 | #navrow2{display:none;} 9 | 10 | /* @group Heading Levels */ 11 | 12 | h1.groupheader { 13 | font-size: 150%; 14 | } 15 | 16 | .title { 17 | font: 400 14px/28px Roboto,sans-serif; 18 | font-size: 150%; 19 | font-weight: bold; 20 | margin: 10px 2px; 21 | } 22 | 23 | h2.groupheader { 24 | border-bottom: 1px solid #879ECB; 25 | color: #354C7B; 26 | font-size: 150%; 27 | font-weight: normal; 28 | margin-top: 1.75em; 29 | padding-top: 8px; 30 | padding-bottom: 4px; 31 | width: 100%; 32 | } 33 | 34 | h3.groupheader { 35 | font-size: 100%; 36 | } 37 | 38 | h1, h2, h3, h4, h5, h6 { 39 | -webkit-transition: text-shadow 0.5s linear; 40 | -moz-transition: text-shadow 0.5s linear; 41 | -ms-transition: text-shadow 0.5s linear; 42 | -o-transition: text-shadow 0.5s linear; 43 | transition: text-shadow 0.5s linear; 44 | margin-right: 15px; 45 | } 46 | 47 | h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { 48 | text-shadow: 0 0 15px cyan; 49 | } 50 | 51 | dt { 52 | font-weight: bold; 53 | } 54 | 55 | div.multicol { 56 | -moz-column-gap: 1em; 57 | -webkit-column-gap: 1em; 58 | -moz-column-count: 3; 59 | -webkit-column-count: 3; 60 | } 61 | 62 | p.startli, p.startdd { 63 | margin-top: 2px; 64 | } 65 | 66 | p.starttd { 67 | margin-top: 0px; 68 | } 69 | 70 | p.endli { 71 | margin-bottom: 0px; 72 | } 73 | 74 | p.enddd { 75 | margin-bottom: 4px; 76 | } 77 | 78 | p.endtd { 79 | margin-bottom: 2px; 80 | } 81 | 82 | /* @end */ 83 | 84 | caption { 85 | font-weight: bold; 86 | } 87 | 88 | span.legend { 89 | font-size: 70%; 90 | text-align: center; 91 | } 92 | 93 | h3.version { 94 | font-size: 90%; 95 | text-align: center; 96 | } 97 | 98 | div.qindex, div.navtab{ 99 | background-color: #EBEFF6; 100 | border: 1px solid #A3B4D7; 101 | text-align: center; 102 | } 103 | 104 | div.qindex, div.navpath { 105 | width: 100%; 106 | line-height: 140%; 107 | } 108 | 109 | div.navtab { 110 | margin-right: 15px; 111 | } 112 | 113 | /* @group Link Styling */ 114 | 115 | a { 116 | color: #3D578C; 117 | font-weight: normal; 118 | text-decoration: none; 119 | } 120 | 121 | .contents a:visited { 122 | color: #4665A2; 123 | } 124 | 125 | a:hover { 126 | text-decoration: underline; 127 | } 128 | 129 | a.qindex { 130 | font-weight: bold; 131 | } 132 | 133 | a.qindexHL { 134 | font-weight: bold; 135 | background-color: #9CAFD4; 136 | color: #ffffff; 137 | border: 1px double #869DCA; 138 | } 139 | 140 | .contents a.qindexHL:visited { 141 | color: #ffffff; 142 | } 143 | 144 | a.el { 145 | font-weight: bold; 146 | } 147 | 148 | a.elRef { 149 | } 150 | 151 | a.code, a.code:visited, a.line, a.line:visited { 152 | color: #4665A2; 153 | } 154 | 155 | a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { 156 | color: #4665A2; 157 | } 158 | 159 | /* @end */ 160 | 161 | dl.el { 162 | margin-left: -1cm; 163 | } 164 | 165 | pre.fragment { 166 | border: 1px solid #C4CFE5; 167 | background-color: #FBFCFD; 168 | padding: 4px 6px; 169 | margin: 4px 8px 4px 2px; 170 | overflow: auto; 171 | word-wrap: break-word; 172 | font-size: 9pt; 173 | line-height: 125%; 174 | font-family: monospace, fixed; 175 | font-size: 105%; 176 | } 177 | 178 | div.fragment { 179 | padding: 4px 6px; 180 | margin: 4px 8px 4px 2px; 181 | background-color: #FBFCFD; 182 | border: 1px solid #C4CFE5; 183 | } 184 | 185 | div.line { 186 | font-family: monospace, fixed; 187 | font-size: 13px; 188 | min-height: 13px; 189 | line-height: 1.0; 190 | text-wrap: unrestricted; 191 | white-space: -moz-pre-wrap; /* Moz */ 192 | white-space: -pre-wrap; /* Opera 4-6 */ 193 | white-space: -o-pre-wrap; /* Opera 7 */ 194 | white-space: pre-wrap; /* CSS3 */ 195 | word-wrap: break-word; /* IE 5.5+ */ 196 | text-indent: -53px; 197 | padding-left: 53px; 198 | padding-bottom: 0px; 199 | margin: 0px; 200 | -webkit-transition-property: background-color, box-shadow; 201 | -webkit-transition-duration: 0.5s; 202 | -moz-transition-property: background-color, box-shadow; 203 | -moz-transition-duration: 0.5s; 204 | -ms-transition-property: background-color, box-shadow; 205 | -ms-transition-duration: 0.5s; 206 | -o-transition-property: background-color, box-shadow; 207 | -o-transition-duration: 0.5s; 208 | transition-property: background-color, box-shadow; 209 | transition-duration: 0.5s; 210 | } 211 | 212 | div.line.glow { 213 | background-color: cyan; 214 | box-shadow: 0 0 10px cyan; 215 | } 216 | 217 | 218 | span.lineno { 219 | padding-right: 4px; 220 | text-align: right; 221 | border-right: 2px solid #0F0; 222 | background-color: #E8E8E8; 223 | white-space: pre; 224 | } 225 | span.lineno a { 226 | background-color: #D8D8D8; 227 | } 228 | 229 | span.lineno a:hover { 230 | background-color: #C8C8C8; 231 | } 232 | 233 | div.ah { 234 | background-color: black; 235 | font-weight: bold; 236 | color: #ffffff; 237 | margin-bottom: 3px; 238 | margin-top: 3px; 239 | padding: 0.2em; 240 | border: solid thin #333; 241 | border-radius: 0.5em; 242 | -webkit-border-radius: .5em; 243 | -moz-border-radius: .5em; 244 | box-shadow: 2px 2px 3px #999; 245 | -webkit-box-shadow: 2px 2px 3px #999; 246 | -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; 247 | background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); 248 | background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); 249 | } 250 | 251 | div.groupHeader { 252 | margin-left: 16px; 253 | margin-top: 12px; 254 | font-weight: bold; 255 | } 256 | 257 | div.groupText { 258 | margin-left: 16px; 259 | font-style: italic; 260 | } 261 | 262 | body { 263 | background-color: white; 264 | color: black; 265 | margin: 0; 266 | } 267 | 268 | div.contents { 269 | margin-top: 10px; 270 | margin-left: auto; 271 | margin-right: auto; 272 | max-width: 830px; 273 | background-color: white; 274 | padding: 5px; 275 | padding-left: 10px; 276 | padding-right: 10px; 277 | border-radius: 5px; 278 | } 279 | 280 | td.indexkey { 281 | background-color: #EBEFF6; 282 | font-weight: bold; 283 | border: 1px solid #C4CFE5; 284 | margin: 2px 0px 2px 0; 285 | padding: 2px 10px; 286 | white-space: nowrap; 287 | vertical-align: top; 288 | } 289 | 290 | td.indexvalue { 291 | background-color: #EBEFF6; 292 | border: 1px solid #C4CFE5; 293 | padding: 2px 10px; 294 | margin: 2px 0px; 295 | } 296 | 297 | tr.memlist { 298 | background-color: #EEF1F7; 299 | } 300 | 301 | p.formulaDsp { 302 | text-align: center; 303 | } 304 | 305 | img.formulaDsp { 306 | 307 | } 308 | 309 | img.formulaInl { 310 | vertical-align: middle; 311 | } 312 | 313 | div.center { 314 | text-align: center; 315 | margin-top: 0px; 316 | margin-bottom: 0px; 317 | padding: 0px; 318 | } 319 | 320 | div.center img { 321 | border: 0px; 322 | } 323 | 324 | address.footer { 325 | text-align: right; 326 | padding-right: 12px; 327 | } 328 | 329 | img.footer { 330 | border: 0px; 331 | vertical-align: middle; 332 | } 333 | 334 | /* @group Code Colorization */ 335 | 336 | span.keyword { 337 | color: #008000 338 | } 339 | 340 | span.keywordtype { 341 | color: #604020 342 | } 343 | 344 | span.keywordflow { 345 | color: #e08000 346 | } 347 | 348 | span.comment { 349 | color: #800000 350 | } 351 | 352 | span.preprocessor { 353 | color: #806020 354 | } 355 | 356 | span.stringliteral { 357 | color: #002080 358 | } 359 | 360 | span.charliteral { 361 | color: #008080 362 | } 363 | 364 | span.vhdldigit { 365 | color: #ff00ff 366 | } 367 | 368 | span.vhdlchar { 369 | color: #000000 370 | } 371 | 372 | span.vhdlkeyword { 373 | color: #700070 374 | } 375 | 376 | span.vhdllogic { 377 | color: #ff0000 378 | } 379 | 380 | blockquote { 381 | background-color: #F7F8FB; 382 | border-left: 2px solid #9CAFD4; 383 | margin: 0 24px 0 4px; 384 | padding: 0 12px 0 16px; 385 | } 386 | 387 | /* @end */ 388 | 389 | /* 390 | .search { 391 | color: #003399; 392 | font-weight: bold; 393 | } 394 | 395 | form.search { 396 | margin-bottom: 0px; 397 | margin-top: 0px; 398 | } 399 | 400 | input.search { 401 | font-size: 75%; 402 | color: #000080; 403 | font-weight: normal; 404 | background-color: #e8eef2; 405 | } 406 | */ 407 | 408 | td.tiny { 409 | font-size: 75%; 410 | } 411 | 412 | .dirtab { 413 | padding: 4px; 414 | border-collapse: collapse; 415 | border: 1px solid #A3B4D7; 416 | } 417 | 418 | th.dirtab { 419 | background: #EBEFF6; 420 | font-weight: bold; 421 | } 422 | 423 | hr { 424 | height: 0px; 425 | border: none; 426 | border-top: 1px solid #4A6AAA; 427 | } 428 | 429 | hr.footer { 430 | height: 1px; 431 | } 432 | 433 | /* @group Member Descriptions */ 434 | 435 | table.memberdecls { 436 | border-spacing: 0px; 437 | padding: 0px; 438 | } 439 | 440 | .memberdecls td, .fieldtable tr { 441 | -webkit-transition-property: background-color, box-shadow; 442 | -webkit-transition-duration: 0.5s; 443 | -moz-transition-property: background-color, box-shadow; 444 | -moz-transition-duration: 0.5s; 445 | -ms-transition-property: background-color, box-shadow; 446 | -ms-transition-duration: 0.5s; 447 | -o-transition-property: background-color, box-shadow; 448 | -o-transition-duration: 0.5s; 449 | transition-property: background-color, box-shadow; 450 | transition-duration: 0.5s; 451 | } 452 | 453 | .memberdecls td.glow, .fieldtable tr.glow { 454 | background-color: cyan; 455 | box-shadow: 0 0 15px cyan; 456 | } 457 | 458 | .mdescLeft, .mdescRight, 459 | .memItemLeft, .memItemRight, 460 | .memTemplItemLeft, .memTemplItemRight, .memTemplParams { 461 | background-color: #F9FAFC; 462 | border: none; 463 | margin: 4px; 464 | padding: 1px 0 0 8px; 465 | } 466 | 467 | .mdescLeft, .mdescRight { 468 | padding: 0px 8px 4px 8px; 469 | color: #555; 470 | } 471 | 472 | .memSeparator { 473 | border-bottom: 1px solid #DEE4F0; 474 | line-height: 1px; 475 | margin: 0px; 476 | padding: 0px; 477 | } 478 | 479 | .memItemLeft, .memTemplItemLeft { 480 | white-space: nowrap; 481 | } 482 | 483 | .memItemRight { 484 | width: 100%; 485 | } 486 | 487 | .memTemplParams { 488 | color: #4665A2; 489 | white-space: nowrap; 490 | font-size: 80%; 491 | } 492 | 493 | /* @end */ 494 | 495 | /* @group Member Details */ 496 | 497 | /* Styles for detailed member documentation */ 498 | 499 | .memtemplate { 500 | font-size: 80%; 501 | color: #4665A2; 502 | font-weight: normal; 503 | margin-left: 9px; 504 | } 505 | 506 | .memnav { 507 | background-color: #EBEFF6; 508 | border: 1px solid #A3B4D7; 509 | text-align: center; 510 | margin: 2px; 511 | margin-right: 15px; 512 | padding: 2px; 513 | } 514 | 515 | .mempage { 516 | width: 100%; 517 | } 518 | 519 | .memitem { 520 | padding: 0; 521 | margin-bottom: 10px; 522 | margin-right: 5px; 523 | -webkit-transition: box-shadow 0.5s linear; 524 | -moz-transition: box-shadow 0.5s linear; 525 | -ms-transition: box-shadow 0.5s linear; 526 | -o-transition: box-shadow 0.5s linear; 527 | transition: box-shadow 0.5s linear; 528 | display: table !important; 529 | width: 100%; 530 | } 531 | 532 | .memitem.glow { 533 | box-shadow: 0 0 15px cyan; 534 | } 535 | 536 | .memname { 537 | font-weight: bold; 538 | margin-left: 6px; 539 | } 540 | 541 | .memname td { 542 | vertical-align: bottom; 543 | } 544 | 545 | .memproto, dl.reflist dt { 546 | border-top: 1px solid #A8B8D9; 547 | border-left: 1px solid #A8B8D9; 548 | border-right: 1px solid #A8B8D9; 549 | padding: 6px 0px 6px 0px; 550 | color: #253555; 551 | font-weight: bold; 552 | text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); 553 | background-image:url('nav_f.png'); 554 | background-repeat:repeat-x; 555 | background-color: #E2E8F2; 556 | /* opera specific markup */ 557 | box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); 558 | border-top-right-radius: 4px; 559 | border-top-left-radius: 4px; 560 | /* firefox specific markup */ 561 | -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; 562 | -moz-border-radius-topright: 4px; 563 | -moz-border-radius-topleft: 4px; 564 | /* webkit specific markup */ 565 | -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); 566 | -webkit-border-top-right-radius: 4px; 567 | -webkit-border-top-left-radius: 4px; 568 | 569 | } 570 | 571 | .memdoc, dl.reflist dd { 572 | border-bottom: 1px solid #A8B8D9; 573 | border-left: 1px solid #A8B8D9; 574 | border-right: 1px solid #A8B8D9; 575 | padding: 6px 10px 2px 10px; 576 | background-color: #FBFCFD; 577 | border-top-width: 0; 578 | background-image:url('nav_g.png'); 579 | background-repeat:repeat-x; 580 | background-color: #FFFFFF; 581 | /* opera specific markup */ 582 | border-bottom-left-radius: 4px; 583 | border-bottom-right-radius: 4px; 584 | box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); 585 | /* firefox specific markup */ 586 | -moz-border-radius-bottomleft: 4px; 587 | -moz-border-radius-bottomright: 4px; 588 | -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; 589 | /* webkit specific markup */ 590 | -webkit-border-bottom-left-radius: 4px; 591 | -webkit-border-bottom-right-radius: 4px; 592 | -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); 593 | } 594 | 595 | dl.reflist dt { 596 | padding: 5px; 597 | } 598 | 599 | dl.reflist dd { 600 | margin: 0px 0px 10px 0px; 601 | padding: 5px; 602 | } 603 | 604 | .paramkey { 605 | text-align: right; 606 | } 607 | 608 | .paramtype { 609 | white-space: nowrap; 610 | } 611 | 612 | .paramname { 613 | color: #602020; 614 | white-space: nowrap; 615 | } 616 | .paramname em { 617 | font-style: normal; 618 | } 619 | .paramname code { 620 | line-height: 14px; 621 | } 622 | 623 | .params, .retval, .exception, .tparams { 624 | margin-left: 0px; 625 | padding-left: 0px; 626 | } 627 | 628 | .params .paramname, .retval .paramname { 629 | font-weight: bold; 630 | vertical-align: top; 631 | } 632 | 633 | .params .paramtype { 634 | font-style: italic; 635 | vertical-align: top; 636 | } 637 | 638 | .params .paramdir { 639 | font-family: "courier new",courier,monospace; 640 | vertical-align: top; 641 | } 642 | 643 | table.mlabels { 644 | border-spacing: 0px; 645 | } 646 | 647 | td.mlabels-left { 648 | width: 100%; 649 | padding: 0px; 650 | } 651 | 652 | td.mlabels-right { 653 | vertical-align: bottom; 654 | padding: 0px; 655 | white-space: nowrap; 656 | } 657 | 658 | span.mlabels { 659 | margin-left: 8px; 660 | } 661 | 662 | span.mlabel { 663 | background-color: #728DC1; 664 | border-top:1px solid #5373B4; 665 | border-left:1px solid #5373B4; 666 | border-right:1px solid #C4CFE5; 667 | border-bottom:1px solid #C4CFE5; 668 | text-shadow: none; 669 | color: white; 670 | margin-right: 4px; 671 | padding: 2px 3px; 672 | border-radius: 3px; 673 | font-size: 7pt; 674 | white-space: nowrap; 675 | vertical-align: middle; 676 | } 677 | 678 | 679 | 680 | /* @end */ 681 | 682 | /* these are for tree view when not used as main index */ 683 | 684 | div.directory { 685 | margin: 10px 0px; 686 | border-top: 1px solid #A8B8D9; 687 | border-bottom: 1px solid #A8B8D9; 688 | width: 100%; 689 | } 690 | 691 | .directory table { 692 | border-collapse:collapse; 693 | } 694 | 695 | .directory td { 696 | margin: 0px; 697 | padding: 0px; 698 | vertical-align: top; 699 | } 700 | 701 | .directory td.entry { 702 | white-space: nowrap; 703 | padding-right: 6px; 704 | padding-top: 3px; 705 | } 706 | 707 | .directory td.entry a { 708 | outline:none; 709 | } 710 | 711 | .directory td.entry a img { 712 | border: none; 713 | } 714 | 715 | .directory td.desc { 716 | width: 100%; 717 | padding-left: 6px; 718 | padding-right: 6px; 719 | padding-top: 3px; 720 | border-left: 1px solid rgba(0,0,0,0.05); 721 | } 722 | 723 | .directory tr.even { 724 | padding-left: 6px; 725 | background-color: #F7F8FB; 726 | } 727 | 728 | .directory img { 729 | vertical-align: -30%; 730 | } 731 | 732 | .directory .levels { 733 | white-space: nowrap; 734 | width: 100%; 735 | text-align: right; 736 | font-size: 9pt; 737 | } 738 | 739 | .directory .levels span { 740 | cursor: pointer; 741 | padding-left: 2px; 742 | padding-right: 2px; 743 | color: #3D578C; 744 | } 745 | 746 | div.dynheader { 747 | margin-top: 8px; 748 | -webkit-touch-callout: none; 749 | -webkit-user-select: none; 750 | -khtml-user-select: none; 751 | -moz-user-select: none; 752 | -ms-user-select: none; 753 | user-select: none; 754 | } 755 | 756 | address { 757 | font-style: normal; 758 | color: #2A3D61; 759 | } 760 | 761 | table.doxtable { 762 | border-collapse:collapse; 763 | margin-top: 4px; 764 | margin-bottom: 4px; 765 | } 766 | 767 | table.doxtable td, table.doxtable th { 768 | border: 1px solid #2D4068; 769 | padding: 3px 7px 2px; 770 | } 771 | 772 | table.doxtable th { 773 | background-color: #374F7F; 774 | color: #FFFFFF; 775 | font-size: 110%; 776 | padding-bottom: 4px; 777 | padding-top: 5px; 778 | } 779 | 780 | table.fieldtable { 781 | /*width: 100%;*/ 782 | margin-bottom: 10px; 783 | border: 1px solid #A8B8D9; 784 | border-spacing: 0px; 785 | -moz-border-radius: 4px; 786 | -webkit-border-radius: 4px; 787 | border-radius: 4px; 788 | -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; 789 | -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); 790 | box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); 791 | } 792 | 793 | .fieldtable td, .fieldtable th { 794 | padding: 3px 7px 2px; 795 | } 796 | 797 | .fieldtable td.fieldtype, .fieldtable td.fieldname { 798 | white-space: nowrap; 799 | border-right: 1px solid #A8B8D9; 800 | border-bottom: 1px solid #A8B8D9; 801 | vertical-align: top; 802 | } 803 | 804 | .fieldtable td.fieldname { 805 | padding-top: 3px; 806 | } 807 | 808 | .fieldtable td.fielddoc { 809 | border-bottom: 1px solid #A8B8D9; 810 | /*width: 100%;*/ 811 | } 812 | 813 | .fieldtable td.fielddoc p:first-child { 814 | margin-top: 0px; 815 | } 816 | 817 | .fieldtable td.fielddoc p:last-child { 818 | margin-bottom: 2px; 819 | } 820 | 821 | .fieldtable tr:last-child td { 822 | border-bottom: none; 823 | } 824 | 825 | .fieldtable th { 826 | background-image:url('nav_f.png'); 827 | background-repeat:repeat-x; 828 | background-color: #E2E8F2; 829 | font-size: 90%; 830 | color: #253555; 831 | padding-bottom: 4px; 832 | padding-top: 5px; 833 | text-align:left; 834 | -moz-border-radius-topleft: 4px; 835 | -moz-border-radius-topright: 4px; 836 | -webkit-border-top-left-radius: 4px; 837 | -webkit-border-top-right-radius: 4px; 838 | border-top-left-radius: 4px; 839 | border-top-right-radius: 4px; 840 | border-bottom: 1px solid #A8B8D9; 841 | } 842 | 843 | 844 | .tabsearch { 845 | top: 0px; 846 | left: 10px; 847 | height: 36px; 848 | background-image: url('tab_b.png'); 849 | z-index: 101; 850 | overflow: hidden; 851 | font-size: 13px; 852 | } 853 | 854 | .navpath ul 855 | { 856 | font-size: 11px; 857 | background-image:url('tab_b.png'); 858 | background-repeat:repeat-x; 859 | background-position: 0 -5px; 860 | height:30px; 861 | line-height:30px; 862 | color:#8AA0CC; 863 | border:solid 1px #C2CDE4; 864 | overflow:hidden; 865 | margin:0px; 866 | padding:0px; 867 | } 868 | 869 | .navpath li 870 | { 871 | list-style-type:none; 872 | float:left; 873 | padding-left:10px; 874 | padding-right:15px; 875 | background-image:url('bc_s.png'); 876 | background-repeat:no-repeat; 877 | background-position:right; 878 | color:#364D7C; 879 | } 880 | 881 | .navpath li.navelem a 882 | { 883 | height:32px; 884 | display:block; 885 | text-decoration: none; 886 | outline: none; 887 | color: #283A5D; 888 | font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; 889 | text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); 890 | text-decoration: none; 891 | } 892 | 893 | .navpath li.navelem a:hover 894 | { 895 | color:#6884BD; 896 | } 897 | 898 | .navpath li.footer 899 | { 900 | list-style-type:none; 901 | float:right; 902 | padding-left:10px; 903 | padding-right:15px; 904 | background-image:none; 905 | background-repeat:no-repeat; 906 | background-position:right; 907 | color:#364D7C; 908 | font-size: 8pt; 909 | } 910 | 911 | 912 | div.summary 913 | { 914 | float: right; 915 | font-size: 8pt; 916 | padding-right: 5px; 917 | width: 50%; 918 | text-align: right; 919 | } 920 | 921 | div.summary a 922 | { 923 | white-space: nowrap; 924 | } 925 | 926 | div.ingroups 927 | { 928 | font-size: 8pt; 929 | width: 50%; 930 | text-align: left; 931 | } 932 | 933 | div.ingroups a 934 | { 935 | white-space: nowrap; 936 | } 937 | 938 | div.header 939 | { 940 | background-image:url('nav_h.png'); 941 | background-repeat:repeat-x; 942 | background-color: #F9FAFC; 943 | margin: 0px; 944 | border-bottom: 1px solid #C4CFE5; 945 | } 946 | 947 | div.headertitle 948 | { 949 | padding: 5px 5px 5px 10px; 950 | } 951 | 952 | dl 953 | { 954 | padding: 0 0 0 10px; 955 | } 956 | 957 | /* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ 958 | dl.section 959 | { 960 | margin-left: 0px; 961 | padding-left: 0px; 962 | } 963 | 964 | dl.note 965 | { 966 | margin-left:-7px; 967 | padding-left: 3px; 968 | border-left:4px solid; 969 | border-color: #D0C000; 970 | } 971 | 972 | dl.warning, dl.attention 973 | { 974 | margin-left:-7px; 975 | padding-left: 3px; 976 | border-left:4px solid; 977 | border-color: #FF0000; 978 | } 979 | 980 | dl.pre, dl.post, dl.invariant 981 | { 982 | margin-left:-7px; 983 | padding-left: 3px; 984 | border-left:4px solid; 985 | border-color: #00D000; 986 | } 987 | 988 | dl.deprecated 989 | { 990 | margin-left:-7px; 991 | padding-left: 3px; 992 | border-left:4px solid; 993 | border-color: #505050; 994 | } 995 | 996 | dl.todo 997 | { 998 | margin-left:-7px; 999 | padding-left: 3px; 1000 | border-left:4px solid; 1001 | border-color: #00C0E0; 1002 | } 1003 | 1004 | dl.test 1005 | { 1006 | margin-left:-7px; 1007 | padding-left: 3px; 1008 | border-left:4px solid; 1009 | border-color: #3030E0; 1010 | } 1011 | 1012 | dl.bug 1013 | { 1014 | margin-left:-7px; 1015 | padding-left: 3px; 1016 | border-left:4px solid; 1017 | border-color: #C08050; 1018 | } 1019 | 1020 | dl.section dd { 1021 | margin-bottom: 6px; 1022 | } 1023 | 1024 | 1025 | #projectlogo 1026 | { 1027 | text-align: center; 1028 | vertical-align: bottom; 1029 | border-collapse: separate; 1030 | } 1031 | 1032 | #projectlogo img 1033 | { 1034 | border: 0px none; 1035 | } 1036 | 1037 | #projectname 1038 | { 1039 | font: 300% Tahoma, Arial,sans-serif; 1040 | margin: 0px; 1041 | padding: 2px 0px; 1042 | } 1043 | 1044 | #projectbrief 1045 | { 1046 | font: 120% Tahoma, Arial,sans-serif; 1047 | margin: 0px; 1048 | padding: 0px; 1049 | } 1050 | 1051 | #projectnumber 1052 | { 1053 | font: 50% Tahoma, Arial,sans-serif; 1054 | margin: 0px; 1055 | padding: 0px; 1056 | } 1057 | 1058 | #titlearea 1059 | { 1060 | padding: 0px; 1061 | margin: 0px; 1062 | width: 100%; 1063 | border-bottom: 1px solid #5373B4; 1064 | } 1065 | 1066 | #doc-content 1067 | { 1068 | background-color: #F0F0F0; 1069 | } 1070 | 1071 | .image 1072 | { 1073 | text-align: center; 1074 | } 1075 | 1076 | .dotgraph 1077 | { 1078 | text-align: center; 1079 | } 1080 | 1081 | .mscgraph 1082 | { 1083 | text-align: center; 1084 | } 1085 | 1086 | .diagraph 1087 | { 1088 | text-align: center; 1089 | } 1090 | 1091 | .caption 1092 | { 1093 | font-weight: bold; 1094 | } 1095 | 1096 | div.zoom 1097 | { 1098 | border: 1px solid #90A5CE; 1099 | } 1100 | 1101 | dl.citelist { 1102 | margin-bottom:50px; 1103 | } 1104 | 1105 | dl.citelist dt { 1106 | color:#334975; 1107 | float:left; 1108 | font-weight:bold; 1109 | margin-right:10px; 1110 | padding:5px; 1111 | } 1112 | 1113 | dl.citelist dd { 1114 | margin:2px 0; 1115 | padding:5px 0; 1116 | } 1117 | 1118 | div.toc { 1119 | padding: 14px 25px; 1120 | background-color: #F4F6FA; 1121 | border: 1px solid #D8DFEE; 1122 | border-radius: 7px 7px 7px 7px; 1123 | float: right; 1124 | height: auto; 1125 | margin: 0 20px 10px 10px; 1126 | width: 200px; 1127 | } 1128 | 1129 | div.toc li { 1130 | background: url("bdwn.png") no-repeat scroll 0 5px transparent; 1131 | font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; 1132 | margin-top: 5px; 1133 | padding-left: 10px; 1134 | padding-top: 2px; 1135 | } 1136 | 1137 | div.toc h3 { 1138 | font: bold 12px/1.2 Arial,FreeSans,sans-serif; 1139 | color: #4665A2; 1140 | border-bottom: 0 none; 1141 | margin: 0; 1142 | } 1143 | 1144 | div.toc ul { 1145 | list-style: none outside none; 1146 | border: medium none; 1147 | padding: 0px; 1148 | } 1149 | 1150 | div.toc li.level1 { 1151 | margin-left: 0px; 1152 | } 1153 | 1154 | div.toc li.level2 { 1155 | margin-left: 15px; 1156 | } 1157 | 1158 | div.toc li.level3 { 1159 | margin-left: 30px; 1160 | } 1161 | 1162 | div.toc li.level4 { 1163 | margin-left: 45px; 1164 | } 1165 | 1166 | .inherit_header { 1167 | font-weight: bold; 1168 | color: gray; 1169 | cursor: pointer; 1170 | -webkit-touch-callout: none; 1171 | -webkit-user-select: none; 1172 | -khtml-user-select: none; 1173 | -moz-user-select: none; 1174 | -ms-user-select: none; 1175 | user-select: none; 1176 | } 1177 | 1178 | .inherit_header td { 1179 | padding: 6px 0px 2px 5px; 1180 | } 1181 | 1182 | .inherit { 1183 | display: none; 1184 | } 1185 | 1186 | tr.heading h2 { 1187 | margin-top: 12px; 1188 | margin-bottom: 4px; 1189 | } 1190 | 1191 | /* tooltip related style info */ 1192 | 1193 | .ttc { 1194 | position: absolute; 1195 | display: none; 1196 | } 1197 | 1198 | #powerTip { 1199 | cursor: default; 1200 | white-space: nowrap; 1201 | background-color: white; 1202 | border: 1px solid gray; 1203 | border-radius: 4px 4px 4px 4px; 1204 | box-shadow: 1px 1px 7px gray; 1205 | display: none; 1206 | font-size: smaller; 1207 | max-width: 80%; 1208 | opacity: 0.9; 1209 | padding: 1ex 1em 1em; 1210 | position: absolute; 1211 | z-index: 2147483647; 1212 | } 1213 | 1214 | #powerTip div.ttdoc { 1215 | color: grey; 1216 | font-style: italic; 1217 | } 1218 | 1219 | #powerTip div.ttname a { 1220 | font-weight: bold; 1221 | } 1222 | 1223 | #powerTip div.ttname { 1224 | font-weight: bold; 1225 | } 1226 | 1227 | #powerTip div.ttdeci { 1228 | color: #006318; 1229 | } 1230 | 1231 | #powerTip div { 1232 | margin: 0px; 1233 | padding: 0px; 1234 | font: 12px/16px Roboto,sans-serif; 1235 | } 1236 | 1237 | #powerTip:before, #powerTip:after { 1238 | content: ""; 1239 | position: absolute; 1240 | margin: 0px; 1241 | } 1242 | 1243 | #powerTip.n:after, #powerTip.n:before, 1244 | #powerTip.s:after, #powerTip.s:before, 1245 | #powerTip.w:after, #powerTip.w:before, 1246 | #powerTip.e:after, #powerTip.e:before, 1247 | #powerTip.ne:after, #powerTip.ne:before, 1248 | #powerTip.se:after, #powerTip.se:before, 1249 | #powerTip.nw:after, #powerTip.nw:before, 1250 | #powerTip.sw:after, #powerTip.sw:before { 1251 | border: solid transparent; 1252 | content: " "; 1253 | height: 0; 1254 | width: 0; 1255 | position: absolute; 1256 | } 1257 | 1258 | #powerTip.n:after, #powerTip.s:after, 1259 | #powerTip.w:after, #powerTip.e:after, 1260 | #powerTip.nw:after, #powerTip.ne:after, 1261 | #powerTip.sw:after, #powerTip.se:after { 1262 | border-color: rgba(255, 255, 255, 0); 1263 | } 1264 | 1265 | #powerTip.n:before, #powerTip.s:before, 1266 | #powerTip.w:before, #powerTip.e:before, 1267 | #powerTip.nw:before, #powerTip.ne:before, 1268 | #powerTip.sw:before, #powerTip.se:before { 1269 | border-color: rgba(128, 128, 128, 0); 1270 | } 1271 | 1272 | #powerTip.n:after, #powerTip.n:before, 1273 | #powerTip.ne:after, #powerTip.ne:before, 1274 | #powerTip.nw:after, #powerTip.nw:before { 1275 | top: 100%; 1276 | } 1277 | 1278 | #powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { 1279 | border-top-color: #ffffff; 1280 | border-width: 10px; 1281 | margin: 0px -10px; 1282 | } 1283 | #powerTip.n:before { 1284 | border-top-color: #808080; 1285 | border-width: 11px; 1286 | margin: 0px -11px; 1287 | } 1288 | #powerTip.n:after, #powerTip.n:before { 1289 | left: 50%; 1290 | } 1291 | 1292 | #powerTip.nw:after, #powerTip.nw:before { 1293 | right: 14px; 1294 | } 1295 | 1296 | #powerTip.ne:after, #powerTip.ne:before { 1297 | left: 14px; 1298 | } 1299 | 1300 | #powerTip.s:after, #powerTip.s:before, 1301 | #powerTip.se:after, #powerTip.se:before, 1302 | #powerTip.sw:after, #powerTip.sw:before { 1303 | bottom: 100%; 1304 | } 1305 | 1306 | #powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { 1307 | border-bottom-color: #ffffff; 1308 | border-width: 10px; 1309 | margin: 0px -10px; 1310 | } 1311 | 1312 | #powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { 1313 | border-bottom-color: #808080; 1314 | border-width: 11px; 1315 | margin: 0px -11px; 1316 | } 1317 | 1318 | #powerTip.s:after, #powerTip.s:before { 1319 | left: 50%; 1320 | } 1321 | 1322 | #powerTip.sw:after, #powerTip.sw:before { 1323 | right: 14px; 1324 | } 1325 | 1326 | #powerTip.se:after, #powerTip.se:before { 1327 | left: 14px; 1328 | } 1329 | 1330 | #powerTip.e:after, #powerTip.e:before { 1331 | left: 100%; 1332 | } 1333 | #powerTip.e:after { 1334 | border-left-color: #ffffff; 1335 | border-width: 10px; 1336 | top: 50%; 1337 | margin-top: -10px; 1338 | } 1339 | #powerTip.e:before { 1340 | border-left-color: #808080; 1341 | border-width: 11px; 1342 | top: 50%; 1343 | margin-top: -11px; 1344 | } 1345 | 1346 | #powerTip.w:after, #powerTip.w:before { 1347 | right: 100%; 1348 | } 1349 | #powerTip.w:after { 1350 | border-right-color: #ffffff; 1351 | border-width: 10px; 1352 | top: 50%; 1353 | margin-top: -10px; 1354 | } 1355 | #powerTip.w:before { 1356 | border-right-color: #808080; 1357 | border-width: 11px; 1358 | top: 50%; 1359 | margin-top: -11px; 1360 | } 1361 | 1362 | @media print 1363 | { 1364 | #top { display: none; } 1365 | #side-nav { display: none; } 1366 | #nav-path { display: none; } 1367 | body { overflow:visible; } 1368 | h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } 1369 | .summary { display: none; } 1370 | .memitem { page-break-inside: avoid; } 1371 | #doc-content 1372 | { 1373 | margin-left:0 !important; 1374 | height:auto !important; 1375 | width:auto !important; 1376 | overflow:inherit; 1377 | display:inline; 1378 | } 1379 | } 1380 | 1381 | -------------------------------------------------------------------------------- /scratchpad.md: -------------------------------------------------------------------------------- 1 | 2 | # Scratchpad 3 | 4 | A file of todo-lists, notes, and other useful stuff. 5 | 6 | --- 7 | 8 | ## Todo List 9 | 10 | ### Features 11 | 12 | - [x] `ast_expression_tostring()` function 13 | - [X] Track source *file* of a construct, as well as line number. 14 | - [ ] Track macro evaluations. 15 | - [ ] Freeing of individual memory structures, rather than all at once. 16 | 17 | ### Build & Flow 18 | 19 | - [X] Better mechanism for building with & without coverage. 20 | - [X] Re-instate coveralls service. 21 | - [X] Rename various "reserved" makefile targets 22 | - [X] Version checking in CMake for FLEX and BISON 23 | 24 | ### Small but important 25 | 26 | - [ ] Fix `identifer` misspellings of `identifier`. 27 | 28 | ### Long-term Changes 29 | 30 | - None 31 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(verilog-parser-src) 4 | 5 | message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") 6 | 7 | set(LIBRARY_NAME verilogparser) 8 | set(EXECUTABLE_NAME parser) 9 | 10 | FIND_PACKAGE(BISON 3.0.4 REQUIRED) 11 | FIND_PACKAGE(FLEX 2.5.35 REQUIRED) 12 | 13 | set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 14 | set(BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) 15 | 16 | set(FLEX_INPUT verilog_scanner.l) 17 | set(FLEX_OUTPUT verilog_scanner.c) 18 | 19 | set(BISON_INPUT verilog_parser.y) 20 | set(BISON_OUTPUT verilog_parser.tab.c) 21 | 22 | # ------------------------------------------------------------------------ 23 | 24 | 25 | option(WITH_COVERAGE "If YES, build the debug executable with coverage." NO) 26 | 27 | SET(COV_FLAGS_C "-fprofile-arcs -ftest-coverage") 28 | SET(COV_FLAGS_LINK "-fprofile-arcs -ftest-coverage") 29 | 30 | # ------------------------------------------------------------------------ 31 | 32 | SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -Wall -W") 33 | SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_C_FLAGS_RELEASE}") 34 | 35 | if( ${WITH_COVERAGE} ) 36 | 37 | message(STATUS "Building with coverage flags set.") 38 | SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${COV_FLAGS_C} -DVERILOG_PARSER_COVERAGE_ON") 39 | SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_C_FLAGS_RELEASE} ${COV_FLAGS_LINK}") 40 | 41 | else() 42 | 43 | message(STATUS "NOT building with coverage.") 44 | 45 | endif() 46 | 47 | 48 | SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") 49 | SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 50 | 51 | message(STATUS "Parser Build Flags Debug: ${CMAKE_C_FLAGS_DEBUG}") 52 | message(STATUS "Parser Link Flags Debug: ${CMAKE_EXE_LINKER_FLAGS_DEBUG}") 53 | message(STATUS "Parser Build Flags Release: ${CMAKE_C_FLAGS_RELEASE}") 54 | message(STATUS "Parser Link Flags Release: ${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 55 | 56 | # ------------------------------------------------------------------------ 57 | 58 | #cmake_policy(SET CMP0050 OLD) 59 | 60 | ADD_CUSTOM_COMMAND( 61 | SOURCE ${SOURCE_DIR}/${BISON_INPUT} 62 | COMMAND ${BISON_EXECUTABLE} 63 | ARGS -y ${SOURCE_DIR}/${BISON_INPUT} -o ${BINARY_DIR}/${BISON_OUTPUT} 64 | TARGET PARSER_LIB 65 | OUTPUTS ${BINARY_DIR}/${BISON_OUTPUT} 66 | ) 67 | 68 | ADD_CUSTOM_COMMAND( 69 | SOURCE ${SOURCE_DIR}/${FLEX_INPUT} 70 | COMMAND ${FLEX_EXECUTABLE} 71 | ARGS -o ${BINARY_DIR}/${FLEX_OUTPUT} ${SOURCE_DIR}/${FLEX_INPUT} 72 | TARGET PARSER_LIB 73 | DEPENDS ${BINARY_DIR}/${BISON_OUTPUT} 74 | OUTPUTS ${BINARY_DIR}/${FLEX_OUTPUT} 75 | ) 76 | 77 | #cmake_policy(SET CMP0050 NEW) 78 | 79 | SET_SOURCE_FILES_PROPERTIES(${BINARY_DIR}/${FLEX_OUTPUT} GENERATED) 80 | SET_SOURCE_FILES_PROPERTIES(${BINARY_DIR}/${BISON_OUTPUT} GENERATED) 81 | 82 | # ------------------------------------------------------------------------ 83 | 84 | INCLUDE_DIRECTORIES(${BINARY_DIR}) 85 | INCLUDE_DIRECTORIES(${SOURCE_DIR}) 86 | 87 | set(PARSER_LIB_SRC ${BINARY_DIR}/${FLEX_OUTPUT} 88 | ${BINARY_DIR}/${BISON_OUTPUT} 89 | ${SOURCE_DIR}/verilog_ast.c 90 | ${SOURCE_DIR}/verilog_ast_mem.c 91 | ${SOURCE_DIR}/verilog_ast_util.c 92 | ${SOURCE_DIR}/verilog_ast_common.c 93 | ${SOURCE_DIR}/verilog_parser_wrapper.c 94 | ${SOURCE_DIR}/verilog_preprocessor.c 95 | ) 96 | 97 | add_library(${LIBRARY_NAME} ${PARSER_LIB_SRC}) 98 | 99 | set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1) 100 | 101 | add_executable(${EXECUTABLE_NAME} main.c) 102 | target_link_libraries(${EXECUTABLE_NAME} ${LIBRARY_NAME}) 103 | 104 | # ------------------------------------------------------------------------ 105 | 106 | if( ${DISABLE_VERILOG_PARSER_TESTS} ) 107 | 108 | else () 109 | if( ${WITH_COVERAGE} ) 110 | 111 | set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1) 112 | 113 | file(GLOB TEST_FILE_LIST "../tests/*.[vh]") 114 | 115 | add_test(NAME verilog_parser_coverage 116 | COMMAND parser ${TEST_FILE_LIST} 117 | WORKING_DIRECTORY ../ 118 | ) 119 | 120 | else () 121 | 122 | file(GLOB TEST_FILE_LIST "../tests/*.[vh]") 123 | 124 | foreach ( TESTFILE ${TEST_FILE_LIST} ) 125 | 126 | add_test(NAME verilog_parser_${TESTFILE} 127 | COMMAND parser ${TESTFILE} 128 | WORKING_DIRECTORY ../ 129 | ) 130 | 131 | endforeach ( TESTFILE ) 132 | 133 | endif() 134 | endif () 135 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /*! 2 | @file main.c 3 | @brief A simple test program for the C library code. 4 | */ 5 | 6 | #include "stdio.h" 7 | 8 | #include "verilog_parser.h" 9 | #include "verilog_ast_common.h" 10 | #include "verilog_preprocessor.h" 11 | #include "verilog_ast_util.h" 12 | 13 | int main(int argc, char ** argv) 14 | { 15 | if(argc < 2) 16 | { 17 | printf("ERROR. Please supply at least one file path argument.\n"); 18 | return 1; 19 | } 20 | else 21 | { 22 | 23 | int F = 0; 24 | for(F = 1; F < argc; F++) 25 | { 26 | 27 | // Initialise the parser. 28 | verilog_parser_init(); 29 | 30 | // Setup the preprocessor to look in ./tests/ for include files. 31 | ast_list_append(yy_preproc -> search_dirs, "./tests/"); 32 | ast_list_append(yy_preproc -> search_dirs, "./"); 33 | printf("%s ", argv[F]);fflush(stdout); 34 | 35 | // Load the file. 36 | FILE * fh = fopen(argv[F], "r"); 37 | 38 | verilog_preprocessor_set_file(yy_preproc, argv[F]); 39 | 40 | // Parse the file and store the result. 41 | int result = verilog_parse_file(fh); 42 | 43 | // Close the file handle 44 | fclose(fh); 45 | 46 | if(result == 0) 47 | { 48 | printf(" - Parse successful\n"); 49 | } 50 | else 51 | { 52 | printf(" - Parse failed\n"); 53 | if(argc<=2) return 1; 54 | } 55 | 56 | verilog_resolve_modules(yy_verilog_source_tree); 57 | } 58 | } 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /src/verilog_ast_common.c: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog_ast_common.c 3 | @brief Contains definitions of value-independent data structures like 4 | linked lists which are used in the ast. 5 | */ 6 | 7 | #include "stdarg.h" 8 | #include "stdlib.h" 9 | #include "assert.h" 10 | #include "string.h" 11 | #include "stdio.h" 12 | 13 | #include "verilog_ast_common.h" 14 | 15 | /*! 16 | @brief Creates and returns a pointer to a new linked list. 17 | */ 18 | ast_list * ast_list_new () 19 | { 20 | ast_list * tr = ast_calloc(1, sizeof(ast_list)); 21 | tr -> head = NULL; 22 | tr -> tail = NULL; 23 | tr -> walker = NULL; 24 | tr -> items = 0; 25 | tr -> current_item = 0; 26 | return tr; 27 | } 28 | 29 | /*! 30 | @brief Frees the memory of the supplied linked list. 31 | @note Does not free the memory of the data elements in the list, only 32 | the list construct itself. 33 | */ 34 | void ast_list_free(ast_list * list) 35 | { 36 | if(list -> items > 0) 37 | { 38 | list -> walker = list -> head; 39 | 40 | // Walk along the list, freeing elements as we go. 41 | while(list -> walker != NULL) 42 | { 43 | ast_list_element * tmp = list -> walker; 44 | list -> walker = list -> walker -> next; 45 | 46 | if(tmp != NULL) 47 | { 48 | free(tmp); 49 | } 50 | } 51 | } 52 | 53 | free(list); 54 | } 55 | 56 | /*! 57 | @brief Adds a new item to the end of a linked list. 58 | */ 59 | void ast_list_append(ast_list * list, void * data) 60 | { 61 | if(list -> items == 0) 62 | { 63 | list -> head = ast_calloc(1,sizeof(ast_list_element)); 64 | list -> head -> next = NULL; 65 | list -> head -> data = data; 66 | 67 | list -> tail = list -> head; 68 | list -> walker = list -> tail; 69 | list -> items += 1; 70 | list -> current_item = list -> items-1; 71 | } 72 | else 73 | { 74 | list -> tail -> next = ast_calloc(1, sizeof(ast_list_element)); 75 | list -> tail = list -> tail -> next; 76 | list -> tail -> data = data; 77 | 78 | list -> items += 1; 79 | } 80 | } 81 | 82 | 83 | /*! 84 | @brief Removes the i'th item from a linked list. 85 | */ 86 | void ast_list_remove_at(ast_list * list, unsigned int i) 87 | { 88 | if(i > list -> items - 1) 89 | { 90 | return; 91 | } 92 | else 93 | { 94 | if(i <= list -> current_item) 95 | { 96 | list -> current_item = 0; 97 | list -> walker = list -> head; 98 | } 99 | 100 | while(list -> current_item != i-1 && list -> walker != NULL) 101 | { 102 | list -> walker = list -> walker -> next; 103 | list -> current_item += 1; 104 | } 105 | if(i > 0){ 106 | assert(i-1 == list -> current_item); 107 | list -> walker -> next = list -> walker -> next -> next; 108 | list -> items -= 1; 109 | //ast_list_element * toremove = list -> walker -> next; 110 | //free(toremove); 111 | } else { 112 | list -> head = list -> head -> next; 113 | //ast_list_element * toremove = list -> head; 114 | //free(toremove); 115 | list -> items -= 1; 116 | } 117 | } 118 | } 119 | 120 | 121 | /*! 122 | @brief Adds a new item to the front of a linked list. 123 | */ 124 | void ast_list_preappend(ast_list * list, void * data) 125 | { 126 | if(list -> items == 0) 127 | { 128 | list -> head = ast_calloc(1,sizeof(ast_list_element)); 129 | list -> head -> next = NULL; 130 | list -> head -> data = data; 131 | 132 | list -> tail = list -> head; 133 | list -> walker = list -> tail; 134 | list -> items += 1; 135 | list -> current_item = list -> items-1; 136 | } 137 | else 138 | { 139 | ast_list_element * to_add = ast_calloc(1, sizeof(ast_list_element)); 140 | to_add -> data = data; 141 | 142 | to_add -> next = list -> head; 143 | list -> head = to_add; 144 | 145 | list -> items += 1; 146 | list -> current_item += 1; 147 | } 148 | } 149 | 150 | /*! 151 | @brief Finds and returns the i'th item in the linked list. 152 | @details Returns a void* pointer. The programmer must be sure to cast this 153 | as the correct type. 154 | */ 155 | void * ast_list_get(ast_list * list, unsigned int item) 156 | { 157 | assert(list != NULL); 158 | if(item > list -> items - 1) 159 | { 160 | return NULL; 161 | } 162 | else 163 | { 164 | if(item < list -> current_item) 165 | { 166 | list -> current_item = 0; 167 | list -> walker = list -> head; 168 | } 169 | 170 | while(list -> current_item != item && list -> walker != NULL) 171 | { 172 | list -> walker = list -> walker -> next; 173 | list -> current_item += 1; 174 | } 175 | 176 | if(list -> walker == NULL) 177 | { 178 | return NULL; 179 | } 180 | else 181 | { 182 | return list -> walker -> data; 183 | } 184 | } 185 | } 186 | 187 | 188 | /*! 189 | @brief Searches the list, returning true or false if the data item supplied is 190 | contained within it. 191 | @details Performs a *pointer* comparison. That is, if the internal list 192 | pointer has the same address as the supplied data pointer, the item is 193 | considered to be found. 194 | */ 195 | int ast_list_contains( 196 | ast_list * list, 197 | void * data 198 | ){ 199 | assert(list != NULL); 200 | if(list -> items <= 0) 201 | { 202 | return 0; 203 | } 204 | else 205 | { 206 | list -> current_item = 0; 207 | list -> walker = list -> head; 208 | 209 | while(list -> walker != NULL) 210 | { 211 | if(list -> walker -> data == data) 212 | { 213 | return 1; 214 | } 215 | else 216 | { 217 | list -> walker = list -> walker -> next; 218 | list -> current_item += 1; 219 | } 220 | } 221 | 222 | return 0; 223 | } 224 | } 225 | 226 | 227 | /*! 228 | @brief concatenates the two supplied lists into one. 229 | @param head - This will form the "front" of the new list. 230 | @param tail - This will form the "end" of the new list. 231 | @details This function takes all the elements in tail and appends them 232 | to those in head. The tail argument is then released from memory, and the 233 | original head pointer is returned, with all data items still in tact. 234 | */ 235 | ast_list * ast_list_concat(ast_list * head, ast_list * tail) 236 | { 237 | assert(head != NULL); 238 | assert(tail != NULL); 239 | 240 | // Perform the concatenation. 241 | 242 | if(head -> tail == NULL) 243 | { 244 | head -> tail = tail -> head; 245 | head -> head = tail -> head; 246 | } 247 | else if(head -> tail -> next == NULL) 248 | { 249 | head -> tail -> next = tail -> head; 250 | head -> tail = tail -> tail; 251 | } 252 | else 253 | { 254 | while(head -> tail -> next != NULL) 255 | { 256 | head -> tail = head -> tail -> next; 257 | } 258 | head -> tail -> next = tail -> head; 259 | head -> tail = tail -> tail; 260 | } 261 | 262 | head -> items += tail -> items; 263 | head -> walker = head -> head; 264 | head -> current_item = 0; 265 | 266 | // Free only the tail data-structure, not it's elements. 267 | //free(tail); 268 | 269 | // return the new list. 270 | return head; 271 | } 272 | 273 | /*! 274 | @brief Creates and returns a new stack object. 275 | */ 276 | ast_stack * ast_stack_new(){ 277 | ast_stack * tr = ast_calloc(1,sizeof(ast_stack)); 278 | tr -> depth = 0; 279 | return tr; 280 | } 281 | 282 | /*! 283 | @brief Free the stack, but not it's contents 284 | */ 285 | void ast_stack_free(ast_stack * stack){ 286 | assert(stack != NULL); 287 | 288 | while(stack -> items != NULL){ 289 | ast_stack_element * tmp = stack -> items -> next; 290 | free(stack -> items); 291 | stack -> items = tmp; 292 | } 293 | 294 | free(stack); 295 | } 296 | 297 | /*! 298 | @brief Push a new item to the top of the stack. 299 | @param [inout] stack - The stack to push to. 300 | @param [in] item - The thing to push onto the stack. 301 | */ 302 | void ast_stack_push( 303 | ast_stack * stack, 304 | void * item 305 | ){ 306 | assert(stack != NULL); 307 | 308 | if(stack -> items == NULL) 309 | { 310 | stack -> items = ast_calloc(1,sizeof(ast_stack_element)); 311 | stack -> items -> data = item; 312 | } 313 | else 314 | { 315 | ast_stack_element * toadd = ast_calloc(1,sizeof(ast_stack_element)); 316 | toadd -> data = item; 317 | toadd -> next = stack -> items; 318 | stack -> items = toadd; 319 | } 320 | 321 | stack -> depth ++; 322 | 323 | } 324 | 325 | /*! 326 | @brief Pop the top item from the top of the stack. 327 | @param [inout] stack - The stack to pop from. 328 | */ 329 | void * ast_stack_pop( 330 | 331 | ast_stack * stack 332 | ){ 333 | assert(stack != NULL); 334 | 335 | if(stack -> items != NULL) 336 | { 337 | void * tr = stack -> items -> data; 338 | // ast_stack_element * tofree = stack -> items; 339 | stack -> items = stack -> items -> next; 340 | stack -> depth --; 341 | // free(tofree); 342 | return tr; 343 | } 344 | else 345 | { 346 | return NULL; 347 | } 348 | } 349 | 350 | /*! 351 | @brief Peek at the top item on the top of the stack. 352 | @param [inout] stack - The stack to peek at 353 | */ 354 | void * ast_stack_peek( 355 | ast_stack * stack 356 | ){ 357 | assert(stack != NULL); 358 | 359 | if(stack -> items != NULL) 360 | { 361 | void * tr = stack -> items -> data; 362 | return tr; 363 | } 364 | else 365 | { 366 | return NULL; 367 | } 368 | } 369 | 370 | /*! 371 | @brief Peek at the item *below* the top item on the top of the stack. 372 | @param [inout] stack - The stack to peek into 373 | */ 374 | void * ast_stack_peek2( 375 | ast_stack * stack 376 | ){ 377 | assert(stack != NULL); 378 | 379 | if(stack -> items != NULL) 380 | { 381 | if(stack -> items -> next != NULL) 382 | { 383 | void * tr = stack -> items -> next -> data; 384 | return tr; 385 | } 386 | else 387 | { 388 | return NULL; 389 | } 390 | } 391 | else 392 | { 393 | return NULL; 394 | } 395 | } 396 | 397 | //! Creates and returns a new hashtable. 398 | ast_hashtable * ast_hashtable_new(){ 399 | ast_hashtable * tr = ast_calloc(1,sizeof(ast_hashtable)); 400 | 401 | tr -> size = 0; 402 | tr -> elements = ast_list_new(); 403 | 404 | return tr; 405 | } 406 | 407 | //! Frees an existing hashtable, but not it's contents, only the structure. 408 | void ast_hashtable_free( 409 | ast_hashtable * table //!< The table to free. 410 | ){ 411 | ast_list_free(table -> elements); 412 | free(table); 413 | return; 414 | } 415 | 416 | //! Inserts a new item into the hashtable. 417 | ast_hashtable_result ast_hashtable_insert( 418 | ast_hashtable * table, //!< The table to insert into. 419 | char * key, //!< The key to insert with. 420 | void * value //!< The data being added. 421 | ){ 422 | assert(key != NULL); 423 | assert(table != NULL); 424 | 425 | unsigned int i; 426 | for(i = 0; i < table -> elements -> items; i ++) 427 | { 428 | ast_hashtable_element * e = ast_list_get(table->elements, i); 429 | if(e != NULL) 430 | { 431 | if(strcmp(e -> key , key) == 0){ 432 | return HASH_KEY_COLLISION; 433 | } 434 | } 435 | } 436 | ast_hashtable_element * toinsert = ast_calloc(1,sizeof(ast_hashtable_element)); 437 | toinsert -> key = key; 438 | toinsert -> data = value; 439 | ast_list_append(table -> elements, toinsert);; 440 | 441 | return HASH_SUCCESS; 442 | } 443 | 444 | //! Returns an item from the hashtable. 445 | ast_hashtable_result ast_hashtable_get( 446 | ast_hashtable * table, //!< The table to fetch from. 447 | char * key, //!< The key of the data to fetch. 448 | void ** value //!< [out] The data being returned. 449 | ){ 450 | unsigned int i; 451 | for(i = 0; i < table -> elements -> items; i ++) 452 | { 453 | ast_hashtable_element * e = ast_list_get(table->elements, i); 454 | if(e != NULL) 455 | { 456 | if(strcmp(e -> key , key) == 0){ 457 | *value = (e -> data); 458 | return HASH_SUCCESS; 459 | } 460 | } 461 | } 462 | return HASH_KEY_NOT_FOUND; 463 | } 464 | 465 | //! Removes a key value pair from the hashtable. 466 | ast_hashtable_result ast_hashtable_delete( 467 | ast_hashtable * table, //!< The table to delete from. 468 | char * key //!< The key to delete. 469 | ){ 470 | unsigned int i; 471 | for(i = 0; i < table -> elements -> items; i ++) 472 | { 473 | ast_hashtable_element * e = ast_list_get(table->elements, i); 474 | if(e != NULL) 475 | { 476 | if(strcmp(e -> key , key) == 0){ 477 | ast_list_remove_at(table->elements, i); 478 | return HASH_SUCCESS; 479 | } 480 | } 481 | } 482 | return HASH_KEY_NOT_FOUND; 483 | } 484 | 485 | //! Updates an existing item in the hashtable. 486 | ast_hashtable_result ast_hashtable_update( 487 | ast_hashtable * table, //!< The table to update. 488 | char * key, //!< The key to update with. 489 | void * value //!< The new data item to update. 490 | ){ 491 | unsigned int i; 492 | for(i = 0; i < table -> elements -> items; i ++) 493 | { 494 | ast_hashtable_element * e = ast_list_get(table->elements, i); 495 | if(strcmp(e -> key , key) == 0){ 496 | e -> data = value; 497 | return HASH_SUCCESS; 498 | } 499 | } 500 | return HASH_KEY_NOT_FOUND; 501 | } 502 | -------------------------------------------------------------------------------- /src/verilog_ast_common.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog_ast_common.h 3 | @brief Contains Declarations of value-independent data structures like 4 | linked lists which are used in the ast. 5 | */ 6 | 7 | #include "stdarg.h" 8 | #include "stdlib.h" 9 | #include "string.h" 10 | 11 | #include "verilog_ast_mem.h" 12 | 13 | #ifndef VERILOG_AST_COMMON_H 14 | #define VERILOG_AST_COMMON_H 15 | 16 | 17 | // --------------- Linked List ------------------------ 18 | 19 | /*! 20 | @defgroup ast-linked-lists Linked List 21 | @{ 22 | @ingroup ast-utility 23 | */ 24 | 25 | 26 | //! Typedef for the ast_list_element_t 27 | typedef struct ast_list_element_t ast_list_element; 28 | 29 | /*! 30 | @brief Storage container for a single element in the linked list. 31 | */ 32 | struct ast_list_element_t{ 33 | ast_list_element * next; 34 | void * data; 35 | }; 36 | 37 | 38 | /*! 39 | @brief Container struct for the linked list data structure. 40 | */ 41 | typedef struct ast_list_t { 42 | ast_list_element * head; //!< The "front" of the list. 43 | ast_list_element * tail; //!< The "end" of the list. 44 | ast_list_element * walker; //!< Used to "walk" along the list. 45 | unsigned int items; //!< Number of items in the list. 46 | unsigned int current_item; //! Current position of walker in list. 47 | } ast_list; 48 | 49 | 50 | /*! 51 | @brief Creates and returns a pointer to a new linked list. 52 | */ 53 | ast_list * ast_list_new (); 54 | 55 | /*! 56 | @brief Frees the memory of the supplied linked list. 57 | @note Does not free the memory of the data elements in the list, only 58 | the list construct itself. 59 | */ 60 | void ast_list_free(ast_list * list); 61 | 62 | /*! 63 | @brief Adds a new item to the end of a linked list. 64 | */ 65 | void ast_list_append(ast_list * list, void * data); 66 | 67 | 68 | /*! 69 | @brief Adds a new item to the front of a linked list. 70 | */ 71 | void ast_list_preappend(ast_list * list, void * data); 72 | 73 | /*! 74 | @brief Finds and returns the i'th item in the linked list. 75 | @details Returns a void* pointer. The programmer must be sure to cast this 76 | as the correct type. 77 | */ 78 | void * ast_list_get(ast_list * list, unsigned int item); 79 | 80 | /*! 81 | @brief Removes the i'th item from a linked list. 82 | */ 83 | void ast_list_remove_at(ast_list * list, unsigned int i); 84 | 85 | /*! 86 | @brief concatenates the two supplied lists into one. 87 | @param head - This will form the "front" of the new list. 88 | @param tail - This will form the "end" of the new list. 89 | @details This function takes all the elements in tail and appends them 90 | to those in head. The tail argument is then released from memory, and the 91 | original head pointer is returned, with all data items still in tact. 92 | */ 93 | ast_list * ast_list_concat(ast_list * head, ast_list * tail); 94 | 95 | 96 | /*! 97 | @brief Searches the list, returning true or false if the data item supplied is 98 | contained within it. 99 | @details Performs a *pointer* comparison. That is, if the internal list 100 | pointer has the same address as the supplied data pointer, the item is 101 | considered to be found. 102 | */ 103 | int ast_list_contains( 104 | ast_list * list, 105 | void * data 106 | ); 107 | 108 | 109 | /*! @} */ 110 | 111 | // ----------------------- Stack -------------------------------------- 112 | 113 | /*! 114 | @defgroup ast-stack Stack 115 | @{ 116 | @ingroup ast-utility 117 | */ 118 | 119 | //! Typedef for the ast_stack_element_t 120 | typedef struct ast_stack_element_t ast_stack_element; 121 | 122 | /*! 123 | @brief Storage container for a single element in the stack 124 | */ 125 | struct ast_stack_element_t{ 126 | ast_stack_element * next; 127 | void * data; 128 | }; 129 | 130 | //! A very simple stack. 131 | typedef struct ast_stack_t{ 132 | unsigned int depth; //!< How many items are on the stack? 133 | ast_stack_element * items; //!< The stack of items. 134 | } ast_stack; 135 | 136 | /*! 137 | @brief Creates and returns a new stack object. 138 | */ 139 | ast_stack * ast_stack_new(); 140 | 141 | /*! 142 | @brief Free the stack, but not it's contents 143 | */ 144 | void ast_stack_free(ast_stack * stack); 145 | 146 | /*! 147 | @brief Push a new item to the top of the stack. 148 | @param [inout] stack - The stack to push to. 149 | @param [in] item - The thing to push onto the stack. 150 | */ 151 | void ast_stack_push( 152 | ast_stack * stack, 153 | void * item 154 | ); 155 | 156 | /*! 157 | @brief Pop the top item from the top of the stack. 158 | @param [inout] stack - The stack to pop from. 159 | */ 160 | void * ast_stack_pop( 161 | ast_stack * stack 162 | ); 163 | 164 | /*! 165 | @brief Peek at the top item on the top of the stack. 166 | @param [inout] stack - The stack to peek at 167 | */ 168 | void * ast_stack_peek( 169 | ast_stack * stack 170 | ); 171 | 172 | /*! 173 | @brief Peek at the item *below* the top item on the top of the stack. 174 | @param [inout] stack - The stack to peek into 175 | */ 176 | void * ast_stack_peek2( 177 | ast_stack * stack 178 | ); 179 | 180 | /*! @} */ 181 | 182 | 183 | // ----------------------- Hash Table --------------------------------- 184 | 185 | 186 | /*! 187 | @defgroup ast-hashtable Hash Table 188 | @{ 189 | @ingroup ast-utility 190 | @brief A *very* simple hash table implemented (for now) over a linked list. 191 | @details This can be used for simple key-value pair storage. Current 192 | access time is O(n) for a table with N elements in it. 193 | @warning This is a *terrible* way to implement a hash table. It doesn't 194 | even do any hashing! 195 | @todo Re-implement over a proper hash table structure. 196 | */ 197 | 198 | /*! @} */ 199 | 200 | 201 | //! A single element in the hash table. 202 | typedef struct ast_hashtable_element_t{ 203 | char * key; //!< The key for the element. 204 | void * data; //!< The data associated with they key. 205 | } ast_hashtable_element; 206 | 207 | 208 | //! A hash table object. 209 | typedef struct ast_hashtable_t{ 210 | ast_list * elements; //!< The items. 211 | unsigned int size; //!< The number of elements in the table. 212 | } ast_hashtable; 213 | 214 | typedef enum ast_hashtable_result_e{ 215 | HASH_SUCCESS = 0, 216 | HASH_FAIL = 1, 217 | HASH_KEY_COLLISION = 2, 218 | HASH_KEY_NOT_FOUND = 3 219 | } ast_hashtable_result; 220 | 221 | //! Creates and returns a new hashtable. 222 | ast_hashtable * ast_hashtable_new(); 223 | 224 | //! Frees an existing hashtable, but not it's contents, only the structure. 225 | void ast_hashtable_free( 226 | ast_hashtable * table //!< The table to free. 227 | ); 228 | 229 | //! Inserts a new item into the hashtable. 230 | ast_hashtable_result ast_hashtable_insert( 231 | ast_hashtable * table, //!< The table to insert into. 232 | char * key, //!< The key to insert with. 233 | void * value //!< The data being added. 234 | ); 235 | 236 | //! Returns an item from the hashtable. 237 | ast_hashtable_result ast_hashtable_get( 238 | ast_hashtable * table, //!< The table to fetch from. 239 | char * key, //!< The key of the data to fetch. 240 | void ** value //!< [out] The data being returned. 241 | ); 242 | 243 | //! Removes a key value pair from the hashtable. 244 | ast_hashtable_result ast_hashtable_delete( 245 | ast_hashtable * table, //!< The table to delete from. 246 | char * key //!< The key to delete. 247 | ); 248 | 249 | //! Updates an existing item in the hashtable. 250 | ast_hashtable_result ast_hashtable_update( 251 | ast_hashtable * table, //!< The table to update. 252 | char * key, //!< The key to update with. 253 | void * value //!< The new data item to update. 254 | ); 255 | 256 | #endif 257 | -------------------------------------------------------------------------------- /src/verilog_ast_mem.c: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog_ast_mem.c 3 | @brief Contains definitions of datastructures and functions for helping to 4 | manage dynamic memory allocation within the library. 5 | */ 6 | 7 | #include "verilog_ast_mem.h" 8 | 9 | /*! 10 | @defgroup ast-utility-mem-manage Memory Management 11 | @{ 12 | @brief Helps to manage memory allocated during AST construction. 13 | @ingroup ast-utility 14 | */ 15 | 16 | //! The total number of memory allocations made. 17 | unsigned int memory_allocations = 0; 18 | 19 | //! The total number of bytes ever allocated using ast_alloc 20 | size_t total_allocated = 0; 21 | 22 | //! Head of the linked list of allocated memory. 23 | ast_memory * memory_head = NULL; 24 | 25 | //! Walker for the linked list of allocated memory. 26 | ast_memory * walker = NULL; 27 | 28 | 29 | /*! 30 | @brief A simple wrapper around calloc. 31 | @details Makes it very easy to clean up afterward using the @ref ast_free_all 32 | function. 33 | @param [in] num - Number of elements to allocate space for. 34 | @param [in] size - The size of each element being allocated. 35 | @returns A pointer to the start of the block of memory allocated. 36 | */ 37 | void * ast_calloc(size_t num, size_t size) 38 | { 39 | // This is the memory the user asked for. 40 | void * data = calloc(num,size); 41 | 42 | memory_allocations += 1; 43 | 44 | // Add the allocated memory to tracking data structure. 45 | if(walker == NULL) 46 | { 47 | memory_head = calloc(1,sizeof(ast_memory)); 48 | memory_head -> size = num * size; 49 | total_allocated += memory_head -> size; 50 | memory_head -> data = data; 51 | memory_head -> next = NULL; 52 | walker = memory_head; 53 | } 54 | else 55 | { 56 | walker -> next = calloc(1,sizeof(ast_memory)); 57 | walker -> next -> size = num * size; 58 | total_allocated += walker -> next -> size; 59 | walker -> next -> data = data; 60 | walker -> next -> next = NULL; 61 | walker = walker -> next; 62 | } 63 | 64 | 65 | return data; 66 | } 67 | 68 | /*! 69 | @brief Frees all memory allocated using @ref ast_calloc. 70 | @details Free's all data stored in the linked list pointed to by the 71 | @ref head variable. 72 | @post @ref walker and @ref head are NULL. All memory allocated by ast_calloc 73 | has been freed. 74 | */ 75 | void ast_free_all() 76 | { 77 | printf("Freeing data for %u memory allocations.\n", memory_allocations); 78 | size_t total_freed = 0; 79 | 80 | while(memory_head != NULL) 81 | { 82 | walker = memory_head -> next; 83 | total_freed += memory_head -> size; 84 | 85 | free(memory_head -> data); 86 | free(memory_head); 87 | 88 | memory_head = walker; 89 | } 90 | 91 | printf("\tFree'd %lu bytes of %lu bytes allocated.\n", 92 | total_freed, total_allocated); 93 | printf("\tBytes remaining: %lu\n", total_allocated - total_freed); 94 | total_allocated -= total_freed; 95 | } 96 | 97 | 98 | char * ast_strdup(char * in) 99 | { 100 | size_t len = strlen(in); 101 | char * tr = ast_calloc(len+1,sizeof(char)); 102 | memcpy(tr,in,len); 103 | return tr; 104 | } 105 | 106 | /*!@}*/ 107 | 108 | -------------------------------------------------------------------------------- /src/verilog_ast_mem.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog_ast_mem.h 3 | @brief Contains Declarations of datastructures and functions for helping to 4 | manage dynamic memory allocation within the library. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #ifndef VERILOG_AST_MEM_H 13 | #define VERILOG_AST_MEM_H 14 | 15 | //! Typedef over ast_memory_T 16 | typedef struct ast_memory_t ast_memory; 17 | 18 | //! Stores information on some allocated memory as a linked list. 19 | struct ast_memory_t{ 20 | size_t size; //!< Amount of memory allocated. 21 | void * data; //!< Pointer to the allocated memory. 22 | ast_memory * next; //!< Next element to be allocated. 23 | }; 24 | 25 | 26 | //! Iterates over all allocated memory and frees it. 27 | void ast_free_all(); 28 | 29 | //! Duplicates the supplied null terminated string. 30 | char * ast_strdup(char * in); 31 | 32 | /*! 33 | @brief A simple wrapper around calloc. 34 | @details This function is identical to calloc, but uses the head and 35 | walker variables above to keep a linked list of all heap memory that the 36 | AST construction allocates. This makes it very easy to clean up afterward 37 | using the @ref ast_free_all function. 38 | @param [in] num - Number of elements to allocate space for. 39 | @param [in] size - The size of each element being allocated. 40 | @returns A pointer to the start of the block of memory allocated. 41 | */ 42 | void * ast_calloc(size_t num, size_t size); 43 | 44 | 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /src/verilog_ast_util.c: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog_ast_util.c 3 | @brief Contains definitions of functions which 4 | operate on the Verilog Abstract Syntax Tree (AST) 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "verilog_ast_util.h" 11 | 12 | 13 | /*! 14 | @brief Searches the list of modules in the parsed source tree, returning the 15 | one that matches the passed identifer. 16 | @returns The matching module declaration, or NULL if no such declaration 17 | exists. 18 | */ 19 | ast_module_declaration * verilog_find_module_declaration( 20 | verilog_source_tree * source, 21 | ast_identifier module_name 22 | ){ 23 | unsigned int m; 24 | for(m = 0; m < source -> modules -> items; m++) 25 | { 26 | ast_module_declaration * candidate = ast_list_get(source -> modules,m); 27 | 28 | if(ast_identifier_cmp(module_name, candidate -> identifier) == 0) 29 | { 30 | return candidate; 31 | } 32 | } 33 | 34 | return NULL; 35 | } 36 | 37 | 38 | /*! 39 | @brief searches across an entire verilog source tree, resolving module 40 | identifiers to their declarations. 41 | */ 42 | void verilog_resolve_modules( 43 | verilog_source_tree * source 44 | ){ 45 | assert(source != NULL); 46 | assert(source -> modules != NULL); 47 | 48 | int resolved = 0; 49 | int unresolved = 0; 50 | 51 | unsigned int m; 52 | for(m = 0; m < source -> modules -> items; m++) 53 | { 54 | ast_module_declaration * module = ast_list_get(source -> modules, m); 55 | 56 | assert(module != NULL); 57 | 58 | if(module -> module_instantiations == NULL || 59 | module -> identifier == NULL){ 60 | continue; 61 | } 62 | 63 | assert(module -> identifier != NULL); 64 | assert(module -> module_instantiations != NULL); 65 | 66 | //printf("%s\n", ast_identifier_tostring(module -> identifier)); 67 | 68 | 69 | unsigned int sm; 70 | for(sm = 0; sm < module -> module_instantiations -> items; sm ++) 71 | { 72 | ast_module_instantiation * submod = 73 | ast_list_get(module -> module_instantiations, sm); 74 | 75 | if(submod -> resolved) 76 | { 77 | // Do Nothing 78 | } 79 | else 80 | { 81 | // Find the module via it's identifier. 82 | ast_module_declaration * foundmod= 83 | verilog_find_module_declaration(source, 84 | submod -> module_identifer); 85 | if(foundmod == NULL) 86 | { 87 | //printf("Could not resolve module name '%s'\n", 88 | //ast_identifier_tostring(submod -> module_identifer)); 89 | unresolved ++; 90 | } 91 | else 92 | { 93 | submod -> resolved = AST_TRUE; 94 | submod -> declaration = foundmod; 95 | resolved ++; 96 | } 97 | } 98 | } 99 | } 100 | //printf("Resolved Modules: %d\t Unresolved Modules: %d\n", 101 | // resolved,unresolved); 102 | } 103 | 104 | 105 | /*! 106 | @brief Returns a list of module instantiations, representing the different 107 | types of module which this parent instantiates. 108 | */ 109 | ast_list * verilog_module_get_children( 110 | ast_module_declaration * module 111 | ){ 112 | ast_list * tr = ast_list_new(); 113 | 114 | unsigned int m; 115 | for(m = 0; m < module -> module_instantiations -> items; m++) 116 | { 117 | ast_module_instantiation * child = 118 | ast_list_get(module -> module_instantiations, m); 119 | 120 | unsigned int c; 121 | unsigned char added_already = 0; 122 | for(c = 0; c < tr -> items; c++) 123 | { 124 | ast_module_instantiation * maybe = ast_list_get(tr,c); 125 | ast_identifier i1, i2; 126 | if(maybe -> resolved) 127 | i1 = maybe -> declaration -> identifier; 128 | else 129 | i1 = maybe -> module_identifer; 130 | 131 | if(child -> resolved) 132 | i2 = child -> declaration -> identifier; 133 | else 134 | i2 = child-> module_identifer; 135 | 136 | if(ast_identifier_cmp(i1,i2) == 0) 137 | { 138 | added_already = 1; 139 | break; 140 | } 141 | } 142 | 143 | if(added_already) 144 | { 145 | continue; 146 | } 147 | else 148 | { 149 | ast_list_append(tr,child); 150 | } 151 | } 152 | 153 | return tr; 154 | } 155 | 156 | 157 | /*! 158 | @brief Finds the child modules for all modules in a source tree. 159 | @returns A hash table, keyed by the module identifiers, of lists of 160 | module children. 161 | @pre The verilog_resolve_modules function has been called on the source tree 162 | to which the passed module belongs. 163 | @see verilog_module_get_children 164 | */ 165 | ast_hashtable * verilog_modules_get_children( 166 | verilog_source_tree * source 167 | ){ 168 | ast_hashtable * tr = ast_hashtable_new(); 169 | 170 | unsigned int m; 171 | for(m = 0; m < source -> modules -> items; m++) 172 | { 173 | ast_module_declaration * module = ast_list_get(source -> modules, m); 174 | 175 | ast_list * children = verilog_module_get_children(module); 176 | 177 | char * key = ast_identifier_tostring(module -> identifier); 178 | 179 | ast_hashtable_insert(tr,key,children); 180 | } 181 | 182 | return tr; 183 | } 184 | -------------------------------------------------------------------------------- /src/verilog_ast_util.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog_ast.h 3 | @brief Contains definitions of functions which 4 | operate on the Verilog Abstract Syntax Tree (AST) 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "verilog_ast.h" 11 | 12 | #ifndef VERILOG_AST_UTIL_H 13 | #define VERILOG_AST_UTIL_H 14 | 15 | /*! 16 | @defgroup ast-utility-modules Module Resoloution & Searching 17 | @{ 18 | @brief Functions for resolving module names. 19 | @ingroup ast-utility 20 | */ 21 | 22 | /*! 23 | @brief searches across an entire verilog source tree, resolving module 24 | identifiers to their declarations. 25 | */ 26 | void verilog_resolve_modules( 27 | verilog_source_tree * source 28 | ); 29 | 30 | /*! 31 | @brief Searches the list of modules in the parsed source tree, returning the 32 | one that matches the passed identifer. 33 | @returns The matching module declaration, or NULL if no such declaration 34 | exists. 35 | */ 36 | ast_module_declaration * verilog_find_module_declaration( 37 | verilog_source_tree * source, 38 | ast_identifier module_name 39 | ); 40 | 41 | // ------------------------------------------------------------------------- 42 | 43 | 44 | /*! 45 | @brief Returns a list of module declarations, representing the different types 46 | of module which this parent instantiates. 47 | @details Each child module will appear once in the returned list. That is, if 48 | a register instantiates eight flip flop modules, then the flip flop module 49 | will appear only once in the returned list. 50 | @returns a list of elements of type ast_module_declaration. 51 | @pre The verilog_resolve_modules function has been called on the source tree 52 | to which the passed module belongs. 53 | @see verilog_modules_get_children 54 | */ 55 | ast_list * verilog_module_get_children( 56 | ast_module_declaration * module 57 | ); 58 | 59 | 60 | /*! 61 | @brief Finds the child modules for all modules in a source tree. 62 | @returns A hash table, keyed by the module identifiers, of lists of 63 | module children. 64 | @pre The verilog_resolve_modules function has been called on the source tree 65 | to which the passed module belongs. 66 | @see verilog_module_get_children 67 | */ 68 | ast_hashtable * verilog_modules_get_children( 69 | verilog_source_tree * source 70 | ); 71 | 72 | /*! @} */ 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/verilog_parser.h: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | @file verilog_parser.h 4 | @brief A nice interface for the whole verilog parser. 5 | @details Provides wrappers around the awkward yylex and yyparse functions, 6 | as well as an easy way to change the input stream. 7 | @note Functions declared in this file are defined in verilog_parser_wrapper.c 8 | */ 9 | 10 | #include "stdio.h" 11 | 12 | // Essential to make sure we have access to all of the yy functions. 13 | #include "verilog_preprocessor.h" 14 | 15 | #ifndef H_VERILOG_PARSER 16 | #define H_VERILOG_PARSER 17 | 18 | #ifndef YY_TYPEDEF_YY_SIZE_T 19 | #define YY_TYPEDEF_YY_SIZE_T 20 | typedef size_t yy_size_t; 21 | #endif 22 | 23 | #ifndef YY_BUF_SIZE 24 | #define YY_BUF_SIZE 16384 25 | #endif 26 | typedef struct yy_buffer_state *YY_BUFFER_STATE; 27 | extern void yyrestart (FILE *input_file ); 28 | extern void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); 29 | extern YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); 30 | extern YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); 31 | extern YY_BUFFER_STATE yy_scan_bytes (const char *bytes,int len ); 32 | extern void yy_delete_buffer (YY_BUFFER_STATE b ); 33 | 34 | /*! 35 | @defgroup parser-api Verilog Parser API 36 | @{ 37 | @brief Describes the top level, programmer facing parser API. 38 | */ 39 | 40 | /*! 41 | @brief Sets up the parsing environment ready for input. 42 | @details Makes sure that there is a vaild preprocessor context and source 43 | tree object ready to store any parsed constructs. 44 | @pre The yy_preproc and yy_verilog_source_tree objects are in an unknown 45 | state 46 | @post The yy_preproc and yy_verilog_source_tree objects are not NULL, and 47 | are certain to be either new or existing contexts ready for parsing. 48 | @note Calling this function, parsing a file, and then calling this function 49 | again, does *not* destroy the original preprocessor context or source tree. 50 | */ 51 | void verilog_parser_init(); 52 | 53 | /*! 54 | @brief Perform a parsing operation on the supplied file. 55 | @details Parses the supplied file object, adding any parsed constructs to 56 | the existing yy_verilog_source_tree object, and using the existing 57 | yy_preproc preprocessor context. 58 | @param [in] to_parse - The open file object to be parsed. 59 | @pre yy_init has been called atleast once, and to_parse is an open and 60 | valid file to be read. 61 | @post Any valid verilog constructs have been added to the 62 | yy_verilog_source_tree global object. 63 | @returns An integer describing the result of the parse operation. If 64 | the return value is a zero, the file was parsed successfully. If it takes 65 | any other value, the file parsed was syntactically invalid. 66 | @note In the event of an invalid file being parsed, then the 67 | yy_verilog_source_tree object will only contain upto, but not including, 68 | the most recently valid parsed object. For example, when the following 69 | source is parsed: 70 | 71 | module valid_module(); 72 | initial begin 73 | $display("This module is valid"); 74 | end 75 | endmodule 76 | 77 | module invalid_module(); 78 | initial begin 79 | $display("This module is syntactically invalid"); 80 | endmodule 81 | 82 | then the first "valid_module" object will be added to the source tree, but 83 | the second will not. 84 | */ 85 | int verilog_parse_file(FILE * to_parse); 86 | 87 | /*! 88 | @brief Perform a parsing operation on the supplied in-memory string. 89 | @details Parses the supplied string, reading at most "length" bytes, adding 90 | any parsed constructs to the existing yy_verilog_source_tree object, and using 91 | the existing yy_preproc preprocessor context. 92 | @param [in] to_parse - The string to be parsed. 93 | @param [in] length - How many characters of to_parse to process. 94 | @pre yy_init has been called atleast once, and to_parse is an accessible 95 | array of characters. 96 | @post Any valid verilog constructs have been added to the 97 | yy_verilog_source_tree global object. 98 | @returns An integer describing the result of the parse operation. If 99 | the return value is a zero, the file was parsed successfully. If it takes 100 | any other value, the file parsed was syntactically invalid. 101 | @warning This function will create a copy of to_parse, and so is not destructive 102 | to the originally passed variable. If you would rather not create a copy, 103 | then use the verilog_parse_buffer function. 104 | @note In the event of an invalid file being parsed, then the 105 | yy_verilog_source_tree object will only contain upto, but not including, 106 | the most recently valid parsed object. For example, when the following 107 | source is parsed: 108 | 109 | module valid_module(); 110 | initial begin 111 | $display("This module is valid"); 112 | end 113 | endmodule 114 | 115 | module invalid_module(); 116 | initial begin 117 | $display("This module is syntactically invalid"); 118 | endmodule 119 | 120 | then the first "valid_module" object will be added to the source tree, but 121 | the second will not. 122 | */ 123 | int verilog_parse_string(char * to_parse, int length); 124 | 125 | 126 | /*! 127 | @brief Perform a parsing operation on the supplied in-memory string. 128 | @details Parses the supplied string, reading at most "length" bytes, adding 129 | any parsed constructs to the existing yy_verilog_source_tree object, and using 130 | the existing yy_preproc preprocessor context. 131 | @param [in] to_parse - The string to be parsed. 132 | @param [in] length - How many characters of to_parse to process. 133 | @pre yy_init has been called atleast once, and to_parse is an accessible 134 | array of characters. 135 | @post Any valid verilog constructs have been added to the 136 | yy_verilog_source_tree global object. 137 | @returns An integer describing the result of the parse operation. If 138 | the return value is a zero, the file was parsed successfully. If it takes 139 | any other value, the file parsed was syntactically invalid. 140 | @warning This function does not create a copy of the to_parse data, and will 141 | destroy the contents of the buffer. If you would rather the function operate 142 | on a copy of the data instead, please use the verilog_parse_string function. 143 | @note In the event of an invalid file being parsed, then the 144 | yy_verilog_source_tree object will only contain upto, but not including, 145 | the most recently valid parsed object. For example, when the following 146 | source is parsed: 147 | 148 | module valid_module(); 149 | initial begin 150 | $display("This module is valid"); 151 | end 152 | endmodule 153 | 154 | module invalid_module(); 155 | initial begin 156 | $display("This module is syntactically invalid"); 157 | endmodule 158 | 159 | then the first "valid_module" object will be added to the source tree, but 160 | the second will not. 161 | */ 162 | int verilog_parse_buffer(char * to_parse, int length); 163 | 164 | /*! }@ */ 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /src/verilog_parser_wrapper.c: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | @file verilog_parser_wrapper.c 4 | @brief Contains implementations of functions declared in verilog_parser.h 5 | */ 6 | 7 | #include "verilog_ast.h" 8 | #include "verilog_parser.h" 9 | 10 | //! This is defined in the generated bison parser code. 11 | extern int yyparse(); 12 | 13 | void verilog_parser_init() 14 | { 15 | yy_preproc = verilog_new_preprocessor_context(); 16 | yy_verilog_source_tree = verilog_new_source_tree(); 17 | } 18 | 19 | /*! 20 | @brief Perform a parsing operation on the currently selected buffer. 21 | */ 22 | int verilog_parse_file(FILE * to_parse) 23 | { 24 | YY_BUFFER_STATE new_buffer = yy_create_buffer(to_parse, YY_BUF_SIZE); 25 | yy_switch_to_buffer(new_buffer); 26 | yylineno = 0; // Reset the global line counter, we are in a new file! 27 | 28 | int result = yyparse(); 29 | return result; 30 | } 31 | 32 | /*! 33 | @brief Perform a parsing operation on the supplied in-memory string. 34 | */ 35 | int verilog_parse_string(char * to_parse, int length) 36 | { 37 | YY_BUFFER_STATE new_buffer = yy_scan_bytes(to_parse, length); 38 | yy_switch_to_buffer(new_buffer); 39 | 40 | int result = yyparse(); 41 | return result; 42 | } 43 | 44 | 45 | /*! 46 | @brief Perform a parsing operation on the supplied in-memory string. 47 | */ 48 | int verilog_parse_buffer(char * to_parse, int length) 49 | { 50 | YY_BUFFER_STATE new_buffer = yy_scan_buffer(to_parse, length); 51 | yy_switch_to_buffer(new_buffer); 52 | 53 | int result = yyparse(); 54 | return result; 55 | } 56 | -------------------------------------------------------------------------------- /src/verilog_preprocessor.c: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog_preprocessor.c 3 | @brief Contains function implementations to support source code preprocessing. 4 | */ 5 | 6 | #include "verilog_preprocessor.h" 7 | 8 | verilog_preprocessor_context * verilog_new_preprocessor_context() 9 | { 10 | verilog_preprocessor_context * tr = 11 | ast_calloc(1,sizeof(verilog_preprocessor_context)); 12 | 13 | tr -> token_count = 0; 14 | tr -> in_cell_define = AST_FALSE; 15 | tr -> emit = AST_TRUE; 16 | 17 | tr -> current_file = ast_stack_new(); 18 | tr -> includes = ast_list_new(); 19 | tr -> net_types = ast_list_new(); 20 | tr -> unconnected_drive_pull = STRENGTH_NONE; 21 | tr -> macrodefines = ast_hashtable_new(); 22 | tr -> ifdefs = ast_stack_new(); 23 | tr -> search_dirs = ast_list_new(); 24 | 25 | // By default, search CWD for include files. 26 | ast_list_append(tr -> search_dirs,"./"); 27 | 28 | return tr; 29 | } 30 | 31 | 32 | /*! 33 | @brief Clears the stack of files being parsed, and sets the current file to 34 | the supplied string. 35 | @param [inout] preproc - The context who's file name is being set. 36 | @param [in] file - The file path to put as the current file. 37 | */ 38 | void verilog_preprocessor_set_file( 39 | verilog_preprocessor_context * preproc, 40 | char * file 41 | ){ 42 | while(ast_stack_peek(preproc -> current_file) != NULL) 43 | { 44 | ast_stack_pop(preproc -> current_file); 45 | } 46 | ast_stack_push(preproc -> current_file, file); 47 | } 48 | 49 | /*! 50 | @brief Returns the file currently being parsed by the context, or NULL 51 | @param [in] preproc - The context to get the current file for. 52 | */ 53 | char * verilog_preprocessor_current_file( 54 | verilog_preprocessor_context * preproc 55 | ){ 56 | return ast_stack_peek(preproc -> current_file); 57 | } 58 | 59 | 60 | void verilog_free_preprocessor_context(verilog_preprocessor_context * tofree) 61 | { 62 | printf("ERROR: Function not implemented. preprocessor context at %p not freed.\n", tofree); 63 | } 64 | 65 | void verilog_preproc_enter_cell_define() 66 | { 67 | yy_preproc -> in_cell_define = AST_FALSE; 68 | } 69 | 70 | void verilog_preproc_exit_cell_define() 71 | { 72 | yy_preproc -> in_cell_define = AST_FALSE; 73 | } 74 | 75 | //! Creates and returns a new default net type directive. 76 | verilog_default_net_type * verilog_new_default_net_type( 77 | unsigned int token_number, //!< Token number of the directive. 78 | unsigned int line_number, //!< Line number of the directive. 79 | ast_net_type type //!< The net type. 80 | ){ 81 | verilog_default_net_type * tr = 82 | ast_calloc(1,sizeof(verilog_default_net_type)); 83 | 84 | tr -> token_number = token_number; 85 | tr -> line_number = line_number; 86 | tr -> type = type; 87 | 88 | return tr; 89 | } 90 | 91 | /*! 92 | @brief Registers a new default net type directive. 93 | @details Adds a record of the directive to the end of the linked list 94 | "net_types" in the global yy_preproc. 95 | */ 96 | void verilog_preproc_default_net( 97 | unsigned int token_number, //!< Token number of the directive. 98 | unsigned int line_number, //!< Line number of the directive. 99 | ast_net_type type //!< The net type. 100 | ){ 101 | verilog_default_net_type * directive = verilog_new_default_net_type( 102 | token_number, 103 | line_number, 104 | type 105 | ); 106 | 107 | ast_list_append(yy_preproc -> net_types, directive); 108 | } 109 | 110 | 111 | /*! 112 | @brief Handles the encounter of a `resetall directive as described in annex 113 | 19.6 of the spec. 114 | */ 115 | void verilog_preprocessor_resetall() 116 | { 117 | return; 118 | } 119 | 120 | 121 | /*! 122 | @brief Handles the entering of a no-unconnected drive directive. 123 | */ 124 | void verilog_preprocessor_nounconnected_drive( 125 | ast_primitive_strength direction 126 | ){ 127 | assert(direction == STRENGTH_PULL1 || 128 | direction == STRENGTH_PULL0 || 129 | direction == STRENGTH_NONE); 130 | 131 | yy_preproc -> unconnected_drive_pull = direction; 132 | } 133 | 134 | 135 | /*! 136 | @brief Handles the encounter of an include directive. 137 | @returns A pointer to the newly created directive reference. 138 | */ 139 | verilog_include_directive * verilog_preprocessor_include( 140 | char * filename, 141 | unsigned int lineNumber 142 | ){ 143 | verilog_include_directive * toadd = 144 | ast_calloc(1,sizeof(verilog_include_directive)); 145 | 146 | filename = filename + 1; // Remove leading quote mark. 147 | size_t length = strlen(filename); 148 | 149 | toadd -> filename = ast_strdup(filename); 150 | toadd -> filename[length-1] = '\0'; 151 | toadd -> lineNumber = lineNumber; 152 | 153 | ast_list_append(yy_preproc -> includes, toadd); 154 | 155 | // Search the possible include paths to find a match. 156 | unsigned int d = 0; 157 | for(d = 0; d < yy_preproc -> search_dirs -> items; d ++) 158 | { 159 | char * dir = ast_list_get(yy_preproc -> search_dirs, d); 160 | size_t dirlen = strlen(dir)+1; 161 | size_t namelen = strlen(toadd -> filename); 162 | char * full_name = ast_calloc(dirlen+namelen, sizeof(char)); 163 | 164 | strcat(full_name, dir); 165 | strcat(full_name, toadd -> filename); 166 | 167 | FILE * handle = fopen(full_name,"r"); 168 | if(handle) 169 | { 170 | fclose(handle); 171 | toadd -> filename = full_name; 172 | toadd -> file_found = AST_TRUE; 173 | 174 | // Since we are diving into an include file, update the stack of 175 | // files currently being parsed. 176 | ast_stack_push(yy_preproc -> current_file, filename); 177 | 178 | break; 179 | } 180 | else 181 | { 182 | toadd -> file_found = AST_FALSE; 183 | } 184 | } 185 | 186 | return toadd; 187 | } 188 | 189 | /* 190 | @brief Instructs the preprocessor to register a new macro definition. 191 | */ 192 | void verilog_preprocessor_macro_define( 193 | unsigned int line, //!< The line the defininition comes from. 194 | char * macro_name, //!< The macro identifier. 195 | char * macro_text, //!< The value the macro expands to. 196 | size_t text_len //!< Length in bytes of macro_text. 197 | ){ 198 | verilog_macro_directive * toadd = 199 | ast_calloc(1, sizeof(verilog_macro_directive)); 200 | 201 | toadd -> line = line; 202 | 203 | //printf("\nEncountered macro '%s' on line %d ",toadd->macro_id,line); 204 | //printf("with value '%s'\n", toadd -> macro_value); 205 | //fflush(stdout); 206 | 207 | // Make space for, and duplicate, the macro text, into the thing 208 | // we will put into the hashtable. 209 | toadd -> macro_id = ast_strdup(macro_name); 210 | 211 | if(text_len > 0){ 212 | // Make sure we exclude all comments from the macro text. 213 | unsigned int i = 0; 214 | for(i = 0; i < text_len-1; i++) 215 | { 216 | if(macro_text[i] == '/' && 217 | macro_text[i+1] == '/') 218 | { 219 | text_len = (size_t)i; 220 | break; 221 | } 222 | } 223 | 224 | toadd -> macro_value = ast_strdup(macro_text); 225 | } else { 226 | toadd -> macro_value = ""; 227 | } 228 | 229 | //printf("MACRO: '%s' - '%s'\n", toadd -> macro_id, toadd -> macro_value); 230 | 231 | // Set source file of the macro 232 | char * current_file = verilog_preprocessor_current_file(yy_preproc); 233 | toadd -> src_file = ast_strdup(current_file); 234 | 235 | ast_hashtable_insert( 236 | yy_preproc -> macrodefines, 237 | toadd -> macro_id, 238 | toadd 239 | ); 240 | 241 | return; 242 | } 243 | 244 | /*! 245 | @brief Removes a macro definition from the preprocessors lookup table. 246 | */ 247 | void verilog_preprocessor_macro_undefine( 248 | char * macro_name //!< The name of the macro to remove. 249 | ){ 250 | 251 | ast_hashtable_delete( 252 | yy_preproc -> macrodefines, 253 | macro_name 254 | ); 255 | //printf("Removed Macro definition: '%s'\n", macro_name); 256 | return; 257 | } 258 | 259 | //! Creates and returns a new conditional context. 260 | verilog_preprocessor_conditional_context * 261 | verilog_preprocessor_new_conditional_context( 262 | char * condition, //!< The definition to check for. 263 | int line_number //!< Where the `ifdef came from. 264 | ){ 265 | verilog_preprocessor_conditional_context * tr = 266 | ast_calloc(1,sizeof(verilog_preprocessor_conditional_context)); 267 | 268 | tr -> line_number = line_number; 269 | tr -> condition = condition; 270 | 271 | return tr; 272 | } 273 | 274 | 275 | /*! 276 | @brief Handles an ifdef statement being encountered. 277 | @param [in] macro_name - The macro to test if defined or not. 278 | */ 279 | void verilog_preprocessor_ifdef ( 280 | char * macro_name, 281 | unsigned int lineno, 282 | ast_boolean is_ndef 283 | ){ 284 | // Create a new ifdef context. 285 | verilog_preprocessor_conditional_context * topush = 286 | verilog_preprocessor_new_conditional_context(macro_name,lineno); 287 | 288 | topush -> is_ndef = is_ndef; 289 | 290 | void * data; 291 | ast_hashtable_result r = ast_hashtable_get(yy_preproc -> macrodefines, 292 | macro_name, &data); 293 | 294 | //printf("Compilation conditional on '%s' ",macro_name); 295 | 296 | if(((r == HASH_SUCCESS && is_ndef == AST_FALSE) || 297 | (r == HASH_KEY_NOT_FOUND && is_ndef == AST_TRUE )) && 298 | yy_preproc -> emit == AST_FALSE) 299 | { 300 | // Push the context, with the condition true. 301 | topush -> condition_passed = AST_TRUE; 302 | topush -> wait_for_endif = AST_TRUE; 303 | yy_preproc -> emit = AST_TRUE; 304 | ast_stack_push(yy_preproc -> ifdefs, topush); 305 | //printf("Condition TRUE\n"); 306 | } 307 | else 308 | { 309 | // Push the context, with the condition false. 310 | topush -> condition_passed = AST_FALSE; 311 | if(yy_preproc -> emit == AST_FALSE) 312 | topush -> wait_for_endif = AST_TRUE; 313 | else 314 | topush -> wait_for_endif = AST_FALSE; 315 | yy_preproc -> emit = AST_FALSE; 316 | ast_stack_push(yy_preproc -> ifdefs, topush); 317 | //printf("Condition FALSE\n"); 318 | } 319 | } 320 | 321 | /*! 322 | @brief Handles an elseif statement being encountered. 323 | @param [in] macro_name - The macro to test if defined or not. 324 | */ 325 | void verilog_preprocessor_elseif(char * macro_name, unsigned int lineno) 326 | { 327 | verilog_preprocessor_conditional_context * tocheck = 328 | ast_stack_peek(yy_preproc -> ifdefs); 329 | 330 | if(tocheck == NULL) 331 | { 332 | printf("ERROR - `elseif without preceding `ifdef or `ifndef on line \ 333 | %d\n\tExpect it all to go wrong from here.\n", lineno); 334 | return; 335 | } 336 | 337 | void * data; 338 | ast_hashtable_result r = ast_hashtable_get(yy_preproc -> macrodefines, 339 | macro_name, &data); 340 | 341 | if(tocheck -> wait_for_endif == AST_FALSE && 342 | yy_preproc -> emit == AST_TRUE) 343 | { 344 | if((tocheck -> is_ndef == AST_TRUE && r == HASH_KEY_NOT_FOUND) || 345 | (tocheck -> is_ndef == AST_FALSE && r == HASH_SUCCESS )) 346 | { 347 | tocheck -> condition_passed = AST_TRUE; 348 | tocheck -> wait_for_endif = AST_TRUE; 349 | yy_preproc -> emit = AST_TRUE; 350 | } 351 | else 352 | { 353 | yy_preproc -> emit = AST_FALSE; 354 | tocheck -> condition_passed = AST_FALSE; 355 | } 356 | } 357 | else 358 | { 359 | yy_preproc -> emit = AST_FALSE; 360 | tocheck -> condition_passed = AST_FALSE; 361 | } 362 | } 363 | 364 | /*! 365 | @brief Handles an else statement being encountered. 366 | */ 367 | void verilog_preprocessor_else (unsigned int lineno) 368 | { 369 | verilog_preprocessor_conditional_context * tocheck = 370 | ast_stack_peek(yy_preproc -> ifdefs); 371 | 372 | verilog_preprocessor_conditional_context * parent = 373 | ast_stack_peek2(yy_preproc -> ifdefs); 374 | 375 | if(tocheck == NULL) 376 | { 377 | printf("ERROR - `else without preceding `ifdef or `ifndef on line \ 378 | %d\n\tExpect it all to go wrong from here.\n", lineno); 379 | return; 380 | } 381 | 382 | if(yy_preproc -> emit == AST_TRUE && 383 | tocheck -> wait_for_endif == AST_FALSE) 384 | { 385 | yy_preproc -> emit = AST_FALSE; 386 | tocheck -> condition_passed = AST_FALSE; 387 | } 388 | else 389 | { 390 | if(parent != NULL) 391 | { 392 | if(parent -> condition_passed == AST_TRUE) 393 | { 394 | yy_preproc -> emit = AST_TRUE; 395 | tocheck -> condition_passed = AST_TRUE; 396 | } 397 | else 398 | { 399 | yy_preproc -> emit = AST_FALSE; 400 | tocheck -> condition_passed = AST_FALSE; 401 | } 402 | } 403 | else 404 | { 405 | yy_preproc -> emit = AST_TRUE; 406 | tocheck -> condition_passed = AST_TRUE; 407 | } 408 | } 409 | 410 | tocheck -> wait_for_endif = AST_TRUE; 411 | } 412 | 413 | /*! 414 | @brief Handles an else statement being encountered. 415 | */ 416 | void verilog_preprocessor_endif (unsigned int lineno) 417 | { 418 | verilog_preprocessor_conditional_context * tocheck = 419 | ast_stack_pop(yy_preproc -> ifdefs); 420 | 421 | if(tocheck == NULL) 422 | { 423 | printf("ERROR - `endif without preceding `ifdef or `ifndef on line \ 424 | %d\n\tExpect it all to go wrong from here.\n", lineno); 425 | return; 426 | } 427 | 428 | tocheck = ast_stack_peek(yy_preproc -> ifdefs); 429 | 430 | if(tocheck == NULL) 431 | yy_preproc -> emit = AST_TRUE; 432 | else 433 | yy_preproc -> emit = tocheck -> condition_passed; 434 | } 435 | 436 | 437 | 438 | -------------------------------------------------------------------------------- /src/verilog_preprocessor.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @file verilog_preprocessor.h 3 | @brief Contains function and data structures to support source code 4 | preprocessing. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "verilog_ast.h" 12 | #include "verilog_ast_common.h" 13 | 14 | #ifndef VERILOG_PREPROCESSOR_H 15 | #define VERILOG_PREPROCESSOR_H 16 | 17 | /*! 18 | @defgroup verilog-preprocessor Preprocessor 19 | @{ 20 | @brief This module contains all code and information on the preprocessor and 21 | how it works / is implemented. 22 | 23 | @details 24 | 25 | The preprocessor is implemented mostly as part of the lexer, with the 26 | various compiler directives handled within the verilog_preprocessor_context 27 | structure and it's associated functions. 28 | 29 | */ 30 | 31 | // ----------------------- Default Net Type Directives ------------------ 32 | 33 | /*! 34 | @brief Keeps track of the points at which default net type directives are 35 | encountered. 36 | */ 37 | typedef struct verilog_default_net_type_t{ 38 | unsigned int token_number; //!< Token number of the directive. 39 | unsigned int line_number; //!< Line number of the directive. 40 | ast_net_type type; //!< The net type. 41 | } verilog_default_net_type; 42 | 43 | //! Creates and returns a new default net type directive. 44 | verilog_default_net_type * verilog_new_default_net_type( 45 | unsigned int token_number, //!< Token number of the directive. 46 | unsigned int line_number, //!< Line number of the directive. 47 | ast_net_type type //!< The net type. 48 | ); 49 | 50 | // ----------------------- Line Directives ------------------------------ 51 | 52 | //! Describes a line directive. 53 | typedef struct verilog_line_directive_t{ 54 | unsigned int line; //!< The line to set the current counter to. 55 | char * file; //!< The file we should pretend stuff comes from. 56 | unsigned char level; //!< Level of include depth. 57 | } verilog_line_directive; 58 | 59 | // ----------------------- Timescale Directives ------------------------- 60 | 61 | //! Describes a simulation timescale directive. 62 | typedef struct verilog_timescale_directive_t{ 63 | char * scale; //!< The timescale to simulate on. 64 | char * precision; //!< Precision of each timestep. 65 | } verilog_timescale_directive; 66 | 67 | // ----------------------- resetall directives -------------------------- 68 | 69 | /*! 70 | @brief Handles the encounter of a `resetall directive as described in annex 71 | 19.6 of the spec. 72 | */ 73 | void verilog_preprocessor_resetall(); 74 | 75 | // ----------------------- Connected Drive Directives ------------------- 76 | 77 | /*! 78 | @brief Handles the entering of a no-unconnected drive directive. 79 | @param [in] direction - Where should an unconnected line be pulled? 80 | */ 81 | void verilog_preprocessor_nounconnected_drive( 82 | ast_primitive_strength direction 83 | ); 84 | 85 | // ----------------------- Include Directives --------------------------- 86 | 87 | //! Stores information on an include directive. 88 | typedef struct verilog_include_directive_t{ 89 | char * filename; //!< The file to include. 90 | unsigned int lineNumber; //!< The line number of the directive. 91 | ast_boolean file_found; //!< Can we find the file? 92 | } verilog_include_directive; 93 | 94 | /*! 95 | @brief Handles the encounter of an include directive. 96 | @returns A pointer to the newly created directive reference. 97 | */ 98 | verilog_include_directive * verilog_preprocessor_include( 99 | char * filename, // token_count ++; \ 11 | if(yy_preproc -> emit) { \ 12 | return x; \ 13 | } 14 | %} 15 | 16 | %option yylineno 17 | %option nodefault 18 | %option noyywrap 19 | 20 | /* Pre-processor definitions */ 21 | CD_DEFAULT_NETTYPE "`default_nettype" 22 | %x in_default_nettype 23 | 24 | CD_LINE "`line" 25 | %x in_line_1 26 | %x in_line_2 27 | %x in_line_3 28 | %x in_line_4 29 | 30 | CD_CELLDEFINE "`celldefine" 31 | CD_DEFINE "`define" 32 | CD_RESETALL "`resetall" 33 | CD_ENDCELLDEFINE "`endcelldefine" 34 | 35 | CD_ELSE "`else" 36 | CD_ELSIF "`elsif" 37 | CD_ENDIF "`endif" 38 | CD_IFDEF "`ifdef" 39 | CD_IFNDEF "`ifndef" 40 | 41 | %x in_ifdef 42 | %x in_ifndef 43 | %x in_elseif 44 | 45 | CD_UNDEF "`undef" 46 | 47 | %x in_undef 48 | 49 | CD_NOUNCONNECTED_DRIVE "`nounconnected_drive" 50 | CD_UNCONNECTED_DRIVE "`unconnected_drive" 51 | 52 | %x in_unconnected_drive 53 | 54 | /* Include Directives */ 55 | 56 | CD_INCLUDE "`include" 57 | 58 | %x in_include 59 | 60 | /* Times and compiler directives */ 61 | 62 | CD_TIMESCALE "`timescale" 63 | TIME_UNITS "(s|ms|us|ns|ps|fs)" 64 | %x in_ts_1 65 | %x in_ts_2 66 | %x in_ts_3 67 | 68 | /* Keyword Token deffinitions. */ 69 | ALWAYS "always" 70 | AND "and" 71 | ASSIGN "assign" 72 | AUTOMATIC "automatic" 73 | BEGIN "begin" 74 | BUF "buf" 75 | BUFIF0 "bufif0" 76 | BUFIF1 "bufif1" 77 | CASE "case" 78 | CASEX "casex" 79 | CASEZ "casez" 80 | CELL "cell" 81 | CMOS "cmos" 82 | CONFIG "config" 83 | DEASSIGN "deassign" 84 | DEFAULT "default" 85 | DEFPARAM "defparam" 86 | DESIGN "design" 87 | DISABLE "disable" 88 | EDGE "edge" 89 | ELSE "else" 90 | END "end" 91 | ENDCASE "endcase" 92 | ENDCONFIG "endconfig" 93 | ENDFUNCTION "endfunction" 94 | ENDGENERATE "endgenerate" 95 | ENDMODULE "endmodule" 96 | ENDPRIMITIVE "endprimitive" 97 | ENDSPECIFY "endspecify" 98 | ENDTABLE "endtable" 99 | ENDTASK "endtask" 100 | EVENT "event" 101 | FOR "for" 102 | FORCE "force" 103 | FOREVER "forever" 104 | FORK "fork" 105 | FUNCTION "function" 106 | GENERATE "generate" 107 | GENVAR "genvar" 108 | HIGHZ0 "highz0" 109 | HIGHZ1 "highz1" 110 | IF "if" 111 | IFNONE "ifnone" 112 | INCDIR "-incdir" 113 | INCLUDE "include" 114 | INITIAL "initial" 115 | INOUT "inout" 116 | INPUT "input" 117 | INSTANCE "instance" 118 | INTEGER "integer" 119 | JOIN "join" 120 | LARGE "large" 121 | LIBLIST "liblist" 122 | LIBRARY "library" 123 | LOCALPARAM "localparam" 124 | MACROMODULE "macromodule" 125 | MEDIUM "medium" 126 | MODULE "module" 127 | NAND "nand" 128 | NEGEDGE "negedge" 129 | NMOS "nmos" 130 | NOR "nor" 131 | NOSHOWCANCELLED "noshowcancelled" 132 | NOT "not" 133 | NOTIF0 "notif0" 134 | NOTIF1 "notif1" 135 | OR "or" 136 | OUTPUT "output" 137 | PARAMETER "parameter" 138 | PMOS "pmos" 139 | POSEDGE "posedge" 140 | PRIMITIVE "primitive" 141 | PULL0 "pull0" 142 | PULL1 "pull1" 143 | PULLDOWN "pulldown" 144 | PULLUP "pullup" 145 | PULSESTYLE_ONEVENT "pulsestyle_onevent" 146 | PULSESTYLE_ONDETECT "pulsestyle_ondetect" 147 | RCMOS "rcmos" 148 | REAL "real" 149 | REALTIME "realtime" 150 | REG "reg" 151 | RELEASE "release" 152 | REPEAT "repeat" 153 | RNMOS "rnmos" 154 | RPMOS "rpmos" 155 | RTRAN "rtran" 156 | RTRANIF0 "rtranif0" 157 | RTRANIF1 "rtranif1" 158 | SCALARED "scalared" 159 | SHOWCANCELLED "showcancelled" 160 | SIGNED "signed" 161 | SMALL "small" 162 | SPECIFY "specify" 163 | SPECPARAM "specparam" 164 | STRONG0 "strong0" 165 | STRONG1 "strong1" 166 | SUPPLY0 "supply0" 167 | SUPPLY1 "supply1" 168 | TABLE "table" 169 | TASK "task" 170 | TIME "time" 171 | TRAN "tran" 172 | TRANIF0 "tranif0" 173 | TRANIF1 "tranif1" 174 | TRI0 "tri0" 175 | TRI1 "tri1" 176 | TRI "tri" 177 | TRIAND "triand" 178 | TRIOR "trior" 179 | TRIREG "trireg" 180 | UNSIGNED "unsigned" 181 | USE "use" 182 | VECTORED "vectored" 183 | WAIT "wait" 184 | WAND "wand" 185 | WEAK0 "weak0" 186 | WEAK1 "weak1" 187 | WHILE "while" 188 | WIRE "wire" 189 | WOR "wor" 190 | XNOR "xnor" 191 | XOR "xor" 192 | 193 | /* Single character tokens */ 194 | 195 | NEWLINE "\n"|"\r\n" 196 | SPACE " " 197 | TAB "\t" 198 | 199 | AT "@" 200 | COMMA "," 201 | HASH "#" 202 | DOT "." 203 | EQ "=" 204 | COLON ":" 205 | IDX_PRT_SEL "+:"|"-:" 206 | SEMICOLON ";" 207 | OPEN_BRACKET "\(" 208 | CLOSE_BRACKET "\)" 209 | OPEN_SQ_BRACKET "\[" 210 | CLOSE_SQ_BRACKET "\]" 211 | OPEN_SQ_BRACE "{" 212 | CLOSE_SQ_BRACE "}" 213 | 214 | 215 | /* Tokens related to numbers */ 216 | 217 | EXP "e"|"E" 218 | UNDERSCORE "_" 219 | SIGN {PLUS}|{MINUS} 220 | X "x"|"X" 221 | Z "z"|"Z"|"?" 222 | 223 | DIGIT_DECIMAL [0-9] 224 | DIGIT_DECMIAL_NZ [1-9] 225 | DIGIT_BINARY [0-1]|{X}|{Z} 226 | DIGIT_OCTAL [0-7]|{X}|{Z} 227 | DIGIT_HEX [0-9a-fA-F]|{X}|{Z} 228 | 229 | BASE_DECIMAL '[sS]?[dD] 230 | BASE_BINARY '[sS]?[bB] 231 | BASE_OCTAL '[sS]?[oO] 232 | BASE_HEX '[sS]?[hH] 233 | 234 | NUM_REAL_EXP {NUM_UNSIGNED}({DOT}{NUM_UNSIGNED})?{EXP}({SIGN})?{NUM_UNSIGNED} 235 | 236 | BIN_VALUE {DIGIT_BINARY}({UNDERSCORE}|{DIGIT_BINARY})* 237 | OCT_VALUE {DIGIT_OCTAL}({UNDERSCORE}|{DIGIT_OCTAL})* 238 | HEX_VALUE {DIGIT_HEX}({UNDERSCORE}|{DIGIT_HEX})* 239 | 240 | %x in_hex_val 241 | %x in_oct_val 242 | %x in_bin_val 243 | %s in_number 244 | 245 | NUM_REAL {NUM_UNSIGNED}{DOT}{NUM_UNSIGNED}|{NUM_REAL_EXP} 246 | NUM_UNSIGNED {DIGIT_DECIMAL}({UNDERSCORE}|{DIGIT_DECIMAL})* 247 | 248 | /* Identifiers */ 249 | 250 | SYSTEM_ID \$[a-zA-Z0-9_\$]+ 251 | SIMPLE_ID [a-zA-Z_][a-zA-Z0-9_$]* 252 | ESCAPED_ID \\{SIMPLE_ID} 253 | MACRO_IDENTIFIER `{SIMPLE_ID} 254 | 255 | MACRO_TEXT .*\n 256 | 257 | %x in_define 258 | %x in_define_t 259 | 260 | /* Attributes */ 261 | 262 | ATTRIBUTE_START \(\* 263 | ATTRIBUTE_END \*\) 264 | 265 | /* Comments */ 266 | COMMENT_LINE "//".*\n 267 | 268 | COMMENT_BEGIN "/*" 269 | COMMENT_END "*/" 270 | 271 | %x in_comment 272 | 273 | /* Strings */ 274 | 275 | STRING \".*\" 276 | 277 | /* Operators */ 278 | 279 | STAR "\*" 280 | PLUS "+" 281 | MINUS "-" 282 | ASL "<<<" 283 | ASR ">>>" 284 | LSL "<<" 285 | LSR ">>" 286 | DIV "/" 287 | POW "**" 288 | MOD "%" 289 | GTE ">=" 290 | LTE "<=" 291 | GT ">" 292 | LT "<" 293 | L_NEG "!" 294 | L_AND "&&" 295 | L_OR "||" 296 | C_EQ "===" 297 | L_EQ "==" 298 | C_NEQ "!==" 299 | L_NEQ "!=" 300 | B_NEG "~" 301 | B_AND "&" 302 | B_OR "|" 303 | B_XOR "^" 304 | B_EQU "^~"|"~^" 305 | B_NAND "~&" 306 | B_NOR "~|" 307 | TERNARY "?" 308 | 309 | %% 310 | {ATTRIBUTE_START} {EMIT_TOKEN(ATTRIBUTE_START);} 311 | {ATTRIBUTE_END} {EMIT_TOKEN(ATTRIBUTE_END);} 312 | 313 | {COMMENT_LINE} {/*EMIT_TOKEN(COMMENT_LINE); IGNORE */} 314 | {COMMENT_BEGIN} {BEGIN(in_comment); ;} 315 | 316 | .|\n {/* IGNORE */} 317 | {COMMENT_END} {BEGIN(INITIAL); } 318 | 319 | {CD_CELLDEFINE} {verilog_preproc_enter_cell_define();} 320 | {CD_ENDCELLDEFINE} {verilog_preproc_exit_cell_define();} 321 | 322 | {CD_DEFAULT_NETTYPE} {BEGIN(in_default_nettype);} 323 | {TRIAND} { 324 | BEGIN(INITIAL); 325 | verilog_preproc_default_net(yy_preproc -> token_count, 326 | yylineno, NET_TYPE_TRIAND ); 327 | } 328 | {TRIOR} { 329 | BEGIN(INITIAL); 330 | verilog_preproc_default_net(yy_preproc -> token_count, 331 | yylineno, NET_TYPE_TRIOR ); 332 | } 333 | {TRIREG} { 334 | BEGIN(INITIAL); 335 | verilog_preproc_default_net(yy_preproc -> token_count, 336 | yylineno, NET_TYPE_TRIREG ); 337 | } 338 | {TRI0} { 339 | BEGIN(INITIAL); 340 | verilog_preproc_default_net(yy_preproc -> token_count, 341 | yylineno, NET_TYPE_TRI ); 342 | } 343 | {TRI} { 344 | BEGIN(INITIAL); 345 | verilog_preproc_default_net(yy_preproc -> token_count, 346 | yylineno, NET_TYPE_TRI ); 347 | } 348 | {WIRE} { 349 | BEGIN(INITIAL); 350 | verilog_preproc_default_net(yy_preproc -> token_count, 351 | yylineno, NET_TYPE_WIRE ); 352 | } 353 | {WAND} { 354 | BEGIN(INITIAL); 355 | verilog_preproc_default_net(yy_preproc -> token_count, 356 | yylineno, NET_TYPE_WAND ); 357 | } 358 | {WOR} { 359 | BEGIN(INITIAL); 360 | verilog_preproc_default_net(yy_preproc -> token_count, 361 | yylineno, NET_TYPE_WOR ); 362 | } 363 | 364 | {CD_TIMESCALE} { 365 | BEGIN(in_ts_1); 366 | } 367 | {NUM_UNSIGNED} { 368 | yy_preproc -> timescale.scale = yylval.string; 369 | } 370 | {SIMPLE_ID} { 371 | BEGIN(in_ts_2); 372 | } 373 | {DIV} { 374 | BEGIN(in_ts_3); 375 | } 376 | {NUM_UNSIGNED} { 377 | yy_preproc -> timescale.precision= yylval.string; 378 | } 379 | {SIMPLE_ID} { 380 | BEGIN(INITIAL); 381 | } 382 | 383 | {CD_RESETALL} { 384 | verilog_preprocessor_resetall(); 385 | } 386 | 387 | {CD_IFDEF} { 388 | BEGIN(in_ifdef); 389 | } 390 | {SIMPLE_ID} { 391 | verilog_preprocessor_ifdef(yytext,yylineno,AST_FALSE); 392 | BEGIN(INITIAL); 393 | } 394 | 395 | {CD_IFNDEF} { 396 | BEGIN(in_ifndef); 397 | } 398 | {SIMPLE_ID} { 399 | verilog_preprocessor_ifdef(yytext,yylineno,AST_TRUE); 400 | BEGIN(INITIAL); 401 | } 402 | 403 | {CD_ELSIF} { 404 | BEGIN(in_elseif); 405 | } 406 | {SIMPLE_ID} { 407 | verilog_preprocessor_elseif(yytext, yylineno); 408 | BEGIN(INITIAL); 409 | } 410 | 411 | {CD_ELSE} { 412 | verilog_preprocessor_else(yylineno); 413 | } 414 | 415 | {CD_ENDIF} { 416 | verilog_preprocessor_endif(yylineno); 417 | } 418 | 419 | {CD_INCLUDE} { 420 | BEGIN(in_include); 421 | } 422 | {STRING} { 423 | YY_BUFFER_STATE cur = YY_CURRENT_BUFFER; 424 | 425 | verilog_include_directive * id = 426 | verilog_preprocessor_include(yytext,yylineno); 427 | 428 | // Now, we need to look for the file, open it as a buffer, and then 429 | // switch to it. 430 | 431 | if(id -> file_found == AST_TRUE) 432 | { 433 | FILE * file = fopen(id -> filename, "r"); 434 | 435 | YY_BUFFER_STATE n = yy_create_buffer(file, YY_BUF_SIZE); 436 | 437 | cur -> yy_bs_lineno = yylineno; 438 | yy_switch_to_buffer(cur); 439 | yypush_buffer_state(n); 440 | BEGIN(INITIAL); 441 | } 442 | else 443 | { 444 | printf("ERROR - Could not find include file %s on line %d\n", 445 | id -> filename, id-> lineNumber); 446 | printf("\tExpect stuff to break now.\n"); 447 | } 448 | 449 | BEGIN(INITIAL); 450 | } 451 | 452 | {CD_LINE} {BEGIN(in_line_1);} 453 | {INTEGER} {BEGIN(in_line_2);} 454 | {NUM_UNSIGNED} {BEGIN(in_line_2);} 455 | {STRING} {BEGIN(in_line_3);} 456 | {INTEGER} {BEGIN(INITIAL);} 457 | {NUM_UNSIGNED} {BEGIN(INITIAL);} 458 | 459 | {CD_NOUNCONNECTED_DRIVE} { 460 | verilog_preprocessor_nounconnected_drive(STRENGTH_NONE); 461 | } 462 | {CD_UNCONNECTED_DRIVE} { 463 | BEGIN(in_unconnected_drive); 464 | } 465 | {PULL0} { 466 | verilog_preprocessor_nounconnected_drive(STRENGTH_PULL0); 467 | BEGIN(INITIAL); 468 | } 469 | {PULL1} { 470 | verilog_preprocessor_nounconnected_drive(STRENGTH_PULL1); 471 | BEGIN(INITIAL); 472 | } 473 | 474 | {CD_DEFINE} { 475 | BEGIN(in_define); 476 | } 477 | 478 | {SIMPLE_ID} { 479 | yy_preproc -> scratch = ast_strdup(yytext); 480 | BEGIN(in_define_t); 481 | } 482 | 483 | {MACRO_TEXT} { 484 | if(yyleng == 1) 485 | { 486 | // Macro has no value, and is just a newline character. 487 | verilog_preprocessor_macro_define( 488 | yylineno-1, 489 | yy_preproc -> scratch, 490 | NULL, 491 | 0); // -1 to avoid including the newline. 492 | } 493 | else 494 | { 495 | // Macro has a proper value. 496 | verilog_preprocessor_macro_define( 497 | yylineno-1, 498 | yy_preproc -> scratch, 499 | yytext+1, 500 | yyleng-2); // -1 to avoid including the newline. 501 | } 502 | BEGIN(INITIAL); 503 | } 504 | 505 | {CD_UNDEF} { 506 | BEGIN(in_undef); 507 | } 508 | 509 | {SIMPLE_ID} { 510 | verilog_preprocessor_macro_undefine( 511 | yytext 512 | ); 513 | BEGIN(INITIAL); 514 | } 515 | 516 | {MACRO_IDENTIFIER} { 517 | 518 | // Look for the macro entry. 519 | verilog_macro_directive * macro = NULL; 520 | char * macroName = (yytext)+1; 521 | ast_hashtable_result r = ast_hashtable_get(yy_preproc -> macrodefines, 522 | macroName, 523 | (void**)¯o); 524 | 525 | if(r == HASH_SUCCESS) 526 | { 527 | // Switch buffers to expand the macro. 528 | 529 | YY_BUFFER_STATE cur = YY_CURRENT_BUFFER; 530 | YY_BUFFER_STATE n = yy_scan_string(macro -> macro_value); 531 | 532 | // Set the "current file" to the one the macro was defined in. 533 | ast_stack_push(yy_preproc -> current_file, macro -> src_file); 534 | 535 | yy_switch_to_buffer(cur); 536 | yypush_buffer_state(n); 537 | } 538 | else 539 | { 540 | // Undefined macro - PANIC! 541 | //printf("ERROR: Undefined macro '%s' on line %d\n", yytext, yylineno); 542 | //printf("\tIt's probably all going to fall apart now...\n\n"); 543 | } 544 | } 545 | 546 | {AT} {EMIT_TOKEN(AT);} 547 | {COMMA} {EMIT_TOKEN(COMMA);} 548 | {HASH} {EMIT_TOKEN(HASH);} 549 | {DOT} {EMIT_TOKEN(DOT);} 550 | {EQ} {yylval.operator = OPERATOR_L_EQ; EMIT_TOKEN(EQ);} 551 | {COLON} {EMIT_TOKEN(COLON);} 552 | {IDX_PRT_SEL} {EMIT_TOKEN(IDX_PRT_SEL);} 553 | {SEMICOLON} {EMIT_TOKEN(SEMICOLON);} 554 | {OPEN_BRACKET} {EMIT_TOKEN(OPEN_BRACKET);} 555 | {CLOSE_BRACKET} {EMIT_TOKEN(CLOSE_BRACKET);} 556 | {OPEN_SQ_BRACKET} {EMIT_TOKEN(OPEN_SQ_BRACKET);} 557 | {CLOSE_SQ_BRACKET} {EMIT_TOKEN(CLOSE_SQ_BRACKET);} 558 | {OPEN_SQ_BRACE} {EMIT_TOKEN(OPEN_SQ_BRACE);} 559 | {CLOSE_SQ_BRACE} {EMIT_TOKEN(CLOSE_SQ_BRACE);} 560 | {STAR} {yylval.operator=OPERATOR_STAR ; EMIT_TOKEN(STAR);} 561 | {PLUS} {yylval.operator=OPERATOR_PLUS ; EMIT_TOKEN(PLUS);} 562 | {MINUS} {yylval.operator=OPERATOR_MINUS ; EMIT_TOKEN(MINUS);} 563 | {ASL} {yylval.operator=OPERATOR_ASL ; EMIT_TOKEN(ASL);} 564 | {ASR} {yylval.operator=OPERATOR_ASR ; EMIT_TOKEN(ASR);} 565 | {LSL} {yylval.operator=OPERATOR_LSL ; EMIT_TOKEN(LSL);} 566 | {LSR} {yylval.operator=OPERATOR_LSR ; EMIT_TOKEN(LSR);} 567 | {DIV} {yylval.operator=OPERATOR_DIV ; EMIT_TOKEN(DIV);} 568 | {POW} {yylval.operator=OPERATOR_POW ; EMIT_TOKEN(POW);} 569 | {MOD} {yylval.operator=OPERATOR_MOD ; EMIT_TOKEN(MOD);} 570 | {GTE} {yylval.operator=OPERATOR_GTE ; EMIT_TOKEN(GTE);} 571 | {LTE} {yylval.operator=OPERATOR_LTE ; EMIT_TOKEN(LTE);} 572 | {GT} {yylval.operator=OPERATOR_GT ; EMIT_TOKEN(GT);} 573 | {LT} {yylval.operator=OPERATOR_LT ; EMIT_TOKEN(LT);} 574 | {L_NEG} {yylval.operator=OPERATOR_L_NEG ; EMIT_TOKEN(L_NEG);} 575 | {L_AND} {yylval.operator=OPERATOR_L_AND ; EMIT_TOKEN(L_AND);} 576 | {L_OR} {yylval.operator=OPERATOR_L_OR ; EMIT_TOKEN(L_OR);} 577 | {C_EQ} {yylval.operator=OPERATOR_C_EQ ; EMIT_TOKEN(C_EQ);} 578 | {L_EQ} {yylval.operator=OPERATOR_L_EQ ; EMIT_TOKEN(L_EQ);} 579 | {C_NEQ} {yylval.operator=OPERATOR_C_NEQ ; EMIT_TOKEN(C_NEQ);} 580 | {L_NEQ} {yylval.operator=OPERATOR_L_NEQ ; EMIT_TOKEN(L_NEQ);} 581 | {B_NEG} {yylval.operator=OPERATOR_B_NEG ; EMIT_TOKEN(B_NEG);} 582 | {B_AND} {yylval.operator=OPERATOR_B_AND ; EMIT_TOKEN(B_AND);} 583 | {B_OR} {yylval.operator=OPERATOR_B_OR ; EMIT_TOKEN(B_OR);} 584 | {B_XOR} {yylval.operator=OPERATOR_B_XOR ; EMIT_TOKEN(B_XOR);} 585 | {B_EQU} {yylval.operator=OPERATOR_B_EQU ; EMIT_TOKEN(B_EQU);} 586 | {B_NAND} {yylval.operator=OPERATOR_B_NAND ; EMIT_TOKEN(B_NAND);} 587 | {B_NOR} {yylval.operator=OPERATOR_B_NOR ; EMIT_TOKEN(B_NOR);} 588 | {TERNARY} {yylval.operator=OPERATOR_TERNARY; EMIT_TOKEN(TERNARY);} 589 | 590 | {BASE_DECIMAL} {EMIT_TOKEN(DEC_BASE);} 591 | {BASE_HEX} {BEGIN(in_hex_val); EMIT_TOKEN(HEX_BASE);} 592 | {BASE_OCTAL} {BEGIN(in_oct_val); EMIT_TOKEN(OCT_BASE);} 593 | {BASE_BINARY} {BEGIN(in_bin_val); EMIT_TOKEN(BIN_BASE);} 594 | 595 | {BIN_VALUE} {BEGIN(INITIAL); yylval.string = yytext; EMIT_TOKEN(BIN_VALUE);} 596 | {OCT_VALUE} {BEGIN(INITIAL); yylval.string = yytext; EMIT_TOKEN(OCT_VALUE);} 597 | {HEX_VALUE} {BEGIN(INITIAL); yylval.string = yytext; EMIT_TOKEN(HEX_VALUE);} 598 | 599 | {NUM_REAL} {yylval.string=yytext;EMIT_TOKEN(NUM_REAL);} 600 | {NUM_UNSIGNED} {yylval.string=yytext;EMIT_TOKEN(UNSIGNED_NUMBER);} 601 | 602 | {ALWAYS} {EMIT_TOKEN(KW_ALWAYS);} 603 | {AND} {EMIT_TOKEN(KW_AND);} 604 | {ASSIGN} {EMIT_TOKEN(KW_ASSIGN);} 605 | {AUTOMATIC} {EMIT_TOKEN(KW_AUTOMATIC);} 606 | {BEGIN} {EMIT_TOKEN(KW_BEGIN);} 607 | {BUF} {EMIT_TOKEN(KW_BUF);} 608 | {BUFIF0} {EMIT_TOKEN(KW_BUFIF0);} 609 | {BUFIF1} {EMIT_TOKEN(KW_BUFIF1);} 610 | {CASE} {EMIT_TOKEN(KW_CASE);} 611 | {CASEX} {EMIT_TOKEN(KW_CASEX);} 612 | {CASEZ} {EMIT_TOKEN(KW_CASEZ);} 613 | {CELL} {EMIT_TOKEN(KW_CELL);} 614 | {CMOS} {EMIT_TOKEN(KW_CMOS);} 615 | {CONFIG} {EMIT_TOKEN(KW_CONFIG);} 616 | {DEASSIGN} {EMIT_TOKEN(KW_DEASSIGN);} 617 | {DEFAULT} {EMIT_TOKEN(KW_DEFAULT);} 618 | {DEFPARAM} {EMIT_TOKEN(KW_DEFPARAM);} 619 | {DESIGN} {EMIT_TOKEN(KW_DESIGN);} 620 | {DISABLE} {EMIT_TOKEN(KW_DISABLE);} 621 | {EDGE} {EMIT_TOKEN(KW_EDGE);} 622 | {ELSE} {EMIT_TOKEN(KW_ELSE);} 623 | {END} {EMIT_TOKEN(KW_END);} 624 | {ENDCASE} {EMIT_TOKEN(KW_ENDCASE);} 625 | {ENDCONFIG} {EMIT_TOKEN(KW_ENDCONFIG);} 626 | {ENDFUNCTION} {EMIT_TOKEN(KW_ENDFUNCTION);} 627 | {ENDGENERATE} {EMIT_TOKEN(KW_ENDGENERATE);} 628 | {ENDMODULE} {EMIT_TOKEN(KW_ENDMODULE);} 629 | {ENDPRIMITIVE} {EMIT_TOKEN(KW_ENDPRIMITIVE);} 630 | {ENDSPECIFY} {EMIT_TOKEN(KW_ENDSPECIFY);} 631 | {ENDTABLE} {EMIT_TOKEN(KW_ENDTABLE);} 632 | {ENDTASK} {EMIT_TOKEN(KW_ENDTASK);} 633 | {EVENT} {EMIT_TOKEN(KW_EVENT);} 634 | {FOR} {EMIT_TOKEN(KW_FOR);} 635 | {FORCE} {EMIT_TOKEN(KW_FORCE);} 636 | {FOREVER} {EMIT_TOKEN(KW_FOREVER);} 637 | {FORK} {EMIT_TOKEN(KW_FORK);} 638 | {FUNCTION} {EMIT_TOKEN(KW_FUNCTION);} 639 | {GENERATE} {EMIT_TOKEN(KW_GENERATE);} 640 | {GENVAR} {EMIT_TOKEN(KW_GENVAR);} 641 | {HIGHZ0} {EMIT_TOKEN(KW_HIGHZ0);} 642 | {HIGHZ1} {EMIT_TOKEN(KW_HIGHZ1);} 643 | {IF} {EMIT_TOKEN(KW_IF);} 644 | {IFNONE} {EMIT_TOKEN(KW_IFNONE);} 645 | {INCDIR} {EMIT_TOKEN(KW_INCDIR);} 646 | {INCLUDE} {EMIT_TOKEN(KW_INCLUDE);} 647 | {INITIAL} {EMIT_TOKEN(KW_INITIAL);} 648 | {INOUT} {EMIT_TOKEN(KW_INOUT);} 649 | {INPUT} {EMIT_TOKEN(KW_INPUT);} 650 | {INSTANCE} {EMIT_TOKEN(KW_INSTANCE);} 651 | {INTEGER} {EMIT_TOKEN(KW_INTEGER);} 652 | {JOIN} {EMIT_TOKEN(KW_JOIN);} 653 | {LARGE} {EMIT_TOKEN(KW_LARGE);} 654 | {LIBLIST} {EMIT_TOKEN(KW_LIBLIST);} 655 | {LIBRARY} {EMIT_TOKEN(KW_LIBRARY);} 656 | {LOCALPARAM} {EMIT_TOKEN(KW_LOCALPARAM);} 657 | {MACROMODULE} {EMIT_TOKEN(KW_MACROMODULE);} 658 | {MEDIUM} {EMIT_TOKEN(KW_MEDIUM);} 659 | {MODULE} {EMIT_TOKEN(KW_MODULE);} 660 | {NAND} {EMIT_TOKEN(KW_NAND);} 661 | {NEGEDGE} {EMIT_TOKEN(KW_NEGEDGE);} 662 | {NMOS} {EMIT_TOKEN(KW_NMOS);} 663 | {NOR} {EMIT_TOKEN(KW_NOR);} 664 | {NOSHOWCANCELLED} {EMIT_TOKEN(KW_NOSHOWCANCELLED);} 665 | {NOT} {EMIT_TOKEN(KW_NOT);} 666 | {NOTIF0} {EMIT_TOKEN(KW_NOTIF0);} 667 | {NOTIF1} {EMIT_TOKEN(KW_NOTIF1);} 668 | {OR} {EMIT_TOKEN(KW_OR);} 669 | {OUTPUT} {EMIT_TOKEN(KW_OUTPUT);} 670 | {PARAMETER} {EMIT_TOKEN(KW_PARAMETER);} 671 | {PMOS} {EMIT_TOKEN(KW_PMOS);} 672 | {POSEDGE} {EMIT_TOKEN(KW_POSEDGE);} 673 | {PRIMITIVE} {EMIT_TOKEN(KW_PRIMITIVE);} 674 | {PULL0} {EMIT_TOKEN(KW_PULL0);} 675 | {PULL1} {EMIT_TOKEN(KW_PULL1);} 676 | {PULLDOWN} {EMIT_TOKEN(KW_PULLDOWN);} 677 | {PULLUP} {EMIT_TOKEN(KW_PULLUP);} 678 | {PULSESTYLE_ONEVENT} {EMIT_TOKEN(KW_PULSESTYLE_ONEVENT);} 679 | {PULSESTYLE_ONDETECT} {EMIT_TOKEN(KW_PULSESTYLE_ONDETECT);} 680 | {RCMOS} {EMIT_TOKEN(KW_RCMOS);} 681 | {REAL} {EMIT_TOKEN(KW_REAL);} 682 | {REALTIME} {EMIT_TOKEN(KW_REALTIME);} 683 | {REG} {EMIT_TOKEN(KW_REG);} 684 | {RELEASE} {EMIT_TOKEN(KW_RELEASE);} 685 | {REPEAT} {EMIT_TOKEN(KW_REPEAT);} 686 | {RNMOS} {EMIT_TOKEN(KW_RNMOS);} 687 | {RPMOS} {EMIT_TOKEN(KW_RPMOS);} 688 | {RTRAN} {EMIT_TOKEN(KW_RTRAN);} 689 | {RTRANIF0} {EMIT_TOKEN(KW_RTRANIF0);} 690 | {RTRANIF1} {EMIT_TOKEN(KW_RTRANIF1);} 691 | {SCALARED} {EMIT_TOKEN(KW_SCALARED);} 692 | {SHOWCANCELLED} {EMIT_TOKEN(KW_SHOWCANCELLED);} 693 | {SIGNED} {EMIT_TOKEN(KW_SIGNED);} 694 | {SMALL} {EMIT_TOKEN(KW_SMALL);} 695 | {SPECIFY} {EMIT_TOKEN(KW_SPECIFY);} 696 | {SPECPARAM} {EMIT_TOKEN(KW_SPECPARAM);} 697 | {STRONG0} {EMIT_TOKEN(KW_STRONG0);} 698 | {STRONG1} {EMIT_TOKEN(KW_STRONG1);} 699 | {SUPPLY0} {EMIT_TOKEN(KW_SUPPLY0);} 700 | {SUPPLY1} {EMIT_TOKEN(KW_SUPPLY1);} 701 | {TABLE} {EMIT_TOKEN(KW_TABLE);} 702 | {TASK} {EMIT_TOKEN(KW_TASK);} 703 | {TIME} {EMIT_TOKEN(KW_TIME);} 704 | {TRAN} {EMIT_TOKEN(KW_TRAN);} 705 | {TRANIF0} {EMIT_TOKEN(KW_TRANIF0);} 706 | {TRANIF1} {EMIT_TOKEN(KW_TRANIF1);} 707 | {TRI0} {EMIT_TOKEN(KW_TRI0);} 708 | {TRI1} {EMIT_TOKEN(KW_TRI1);} 709 | {TRIAND} {EMIT_TOKEN(KW_TRIAND);} 710 | {TRIOR} {EMIT_TOKEN(KW_TRIOR);} 711 | {TRIREG} {EMIT_TOKEN(KW_TRIREG);} 712 | {TRI} {EMIT_TOKEN(KW_TRI);} 713 | {UNSIGNED} {EMIT_TOKEN(KW_UNSIGNED);} 714 | {USE} {EMIT_TOKEN(KW_USE);} 715 | {VECTORED} {EMIT_TOKEN(KW_VECTORED);} 716 | {WAIT} {EMIT_TOKEN(KW_WAIT);} 717 | {WAND} {EMIT_TOKEN(KW_WAND);} 718 | {WEAK0} {EMIT_TOKEN(KW_WEAK0);} 719 | {WEAK1} {EMIT_TOKEN(KW_WEAK1);} 720 | {WHILE} {EMIT_TOKEN(KW_WHILE);} 721 | {WIRE} {EMIT_TOKEN(KW_WIRE);} 722 | {WOR} {EMIT_TOKEN(KW_WOR);} 723 | {XNOR} {EMIT_TOKEN(KW_XNOR);} 724 | {XOR} {EMIT_TOKEN(KW_XOR);} 725 | 726 | {SYSTEM_ID} { 727 | yylval.identifier = ast_new_identifier(yytext,yylineno); 728 | EMIT_TOKEN(SYSTEM_ID); 729 | } 730 | {ESCAPED_ID} { 731 | yylval.identifier = ast_new_identifier(yytext,yylineno); 732 | EMIT_TOKEN(ESCAPED_ID); 733 | } 734 | {SIMPLE_ID} { 735 | yylval.identifier = ast_new_identifier(yytext,yylineno); 736 | EMIT_TOKEN(SIMPLE_ID); 737 | } 738 | 739 | {STRING} {yylval.string= yytext;EMIT_TOKEN(STRING);} 740 | 741 | <*>{NEWLINE} {/*EMIT_TOKEN(NEWLINE); IGNORE */ } 742 | <*>{SPACE} {/*EMIT_TOKEN(SPACE); IGNORE */ } 743 | <*>{TAB} {/*EMIT_TOKEN(TAB); IGNORE */ } 744 | 745 | <> { 746 | 747 | yypop_buffer_state(); 748 | 749 | // We are exiting a file, so pop from the the preprocessor stack of files 750 | // being parsed. 751 | ast_stack_pop(yy_preproc -> current_file); 752 | 753 | 754 | if ( !YY_CURRENT_BUFFER ) 755 | { 756 | yyterminate(); 757 | } 758 | else 759 | { 760 | YY_BUFFER_STATE cur = YY_CURRENT_BUFFER; 761 | yylineno = cur -> yy_bs_lineno; 762 | } 763 | } 764 | 765 | . { 766 | EMIT_TOKEN(ANY); 767 | } 768 | 769 | %% 770 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.h 3 | *.v 4 | -------------------------------------------------------------------------------- /tests/attributes.v: -------------------------------------------------------------------------------- 1 | 2 | module foo ( 3 | input clk, 4 | input reset, 5 | input head, 6 | input tail, 7 | input valid 8 | ); 9 | 10 | parameter STATE_IDLE = 2'b00, 11 | STATE_HEAD = 2'b01, 12 | STATE_DATA = 2'b10, 13 | STATE_TAIL = 2'b11; 14 | 15 | reg [1:0] state; 16 | reg [1:0] next_state; 17 | 18 | always @(posedge clock) 19 | state <= reset ? STATE_IDLE : next_state; 20 | 21 | (* covered_fsm, channel, is="state", os="next_state", 22 | trans="STATE_IDLE->STATE_IDLE", 23 | trans="STATE_IDLE->STATE_HEAD", 24 | trans="STATE_HEAD->STATE_DATA", 25 | trans="STATE_HEAD->STATE_TAIL", 26 | trans="STATE_DATA->STATE_DATA", 27 | trans="STATE_DATA->STATE_TAIL", 28 | trans="STATE_TAIL->STATE_HEAD", 29 | trans="STATE_TAIL->STATE_IDLE" *) 30 | always @(reset or state or head or valid or tail) 31 | begin 32 | case( state ) 33 | STATE_IDLE: next_state = (valid & head) ? 34 | STATE_HEAD : STATE_IDLE; 35 | STATE_HEAD: next_state = (valid & tail) ? 36 | STATE_TAIL : STATE_DATA; 37 | STATE_DATA: next_state = (valid & tail) ? 38 | STATE_TAIL : STATE_DATA; 39 | STATE_TAIL: next_state = (valid & head) ? 40 | STATE_HEAD : STATE_IDLE; 41 | endcase 42 | end 43 | 44 | endmodule 45 | 46 | -------------------------------------------------------------------------------- /tests/casez.v: -------------------------------------------------------------------------------- 1 | 2 | 3 | module tb_casez; 4 | 5 | wire [31:0] shifter; 6 | wire [31:0] result; 7 | 8 | initial begin 9 | 10 | $monitor(shifter,result); 11 | shifter = 32'b1; 12 | 13 | result = shifter << 4; 14 | 15 | casez(result) 16 | 32'b10000 : $display("true"); 17 | 32'b11000 : $display("false"); 18 | endcase 19 | 20 | casez(result) 21 | 32'b11000 : $display("false"); 22 | default: $display("default case"); 23 | endcase 24 | 25 | end 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /tests/cd-missed.v: -------------------------------------------------------------------------------- 1 | 2 | // Missed compiler directives. 3 | 4 | `line 1 "a-new-file.v" 0 5 | 6 | `default_nettype wire 7 | `default_nettype tri 8 | `default_nettype tri0 9 | `default_nettype wand 10 | `default_nettype triand 11 | `default_nettype wor 12 | `default_nettype trior 13 | `default_nettype trireg 14 | 15 | `resetall 16 | -------------------------------------------------------------------------------- /tests/expression_tostring.v: -------------------------------------------------------------------------------- 1 | 2 | `define NUMBER 65 3 | 4 | module dummy(); 5 | 6 | assign d = `NUMBER - 1; 7 | 8 | assign Z = 32'b0010101; 9 | 10 | assign a = !b; 11 | 12 | assign cc_mvbr_d = ~(~op_d[1] & ~op_d[0] & op3_d[4] & op3_d[3] | 13 | op_d[1] & ~op_d[0] & op3_d[5] & ~op3_d[4] & 14 | op3_d[3] & op3_d[2] & op3_d[1] & op3_d[0] | 15 | op_d[1] & ~op_d[0] & op3_d[5] & op3_d[4] & 16 | ~op3_d[3] & op3_d[2] & ~op3_d[1] & op3_d[0] & 17 | dtu_dcl_opf2_d); 18 | 19 | 20 | endmodule 21 | -------------------------------------------------------------------------------- /tests/forever-disable.v: -------------------------------------------------------------------------------- 1 | 2 | module forever_disable(); 3 | 4 | initial begin 5 | i = 0; 6 | forever begin : continue_block 7 | if (i==a) 8 | disable continue_block; 9 | #1 i = i + 1; 10 | end 11 | end 12 | 13 | endmodule 14 | -------------------------------------------------------------------------------- /tests/functions.v: -------------------------------------------------------------------------------- 1 | 2 | module tb_functions; 3 | 4 | function myfunction; 5 | input a, b, c, d; 6 | begin 7 | myfunction = ((a+b) + (c-d)); 8 | end 9 | endfunction 10 | 11 | endmodule 12 | -------------------------------------------------------------------------------- /tests/generate.v: -------------------------------------------------------------------------------- 1 | 2 | module tb_generate; 3 | genvar i; 4 | 5 | generate 6 | for (i=0; i < 4; i=i+1) begin : MEM 7 | memory U (read, write, 8 | data_in[(i*8)+7:(i*8)], 9 | address,data_out[(i*8)+7:(i*8)]); 10 | end 11 | endgenerate 12 | 13 | endmodule 14 | -------------------------------------------------------------------------------- /tests/ifdef-1.v: -------------------------------------------------------------------------------- 1 | 2 | module test(out); 3 | output out; 4 | 5 | `define wow 6 | `define nest_one 7 | `define second_nest 8 | `define nest_two 9 | 10 | `ifdef wow 11 | initial $display("wow is defined"); 12 | `ifdef nest_one 13 | initial $display("nest_one is defined"); 14 | `ifdef nest_two 15 | initial $display("nest_two is defined"); 16 | `else 17 | initial $display("nest_two is not defined"); 18 | `endif 19 | `else 20 | initial $display("nest_one is not defined"); 21 | `endif 22 | `else 23 | initial $display("wow is not defined"); 24 | `ifdef second_nest 25 | initial $display("nest_two is defined"); 26 | `else 27 | initial $display("nest_two is not defined"); 28 | `endif 29 | `endif 30 | 31 | endmodule 32 | -------------------------------------------------------------------------------- /tests/ifdef-2.v: -------------------------------------------------------------------------------- 1 | 2 | `celldefine 3 | 4 | module test; 5 | `ifdef first_block 6 | `ifndef second_nest 7 | initial $display("first_block is defined"); 8 | `else 9 | initial $display("first_block and second_nest defined"); 10 | `endif 11 | `elsif second_block 12 | initial $display("second_block defined, first_block is not"); 13 | `else 14 | `ifndef last_result 15 | initial $display("first_block, second_block, last_result not ."); 16 | `elsif real_last 17 | initial $display("first_block, second_block not defined, 18 | last_result and real_last defined."); 19 | `else 20 | initial $display("Only last_result defined!"); 21 | `endif 22 | `endif 23 | endmodule 24 | 25 | `endcelldefine 26 | -------------------------------------------------------------------------------- /tests/inc-1.h: -------------------------------------------------------------------------------- 1 | 2 | `define BUS_WIDTH 31:0 // width of a bus 3 | -------------------------------------------------------------------------------- /tests/inc-2.v: -------------------------------------------------------------------------------- 1 | 2 | `include "inc-1.h" 3 | 4 | 5 | module a_module( 6 | input [`BUS_WIDTH] bus 7 | ); 8 | 9 | endmodule 10 | -------------------------------------------------------------------------------- /tests/loops.v: -------------------------------------------------------------------------------- 1 | 2 | 3 | module tb_loops; 4 | 5 | integer a = 0; 6 | 7 | initial begin 8 | 9 | while(a < 10) begin 10 | a = a + 1; 11 | end 12 | 13 | wait (10); 14 | 15 | forever begin 16 | a = a - 1; 17 | if( a < 0) $finish; 18 | end 19 | 20 | end 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /tests/macros.v: -------------------------------------------------------------------------------- 1 | 2 | `define HEADER_GUARD 0 3 | 4 | `define BUS_RANGE 31:0 5 | 6 | `undef HEADER_GUARD 7 | 8 | module bus_snooper( 9 | input [31:0] safe_buslines, 10 | input [`BUS_RANGE] bus_lines_1, 11 | input [`BUS_RANGE] bus_lines_2 12 | ); 13 | 14 | `undef BUS_WIDTH 15 | 16 | `undef BUS_RANGE 17 | 18 | endmodule 19 | -------------------------------------------------------------------------------- /tests/mod-param-dec.v: -------------------------------------------------------------------------------- 1 | 2 | module mod_param_dec_1 3 | #(parameter DATA_WIDTH = 8, 4 | ADDRESS_WIDTH = 4, 5 | FIFO_DEPTH = (1 << ADDRESS_WIDTH)); 6 | endmodule 7 | 8 | 9 | module mod_param_dec_2 10 | #(parameter DATA_WIDTH = 8, 11 | ADDRESS_WIDTH = 4, 12 | FIFO_DEPTH = (1 << ADDRESS_WIDTH)) 13 | (input wire clk, 14 | output wire half_clk); 15 | endmodule 16 | -------------------------------------------------------------------------------- /tests/module-instance.v: -------------------------------------------------------------------------------- 1 | 2 | 3 | module test_top(); 4 | 5 | dbl_buf #(1, 6 | 2,3, 7 | REG_WIDTH 8 | + 9 | 64) 10 | dbl_buf (.rst_l(rst_l), 11 | .clk(clk), 12 | .wr(dbl_buf_wr), 13 | .din(c2i_packet), 14 | .rd(dbl_buf_rd), 15 | .dout(outdata_buf_in), 16 | .vld(dbl_buf_vld), 17 | .full(dbl_buf_full)); 18 | 19 | module_being_instanced MODULE_NAME ( 20 | .serial_in ({serial_in[87:72] } ), 21 | .afo ({afo[87:72] } ), 22 | .serial_out ({serial_out[87:72] } ), 23 | .afi ({afi[87:72] } ), 24 | .vrefcode_i_l ({net0527[0] ,net0527[1] ,net0527[2] ,net0527[3] , 25 | net0527[4] ,net0527[5] ,net0527[6] ,net0527[7] } ), 26 | .vrefcode_i_r ({net0578[0] ,net0578[1] ,net0578[2] ,net0578[3] , 27 | net0578[4] ,net0578[5] ,net0578[6] ,net0578[7] } ), 28 | .data_neg 29 | ({\dram_io_data_out[247] , 30 | \dram_io_data_out[246] , 31 | \dram_io_data_out[245] , 32 | \dram_io_data_out[244] , 33 | \dram_io_data_out[243] , 34 | \dram_io_data_out[242] , 35 | \dram_io_data_out[241] , 36 | \dram_io_data_out[240] , 37 | \dram_io_data_out[183] , 38 | \dram_io_data_out[182] , 39 | \dram_io_data_out[181] , 40 | \dram_io_data_out[180] , 41 | \dram_io_data_out[179] , 42 | \dram_io_data_out[178] , 43 | \dram_io_data_out[177] , 44 | \dram_io_data_out[176] } ) 45 | ); 46 | 47 | endmodule 48 | -------------------------------------------------------------------------------- /tests/net_type_directive.v: -------------------------------------------------------------------------------- 1 | 2 | `default_nettype wire 3 | 4 | 5 | module dumb(); 6 | 7 | endmodule 8 | -------------------------------------------------------------------------------- /tests/operators.v: -------------------------------------------------------------------------------- 1 | 2 | module tb_operators ; 3 | 4 | wire [31:0] shifter; 5 | wire [31:0] result; 6 | 7 | initial begin 8 | 9 | $monitor(shifter,result); 10 | shifter = 32'b1; 11 | 12 | result = shifter << 4; 13 | result = shifter >> 4; 14 | result = shifter << 4; 15 | result = {1'b1,31'b0} >>> 31; 16 | result = {1'b0,31'b1} <<< 31; 17 | 18 | result = shifter ** 2; 19 | result = result % 4; 20 | 21 | if(shifter >= result) begin 22 | $display("GTE TEST 1"); 23 | end else if(shifter != result) begin 24 | $display("GTE TEST 2"); 25 | end else if(shifter === result) begin 26 | $display("GTE TEST 3"); 27 | end else if(shifter !== result) begin 28 | $display("GTE TEST 3"); 29 | end 30 | 31 | result = shifter !== shifter; 32 | 33 | shifter = shifter ~& result; 34 | shifter = shifter ~| result; 35 | end 36 | 37 | endmodule 38 | -------------------------------------------------------------------------------- /tests/primitives.v: -------------------------------------------------------------------------------- 1 | module d_latch_gates(d,clk,q,q_bar); 2 | input d,clk; 3 | output q, q_bar; 4 | 5 | wire n1,n2,n3; 6 | 7 | not a (n1,d); 8 | not a (n1,d), b(n2,c); 9 | not c (n1,d), (n2,c); 10 | not (n1,d), b(n2,c); 11 | not a (n1,d), b(n2,c); 12 | not (supply0,supply1) a (n1,d), b(n2,c); 13 | not (supply0,supply1) #(1) a (n1,d), b(n2,c); 14 | not a (n1,d), b(n2,c); 15 | not #(1) a (n1,d), b(n2,c); 16 | not #(1,2) a (n1,d), b(n2,c); 17 | 18 | tranif0 (b,c,d); 19 | tranif0 a (b,c,d); 20 | tranif0 #(1) (b,c,d); 21 | tranif0 #(1) a (b,c,d); 22 | 23 | bufif0 (b,c,d); 24 | bufif0 a (b,c,d); 25 | bufif0 #(1) (b,c,d); 26 | bufif0 #(1) a (b,c,d); 27 | 28 | 29 | nand (n2,d,clk); 30 | nand (n3,n1,clk); 31 | 32 | nand (q,q_bar,n2); 33 | nand (q_bar,q,n3); 34 | 35 | endmodule 36 | -------------------------------------------------------------------------------- /tests/primitives2.v: -------------------------------------------------------------------------------- 1 | 2 | module primitives_2_test(); 3 | 4 | wire a,b; 5 | wire y; 6 | wire i1,i2,ctrl,o; 7 | 8 | and (strong1, weak0) b(o, i1, i2); 9 | trireg (medium) t; 10 | buf (strong1, weak0) g1 (y, a); 11 | buf (pull1, supply0) g2 (y, b); 12 | buf (strong1, weak0) g1 (y, a); 13 | buf (strong1, weak0) g1 (y, b); 14 | buf (strong1, weak0) g1 (y, a); 15 | buf (weak1, strong0) g1 (y, b); 16 | bufif0 (strong1, weak0) g1 (y, i1, ctrl); 17 | bufif0 (strong1, weak0) g2 (y, i2, ctrl); 18 | 19 | endmodule 20 | -------------------------------------------------------------------------------- /tests/reg-data-types.v: -------------------------------------------------------------------------------- 1 | 2 | module reg_data_types(); 3 | 4 | reg scal; 5 | reg [7:0] vect; 6 | reg [7:0] mem [31:0]; 7 | integer i; 8 | integer i_mem [7:0]; 9 | time t; 10 | time t_mem [3:0]; 11 | real r; 12 | realtime rt1, rt2; 13 | 14 | endmodule 15 | -------------------------------------------------------------------------------- /tests/simple_task.v: -------------------------------------------------------------------------------- 1 | module simple_task(); 2 | 3 | task convert; 4 | input [7:0] temp_in; 5 | output [7:0] temp_out; 6 | begin 7 | temp_out = (9/5) *( temp_in + 32); 8 | end 9 | endtask 10 | 11 | endmodule 12 | -------------------------------------------------------------------------------- /tests/std-2.6.2.v: -------------------------------------------------------------------------------- 1 | module string_test; 2 | reg [8*14:1] stringvar; 3 | initial begin 4 | stringvar = "Hello world"; 5 | $display("%s is stored as %h", stringvar,stringvar); 6 | stringvar = {stringvar,"!!!"}; 7 | $display("%s is stored as %h", stringvar,stringvar); 8 | end 9 | endmodule 10 | -------------------------------------------------------------------------------- /tests/std-3.10.3.1.1-array-declaration.v: -------------------------------------------------------------------------------- 1 | 2 | module test; 3 | reg [7:0] mema[0:255]; 4 | reg arrayb[7:0][0:255]; 5 | wire w_array[7:0][5:0]; 6 | integer inta[1:64]; 7 | time chng_hist[1:1000]; 8 | integer t_index; 9 | endmodule 10 | -------------------------------------------------------------------------------- /tests/std-3.11.1-parameters.v: -------------------------------------------------------------------------------- 1 | module test; 2 | parameter msb = 7; 3 | parameter e = 25, f = 9; 4 | parameter r = 5.7; 5 | parameter byte_size = 8; 6 | parameter byte_mask = byte_size -1; 7 | parameter average_delay = (r + f)/2; 8 | parameter signed [3:0] mux_selector = 0; 9 | parameter real r1 = 3.5e17; 10 | parameter p1 = 13'h7e; 11 | parameter [31:0] dec_const = 1'b1; 12 | parameter newconst = 3'h4; 13 | parameter newconst = 4; 14 | endmodule 15 | -------------------------------------------------------------------------------- /tests/std-3.11.1-specparam.v: -------------------------------------------------------------------------------- 1 | module RAM16GEN (DOUT, DIN, ADR, WE, CE); 2 | specparam dhold = 1.0; 3 | specparam ddly = 1.0; 4 | parameter width = 1; 5 | parameter regsize = dhold + 1.0; 6 | // Illegal - can’t assign 7 | // specparams to parameters 8 | 9 | specify 10 | specparam tRise_clk_q = 150, tFall_clk_q = 200; 11 | specparam tRise_control = 40, tFall_control = 50; 12 | endspecify 13 | 14 | endmodule 15 | -------------------------------------------------------------------------------- /tests/std-4.4.3-expressions.v: -------------------------------------------------------------------------------- 1 | module test; 2 | reg [3:0] a; 3 | reg [5:0] b; 4 | reg [15:0] c; 5 | initial begin 6 | a = 4'hF; 7 | b = 6'ha; 8 | $display("a*b=%x", 9 | a*b); 10 | c = {a**b}; 11 | $display("a**b=%x", c); 12 | c = a**b; 13 | $display("c=%x", c); 14 | end 15 | endmodule 16 | -------------------------------------------------------------------------------- /tests/std-6.1.2-contassign.v: -------------------------------------------------------------------------------- 1 | module adder (sum_out, carry_out, carry_in, ina, inb); 2 | output carry_out; 3 | output [3:0] sum_out; 4 | input [3:0] ina, inb; 5 | input carry_in; 6 | wire carry_out, carry_in; 7 | wire [3:0] sum_out, ina, inb; 8 | assign {carry_out, sum_out} = ina + inb + carry_in; 9 | endmodule 10 | -------------------------------------------------------------------------------- /tests/std-6.1.2-contassign2.v: -------------------------------------------------------------------------------- 1 | module select_bus(busout, bus0, bus1, bus2, bus3, enable, s); 2 | parameter n = 16; 3 | parameter Zee = 16'bz; 4 | output [1:n] busout; 5 | input [1:n] bus0, bus1, bus2, bus3; 6 | input enable; 7 | input [1:2] s; 8 | tri [1:n] data; 9 | // net declaration 10 | // net declaration with continuous assignment 11 | tri [1:n] busout = enable ? data : Zee; 12 | // assignment statement with four continuous assignments 13 | assign 14 | data = (s == 0) ? bus0 : Zee, 15 | data = (s == 1) ? bus1 : Zee, 16 | data = (s == 2) ? bus2 : Zee, 17 | data = (s == 3) ? bus3 : Zee; 18 | endmodule 19 | -------------------------------------------------------------------------------- /tests/std-7.1.6-primitives.v: -------------------------------------------------------------------------------- 1 | module driver (in, out, en); 2 | input [3:0] in; 3 | output [3:0] out; 4 | input en; 5 | bufif0 ar[3:0] (out, in, en); // array of three-state buffers 6 | endmodule 7 | 8 | module busdriver_equiv (busin, bushigh, buslow, enh, enl); 9 | input [15:0] busin; 10 | output [7:0] bushigh, buslow; 11 | input enh, enl; 12 | driver busar[3:0] (.out({bushigh, buslow}), .in(busin), 13 | .en({enh, enh, enl, enl})); 14 | endmodule 15 | -------------------------------------------------------------------------------- /tests/timescale.v: -------------------------------------------------------------------------------- 1 | 2 | `timescale 10ns/10ns 3 | 4 | module nop(); 5 | 6 | endmodule 7 | -------------------------------------------------------------------------------- /tests/unconnected_drive.v: -------------------------------------------------------------------------------- 1 | 2 | `unconnected_drive pull0 3 | 4 | module test(); 5 | 6 | endmodule 7 | 8 | `nounconnected_drive 9 | 10 | `unconnected_drive pull1 11 | 12 | `nounconnected_drive 13 | --------------------------------------------------------------------------------