├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile.am ├── README.md ├── autogen.sh ├── configure.ac ├── firrtlator.pc.in ├── firrtlator ├── Makefile.am └── src │ └── Firrtlator.cpp ├── lib ├── Makefile.am ├── backends │ ├── FirrtlatorBackend.h │ ├── dot │ │ ├── include │ │ │ └── DotBackend.h │ │ └── src │ │ │ └── DotBackend.cpp │ ├── firrtl │ │ ├── include │ │ │ └── FirrtlBackend.h │ │ └── src │ │ │ └── FirrtlBackend.cpp │ ├── generic │ │ ├── include │ │ │ └── StreamIndentation.h │ │ └── src │ │ │ ├── Backends.cpp │ │ │ └── StreamIndentation.cpp │ └── tree │ │ ├── include │ │ └── TreeBackend.h │ │ └── src │ │ └── TreeBackend.cpp ├── frontends │ ├── FirrtlatorFrontend.h │ ├── firrtl │ │ ├── include │ │ │ ├── FirrtlFrontend.h │ │ │ ├── FirrtlFrontendGrammar.h │ │ │ ├── FirrtlFrontendLexer.h │ │ │ └── FirrtlFrontendLexerHelper.h │ │ └── src │ │ │ └── FirrtlFrontend.cpp │ └── generic │ │ └── src │ │ └── Frontends.cpp ├── include │ ├── Firrtlator.h │ ├── IR.h │ ├── Util.h │ └── Visitor.h ├── ir │ └── src │ │ ├── Circuit.cpp │ │ ├── Expression.cpp │ │ ├── IRNode.cpp │ │ ├── Memory.cpp │ │ ├── Module.cpp │ │ ├── Parameter.cpp │ │ ├── Port.cpp │ │ ├── Stmt.cpp │ │ └── Type.cpp ├── passes │ ├── FirrtlatorPass.h │ ├── generic │ │ └── src │ │ │ └── Passes.cpp │ └── stripinfo │ │ ├── include │ │ └── StripInfo.h │ │ └── src │ │ └── StripInfo.cpp └── src │ ├── Firrtlator.cpp │ └── Visitor.cpp └── m4 ├── .gitignore ├── ax_cxx_compile_stdcxx.m4 ├── ax_cxx_compile_stdcxx_11.m4 └── boost.m4 /.gitignore: -------------------------------------------------------------------------------- 1 | .cproject 2 | .project 3 | .settings/ 4 | Makefile.in 5 | aclocal.m4 6 | autom4te.cache/ 7 | build-aux/ 8 | build/ 9 | config.h.in 10 | *~ 11 | configure 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: enabled 3 | 4 | language: c++ 5 | 6 | before_install: 7 | - sudo add-apt-repository ppa:kzemek/boost -y 8 | - sudo apt-get update -q 9 | - sudo apt-get install -y libboost1.58-dev 10 | - ./autogen.sh 11 | 12 | script: 13 | - ./configure 14 | - make 15 | 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 authors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} 2 | AM_MAKEFLAGS = --no-print-directory 3 | 4 | SUBDIRS = lib firrtlator 5 | 6 | pkgconfigdir = $(datadir)/pkgconfig 7 | pkgconfig_DATA = firrtlator.pc 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Logo](http://firrtlator.org/logo_wide.png) 2 | 3 | [![Build Status](https://travis-ci.org/SiliconSemantics/firrtlator.svg?branch=master)](https://travis-ci.org/SiliconSemantics/firrtlator) 4 | 5 | Firrtlator is a C++ library and tool for the 6 | [Flexible Intermediate Representation for RTL (FIRRTL)](https://github.com/ucb-bar/firrtl). It 7 | provides the representation of FIRRTL in C++ and comes with the 8 | frontend to parse FIRRTL and backend to emit FIRRTL (and other 9 | representations). Passes can operate on a FIRRTL design to optimize 10 | it, inject logic, etc. Firrtlator can be easily extended with custom 11 | frontend, passes and backends. 12 | 13 | The FIRRTL grammar itself is in alpha status. Firrtlator is even 14 | before that, as currently semantics are not fully implemented. 15 | 16 | ## Build Firrtlator 17 | 18 | You need g++, autotools and the [Boost](http://www.boost.org/) headers 19 | to build firrtlator. The Boost headers are usually found as the boost 20 | development package in your Linux distribution (such as `libboost-dev` 21 | in Debian/Ubuntu). 22 | 23 | To build Firrtlator, simply run 24 | 25 | ./autogen.sh 26 | mkdir build; cd build 27 | ../configure --prefix=~/firrtlator-install/ 28 | make 29 | make install 30 | 31 | You will find the firrlator library, pkgconfig and firrtlator tool 32 | installed in your home directory for testing (`~/firrtlator-install`). 33 | 34 | Firrtlator (specifically the FIRRTL frontend partser) needs a recent 35 | version of Boost. Your system's Boost version may not be recent enough 36 | and you will see: 37 | 38 | checking for Boost headers version >= 1.58.0... no 39 | configure: error: cannot find Boost headers version >= 1.58.0 40 | 41 | If that is the case, download and extract a recent Boost version. You 42 | will not need to build Boost, it is headers-only which means you can 43 | also delete it after building. For example: 44 | 45 | wget https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.zip 46 | unzip boost_1_62_0.zip 47 | ../configure --prefix=~/firrtlator-install/ --with-boost=$PWD/boost_1_62_0 48 | make 49 | make install 50 | 51 | ## Try out Firrtlator 52 | 53 | To try out Firrtlator, create a simple design `simple.fir`: 54 | 55 | ; Simple test circuit 56 | circuit test : @[simple.v 4:1] 57 | module test : @[simple.v 4:1] 58 | input a : UInt<1> @[simple.v 5:1] 59 | input b : UInt<1> @[simple.v 5:1] 60 | input clk : Clock @[simple.v 6:1] 61 | input rst : UInt<1> @[simple.v 5:1] 62 | output c : UInt<1> @[simple.v 7:1] 63 | reg creg : UInt<1> clk with: ( reset => ( rst, UInt<1>(0) ) ) @[simple.v 9:3] 64 | creg <= add(a,b) @[simple.v 11:3] 65 | c <= creg @[simple.v 12:3] 66 | 67 | To ease the command lines in this example, add Firrtlator to your 68 | path: 69 | 70 | export PATH=~/firrtlator-install/bin:$PATH 71 | 72 | First, have a look at the help that explains the usage: 73 | 74 | firrtlator --help 75 | 76 | Now, we just write the design back as FIRRTL: 77 | 78 | firrtlator -i simple.ir out.fir 79 | 80 | If you now inspect `out.fir` you will find that the comment (line 1) 81 | is gone, but the design itself is preserved. 82 | 83 | In the next step, we can let Firrtlator print the design as a tree: 84 | 85 | firrtlator -i simple.ir out.tree 86 | 87 | The resulting `out.tree` shows the IR tree: 88 | 89 | (circuit) id=test, info="simple.v 4:1" 90 | (module) id=test, info="simple.v 4:1" 91 | (port) id=a, dir=input, info="simple.v 5:1" 92 | (type int) signed=false, width=1 93 | (port) id=b, dir=input, info="simple.v 5:1" 94 | (type int) signed=false, width=1 95 | (port) id=clk, dir=input, info="simple.v 6:1" 96 | (type clock) 97 | (port) id=rst, dir=input, info="simple.v 5:1" 98 | (type int) signed=false, width=1 99 | (port) id=c, dir=output, info="simple.v 7:1" 100 | (type int) signed=false, width=1 101 | (stmt group) 102 | (reg) id=creg 103 | [type] (type int) signed=false, width=1 104 | [clock] (ref) to=clk 105 | [reset trigger] (ref) to=rst 106 | [reset value] (const) value=0 107 | (type int) signed=false, width=1 108 | (connect) partial=false, info="simple.v 11:3" 109 | [to](ref) to=creg 110 | [from](add) 111 | (ref) to=a 112 | (ref) to=b 113 | (connect) partial=false, info="simple.v 12:3" 114 | [to](ref) to=c 115 | [from](ref) to=creg 116 | 117 | It is also possible to print it with dot: 118 | 119 | firrtlator -i simple.ir out.dot 120 | dot -Tpng out.dot > out.png 121 | 122 | This will produce this output: 123 | 124 | ![Dot](http://firrtlator.org/example-simple.png) 125 | 126 | Finally we want to use a very, very simple pass that removes all 127 | annotated source information from the source: 128 | 129 | firrtlator -i simple.fir -p stripinfo our.fir 130 | 131 | ## Get involved 132 | 133 | As mentioned, Firrtlator is right at the beginning. For the moment it 134 | does not do much semantics, including width inference etc. So 135 | manipulating the IR tree requires care. 136 | 137 | The next steps I want to do are: 138 | 139 | * Create a Verilator frontend using Firrtlator 140 | * Add semantics 141 | * Add a pass for injection of Vivado-compatible debug probes 142 | 143 | You are invited to contribute ideas, thoughts and code. Please open an 144 | [issue](https://github.com/SiliconSemantics/firrtlator/issues) with 145 | your input or send me an email to 146 | [stefan@wallentowitz.de](mailto:stefan@wallentowitz.de). 147 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | autoreconf --install --symlink 4 | 5 | echo 6 | echo "Configuration done. Before proceeding you need to decide for an installation" 7 | echo "Usual build procedure:" 8 | echo 9 | echo " mkdir build; cd build;" 10 | echo " ../configure" 11 | echo " make" 12 | echo " sudo make install" 13 | echo -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ(2.60) 2 | AC_INIT([firrtlator], 3 | [0.1], 4 | [wallento@silicon-semantics.com], 5 | [firrtlator], 6 | [http://www.firrtlator.org]) 7 | AC_CONFIG_SRCDIR([lib/include/Firrtlator.h]) 8 | AC_CONFIG_AUX_DIR([build-aux]) 9 | AM_INIT_AUTOMAKE([check-news foreign 1.11 -Wall -Wno-portability silent-rules tar-pax no-dist-gzip dist-xz subdir-objects]) 10 | 11 | FIRRTLATOR_CURRENT=0 12 | FIRRTLATOR_REVISION=1 13 | FIRRTLATOR_AGE=0 14 | LTLDFLAGS="-version-info ${FIRRTLATOR_CURRENT}:${FIRRTLATOR_REVISION}:${FIRRTLATOR_AGE}" 15 | AC_SUBST(LTLDFLAGS) 16 | 17 | AC_USE_SYSTEM_EXTENSIONS 18 | AC_PROG_CXX 19 | AC_PROG_CXXCPP 20 | AX_CXX_COMPILE_STDCXX_11 21 | AC_SYS_LARGEFILE 22 | AC_CONFIG_MACRO_DIR([m4]) 23 | AM_SILENT_RULES([yes]) 24 | LT_INIT([disable-static pic-only]) 25 | AC_PREFIX_DEFAULT([/usr]) 26 | 27 | BOOST_REQUIRE([1.58]) 28 | 29 | AM_CXXFLAGS="-Wall \ 30 | -Wmissing-declarations -Wpointer-arith \ 31 | -Wsign-compare -Wchar-subscripts -Wshadow \ 32 | -Wformat-security -Wtype-limits \ 33 | -pedantic -pedantic-errors -Werror\ 34 | -fvisibility=hidden" 35 | AC_SUBST([AM_CXXFLAGS]) 36 | 37 | AM_LDFLAGS="-Wl,--gc-sections \ 38 | -Wl,--as-needed \ 39 | -pthread \ 40 | -lrt \ 41 | ${libglip_LIBS}" 42 | AC_SUBST(AM_LDFLAGS) 43 | 44 | AC_CONFIG_HEADERS(config.h) 45 | AC_CONFIG_FILES([ 46 | firrtlator.pc 47 | Makefile 48 | lib/Makefile 49 | firrtlator/Makefile 50 | ]) 51 | 52 | AC_OUTPUT 53 | AC_MSG_RESULT([ 54 | $PACKAGE $VERSION 55 | ===== 56 | 57 | prefix: ${prefix} 58 | libdir: ${libdir} 59 | includedir: ${includedir} 60 | datarootdir: ${datarootdir} 61 | datadir: ${datadir} 62 | 63 | compiler: ${CC} 64 | cflags: ${CFLAGS} 65 | ldflags: ${LDFLAGS} 66 | ]) 67 | -------------------------------------------------------------------------------- /firrtlator.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: Firrtlator 7 | Description: FIRRTL C++ library and Firrtlator program 8 | URL: http://www.firrtlator.org 9 | Version: @VERSION@ 10 | Requires: 11 | Libs: -L${libdir} -lfiirtlator 12 | Cflags: -I${includedir} -------------------------------------------------------------------------------- /firrtlator/Makefile.am: -------------------------------------------------------------------------------- 1 | LDADD = ../lib/libfirrtlator.la 2 | 3 | bin_PROGRAMS = firrtlator 4 | 5 | firrtlator_SOURCES = \ 6 | src/Firrtlator.cpp 7 | 8 | firrtlator_CXXFLAGS = $(AM_CXXFLAGS) \ 9 | -I $(top_srcdir)/lib/include/ -------------------------------------------------------------------------------- /firrtlator/src/Firrtlator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void help(void); 10 | 11 | int main(int argc, char* argv[]) { 12 | int c; 13 | 14 | std::vector input_files; 15 | std::vector passes; 16 | std::string output_file = "out.fir"; 17 | 18 | while ((c = getopt (argc, argv, "hi:p:")) != -1) { 19 | switch(c) { 20 | case 'i': 21 | input_files.push_back(optarg); 22 | break; 23 | case 'p': 24 | passes.push_back(optarg); 25 | break; 26 | case 'h': 27 | help(); 28 | exit(0); 29 | break; 30 | } 31 | } 32 | 33 | if (optind < argc) { 34 | output_file = argv[optind]; 35 | } 36 | 37 | if ((optind+1)< argc) { 38 | std::cerr << "Only one output file possible. Ignore extra arguments" << std::endl; 39 | } 40 | 41 | if (input_files.size() > 1) { 42 | std::cerr << "Only one input file possible. Ignore extra arguments" << std::endl; 43 | } 44 | 45 | if (input_files.size() == 0) { 46 | std::cout << "No input file given." << std::endl; 47 | return 0; 48 | } 49 | 50 | Firrtlator::Firrtlator firrtlator; 51 | 52 | std::string::size_type pos = input_files[0].find_last_of("."); 53 | if (pos == std::string::npos) { 54 | std::cout << "Cannot determine the output file type" << std::endl; 55 | exit(1); 56 | } 57 | 58 | std::string ext = input_files[0].substr(pos+1, -1); 59 | 60 | if (!firrtlator.parseFile(input_files[0], firrtlator.getFrontend(ext))) { 61 | std::cout << "Failed parsing " << input_files[0] << std::endl; 62 | } 63 | 64 | for (auto p : passes) { 65 | firrtlator.pass(p); 66 | } 67 | 68 | pos = output_file.find_last_of("."); 69 | if (pos == std::string::npos) { 70 | std::cout << "Cannot determine the output file type" << std::endl; 71 | exit(1); 72 | } 73 | 74 | ext = output_file.substr(pos+1, -1); 75 | 76 | firrtlator.generate(output_file, firrtlator.getBackend(ext)); 77 | } 78 | 79 | void help(void) { 80 | std::cout << "Usage: firrtlator [options] " << std::endl; 81 | std::cout << " is an output file name. The extension hints used backend (see below)." << std::endl; 82 | std::cout << std::endl; 83 | std::cout << " options:" << std::endl; 84 | std::cout << " -i Set input file. Currently only one file is supported." << std::endl; 85 | std::cout << " -p Run pass on IR." << std::endl; 86 | std::cout << std::endl; 87 | 88 | std::vector<::Firrtlator::Firrtlator::FrontendDescriptor> fdesc; 89 | fdesc = ::Firrtlator::Firrtlator::getFrontends(); 90 | std::cout << "Supported frontends:" << std::endl; 91 | for (auto f : fdesc) { 92 | std::cout << " " << f.name << std::endl; 93 | std::cout << " " << f.description << std::endl; 94 | std::cout << " Filetypes:"; 95 | for (auto t : f.filetypes) { 96 | std::cout << " " << t; 97 | } 98 | std::cout << std::endl; 99 | } 100 | std::cout << std::endl; 101 | 102 | std::vector<::Firrtlator::Firrtlator::BackendDescriptor> bdesc; 103 | bdesc = ::Firrtlator::Firrtlator::getBackends(); 104 | std::cout << "Supported backends:" << std::endl; 105 | for (auto b : bdesc) { 106 | std::cout << " " << b.name << std::endl; 107 | std::cout << " " << b.description << std::endl; 108 | std::cout << " Filetypes:"; 109 | for (auto t : b.filetypes) { 110 | std::cout << " " << t; 111 | } 112 | std::cout << std::endl; 113 | } 114 | std::cout << std::endl; 115 | 116 | std::vector<::Firrtlator::Firrtlator::PassDescriptor> pdesc; 117 | pdesc = ::Firrtlator::Firrtlator::getPasses(); 118 | std::cout << "Supported passes:" << std::endl; 119 | for (auto p : pdesc) { 120 | std::cout << " " << p.name << std::endl; 121 | std::cout << " " << p.description << std::endl; 122 | std::cout << std::endl; 123 | } 124 | std::cout << std::endl; 125 | } 126 | -------------------------------------------------------------------------------- /lib/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | pkginclude_HEADERS = include/Firrtlator.h include/IR.h include/Visitor.h 3 | lib_LTLIBRARIES = libfirrtlator.la 4 | 5 | libfirrtlator_la_SOURCES = \ 6 | src/Firrtlator.cpp \ 7 | src/Visitor.cpp \ 8 | ir/src/Circuit.cpp \ 9 | ir/src/Expression.cpp \ 10 | ir/src/IRNode.cpp \ 11 | ir/src/Memory.cpp \ 12 | ir/src/Module.cpp \ 13 | ir/src/Parameter.cpp \ 14 | ir/src/Port.cpp \ 15 | ir/src/Stmt.cpp \ 16 | ir/src/Type.cpp \ 17 | frontends/generic/src/Frontends.cpp \ 18 | frontends/firrtl/src/FirrtlFrontend.cpp \ 19 | passes/generic/src/Passes.cpp \ 20 | passes/stripinfo/src/StripInfo.cpp \ 21 | backends/generic/src/Backends.cpp \ 22 | backends/firrtl/src/FirrtlBackend.cpp \ 23 | backends/dot/src/DotBackend.cpp \ 24 | backends/tree/src/TreeBackend.cpp \ 25 | backends/generic/src/StreamIndentation.cpp 26 | 27 | libfirrtlator_la_LDFLAGS = $(AM_LDFLAGS) $(LTLDFLAGS) 28 | libfirrtlator_la_CPPFLAGS = $(AM_CPPFLAGS) $(BOOST_CPPFLAGS) \ 29 | -include $(top_builddir)/config.h \ 30 | -I $(srcdir)/include \ 31 | -I $(srcdir)/frontends \ 32 | -I $(srcdir)/frontends/firrtl/include \ 33 | -I $(srcdir)/passes \ 34 | -I $(srcdir)/passes/stripinfo/include \ 35 | -I $(srcdir)/backends \ 36 | -I $(srcdir)/backends/generic/include \ 37 | -I $(srcdir)/backends/firrtl/include \ 38 | -I $(srcdir)/backends/tree/include 39 | libfirrtlator_la_CXXFLAGS = $(AM_CXXFLAGS) 40 | -------------------------------------------------------------------------------- /lib/backends/FirrtlatorBackend.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "IR.h" 26 | #include "Firrtlator.h" 27 | 28 | namespace Firrtlator { 29 | namespace Backend { 30 | 31 | class BackendBase { 32 | public: 33 | virtual ~BackendBase() {}; 34 | BackendBase(std::ostream &os) : mStream(&os) {} 35 | virtual void generate(std::shared_ptr ir) = 0; 36 | protected: 37 | std::ostream *mStream; 38 | }; 39 | 40 | class BackendFactory 41 | { 42 | public: 43 | virtual ~BackendFactory() {} 44 | virtual std::shared_ptr create(std::ostream &os) = 0; 45 | 46 | virtual std::string getName() = 0; 47 | virtual std::string getDescription() = 0; 48 | virtual std::vector getFiletypes() = 0; 49 | }; 50 | 51 | class Registry { 52 | public: 53 | static void registerBackend(const std::string &name, 54 | BackendFactory * factory); 55 | static std::shared_ptr create(const std::string &name, std::ostream &os) { 56 | throwAssert(getBackendMap().find(name) != getBackendMap().end(), 57 | "Cannot find backend: " + name); 58 | return getBackendMap()[name]->create(os); 59 | } 60 | 61 | static std::vector getDescriptors() { 62 | std::vector list; 63 | for (auto b : getBackendMap()) { 64 | Firrtlator::BackendDescriptor desc; 65 | desc.name = b.second->getName(); 66 | desc.description = b.second->getDescription(); 67 | desc.filetypes = b.second->getFiletypes(); 68 | list.push_back(desc); 69 | } 70 | return list; 71 | } 72 | private: 73 | typedef std::map BackendMap; 74 | static BackendMap &getBackendMap() { 75 | static BackendMap map; 76 | return map; 77 | } 78 | }; 79 | 80 | } 81 | } 82 | 83 | #define REGISTER_BACKEND(backend) \ 84 | class backend##Factory : public ::Firrtlator::Backend::BackendFactory { \ 85 | public: \ 86 | backend##Factory() \ 87 | { \ 88 | ::Firrtlator::Backend::Registry::registerBackend(backend::name, \ 89 | this); \ 90 | } \ 91 | virtual std::shared_ptr<::Firrtlator::Backend::BackendBase> create(std::ostream &os) { \ 92 | return std::make_shared(os); \ 93 | } \ 94 | virtual std::string getName() { \ 95 | return backend::name; \ 96 | } \ 97 | virtual std::string getDescription() { \ 98 | return backend::description; \ 99 | } \ 100 | virtual std::vector getFiletypes() { \ 101 | return backend::filetypes; \ 102 | } \ 103 | }; \ 104 | static backend##Factory global_##backend##Factory; 105 | -------------------------------------------------------------------------------- /lib/backends/dot/include/DotBackend.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "FirrtlatorBackend.h" 26 | #include "Visitor.h" 27 | 28 | #include 29 | #include 30 | 31 | namespace Firrtlator { 32 | namespace Backend { 33 | namespace Dot { 34 | 35 | class Backend : public ::Firrtlator::Backend::BackendBase { 36 | public: 37 | Backend(std::ostream &os); 38 | virtual void generate(std::shared_ptr ir); 39 | static std::string name; 40 | static std::string description; 41 | static std::vector filetypes; 42 | }; 43 | 44 | class Visitor : public ::Firrtlator::Visitor { 45 | public: 46 | Visitor(std::ostream *os); 47 | 48 | virtual ~Visitor(); 49 | virtual bool visit(std::shared_ptr); 50 | virtual void leave(std::shared_ptr); 51 | 52 | virtual bool visit(std::shared_ptr); 53 | virtual void leave(std::shared_ptr); 54 | 55 | virtual bool visit(std::shared_ptr); 56 | virtual void leave(std::shared_ptr); 57 | 58 | virtual bool visit(std::shared_ptr); 59 | 60 | virtual void visit(std::shared_ptr); 61 | 62 | virtual void visit(std::shared_ptr); 63 | 64 | virtual bool visit(std::shared_ptr); 65 | 66 | virtual bool visit(std::shared_ptr); 67 | 68 | virtual bool visit(std::shared_ptr); 69 | 70 | virtual bool visit(std::shared_ptr); 71 | 72 | virtual bool visit(std::shared_ptr); 73 | 74 | virtual bool visit(std::shared_ptr); 75 | 76 | virtual bool visit(std::shared_ptr); 77 | 78 | virtual bool visit(std::shared_ptr); 79 | 80 | virtual bool visit(std::shared_ptr); 81 | 82 | virtual bool visit(std::shared_ptr); 83 | 84 | virtual bool visit(std::shared_ptr); 85 | virtual void leave(std::shared_ptr); 86 | 87 | virtual bool visit(std::shared_ptr); 88 | 89 | virtual bool visit(std::shared_ptr); 90 | 91 | virtual bool visit(std::shared_ptr); 92 | 93 | virtual bool visit(std::shared_ptr); 94 | 95 | virtual void visit(std::shared_ptr); 96 | 97 | virtual void visit(std::shared_ptr); 98 | 99 | virtual void visit(std::shared_ptr); 100 | 101 | virtual bool visit(std::shared_ptr); 102 | 103 | virtual bool visit(std::shared_ptr); 104 | 105 | virtual bool visit(std::shared_ptr); 106 | 107 | virtual bool visit(std::shared_ptr); 108 | 109 | virtual bool visit(std::shared_ptr); 110 | 111 | virtual bool visit(std::shared_ptr); 112 | private: 113 | std::ostream *mStream; 114 | std::vector mNodes; 115 | std::vector, std::shared_ptr, 116 | std::string> > mEdges; 117 | 118 | std::map, int> mNodeDictionary; 119 | 120 | void addNode(std::shared_ptr node, std::string text); 121 | void addEdge(std::shared_ptr from, std::shared_ptr to, 122 | std::string text); 123 | }; 124 | 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /lib/backends/dot/src/DotBackend.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "StreamIndentation.h" 24 | 25 | #include 26 | #include "../include/DotBackend.h" 27 | 28 | namespace Firrtlator { 29 | namespace Backend { 30 | namespace Dot { 31 | 32 | std::string Backend::name = "dot"; 33 | std::string Backend::description = "Generates graphviz dot files"; 34 | std::vector Backend::filetypes = { "dot" }; 35 | 36 | REGISTER_BACKEND(Backend) 37 | 38 | Backend::Backend(std::ostream &os) : BackendBase(os) { 39 | 40 | } 41 | 42 | void Backend::generate(std::shared_ptr ir) { 43 | Visitor v(mStream); 44 | 45 | ir->accept(v); 46 | } 47 | 48 | Visitor::Visitor(std::ostream *os) { 49 | mStream = os; 50 | } 51 | 52 | Visitor::~Visitor() { 53 | 54 | } 55 | 56 | bool Visitor::visit(std::shared_ptr c) { 57 | addNode(c, "circuit\n"+c->getId()); 58 | 59 | for (auto m : c->getModules()) { 60 | addEdge(c, m, ""); 61 | } 62 | 63 | return true; 64 | } 65 | 66 | void Visitor::leave(std::shared_ptr c) { 67 | *mStream << "diGraph " << c->getId() << " {" << indent << endl; 68 | 69 | for (auto n : mNodes) 70 | *mStream << n << endl; 71 | 72 | for (auto e : mEdges) { 73 | int from = mNodeDictionary[std::get<0>(e)]; 74 | int to = mNodeDictionary[std::get<1>(e)]; 75 | std::string text = std::get<2>(e); 76 | 77 | *mStream << from << "->" << to; 78 | if (text.length() > 0) 79 | *mStream << "[label=\"" << text << "\"]"; 80 | *mStream << ";" << endl; 81 | } 82 | 83 | *mStream << dedent << endl << "}" << endl; 84 | } 85 | 86 | bool Visitor::visit(std::shared_ptr m) { 87 | addNode(m, "module\n"+m->getId()); 88 | 89 | for (auto p : m->getPorts()) 90 | addEdge(m, p, ""); 91 | 92 | addEdge(m, m->getStmts(), ""); 93 | 94 | return true; 95 | } 96 | 97 | void Visitor::leave(std::shared_ptr m) { 98 | } 99 | 100 | bool Visitor::visit(std::shared_ptr p) { 101 | addNode(p, "port\n"+p->getId()); 102 | 103 | return true; 104 | } 105 | 106 | void Visitor::leave(std::shared_ptr p) { 107 | } 108 | 109 | bool Visitor::visit(std::shared_ptr ) { 110 | return true; 111 | } 112 | 113 | void Visitor::visit(std::shared_ptr t) { 114 | } 115 | 116 | void Visitor::visit(std::shared_ptr t) { 117 | } 118 | 119 | bool Visitor::visit(std::shared_ptr ) { 120 | return true; 121 | } 122 | 123 | bool Visitor::visit(std::shared_ptr ) { 124 | return true; 125 | } 126 | 127 | bool Visitor::visit(std::shared_ptr ) { 128 | return true; 129 | } 130 | 131 | 132 | bool Visitor::visit(std::shared_ptr g) { 133 | addNode(g, "stmt_group\n"); 134 | 135 | int i = 0; 136 | for (auto s : *g) 137 | addEdge(g, s, "[" + std::to_string(i++) + "]"); 138 | 139 | return true; 140 | } 141 | 142 | bool Visitor::visit(std::shared_ptr w) { 143 | addNode(w, "wire\n"+w->getId()); 144 | return true; 145 | } 146 | 147 | bool Visitor::visit(std::shared_ptr r) { 148 | addNode(r, "reg\n"+r->getId()); 149 | return false; 150 | } 151 | 152 | bool Visitor::visit(std::shared_ptr i) { 153 | addNode(i, "inst:\n"+i->getId()); 154 | return true; 155 | } 156 | 157 | bool Visitor::visit(std::shared_ptr m) { 158 | addNode(m, "memory:\n"+m->getId()); 159 | return true; 160 | } 161 | bool Visitor::visit(std::shared_ptr n) { 162 | addNode(n, "node:\n"+n->getId()); 163 | return true; 164 | } 165 | 166 | bool Visitor::visit(std::shared_ptr c) { 167 | addNode(c, "connect"); 168 | 169 | addEdge(c, c->getFrom(), "from"); 170 | c->getFrom()->accept(*this); 171 | 172 | addEdge(c, c->getTo(), "to"); 173 | c->getTo()->accept(*this); 174 | 175 | return false; 176 | } 177 | 178 | bool Visitor::visit(std::shared_ptr i) { 179 | addNode(i, "invalid"); 180 | return true; 181 | } 182 | 183 | void Visitor::leave(std::shared_ptr in) { 184 | } 185 | 186 | bool Visitor::visit(std::shared_ptr c) { 187 | addNode(c, "conditional"); 188 | 189 | addEdge(c, c->getCondition(), "cond"); 190 | 191 | addEdge(c, c->getThen(), "then"); 192 | 193 | if (c->getElse()) 194 | addEdge(c, c->getElse(), "else"); 195 | 196 | return true; 197 | } 198 | 199 | bool Visitor::visit(std::shared_ptr c) { 200 | addNode(c, "else"); 201 | return true; 202 | } 203 | 204 | bool Visitor::visit(std::shared_ptr s) { 205 | addNode(s, "stop"); 206 | return true; 207 | } 208 | 209 | bool Visitor::visit(std::shared_ptr p) { 210 | addNode(p, "printf"); 211 | return true; 212 | } 213 | 214 | void Visitor::visit(std::shared_ptr e) { 215 | addNode(e, "skip"); 216 | } 217 | 218 | void Visitor::visit(std::shared_ptr r) { 219 | addNode(r, "ref\n" + r->getToString()); 220 | } 221 | 222 | void Visitor::visit(std::shared_ptr c) { 223 | addNode(c, "const"); 224 | } 225 | 226 | bool Visitor::visit(std::shared_ptr s) { 227 | addNode(s, "subfield"); 228 | return true; 229 | } 230 | 231 | bool Visitor::visit(std::shared_ptr s) { 232 | addNode(s, "subindex"); 233 | return true; 234 | } 235 | 236 | bool Visitor::visit(std::shared_ptr s) { 237 | addNode(s, "subaccess"); 238 | return true; 239 | } 240 | 241 | bool Visitor::visit(std::shared_ptr m) { 242 | addNode(m, "mux"); 243 | return true; 244 | } 245 | 246 | bool Visitor::visit(std::shared_ptr c) { 247 | addNode(c, "condvalid"); 248 | return true; 249 | } 250 | 251 | bool Visitor::visit(std::shared_ptr op) { 252 | addNode(op, op->operationName()); 253 | 254 | int i = 0; 255 | for (auto o: op->getOperands()) 256 | addEdge(op, o, "["+std::to_string(i++)+"]"); 257 | 258 | return true; 259 | } 260 | 261 | void Visitor::addNode(std::shared_ptr node, std::string text) { 262 | std::string n; 263 | int id = mNodes.size(); 264 | mNodeDictionary[node] = id; 265 | n += std::to_string(id) + " [label=\"" + text + "\"];"; 266 | mNodes.push_back(n); 267 | } 268 | 269 | void Visitor::addEdge(std::shared_ptr from, std::shared_ptr to, 270 | std::string text) { 271 | mEdges.push_back(std::make_tuple(from, to, text)); 272 | } 273 | 274 | } 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /lib/backends/firrtl/include/FirrtlBackend.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "FirrtlatorBackend.h" 26 | #include "Visitor.h" 27 | 28 | #include 29 | #include 30 | 31 | namespace Firrtlator { 32 | namespace Backend { 33 | namespace Firrtl { 34 | 35 | class Backend : public ::Firrtlator::Backend::BackendBase { 36 | public: 37 | Backend(std::ostream &os); 38 | virtual void generate(std::shared_ptr ir); 39 | static std::string name; 40 | static std::string description; 41 | static std::vector filetypes; 42 | }; 43 | 44 | class Visitor : public ::Firrtlator::Visitor { 45 | public: 46 | Visitor(std::basic_stringstream > *os); 47 | 48 | virtual ~Visitor(); 49 | virtual bool visit(std::shared_ptr); 50 | virtual void leave(std::shared_ptr); 51 | 52 | virtual bool visit(std::shared_ptr); 53 | virtual void leave(std::shared_ptr); 54 | 55 | virtual bool visit(std::shared_ptr); 56 | virtual void leave(std::shared_ptr); 57 | 58 | virtual bool visit(std::shared_ptr); 59 | 60 | virtual void visit(std::shared_ptr); 61 | 62 | virtual void visit(std::shared_ptr); 63 | 64 | virtual bool visit(std::shared_ptr); 65 | 66 | virtual bool visit(std::shared_ptr); 67 | 68 | virtual bool visit(std::shared_ptr); 69 | virtual void leave(std::shared_ptr); 70 | 71 | virtual bool visit(std::shared_ptr); 72 | virtual void leave(std::shared_ptr); 73 | 74 | virtual bool visit(std::shared_ptr); 75 | virtual void leave(std::shared_ptr); 76 | 77 | virtual bool visit(std::shared_ptr); 78 | 79 | virtual bool visit(std::shared_ptr); 80 | virtual void leave(std::shared_ptr); 81 | 82 | virtual bool visit(std::shared_ptr); 83 | 84 | virtual bool visit(std::shared_ptr); 85 | virtual void leave(std::shared_ptr); 86 | 87 | virtual bool visit(std::shared_ptr); 88 | 89 | virtual bool visit(std::shared_ptr); 90 | virtual void leave(std::shared_ptr); 91 | 92 | virtual bool visit(std::shared_ptr); 93 | 94 | virtual bool visit(std::shared_ptr); 95 | 96 | virtual bool visit(std::shared_ptr); 97 | 98 | virtual bool visit(std::shared_ptr); 99 | 100 | virtual void visit(std::shared_ptr); 101 | 102 | virtual void visit(std::shared_ptr); 103 | 104 | virtual void visit(std::shared_ptr); 105 | 106 | virtual bool visit(std::shared_ptr); 107 | 108 | virtual bool visit(std::shared_ptr); 109 | 110 | virtual bool visit(std::shared_ptr); 111 | 112 | virtual bool visit(std::shared_ptr); 113 | 114 | virtual bool visit(std::shared_ptr); 115 | 116 | virtual bool visit(std::shared_ptr); 117 | private: 118 | std::basic_stringstream *mStream; 119 | void outputInfo(std::shared_ptr); 120 | }; 121 | 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /lib/backends/firrtl/src/FirrtlBackend.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "FirrtlBackend.h" 24 | #include "StreamIndentation.h" 25 | 26 | #include 27 | 28 | namespace Firrtlator { 29 | namespace Backend { 30 | namespace Firrtl { 31 | 32 | std::string Backend::name = "FIRRTL"; 33 | std::string Backend::description = "Generates FIRRTL files"; 34 | std::vector Backend::filetypes = { "fir" }; 35 | 36 | REGISTER_BACKEND(Backend) 37 | 38 | Backend::Backend(std::ostream &os) : ::Firrtlator::Backend::BackendBase(os) { 39 | 40 | } 41 | 42 | void Backend::generate(std::shared_ptr ir) { 43 | std::basic_stringstream sstream; 44 | Visitor v(&sstream); 45 | 46 | ir->accept(v); 47 | 48 | *mStream << sstream.str(); 49 | } 50 | 51 | Visitor::Visitor(std::basic_stringstream > *os) { 52 | mStream = os; 53 | } 54 | 55 | Visitor::~Visitor() { 56 | 57 | } 58 | 59 | bool Visitor::visit(std::shared_ptr c) { 60 | *mStream << "circuit " << c->getId() << " :"; 61 | 62 | outputInfo(c); 63 | 64 | *mStream << indent << endl; 65 | return true; 66 | } 67 | 68 | void Visitor::leave(std::shared_ptr c) { 69 | *mStream << dedent; 70 | } 71 | 72 | bool Visitor::visit(std::shared_ptr m) { 73 | bool ext = m->isExternal(); 74 | 75 | *mStream << (ext ? "extmodule " : "module ") << m->getId() << " :"; 76 | 77 | outputInfo(m); 78 | 79 | *mStream << indent << endl; 80 | return true; 81 | } 82 | 83 | void Visitor::leave(std::shared_ptr m) { 84 | *mStream << dedent; 85 | } 86 | 87 | bool Visitor::visit(std::shared_ptr p) { 88 | if (p->getDirection() == Port::INPUT) 89 | *mStream << "input "; 90 | else 91 | *mStream << "output "; 92 | *mStream << p->getId() << " : "; 93 | 94 | return true; 95 | } 96 | 97 | void Visitor::leave(std::shared_ptr p) { 98 | outputInfo(p); 99 | 100 | *mStream << endl; 101 | } 102 | 103 | bool Visitor::visit(std::shared_ptr ) { 104 | return true; 105 | } 106 | 107 | void Visitor::visit(std::shared_ptr t) { 108 | if (t->getSigned()) 109 | *mStream << "SInt"; 110 | else 111 | *mStream << "UInt"; 112 | 113 | *mStream << "<" << t->getWidth() << ">"; 114 | } 115 | 116 | void Visitor::visit(std::shared_ptr t) { 117 | *mStream << "Clock"; 118 | } 119 | 120 | bool Visitor::visit(std::shared_ptr f) { 121 | if (f->getFlip()) 122 | *mStream << "flip "; 123 | 124 | *mStream << f->getId(); 125 | *mStream << " : "; 126 | 127 | return true; 128 | } 129 | 130 | bool Visitor::visit(std::shared_ptr t) { 131 | *mStream << "{"; 132 | 133 | auto fields = t->getFields(); 134 | 135 | if (fields.size() > 0) { 136 | fields[0]->accept(*this); 137 | fields.erase(fields.begin()); 138 | } 139 | 140 | for (auto f : fields) { 141 | *mStream << ", "; 142 | f->accept(*this); 143 | } 144 | 145 | *mStream << " }"; 146 | return false; 147 | } 148 | 149 | bool Visitor::visit(std::shared_ptr ) { 150 | return true; 151 | } 152 | 153 | void Visitor::leave(std::shared_ptr t) { 154 | *mStream << "[" << std::to_string(t->getSize()) << "]"; 155 | } 156 | 157 | bool Visitor::visit(std::shared_ptr g) { 158 | return true; 159 | } 160 | 161 | void Visitor::leave(std::shared_ptr g) { 162 | 163 | } 164 | 165 | bool Visitor::visit(std::shared_ptr w) { 166 | *mStream << "wire " << w->getId() << " : "; 167 | return true; 168 | } 169 | 170 | void Visitor::leave(std::shared_ptr w) { 171 | *mStream << " "; 172 | outputInfo(w); 173 | *mStream << endl; 174 | } 175 | 176 | bool Visitor::visit(std::shared_ptr r) { 177 | std::shared_ptr type = r->getType(); 178 | std::shared_ptr clk = r->getClock(); 179 | std::shared_ptr rtrig = r->getResetTrigger(); 180 | std::shared_ptr rval = r->getResetValue(); 181 | *mStream << "reg " << r->getId() << " : "; 182 | 183 | type->accept(*this); 184 | 185 | *mStream << " "; 186 | 187 | clk->accept(*this); 188 | 189 | if (rtrig && rval) { 190 | *mStream << " with : ( reset => ( "; 191 | rtrig->accept(*this); 192 | *mStream << ", "; 193 | rval->accept(*this); 194 | *mStream << " ) "; 195 | } 196 | 197 | *mStream << ")"; 198 | 199 | outputInfo(r); 200 | 201 | *mStream << endl; 202 | 203 | return false; 204 | } 205 | 206 | bool Visitor::visit(std::shared_ptr inst) { 207 | *mStream << "inst " << inst->getId() << " of "; 208 | return true; 209 | } 210 | 211 | void Visitor::leave(std::shared_ptr inst) { 212 | *mStream << " "; 213 | outputInfo(inst); 214 | *mStream << endl; 215 | } 216 | 217 | bool Visitor::visit(std::shared_ptr m) { 218 | *mStream << "mem " << m->getId() << " : ("; 219 | outputInfo(m); 220 | *mStream << indent << endl; 221 | 222 | *mStream << "data-type => "; 223 | m->getDType()->accept(*this); 224 | *mStream << endl; 225 | *mStream << "depth => " << std::to_string(m->getDepth()) << endl; 226 | *mStream << "read-latency => " << std::to_string(m->getReadlatency()) << endl; 227 | *mStream << "write-latency => " << std::to_string(m->getWritelatency()) << endl; 228 | *mStream << "read-under-write => "; 229 | switch (m->getRuwflag()) { 230 | case Memory::RuwFlag::OLD: *mStream << "old" << endl; break; 231 | case Memory::RuwFlag::NEW: *mStream << "new" << endl; break; 232 | default: *mStream << "undefined" << endl; break; 233 | } 234 | 235 | for (auto r : m->getReaders()) 236 | *mStream << "reader => " << r << endl; 237 | 238 | for (auto w : m->getWriters()) 239 | *mStream << "writer => " << w << endl; 240 | 241 | for (auto rw : m->getReadWriters()) 242 | *mStream << "readwriter => " << rw << endl; 243 | 244 | *mStream << ")" << dedent << endl; 245 | 246 | return false; 247 | } 248 | 249 | bool Visitor::visit(std::shared_ptr n) { 250 | *mStream << "node " << n->getId() << " = "; 251 | return true; 252 | } 253 | 254 | void Visitor::leave(std::shared_ptr n) { 255 | *mStream << " "; 256 | outputInfo(n); 257 | *mStream << endl; 258 | } 259 | 260 | bool Visitor::visit(std::shared_ptr c) { 261 | std::shared_ptr from, to; 262 | 263 | from = c->getFrom(); 264 | to = c->getTo(); 265 | 266 | to->accept(*this); 267 | 268 | if (c->getPartial()) 269 | *mStream << " <- "; 270 | else 271 | *mStream << " <= "; 272 | 273 | from->accept(*this); 274 | 275 | outputInfo(c); 276 | 277 | *mStream << endl; 278 | 279 | return false; 280 | } 281 | 282 | bool Visitor::visit(std::shared_ptr ) { 283 | return true; 284 | } 285 | 286 | void Visitor::leave(std::shared_ptr i) { 287 | *mStream << " is invalid"; 288 | outputInfo(i); 289 | *mStream << endl; 290 | } 291 | 292 | bool Visitor::visit(std::shared_ptr c) { 293 | *mStream << "when "; 294 | c->getCondition()->accept(*this); 295 | *mStream << " :"; 296 | outputInfo(c); 297 | *mStream << indent << endl; 298 | 299 | c->getThen()->accept(*this); 300 | 301 | *mStream << dedent; 302 | 303 | if (c->getElse()) 304 | c->getElse()->accept(*this); 305 | 306 | return false; 307 | } 308 | 309 | bool Visitor::visit(std::shared_ptr e) { 310 | *mStream << "else :"; 311 | outputInfo(e); 312 | *mStream << indent << endl; 313 | 314 | e->getStmts()->accept(*this); 315 | 316 | *mStream << dedent; 317 | 318 | return true; 319 | } 320 | 321 | bool Visitor::visit(std::shared_ptr s) { 322 | *mStream << "stop("; 323 | s->getClock()->accept(*this); 324 | *mStream << ", "; 325 | s->getCondition()->accept(*this); 326 | *mStream << ", " << std::to_string(s->getCode()); 327 | *mStream << ")"; 328 | outputInfo(s); 329 | *mStream << endl; 330 | return false; 331 | } 332 | 333 | bool Visitor::visit(std::shared_ptr p) { 334 | *mStream << "printf("; 335 | p->getClock()->accept(*this); 336 | *mStream << ", "; 337 | p->getCondition()->accept(*this); 338 | *mStream << ", \"" << p->getFormat() << "\")" << endl; 339 | return false; 340 | } 341 | 342 | void Visitor::visit(std::shared_ptr e) { 343 | *mStream << "skip"; 344 | outputInfo(e); 345 | *mStream << endl; 346 | } 347 | 348 | void Visitor::visit(std::shared_ptr r) { 349 | *mStream << r->getToString(); 350 | } 351 | 352 | void Visitor::visit(std::shared_ptr c) { 353 | *mStream << c->getString(); 354 | } 355 | 356 | bool Visitor::visit(std::shared_ptr f) { 357 | f->getOf()->accept(*this); 358 | *mStream << "."; 359 | f->getField()->accept(*this); 360 | 361 | return false; 362 | } 363 | 364 | bool Visitor::visit(std::shared_ptr i) { 365 | i->getOf()->accept(*this); 366 | *mStream << "[" << std::to_string(i->getIndex()) << "]"; 367 | 368 | return false; 369 | } 370 | 371 | bool Visitor::visit(std::shared_ptr a) { 372 | a->getOf()->accept(*this); 373 | *mStream << "["; 374 | a->getExp()->accept(*this); 375 | *mStream << "]"; 376 | return false; 377 | } 378 | 379 | bool Visitor::visit(std::shared_ptr m) { 380 | *mStream << "mux("; 381 | m->getSel()->accept(*this); 382 | *mStream << ", "; 383 | m->getA()->accept(*this); 384 | *mStream << ", "; 385 | m->getB()->accept(*this); 386 | *mStream << ")"; 387 | 388 | return false; 389 | } 390 | 391 | bool Visitor::visit(std::shared_ptr c) { 392 | *mStream << "mux("; 393 | c->getSel()->accept(*this); 394 | *mStream << ", "; 395 | c->getA()->accept(*this); 396 | *mStream << ")"; 397 | 398 | return false; 399 | } 400 | 401 | bool Visitor::visit(std::shared_ptr op) { 402 | *mStream << op->operationName() << "("; 403 | 404 | auto ops = op->getOperands(); 405 | auto params = op->getParameters(); 406 | 407 | ops[0]->accept(*this); 408 | ops.erase(ops.begin()); 409 | 410 | for (auto o : ops) { 411 | *mStream << ", "; 412 | o->accept(*this); 413 | } 414 | 415 | *mStream << ")"; 416 | 417 | return false; 418 | } 419 | 420 | void Visitor::outputInfo(std::shared_ptr n) { 421 | std::shared_ptr info = n->getInfo(); 422 | 423 | if (info) 424 | *mStream << " @[" << info->getValue() << "]"; 425 | } 426 | 427 | } 428 | } 429 | } 430 | -------------------------------------------------------------------------------- /lib/backends/generic/include/StreamIndentation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include 26 | 27 | namespace Firrtlator { 28 | 29 | std::basic_ostream>& indent(std::basic_ostream>& stream); 30 | 31 | std::basic_ostream>& dedent(std::basic_ostream>& stream); 32 | 33 | std::basic_ostream>& endl(std::basic_ostream>& stream); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /lib/backends/generic/src/Backends.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "Firrtlator.h" 24 | #include "FirrtlBackend.h" 25 | 26 | namespace Firrtlator { 27 | namespace Backend { 28 | 29 | 30 | void Registry::registerBackend(const std::string &name, 31 | BackendFactory* factory) { 32 | getBackendMap()[name] = factory; 33 | } 34 | 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/backends/generic/src/StreamIndentation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "StreamIndentation.h" 24 | #include "Util.h" 25 | 26 | #include 27 | #include 28 | 29 | namespace Firrtlator { 30 | 31 | /* Helper function to get a storage index in a stream */ 32 | static int get_indent_index() { 33 | static int index = std::ios_base::xalloc(); 34 | return index; 35 | } 36 | 37 | inline void beginOfLine(std::basic_stringstream* stream) { 38 | std::stringbuf *pbuf = stream->rdbuf(); 39 | int p, origin = stream->tellp(); 40 | 41 | 42 | for (p = origin-1; p > 0; p--) { 43 | pbuf->pubseekpos(p-1); 44 | char c = pbuf->sgetc(); 45 | if (c == '\n') { 46 | pbuf->pubseekpos(p); 47 | int indent = stream->iword(get_indent_index()); 48 | while (indent) { 49 | *stream << " "; 50 | indent--; 51 | } 52 | break; 53 | } else if ((c == ' ') || (c == '\n')) { 54 | /* continue skipping */ 55 | } else { 56 | pbuf->pubseekpos(origin); 57 | break; 58 | } 59 | } 60 | } 61 | 62 | std::basic_ostream>& indent(std::basic_ostream>& stream) { 63 | std::basic_stringstream *sstream; 64 | 65 | stream.iword(get_indent_index())++; 66 | sstream = dynamic_cast* >(&stream); 67 | if (sstream) { 68 | beginOfLine(sstream); 69 | } 70 | 71 | return stream; 72 | } 73 | 74 | std::basic_ostream>& dedent(std::basic_ostream>& stream) { 75 | std::basic_stringstream *sstream; 76 | throwAssert((stream.iword(get_indent_index()) > 0), "Cannot dedent at level 0"); 77 | 78 | stream.iword(get_indent_index())--; 79 | 80 | sstream = dynamic_cast* >(&stream); 81 | if (sstream) { 82 | beginOfLine(sstream); 83 | } 84 | return stream; 85 | } 86 | 87 | std::basic_ostream>& endl(std::basic_ostream>& stream) { 88 | int indent = stream.iword(get_indent_index()); 89 | stream.put(stream.widen('\n')); 90 | 91 | while (indent) { 92 | stream << " "; 93 | indent--; 94 | } 95 | stream.flush(); 96 | return stream; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /lib/backends/tree/include/TreeBackend.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "FirrtlatorBackend.h" 26 | #include "Visitor.h" 27 | 28 | #include 29 | #include 30 | 31 | namespace Firrtlator { 32 | namespace Backend { 33 | namespace Tree { 34 | 35 | class Backend : public ::Firrtlator::Backend::BackendBase { 36 | public: 37 | Backend(std::ostream &os); 38 | virtual void generate(std::shared_ptr ir); 39 | static std::string name; 40 | static std::string description; 41 | static std::vector filetypes; 42 | }; 43 | 44 | class Visitor : public ::Firrtlator::Visitor { 45 | public: 46 | Visitor(std::basic_stringstream > *os); 47 | 48 | virtual ~Visitor(); 49 | virtual bool visit(std::shared_ptr); 50 | virtual void leave(std::shared_ptr); 51 | 52 | virtual bool visit(std::shared_ptr); 53 | virtual void leave(std::shared_ptr); 54 | 55 | virtual bool visit(std::shared_ptr); 56 | virtual void leave(std::shared_ptr); 57 | 58 | virtual bool visit(std::shared_ptr); 59 | 60 | virtual void visit(std::shared_ptr); 61 | 62 | virtual void visit(std::shared_ptr); 63 | 64 | virtual bool visit(std::shared_ptr); 65 | virtual void leave(std::shared_ptr); 66 | 67 | virtual bool visit(std::shared_ptr); 68 | virtual void leave(std::shared_ptr); 69 | 70 | virtual bool visit(std::shared_ptr); 71 | virtual void leave(std::shared_ptr); 72 | 73 | virtual bool visit(std::shared_ptr); 74 | virtual void leave(std::shared_ptr); 75 | 76 | virtual bool visit(std::shared_ptr); 77 | virtual void leave(std::shared_ptr); 78 | 79 | virtual bool visit(std::shared_ptr); 80 | 81 | virtual bool visit(std::shared_ptr); 82 | virtual void leave(std::shared_ptr); 83 | 84 | virtual bool visit(std::shared_ptr); 85 | 86 | virtual bool visit(std::shared_ptr); 87 | virtual void leave(std::shared_ptr); 88 | 89 | virtual bool visit(std::shared_ptr); 90 | 91 | virtual bool visit(std::shared_ptr); 92 | virtual void leave(std::shared_ptr); 93 | 94 | virtual bool visit(std::shared_ptr); 95 | virtual void leave(std::shared_ptr); 96 | 97 | virtual bool visit(std::shared_ptr); 98 | virtual void leave(std::shared_ptr); 99 | 100 | virtual bool visit(std::shared_ptr); 101 | 102 | virtual bool visit(std::shared_ptr); 103 | 104 | virtual void visit(std::shared_ptr); 105 | 106 | virtual void visit(std::shared_ptr); 107 | 108 | virtual void visit(std::shared_ptr); 109 | 110 | virtual bool visit(std::shared_ptr); 111 | 112 | virtual bool visit(std::shared_ptr); 113 | 114 | virtual bool visit(std::shared_ptr); 115 | 116 | virtual bool visit(std::shared_ptr); 117 | 118 | virtual bool visit(std::shared_ptr); 119 | 120 | virtual bool visit(std::shared_ptr); 121 | virtual void leave(std::shared_ptr); 122 | private: 123 | std::basic_stringstream *mStream; 124 | void outputInfo(std::shared_ptr); 125 | }; 126 | 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /lib/backends/tree/src/TreeBackend.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "StreamIndentation.h" 24 | 25 | #include 26 | 27 | #include "TreeBackend.h" 28 | 29 | #include 30 | 31 | namespace Firrtlator { 32 | namespace Backend { 33 | namespace Tree { 34 | 35 | std::string Backend::name = "tree"; 36 | std::string Backend::description = "Dump the IR tree in ASCII"; 37 | std::vector Backend::filetypes = { "tree" }; 38 | 39 | REGISTER_BACKEND(Backend) 40 | 41 | Backend::Backend(std::ostream &os) : BackendBase(os) { 42 | 43 | } 44 | 45 | void Backend::generate(std::shared_ptr ir) { 46 | std::basic_stringstream sstream; 47 | Visitor v(&sstream); 48 | 49 | ir->accept(v); 50 | 51 | *mStream << sstream.str(); 52 | } 53 | 54 | Visitor::Visitor(std::basic_stringstream *os) { 55 | mStream = os; 56 | } 57 | 58 | Visitor::~Visitor() { 59 | 60 | } 61 | 62 | bool Visitor::visit(std::shared_ptr c) { 63 | *mStream << "(circuit) id=" << c->getId(); 64 | outputInfo(c); 65 | *mStream << indent << endl; 66 | return true; 67 | } 68 | 69 | void Visitor::leave(std::shared_ptr c) { 70 | *mStream << dedent; 71 | } 72 | 73 | bool Visitor::visit(std::shared_ptr m) { 74 | *mStream << "(module) id=" << m->getId(); 75 | outputInfo(m); 76 | *mStream << indent << endl; 77 | return true; 78 | } 79 | 80 | void Visitor::leave(std::shared_ptr m) { 81 | *mStream << dedent; 82 | } 83 | 84 | bool Visitor::visit(std::shared_ptr p) { 85 | *mStream << "(port) id=" << p->getId() << ", dir="; 86 | if (p->getDirection() == Port::INPUT) 87 | *mStream << "input"; 88 | else 89 | *mStream << "output"; 90 | outputInfo(p); 91 | *mStream << indent << endl; 92 | return true; 93 | } 94 | 95 | void Visitor::leave(std::shared_ptr p) { 96 | *mStream << dedent; 97 | } 98 | 99 | bool Visitor::visit(std::shared_ptr ) { 100 | return true; 101 | } 102 | 103 | void Visitor::visit(std::shared_ptr t) { 104 | *mStream << "(type int) signed=" << (t->getSigned() ? "true" : "false"); 105 | *mStream << ", width=" << t->getWidth() << endl; 106 | } 107 | 108 | void Visitor::visit(std::shared_ptr t) { 109 | *mStream << "(type clock)" << endl; 110 | } 111 | 112 | bool Visitor::visit(std::shared_ptr f) { 113 | *mStream << "(field) id=" << f->getId(); 114 | *mStream << ", flipped=" << (f->getFlip() ? "true" : "false"); 115 | *mStream << indent; 116 | return true; 117 | } 118 | 119 | void Visitor::leave(std::shared_ptr ) { 120 | *mStream << dedent; 121 | } 122 | 123 | bool Visitor::visit(std::shared_ptr b) { 124 | *mStream << "(type bundle)" << indent << endl; 125 | return true; 126 | } 127 | 128 | void Visitor::leave(std::shared_ptr b) { 129 | *mStream << dedent; 130 | } 131 | 132 | bool Visitor::visit(std::shared_ptr v) { 133 | *mStream << "(type vector) size=" << v->getSize(); 134 | *mStream << indent << endl; 135 | return true; 136 | } 137 | 138 | void Visitor::leave(std::shared_ptr b) { 139 | *mStream << dedent; 140 | } 141 | 142 | bool Visitor::visit(std::shared_ptr ) { 143 | *mStream << "(stmt group)" << indent << endl; 144 | return true; 145 | } 146 | 147 | void Visitor::leave(std::shared_ptr ) { 148 | *mStream << dedent; 149 | } 150 | 151 | 152 | bool Visitor::visit(std::shared_ptr w) { 153 | *mStream << "(wire) id=" << w->getId(); 154 | outputInfo(w); 155 | *mStream << indent << endl;; 156 | return true; 157 | } 158 | 159 | void Visitor::leave(std::shared_ptr ) { 160 | *mStream << dedent; 161 | } 162 | 163 | bool Visitor::visit(std::shared_ptr r) { 164 | *mStream << "(reg) id=" << r->getId(); 165 | outputInfo(r); 166 | *mStream << indent << endl; 167 | *mStream << "[type] "; 168 | r->getType()->accept(*this); 169 | *mStream << "[clock] "; 170 | r->getClock()->accept(*this); 171 | if (r->getResetTrigger()) { 172 | *mStream << "[reset trigger] "; 173 | r->getResetTrigger()->accept(*this); 174 | *mStream << "[reset value] "; 175 | r->getResetValue()->accept(*this); 176 | } 177 | outputInfo(r); 178 | *mStream << dedent; 179 | return false; 180 | } 181 | 182 | bool Visitor::visit(std::shared_ptr i) { 183 | *mStream << "(inst) id=" << i->getId(); 184 | outputInfo(i); 185 | *mStream << indent << endl; 186 | return true; 187 | } 188 | 189 | void Visitor::leave(std::shared_ptr ) { 190 | *mStream << dedent; 191 | } 192 | 193 | bool Visitor::visit(std::shared_ptr m) { 194 | *mStream << "(memory)"; 195 | outputInfo(m); 196 | return false; 197 | } 198 | 199 | bool Visitor::visit(std::shared_ptr n) { 200 | *mStream << "(node) id=" << n->getId(); 201 | outputInfo(n); 202 | *mStream << indent << endl; 203 | return true; 204 | } 205 | 206 | void Visitor::leave(std::shared_ptr n) { 207 | *mStream << dedent; 208 | } 209 | 210 | bool Visitor::visit(std::shared_ptr c) { 211 | *mStream << "(connect) partial=" << (c->getPartial() ? "true" : "false"); 212 | outputInfo(c); 213 | *mStream << indent << endl << "[to]"; 214 | c->getTo()->accept(*this); 215 | *mStream << "[from]"; 216 | c->getFrom()->accept(*this); 217 | *mStream << dedent; 218 | return false; 219 | } 220 | 221 | bool Visitor::visit(std::shared_ptr i) { 222 | *mStream << "(invalid)"; 223 | outputInfo(i); 224 | *mStream << indent << endl; 225 | return true; 226 | } 227 | 228 | void Visitor::leave(std::shared_ptr) { 229 | *mStream << dedent; 230 | } 231 | 232 | bool Visitor::visit(std::shared_ptr c) { 233 | *mStream << "(when)" << indent << endl; 234 | *mStream << "[cond]"; 235 | 236 | return true; 237 | } 238 | 239 | void Visitor::leave(std::shared_ptr) { 240 | *mStream << dedent; 241 | } 242 | 243 | bool Visitor::visit(std::shared_ptr e) { 244 | *mStream << "(else)" << indent << endl; 245 | return true; 246 | } 247 | 248 | void Visitor::leave(std::shared_ptr) { 249 | *mStream << dedent; 250 | } 251 | 252 | bool Visitor::visit(std::shared_ptr s) { 253 | *mStream << "(stop) code=" << s->getCode(); 254 | outputInfo(s); 255 | *mStream << indent << endl; 256 | *mStream << "[clk]"; 257 | s->getClock()->accept(*this); 258 | *mStream << "[cond]"; 259 | s->getCondition()->accept(*this); 260 | *mStream << dedent; 261 | return false; 262 | } 263 | 264 | bool Visitor::visit(std::shared_ptr p) { 265 | *mStream << "(printf) format=\"" << p->getFormat() << "\"" << endl; 266 | outputInfo(p); 267 | *mStream << indent << "[clock]"; 268 | p->getClock()->accept(*this); 269 | *mStream << "[condition]"; 270 | p->getCondition()->accept(*this); 271 | 272 | for (auto a : p->getArguments()) 273 | a->accept(*this); 274 | 275 | *mStream << dedent; 276 | return false; 277 | } 278 | 279 | void Visitor::visit(std::shared_ptr e) { 280 | *mStream << "(skip)"; 281 | outputInfo(e); 282 | *mStream << endl; 283 | } 284 | 285 | void Visitor::visit(std::shared_ptr r) { 286 | *mStream << "(ref) to=" << r->getToString() << endl; 287 | } 288 | 289 | void Visitor::visit(std::shared_ptr c) { 290 | *mStream << "(const) value=" << c->getValue() << endl; 291 | *mStream << indent; 292 | c->getType()->accept(*this); 293 | *mStream << dedent; 294 | } 295 | 296 | bool Visitor::visit(std::shared_ptr s) { 297 | *mStream << "(subfield)" << indent << endl; 298 | *mStream << "[field]"; 299 | s->getField()->accept(*this); 300 | *mStream << "[of]"; 301 | s->getOf()->accept(*this); 302 | *mStream << dedent; 303 | return false; 304 | } 305 | 306 | bool Visitor::visit(std::shared_ptr s) { 307 | *mStream << "(subindex) index=" << s->getIndex() << indent << endl; 308 | *mStream << "[of]"; 309 | s->getOf()->accept(*this); 310 | *mStream << dedent; 311 | return false; 312 | } 313 | 314 | bool Visitor::visit(std::shared_ptr s) { 315 | *mStream << "(subaccess)" << indent << endl; 316 | *mStream << "[expr]"; 317 | s->getExp()->accept(*this); 318 | *mStream << "[of]"; 319 | s->getOf()->accept(*this); 320 | *mStream << dedent; 321 | return false; 322 | } 323 | 324 | bool Visitor::visit(std::shared_ptr m) { 325 | *mStream << "(mux)" << indent << endl; 326 | *mStream << "[sel]"; 327 | m->getSel()->accept(*this); 328 | *mStream << "[a]"; 329 | m->getA()->accept(*this); 330 | *mStream << "[b]"; 331 | m->getB()->accept(*this); 332 | *mStream << dedent; 333 | return false; 334 | } 335 | 336 | bool Visitor::visit(std::shared_ptr c) { 337 | *mStream << "(condvalid)" << indent << endl; 338 | *mStream << "[sel]"; 339 | c->getSel()->accept(*this); 340 | *mStream << "[a]"; 341 | c->getA()->accept(*this); 342 | *mStream << dedent; 343 | return false; 344 | } 345 | 346 | bool Visitor::visit(std::shared_ptr op) { 347 | *mStream << "(" << op->operationName() << ")" << indent << endl; 348 | return true; 349 | } 350 | 351 | void Visitor::leave(std::shared_ptr op) { 352 | *mStream << dedent; 353 | } 354 | void Visitor::outputInfo(std::shared_ptr n) { 355 | if (n->getInfo()) { 356 | *mStream << ", info=\"" << n->getInfo()->getValue() << "\""; 357 | } 358 | } 359 | 360 | } 361 | } 362 | } 363 | -------------------------------------------------------------------------------- /lib/frontends/FirrtlatorFrontend.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "IR.h" 30 | #include "Firrtlator.h" 31 | 32 | namespace Firrtlator { 33 | namespace Frontend { 34 | 35 | class FrontendBase { 36 | public: 37 | virtual ~FrontendBase(); 38 | virtual bool parseString(std::string::const_iterator begin, 39 | std::string::const_iterator end) = 0; 40 | virtual std::shared_ptr getIR(); 41 | protected: 42 | std::shared_ptr mIR; 43 | }; 44 | 45 | class FrontendFactory 46 | { 47 | public: 48 | virtual ~FrontendFactory() {} 49 | virtual std::shared_ptr create() = 0; 50 | 51 | virtual std::string getName() = 0; 52 | virtual std::string getDescription() = 0; 53 | virtual std::vector getFiletypes() = 0; 54 | }; 55 | 56 | class Registry { 57 | public: 58 | static void registerFrontend(const std::string &name, 59 | FrontendFactory * factory); 60 | static std::shared_ptr create(const std::string &name) { 61 | throwAssert(getFrontendMap().find(name) != getFrontendMap().end(), 62 | "Cannot find frontend: " + name); 63 | return getFrontendMap()[name]->create(); 64 | } 65 | 66 | static std::vector getDescriptors() { 67 | std::vector list; 68 | for (auto b : getFrontendMap()) { 69 | Firrtlator::FrontendDescriptor desc; 70 | desc.name = b.second->getName(); 71 | desc.description = b.second->getDescription(); 72 | desc.filetypes = b.second->getFiletypes(); 73 | list.push_back(desc); 74 | } 75 | return list; 76 | } 77 | private: 78 | typedef std::map FrontendMap; 79 | static FrontendMap &getFrontendMap() { 80 | static FrontendMap map; 81 | return map; 82 | } 83 | }; 84 | 85 | } 86 | } 87 | 88 | #define REGISTER_FRONTEND(frontend) \ 89 | class frontend##Factory : public ::Firrtlator::Frontend::FrontendFactory { \ 90 | public: \ 91 | frontend##Factory() \ 92 | { \ 93 | ::Firrtlator::Frontend::Registry::registerFrontend(frontend::name, \ 94 | this); \ 95 | } \ 96 | virtual std::shared_ptr<::Firrtlator::Frontend::FrontendBase> create() { \ 97 | return std::make_shared(); \ 98 | } \ 99 | virtual std::string getName() { \ 100 | return frontend::name; \ 101 | } \ 102 | virtual std::string getDescription() { \ 103 | return frontend::description; \ 104 | } \ 105 | virtual std::vector getFiletypes() { \ 106 | return frontend::filetypes; \ 107 | } \ 108 | }; \ 109 | static frontend##Factory global_##frontend##Factory; 110 | -------------------------------------------------------------------------------- /lib/frontends/firrtl/include/FirrtlFrontend.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "FirrtlatorFrontend.h" 26 | 27 | namespace Firrtlator { 28 | namespace Frontend { 29 | namespace Firrtl { 30 | 31 | class Frontend : public ::Firrtlator::Frontend::FrontendBase { 32 | public: 33 | virtual bool parseString(std::string::const_iterator begin, 34 | std::string::const_iterator end); 35 | static std::string name; 36 | static std::string description; 37 | static std::vector filetypes; 38 | }; 39 | 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/frontends/firrtl/include/FirrtlFrontendGrammar.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */#pragma once 22 | 23 | //#define BOOST_SPIRIT_DEBUG 1 24 | 25 | #include "FirrtlFrontendLexer.h" 26 | 27 | #include 28 | #include 29 | 30 | namespace Firrtlator { 31 | namespace Frontend { 32 | namespace Firrtl { 33 | 34 | namespace qi = boost::spirit::qi; 35 | namespace ascii = boost::spirit::ascii; 36 | namespace phoenix = boost::phoenix; 37 | 38 | template 39 | struct make_shared_f 40 | { 41 | template struct result 42 | { typedef std::shared_ptr type; }; 43 | 44 | template 45 | typename result::type operator()(A&&... a) const { 46 | return std::make_shared(std::forward(a)...); 47 | } 48 | }; 49 | 50 | template 51 | using make_shared = phoenix::function >; 52 | 53 | struct gen_primop_f 54 | { 55 | struct result { typedef std::shared_ptr type; }; 56 | 57 | typename result::type operator()(std::string &op) const { 58 | return PrimOp::generate(op); 59 | } 60 | }; 61 | 62 | using gen_primop = phoenix::function; 63 | 64 | template 65 | struct FirrtlGrammar : qi::grammar()> 66 | { 67 | template< typename TokenDef > 68 | FirrtlGrammar(const TokenDef& tok) : FirrtlGrammar::base_type(circuit) 69 | { 70 | using qi::lit; 71 | using qi::lexeme; 72 | using ascii::char_; 73 | using ascii::alpha; 74 | using ascii::alnum; 75 | using ascii::string; 76 | using namespace qi::labels; 77 | 78 | using phoenix::at_c; 79 | using phoenix::push_back; 80 | using phoenix::construct; 81 | using phoenix::function; 82 | using phoenix::bind; 83 | 84 | using boost::spirit::eps; 85 | 86 | circuit = tok.circuit 87 | >> tok.identifier [_val = make_shared()(_1)] 88 | >> ":" 89 | >> -info [bind(&Circuit::setInfo, _val, _1)] 90 | >> -(qi::token(INDENT) 91 | >> *module [bind(&Circuit::addModule, _val, _1)] 92 | >> qi::token(DEDENT)) 93 | ; 94 | BOOST_SPIRIT_DEBUG_NODE(circuit); 95 | 96 | info = tok.info[_val = make_shared()(_1)] 97 | ; 98 | BOOST_SPIRIT_DEBUG_NODE(info); 99 | 100 | module %= intmodule | 101 | extmodule 102 | ; 103 | BOOST_SPIRIT_DEBUG_NODE(module); 104 | 105 | intmodule = 106 | tok.module 107 | >> tok.identifier [_val = make_shared()(_1, false)] 108 | >> ":" 109 | >> -info [bind(&Module::setInfo, _val, _1)] 110 | >> -( 111 | qi::token(INDENT) 112 | >> *port [bind(&Module::addPort, _val, _1)] 113 | >> stmt_group [bind(&Module::setStatementGroup, _val, _1)] 114 | >> qi::token(DEDENT) 115 | ) 116 | ; 117 | BOOST_SPIRIT_DEBUG_NODE(intmodule); 118 | 119 | extmodule = 120 | tok.extmodule 121 | >> tok.identifier [_val = make_shared()(_1, true)] 122 | >> ":" 123 | >> -info [bind(&Module::setInfo, _val, _1)] 124 | >> -( 125 | qi::token(INDENT) 126 | >> *port [bind(&Module::addPort, _val, _1)] 127 | >> -defname [bind(&Module::setDefname, _val, _1)] 128 | >> *parameter [bind(&Module::addParameter, _val, _1)] 129 | >> qi::token(DEDENT) 130 | ) 131 | ; 132 | BOOST_SPIRIT_DEBUG_NODE(extmodule); 133 | 134 | port = (tok.input [_a = Port::Direction::INPUT] 135 | | tok.output [_a = Port::Direction::OUTPUT]) 136 | >> (tok.identifier 137 | >> ":" >> type ) [_val = make_shared()(_1, _a, _2)] 138 | >> -info [bind(&Port::setInfo, _val, _1)] 139 | ; 140 | BOOST_SPIRIT_DEBUG_NODE(port); 141 | 142 | defname = tok.defname >> "=" >> tok.identifier [_val = _1] 143 | ; 144 | BOOST_SPIRIT_DEBUG_NODE(defname); 145 | 146 | parameter = tok.parameter [_val = make_shared()()] 147 | >> tok.identifier >> "=" >> 148 | (tok.int_ | tok.double_ | tok.string_double | tok.string_single) 149 | ; 150 | BOOST_SPIRIT_DEBUG_NODE(parameter); 151 | 152 | type = type_int [_val = _1] 153 | | tok.Clock [_val = make_shared()()] 154 | | type_bundle [_val = _1] 155 | | type_vector [_val = _1] 156 | ; 157 | BOOST_SPIRIT_DEBUG_NODE(type); 158 | 159 | type_int = (tok.UInt [_val = make_shared()(false)] 160 | | tok.SInt [_val = make_shared()(true)]) 161 | >> -("<" >> tok.int_ [bind(&TypeInt::setWidth, _val, _1)] >> ">") 162 | ; 163 | BOOST_SPIRIT_DEBUG_NODE(type_int); 164 | 165 | type_bundle = lit("{") [_val = make_shared()()] 166 | >> *field [bind(&TypeBundle::addField, _val, _1)] 167 | >> "}" 168 | ; 169 | BOOST_SPIRIT_DEBUG_NODE(type_bundle); 170 | 171 | type_vector = type [_val = make_shared()()] 172 | >> "[" 173 | >> tok.int_ [bind(&TypeVector::setSize, _val, _1)] 174 | >> "]" 175 | ; 176 | BOOST_SPIRIT_DEBUG_NODE(type_vector); 177 | 178 | field = (eps [_a = false] 179 | | tok.flip [_a = true]) 180 | >> (tok.identifier 181 | >> ":" 182 | >> type) [_val = make_shared()(_1, _2, _a)] 183 | ; 184 | BOOST_SPIRIT_DEBUG_NODE(field); 185 | 186 | stmt %= wire | reg | mem | inst | node | connect | partconnect 187 | | invalidate | conditional | stop | printf_ | empty 188 | ; 189 | BOOST_SPIRIT_DEBUG_NODE(stmt); 190 | 191 | stmt_group = eps [_val = make_shared()()] 192 | >> +stmt [bind(&StmtGroup::addStatement,_val,_1)] 193 | ; 194 | BOOST_SPIRIT_DEBUG_NODE(stmt_group); 195 | 196 | stmt_suite = (qi::tokenid(INDENT) 197 | >> stmt_group [_val = _1] 198 | >> qi::tokenid(DEDENT)) 199 | ; 200 | BOOST_SPIRIT_DEBUG_NODE(stmt_suite); 201 | 202 | wire = tok.wire 203 | >> (tok.identifier 204 | >> ":" 205 | >> type) [_val = make_shared()(_1, _2)] 206 | >> -info [bind(&Stmt::setInfo, _val, _1)] 207 | ; 208 | BOOST_SPIRIT_DEBUG_NODE(wire); 209 | 210 | reg = tok.reg 211 | >> (tok.identifier 212 | >> ":" 213 | >> type 214 | >> exp_) [_val = make_shared()(_1, _2, _3)] 215 | >> -(tok.with >> ":" >> '(' 216 | >> tok.identifier [ qi::_pass = (_1 == "reset") ] 217 | >> tok.assign >> '(' 218 | >> exp_ [bind(&Reg::setResetTrigger, _val, _1)] 219 | >> exp_ [bind(&Reg::setResetValue, _val, _1)] 220 | >> ')' >> ')' ) 221 | >> -info [bind(&Stmt::setInfo, _val, _1)] 222 | ; 223 | BOOST_SPIRIT_DEBUG_NODE(reg); 224 | 225 | mem = tok.mem 226 | >> tok.identifier [_val = make_shared()(_1)] 227 | >> ":" >> "(" 228 | >> *(mem_dtype(_val) | mem_depth(_val) | mem_readlat(_val) 229 | | mem_writelat(_val) | mem_ruw(_val) | mem_reader(_val) 230 | | mem_writer(_val) | mem_readwriter(_val)) 231 | >> ")" 232 | ; 233 | BOOST_SPIRIT_DEBUG_NODE(mem); 234 | 235 | mem_dtype = tok.dtype >> tok.assign 236 | >> type [bind(&Memory::setDType, _r1, _1)] 237 | ; 238 | BOOST_SPIRIT_DEBUG_NODE(mem_dtype); 239 | 240 | mem_depth = tok.depth >> tok.assign 241 | >> tok.int_ [bind(&Memory::setDepth, _r1, _1)] 242 | ; 243 | BOOST_SPIRIT_DEBUG_NODE(mem_depth); 244 | 245 | mem_readlat = tok.readlat >> tok.assign 246 | >> tok.int_ [bind(&Memory::setReadLatency, _r1, _1)] 247 | ; 248 | BOOST_SPIRIT_DEBUG_NODE(mem_readlat); 249 | 250 | mem_writelat = tok.writelat >> tok.assign 251 | >> tok.int_ [bind(&Memory::setWriteLatency, _r1, _1)] 252 | ; 253 | BOOST_SPIRIT_DEBUG_NODE(mem_writelat); 254 | 255 | mem_ruw = tok.ruw >> tok.assign >> 256 | (tok.old [_a = Memory::RuwFlag::OLD] 257 | | tok.new_ [_a = Memory::RuwFlag::NEW] 258 | | tok.undefined [_a = Memory::RuwFlag::UNDEFINED] 259 | ) [bind(&Memory::setRuwFlag, _r1, _a)] 260 | ; 261 | BOOST_SPIRIT_DEBUG_NODE(mem_ruw); 262 | 263 | mem_reader = tok.reader >> tok.assign 264 | >> tok.identifier [bind(&Memory::addReader, _r1, _1)] 265 | ; 266 | BOOST_SPIRIT_DEBUG_NODE(mem_reader); 267 | 268 | mem_writer = tok.writer >> tok.assign 269 | >> tok.identifier [bind(&Memory::addWriter, _r1, _1)] 270 | ; 271 | BOOST_SPIRIT_DEBUG_NODE(mem_writer); 272 | 273 | mem_readwriter = tok.readwriter >> tok.assign 274 | >> tok.identifier [bind(&Memory::addReadWriter, _r1, _1)] 275 | ; 276 | BOOST_SPIRIT_DEBUG_NODE(mem_readwriter); 277 | 278 | inst = tok.inst 279 | >> (tok.identifier 280 | >> tok.of 281 | >> reference) [_val = make_shared()(_1, _3)] 282 | >> -info [bind(&Stmt::setInfo, _val, _1)] 283 | ; 284 | BOOST_SPIRIT_DEBUG_NODE(inst); 285 | 286 | node = tok.node 287 | >> (tok.identifier 288 | >> "=" 289 | >> exp_) [_val = make_shared()(_1, _2)] 290 | >> -info [bind(&Stmt::setInfo, _val, _1)] 291 | ; 292 | BOOST_SPIRIT_DEBUG_NODE(node); 293 | 294 | connect = (exp_ 295 | >> tok.connect 296 | >> exp_) [_val = make_shared()(_1, _3)] 297 | >> -info [bind(&Connect::setInfo, _val, _1)] 298 | ; 299 | BOOST_SPIRIT_DEBUG_NODE(connect); 300 | 301 | partconnect = (exp_ 302 | >> tok.partconnect 303 | >> exp_) [_val = make_shared()(_1, _3, true)] 304 | >> -info [bind(&Connect::setInfo, _val, _1)] 305 | ; 306 | BOOST_SPIRIT_DEBUG_NODE(partconnect); 307 | 308 | invalidate = exp_ [_val = make_shared()(_1)] 309 | >> tok.is >> tok.invalid 310 | >> -info [bind(&Invalid::setInfo, _val, _1)] 311 | ; 312 | BOOST_SPIRIT_DEBUG_NODE(invalidate); 313 | 314 | conditional = tok.when 315 | >> exp_ [_val = make_shared()(_1)] 316 | >> ":" 317 | >> -info [bind(&Conditional::setInfo, _val, _1)] 318 | >> -(stmt_group [bind(&Conditional::setThen, _val, _1)] 319 | | stmt_suite [bind(&Conditional::setThen, _val, _1)] 320 | ) 321 | >> -conditional_else 322 | ; 323 | BOOST_SPIRIT_DEBUG_NODE(conditional); 324 | 325 | conditional_else = tok.else_ [_val = make_shared()()] 326 | >> (conditional [_a = make_shared()(_1)] 327 | | (':' 328 | >> -info [bind(&ConditionalElse::setInfo, _val, _1)] 329 | >> (stmt_group [_a = _1] 330 | | stmt_suite [_a = _1] 331 | ) 332 | ) 333 | ) [bind(&ConditionalElse::setStmts, _val, _a)] 334 | ; 335 | BOOST_SPIRIT_DEBUG_NODE(conditional_else); 336 | 337 | stop = tok.stop 338 | >> "(" 339 | >> (exp_ >> exp_ >> 340 | tok.int_) [_val = make_shared()(_1, _2, _3)] 341 | >> ")" 342 | >> -info [bind(&Stop::setInfo, _val, _1)] 343 | ; 344 | BOOST_SPIRIT_DEBUG_NODE(stop); 345 | 346 | printf_ = tok.printf 347 | >> "(" 348 | >> (exp_ >> exp_ 349 | >> tok.string_double) [_val = make_shared()(_1, _2, _3)] 350 | >> *exp_ /*[bind(&Printf::addArgument, _val, _1)]*/ 351 | >> ")" 352 | >> -info [bind(&Printf::setInfo, _val, _1)] 353 | ; 354 | BOOST_SPIRIT_DEBUG_NODE(printf_); 355 | 356 | empty = tok.skip [_val = make_shared()()] 357 | >> -info [bind(&Empty::setInfo, _val, _1)] 358 | ; 359 | BOOST_SPIRIT_DEBUG_NODE(empty); 360 | 361 | reference = tok.identifier [_val = make_shared()(_1)] 362 | ; 363 | BOOST_SPIRIT_DEBUG_NODE(reference); 364 | 365 | exp_ = (reference [_a = _1] | exp_int [_a = _1] | mux [_a = _1] 366 | | validif [_a = _1] | primop [_a = _1] ) 367 | >> exp_helper(_a) [_val = _1] 368 | ; 369 | BOOST_SPIRIT_DEBUG_NODE(exp_); 370 | 371 | exp_helper = exp_subfield(_r1) [_val = _1] 372 | | exp_subindex(_r1) [_val = _1] 373 | | exp_subaccess(_r1) [_val = _1] 374 | | eps [_val = _r1] 375 | ; 376 | BOOST_SPIRIT_DEBUG_NODE(exp_helper); 377 | 378 | exp_int = type_int [_a = _1] 379 | >> "(" 380 | >> ( tok.int_ [_val = make_shared()(_a, _1)] 381 | | tok.string_double [_val = make_shared()(_a, _1)] 382 | ) >> ")" 383 | ; 384 | BOOST_SPIRIT_DEBUG_NODE(exp_int); 385 | 386 | exp_subfield = "." 387 | >> reference [_a = make_shared()(_1, _r1)] 388 | >> exp_helper(_a) [_val = _1] 389 | ; 390 | BOOST_SPIRIT_DEBUG_NODE(exp_subfield); 391 | 392 | exp_subindex = "[" >> tok.int_ [_a = make_shared()(_1, _r1)] 393 | >> "]" >> exp_helper(_a) [_val = _1] 394 | ; 395 | BOOST_SPIRIT_DEBUG_NODE(exp_subindex); 396 | 397 | exp_subaccess = "[" 398 | >> exp_ [_a = make_shared()(_1, _r1)] 399 | >> "]" >> exp_helper(_a) [_val = _1] 400 | ; 401 | BOOST_SPIRIT_DEBUG_NODE(exp_subaccess); 402 | 403 | mux = tok.mux >> "(" >> (exp_ >> exp_ >> 404 | exp_ )[_val = make_shared()(_1, _2, _3)] 405 | >> ")" 406 | ; 407 | BOOST_SPIRIT_DEBUG_NODE(mux); 408 | 409 | validif = tok.validif >> "(" >> (exp_ 410 | >> exp_) [_val = make_shared()(_1, _2)] 411 | >> ")" 412 | ; 413 | BOOST_SPIRIT_DEBUG_NODE(validif); 414 | 415 | primop = tok.primop [_val = gen_primop()(_1)] 416 | >> *exp_ [bind(&PrimOp::addOperand, _val, _1)] 417 | >> *tok.int_ [bind(&PrimOp::addParameter, _val, _1)] 418 | >> ")" 419 | ; 420 | BOOST_SPIRIT_DEBUG_NODE(primop); 421 | 422 | } 423 | 424 | qi::rule()> circuit; 425 | qi::rule()> info; 426 | qi::rule()> module, extmodule, intmodule; 427 | qi::rule(), qi::locals> port; 428 | qi::rule defname; 429 | qi::rule()> parameter; 430 | qi::rule()> type; 431 | qi::rule()> type_int; 432 | qi::rule()> type_bundle; 433 | qi::rule()> type_vector; 434 | qi::rule(), qi::locals > field; 435 | 436 | qi::rule()> stmt; 437 | qi::rule()> wire; 438 | qi::rule()> reg; 439 | qi::rule()> mem; 440 | qi::rule() > inst; 441 | qi::rule()> node; 442 | qi::rule()> connect, partconnect; 443 | qi::rule()> invalidate; 444 | qi::rule()> stop; 445 | qi::rule()> printf_; 446 | qi::rule()> empty; 447 | 448 | qi::rule()> conditional; 449 | qi::rule(), 450 | qi::locals > > conditional_else; 451 | qi::rule()> stmt_group, stmt_suite; 452 | 453 | qi::rule reset_block, simple_reset, simple_reset0; 454 | 455 | qi::rule)> mem_dtype, mem_depth, 456 | mem_readlat, mem_writelat, mem_reader, mem_writer, mem_readwriter; 457 | qi::rule), 458 | qi::locals > mem_ruw; 459 | 460 | qi::rule(), 461 | qi::locals > > exp_; 462 | qi::rule(std::shared_ptr) > exp_helper; 464 | qi::rule()> mux, validif; 465 | qi::rule(), 466 | qi::locals > > exp_int; 467 | qi::rule()> reference; 468 | 469 | qi::rule(std::shared_ptr), 471 | qi::locals > > exp_subaccess, 472 | exp_subfield, exp_subindex; 473 | 474 | qi::rule()> primop; 475 | }; 476 | 477 | } 478 | } 479 | } 480 | -------------------------------------------------------------------------------- /lib/frontends/firrtl/include/FirrtlFrontendLexer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | //#define BOOST_SPIRIT_LEXERTL_DEBUG 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | namespace Firrtlator { 36 | namespace Frontend { 37 | namespace Firrtl { 38 | 39 | namespace lex = boost::spirit::lex; 40 | namespace phoenix = boost::phoenix; 41 | 42 | // The indent and dedent handling was inspired from: 43 | // http://zhuoqiang.me/lexing-python-indentation-using-spirit-lex.html 44 | 45 | template 46 | class Tokens : public lex::lexer { 47 | public: 48 | Tokens() 49 | : indent_("[ \\t]*") 50 | , newline_("[\\n\\r\\f]+") 51 | , whitespace_("[ \\t,]+") 52 | , emptyline("[ \\t]*$") 53 | , comment_ (";.*$") 54 | , identifier("[A-Za-z_][A-Za-z0-9_]*") 55 | , info ("@\\[[^\\]]*\\]") 56 | #define TERM(x) x(#x) 57 | , TERM(circuit) 58 | , TERM(module) 59 | , TERM(extmodule) 60 | , TERM(input) 61 | , TERM(output) 62 | , TERM(defname) 63 | , TERM(parameter) 64 | , TERM(UInt) 65 | , TERM(SInt) 66 | , TERM(Clock) 67 | , TERM(wire) 68 | , TERM(reg) 69 | , TERM(mem) 70 | , TERM(cmem) 71 | , TERM(smem) 72 | , TERM(mport) 73 | , TERM(inst) 74 | , TERM(of) 75 | , TERM(node) 76 | , TERM(infer) 77 | , TERM(flip) 78 | , TERM(with) 79 | , TERM(is) 80 | , TERM(invalid) 81 | , dtype("datatype") 82 | , TERM(depth) 83 | , readlat("read-latency") 84 | , writelat("write-latency") 85 | , ruw("read-under-write") 86 | , TERM(reader) 87 | , TERM(writer) 88 | , TERM(readwriter) 89 | , TERM(when) 90 | , else_("else") 91 | , TERM(stop) 92 | , TERM(printf) 93 | , TERM(skip) 94 | , TERM(old) 95 | , new_("new") 96 | , TERM(undefined) 97 | , TERM(mux) 98 | , TERM(validif) 99 | //, TERM(reset) // Don't match 100 | , connect("<=") 101 | , partconnect("<-") 102 | , assign("=>") 103 | , primop("(add|sub|mul|div|mod|lt|leq|gt|geq|eq|neq|pad|asUInt|asSint|" 104 | "asClock|shl|shr|dshl|dshr|cvt|neg|not|and|or|xor|andr|orr|" 105 | "xorr|cat|bits|head|tail)\\(") 106 | 107 | , int_ ("(-?[0-9]+)|(0x[A-F0-9_]+)|(0o[0-7]+)|(0x[01]+)") 108 | , double_ ("-?[0-9]+.[0-9]+") 109 | , string_double ("\\\"(\\\\\\\"|[^\"]|\\\"\\\")*\\\"") 110 | , string_single ("'([^']|'')*'") 111 | #undef TERM 112 | { 113 | this->self = emptyline [HandleEmpty()] | 114 | indent_[HandleIndent(scopeLevels_)]; 115 | 116 | this->self("NORMAL") = 117 | circuit | module | extmodule | input | output | defname | parameter | 118 | UInt | SInt | Clock | 119 | wire | reg | mem | cmem | smem | inst | of | node | 120 | flip | with | reset | is | invalid | 121 | dtype | depth | readlat | writelat | ruw | reader | writer | readwriter | 122 | when | else_ | stop | printf | skip | old | new_ | undefined | 123 | mux | validif | 124 | 125 | connect | partconnect | assign | 126 | 127 | primop [HandlePrimOp()]| 128 | 129 | string_double [HandleDoubleQuote()] | 130 | string_single [HandleSingleQuote()] | 131 | int_ | double_ | 132 | identifier | info [HandleInfo()] | 133 | 134 | ":" | "<" | ">" | "(" | ")" | "=" | "{" | "}" | "." | 135 | 136 | comment_[lex::_pass=lex::pass_flags::pass_ignore] 137 | | newline_[HandleNewline(scopeLevels_)] 138 | | whitespace_[lex::_pass=lex::pass_flags::pass_ignore] 139 | ; 140 | } 141 | lex::token_def<> indent_; 142 | lex::token_def newline_, whitespace_, emptyline; 143 | lex::token_def<> comment_; 144 | lex::token_def identifier; 145 | lex::token_def info; 146 | 147 | lex::token_def<> circuit, module, extmodule; 148 | lex::token_def<> input, output, defname, parameter; 149 | lex::token_def<> UInt, SInt, Clock; 150 | lex::token_def<> wire, reg, mem, cmem, smem, mport, inst, of, node, infer; 151 | lex::token_def<> flip, with, reset, is, invalid; 152 | lex::token_def<> dtype, depth, readlat, writelat, ruw, reader, writer, readwriter; 153 | lex::token_def<> when, else_, stop, printf, skip, old, new_, undefined; 154 | lex::token_def<> mux, validif; 155 | 156 | lex::token_def<> connect, partconnect, assign; 157 | 158 | lex::token_def primop; 159 | 160 | lex::token_def int_; 161 | lex::token_def<> double_; 162 | lex::token_def string_double, string_single; 163 | 164 | std::stack scopeLevels_; 165 | }; 166 | } 167 | } 168 | } 169 | 170 | -------------------------------------------------------------------------------- /lib/frontends/firrtl/include/FirrtlFrontendLexerHelper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */#pragma once 22 | 23 | #include 24 | #include 25 | 26 | namespace Firrtlator { 27 | namespace Frontend { 28 | namespace Firrtl { 29 | 30 | namespace lex = boost::spirit::lex; 31 | 32 | enum TokenIds { 33 | INDENT = 1000, 34 | DEDENT = 1001 35 | }; 36 | 37 | class HandleIndent { 38 | public: 39 | HandleIndent(std::stack& scopeLevels) 40 | : scopeLevels_(scopeLevels) 41 | {} 42 | 43 | template 44 | void operator() ( 45 | Iterator& start, 46 | Iterator& end, 47 | BOOST_SCOPED_ENUM(lex::pass_flags)& passFlag, 48 | IdType& id, Context& context) { 49 | 50 | int const level = std::distance(start, end); 51 | if (scopeLevels_.empty()) { 52 | if (level != 0) { 53 | throw std::runtime_error("Indent must start from 0!"); 54 | } 55 | scopeLevels_.push(level); 56 | } 57 | // If the level is same, just ignore it and switch to normal state 58 | if (level == scopeLevels_.top()) { 59 | passFlag = lex::pass_flags::pass_ignore; 60 | context.set_state_name("NORMAL"); 61 | } 62 | // If the level is larger, emit BEGIN and push the new level on stack 63 | else if (level > scopeLevels_.top()) { 64 | scopeLevels_.push(level); 65 | id = INDENT; 66 | context.set_state_name("NORMAL"); 67 | } 68 | // If the level is smaller, emit END and pop the top level from stack 69 | else { //Dedent, end scope 70 | scopeLevels_.pop(); 71 | // Level must be one of the numbers occurring on the stack 72 | if (scopeLevels_.empty() || level > scopeLevels_.top()) { 73 | throw std::runtime_error("Dedenting failed, could not find indent matching previews "); 74 | } else { 75 | // make it a zero match, we can generate multiple END token by this trick 76 | end = start; 77 | id = DEDENT; 78 | } 79 | } 80 | } 81 | 82 | private: 83 | std::stack& scopeLevels_; 84 | }; 85 | 86 | 87 | class HandleNewline { 88 | public: 89 | HandleNewline(std::stack& scopeLevels) 90 | : scopeLevels_(scopeLevels) 91 | {} 92 | 93 | template 94 | void operator() ( 95 | Iterator& start, 96 | Iterator& end, 97 | BOOST_SCOPED_ENUM(lex::pass_flags)& passFlag, 98 | IdType& id, Context& context) { 99 | 100 | if (context.get_eoi() == end) { 101 | // If the "end of input" is reached 102 | // we pop up all the non-zero levels. 103 | // for each pop up we generate a corresponding END token 104 | // here we apply the zero-match trick again to emit multiple END token 105 | while (scopeLevels_.top() != 0) { 106 | scopeLevels_.pop(); 107 | end = start; 108 | id = DEDENT; 109 | return; 110 | } 111 | } 112 | passFlag = lex::pass_flags::pass_ignore; 113 | context.set_state_name("INITIAL"); 114 | } 115 | 116 | private: 117 | std::stack& scopeLevels_; 118 | }; 119 | 120 | class HandleEmpty { 121 | public: 122 | HandleEmpty() {} 123 | 124 | template 125 | void operator() ( 126 | Iterator& start, 127 | Iterator& end, 128 | BOOST_SCOPED_ENUM(lex::pass_flags)& passFlag, 129 | IdType& id, Context& context) { 130 | 131 | passFlag = lex::pass_flags::pass_ignore; 132 | context.set_state_name("NORMAL"); 133 | } 134 | }; 135 | 136 | class HandleInfo { 137 | public: 138 | HandleInfo() {} 139 | template 140 | void operator() ( 141 | Iterator& start, 142 | Iterator& end, 143 | BOOST_SCOPED_ENUM(lex::pass_flags)& passFlag, 144 | IdType& id, Context& context) { 145 | context.set_value(std::string(start+2,end-1)); 146 | } 147 | }; 148 | 149 | class HandleSingleQuote { 150 | public: 151 | HandleSingleQuote() {} 152 | static bool unquote(std::string& val) 153 | { 154 | auto outidx = 0; 155 | for(auto in = val.begin(); in!=val.end(); ++in) { 156 | switch(*in) { 157 | case 0x27: 158 | if (++in == val.end()) { // eat the escape 159 | // end of input reached 160 | val.resize(outidx); // resize to effective chars 161 | return true; 162 | } 163 | // fall through 164 | default: 165 | val[outidx++] = *in; // append the character 166 | } 167 | } 168 | 169 | return false; // not ended with double quote as expected 170 | } 171 | 172 | template 173 | void operator() ( 174 | Iterator& start, 175 | Iterator& end, 176 | BOOST_SCOPED_ENUM(lex::pass_flags)& passFlag, 177 | IdType& id, Context& context) { 178 | std::string raw(start,end); 179 | if (unquote(raw)) 180 | context.set_value(raw); 181 | else 182 | passFlag = lex::pass_flags::pass_fail; 183 | } 184 | }; 185 | 186 | class HandleDoubleQuote { 187 | public: 188 | HandleDoubleQuote() {} 189 | static bool unquote(std::string& val) 190 | { 191 | auto outidx = 0; 192 | for(auto in = val.begin(); in!=val.end(); ++in) { 193 | switch(*in) { 194 | case '"': 195 | if (++in == val.end()) { // eat the escape 196 | // end of input reached 197 | val.resize(outidx); // resize to effective chars 198 | return true; 199 | } 200 | // fall through 201 | default: 202 | val[outidx++] = *in; // append the character 203 | } 204 | } 205 | 206 | return false; // not ended with double quote as expected 207 | } 208 | 209 | template 210 | void operator() ( 211 | Iterator& start, 212 | Iterator& end, 213 | BOOST_SCOPED_ENUM(lex::pass_flags)& passFlag, 214 | IdType& id, Context& context) { 215 | std::string raw(start,end); 216 | if (unquote(raw)) 217 | context.set_value(raw); 218 | else 219 | passFlag = lex::pass_flags::pass_fail; 220 | } 221 | }; 222 | 223 | class HandlePrimOp { 224 | public: 225 | HandlePrimOp() {} 226 | 227 | template 228 | void operator() ( 229 | Iterator& start, 230 | Iterator& end, 231 | BOOST_SCOPED_ENUM(lex::pass_flags)& passFlag, 232 | IdType& id, Context& context) { 233 | std::string raw(start,end-1); 234 | PrimOp::Operation op; 235 | if (PrimOp::lookup(raw, op)) { 236 | context.set_value(raw); 237 | } else { 238 | passFlag = lex::pass_flags::pass_fail; 239 | } 240 | } 241 | }; 242 | 243 | } 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /lib/frontends/firrtl/src/FirrtlFrontend.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "FirrtlFrontend.h" 24 | 25 | #include "FirrtlFrontendLexer.h" 26 | #include "FirrtlFrontendGrammar.h" 27 | 28 | #include 29 | 30 | namespace Firrtlator { 31 | namespace Frontend { 32 | namespace Firrtl { 33 | 34 | std::string Frontend::name = "FIRRTL"; 35 | std::string Frontend::description = "Reads FIRRTL files"; 36 | std::vector Frontend::filetypes = { "fir" }; 37 | 38 | REGISTER_FRONTEND(Frontend) 39 | 40 | bool Frontend::parseString(std::string::const_iterator begin, 41 | std::string::const_iterator end) { 42 | 43 | typedef lex::lexertl::token > token_type; 45 | typedef lex::lexertl::actor_lexer lexer_type; 46 | typedef Tokens::iterator_type iterator_type; 47 | 48 | Tokens token_lexer; 49 | 50 | lexer_type::iterator_type first = token_lexer.begin(begin, end); 51 | lexer_type::iterator_type last = token_lexer.end(); 52 | 53 | FirrtlGrammar g(token_lexer); 54 | 55 | bool res = lex::tokenize_and_parse(begin, end, token_lexer, g, mIR); 56 | 57 | if (begin != end) 58 | res = false; 59 | 60 | if (!res) { 61 | return false; 62 | } 63 | 64 | return true; 65 | } 66 | 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/frontends/generic/src/Frontends.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "FirrtlatorFrontend.h" 24 | 25 | namespace Firrtlator { 26 | namespace Frontend { 27 | 28 | FrontendBase::~FrontendBase() { 29 | 30 | } 31 | 32 | std::shared_ptr FrontendBase::getIR() { 33 | return mIR; 34 | } 35 | 36 | void Registry::registerFrontend(const std::string &name, 37 | FrontendFactory* factory) { 38 | getFrontendMap()[name] = factory; 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/include/Firrtlator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include 26 | #include 27 | 28 | namespace Firrtlator { 29 | 30 | class 31 | __attribute__ ((visibility ("default"))) 32 | Firrtlator { 33 | public: 34 | Firrtlator(); 35 | ~Firrtlator(); 36 | 37 | typedef struct { 38 | std::string name; 39 | std::string description; 40 | std::vector filetypes; 41 | } FrontendDescriptor; 42 | 43 | static std::vector getFrontends(); 44 | static std::string getFrontend(std::string type); 45 | 46 | bool parse(std::string::const_iterator begin, 47 | std::string::const_iterator end, std::string type = ""); 48 | bool parseFile(std::string filename, std::string type = ""); 49 | bool parseString(std::string string, std::string type = ""); 50 | 51 | void elaborate(); 52 | 53 | typedef struct { 54 | std::string name; 55 | std::string description; 56 | } PassDescriptor; 57 | 58 | static std::vector getPasses(); 59 | 60 | void pass(std::string id); 61 | 62 | typedef struct { 63 | std::string name; 64 | std::string description; 65 | std::vector filetypes; 66 | } BackendDescriptor; 67 | 68 | static std::vector getBackends(); 69 | static std::string getBackend(std::string type); 70 | void generate(std::string filename, std::string backend = "FIRRTL"); 71 | private: 72 | class impl; 73 | std::unique_ptr pimpl; 74 | }; 75 | 76 | } 77 | 78 | -------------------------------------------------------------------------------- /lib/include/IR.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "Util.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | namespace Firrtlator { 34 | 35 | class Info; 36 | class IRNode; 37 | class Reference; 38 | class Module; 39 | class Stmt; 40 | class StmtGroup; 41 | class Expression; 42 | class Type; 43 | class Visitor; 44 | 45 | class Info { 46 | private: 47 | std::string mValue; 48 | public: 49 | Info(std::string value = ""); 50 | void setValue(std::string value); 51 | std::string getValue(); 52 | friend std::ostream& operator<< (std::ostream &out, const Info &Info); 53 | }; 54 | 55 | class IRNode : public std::enable_shared_from_this { 56 | public: 57 | virtual ~IRNode(); 58 | IRNode(); 59 | IRNode(std::string id); 60 | std::string getId(); 61 | void setId(std::string id); 62 | std::shared_ptr getInfo(); 63 | void setInfo(std::shared_ptr info); 64 | bool isDeclaration(); 65 | virtual void accept(Visitor& v) = 0; 66 | protected: 67 | std::shared_ptr mInfo; 68 | std::string mId; 69 | std::vector > mReferences; 70 | 71 | template 72 | std::shared_ptr shared_from_base() 73 | { 74 | return std::static_pointer_cast(shared_from_this()); 75 | } 76 | }; 77 | 78 | std::ostream& operator<< (std::ostream& os, const ::Firrtlator::IRNode& n); 79 | 80 | class Circuit : public IRNode { 81 | public: 82 | Circuit(); 83 | Circuit(std::string id); 84 | Circuit(std::string id, std::shared_ptr info); 85 | 86 | void addModule(std::shared_ptr mod); 87 | std::vector > getModules(); 88 | 89 | virtual void accept(Visitor& v); 90 | private: 91 | std::vector > mModules; 92 | std::vector > mExternalModules; 93 | std::vector > mInternalModules; 94 | }; 95 | 96 | class Port : public IRNode { 97 | public: 98 | typedef enum { INPUT, OUTPUT } Direction; 99 | Port(); 100 | Port(std::string id, Direction dir, std::shared_ptr type); 101 | void setDirection(Direction dir); 102 | Direction getDirection(); 103 | virtual void accept(Visitor& v); 104 | private: 105 | Direction mDirection; 106 | std::shared_ptr mType; 107 | }; 108 | 109 | class Type : public IRNode { 110 | public: 111 | typedef enum { INT, CLOCK, BUNDLE, VECTOR, UNDEFINED } Basetype; 112 | Type(); 113 | Type(Basetype type); 114 | virtual void accept(Visitor& v) = 0; 115 | protected: 116 | Basetype mBasetype; 117 | }; 118 | 119 | class TypeInt : public Type { 120 | public: 121 | TypeInt(); 122 | TypeInt(bool sign, int width = -1); 123 | 124 | void setWidth(int width); 125 | int getWidth(); 126 | 127 | bool getSigned(); 128 | void setSigned(bool sign); 129 | virtual void accept(Visitor& v); 130 | private: 131 | int mWidth; 132 | bool mSigned; 133 | }; 134 | 135 | class TypeClock : public Type { 136 | public: 137 | TypeClock(); 138 | virtual void accept(Visitor& v); 139 | }; 140 | 141 | class Field : public IRNode { 142 | public: 143 | Field(); 144 | Field(std::string id, std::shared_ptr type, bool flip = false); 145 | 146 | void setType(std::shared_ptr t); 147 | std::shared_ptr getType(); 148 | void setFlip(bool flip); 149 | bool getFlip(); 150 | 151 | virtual void accept(Visitor& v); 152 | private: 153 | bool mFlip; 154 | std::shared_ptr mType; 155 | }; 156 | 157 | class TypeBundle : public Type { 158 | public: 159 | TypeBundle(); 160 | 161 | void addField(std::shared_ptr field); 162 | std::vector > getFields(); 163 | 164 | virtual void accept(Visitor& v); 165 | private: 166 | std::vector > mFields; 167 | }; 168 | 169 | class TypeVector : public Type { 170 | public: 171 | TypeVector(); 172 | 173 | void setSize(int size); 174 | int getSize(); 175 | 176 | virtual void accept(Visitor& v); 177 | private: 178 | std::shared_ptr mType; 179 | int mSize; 180 | }; 181 | 182 | class Parameter : public IRNode { 183 | public: 184 | Parameter(); 185 | virtual void accept(Visitor& v); 186 | }; 187 | 188 | class Module : public IRNode { 189 | public: 190 | Module(); 191 | Module(std::string id, bool external = false); 192 | 193 | void addPort(std::shared_ptr port); 194 | void setStatementGroup(std::shared_ptr stmt); 195 | void setDefname(std::string defname); 196 | void addParameter(std::shared_ptr param); 197 | 198 | bool isExternal(); 199 | std::string getDefname(); 200 | std::vector > getPorts(); 201 | std::shared_ptr getStmts(); 202 | std::vector > getParameters(); 203 | 204 | virtual void accept(Visitor& v); 205 | private: 206 | bool mExternal; 207 | std::string mDefname; 208 | std::vector > mPorts; 209 | std::shared_ptr mStmts; 210 | std::vector > mParameters; 211 | }; 212 | 213 | class Stmt : public IRNode { 214 | public: 215 | Stmt(); 216 | Stmt(std::string id); 217 | virtual void accept(Visitor& v) = 0; 218 | }; 219 | 220 | class StmtGroup : public Stmt { 221 | public: 222 | StmtGroup(); 223 | StmtGroup(std::shared_ptr stmt); 224 | StmtGroup(std::vector > group); 225 | 226 | void addStatement(std::shared_ptr stmt); 227 | 228 | typedef std::vector >::iterator iterator; 229 | typedef std::vector >::const_iterator const_iterator; 230 | iterator begin(); 231 | iterator end(); 232 | 233 | virtual void accept(Visitor& v); 234 | private: 235 | std::vector > mGroup; 236 | }; 237 | 238 | class Wire : public Stmt { 239 | public: 240 | Wire(); 241 | Wire(std::string id, std::shared_ptr type); 242 | 243 | std::shared_ptr getType(); 244 | 245 | virtual void accept(Visitor& v); 246 | private: 247 | std::shared_ptr mType; 248 | }; 249 | 250 | class Reg : public Stmt { 251 | public: 252 | Reg(); 253 | Reg(std::string id, std::shared_ptr type, 254 | std::shared_ptr clock); 255 | virtual void accept(Visitor& v); 256 | std::shared_ptr getType(); 257 | std::shared_ptr getClock(); 258 | void setResetTrigger(std::shared_ptr trigger); 259 | void setResetValue(std::shared_ptr value); 260 | std::shared_ptr getResetTrigger(); 261 | std::shared_ptr getResetValue(); 262 | private: 263 | std::shared_ptr mType; 264 | std::shared_ptr mClock; 265 | std::shared_ptr mResetTrigger; 266 | std::shared_ptr mResetValue; 267 | }; 268 | 269 | class Memory : public Stmt { 270 | public: 271 | typedef enum { OLD, NEW, UNDEFINED } RuwFlag; 272 | Memory(std::string id); 273 | void setDType(std::shared_ptr type); 274 | void setDepth(int depth); 275 | void setReadLatency(int lat); 276 | void setWriteLatency(int lat); 277 | void setRuwFlag(RuwFlag flag); 278 | void addReader(std::string r); 279 | void addWriter(std::string w); 280 | void addReadWriter(std::string rw); 281 | 282 | std::shared_ptr getDType(); 283 | std::shared_ptr getType(); 284 | std::vector getReaders(); 285 | std::vector getWriters(); 286 | std::vector getReadWriters(); 287 | int getDepth(); 288 | int getReadlatency(); 289 | int getWritelatency(); 290 | RuwFlag getRuwflag(); 291 | 292 | virtual void accept(Visitor& v); 293 | protected: 294 | std::shared_ptr mDType = nullptr; 295 | std::shared_ptr mType = nullptr; 296 | std::vector mReaders; 297 | std::vector mWriters; 298 | std::vector mReadWriters; 299 | int mDepth = -1; 300 | int mReadlatency = -1; 301 | int mWritelatency = -1; 302 | bool mRuwflagset = false; 303 | RuwFlag mRuwflag = UNDEFINED; 304 | 305 | bool checkAndUpdateDeferedType(); 306 | void addReaderToType(std::string r); 307 | void addWriterToType(std::string w); 308 | void addReadWriterToType(std::string rw); 309 | }; 310 | 311 | class Instance : public Stmt { 312 | public: 313 | Instance(); 314 | Instance(std::string id, std::shared_ptr of); 315 | 316 | std::shared_ptr getOf(); 317 | 318 | virtual void accept(Visitor& v); 319 | private: 320 | std::shared_ptr mOf; 321 | }; 322 | 323 | class Node : public Stmt { 324 | public: 325 | Node(); 326 | Node(std::string id, std::shared_ptr expr); 327 | 328 | std::shared_ptr getExpression(); 329 | 330 | virtual void accept(Visitor& v); 331 | private: 332 | std::shared_ptr mExpr; 333 | }; 334 | 335 | class Connect : public Stmt { 336 | public: 337 | Connect(); 338 | Connect(std::shared_ptr to, 339 | std::shared_ptr from, 340 | bool partial = false); 341 | 342 | bool getPartial(); 343 | std::shared_ptr getTo(); 344 | std::shared_ptr getFrom(); 345 | 346 | virtual void accept(Visitor& v); 347 | private: 348 | std::shared_ptr mTo; 349 | std::shared_ptr mFrom; 350 | bool mPartial; 351 | }; 352 | 353 | class Invalid : public Stmt { 354 | public: 355 | Invalid(); 356 | Invalid(std::shared_ptr exp); 357 | 358 | std::shared_ptr getExpr(); 359 | 360 | virtual void accept(Visitor& v); 361 | private: 362 | std::shared_ptr mExp; 363 | }; 364 | 365 | class ConditionalElse; 366 | 367 | class Conditional : public Stmt { 368 | public: 369 | Conditional(); 370 | Conditional(std::shared_ptr cond); 371 | void setThen(std::shared_ptr stmts); 372 | void setElse(std::shared_ptr stmt); 373 | 374 | std::shared_ptr getCondition(); 375 | std::shared_ptr getThen(); 376 | std::shared_ptr getElse(); 377 | 378 | virtual void accept(Visitor& v); 379 | private: 380 | std::shared_ptr mCond; 381 | std::shared_ptr mThen; 382 | std::shared_ptr mElse; 383 | }; 384 | 385 | class ConditionalElse : public IRNode { 386 | public: 387 | ConditionalElse(); 388 | ConditionalElse(std::shared_ptr stmts); 389 | 390 | void setStmts(std::shared_ptr stmts); 391 | 392 | std::shared_ptr getStmts(); 393 | 394 | virtual void accept(Visitor& v); 395 | private: 396 | std::shared_ptr mStmts; 397 | }; 398 | 399 | 400 | class Stop : public Stmt { 401 | public: 402 | Stop(); 403 | Stop(std::shared_ptr clock, 404 | std::shared_ptr cond, 405 | int code); 406 | 407 | std::shared_ptr getClock(); 408 | std::shared_ptr getCondition(); 409 | int getCode(); 410 | 411 | virtual void accept(Visitor& v); 412 | private: 413 | std::shared_ptr mClock; 414 | std::shared_ptr mCond; 415 | int mCode; 416 | }; 417 | 418 | class Printf : public Stmt { 419 | public: 420 | Printf(); 421 | Printf(std::shared_ptr clock, 422 | std::shared_ptr cond, 423 | std::string format); 424 | void addArgument(std::shared_ptr arg); 425 | 426 | std::shared_ptr getClock(); 427 | std::shared_ptr getCondition(); 428 | std::string getFormat(); 429 | std::vector > getArguments(); 430 | 431 | virtual void accept(Visitor& v); 432 | private: 433 | std::shared_ptr mClock; 434 | std::shared_ptr mCond; 435 | std::string mFormat; 436 | std::vector > mArguments; 437 | }; 438 | 439 | class Empty : public Stmt { 440 | public: 441 | virtual void accept(Visitor& v); 442 | }; 443 | 444 | class Expression : public IRNode { 445 | public: 446 | typedef enum { MALE, FEMALE, BI } Gender; 447 | Expression(); 448 | Expression(Gender g); 449 | Gender getGender(); 450 | virtual void accept(Visitor& v) = 0; 451 | private: 452 | Gender mGender; 453 | }; 454 | 455 | class Reference : public Expression { 456 | public: 457 | Reference(); 458 | Reference(std::string id); 459 | 460 | bool isResolved(); 461 | virtual std::string getToString(); 462 | 463 | virtual void accept(Visitor& v); 464 | private: 465 | std::shared_ptr mTo; 466 | std::string mToString; 467 | }; 468 | 469 | class Constant : public Expression { 470 | public: 471 | typedef enum { UNDEFINED, INT, STRING } GenerateHint; 472 | Constant(); 473 | Constant(std::shared_ptr type, int val, 474 | GenerateHint hint = INT); 475 | Constant(std::shared_ptr type, std::string val, 476 | GenerateHint hint = STRING); 477 | 478 | std::shared_ptr getType(); 479 | int getValue(); 480 | GenerateHint getHint(); 481 | std::string getString(); 482 | 483 | virtual void accept(Visitor& v); 484 | private: 485 | std::shared_ptr mType; 486 | int mVal; 487 | GenerateHint mHint; 488 | }; 489 | 490 | class SubField : public Expression { 491 | public: 492 | SubField(); 493 | SubField(std::shared_ptr field, std::shared_ptr of); 494 | 495 | std::shared_ptr getOf(); 496 | std::shared_ptr getField(); 497 | 498 | virtual void accept(Visitor& v); 499 | private: 500 | std::shared_ptr mOf; 501 | std::shared_ptr mField; 502 | }; 503 | 504 | class SubIndex : public Expression { 505 | public: 506 | SubIndex(); 507 | SubIndex(int index, std::shared_ptr of); 508 | 509 | std::shared_ptr getOf(); 510 | int getIndex(); 511 | 512 | virtual void accept(Visitor& v); 513 | private: 514 | std::shared_ptr mOf; 515 | int mIndex; 516 | }; 517 | 518 | class SubAccess : public Expression { 519 | public: 520 | SubAccess(); 521 | SubAccess(std::shared_ptr expr, 522 | std::shared_ptr of); 523 | 524 | std::shared_ptr getOf(); 525 | std::shared_ptr getExp(); 526 | 527 | virtual void accept(Visitor& v); 528 | private: 529 | std::shared_ptr mOf; 530 | std::shared_ptr mExp; 531 | }; 532 | 533 | class Mux : public Expression { 534 | public: 535 | Mux(); 536 | Mux(std::shared_ptr sel, std::shared_ptr a, 537 | std::shared_ptr b); 538 | 539 | std::shared_ptr getSel(); 540 | std::shared_ptr getA(); 541 | std::shared_ptr getB(); 542 | 543 | virtual void accept(Visitor& v); 544 | private: 545 | std::shared_ptr mSel; 546 | std::shared_ptr mA; 547 | std::shared_ptr mB; 548 | }; 549 | 550 | class CondValid : public Expression { 551 | public: 552 | CondValid(); 553 | CondValid(std::shared_ptr sel, 554 | std::shared_ptr a); 555 | 556 | std::shared_ptr getSel(); 557 | std::shared_ptr getA(); 558 | 559 | virtual void accept(Visitor& v); 560 | private: 561 | std::shared_ptr mSel; 562 | std::shared_ptr mA; 563 | }; 564 | 565 | 566 | class PrimOp : public Expression { 567 | public: 568 | typedef enum { 569 | ADD, SUB, MUL, DIV, MOD, LT, LEQ, GT, GEQ, EQ, NEQ, PAD, ASUINT, 570 | ASSINT, ASCLOCK, SHL, SHR, DSHL, DSHR, CVT, NEG, NOT, AND, OR, 571 | XOR, ANDR, ORR, XORR, CAT, BITS, HEAD, TAIL, UNDEFINED 572 | } Operation; 573 | 574 | PrimOp(); 575 | PrimOp(Operation op, int numOp, int numParam); 576 | virtual ~PrimOp() {} 577 | 578 | static const bool lookup(std::string v, Operation &op); 579 | std::string operationName(); 580 | static const std::string operationName(Operation op); 581 | 582 | static std::shared_ptr generate(const Operation &op); 583 | static std::shared_ptr generate(const std::string &op); 584 | 585 | void addOperand(std::shared_ptr o); 586 | void addParameter(int p); 587 | 588 | int numOperands() { return mNumOperands; } 589 | int numParameters() {return mNumParameters; } 590 | 591 | Operation getOp(); 592 | std::vector > getOperands(); 593 | std::vector getParameters(); 594 | 595 | virtual void accept(Visitor& v); 596 | protected: 597 | Operation mOp; 598 | std::vector > mOperands; 599 | std::vector mParameters; 600 | 601 | int mNumOperands; 602 | int mNumParameters; 603 | }; 604 | 605 | class PrimOpADD : public PrimOp { 606 | public: 607 | PrimOpADD() : PrimOp(ADD, 2, 0) {} 608 | }; 609 | 610 | class PrimOpSUB : public PrimOp { 611 | public: 612 | PrimOpSUB() : PrimOp(SUB, 2, 0) {} 613 | }; 614 | 615 | class PrimOpMUL : public PrimOp { 616 | public: 617 | PrimOpMUL() : PrimOp(MUL, 2, 0) {} 618 | }; 619 | 620 | class PrimOpDIV : public PrimOp { 621 | public: 622 | PrimOpDIV() : PrimOp(DIV, 2, 0) {} 623 | }; 624 | 625 | class PrimOpMOD : public PrimOp { 626 | public: 627 | PrimOpMOD() : PrimOp(MOD, 2, 0) {} 628 | }; 629 | 630 | class PrimOpLT : public PrimOp { 631 | public: 632 | PrimOpLT() : PrimOp(LT, 2, 0) {} 633 | }; 634 | 635 | class PrimOpLEQ : public PrimOp { 636 | public: 637 | PrimOpLEQ() : PrimOp(LEQ, 2, 0) {} 638 | }; 639 | 640 | class PrimOpGT : public PrimOp { 641 | public: 642 | PrimOpGT() : PrimOp(GT, 2, 0) {} 643 | }; 644 | 645 | class PrimOpGEQ : public PrimOp { 646 | public: 647 | PrimOpGEQ() : PrimOp(GEQ, 2, 0) {} 648 | }; 649 | 650 | class PrimOpEQ : public PrimOp { 651 | public: 652 | PrimOpEQ() : PrimOp(EQ, 2, 0) {} 653 | }; 654 | 655 | class PrimOpNEQ : public PrimOp { 656 | public: 657 | PrimOpNEQ() : PrimOp(NEQ, 2, 0) {} 658 | }; 659 | 660 | class PrimOpPAD : public PrimOp { 661 | public: 662 | PrimOpPAD() : PrimOp(ADD, 1, 1) {} 663 | }; 664 | 665 | class PrimOpASUINT : public PrimOp { 666 | public: 667 | PrimOpASUINT() : PrimOp(ASUINT, 1, 0) {} 668 | }; 669 | 670 | class PrimOpASSINT : public PrimOp { 671 | public: 672 | PrimOpASSINT() : PrimOp(ASSINT, 1, 0) {} 673 | }; 674 | 675 | class PrimOpASCLOCK : public PrimOp { 676 | public: 677 | PrimOpASCLOCK() : PrimOp(ASCLOCK, 1, 0) {} 678 | }; 679 | 680 | class PrimOpSHL : public PrimOp { 681 | public: 682 | PrimOpSHL() : PrimOp(SHL, 1, 1) {} 683 | }; 684 | 685 | class PrimOpSHR : public PrimOp { 686 | public: 687 | PrimOpSHR() : PrimOp(SHR, 1, 1) {} 688 | }; 689 | 690 | class PrimOpDSHL : public PrimOp { 691 | public: 692 | PrimOpDSHL() : PrimOp(DSHL, 2, 0) {} 693 | }; 694 | 695 | class PrimOpDSHR : public PrimOp { 696 | public: 697 | PrimOpDSHR() : PrimOp(DSHR, 2, 0) {} 698 | }; 699 | 700 | class PrimOpCVT : public PrimOp { 701 | public: 702 | PrimOpCVT() : PrimOp(CVT, 1, 0) {} 703 | }; 704 | 705 | class PrimOpNEG : public PrimOp { 706 | public: 707 | PrimOpNEG() : PrimOp(NEG, 1, 0) {} 708 | }; 709 | 710 | class PrimOpNOT : public PrimOp { 711 | public: 712 | PrimOpNOT() : PrimOp(NOT, 1, 0) {} 713 | }; 714 | 715 | class PrimOpAND : public PrimOp { 716 | public: 717 | PrimOpAND() : PrimOp(ADD, 2, 0) {} 718 | }; 719 | 720 | class PrimOpOR : public PrimOp { 721 | public: 722 | PrimOpOR() : PrimOp(OR, 2, 0) {} 723 | }; 724 | 725 | class PrimOpXOR : public PrimOp { 726 | public: 727 | PrimOpXOR() : PrimOp(XOR, 2, 0) {} 728 | }; 729 | 730 | class PrimOpANDR : public PrimOp { 731 | public: 732 | PrimOpANDR() : PrimOp(ANDR, 1, 0) {} 733 | }; 734 | 735 | class PrimOpORR : public PrimOp { 736 | public: 737 | PrimOpORR() : PrimOp(ORR, 1, 0) {} 738 | }; 739 | 740 | class PrimOpXORR : public PrimOp { 741 | public: 742 | PrimOpXORR() : PrimOp(XORR, 1, 0) {} 743 | }; 744 | 745 | class PrimOpCAT : public PrimOp { 746 | public: 747 | PrimOpCAT() : PrimOp(CAT, 2, 0) {} 748 | }; 749 | 750 | class PrimOpBITS : public PrimOp { 751 | public: 752 | PrimOpBITS() : PrimOp(BITS, 1, 2) {} 753 | }; 754 | 755 | class PrimOpHEAD : public PrimOp { 756 | public: 757 | PrimOpHEAD() : PrimOp(HEAD, 1, 1) {} 758 | }; 759 | 760 | class PrimOpTAIL : public PrimOp { 761 | public: 762 | PrimOpTAIL() : PrimOp(TAIL, 1, 1) {} 763 | }; 764 | 765 | } 766 | -------------------------------------------------------------------------------- /lib/include/Util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include 26 | #include 27 | 28 | namespace Firrtlator { 29 | 30 | inline void throwAssert(bool cond, std::string msg) { 31 | if (!cond) 32 | throw std::runtime_error(msg); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /lib/include/Visitor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "IR.h" 26 | 27 | namespace Firrtlator { 28 | 29 | class Visitor { 30 | public: 31 | virtual ~Visitor(); 32 | 33 | virtual bool visit(std::shared_ptr){ return true; }; 34 | virtual void leave(std::shared_ptr){}; 35 | 36 | virtual bool visit(std::shared_ptr){ return true; }; 37 | virtual void leave(std::shared_ptr){}; 38 | 39 | virtual bool visit(std::shared_ptr){ return true; }; 40 | virtual void leave(std::shared_ptr){}; 41 | 42 | virtual bool visit(std::shared_ptr){ return true; }; 43 | virtual void leave(std::shared_ptr){}; 44 | 45 | virtual void visit(std::shared_ptr){}; 46 | 47 | virtual void visit(std::shared_ptr){}; 48 | 49 | virtual bool visit(std::shared_ptr){ return true; }; 50 | virtual void leave(std::shared_ptr){}; 51 | 52 | virtual bool visit(std::shared_ptr){ return true; }; 53 | virtual void leave(std::shared_ptr){}; 54 | 55 | virtual bool visit(std::shared_ptr){ return true; }; 56 | virtual void leave(std::shared_ptr){}; 57 | 58 | virtual bool visit(std::shared_ptr){ return true; }; 59 | virtual void leave(std::shared_ptr){}; 60 | 61 | virtual bool visit(std::shared_ptr){ return true; }; 62 | virtual void leave(std::shared_ptr){}; 63 | 64 | virtual bool visit(std::shared_ptr){ return true; }; 65 | virtual void leave(std::shared_ptr){}; 66 | 67 | virtual bool visit(std::shared_ptr){ return true; }; 68 | virtual void leave(std::shared_ptr){}; 69 | 70 | virtual bool visit(std::shared_ptr){ return true; }; 71 | virtual void leave(std::shared_ptr){}; 72 | 73 | virtual bool visit(std::shared_ptr){ return true; }; 74 | virtual void leave(std::shared_ptr){}; 75 | 76 | virtual bool visit(std::shared_ptr){ return true; }; 77 | virtual void leave(std::shared_ptr){}; 78 | 79 | virtual bool visit(std::shared_ptr){ return true; }; 80 | virtual void leave(std::shared_ptr){}; 81 | 82 | virtual bool visit(std::shared_ptr){ return true; }; 83 | virtual void leave(std::shared_ptr){}; 84 | 85 | virtual bool visit(std::shared_ptr){ return true; }; 86 | virtual void leave(std::shared_ptr){}; 87 | 88 | virtual bool visit(std::shared_ptr){ return true; }; 89 | virtual void leave(std::shared_ptr){}; 90 | 91 | virtual bool visit(std::shared_ptr){ return true; }; 92 | virtual void leave(std::shared_ptr){}; 93 | 94 | virtual void visit(std::shared_ptr){}; 95 | 96 | virtual void visit(std::shared_ptr){}; 97 | 98 | virtual void visit(std::shared_ptr){}; 99 | 100 | virtual bool visit(std::shared_ptr){ return true; }; 101 | virtual void leave(std::shared_ptr){}; 102 | 103 | virtual bool visit(std::shared_ptr){ return true; }; 104 | virtual void leave(std::shared_ptr){}; 105 | 106 | virtual bool visit(std::shared_ptr){ return true; }; 107 | virtual void leave(std::shared_ptr){}; 108 | 109 | virtual bool visit(std::shared_ptr){ return true; }; 110 | virtual void leave(std::shared_ptr){}; 111 | 112 | virtual bool visit(std::shared_ptr){ return true; }; 113 | virtual void leave(std::shared_ptr){}; 114 | 115 | virtual bool visit(std::shared_ptr){ return true; }; 116 | virtual void leave(std::shared_ptr){}; 117 | 118 | // TODO: all PrimOps and default calls base 119 | }; 120 | 121 | } 122 | -------------------------------------------------------------------------------- /lib/ir/src/Circuit.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "IR.h" 24 | 25 | #include 26 | 27 | #include "Visitor.h" 28 | 29 | namespace Firrtlator { 30 | 31 | Circuit::Circuit() {} 32 | 33 | Circuit::Circuit(std::string id) : IRNode(id) {} 34 | 35 | void Circuit::addModule(std::shared_ptr mod) { 36 | mModules.push_back(mod); 37 | if (mod->isExternal()) { 38 | mExternalModules.push_back(mod); 39 | } else { 40 | mInternalModules.push_back(mod); 41 | } 42 | } 43 | 44 | std::vector > Circuit::getModules() { 45 | return mModules; 46 | } 47 | 48 | void Circuit::accept(Visitor& v) { 49 | if (!v.visit(shared_from_base())) 50 | return; 51 | 52 | for (auto m : mExternalModules) 53 | m->accept(v); 54 | 55 | for (auto m : mInternalModules) 56 | m->accept(v); 57 | 58 | 59 | v.leave(shared_from_base()); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /lib/ir/src/Expression.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "IR.h" 24 | #include "Visitor.h" 25 | 26 | #include 27 | 28 | namespace Firrtlator { 29 | 30 | typedef enum { MALE, FEMALE, BI } Gender; 31 | 32 | Expression::Expression() : mGender(MALE) {} 33 | 34 | Expression::Expression(Gender g) : mGender(g) {} 35 | 36 | Expression::Gender Expression::getGender() { 37 | return mGender; 38 | } 39 | 40 | Reference::Reference() : Reference("") {} 41 | 42 | Reference::Reference(std::string id) : mTo(nullptr), mToString(id) {} 43 | 44 | bool Reference::isResolved() { 45 | return (mTo != nullptr && mTo != 0); 46 | } 47 | 48 | std::string Reference::getToString() { 49 | return mToString; 50 | } 51 | 52 | void Reference::accept(Visitor& v) { 53 | v.visit(shared_from_base()); 54 | } 55 | 56 | Constant::Constant() : Constant(nullptr, -1, UNDEFINED) {} 57 | 58 | Constant::Constant(std::shared_ptr type, int val, 59 | GenerateHint hint) 60 | : mType(type), mVal(val), mHint(hint) {} 61 | 62 | Constant::Constant(std::shared_ptr type, std::string val, 63 | GenerateHint hint) 64 | : mType(type), mHint(hint) { 65 | mVal = 0; //TODO: convert 66 | } 67 | 68 | std::shared_ptr Constant::getType() { 69 | return mType; 70 | } 71 | 72 | int Constant::getValue() { 73 | return mVal; 74 | } 75 | 76 | Constant::GenerateHint Constant::getHint() { 77 | return mHint; 78 | } 79 | 80 | std::string Constant::getString() { 81 | std::string t = mType->getSigned() ? "SInt" : "UInt"; 82 | std::string w = std::to_string(mType->getWidth()); 83 | std::string v = std::to_string(mVal); 84 | 85 | return std::string(t+"<"+w+">("+v+")"); 86 | } 87 | 88 | void Constant::accept(Visitor& v) { 89 | v.visit(shared_from_base()); 90 | } 91 | 92 | SubField::SubField() : SubField(nullptr, nullptr) {} 93 | 94 | SubField::SubField(std::shared_ptr id, std::shared_ptr of) 95 | : mOf(of), mField(id) {} 96 | 97 | std::shared_ptr SubField::getOf() { 98 | return mOf; 99 | } 100 | 101 | std::shared_ptr SubField::getField() { 102 | return mField; 103 | } 104 | 105 | void SubField::accept(Visitor& v) { 106 | if (!v.visit(shared_from_base())) 107 | return; 108 | 109 | mOf->accept(v); 110 | mField->accept(v); 111 | 112 | v.leave(shared_from_base()); 113 | } 114 | 115 | SubIndex::SubIndex() : SubIndex(-1, nullptr) {} 116 | 117 | SubIndex::SubIndex(int index, std::shared_ptr of) 118 | : mOf(of), mIndex(index) {} 119 | 120 | std::shared_ptr SubIndex::getOf() { 121 | return mOf; 122 | } 123 | 124 | int SubIndex::getIndex() { 125 | return mIndex; 126 | } 127 | 128 | void SubIndex::accept(Visitor& v) { 129 | if(!v.visit(shared_from_base())) 130 | return; 131 | 132 | mOf->accept(v); 133 | 134 | v.leave(shared_from_base()); 135 | } 136 | 137 | SubAccess::SubAccess() : SubAccess(nullptr, nullptr) {} 138 | 139 | SubAccess::SubAccess(std::shared_ptr expr, 140 | std::shared_ptr of) 141 | : mOf(of), mExp(expr) {} 142 | 143 | std::shared_ptr SubAccess::getOf() { 144 | return mOf; 145 | } 146 | 147 | std::shared_ptr SubAccess::getExp() { 148 | return mExp; 149 | } 150 | 151 | void SubAccess::accept(Visitor& v) { 152 | if (!v.visit(shared_from_base())) 153 | return; 154 | 155 | mOf->accept(v); 156 | mExp->accept(v); 157 | 158 | v.leave(shared_from_base()); 159 | } 160 | 161 | Mux::Mux() : Mux(nullptr, nullptr, nullptr) {} 162 | 163 | Mux::Mux(std::shared_ptr sel, std::shared_ptr a, 164 | std::shared_ptr b) 165 | : mSel(sel), mA(a), mB(b) {} 166 | 167 | std::shared_ptr Mux::getSel() { 168 | return mSel; 169 | } 170 | 171 | std::shared_ptr Mux::getA() { 172 | return mA; 173 | } 174 | 175 | std::shared_ptr Mux::getB() { 176 | return mB; 177 | } 178 | 179 | void Mux::accept(Visitor& v) { 180 | if (!v.visit(shared_from_base())) 181 | return; 182 | 183 | mSel->accept(v); 184 | mA->accept(v); 185 | mB->accept(v); 186 | 187 | v.leave(shared_from_base()); 188 | } 189 | 190 | CondValid::CondValid() : CondValid(nullptr, nullptr) {} 191 | 192 | CondValid::CondValid(std::shared_ptr sel, 193 | std::shared_ptr a) 194 | : mSel(sel), mA(a) {} 195 | 196 | std::shared_ptr CondValid::getSel() { 197 | return mSel; 198 | } 199 | 200 | std::shared_ptr CondValid::getA() { 201 | return mA; 202 | } 203 | 204 | void CondValid::accept(Visitor& v) { 205 | if (!v.visit(shared_from_base())) 206 | return; 207 | 208 | mSel->accept(v); 209 | mA->accept(v); 210 | 211 | v.leave(shared_from_base()); 212 | } 213 | 214 | const bool PrimOp::lookup(std::string v, Operation &op) { 215 | static const std::map map = { 216 | {"add", ADD}, {"sub", SUB }, {"mul", MUL }, 217 | {"div", DIV}, {"mod", MOD }, {"lt", LT }, 218 | {"leq", LEQ}, {"gt", GT}, {"geq", GEQ }, {"eq", EQ}, 219 | {"neq", NEQ}, {"pad", PAD}, {"asUInt", ASUINT}, 220 | {"asSInt", ASSINT}, {"asClock", ASCLOCK}, 221 | {"shl", SHL}, {"shr", SHR}, {"dshl", DSHL}, 222 | {"dshr", DSHR}, {"cvt", CVT}, {"neg", NEG}, 223 | {"not", NOT}, {"and", AND}, {"or", OR}, 224 | {"xor", XOR}, {"andr", ANDR}, {"orr", ORR}, 225 | {"xorr", XORR}, {"cat", CAT}, {"bits", BITS}, 226 | {"head", HEAD}, {"tail", TAIL} 227 | }; 228 | 229 | if (map.find(v) == map.end()) { 230 | op = UNDEFINED; 231 | return false; 232 | } 233 | 234 | op = map.find(v)->second; 235 | return true; 236 | } 237 | 238 | PrimOp::PrimOp() : PrimOp(UNDEFINED, 0, 0) {} 239 | 240 | PrimOp::PrimOp(Operation op, int numOps, int numParams) : 241 | Expression(MALE), mOp(op), 242 | mNumOperands(numOps), mNumParameters(numParams) { 243 | 244 | } 245 | 246 | std::shared_ptr PrimOp::generate(const Operation &op) { 247 | #define GENOP(x) case x: return std::make_shared(); 248 | switch (op) { 249 | GENOP(ADD); GENOP(SUB); GENOP(MUL); GENOP(DIV); GENOP(MOD); 250 | GENOP(LT); GENOP(LEQ); GENOP(GT); GENOP(GEQ); GENOP(EQ); 251 | GENOP(NEQ); GENOP(PAD); GENOP(ASUINT);GENOP(ASSINT); GENOP(ASCLOCK); 252 | GENOP(SHL); GENOP(SHR); GENOP(DSHL); GENOP(DSHR); GENOP(CVT); 253 | GENOP(NEG); GENOP(NOT); GENOP(AND); GENOP(OR); GENOP(XOR); 254 | GENOP(ANDR); GENOP(ORR); GENOP(XORR); GENOP(CAT); GENOP(BITS); 255 | GENOP(HEAD); GENOP(TAIL); 256 | default: 257 | throw std::runtime_error("Unknown operation type"); 258 | } 259 | #undef GENOP 260 | } 261 | 262 | const std::string PrimOp::operationName(Operation op) { 263 | #define GENOP(x,y) case x: return y; 264 | switch(op) { 265 | GENOP(ADD,"add"); GENOP(SUB,"sub"); GENOP(MUL,"mul"); GENOP(DIV,"div"); 266 | GENOP(MOD,"mod"); GENOP(LT,"lt"); GENOP(LEQ,"leq"); GENOP(GT,"gt"); 267 | GENOP(GEQ,"geq"); GENOP(EQ,"eq"); GENOP(NEQ,"neq"); GENOP(PAD,"pad"); 268 | GENOP(ASUINT,"asUInt"); GENOP(ASSINT,"asSInt"); GENOP(ASCLOCK,"asClock"); 269 | GENOP(SHL,"shl"); GENOP(SHR,"shr"); GENOP(DSHL,"dshl"); GENOP(DSHR,"dshr"); 270 | GENOP(CVT,"cvt"); GENOP(NEG,"neg"); GENOP(NOT,"not"); GENOP(AND,"and"); 271 | GENOP(OR,"or"); GENOP(XOR,"xor"); GENOP(ANDR,"andr"); GENOP(ORR,"orr"); 272 | GENOP(XORR,"xorr"); GENOP(CAT,"cat"); GENOP(BITS,"bits"); 273 | GENOP(HEAD,"head"); GENOP(TAIL,"tail"); 274 | default: 275 | throw std::runtime_error("Unknown operation type"); 276 | } 277 | #undef GENOP 278 | } 279 | 280 | std::string PrimOp::operationName() { 281 | return operationName(mOp); 282 | } 283 | 284 | std::shared_ptr PrimOp::generate(const std::string &s) { 285 | Operation op; 286 | if (!lookup(s, op)) { 287 | throw std::runtime_error("Unknown operation type"); 288 | } 289 | 290 | return generate(op); 291 | } 292 | 293 | void PrimOp::addOperand(std::shared_ptr o) { 294 | if (mOperands.size() == (unsigned) mNumOperands) { 295 | throw std::runtime_error("Too many operands"); 296 | } 297 | mOperands.push_back(o); 298 | } 299 | 300 | void PrimOp::addParameter(int p) { 301 | if (mParameters.size() == (unsigned) mNumParameters) { 302 | throw std::runtime_error("Too many parameters"); 303 | } 304 | mParameters.push_back(p); 305 | } 306 | 307 | PrimOp::Operation PrimOp::getOp() { 308 | return mOp; 309 | } 310 | 311 | std::vector > PrimOp::getOperands() { 312 | return mOperands; 313 | } 314 | 315 | std::vector PrimOp::getParameters() { 316 | return mParameters; 317 | } 318 | 319 | void PrimOp::accept(Visitor& v) { 320 | if (!v.visit(shared_from_base())) 321 | return; 322 | 323 | for (auto o : mOperands) 324 | o->accept(v); 325 | 326 | v.leave(shared_from_base()); 327 | } 328 | 329 | } 330 | -------------------------------------------------------------------------------- /lib/ir/src/IRNode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace Firrtlator { 28 | 29 | IRNode::~IRNode() {} 30 | 31 | IRNode::IRNode() : IRNode("") {} 32 | 33 | IRNode::IRNode(std::string id) : mId(id) {} 34 | 35 | std::string IRNode::getId() { return mId; } 36 | 37 | void IRNode::setId(std::string id) { mId = id; } 38 | 39 | std::shared_ptr IRNode::getInfo() { return mInfo; } 40 | 41 | void IRNode::setInfo(std::shared_ptr info) { 42 | mInfo = info; 43 | } 44 | 45 | bool IRNode::isDeclaration() { return (mId.length() != 0); } 46 | 47 | Info::Info(std::string value) : mValue(value) {} 48 | 49 | void Info::setValue(std::string value) { mValue = value; } 50 | 51 | std::string Info::getValue() { return mValue; } 52 | 53 | std::ostream& operator<< (std::ostream &os, const Info &info) 54 | { 55 | if (info.mValue.length() > 0) { 56 | os << " @[" << info.mValue << "] "; 57 | } 58 | return os; 59 | } 60 | 61 | } 62 | 63 | -------------------------------------------------------------------------------- /lib/ir/src/Memory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "IR.h" 24 | #include "Visitor.h" 25 | #include "Util.h" 26 | 27 | namespace Firrtlator { 28 | 29 | Memory::Memory(std::string id) : Stmt(id) {} 30 | 31 | void Memory::setDType(std::shared_ptr type) { 32 | throwAssert((type != nullptr), "Invalid memory type"); 33 | throwAssert((mDType == nullptr), "Memory type already set"); 34 | 35 | mDType = type; 36 | } 37 | 38 | void Memory::setDepth(int depth) { 39 | throwAssert((depth >= 0), "Invalid memory depth"); 40 | throwAssert((mDepth == -1), "Memory depth already set"); 41 | 42 | mDepth = depth; 43 | } 44 | 45 | void Memory::setReadLatency(int lat) { 46 | throwAssert((lat >= 0), "Invalid memory read latency"); 47 | throwAssert((mReadlatency == -1), "Memory read latency already set"); 48 | 49 | mDepth = lat; 50 | } 51 | 52 | void Memory::setWriteLatency(int lat) { 53 | throwAssert((lat >= 0), "Invalid memory write latency"); 54 | throwAssert((mWritelatency == -1), "Memory write latency already set"); 55 | 56 | mWritelatency = lat; 57 | } 58 | 59 | void Memory::setRuwFlag(RuwFlag flag) { 60 | throwAssert(!mRuwflagset, "Memory RUW flag already set"); 61 | 62 | mRuwflagset = true; 63 | mRuwflag = flag; 64 | } 65 | 66 | void Memory::addReader(std::string r) { 67 | throwAssert((std::find(mReaders.begin(), mReaders.end(), (r)) 68 | == mReaders.end()), "Reader already defined"); 69 | 70 | if (!checkAndUpdateDeferedType()) 71 | addReaderToType(r); 72 | 73 | mReaders.push_back(r); 74 | } 75 | 76 | void Memory::addWriter(std::string w) { 77 | throwAssert((std::find(mWriters.begin(), mWriters.end(), (w)) 78 | == mWriters.end()), "writer already defined"); 79 | 80 | if (!checkAndUpdateDeferedType()) 81 | addWriterToType(w); 82 | 83 | mWriters.push_back(w); 84 | } 85 | 86 | void Memory::addReadWriter(std::string rw) { 87 | throwAssert((std::find(mReadWriters.begin(), mReadWriters.end(), (rw)) 88 | == mReadWriters.end()), "ReadWriter already defined"); 89 | 90 | if (!checkAndUpdateDeferedType()) 91 | addReadWriterToType(rw); 92 | 93 | mReadWriters.push_back(rw); 94 | } 95 | 96 | std::shared_ptr Memory::getDType() { 97 | return mDType; 98 | } 99 | 100 | std::shared_ptr Memory::getType() { 101 | return mType; 102 | } 103 | 104 | std::vector Memory::getReaders() { 105 | return mReaders; 106 | } 107 | 108 | std::vector Memory::getWriters() { 109 | return mWriters; 110 | } 111 | 112 | std::vector Memory::getReadWriters() { 113 | return mReadWriters; 114 | } 115 | 116 | int Memory::getDepth() { 117 | return mDepth; 118 | } 119 | 120 | int Memory::getReadlatency() { 121 | return mReadlatency; 122 | } 123 | 124 | int Memory::getWritelatency() { 125 | return mWritelatency; 126 | } 127 | 128 | Memory::RuwFlag Memory::getRuwflag() { 129 | return mRuwflag; 130 | } 131 | 132 | bool Memory::checkAndUpdateDeferedType() { 133 | // TODO: Add further defer reasons 134 | if (mDType == nullptr) 135 | return false; 136 | 137 | if (mType != nullptr) 138 | return true; 139 | 140 | mType = std::make_shared(); 141 | 142 | for (auto r : mReaders) 143 | addReaderToType(r); 144 | for (auto w : mWriters) 145 | addWriterToType(w); 146 | for (auto rw : mReadWriters) 147 | addReadWriterToType(rw); 148 | 149 | return true; 150 | } 151 | 152 | void Memory::addReaderToType(std::string r) { 153 | std::shared_ptr bundle; 154 | bundle = std::make_shared(); 155 | //bundle->addField(std::make_shared("data", TODO, true)); // Copy constructor 156 | //bundle->addField(std::make_shared("addr", TODO)); // Width inference 157 | bundle->addField(std::make_shared("en", 158 | std::make_shared(false, 1))); 159 | bundle->addField(std::make_shared("clk", 160 | std::make_shared())); 161 | mType->addField(std::make_shared(r, bundle)); 162 | } 163 | 164 | void Memory::addWriterToType(std::string w) { 165 | std::shared_ptr bundle; 166 | bundle = std::make_shared(); 167 | //bundle->addField(std::make_shared("data", TODO, true)); // Copy constructor 168 | //bundle->addField(std::make_shared("mask", TODO, true)); // Inference 169 | //bundle->addField(std::make_shared("addr", TODO)); // Width inference 170 | bundle->addField(std::make_shared("en", 171 | std::make_shared(false, 1))); 172 | bundle->addField(std::make_shared("clk", 173 | std::make_shared())); 174 | mType->addField(std::make_shared(w, bundle)); 175 | } 176 | 177 | void Memory::addReadWriterToType(std::string rw) { 178 | std::shared_ptr bundle; 179 | bundle = std::make_shared(); 180 | //bundle->addField(std::make_shared("data", TODO, true)); // Copy constructor 181 | //bundle->addField(std::make_shared("mask", TODO, true)); // Inference 182 | //bundle->addField(std::make_shared("addr", TODO)); // Width inference 183 | bundle->addField(std::make_shared("en", 184 | std::make_shared(false, 1))); 185 | bundle->addField(std::make_shared("clk", 186 | std::make_shared())); 187 | bundle->addField(std::make_shared("wmode", 188 | std::make_shared(false, 1))); 189 | mType->addField(std::make_shared(rw, bundle)); 190 | } 191 | 192 | void Memory::accept(Visitor& v) { 193 | v.visit(shared_from_base()); 194 | } 195 | 196 | } 197 | -------------------------------------------------------------------------------- /lib/ir/src/Module.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "../backends/generic/include/StreamIndentation.h" 24 | #include "IR.h" 25 | #include "Util.h" 26 | 27 | #include "Visitor.h" 28 | 29 | namespace Firrtlator { 30 | 31 | Module::Module() : Module("") {} 32 | Module::Module(std::string id, bool external) 33 | : IRNode(id), mExternal(external) {} 34 | 35 | void Module::addPort(std::shared_ptr port) { 36 | mPorts.push_back(port); 37 | } 38 | 39 | void Module::setStatementGroup(std::shared_ptr stmts) { 40 | mStmts = stmts; 41 | } 42 | 43 | void Module::setDefname(std::string defname) { 44 | throwAssert(mExternal, "Cannot assign defname to module"); 45 | 46 | mDefname = defname; 47 | } 48 | void Module::addParameter(std::shared_ptr param) { 49 | throwAssert(mExternal, "Cannot add parameter to module"); 50 | 51 | mParameters.push_back(param); 52 | } 53 | 54 | bool Module::isExternal() { 55 | return mExternal; 56 | } 57 | 58 | std::string Module::getDefname() { 59 | return mDefname; 60 | } 61 | 62 | std::vector > Module::getPorts() { 63 | return mPorts; 64 | } 65 | 66 | std::shared_ptr Module::getStmts() { 67 | return mStmts; 68 | } 69 | 70 | std::vector > Module::getParameters() { 71 | return mParameters; 72 | } 73 | 74 | void Module::accept(Visitor& v) { 75 | if (!v.visit(shared_from_base())) 76 | return; 77 | 78 | for (auto p : mPorts) 79 | p->accept(v); 80 | 81 | if (mStmts) 82 | mStmts->accept(v); 83 | 84 | v.leave(shared_from_base()); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /lib/ir/src/Parameter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "IR.h" 24 | #include "Visitor.h" 25 | 26 | namespace Firrtlator { 27 | 28 | Parameter::Parameter() { 29 | 30 | } 31 | 32 | void Parameter::accept(Visitor& v) { 33 | v.visit(shared_from_base()); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /lib/ir/src/Port.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "../backends/generic/include/StreamIndentation.h" 24 | #include "IR.h" 25 | #include "Visitor.h" 26 | 27 | namespace Firrtlator { 28 | 29 | Port::Port() : Port("", INPUT, nullptr) { } 30 | 31 | Port::Port(std::string id, Direction dir, std::shared_ptr type) 32 | : IRNode(id), mDirection(dir), mType(type) {} 33 | 34 | void Port::setDirection(Direction dir) { 35 | mDirection = dir; 36 | } 37 | 38 | Port::Direction Port::getDirection() { 39 | return mDirection; 40 | } 41 | 42 | void Port::accept(Visitor& v) { 43 | if (!v.visit(shared_from_base())) 44 | return; 45 | 46 | mType->accept(v); 47 | 48 | v.leave(shared_from_base()); 49 | } 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /lib/ir/src/Stmt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "../backends/generic/include/StreamIndentation.h" 24 | #include "IR.h" 25 | #include "Util.h" 26 | #include "Visitor.h" 27 | 28 | namespace Firrtlator { 29 | 30 | Stmt::Stmt() : Stmt("") {} 31 | 32 | Stmt::Stmt(std::string id) : IRNode(id) {} 33 | 34 | StmtGroup::StmtGroup() {} 35 | 36 | StmtGroup::StmtGroup(std::shared_ptr stmt) { 37 | mGroup.push_back(stmt); 38 | } 39 | 40 | 41 | StmtGroup::StmtGroup(std::vector > group) { 42 | mGroup = group; 43 | } 44 | 45 | void StmtGroup::addStatement(std::shared_ptr stmt) { 46 | mGroup.push_back(stmt); 47 | } 48 | 49 | StmtGroup::iterator StmtGroup::begin() { 50 | return mGroup.begin(); 51 | } 52 | 53 | StmtGroup::iterator StmtGroup::end() { 54 | return mGroup.end(); 55 | } 56 | 57 | void StmtGroup::accept(Visitor& v) { 58 | if (!v.visit(shared_from_base())) 59 | return; 60 | 61 | for (auto s : mGroup) 62 | s->accept(v); 63 | 64 | v.leave(shared_from_base()); 65 | } 66 | 67 | 68 | Wire::Wire() : Wire("", nullptr) {} 69 | 70 | Wire::Wire(std::string id, std::shared_ptr type) 71 | : Stmt(id), mType(type) {} 72 | 73 | std::shared_ptr Wire::getType() { 74 | return mType; 75 | } 76 | 77 | void Wire::accept(Visitor& v) { 78 | if(!v.visit(shared_from_base())) 79 | return; 80 | 81 | mType->accept(v); 82 | 83 | v.leave(shared_from_base()); 84 | } 85 | 86 | Reg::Reg() : Reg("", nullptr, nullptr) {} 87 | 88 | Reg::Reg(std::string id, std::shared_ptr type, 89 | std::shared_ptr clock) 90 | : Stmt(id), mType(type), mClock(clock) {} 91 | 92 | std::shared_ptr Reg::getType() { 93 | return mType; 94 | } 95 | 96 | std::shared_ptr Reg::getClock() { 97 | return mClock; 98 | } 99 | 100 | void Reg::accept(Visitor& v) { 101 | if (!v.visit(shared_from_base())) 102 | return; 103 | 104 | mType->accept(v); 105 | mClock->accept(v); 106 | 107 | if (mResetTrigger && mResetValue) { 108 | mResetTrigger->accept(v); 109 | mResetValue->accept(v); 110 | } 111 | 112 | v.leave(shared_from_base()); 113 | } 114 | 115 | void Reg::setResetTrigger(std::shared_ptr trigger) { 116 | mResetTrigger = trigger; 117 | } 118 | 119 | void Reg::setResetValue(std::shared_ptr value) { 120 | mResetValue = value; 121 | } 122 | 123 | std::shared_ptr Reg::getResetTrigger() { 124 | return mResetTrigger; 125 | } 126 | 127 | std::shared_ptr Reg::getResetValue() { 128 | return mResetValue; 129 | } 130 | 131 | 132 | Instance::Instance() : Instance("", nullptr) {} 133 | 134 | Instance::Instance(std::string id, std::shared_ptr of) 135 | : Stmt(id), mOf(of) {} 136 | 137 | std::shared_ptr Instance::getOf() { 138 | return mOf; 139 | } 140 | 141 | void Instance::accept(Visitor& v) { 142 | if (!v.visit(shared_from_base())) 143 | return; 144 | 145 | mOf->accept(v); 146 | 147 | v.leave(shared_from_base()); 148 | } 149 | 150 | Node::Node() : Node("", nullptr) {} 151 | 152 | Node::Node(std::string id, std::shared_ptr expr) 153 | : Stmt(id), mExpr(expr) {} 154 | 155 | std::shared_ptr Node::getExpression() { 156 | return mExpr; 157 | } 158 | 159 | void Node::accept(Visitor& v) { 160 | if (!v.visit(shared_from_base())) 161 | return; 162 | 163 | mExpr->accept(v); 164 | 165 | v.leave(shared_from_base()); 166 | } 167 | 168 | Connect::Connect() : Connect(nullptr, nullptr) {} 169 | 170 | Connect::Connect(std::shared_ptr to, 171 | std::shared_ptr from, 172 | bool partial) 173 | : mTo(to), mFrom(from), mPartial(partial) {} 174 | 175 | bool Connect::getPartial() { 176 | return mPartial; 177 | } 178 | 179 | std::shared_ptr Connect::getTo() { 180 | return mTo; 181 | } 182 | 183 | std::shared_ptr Connect::getFrom() { 184 | return mFrom; 185 | } 186 | 187 | void Connect::accept(Visitor& v) { 188 | if (!v.visit(shared_from_base())) 189 | return; 190 | 191 | mTo->accept(v); 192 | mFrom->accept(v); 193 | 194 | v.leave(shared_from_base()); 195 | } 196 | 197 | Invalid::Invalid() : Invalid(nullptr) {} 198 | 199 | Invalid::Invalid(std::shared_ptr exp) 200 | : mExp(exp) {} 201 | 202 | std::shared_ptr Invalid::getExpr() { 203 | return mExp; 204 | } 205 | 206 | void Invalid::accept(Visitor& v) { 207 | if (!v.visit(shared_from_base())) 208 | return; 209 | 210 | mExp->accept(v); 211 | 212 | v.leave(shared_from_base()); 213 | } 214 | 215 | Conditional::Conditional() : Conditional(nullptr) {} 216 | 217 | Conditional::Conditional(std::shared_ptr cond) 218 | : mCond(cond) {} 219 | 220 | void Conditional::setThen(std::shared_ptr stmt) { 221 | mThen = stmt; 222 | } 223 | 224 | void Conditional::setElse(std::shared_ptr e) { 225 | mElse = e; 226 | } 227 | 228 | std::shared_ptr Conditional::getCondition() { 229 | return mCond; 230 | } 231 | 232 | std::shared_ptr Conditional::getThen() { 233 | return mThen; 234 | } 235 | 236 | std::shared_ptr Conditional::getElse() { 237 | return mElse; 238 | } 239 | 240 | void Conditional::accept(Visitor& v) { 241 | if (!v.visit(shared_from_base())) 242 | return; 243 | 244 | mCond->accept(v); 245 | 246 | mThen->accept(v); 247 | 248 | if (mElse) 249 | mElse->accept(v); 250 | 251 | v.leave(shared_from_base()); 252 | } 253 | 254 | ConditionalElse::ConditionalElse() {} 255 | 256 | ConditionalElse::ConditionalElse(std::shared_ptr stmts) 257 | : mStmts(stmts) {} 258 | 259 | void ConditionalElse::setStmts(std::shared_ptr stmt) { 260 | mStmts = stmt; 261 | } 262 | 263 | std::shared_ptr ConditionalElse::getStmts() { 264 | return mStmts; 265 | } 266 | 267 | void ConditionalElse::accept(Visitor& v) { 268 | if (!v.visit(shared_from_base())) 269 | return; 270 | 271 | mStmts->accept(v); 272 | 273 | v.leave(shared_from_base()); 274 | } 275 | 276 | Stop::Stop() : Stop(nullptr, nullptr, -1) {} 277 | 278 | Stop::Stop(std::shared_ptr clock, 279 | std::shared_ptr cond, 280 | int code) 281 | : mClock(clock), mCond(cond), mCode(code) {} 282 | 283 | std::shared_ptr Stop::getClock() { 284 | return mClock; 285 | } 286 | 287 | std::shared_ptr Stop::getCondition() { 288 | return mCond; 289 | } 290 | 291 | int Stop::getCode() { 292 | return mCode; 293 | } 294 | 295 | void Stop::accept(Visitor& v) { 296 | if (!v.visit(shared_from_base())) 297 | return; 298 | 299 | mClock->accept(v); 300 | mCond->accept(v); 301 | 302 | v.leave(shared_from_base()); 303 | } 304 | 305 | Printf::Printf() : Printf(nullptr, nullptr, "") {} 306 | Printf::Printf(std::shared_ptr clock, 307 | std::shared_ptr cond, 308 | std::string format) 309 | : mClock(clock), mCond(cond), mFormat(format) {} 310 | void Printf::addArgument(std::shared_ptr arg) { 311 | mArguments.push_back(arg); 312 | } 313 | 314 | std::shared_ptr Printf::getClock() { 315 | return mClock; 316 | } 317 | 318 | std::shared_ptr Printf::getCondition() { 319 | return mCond; 320 | } 321 | 322 | std::string Printf::getFormat() { 323 | return mFormat; 324 | } 325 | 326 | std::vector > Printf::getArguments() { 327 | return mArguments; 328 | } 329 | 330 | void Printf::accept(Visitor& v) { 331 | if (!v.visit(shared_from_base())) 332 | return; 333 | 334 | mClock->accept(v); 335 | mCond->accept(v); 336 | 337 | for (auto a : mArguments) 338 | a->accept(v); 339 | 340 | v.leave(shared_from_base()); 341 | } 342 | 343 | void Empty::accept(Visitor& v) { 344 | v.visit(shared_from_base()); 345 | } 346 | 347 | 348 | } 349 | -------------------------------------------------------------------------------- /lib/ir/src/Type.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "../backends/generic/include/StreamIndentation.h" 24 | #include "IR.h" 25 | #include "Visitor.h" 26 | 27 | namespace Firrtlator { 28 | 29 | Type::Type() : mBasetype(UNDEFINED) {} 30 | 31 | Type::Type(Basetype type) : mBasetype(type) {} 32 | 33 | TypeInt::TypeInt() : TypeInt(false) {} 34 | 35 | TypeInt::TypeInt(bool sign, int width) 36 | : Type(INT), mWidth(width), mSigned(sign) {} 37 | 38 | void TypeInt::setWidth(int width) { 39 | mWidth = width; 40 | } 41 | 42 | int TypeInt::getWidth() { 43 | return mWidth; 44 | } 45 | 46 | bool TypeInt::getSigned() { 47 | return mSigned; 48 | } 49 | 50 | void TypeInt::setSigned(bool sign) { 51 | mSigned = sign; 52 | } 53 | 54 | void TypeInt::accept(Visitor& v) { 55 | v.visit(shared_from_base()); 56 | } 57 | 58 | TypeClock::TypeClock() : Type(CLOCK) { } 59 | 60 | void TypeClock::accept(Visitor& v) { 61 | v.visit(shared_from_base()); 62 | } 63 | 64 | Field::Field() : Field("", nullptr) {} 65 | Field::Field(std::string id, std::shared_ptr type, bool flip) 66 | : IRNode(id), mFlip(flip), mType(type) {} 67 | 68 | void Field::setType(std::shared_ptr t) { 69 | mType = t; 70 | } 71 | 72 | void Field::setFlip(bool flip) { 73 | mFlip = flip; 74 | } 75 | 76 | std::shared_ptr Field::getType() { 77 | return mType; 78 | } 79 | 80 | bool Field::getFlip() { 81 | return mFlip; 82 | } 83 | 84 | void Field::accept(Visitor& v) { 85 | v.visit(shared_from_base()); 86 | } 87 | 88 | TypeBundle::TypeBundle() : Type(BUNDLE) {} 89 | void TypeBundle::addField(std::shared_ptr field) { 90 | mFields.push_back(field); 91 | } 92 | 93 | std::vector > TypeBundle::getFields() { 94 | return mFields; 95 | } 96 | 97 | void TypeBundle::accept(Visitor& v) { 98 | 99 | } 100 | 101 | TypeVector::TypeVector() : Type(VECTOR), mSize(0) { } 102 | 103 | void TypeVector::setSize(int size) { 104 | mSize = size; 105 | } 106 | 107 | int TypeVector::getSize() { 108 | return mSize; 109 | } 110 | 111 | void TypeVector::accept(Visitor& v) { 112 | v.visit(shared_from_base()); 113 | } 114 | 115 | } 116 | 117 | -------------------------------------------------------------------------------- /lib/passes/FirrtlatorPass.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "IR.h" 30 | #include "Firrtlator.h" 31 | 32 | namespace Firrtlator { 33 | namespace Pass { 34 | 35 | class PassBase { 36 | public: 37 | virtual ~PassBase(); 38 | virtual void run(std::shared_ptr) = 0; 39 | }; 40 | 41 | class PassFactory 42 | { 43 | public: 44 | virtual ~PassFactory() {} 45 | virtual std::shared_ptr create() = 0; 46 | 47 | virtual std::string getName() = 0; 48 | virtual std::string getDescription() = 0; 49 | }; 50 | 51 | class Registry { 52 | public: 53 | static void registerPass(const std::string &name, 54 | PassFactory * factory); 55 | static std::shared_ptr create(const std::string &name) { 56 | throwAssert(getPassMap().find(name) != getPassMap().end(), 57 | "Cannot find pass: " + name); 58 | return getPassMap()[name]->create(); 59 | } 60 | 61 | static std::vector getDescriptors() { 62 | std::vector list; 63 | for (auto b : getPassMap()) { 64 | Firrtlator::PassDescriptor desc; 65 | desc.name = b.second->getName(); 66 | desc.description = b.second->getDescription(); 67 | list.push_back(desc); 68 | } 69 | return list; 70 | } 71 | private: 72 | typedef std::map PassMap; 73 | static PassMap &getPassMap() { 74 | static PassMap map; 75 | return map; 76 | } 77 | }; 78 | 79 | } 80 | } 81 | 82 | #define REGISTER_PASS(pass) \ 83 | class pass##Factory : public ::Firrtlator::Pass::PassFactory { \ 84 | public: \ 85 | pass##Factory() \ 86 | { \ 87 | ::Firrtlator::Pass::Registry::registerPass(pass::name, \ 88 | this); \ 89 | } \ 90 | virtual std::shared_ptr<::Firrtlator::Pass::PassBase> create() { \ 91 | return std::make_shared(); \ 92 | } \ 93 | virtual std::string getName() { \ 94 | return pass::name; \ 95 | } \ 96 | virtual std::string getDescription() { \ 97 | return pass::description; \ 98 | } \ 99 | }; \ 100 | static pass##Factory global_##pass##Factory; 101 | -------------------------------------------------------------------------------- /lib/passes/generic/src/Passes.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "FirrtlatorPass.h" 24 | 25 | namespace Firrtlator { 26 | namespace Pass { 27 | 28 | PassBase::~PassBase() { 29 | 30 | } 31 | 32 | void Registry::registerPass(const std::string &name, 33 | PassFactory* factory) { 34 | getPassMap()[name] = factory; 35 | } 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/passes/stripinfo/include/StripInfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "Visitor.h" 26 | #include "FirrtlatorPass.h" 27 | 28 | #include 29 | #include 30 | 31 | namespace Firrtlator { 32 | namespace Pass { 33 | namespace StripInfo { 34 | 35 | class Pass : public ::Firrtlator::Pass::PassBase { 36 | public: 37 | Pass(); 38 | virtual void run(std::shared_ptr ir); 39 | static std::string name; 40 | static std::string description; 41 | }; 42 | 43 | class Visitor : public ::Firrtlator::Visitor { 44 | public: 45 | Visitor(); 46 | 47 | virtual ~Visitor(); 48 | virtual bool visit(std::shared_ptr); 49 | 50 | virtual bool visit(std::shared_ptr); 51 | 52 | virtual bool visit(std::shared_ptr); 53 | 54 | virtual bool visit(std::shared_ptr); 55 | 56 | virtual bool visit(std::shared_ptr); 57 | 58 | virtual bool visit(std::shared_ptr); 59 | 60 | virtual bool visit(std::shared_ptr); 61 | 62 | virtual bool visit(std::shared_ptr); 63 | 64 | virtual bool visit(std::shared_ptr); 65 | 66 | virtual bool visit(std::shared_ptr); 67 | 68 | virtual bool visit(std::shared_ptr); 69 | 70 | virtual bool visit(std::shared_ptr); 71 | 72 | virtual bool visit(std::shared_ptr); 73 | 74 | virtual bool visit(std::shared_ptr); 75 | 76 | virtual void visit(std::shared_ptr); 77 | }; 78 | 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lib/passes/stripinfo/src/StripInfo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "../../stripinfo/include/StripInfo.h" 24 | 25 | #include "StreamIndentation.h" 26 | 27 | #include 28 | 29 | 30 | namespace Firrtlator { 31 | namespace Pass { 32 | namespace StripInfo { 33 | 34 | std::string Pass::name = "stripinfo"; 35 | std::string Pass::description = "Remove all info nodes"; 36 | 37 | REGISTER_PASS(Pass) 38 | 39 | Pass::Pass() : PassBase() { 40 | 41 | } 42 | 43 | void Pass::run(std::shared_ptr ir) { 44 | Visitor v; 45 | 46 | ir->accept(v); 47 | } 48 | 49 | Visitor::Visitor() { 50 | 51 | } 52 | 53 | Visitor::~Visitor() { 54 | 55 | } 56 | 57 | bool Visitor::visit(std::shared_ptr c) { 58 | c->setInfo(nullptr); 59 | return true; 60 | } 61 | 62 | bool Visitor::visit(std::shared_ptr m) { 63 | m->setInfo(nullptr); 64 | return true; 65 | } 66 | 67 | bool Visitor::visit(std::shared_ptr p) { 68 | p->setInfo(nullptr); 69 | return false; 70 | } 71 | 72 | bool Visitor::visit(std::shared_ptr w) { 73 | w->setInfo(nullptr); 74 | return false; 75 | } 76 | 77 | bool Visitor::visit(std::shared_ptr r) { 78 | r->setInfo(nullptr); 79 | return false; 80 | } 81 | 82 | bool Visitor::visit(std::shared_ptr i) { 83 | i->setInfo(nullptr); 84 | return false; 85 | } 86 | 87 | bool Visitor::visit(std::shared_ptr m) { 88 | m->setInfo(nullptr); 89 | return false; 90 | } 91 | bool Visitor::visit(std::shared_ptr n) { 92 | n->setInfo(nullptr); 93 | return false; 94 | } 95 | 96 | bool Visitor::visit(std::shared_ptr c) { 97 | c->setInfo(nullptr); 98 | return false; 99 | } 100 | 101 | bool Visitor::visit(std::shared_ptr i) { 102 | i->setInfo(nullptr); 103 | return false; 104 | } 105 | 106 | bool Visitor::visit(std::shared_ptr c) { 107 | c->setInfo(nullptr); 108 | return true; 109 | } 110 | 111 | bool Visitor::visit(std::shared_ptr c) { 112 | c->setInfo(nullptr); 113 | return true; 114 | } 115 | 116 | bool Visitor::visit(std::shared_ptr s) { 117 | s->setInfo(nullptr); 118 | return false; 119 | } 120 | 121 | bool Visitor::visit(std::shared_ptr p) { 122 | p->setInfo(nullptr); 123 | return false; 124 | } 125 | 126 | void Visitor::visit(std::shared_ptr e) { 127 | e->setInfo(nullptr); 128 | } 129 | 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /lib/src/Firrtlator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include 24 | #include 25 | #include "FirrtlatorFrontend.h" 26 | #include "FirrtlatorPass.h" 27 | #include "FirrtlatorBackend.h" 28 | 29 | namespace Firrtlator { 30 | 31 | class Firrtlator::impl { 32 | public: 33 | std::shared_ptr mIR; 34 | }; 35 | 36 | Firrtlator::Firrtlator() : pimpl(new impl()) {} 37 | 38 | Firrtlator::~Firrtlator() {} 39 | 40 | std::vector Firrtlator::getFrontends() { 41 | return Frontend::Registry::getDescriptors(); 42 | } 43 | 44 | std::string Firrtlator::getFrontend(std::string type) { 45 | auto desc = Frontend::Registry::getDescriptors(); 46 | 47 | for (auto f : desc) { 48 | if (std::find(f.filetypes.begin(), f.filetypes.end(), type) 49 | != f.filetypes.end()) { 50 | return f.name; 51 | } 52 | } 53 | 54 | throw std::runtime_error("Cannot find backend for: " + type); 55 | } 56 | 57 | bool Firrtlator::parse(std::string::const_iterator begin, 58 | std::string::const_iterator end, std::string type) { 59 | 60 | std::shared_ptr frontend; 61 | frontend = Frontend::Registry::create(type); 62 | 63 | if (!frontend->parseString(begin, end)) 64 | return false; 65 | pimpl->mIR = frontend->getIR(); 66 | 67 | return true; 68 | } 69 | 70 | bool Firrtlator::parseFile(std::string filename, std::string type) { 71 | std::ifstream in(filename, std::ios_base::in); 72 | if (!in) { 73 | // TODO: log 74 | return false; 75 | } 76 | std::string str((std::istreambuf_iterator(in)), 77 | std::istreambuf_iterator()); 78 | 79 | return parse(str.begin(), str.end(), type); 80 | } 81 | 82 | bool Firrtlator::parseString(std::string content, std::string type) { 83 | return parse(content.begin(), content.end(), type); 84 | 85 | } 86 | 87 | void Firrtlator::elaborate() { 88 | // Nothing for now 89 | } 90 | 91 | std::vector Firrtlator::getPasses() { 92 | return Pass::Registry::getDescriptors(); 93 | } 94 | 95 | 96 | void Firrtlator::pass(std::string id) { 97 | std::shared_ptr p = Pass::Registry::create(id); 98 | p->run(pimpl->mIR); 99 | } 100 | 101 | void Firrtlator::generate(std::string filename, std::string type) { 102 | std::shared_ptr backend; 103 | 104 | std::fstream fs; 105 | fs.open (filename, std::fstream::out); 106 | 107 | backend = Backend::Registry::create(type, fs); 108 | backend->generate(pimpl->mIR); 109 | 110 | fs.close(); 111 | } 112 | 113 | std::vector Firrtlator::getBackends() { 114 | return Backend::Registry::getDescriptors(); 115 | } 116 | 117 | std::string Firrtlator::getBackend(std::string type) { 118 | auto desc = Backend::Registry::getDescriptors(); 119 | 120 | for (auto b : desc) { 121 | if (std::find(b.filetypes.begin(), b.filetypes.end(), type) 122 | != b.filetypes.end()) { 123 | return b.name; 124 | } 125 | } 126 | 127 | throw std::runtime_error("Cannot find backend for: " + type); 128 | } 129 | 130 | 131 | } 132 | -------------------------------------------------------------------------------- /lib/src/Visitor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Stefan Wallentowitz 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include "Visitor.h" 24 | 25 | namespace Firrtlator { 26 | 27 | Visitor::~Visitor() { 28 | 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /m4/.gitignore: -------------------------------------------------------------------------------- 1 | libtool.m4 2 | ltoptions.m4 3 | ltsugar.m4 4 | ltversion.m4 5 | lt~obsolete.m4 6 | -------------------------------------------------------------------------------- /m4/ax_cxx_compile_stdcxx.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for baseline language coverage in the compiler for the specified 12 | # version of the C++ standard. If necessary, add switches to CXX and 13 | # CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) 14 | # or '14' (for the C++14 standard). 15 | # 16 | # The second argument, if specified, indicates whether you insist on an 17 | # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. 18 | # -std=c++11). If neither is specified, you get whatever works, with 19 | # preference for an extended mode. 20 | # 21 | # The third argument, if specified 'mandatory' or if left unspecified, 22 | # indicates that baseline support for the specified C++ standard is 23 | # required and that the macro should error out if no mode with that 24 | # support is found. If specified 'optional', then configuration proceeds 25 | # regardless, after defining HAVE_CXX${VERSION} if and only if a 26 | # supporting mode is found. 27 | # 28 | # LICENSE 29 | # 30 | # Copyright (c) 2008 Benjamin Kosnik 31 | # Copyright (c) 2012 Zack Weinberg 32 | # Copyright (c) 2013 Roy Stogner 33 | # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov 34 | # Copyright (c) 2015 Paul Norman 35 | # Copyright (c) 2015 Moritz Klammler 36 | # 37 | # Copying and distribution of this file, with or without modification, are 38 | # permitted in any medium without royalty provided the copyright notice 39 | # and this notice are preserved. This file is offered as-is, without any 40 | # warranty. 41 | 42 | #serial 4 43 | 44 | dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro 45 | dnl (serial version number 13). 46 | 47 | AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl 48 | m4_if([$1], [11], [], 49 | [$1], [14], [], 50 | [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])], 51 | [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl 52 | m4_if([$2], [], [], 53 | [$2], [ext], [], 54 | [$2], [noext], [], 55 | [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl 56 | m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], 57 | [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], 58 | [$3], [optional], [ax_cxx_compile_cxx$1_required=false], 59 | [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) 60 | AC_LANG_PUSH([C++])dnl 61 | ac_success=no 62 | AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, 63 | ax_cv_cxx_compile_cxx$1, 64 | [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 65 | [ax_cv_cxx_compile_cxx$1=yes], 66 | [ax_cv_cxx_compile_cxx$1=no])]) 67 | if test x$ax_cv_cxx_compile_cxx$1 = xyes; then 68 | ac_success=yes 69 | fi 70 | 71 | m4_if([$2], [noext], [], [dnl 72 | if test x$ac_success = xno; then 73 | for switch in -std=gnu++$1 -std=gnu++0x; do 74 | cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 75 | AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 76 | $cachevar, 77 | [ac_save_CXX="$CXX" 78 | CXX="$CXX $switch" 79 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 80 | [eval $cachevar=yes], 81 | [eval $cachevar=no]) 82 | CXX="$ac_save_CXX"]) 83 | if eval test x\$$cachevar = xyes; then 84 | CXX="$CXX $switch" 85 | if test -n "$CXXCPP" ; then 86 | CXXCPP="$CXXCPP $switch" 87 | fi 88 | ac_success=yes 89 | break 90 | fi 91 | done 92 | fi]) 93 | 94 | m4_if([$2], [ext], [], [dnl 95 | if test x$ac_success = xno; then 96 | dnl HP's aCC needs +std=c++11 according to: 97 | dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf 98 | dnl Cray's crayCC needs "-h std=c++11" 99 | for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do 100 | cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 101 | AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 102 | $cachevar, 103 | [ac_save_CXX="$CXX" 104 | CXX="$CXX $switch" 105 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 106 | [eval $cachevar=yes], 107 | [eval $cachevar=no]) 108 | CXX="$ac_save_CXX"]) 109 | if eval test x\$$cachevar = xyes; then 110 | CXX="$CXX $switch" 111 | if test -n "$CXXCPP" ; then 112 | CXXCPP="$CXXCPP $switch" 113 | fi 114 | ac_success=yes 115 | break 116 | fi 117 | done 118 | fi]) 119 | AC_LANG_POP([C++]) 120 | if test x$ax_cxx_compile_cxx$1_required = xtrue; then 121 | if test x$ac_success = xno; then 122 | AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) 123 | fi 124 | fi 125 | if test x$ac_success = xno; then 126 | HAVE_CXX$1=0 127 | AC_MSG_NOTICE([No compiler with C++$1 support was found]) 128 | else 129 | HAVE_CXX$1=1 130 | AC_DEFINE(HAVE_CXX$1,1, 131 | [define if the compiler supports basic C++$1 syntax]) 132 | fi 133 | AC_SUBST(HAVE_CXX$1) 134 | ]) 135 | 136 | 137 | dnl Test body for checking C++11 support 138 | 139 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], 140 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 141 | ) 142 | 143 | 144 | dnl Test body for checking C++14 support 145 | 146 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], 147 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 148 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 149 | ) 150 | 151 | 152 | dnl Tests for new features in C++11 153 | 154 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ 155 | 156 | // If the compiler admits that it is not ready for C++11, why torture it? 157 | // Hopefully, this will speed up the test. 158 | 159 | #ifndef __cplusplus 160 | 161 | #error "This is not a C++ compiler" 162 | 163 | #elif __cplusplus < 201103L 164 | 165 | #error "This is not a C++11 compiler" 166 | 167 | #else 168 | 169 | namespace cxx11 170 | { 171 | 172 | namespace test_static_assert 173 | { 174 | 175 | template 176 | struct check 177 | { 178 | static_assert(sizeof(int) <= sizeof(T), "not big enough"); 179 | }; 180 | 181 | } 182 | 183 | namespace test_final_override 184 | { 185 | 186 | struct Base 187 | { 188 | virtual void f() {} 189 | }; 190 | 191 | struct Derived : public Base 192 | { 193 | virtual void f() override {} 194 | }; 195 | 196 | } 197 | 198 | namespace test_double_right_angle_brackets 199 | { 200 | 201 | template < typename T > 202 | struct check {}; 203 | 204 | typedef check single_type; 205 | typedef check> double_type; 206 | typedef check>> triple_type; 207 | typedef check>>> quadruple_type; 208 | 209 | } 210 | 211 | namespace test_decltype 212 | { 213 | 214 | int 215 | f() 216 | { 217 | int a = 1; 218 | decltype(a) b = 2; 219 | return a + b; 220 | } 221 | 222 | } 223 | 224 | namespace test_type_deduction 225 | { 226 | 227 | template < typename T1, typename T2 > 228 | struct is_same 229 | { 230 | static const bool value = false; 231 | }; 232 | 233 | template < typename T > 234 | struct is_same 235 | { 236 | static const bool value = true; 237 | }; 238 | 239 | template < typename T1, typename T2 > 240 | auto 241 | add(T1 a1, T2 a2) -> decltype(a1 + a2) 242 | { 243 | return a1 + a2; 244 | } 245 | 246 | int 247 | test(const int c, volatile int v) 248 | { 249 | static_assert(is_same::value == true, ""); 250 | static_assert(is_same::value == false, ""); 251 | static_assert(is_same::value == false, ""); 252 | auto ac = c; 253 | auto av = v; 254 | auto sumi = ac + av + 'x'; 255 | auto sumf = ac + av + 1.0; 256 | static_assert(is_same::value == true, ""); 257 | static_assert(is_same::value == true, ""); 258 | static_assert(is_same::value == true, ""); 259 | static_assert(is_same::value == false, ""); 260 | static_assert(is_same::value == true, ""); 261 | return (sumf > 0.0) ? sumi : add(c, v); 262 | } 263 | 264 | } 265 | 266 | namespace test_noexcept 267 | { 268 | 269 | int f() { return 0; } 270 | int g() noexcept { return 0; } 271 | 272 | static_assert(noexcept(f()) == false, ""); 273 | static_assert(noexcept(g()) == true, ""); 274 | 275 | } 276 | 277 | namespace test_constexpr 278 | { 279 | 280 | template < typename CharT > 281 | unsigned long constexpr 282 | strlen_c_r(const CharT *const s, const unsigned long acc) noexcept 283 | { 284 | return *s ? strlen_c_r(s + 1, acc + 1) : acc; 285 | } 286 | 287 | template < typename CharT > 288 | unsigned long constexpr 289 | strlen_c(const CharT *const s) noexcept 290 | { 291 | return strlen_c_r(s, 0UL); 292 | } 293 | 294 | static_assert(strlen_c("") == 0UL, ""); 295 | static_assert(strlen_c("1") == 1UL, ""); 296 | static_assert(strlen_c("example") == 7UL, ""); 297 | static_assert(strlen_c("another\0example") == 7UL, ""); 298 | 299 | } 300 | 301 | namespace test_rvalue_references 302 | { 303 | 304 | template < int N > 305 | struct answer 306 | { 307 | static constexpr int value = N; 308 | }; 309 | 310 | answer<1> f(int&) { return answer<1>(); } 311 | answer<2> f(const int&) { return answer<2>(); } 312 | answer<3> f(int&&) { return answer<3>(); } 313 | 314 | void 315 | test() 316 | { 317 | int i = 0; 318 | const int c = 0; 319 | static_assert(decltype(f(i))::value == 1, ""); 320 | static_assert(decltype(f(c))::value == 2, ""); 321 | static_assert(decltype(f(0))::value == 3, ""); 322 | } 323 | 324 | } 325 | 326 | namespace test_uniform_initialization 327 | { 328 | 329 | struct test 330 | { 331 | static const int zero {}; 332 | static const int one {1}; 333 | }; 334 | 335 | static_assert(test::zero == 0, ""); 336 | static_assert(test::one == 1, ""); 337 | 338 | } 339 | 340 | namespace test_lambdas 341 | { 342 | 343 | void 344 | test1() 345 | { 346 | auto lambda1 = [](){}; 347 | auto lambda2 = lambda1; 348 | lambda1(); 349 | lambda2(); 350 | } 351 | 352 | int 353 | test2() 354 | { 355 | auto a = [](int i, int j){ return i + j; }(1, 2); 356 | auto b = []() -> int { return '0'; }(); 357 | auto c = [=](){ return a + b; }(); 358 | auto d = [&](){ return c; }(); 359 | auto e = [a, &b](int x) mutable { 360 | const auto identity = [](int y){ return y; }; 361 | for (auto i = 0; i < a; ++i) 362 | a += b--; 363 | return x + identity(a + b); 364 | }(0); 365 | return a + b + c + d + e; 366 | } 367 | 368 | int 369 | test3() 370 | { 371 | const auto nullary = [](){ return 0; }; 372 | const auto unary = [](int x){ return x; }; 373 | using nullary_t = decltype(nullary); 374 | using unary_t = decltype(unary); 375 | const auto higher1st = [](nullary_t f){ return f(); }; 376 | const auto higher2nd = [unary](nullary_t f1){ 377 | return [unary, f1](unary_t f2){ return f2(unary(f1())); }; 378 | }; 379 | return higher1st(nullary) + higher2nd(nullary)(unary); 380 | } 381 | 382 | } 383 | 384 | namespace test_variadic_templates 385 | { 386 | 387 | template 388 | struct sum; 389 | 390 | template 391 | struct sum 392 | { 393 | static constexpr auto value = N0 + sum::value; 394 | }; 395 | 396 | template <> 397 | struct sum<> 398 | { 399 | static constexpr auto value = 0; 400 | }; 401 | 402 | static_assert(sum<>::value == 0, ""); 403 | static_assert(sum<1>::value == 1, ""); 404 | static_assert(sum<23>::value == 23, ""); 405 | static_assert(sum<1, 2>::value == 3, ""); 406 | static_assert(sum<5, 5, 11>::value == 21, ""); 407 | static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); 408 | 409 | } 410 | 411 | // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae 412 | // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function 413 | // because of this. 414 | namespace test_template_alias_sfinae 415 | { 416 | 417 | struct foo {}; 418 | 419 | template 420 | using member = typename T::member_type; 421 | 422 | template 423 | void func(...) {} 424 | 425 | template 426 | void func(member*) {} 427 | 428 | void test(); 429 | 430 | void test() { func(0); } 431 | 432 | } 433 | 434 | } // namespace cxx11 435 | 436 | #endif // __cplusplus >= 201103L 437 | 438 | ]]) 439 | 440 | 441 | dnl Tests for new features in C++14 442 | 443 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ 444 | 445 | // If the compiler admits that it is not ready for C++14, why torture it? 446 | // Hopefully, this will speed up the test. 447 | 448 | #ifndef __cplusplus 449 | 450 | #error "This is not a C++ compiler" 451 | 452 | #elif __cplusplus < 201402L 453 | 454 | #error "This is not a C++14 compiler" 455 | 456 | #else 457 | 458 | namespace cxx14 459 | { 460 | 461 | namespace test_polymorphic_lambdas 462 | { 463 | 464 | int 465 | test() 466 | { 467 | const auto lambda = [](auto&&... args){ 468 | const auto istiny = [](auto x){ 469 | return (sizeof(x) == 1UL) ? 1 : 0; 470 | }; 471 | const int aretiny[] = { istiny(args)... }; 472 | return aretiny[0]; 473 | }; 474 | return lambda(1, 1L, 1.0f, '1'); 475 | } 476 | 477 | } 478 | 479 | namespace test_binary_literals 480 | { 481 | 482 | constexpr auto ivii = 0b0000000000101010; 483 | static_assert(ivii == 42, "wrong value"); 484 | 485 | } 486 | 487 | namespace test_generalized_constexpr 488 | { 489 | 490 | template < typename CharT > 491 | constexpr unsigned long 492 | strlen_c(const CharT *const s) noexcept 493 | { 494 | auto length = 0UL; 495 | for (auto p = s; *p; ++p) 496 | ++length; 497 | return length; 498 | } 499 | 500 | static_assert(strlen_c("") == 0UL, ""); 501 | static_assert(strlen_c("x") == 1UL, ""); 502 | static_assert(strlen_c("test") == 4UL, ""); 503 | static_assert(strlen_c("another\0test") == 7UL, ""); 504 | 505 | } 506 | 507 | namespace test_lambda_init_capture 508 | { 509 | 510 | int 511 | test() 512 | { 513 | auto x = 0; 514 | const auto lambda1 = [a = x](int b){ return a + b; }; 515 | const auto lambda2 = [a = lambda1(x)](){ return a; }; 516 | return lambda2(); 517 | } 518 | 519 | } 520 | 521 | namespace test_digit_seperators 522 | { 523 | 524 | constexpr auto ten_million = 100'000'000; 525 | static_assert(ten_million == 100000000, ""); 526 | 527 | } 528 | 529 | namespace test_return_type_deduction 530 | { 531 | 532 | auto f(int& x) { return x; } 533 | decltype(auto) g(int& x) { return x; } 534 | 535 | template < typename T1, typename T2 > 536 | struct is_same 537 | { 538 | static constexpr auto value = false; 539 | }; 540 | 541 | template < typename T > 542 | struct is_same 543 | { 544 | static constexpr auto value = true; 545 | }; 546 | 547 | int 548 | test() 549 | { 550 | auto x = 0; 551 | static_assert(is_same::value, ""); 552 | static_assert(is_same::value, ""); 553 | return x; 554 | } 555 | 556 | } 557 | 558 | } // namespace cxx14 559 | 560 | #endif // __cplusplus >= 201402L 561 | 562 | ]]) 563 | -------------------------------------------------------------------------------- /m4/ax_cxx_compile_stdcxx_11.m4: -------------------------------------------------------------------------------- 1 | # ============================================================================ 2 | # http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html 3 | # ============================================================================ 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CXX_COMPILE_STDCXX_11([ext|noext], [mandatory|optional]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for baseline language coverage in the compiler for the C++11 12 | # standard; if necessary, add switches to CXX and CXXCPP to enable 13 | # support. 14 | # 15 | # This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX 16 | # macro with the version set to C++11. The two optional arguments are 17 | # forwarded literally as the second and third argument respectively. 18 | # Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for 19 | # more information. If you want to use this macro, you also need to 20 | # download the ax_cxx_compile_stdcxx.m4 file. 21 | # 22 | # LICENSE 23 | # 24 | # Copyright (c) 2008 Benjamin Kosnik 25 | # Copyright (c) 2012 Zack Weinberg 26 | # Copyright (c) 2013 Roy Stogner 27 | # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov 28 | # Copyright (c) 2015 Paul Norman 29 | # Copyright (c) 2015 Moritz Klammler 30 | # 31 | # Copying and distribution of this file, with or without modification, are 32 | # permitted in any medium without royalty provided the copyright notice 33 | # and this notice are preserved. This file is offered as-is, without any 34 | # warranty. 35 | 36 | #serial 17 37 | 38 | AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) 39 | AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [AX_CXX_COMPILE_STDCXX([11], [$1], [$2])]) 40 | 41 | --------------------------------------------------------------------------------