├── README ├── penelope ├── .gitignore ├── Makefile ├── README ├── penelope-fixes.diff └── penelope.cc └── vhdl ├── .gitignore ├── Makefile ├── README ├── def.h ├── preproc.cc ├── test ├── LED_VHDL.ast-expected ├── LED_VHDL.vhd ├── entity001.ast-expected ├── entity001.vhd ├── entity002.ast-expected ├── entity002.vhd └── runtests ├── vhdl_frontend.cc ├── vhdl_frontend.h ├── vhdl_lexer.l └── vhdl_parser.y /README: -------------------------------------------------------------------------------- 1 | This repository contains various Yosys plugins. 2 | See README files in the individual directories for details. 3 | -------------------------------------------------------------------------------- /penelope/.gitignore: -------------------------------------------------------------------------------- 1 | bhoessen-penelope-08b284b059bf.zip 2 | bhoessen-penelope-08b284b059bf 3 | penelope.so 4 | *.o 5 | *.d 6 | -------------------------------------------------------------------------------- /penelope/Makefile: -------------------------------------------------------------------------------- 1 | 2 | PENELOPE_VER = 08b284b059bf 3 | PENELOPE_OBJS = Asserts.o Cooperation.o INIParser.o Options.o Semaphore.o Solver.o System.o 4 | 5 | penelope.so: $(PENELOPE_OBJS) 6 | $(shell yosys-config --cxx --cxxflags -O0 -I bhoessen-penelope-$(PENELOPE_VER)/include --ldflags -o penelope.so -shared penelope.cc $(PENELOPE_OBJS) --ldlibs) 7 | 8 | bhoessen-penelope-$(PENELOPE_VER): bhoessen-penelope-$(PENELOPE_VER).zip 9 | unzip bhoessen-penelope-$(PENELOPE_VER).zip 10 | cd bhoessen-penelope-$(PENELOPE_VER) && patch -p1 < ../penelope-fixes.diff 11 | 12 | bhoessen-penelope-$(PENELOPE_VER).zip: 13 | wget -O bhoessen-penelope-$(PENELOPE_VER).zip.part https://bitbucket.org/bhoessen/penelope/get/$(PENELOPE_VER).zip 14 | mv bhoessen-penelope-$(PENELOPE_VER).zip.part bhoessen-penelope-$(PENELOPE_VER).zip 15 | 16 | $(PENELOPE_OBJS): bhoessen-penelope-$(PENELOPE_VER) 17 | $(shell yosys-config --cxx -c -o $@ --cxxflags -O0 -I bhoessen-penelope-$(PENELOPE_VER)/include bhoessen-penelope-$(PENELOPE_VER)/src/$(basename $@).cpp) 18 | 19 | clean: 20 | rm -rfv *.d *.o bhoessen-penelope-$(PENELOPE_VER) penelope.so 21 | 22 | -include *.d 23 | 24 | -------------------------------------------------------------------------------- /penelope/README: -------------------------------------------------------------------------------- 1 | 2 | Yosys Plugin: PeneLoPe SAT Solver 3 | ================================= 4 | 5 | Warning: This is work under construction. 6 | 7 | Compile: 8 | -------- 9 | 10 | - Make sure you have "yosys-config" in the $PATH 11 | 12 | - Run "make" in this directory 13 | 14 | Usage: 15 | ------ 16 | 17 | Run yosys with "-m penelope.so" to use the PeneLoPe SAT Solver. 18 | 19 | -------------------------------------------------------------------------------- /penelope/penelope-fixes.diff: -------------------------------------------------------------------------------- 1 | diff -ru bhoessen-penelope-08b284b059bf.orig/include/penelope/core/SolverTypes.h bhoessen-penelope-08b284b059bf/include/penelope/core/SolverTypes.h 2 | --- bhoessen-penelope-08b284b059bf.orig/include/penelope/core/SolverTypes.h 2015-02-21 12:28:37.573342252 +0100 3 | +++ bhoessen-penelope-08b284b059bf/include/penelope/core/SolverTypes.h 2015-02-21 12:29:48.197344050 +0100 4 | @@ -51,7 +51,7 @@ 5 | int x; 6 | 7 | // Use this as a constructor: 8 | - friend Lit mkLit(Var var, bool sign = false); 9 | + friend Lit mkLit(Var var, bool sign); 10 | 11 | bool operator == (Lit p) const { return x == p.x; } 12 | bool operator != (Lit p) const { return x != p.x; } 13 | @@ -59,7 +59,7 @@ 14 | }; 15 | 16 | 17 | -inline Lit mkLit (Var var, bool sign) { Lit p; p.x = var + var + (int)sign; return p; } 18 | +inline Lit mkLit (Var var, bool sign = false) { Lit p; p.x = var + var + (int)sign; return p; } 19 | inline Lit operator ~(Lit p) { Lit q; q.x = p.x ^ 1; return q; } 20 | inline Lit operator ^(Lit p, bool b) { Lit q; q.x = p.x ^ (unsigned int)b; return q; } 21 | inline bool sign (Lit p) { return p.x & 1; } 22 | diff -ru bhoessen-penelope-08b284b059bf.orig/include/penelope/utils/Alg.h bhoessen-penelope-08b284b059bf/include/penelope/utils/Alg.h 23 | --- bhoessen-penelope-08b284b059bf.orig/include/penelope/utils/Alg.h 2015-02-21 12:52:12.649378289 +0100 24 | +++ bhoessen-penelope-08b284b059bf/include/penelope/utils/Alg.h 2015-02-21 12:52:37.261378916 +0100 25 | @@ -36,7 +36,7 @@ 26 | static inline void remove(V& ts, const T& t) 27 | { 28 | int j = 0; 29 | - for (; j < ts.size() && ts[j] != t; j++); 30 | + for (; j < ts.size() && ts[j] != t; j++) { } 31 | ASSERT_TRUE(j < ts.size()); 32 | for (; j < ts.size()-1; j++) ts[j] = ts[j+1]; 33 | ts.pop(); 34 | diff -ru bhoessen-penelope-08b284b059bf.orig/include/penelope/utils/Map.h bhoessen-penelope-08b284b059bf/include/penelope/utils/Map.h 35 | --- bhoessen-penelope-08b284b059bf.orig/include/penelope/utils/Map.h 2015-02-21 12:52:12.649378289 +0100 36 | +++ bhoessen-penelope-08b284b059bf/include/penelope/utils/Map.h 2015-02-21 12:53:41.001380539 +0100 37 | @@ -66,8 +66,8 @@ 38 | int size; 39 | 40 | // Don't allow copying (error prone): 41 | - Map& operator = (Map& other) { ASSERT_TRUE(0); } 42 | - Map (Map& other) { ASSERT_TRUE(0); } 43 | + Map& operator = (Map&) { ASSERT_TRUE(0); } 44 | + Map (Map&) { ASSERT_TRUE(0); } 45 | 46 | bool checkCap(int new_size) const { return new_size > cap; } 47 | 48 | @@ -155,7 +155,7 @@ 49 | ASSERT_TRUE(table != NULL); 50 | vec& ps = table[index(k)]; 51 | int j = 0; 52 | - for (; j < ps.size() && !equals(ps[j].key, k); j++); 53 | + for (; j < ps.size() && !equals(ps[j].key, k); j++) { } 54 | ASSERT_TRUE(j < ps.size()); 55 | ps[j] = ps.last(); 56 | ps.pop(); 57 | diff -ru bhoessen-penelope-08b284b059bf.orig/include/penelope/utils/Vec.h bhoessen-penelope-08b284b059bf/include/penelope/utils/Vec.h 58 | --- bhoessen-penelope-08b284b059bf.orig/include/penelope/utils/Vec.h 2015-02-21 12:52:12.649378289 +0100 59 | +++ bhoessen-penelope-08b284b059bf/include/penelope/utils/Vec.h 2015-02-21 12:53:59.489381010 +0100 60 | @@ -41,8 +41,8 @@ 61 | int cap; 62 | 63 | // Don't allow copying (error prone): 64 | - vec& operator = (vec& other) { ASSERT_TRUE(0); return *this; } 65 | - vec (vec& other) { ASSERT_TRUE(0); } 66 | + vec& operator = (vec&) { ASSERT_TRUE(0); return *this; } 67 | + vec (vec&) { ASSERT_TRUE(0); } 68 | 69 | // Helpers for calculating next capacity: 70 | static inline int imax (int x, int y) { int mask = (y-x) >> (sizeof(int)*8-1); return (x&mask) + (y&(~mask)); } 71 | -------------------------------------------------------------------------------- /penelope/penelope.cc: -------------------------------------------------------------------------------- 1 | // This is free and unencumbered software released into the public domain. 2 | // 3 | // Anyone is free to copy, modify, publish, use, compile, sell, or 4 | // distribute this software, either in source code form or as a compiled 5 | // binary, for any purpose, commercial or non-commercial, and by any 6 | // means. 7 | 8 | #include "kernel/satgen.h" 9 | #include "penelope/core/Cooperation.h" 10 | #include "penelope/core/Solver.h" 11 | 12 | using namespace penelope; 13 | USING_YOSYS_NAMESPACE 14 | PRIVATE_NAMESPACE_BEGIN 15 | 16 | const int nbThreads = 1; 17 | const int limitExport = 10; 18 | 19 | struct ezPenelope : public ezSAT 20 | { 21 | private: 22 | INIParser parser; 23 | Cooperation* coop; 24 | std::vector satVars; 25 | bool foundContradiction; 26 | 27 | public: 28 | ezPenelope() : parser("penelope_config.ini") 29 | { 30 | coop = nullptr; 31 | foundContradiction = false; 32 | parser.parse(); 33 | } 34 | 35 | virtual ~ezPenelope() 36 | { 37 | if (coop) 38 | delete coop; 39 | } 40 | 41 | virtual void clear() 42 | { 43 | if (coop) 44 | delete coop; 45 | coop = nullptr; 46 | foundContradiction = false; 47 | } 48 | 49 | virtual bool solver(const std::vector &modelExpressions, std::vector &modelValues, const std::vector &assumptions) 50 | { 51 | preSolverCallback(); 52 | 53 | if (0) { 54 | contradiction: 55 | if (coop) 56 | delete coop; 57 | coop = nullptr; 58 | foundContradiction = true; 59 | return false; 60 | } 61 | 62 | if (foundContradiction) { 63 | consumeCnf(); 64 | return false; 65 | } 66 | 67 | std::vector < int >extraClauses, modelIdx; 68 | 69 | for (auto id:assumptions) 70 | extraClauses.push_back(bind(id)); 71 | for (auto id:modelExpressions) 72 | modelIdx.push_back(bind(id)); 73 | 74 | if (coop == nullptr) { 75 | log_assert(nbThreads == 1); 76 | coop = new Cooperation(nbThreads, limitExport); 77 | for (int i = 0; i < nbThreads; i++) { 78 | coop->solvers[0].initialize(coop, i, parser); 79 | coop->solvers[0].verbosity = 0; 80 | coop->solvers[0].deterministic_mode = 0; 81 | } 82 | } 83 | 84 | std::vector> cnf; 85 | consumeCnf(cnf); 86 | 87 | while (int(satVars.size()) < numCnfVariables()) 88 | satVars.push_back(coop->solvers[0].newVar()); 89 | 90 | for (auto &clause : cnf) { 91 | penelope::vec ps; 92 | for (auto idx : clause) { 93 | if (idx > 0) 94 | ps.push(mkLit(satVars.at(idx - 1))); 95 | else 96 | ps.push(mkLit(satVars.at(-idx - 1), true)); 97 | } 98 | if (!coop->solvers[0].addClause(ps)) 99 | goto contradiction; 100 | } 101 | 102 | if (cnf.size() > 0 && !coop->solvers[0].simplify(coop)) 103 | goto contradiction; 104 | 105 | penelope::vec assumps; 106 | 107 | for (auto idx : extraClauses) { 108 | if (idx > 0) 109 | assumps.push(mkLit(satVars.at(idx-1))); 110 | else 111 | assumps.push(mkLit(satVars.at(-idx-1), true)); 112 | } 113 | 114 | bool foundSolution = coop->solvers[0].solve(assumps, coop); 115 | 116 | if (!foundSolution) 117 | return false; 118 | 119 | modelValues.clear(); 120 | modelValues.resize(modelIdx.size()); 121 | 122 | for (size_t i = 0; i < modelIdx.size(); i++) { 123 | int idx = modelIdx[i]; 124 | bool refvalue = true; 125 | 126 | if (idx < 0) 127 | idx = -idx, refvalue = false; 128 | 129 | lbool value = coop->solvers[0].modelValue(satVars.at(idx - 1)); 130 | modelValues[i] = (value == lbool(refvalue)); 131 | } 132 | 133 | return true; 134 | } 135 | }; 136 | 137 | struct PenelopeSatSolver : public SatSolver { 138 | PenelopeSatSolver() : SatSolver("penelope") { 139 | yosys_satsolver = this; 140 | } 141 | virtual ezSAT *create() YS_OVERRIDE { 142 | return new ezPenelope(); 143 | } 144 | } PenelopeSatSolver; 145 | 146 | PRIVATE_NAMESPACE_END 147 | -------------------------------------------------------------------------------- /vhdl/.gitignore: -------------------------------------------------------------------------------- 1 | *.d 2 | *.o 3 | vhdl.so 4 | vhdl_lexer.cc 5 | vhdl_parser.output 6 | vhdl_parser.tab.cc 7 | vhdl_parser.tab.h 8 | -------------------------------------------------------------------------------- /vhdl/Makefile: -------------------------------------------------------------------------------- 1 | CXX = $(shell yosys-config --cxx) 2 | CXXFLAGS = $(shell yosys-config --cxxflags) 3 | LDFLAGS = $(shell yosys-config --ldflags) 4 | LDLIBS = $(shell yosys-config --ldlibs) 5 | PLUGINS_DIR = $(shell yosys-config --datdir)/plugins 6 | 7 | OBJS = vhdl_parser.tab.o vhdl_lexer.o vhdl_frontend.o preproc.o 8 | 9 | vhdl.so: vhdl_parser.tab.o vhdl_lexer.o vhdl_frontend.o preproc.o 10 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) 11 | $(MAKE) test 12 | 13 | vhdl_parser.tab.cc: vhdl_parser.y def.h 14 | bison -d -r all -b vhdl_parser $< 15 | mv vhdl_parser.tab.c vhdl_parser.tab.cc 16 | 17 | vhdl_parser.tab.h: vhdl_parser.tab.cc 18 | 19 | vhdl_lexer.cc: vhdl_lexer.l def.h vhdl_parser.tab.h 20 | flex -d -i -o $@ $< 21 | 22 | .PHONY: test 23 | test: 24 | cd test; ./runtests 25 | 26 | .PHONY: install 27 | install: vhdl.so 28 | mkdir -p $(PLUGINS_DIR) 29 | cp vhdl.so $(PLUGINS_DIR)/vhdl.so 30 | 31 | clean: 32 | rm -f *.d *.o vhdl.so vhdl_lexer.cc vhdl_parser.output vhdl_parser.tab.cc vhdl_parser.tab.h 33 | 34 | -------------------------------------------------------------------------------- /vhdl/README: -------------------------------------------------------------------------------- 1 | 2 | VHDL front-end plugin, upstream for this plugin: 3 | https://github.com/SebKuzminsky/yosys-plugins/tree/master/vhdl 4 | 5 | Based on vhdl2vl. See https://github.com/ldoolitt/vhd2vl/tree/master/examples 6 | for more example VHDL files. 7 | 8 | -------------------------------------------------------------------------------- /vhdl/def.h: -------------------------------------------------------------------------------- 1 | /* 2 | vhd2vl v2.3 3 | VHDL to Verilog RTL translator 4 | Copyright (C) 2001 Vincenzo Liguori - Ocean Logic Pty Ltd - http://www.ocean-logic.com 5 | Modifications (C) 2006 Mark Gonzales - PMC Sierra Inc 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License along 18 | with this program; if not, write to the Free Software Foundation, Inc., 19 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 | */ 21 | 22 | #ifndef __def_h 23 | #define __def_h 24 | 25 | #define MAXINDENT 36 26 | #define MAXEDGES 1000 /* maximum number of @(edge) processes supported in a source file */ 27 | typedef struct signal { 28 | char *name; /* Signal name */ 29 | int reg; /* Verilog reg */ 30 | struct signal *next; 31 | } signal; 32 | 33 | typedef struct nlist { 34 | char *name; /* Name */ 35 | struct nlist *next; 36 | } nlist; 37 | 38 | typedef struct slist { 39 | unsigned int type; 40 | struct slist *slst; 41 | union { 42 | struct slist *sl; /* type 0 */ 43 | char *txt; /* type 1 */ 44 | char **ptxt; /* type 3!*/ 45 | int val; /* type 2,4 */ 46 | } data; 47 | } slist; 48 | 49 | enum vrangeType {tSCALAR, tSUBSCRIPT, tVRANGE}; 50 | typedef struct vrange { 51 | /* int hi, lo; */ 52 | enum vrangeType vtype; 53 | struct slist *nhi, *nlo; /* MAG index is a simple expression */ 54 | slist *size_expr; /* expression that calculates size (width) of this vrange */ 55 | int sizeval; /* precalculated size value */ 56 | struct slist *xhi, *xlo; /* array index range; 0,0 for normal scalars */ 57 | } vrange; 58 | 59 | typedef struct slval { 60 | slist *sl; 61 | int val; /* Signal size */ 62 | vrange *range; /* Signal size */ 63 | } slval; 64 | 65 | typedef enum { 66 | EXPDATA_TYPE_NONE = 0, 67 | EXPDATA_TYPE_AST, 68 | EXPDATA_TYPE_BITS, 69 | EXPDATA_TYPE_INT, 70 | EXPDATA_TYPE_FLOAT, 71 | 72 | EXPDATA_TYPE_TILDE = '~', 73 | EXPDATA_TYPE_ADD = '+', 74 | EXPDATA_TYPE_SUBTRACT = '-', 75 | EXPDATA_TYPE_MULT = '*', 76 | EXPDATA_TYPE_DIV = '/', 77 | EXPDATA_TYPE_MOD = '%', 78 | EXPDATA_TYPE_AND = '&', 79 | EXPDATA_TYPE_CARET = '^', 80 | EXPDATA_TYPE_OR = '|', 81 | 82 | EXPDATA_TYPE_C = 'c', 83 | EXPDATA_TYPE_M = 'm', 84 | EXPDATA_TYPE_N = 'n', 85 | EXPDATA_TYPE_OTHERS = 'o', 86 | EXPDATA_TYPE_P = 'p', 87 | EXPDATA_TYPE_TERMINAL = 't', 88 | } expdata_type_t; 89 | 90 | typedef struct expdata { 91 | expdata_type_t op; 92 | bool is_others; 93 | int value; /* only set for simple_expr */ 94 | slist *sl; 95 | std::vector bits; 96 | Yosys::AST::AstNode *node; 97 | } expdata; 98 | 99 | typedef struct sglist { 100 | char *name; /* Signal name */ 101 | char *type; /* Reg or wire */ 102 | const char *dir; /* input, output, inout */ 103 | vrange *range; /* Signal size */ 104 | struct sglist *next; 105 | } sglist; 106 | 107 | typedef struct blknamelist { 108 | char *name; /* Optional name */ 109 | struct blknamelist *next; 110 | } blknamelist; 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /vhdl/preproc.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * yosys -- Yosys Open SYnthesis Suite 3 | * 4 | * Copyright (C) 2012 Clifford Wolf 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | * 18 | * --- 19 | * 20 | * The VHDL frontend. 21 | * 22 | * This frontend is using the AST frontend library (see frontends/ast/). 23 | * Thus this frontend does not generate RTLIL code directly but creates an 24 | * AST directly from the VHDL parse tree and then passes this AST to 25 | * the AST frontend library. 26 | * 27 | * --- 28 | * 29 | * Ad-hoc implementation of a VHDL preprocessor. The directives `define, 30 | * `include, `ifdef, `ifndef, `else and `endif are handled here. All other 31 | * directives are handled by the lexer (see lexer.l). 32 | * 33 | */ 34 | 35 | #include "vhdl_frontend.h" 36 | #include "kernel/log.h" 37 | #include 38 | #include 39 | #include 40 | 41 | YOSYS_NAMESPACE_BEGIN 42 | using namespace VHDL_FRONTEND; 43 | 44 | static std::list output_code; 45 | static std::list input_buffer; 46 | static size_t input_buffer_charp; 47 | 48 | static void return_char(char ch) 49 | { 50 | if (input_buffer_charp == 0) 51 | input_buffer.push_front(std::string() + ch); 52 | else 53 | input_buffer.front()[--input_buffer_charp] = ch; 54 | } 55 | 56 | static void insert_input(std::string str) 57 | { 58 | if (input_buffer_charp != 0) { 59 | input_buffer.front() = input_buffer.front().substr(input_buffer_charp); 60 | input_buffer_charp = 0; 61 | } 62 | input_buffer.push_front(str); 63 | } 64 | 65 | static char next_char() 66 | { 67 | if (input_buffer.empty()) 68 | return 0; 69 | 70 | log_assert(input_buffer_charp <= input_buffer.front().size()); 71 | if (input_buffer_charp == input_buffer.front().size()) { 72 | input_buffer_charp = 0; 73 | input_buffer.pop_front(); 74 | return next_char(); 75 | } 76 | 77 | char ch = input_buffer.front()[input_buffer_charp++]; 78 | return ch == '\r' ? next_char() : ch; 79 | } 80 | 81 | static std::string skip_spaces() 82 | { 83 | std::string spaces; 84 | while (1) { 85 | char ch = next_char(); 86 | if (ch == 0) 87 | break; 88 | if (ch != ' ' && ch != '\t') { 89 | return_char(ch); 90 | break; 91 | } 92 | spaces += ch; 93 | } 94 | return spaces; 95 | } 96 | 97 | static std::string next_token(bool pass_newline = false) 98 | { 99 | std::string token; 100 | 101 | char ch = next_char(); 102 | if (ch == 0) 103 | return token; 104 | 105 | token += ch; 106 | if (ch == '\n') { 107 | if (pass_newline) { 108 | output_code.push_back(token); 109 | return ""; 110 | } 111 | return token; 112 | } 113 | 114 | if (ch == ' ' || ch == '\t') 115 | { 116 | while ((ch = next_char()) != 0) { 117 | if (ch != ' ' && ch != '\t') { 118 | return_char(ch); 119 | break; 120 | } 121 | token += ch; 122 | } 123 | } 124 | else if (ch == '"') 125 | { 126 | while ((ch = next_char()) != 0) { 127 | token += ch; 128 | if (ch == '"') 129 | break; 130 | if (ch == '\\') { 131 | if ((ch = next_char()) != 0) 132 | token += ch; 133 | } 134 | } 135 | if (token == "\"\"" && (ch = next_char()) != 0) { 136 | if (ch == '"') 137 | token += ch; 138 | else 139 | return_char(ch); 140 | } 141 | } 142 | else if (ch == '/') 143 | { 144 | if ((ch = next_char()) != 0) { 145 | if (ch == '/') { 146 | token += '*'; 147 | char last_ch = 0; 148 | while ((ch = next_char()) != 0) { 149 | if (ch == '\n') { 150 | return_char(ch); 151 | break; 152 | } 153 | if (last_ch != '*' || ch != '/') { 154 | token += ch; 155 | last_ch = ch; 156 | } 157 | } 158 | token += " */"; 159 | } 160 | else if (ch == '*') { 161 | token += '*'; 162 | int newline_count = 0; 163 | char last_ch = 0; 164 | while ((ch = next_char()) != 0) { 165 | if (ch == '\n') { 166 | newline_count++; 167 | token += ' '; 168 | } else 169 | token += ch; 170 | if (last_ch == '*' && ch == '/') 171 | break; 172 | last_ch = ch; 173 | } 174 | while (newline_count-- > 0) 175 | return_char('\n'); 176 | } 177 | else 178 | return_char(ch); 179 | } 180 | } 181 | else 182 | { 183 | const char *ok = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789"; 184 | if (ch == '`' || strchr(ok, ch) != NULL) 185 | while ((ch = next_char()) != 0) { 186 | if (strchr(ok, ch) == NULL) { 187 | return_char(ch); 188 | break; 189 | } 190 | token += ch; 191 | } 192 | } 193 | 194 | return token; 195 | } 196 | 197 | static void input_file(std::istream &f, std::string filename) 198 | { 199 | char buffer[513]; 200 | int rc; 201 | 202 | insert_input(""); 203 | auto it = input_buffer.begin(); 204 | 205 | input_buffer.insert(it, "`file_push \"" + filename + "\"\n"); 206 | while ((rc = readsome(f, buffer, sizeof(buffer)-1)) > 0) { 207 | buffer[rc] = 0; 208 | input_buffer.insert(it, buffer); 209 | } 210 | input_buffer.insert(it, "\n`file_pop\n"); 211 | } 212 | 213 | std::string frontend_vhdl_preproc(std::istream &f, std::string filename, const std::map pre_defines_map, const std::list include_dirs) 214 | { 215 | std::set defines_with_args; 216 | std::map defines_map(pre_defines_map); 217 | int ifdef_fail_level = 0; 218 | bool in_elseif = false; 219 | 220 | output_code.clear(); 221 | input_buffer.clear(); 222 | input_buffer_charp = 0; 223 | 224 | input_file(f, filename); 225 | defines_map["YOSYS"] = "1"; 226 | 227 | while (!input_buffer.empty()) 228 | { 229 | std::string tok = next_token(); 230 | // printf("token: >>%s<<\n", tok != "\n" ? tok.c_str() : "NEWLINE"); 231 | 232 | if (tok == "`endif") { 233 | if (ifdef_fail_level > 0) 234 | ifdef_fail_level--; 235 | if (ifdef_fail_level == 0) 236 | in_elseif = false; 237 | continue; 238 | } 239 | 240 | if (tok == "`else") { 241 | if (ifdef_fail_level == 0) 242 | ifdef_fail_level = 1; 243 | else if (ifdef_fail_level == 1 && !in_elseif) 244 | ifdef_fail_level = 0; 245 | continue; 246 | } 247 | 248 | if (tok == "`elsif") { 249 | skip_spaces(); 250 | std::string name = next_token(true); 251 | if (ifdef_fail_level == 0) 252 | ifdef_fail_level = 1, in_elseif = true; 253 | else if (ifdef_fail_level == 1 && defines_map.count(name) != 0) 254 | ifdef_fail_level = 0, in_elseif = true; 255 | continue; 256 | } 257 | 258 | if (tok == "`ifdef") { 259 | skip_spaces(); 260 | std::string name = next_token(true); 261 | if (ifdef_fail_level > 0 || defines_map.count(name) == 0) 262 | ifdef_fail_level++; 263 | continue; 264 | } 265 | 266 | if (tok == "`ifndef") { 267 | skip_spaces(); 268 | std::string name = next_token(true); 269 | if (ifdef_fail_level > 0 || defines_map.count(name) != 0) 270 | ifdef_fail_level++; 271 | continue; 272 | } 273 | 274 | if (ifdef_fail_level > 0) { 275 | if (tok == "\n") 276 | output_code.push_back(tok); 277 | continue; 278 | } 279 | 280 | if (tok == "`include") { 281 | skip_spaces(); 282 | std::string fn = next_token(true); 283 | while (1) { 284 | size_t pos = fn.find('"'); 285 | if (pos == std::string::npos) 286 | break; 287 | if (pos == 0) 288 | fn = fn.substr(1); 289 | else 290 | fn = fn.substr(0, pos) + fn.substr(pos+1); 291 | } 292 | std::ifstream ff; 293 | ff.clear(); 294 | ff.open(fn.c_str()); 295 | if (ff.fail() && fn.size() > 0 && fn[0] != '/' && filename.find('/') != std::string::npos) { 296 | // if the include file was not found, it is not given with an absolute path, and the 297 | // currently read file is given with a path, then try again relative to its directory 298 | ff.clear(); 299 | ff.open(filename.substr(0, filename.rfind('/')+1) + fn); 300 | } 301 | if (ff.fail() && fn.size() > 0 && fn[0] != '/') { 302 | // if the include file was not found and it is not given with an absolute path, then 303 | // search it in the include path 304 | for (auto incdir : include_dirs) { 305 | ff.clear(); 306 | ff.open(incdir + '/' + fn); 307 | if (!ff.fail()) break; 308 | } 309 | } 310 | if (ff.fail()) 311 | output_code.push_back("`file_notfound " + fn); 312 | else 313 | input_file(ff, fn); 314 | continue; 315 | } 316 | 317 | if (tok == "`define") { 318 | std::string name, value; 319 | std::map args; 320 | skip_spaces(); 321 | name = next_token(true); 322 | bool here_doc_mode = false; 323 | int newline_count = 0; 324 | int state = 0; 325 | if (skip_spaces() != "") 326 | state = 3; 327 | while (!tok.empty()) { 328 | tok = next_token(); 329 | if (tok == "\"\"\"") { 330 | here_doc_mode = !here_doc_mode; 331 | continue; 332 | } 333 | if (state == 0 && tok == "(") { 334 | state = 1; 335 | skip_spaces(); 336 | } else 337 | if (state == 1) { 338 | if (tok == ")") 339 | state = 2; 340 | else if (tok != ",") { 341 | int arg_idx = args.size()+1; 342 | args[tok] = arg_idx; 343 | } 344 | skip_spaces(); 345 | } else { 346 | if (state != 2) 347 | state = 3; 348 | if (tok == "\n") { 349 | if (here_doc_mode) { 350 | value += " "; 351 | newline_count++; 352 | } else { 353 | return_char('\n'); 354 | break; 355 | } 356 | } else 357 | if (tok == "\\") { 358 | char ch = next_char(); 359 | if (ch == '\n') { 360 | value += " "; 361 | newline_count++; 362 | } else { 363 | value += std::string("\\"); 364 | return_char(ch); 365 | } 366 | } else 367 | if (args.count(tok) > 0) 368 | value += stringf("`macro_%s_arg%d", name.c_str(), args.at(tok)); 369 | else 370 | value += tok; 371 | } 372 | } 373 | while (newline_count-- > 0) 374 | return_char('\n'); 375 | // printf("define: >>%s<< -> >>%s<<\n", name.c_str(), value.c_str()); 376 | defines_map[name] = value; 377 | if (state == 2) 378 | defines_with_args.insert(name); 379 | else 380 | defines_with_args.erase(name); 381 | continue; 382 | } 383 | 384 | if (tok == "`undef") { 385 | std::string name; 386 | skip_spaces(); 387 | name = next_token(true); 388 | // printf("undef: >>%s<<\n", name.c_str()); 389 | defines_map.erase(name); 390 | defines_with_args.erase(name); 391 | continue; 392 | } 393 | 394 | if (tok == "`timescale") { 395 | skip_spaces(); 396 | while (!tok.empty() && tok != "\n") 397 | tok = next_token(true); 398 | if (tok == "\n") 399 | return_char('\n'); 400 | continue; 401 | } 402 | 403 | if (tok.size() > 1 && tok[0] == '`' && defines_map.count(tok.substr(1)) > 0) { 404 | std::string name = tok.substr(1); 405 | // printf("expand: >>%s<< -> >>%s<<\n", name.c_str(), defines_map[name].c_str()); 406 | std::string skipped_spaces = skip_spaces(); 407 | tok = next_token(false); 408 | if (tok == "(" && defines_with_args.count(name) > 0) { 409 | int level = 1; 410 | std::vector args; 411 | args.push_back(std::string()); 412 | while (1) 413 | { 414 | tok = next_token(true); 415 | if (tok == ")" || tok == "}" || tok == "]") 416 | level--; 417 | if (level == 0) 418 | break; 419 | if (level == 1 && tok == ",") 420 | args.push_back(std::string()); 421 | else 422 | args.back() += tok; 423 | if (tok == "(" || tok == "{" || tok == "[") 424 | level++; 425 | } 426 | for (int i = 0; i < GetSize(args); i++) 427 | defines_map[stringf("macro_%s_arg%d", name.c_str(), i+1)] = args[i]; 428 | } else { 429 | insert_input(tok); 430 | insert_input(skipped_spaces); 431 | } 432 | insert_input(defines_map[name]); 433 | continue; 434 | } 435 | 436 | output_code.push_back(tok); 437 | } 438 | 439 | std::string output; 440 | for (auto &str : output_code) 441 | output += str; 442 | 443 | output_code.clear(); 444 | input_buffer.clear(); 445 | input_buffer_charp = 0; 446 | 447 | return output; 448 | } 449 | 450 | YOSYS_NAMESPACE_END 451 | 452 | -------------------------------------------------------------------------------- /vhdl/test/LED_VHDL.ast-expected: -------------------------------------------------------------------------------- 1 | AST_MODULE [0xPointer] str='\LED_VHDL' 2 | AST_WIRE [0xPointer] str='\clk' input port=1 3 | AST_WIRE [0xPointer] str='\LED1' output port=2 4 | AST_WIRE [0xPointer] str='\LED2' output port=3 5 | AST_WIRE [0xPointer] str='\LED3' output port=4 6 | AST_WIRE [0xPointer] str='\LED4' output port=5 7 | AST_WIRE [0xPointer] str='\LED5' output port=6 8 | AST_WIRE [0xPointer] str='\LED6' output port=7 9 | AST_WIRE [0xPointer] str='\LED7' output port=8 10 | AST_WIRE [0xPointer] str='\LED8' output port=9 11 | AST_WIRE [0xPointer] str='\div_cntr1' 12 | AST_RANGE [0xPointer] 13 | AST_CONSTANT [0xPointer] bits='00000000000000000000000000001111'(32) range=[31:0] int=15 14 | AST_CONSTANT [0xPointer] bits='00000000000000000000000000000000'(32) range=[31:0] 15 | AST_INITIAL [0xPointer] 16 | AST_ASSIGN_LE [0xPointer] 17 | AST_IDENTIFIER [0xPointer] str='\div_cntr1' 18 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 19 | AST_WIRE [0xPointer] str='\div_cntr2' 20 | AST_RANGE [0xPointer] 21 | AST_CONSTANT [0xPointer] bits='00000000000000000000000000000110'(32) range=[31:0] int=6 22 | AST_CONSTANT [0xPointer] bits='00000000000000000000000000000000'(32) range=[31:0] 23 | AST_INITIAL [0xPointer] 24 | AST_ASSIGN_LE [0xPointer] 25 | AST_IDENTIFIER [0xPointer] str='\div_cntr2' 26 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 27 | AST_WIRE [0xPointer] str='\dec_cntr' 28 | AST_INITIAL [0xPointer] 29 | AST_ASSIGN_LE [0xPointer] 30 | AST_IDENTIFIER [0xPointer] str='\dec_cntr' 31 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 32 | AST_WIRE [0xPointer] str='\half_sec_pulse' 33 | AST_INITIAL [0xPointer] 34 | AST_ASSIGN_LE [0xPointer] 35 | AST_IDENTIFIER [0xPointer] str='\half_sec_pulse' 36 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 37 | AST_ALWAYS [0xPointer] 38 | AST_POSEDGE [0xPointer] 39 | AST_IDENTIFIER [0xPointer] str='\clk' 40 | AST_BLOCK [0xPointer] 41 | AST_ASSIGN_LE [0xPointer] 42 | AST_IDENTIFIER [0xPointer] str='\div_cntr1' 43 | AST_ADD [0xPointer] 44 | AST_IDENTIFIER [0xPointer] str='\div_cntr1' 45 | AST_CONSTANT [0xPointer] bits='00000000000000000000000000000001'(32) range=[31:0] int=1 46 | AST_CASE [0xPointer] 47 | AST_REDUCE_BOOL [0xPointer] 48 | AST_EQ [0xPointer] 49 | AST_IDENTIFIER [0xPointer] str='\div_cntr1' 50 | AST_CONSTANT [0xPointer] bits='00000000000000000000000000000000'(32) range=[31:0] 51 | AST_COND [0xPointer] 52 | AST_CONSTANT [0xPointer] bits='00000000000000000000000000000001'(32) range=[31:0] int=1 53 | AST_BLOCK [0xPointer] 54 | AST_CASE [0xPointer] 55 | AST_REDUCE_BOOL [0xPointer] 56 | AST_EQ [0xPointer] 57 | AST_IDENTIFIER [0xPointer] str='\div_cntr2' 58 | AST_CONSTANT [0xPointer] bits='00000000000000000000000001011011'(32) range=[31:0] int=91 59 | AST_COND [0xPointer] 60 | AST_CONSTANT [0xPointer] bits='00000000000000000000000000000001'(32) range=[31:0] int=1 61 | AST_BLOCK [0xPointer] 62 | AST_ASSIGN_LE [0xPointer] 63 | AST_IDENTIFIER [0xPointer] str='\div_cntr2' 64 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 65 | AST_ASSIGN_LE [0xPointer] 66 | AST_IDENTIFIER [0xPointer] str='\half_sec_pulse' 67 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 68 | AST_COND [0xPointer] 69 | AST_DEFAULT [0xPointer] 70 | AST_BLOCK [0xPointer] 71 | AST_ASSIGN_LE [0xPointer] 72 | AST_IDENTIFIER [0xPointer] str='\div_cntr2' 73 | AST_ADD [0xPointer] 74 | AST_IDENTIFIER [0xPointer] str='\div_cntr2' 75 | AST_CONSTANT [0xPointer] bits='00000000000000000000000000000001'(32) range=[31:0] int=1 76 | AST_COND [0xPointer] 77 | AST_DEFAULT [0xPointer] 78 | AST_BLOCK [0xPointer] 79 | AST_ASSIGN_LE [0xPointer] 80 | AST_IDENTIFIER [0xPointer] str='\half_sec_pulse' 81 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 82 | AST_CASE [0xPointer] 83 | AST_REDUCE_BOOL [0xPointer] 84 | AST_EQ [0xPointer] 85 | AST_IDENTIFIER [0xPointer] str='\half_sec_pulse' 86 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 87 | AST_COND [0xPointer] 88 | AST_CONSTANT [0xPointer] bits='00000000000000000000000000000001'(32) range=[31:0] int=1 89 | AST_BLOCK [0xPointer] 90 | AST_ASSIGN_LE [0xPointer] 91 | AST_IDENTIFIER [0xPointer] str='\dec_cntr' 92 | AST_BIT_NOT [0xPointer] 93 | AST_IDENTIFIER [0xPointer] str='\dec_cntr' 94 | AST_ASSIGN [0xPointer] 95 | AST_IDENTIFIER [0xPointer] str='\LED1' 96 | AST_TERNARY [0xPointer] 97 | AST_EQ [0xPointer] 98 | AST_IDENTIFIER [0xPointer] str='\dec_cntr' 99 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 100 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 101 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 102 | AST_ASSIGN [0xPointer] 103 | AST_IDENTIFIER [0xPointer] str='\LED2' 104 | AST_TERNARY [0xPointer] 105 | AST_EQ [0xPointer] 106 | AST_IDENTIFIER [0xPointer] str='\dec_cntr' 107 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 108 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 109 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 110 | AST_ASSIGN [0xPointer] 111 | AST_IDENTIFIER [0xPointer] str='\LED3' 112 | AST_TERNARY [0xPointer] 113 | AST_EQ [0xPointer] 114 | AST_IDENTIFIER [0xPointer] str='\dec_cntr' 115 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 116 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 117 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 118 | AST_ASSIGN [0xPointer] 119 | AST_IDENTIFIER [0xPointer] str='\LED4' 120 | AST_TERNARY [0xPointer] 121 | AST_EQ [0xPointer] 122 | AST_IDENTIFIER [0xPointer] str='\dec_cntr' 123 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 124 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 125 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 126 | AST_ASSIGN [0xPointer] 127 | AST_IDENTIFIER [0xPointer] str='\LED5' 128 | AST_TERNARY [0xPointer] 129 | AST_EQ [0xPointer] 130 | AST_IDENTIFIER [0xPointer] str='\dec_cntr' 131 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 132 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 133 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 134 | AST_ASSIGN [0xPointer] 135 | AST_IDENTIFIER [0xPointer] str='\LED6' 136 | AST_TERNARY [0xPointer] 137 | AST_EQ [0xPointer] 138 | AST_IDENTIFIER [0xPointer] str='\dec_cntr' 139 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 140 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 141 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 142 | AST_ASSIGN [0xPointer] 143 | AST_IDENTIFIER [0xPointer] str='\LED7' 144 | AST_TERNARY [0xPointer] 145 | AST_EQ [0xPointer] 146 | AST_IDENTIFIER [0xPointer] str='\dec_cntr' 147 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 148 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 149 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 150 | AST_ASSIGN [0xPointer] 151 | AST_IDENTIFIER [0xPointer] str='\LED8' 152 | AST_TERNARY [0xPointer] 153 | AST_EQ [0xPointer] 154 | AST_IDENTIFIER [0xPointer] str='\dec_cntr' 155 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 156 | AST_CONSTANT [0xPointer] bits='1'(1) range=[0:0] int=1 157 | AST_CONSTANT [0xPointer] bits='0'(1) range=[0:0] 158 | -------------------------------------------------------------------------------- /vhdl/test/LED_VHDL.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: Axelsys 3 | -- Engineer: Greg Miller 4 | -- 5 | -- Create Date: 10:08:13 04/30/2013 6 | -- Design Name: LED LED 7 | -- Module Name: LED_VHDL 8 | -- Project Name: iCE40 Evaluation Kit 9 | -- Target Devices: iCE40-HX8K_CT256 10 | -- Tool versions: 11 | -- Description: 12 | -- LEDs, D1 through D8 will blink on for 1/2 second and off for 1/2 second. 13 | -- Clock is operating at 12MHz. 14 | -- 15 | -- Dependencies: 16 | -- 17 | -- Revision: 18 | -- Revision 0.01 - File Created 19 | -- Additional Comments: 20 | -- 21 | ---------------------------------------------------------------------------------- 22 | library IEEE; 23 | use IEEE.STD_LOGIC_1164.ALL; 24 | use IEEE.std_logic_unsigned.all; 25 | use IEEE.NUMERIC_STD.ALL; 26 | 27 | entity LED_VHDL is 28 | Port ( clk : in STD_LOGIC; 29 | LED1 : out STD_LOGIC; 30 | LED2 : out STD_LOGIC; 31 | LED3 : out STD_LOGIC; 32 | LED4 : out STD_LOGIC; 33 | LED5 : out STD_LOGIC; 34 | LED6 : out STD_LOGIC; 35 | LED7 : out STD_LOGIC; 36 | LED8 : out STD_LOGIC); 37 | end LED_VHDL; 38 | 39 | architecture Behavioral of LED_VHDL is 40 | 41 | signal div_cntr1 : std_logic_vector(15 downto 0) := (others => '0'); 42 | signal div_cntr2 : std_logic_vector(6 downto 0) := (others => '0'); 43 | signal dec_cntr : std_logic := '0'; 44 | signal half_sec_pulse : std_logic := '0'; 45 | 46 | begin 47 | 48 | process(clk) 49 | begin 50 | if rising_edge(clk) then 51 | div_cntr1 <= div_cntr1 + 1; 52 | if div_cntr1 = 0 then 53 | if div_cntr2 = 91 then 54 | div_cntr2 <= (others => '0'); 55 | half_sec_pulse <= '1'; 56 | else 57 | div_cntr2 <= div_cntr2 + 1; 58 | end if; 59 | else 60 | half_sec_pulse <= '0'; 61 | end if; 62 | 63 | if (half_sec_pulse = '1') then 64 | dec_cntr <= not dec_cntr; 65 | end if; 66 | 67 | end if; 68 | end process; 69 | 70 | --LED decording 71 | LED1 <= '1' when (dec_cntr = '1') else '0'; 72 | LED2 <= '1' when (dec_cntr = '1') else '0'; 73 | LED3 <= '1' when (dec_cntr = '1') else '0'; 74 | LED4 <= '1' when (dec_cntr = '1') else '0'; 75 | LED5 <= '1' when (dec_cntr = '1') else '0'; 76 | LED6 <= '1' when (dec_cntr = '1') else '0'; 77 | LED7 <= '1' when (dec_cntr = '1') else '0'; 78 | LED8 <= '1' when (dec_cntr = '1') else '0'; 79 | 80 | end Behavioral; 81 | 82 | -------------------------------------------------------------------------------- /vhdl/test/entity001.ast-expected: -------------------------------------------------------------------------------- 1 | AST_MODULE [0xPointer] str='\e1' 2 | AST_WIRE [0xPointer] str='\a' input port=1 3 | AST_WIRE [0xPointer] str='\b' output port=2 4 | -------------------------------------------------------------------------------- /vhdl/test/entity001.vhd: -------------------------------------------------------------------------------- 1 | entity e1 is 2 | Port ( 3 | a: in STD_LOGIC; 4 | b: out STD_LOGIC 5 | ); 6 | end e1; 7 | -------------------------------------------------------------------------------- /vhdl/test/entity002.ast-expected: -------------------------------------------------------------------------------- 1 | AST_MODULE [0xPointer] str='\e1' 2 | AST_WIRE [0xPointer] str='\a' input port=1 3 | AST_WIRE [0xPointer] str='\b' output port=2 4 | AST_WIRE [0xPointer] str='\c' output port=3 5 | AST_WIRE [0xPointer] str='\d' output port=4 6 | AST_WIRE [0xPointer] str='\e' input port=5 7 | AST_WIRE [0xPointer] str='\f' input port=6 8 | -------------------------------------------------------------------------------- /vhdl/test/entity002.vhd: -------------------------------------------------------------------------------- 1 | entity e1 is 2 | Port ( 3 | a: in STD_LOGIC; 4 | b,c,d: out STD_LOGIC; 5 | e,f: in STD_LOGIC 6 | ); 7 | end e1; 8 | -------------------------------------------------------------------------------- /vhdl/test/runtests: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cleanup_ast() { 4 | AST=$1 5 | PRE_REGEX='^Dumping .*AST before simplification:$' 6 | POST_REGEX='^--- END OF AST DUMP ---$' 7 | cat ${AST} | egrep -A 1000000 "${PRE_REGEX}" | egrep -B 1000000 "${POST_REGEX}" | egrep -v "(${PRE_REGEX})|(${POST_REGEX})" > ${AST}.cleaned 8 | mv ${AST}.cleaned ${AST} 9 | sed -i -re 's/\[(0x[0-9a-f]+)]/[0xPointer]/' ${AST} 10 | } 11 | 12 | 13 | RETVAL=0 14 | 15 | for V in *.vhd; do 16 | BASENAME=$(basename $V .vhd) 17 | echo test: ${BASENAME} 18 | AST=${BASENAME}.ast 19 | yosys -m ../vhdl.so -p "read_vhdl -dump_ast1 $V" > ${AST} 20 | cleanup_ast ${AST} 21 | if ! diff -u ${AST}-expected ${AST}; then 22 | echo "error: ${AST} does not match expected" 23 | RETVAL=1 24 | else 25 | rm ${AST} 26 | fi 27 | done 28 | 29 | if [ ${RETVAL} == 0 ]; then 30 | echo "all tests pass" 31 | fi 32 | 33 | exit ${RETVAL} 34 | 35 | -------------------------------------------------------------------------------- /vhdl/vhdl_frontend.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * yosys -- Yosys Open SYnthesis Suite 3 | * 4 | * Copyright (C) 2012 Clifford Wolf 5 | * Copyright (C) 2016 Sebastian Kuzminsky 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | * 19 | * --- 20 | * 21 | * The VHDL frontend. 22 | * 23 | * This frontend is using the AST frontend library (see frontends/ast/). 24 | * Thus this frontend does not generate RTLIL code directly but creates an 25 | * AST directly from the VHDL parse tree and then passes this AST to 26 | * the AST frontend library. 27 | * 28 | */ 29 | 30 | #include "vhdl_frontend.h" 31 | #include "kernel/yosys.h" 32 | #include "libs/sha1/sha1.h" 33 | #include 34 | 35 | YOSYS_NAMESPACE_BEGIN 36 | using namespace VHDL_FRONTEND; 37 | 38 | // use the VHDL bison/flex parser to generate an AST and use AST::process() to convert it to RTLIL 39 | 40 | static std::vector vhdl_defaults; 41 | static std::list> vhdl_defaults_stack; 42 | 43 | static void error_on_dpi_function(AST::AstNode *node) 44 | { 45 | if (node->type == AST::AST_DPI_FUNCTION) 46 | log_error("Found DPI function %s at %s:%d.\n", node->str.c_str(), node->filename.c_str(), node->linenum); 47 | for (auto child : node->children) 48 | error_on_dpi_function(child); 49 | } 50 | 51 | struct VHDLFrontend : public Frontend { 52 | VHDLFrontend() : Frontend("vhdl", "read modules from VHDL file") { } 53 | virtual void help() 54 | { 55 | // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 56 | log("\n"); 57 | log(" read_vhdl [options] [filename]\n"); 58 | log("\n"); 59 | log("Load modules from a VHDL file to the current design.\n"); 60 | log("\n"); 61 | log(" -dump_ast1\n"); 62 | log(" dump abstract syntax tree (before simplification)\n"); 63 | log("\n"); 64 | log(" -dump_ast2\n"); 65 | log(" dump abstract syntax tree (after simplification)\n"); 66 | log("\n"); 67 | log(" -no_dump_ptr\n"); 68 | log(" do not include hex memory addresses in dump (easier to diff dumps)\n"); 69 | log("\n"); 70 | log(" -dump_vlog1\n"); 71 | log(" dump ast as Verilog code (before simplification)\n"); 72 | log("\n"); 73 | log(" -dump_vlog2\n"); 74 | log(" dump ast as Verilog code (after simplification)\n"); 75 | log("\n"); 76 | log(" -dump_vhdl\n"); 77 | log(" dump ast as VHDL code (after simplification)\n"); 78 | log("\n"); 79 | log(" -yydebug\n"); 80 | log(" enable parser debug output\n"); 81 | log("\n"); 82 | log(" -nolatches\n"); 83 | log(" usually latches are synthesized into logic loops\n"); 84 | log(" this option prohibits this and sets the output to 'x'\n"); 85 | log(" in what would be the latches hold condition\n"); 86 | log("\n"); 87 | log(" this behavior can also be achieved by setting the\n"); 88 | log(" 'nolatches' attribute on the respective module or\n"); 89 | log(" always block.\n"); 90 | log("\n"); 91 | log(" -nomem2reg\n"); 92 | log(" under certain conditions memories are converted to registers\n"); 93 | log(" early during simplification to ensure correct handling of\n"); 94 | log(" complex corner cases. this option disables this behavior.\n"); 95 | log("\n"); 96 | log(" this can also be achieved by setting the 'nomem2reg'\n"); 97 | log(" attribute on the respective module or register.\n"); 98 | log("\n"); 99 | log(" This is potentially dangerous. Usually the front-end has good\n"); 100 | log(" reasons for converting an array to a list of registers.\n"); 101 | log(" Prohibiting this step will likely result in incorrect synthesis\n"); 102 | log(" results.\n"); 103 | log("\n"); 104 | log(" -mem2reg\n"); 105 | log(" always convert memories to registers. this can also be\n"); 106 | log(" achieved by setting the 'mem2reg' attribute on the respective\n"); 107 | log(" module or register.\n"); 108 | log("\n"); 109 | log(" -nomeminit\n"); 110 | log(" do not infer $meminit cells and instead convert initialized\n"); 111 | log(" memories to registers directly in the front-end.\n"); 112 | log("\n"); 113 | log(" -ppdump\n"); 114 | log(" dump VHDL code after pre-processor\n"); 115 | log("\n"); 116 | log(" -nopp\n"); 117 | log(" do not run the pre-processor\n"); 118 | log("\n"); 119 | log(" -nodpi\n"); 120 | log(" disable DPI-C support\n"); 121 | log("\n"); 122 | log(" -noblackbox\n"); 123 | log(" do not automatically add a (* blackbox *) attribute to an\n"); 124 | log(" empty module.\n"); 125 | log("\n"); 126 | log(" -lib\n"); 127 | log(" only create empty blackbox modules. This implies -DBLACKBOX.\n"); 128 | log("\n"); 129 | log(" -nowb\n"); 130 | log(" delete (* whitebox *) and (* lib_whitebox *) attributes from\n"); 131 | log(" all modules.\n"); 132 | log("\n"); 133 | log(" -noopt\n"); 134 | log(" don't perform basic optimizations (such as const folding) in the\n"); 135 | log(" high-level front-end.\n"); 136 | log("\n"); 137 | log(" -icells\n"); 138 | log(" interpret cell types starting with '$' as internal cell types\n"); 139 | log("\n"); 140 | log(" -pwires\n"); 141 | log(" add a wire for each module parameter\n"); 142 | log("\n"); 143 | log(" -nooverwrite\n"); 144 | log(" ignore re-definitions of modules. (the default behavior is to\n"); 145 | log(" create an error message if the existing module is not a black box\n"); 146 | log(" module, and overwrite the existing module otherwise.)\n"); 147 | log("\n"); 148 | log(" -overwrite\n"); 149 | log(" overwrite existing modules with the same name\n"); 150 | log("\n"); 151 | log(" -defer\n"); 152 | log(" only read the abstract syntax tree and defer actual compilation\n"); 153 | log(" to a later 'hierarchy' command. Useful in cases where the default\n"); 154 | log(" parameters of modules yield invalid or not synthesizable code.\n"); 155 | log("\n"); 156 | log(" -noautowire\n"); 157 | log(" make the default of `default_nettype be \"none\" instead of \"wire\".\n"); 158 | log("\n"); 159 | log(" -setattr \n"); 160 | log(" set the specified attribute (to the value 1) on all loaded modules\n"); 161 | log("\n"); 162 | log(" -Dname[=definition]\n"); 163 | log(" define the preprocessor symbol 'name' and set its optional value\n"); 164 | log(" 'definition'\n"); 165 | log("\n"); 166 | log(" -Idir\n"); 167 | log(" add 'dir' to the directories which are used when searching include\n"); 168 | log(" files\n"); 169 | log("\n"); 170 | log("The command 'vhdl_defaults' can be used to register default options for\n"); 171 | log("subsequent calls to 'read_vhdl'.\n"); 172 | log("\n"); 173 | log("Note that the VHDL frontend does a pretty good job of processing valid\n"); 174 | log("VHDL input, but has not very good error reporting. It generally is\n"); 175 | log("recommended to use a simulator for checking the syntax of the code, rather\n"); 176 | log("than to rely on read_vhdl for that.\n"); 177 | log("\n"); 178 | } 179 | virtual void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) 180 | { 181 | bool flag_dump_ast1 = false; 182 | bool flag_dump_ast2 = false; 183 | bool flag_no_dump_ptr = false; 184 | bool flag_dump_vlog1 = false; 185 | bool flag_dump_vlog2 = false; 186 | bool flag_nolatches = false; 187 | bool flag_nomeminit = false; 188 | bool flag_nomem2reg = false; 189 | bool flag_mem2reg = false; 190 | bool flag_ppdump = false; 191 | bool flag_nopp = false; 192 | bool flag_nodpi = false; 193 | bool flag_noblackbox = false; 194 | bool flag_lib = false; 195 | bool flag_nowb = false; 196 | bool flag_noopt = false; 197 | bool flag_icells = false; 198 | bool flag_pwires = false; 199 | bool flag_nooverwrite = false; 200 | bool flag_overwrite = false; 201 | bool flag_defer = false; 202 | bool flag_dump_rtlil = false; 203 | std::map defines_map; 204 | std::list include_dirs; 205 | std::list attributes; 206 | 207 | frontend_vhdl_yydebug = false; 208 | frontend_vhdl_yy_flex_debug = false; 209 | default_nettype_wire = true; 210 | 211 | log_header(design,"Executing VHDL frontend.\n"); 212 | 213 | args.insert(args.begin()+1, vhdl_defaults.begin(), vhdl_defaults.end()); 214 | 215 | size_t argidx; 216 | for (argidx = 1; argidx < args.size(); argidx++) { 217 | std::string arg = args[argidx]; 218 | if (arg == "-dump_ast1") { 219 | flag_dump_ast1 = true; 220 | continue; 221 | } 222 | if (arg == "-dump_ast2") { 223 | flag_dump_ast2 = true; 224 | continue; 225 | } 226 | if (arg == "-no_dump_ptr") { 227 | flag_no_dump_ptr = true; 228 | continue; 229 | } 230 | if (arg == "-dump_vlog1") { 231 | flag_dump_vlog1 = true; 232 | continue; 233 | } 234 | if (arg == "-dump_vlog2") { 235 | flag_dump_vlog2 = true; 236 | continue; 237 | } 238 | if (arg == "-yydebug") { 239 | frontend_vhdl_yydebug = true; 240 | frontend_vhdl_yy_flex_debug = true; 241 | continue; 242 | } 243 | if (arg == "-nolatches") { 244 | flag_nolatches = true; 245 | continue; 246 | } 247 | if (arg == "-nomeminit") { 248 | flag_nomeminit = true; 249 | continue; 250 | } 251 | if (arg == "-nomem2reg") { 252 | flag_nomem2reg = true; 253 | continue; 254 | } 255 | if (arg == "-mem2reg") { 256 | flag_mem2reg = true; 257 | continue; 258 | } 259 | if (arg == "-ppdump") { 260 | flag_ppdump = true; 261 | continue; 262 | } 263 | if (arg == "-nopp") { 264 | flag_nopp = true; 265 | continue; 266 | } 267 | if (arg == "-nodpi") { 268 | flag_nodpi = true; 269 | continue; 270 | } 271 | if (arg == "-noblackbox") { 272 | flag_noblackbox = true; 273 | continue; 274 | } 275 | if (arg == "-lib") { 276 | flag_lib = true; 277 | defines_map["BLACKBOX"] = string(); 278 | continue; 279 | } 280 | if (arg == "-nowb") { 281 | flag_nowb = true; 282 | continue; 283 | } 284 | if (arg == "-noopt") { 285 | flag_noopt = true; 286 | continue; 287 | } 288 | if (arg == "-icells") { 289 | flag_icells = true; 290 | continue; 291 | } 292 | if (arg == "-pwires") { 293 | flag_pwires = true; 294 | continue; 295 | } 296 | if (arg == "-ignore_redef" || arg == "-nooverwrite") { 297 | flag_nooverwrite = true; 298 | continue; 299 | } 300 | if (arg == "-overwrite") { 301 | flag_overwrite = true; 302 | continue; 303 | } 304 | if (arg == "-defer") { 305 | flag_defer = true; 306 | continue; 307 | } 308 | if (arg == "-noautowire") { 309 | default_nettype_wire = false; 310 | continue; 311 | } 312 | if (arg == "-setattr" && argidx+1 < args.size()) { 313 | attributes.push_back(RTLIL::escape_id(args[++argidx])); 314 | continue; 315 | } 316 | if (arg == "-D" && argidx+1 < args.size()) { 317 | std::string name = args[++argidx], value; 318 | size_t equal = name.find('=', 2); 319 | if (equal != std::string::npos) { 320 | value = arg.substr(equal+1); 321 | name = arg.substr(0, equal); 322 | } 323 | defines_map[name] = value; 324 | continue; 325 | } 326 | if (arg.compare(0, 2, "-D") == 0) { 327 | size_t equal = arg.find('=', 2); 328 | std::string name = arg.substr(2, equal-2); 329 | std::string value; 330 | if (equal != std::string::npos) 331 | value = arg.substr(equal+1); 332 | defines_map[name] = value; 333 | continue; 334 | } 335 | if (arg == "-I" && argidx+1 < args.size()) { 336 | include_dirs.push_back(args[++argidx]); 337 | continue; 338 | } 339 | if (arg.compare(0, 2, "-I") == 0) { 340 | include_dirs.push_back(arg.substr(2)); 341 | continue; 342 | } 343 | break; 344 | } 345 | extra_args(f, filename, args, argidx); 346 | 347 | log("Parsing VHDL input from `%s' to AST representation.\n", filename.c_str()); 348 | 349 | AST::current_filename = filename; 350 | AST::set_line_num = &frontend_vhdl_yyset_lineno; 351 | AST::get_line_num = &frontend_vhdl_yyget_lineno; 352 | 353 | current_ast = new AST::AstNode(AST::AST_DESIGN); 354 | 355 | lexin = f; 356 | std::string code_after_preproc; 357 | 358 | if (!flag_nopp) { 359 | code_after_preproc = frontend_vhdl_preproc(*f, filename, defines_map, include_dirs); 360 | if (flag_ppdump) 361 | log("-- vhdl code after preprocessor --\n%s-- END OF DUMP --\n", code_after_preproc.c_str()); 362 | lexin = new std::istringstream(code_after_preproc); 363 | } 364 | 365 | frontend_vhdl_yyset_lineno(1); 366 | frontend_vhdl_yyrestart(NULL); 367 | frontend_vhdl_yyparse(); 368 | frontend_vhdl_yylex_destroy(); 369 | 370 | for (auto &child : current_ast->children) { 371 | if (child->type == AST::AST_MODULE) 372 | for (auto &attr : attributes) 373 | if (child->attributes.count(attr) == 0) 374 | child->attributes[attr] = AST::AstNode::mkconst_int(1, false); 375 | } 376 | 377 | if (flag_nodpi) 378 | error_on_dpi_function(current_ast); 379 | 380 | AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire); 381 | 382 | if (!flag_nopp) 383 | delete lexin; 384 | 385 | delete current_ast; 386 | current_ast = NULL; 387 | 388 | log("Successfully finished VHDL frontend.\n"); 389 | } 390 | } VHDLFrontend; 391 | 392 | struct VHDLDefaults : public Pass { 393 | VHDLDefaults() : Pass("vhdl_defaults", "set default options for read_vhdl") { } 394 | virtual void help() 395 | { 396 | // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 397 | log("\n"); 398 | log(" vhdl_defaults -add [options]\n"); 399 | log("\n"); 400 | log("Add the specified options to the list of default options to read_vhdl.\n"); 401 | log("\n"); 402 | log("\n"); 403 | log(" vhdl_defaults -clear"); 404 | log("\n"); 405 | log("Clear the list of VHDL default options.\n"); 406 | log("\n"); 407 | log("\n"); 408 | log(" vhdl_defaults -push"); 409 | log(" vhdl_defaults -pop"); 410 | log("\n"); 411 | log("Push or pop the list of default options to a stack. Note that -push does\n"); 412 | log("not imply -clear.\n"); 413 | log("\n"); 414 | } 415 | virtual void execute(std::vector args, RTLIL::Design*) 416 | { 417 | if (args.size() == 0) 418 | cmd_error(args, 1, "Missing argument."); 419 | 420 | if (args[1] == "-add") { 421 | vhdl_defaults.insert(vhdl_defaults.end(), args.begin()+2, args.end()); 422 | return; 423 | } 424 | 425 | if (args.size() != 2) 426 | cmd_error(args, 2, "Extra argument."); 427 | 428 | if (args[1] == "-clear") { 429 | vhdl_defaults.clear(); 430 | return; 431 | } 432 | 433 | if (args[1] == "-push") { 434 | vhdl_defaults_stack.push_back(vhdl_defaults); 435 | return; 436 | } 437 | 438 | if (args[1] == "-pop") { 439 | if (vhdl_defaults_stack.empty()) { 440 | vhdl_defaults.clear(); 441 | } else { 442 | vhdl_defaults.swap(vhdl_defaults_stack.back()); 443 | vhdl_defaults_stack.pop_back(); 444 | } 445 | return; 446 | } 447 | } 448 | } VHDLDefaults; 449 | 450 | YOSYS_NAMESPACE_END 451 | 452 | // the yyerror function used by bison to report parser errors 453 | void frontend_vhdl_yyerror(char const *fmt, ...) 454 | { 455 | va_list ap; 456 | char buffer[1024]; 457 | char *p = buffer; 458 | p += snprintf(p, buffer + sizeof(buffer) - p, "Parser error in line %s:%d: ", 459 | YOSYS_NAMESPACE_PREFIX AST::current_filename.c_str(), frontend_vhdl_yyget_lineno()); 460 | va_start(ap, fmt); 461 | p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap); 462 | va_end(ap); 463 | p += snprintf(p, buffer + sizeof(buffer) - p, "\n"); 464 | YOSYS_NAMESPACE_PREFIX log_error("%s", buffer); 465 | exit(1); 466 | } 467 | -------------------------------------------------------------------------------- /vhdl/vhdl_frontend.h: -------------------------------------------------------------------------------- 1 | /* 2 | * yosys -- Yosys Open SYnthesis Suite 3 | * 4 | * Copyright (C) 2012 Clifford Wolf 5 | * Copyright (C) 2016 Sebastian Kuzminsky 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | * 19 | * --- 20 | * 21 | * The VHDL frontend. 22 | * 23 | * This frontend is using the AST frontend library (see frontends/ast/). 24 | * Thus this frontend does not generate RTLIL code directly but creates an 25 | * AST directly from the VHDL parse tree and then passes this AST to 26 | * the AST frontend library. 27 | * 28 | */ 29 | 30 | #ifndef VHDL_FRONTEND_H 31 | #define VHDL_FRONTEND_H 32 | 33 | #include "kernel/yosys.h" 34 | #include "frontends/ast/ast.h" 35 | #include 36 | #include 37 | #include 38 | 39 | YOSYS_NAMESPACE_BEGIN 40 | 41 | namespace VHDL_FRONTEND 42 | { 43 | // this variable is set to a new AST_DESIGN node and then filled with the AST by the bison parser 44 | extern struct AST::AstNode *current_ast; 45 | 46 | // this function converts a VHDL constant to an AST_CONSTANT node 47 | AST::AstNode *const2ast(std::string code, char case_type = 0, bool warn_z = false); 48 | 49 | // state of `default_nettype 50 | extern bool default_nettype_wire; 51 | 52 | // lexer input stream 53 | extern std::istream *lexin; 54 | } 55 | 56 | // the pre-processor 57 | std::string frontend_vhdl_preproc(std::istream &f, std::string filename, const std::map pre_defines_map, const std::list include_dirs); 58 | 59 | YOSYS_NAMESPACE_END 60 | 61 | // the usual bison/flex stuff 62 | extern int frontend_vhdl_yydebug; 63 | extern int frontend_vhdl_yy_flex_debug; 64 | int frontend_vhdl_yylex(void); 65 | void frontend_vhdl_yyerror(char const *fmt, ...); 66 | void frontend_vhdl_yyrestart(FILE *f); 67 | int frontend_vhdl_yyparse(void); 68 | int frontend_vhdl_yylex_destroy(void); 69 | int frontend_vhdl_yyget_lineno(void); 70 | void frontend_vhdl_yyset_lineno (int); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /vhdl/vhdl_lexer.l: -------------------------------------------------------------------------------- 1 | /* 2 | vhd2vl v2.3 3 | VHDL to Verilog RTL translator 4 | Copyright (C) 2001 Vincenzo Liguori - Ocean Logic Pty Ltd - http://www.ocean-logic.com 5 | Modifications Copyright (C) 2006 Mark Gonzales - PMC Sierra Inc 6 | Modifications Copyright (C) 2008-2010 Larry Doolittle - LBNL 7 | Copyright (C) 2016 Sebastian Kuzminsky 8 | 9 | This program is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation; either version 2 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License along 20 | with this program; if not, write to the Free Software Foundation, Inc., 21 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22 | */ 23 | 24 | %option noinput 25 | %option nounput 26 | %option noyywrap 27 | %option prefix="frontend_vhdl_yy" 28 | %option debug 29 | %option yylineno 30 | 31 | %x SYNOPSYS_TRANSLATE_OFF 32 | 33 | %{ 34 | 35 | #ifdef __clang__ 36 | // bison generates code using the 'register' storage class specifier 37 | #pragma clang diagnostic ignored "-Wdeprecated-register" 38 | #endif 39 | 40 | #include 41 | #include 42 | 43 | #include "kernel/log.h" 44 | #include "vhdl_frontend.h" 45 | #include "frontends/ast/ast.h" 46 | 47 | #include "def.h" 48 | #include "vhdl_parser.tab.h" 49 | 50 | USING_YOSYS_NAMESPACE 51 | using namespace AST; 52 | using namespace VHDL_FRONTEND; 53 | 54 | YOSYS_NAMESPACE_BEGIN 55 | namespace VHDL_FRONTEND { 56 | std::vector fn_stack; 57 | std::vector ln_stack; 58 | } 59 | YOSYS_NAMESPACE_END 60 | 61 | 62 | extern int lineno; 63 | 64 | extern int skipRem; 65 | 66 | void getstring(unsigned skip); 67 | void getbasedstring(unsigned skip); 68 | 69 | #define YY_INPUT(buf,result,max_size) \ 70 | result = readsome(*VHDL_FRONTEND::lexin, buf, max_size) 71 | 72 | %} 73 | 74 | %% 75 | 76 | "`file_push "[^\n]* { 77 | fn_stack.push_back(current_filename); 78 | ln_stack.push_back(frontend_vhdl_yyget_lineno()); 79 | current_filename = yytext+11; 80 | if (!current_filename.empty() && current_filename.front() == '"') 81 | current_filename = current_filename.substr(1); 82 | if (!current_filename.empty() && current_filename.back() == '"') 83 | current_filename = current_filename.substr(0, current_filename.size()-1); 84 | frontend_vhdl_yyset_lineno(0); 85 | } 86 | 87 | "`file_pop"[^\n]*\n { 88 | current_filename = fn_stack.back(); 89 | fn_stack.pop_back(); 90 | frontend_vhdl_yyset_lineno(ln_stack.back()); 91 | ln_stack.pop_back(); 92 | } 93 | 94 | 95 | [ \t] {;} 96 | 97 | "--".*\n { 98 | lineno++; 99 | if (skipRem == 0) { 100 | /* sometimes comments should be dropped by lex - 101 | * e.g. in expressions - this makes the grammar much simpler 102 | */ 103 | size_t l=strlen(yytext); 104 | frontend_vhdl_yylval.txt=(char*)malloc(l+1); 105 | strcpy(frontend_vhdl_yylval.txt, yytext); 106 | frontend_vhdl_yylval.txt[0]='/'; 107 | frontend_vhdl_yylval.txt[1]='/'; 108 | if(frontend_vhdl_yylval.txt[l-2]=='\r') { 109 | frontend_vhdl_yylval.txt[l-2]='\n'; 110 | frontend_vhdl_yylval.txt[l-1]='\0'; 111 | } 112 | return REM; 113 | } 114 | } 115 | "library ".*\n {lineno++;} 116 | "use ".*\n {lineno++;} 117 | 118 | "\x0d\n" | 119 | \n { lineno++;} 120 | 121 | "entity" { return ENTITY; } 122 | "is" { return IS; } 123 | "port" { return PORT; } 124 | "generic" { return GENERIC; } 125 | "map" { return MAP; } 126 | "in" { return IN; } 127 | "out" { return OUT; } 128 | "inout" { return INOUT; } 129 | "time" | 130 | "natural" | 131 | "positive" | 132 | "integer" { return INTEGER; } 133 | "boolean" | 134 | "std_logic" | 135 | "std_ulogic" { return BIT; } 136 | "signed" | 137 | "unsigned" | 138 | "std_logic_vector" | 139 | "std_ulogic_vector" { return BITVECT; } 140 | "downto" { return DOWNTO; } 141 | "to" { return TO; } 142 | "type" {return TYPE; } 143 | "end" { return END; } 144 | "for" { return FOR; } 145 | "loop" { return LOOP; } 146 | "generate" { return GENERATE; } 147 | "architecture" { return ARCHITECTURE; } 148 | "component" { return COMPONENT; } 149 | "of" { return OF; } 150 | "array" {return ARRAY; } 151 | "signal" { return SIGNAL; } 152 | "begin" { return BEGN; } 153 | "not" { return NOT; } 154 | "when" { return WHEN; } 155 | "exit" { return EXIT; } 156 | "with" { return WITH; } 157 | "select" { return SELECT; } 158 | "others" { return OTHERS; } 159 | "range" { return RANGE; } 160 | "process" { return PROCESS; } 161 | "variable" { return VARIABLE; } 162 | "constant" { return CONSTANT; } 163 | "null" { return NULLV; } 164 | "open" { return OPEN; } 165 | "if" { return IF; } 166 | "then" { return THEN; } 167 | "elsif" { return ELSIF; } 168 | "else" { return ELSE; } 169 | "case" { return CASE; } 170 | "after" { return AFTER; } 171 | "and" { return AND; } 172 | "or" { return OR; } 173 | "xor" { return XOR; } 174 | "xnor" { return XNOR; } 175 | "mod" { return MOD; } 176 | "event" { return EVENT; } 177 | "rising_edge" { return POSEDGE;} 178 | "falling_edge" { return NEGEDGE;} 179 | "resize" { return CONVFUNC_2;} 180 | "to_unsigned" { return CONVFUNC_2;} 181 | "conv_integer" { return CONVFUNC_1;} 182 | "left" { return LEFT;} 183 | "high" { return LEFT;} 184 | 185 | \"[ \!#-~]*\" | 186 | \'[01xz]\' { getstring(1); return STRING;} 187 | 188 | #[0-9a-f]*# { 189 | getbasedstring(1); /* skip leading # */ 190 | return BASED; 191 | } 192 | 193 | [a-zA-Z_$][a-zA-Z0-9_$.]* { 194 | frontend_vhdl_yylval.txt=(char*)malloc(strlen(yytext)+2); 195 | frontend_vhdl_yylval.txt[0] = '\\'; 196 | frontend_vhdl_yylval.txt[1] = '\0'; 197 | strcat(frontend_vhdl_yylval.txt, yytext); 198 | return NAME; 199 | } 200 | 201 | [0-9]+ { 202 | sscanf(yytext, "%d", &frontend_vhdl_yylval.n); 203 | return NATURAL; 204 | } 205 | 206 | [0-9]+\.[0-9]+ { 207 | getstring(0); 208 | return FLOAT; 209 | } 210 | 211 | . { return yytext[0]; } 212 | 213 | %% 214 | 215 | void getstring(unsigned skip){ 216 | /* Gets a string excluding " or ' */ 217 | unsigned i; 218 | for(i=skip; yytext[i]!='"' && yytext[i]!='\'' && yytext[i]!=0; i++); 219 | yytext[i]=0; 220 | frontend_vhdl_yylval.txt=(char*)malloc(i+1); 221 | strcpy(frontend_vhdl_yylval.txt, yytext+skip); 222 | } 223 | 224 | void getbasedstring(unsigned skip){ 225 | /* Gets a string excluding # */ 226 | unsigned i; 227 | for(i=skip; yytext[i]!='#' && yytext[i]!=0; i++); 228 | yytext[i]=0; 229 | frontend_vhdl_yylval.txt=(char*)malloc(i+1); 230 | strcpy(frontend_vhdl_yylval.txt, yytext+skip); 231 | } 232 | 233 | void yyerror(char *s){ 234 | fprintf(stderr,"%s at \"%s\" in line %d.\n\n",s,yytext,lineno); 235 | } 236 | -------------------------------------------------------------------------------- /vhdl/vhdl_parser.y: -------------------------------------------------------------------------------- 1 | // vim: set noexpandtab tabstop=8 shiftwidth=8 : 2 | /* 3 | vhd2vl v2.5 4 | VHDL to Verilog RTL translator 5 | Copyright (C) 2001 Vincenzo Liguori - Ocean Logic Pty Ltd - http://www.ocean-logic.com 6 | Modifications (C) 2006 Mark Gonzales - PMC Sierra Inc 7 | Modifications (C) 2010 Shankar Giri 8 | Modifications (C) 2002, 2005, 2008-2010, 2015 Larry Doolittle - LBNL 9 | 10 | This program is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation; either version 2 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License along 21 | with this program; if not, write to the Free Software Foundation, Inc., 22 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | 24 | --- 25 | 26 | The VHDL frontend. 27 | 28 | This frontend is using the AST frontend library (see frontends/ast/). 29 | Thus this frontend does not generate RTLIL code directly but creates an 30 | AST directly from the VHDL parse tree and then passes this AST to 31 | the AST frontend library. 32 | 33 | --- 34 | 35 | This is the actual bison parser for VHDL code. It is based on the 36 | "vhd2vl" parser (by Vincenzo Liguori, Mark Gonzales, Shankar Giri, 37 | and Larry Doolittle) and the Yosys Verilog Frontend (by Clifford 38 | Wolf). The AST ist created directly from the bison reduce functions 39 | here. Note that this code uses a few global variables to hold the 40 | state of the AST generator and therefore this parser is not reentrant. 41 | 42 | */ 43 | 44 | %{ 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | #include "kernel/log.h" 54 | #include "vhdl_frontend.h" 55 | #include "def.h" 56 | 57 | USING_YOSYS_NAMESPACE 58 | using namespace AST; 59 | using namespace VHDL_FRONTEND; 60 | 61 | YOSYS_NAMESPACE_BEGIN 62 | namespace VHDL_FRONTEND { 63 | // std::map attr_list; 64 | std::map default_attr_list; 65 | std::map modules; 66 | // std::map *albuf; 67 | 68 | struct AstNode *astbuf1, *astbuf2, *astbuf3; 69 | // struct AstNode *current_function_or_task; 70 | 71 | // This gets initialized by the caller (the vhdl frontend) to the 72 | // AST_DESIGN node that we're to parse the VHDL into. 73 | struct AstNode *current_ast; 74 | 75 | struct AstNode *current_ast_mod; 76 | // int current_function_or_task_port_id; 77 | // std::vector case_type_stack; 78 | // bool do_not_require_port_stubs; 79 | bool default_nettype_wire; 80 | std::istream *lexin; 81 | 82 | typedef enum { 83 | DIR_IN = 0, 84 | DIR_OUT = 1, 85 | DIR_INOUT = 2, 86 | DIR_NONE 87 | } port_dir_t; 88 | 89 | const char *port_dir_str[] = { "IN", "OUT", "INOUT" }; 90 | 91 | #define NOT_IMPLEMENTED log_error("NOT IMPLEMENTED: %s:%d (%s:%d)\n", AST::current_filename.c_str(), frontend_vhdl_yyget_lineno(), __FILE__, __LINE__) 92 | 93 | } 94 | YOSYS_NAMESPACE_END 95 | 96 | 97 | int vlog_ver=0; /* default is -g1995 */ 98 | 99 | /* You will of course want to tinker with this if you use a debugging 100 | * malloc(), otherwise all the line numbers will point here. 101 | */ 102 | void *xmalloc(size_t size) { 103 | void *p = calloc(1, size); 104 | if (!p) { 105 | perror("calloc"); 106 | exit(2); 107 | } 108 | return p; 109 | } 110 | 111 | int skipRem = 0; 112 | int lineno=1; 113 | 114 | sglist *io_list=NULL; 115 | sglist *sig_list=NULL; 116 | sglist *type_list=NULL; 117 | blknamelist *blkname_list=NULL; 118 | 119 | /* need a stack of clock-edges because all edges are processed before all processes are processed. 120 | * Edges are processed in source file order, processes are processed in reverse source file order. 121 | * The original scheme of just one clkedge variable makes all clocked processes have the edge sensitivity 122 | * of the last clocked process in the file. 123 | */ 124 | int clkedges[MAXEDGES]; 125 | int clkptr = 0; 126 | int delay=1; 127 | int dolist=1; 128 | int np=1; 129 | char wire[]="wire"; 130 | char reg[]="reg"; 131 | int dowith=0; 132 | slist *slwith; 133 | 134 | /* Indentation variables */ 135 | int indent=0; 136 | slist *indents[MAXINDENT]; 137 | 138 | struct vrange *new_vrange(enum vrangeType t) 139 | { 140 | struct vrange *v=(vrange*)xmalloc(sizeof(vrange)); 141 | v->vtype=t; 142 | v->nlo = NULL; 143 | v->nhi = NULL; 144 | v->size_expr = NULL; 145 | v->sizeval = 0; 146 | v->xlo = NULL; 147 | v->xhi = NULL; 148 | return v; 149 | } 150 | 151 | void fslprint(FILE *fp,slist *sl){ 152 | // if(sl){ 153 | // assert(sl != sl->slst); 154 | // fslprint(fp,sl->slst); 155 | // switch(sl->type){ 156 | // case 0 : 157 | // assert(sl != sl->data.sl); 158 | // fslprint(fp,sl->data.sl); 159 | // break; 160 | // case 1 : case 4 : 161 | // fprintf(fp,"%s",sl->data.txt); 162 | // break; 163 | // case 2 : 164 | // fprintf(fp,"%d",sl->data.val); 165 | // break; 166 | // case 3 : 167 | // fprintf(fp,"%s",*(sl->data.ptxt)); 168 | // break; 169 | // } 170 | // } 171 | } 172 | 173 | void slprint(slist *sl){ 174 | fslprint(stdout, sl); 175 | } 176 | 177 | slist *copysl(slist *sl){ 178 | if(sl){ 179 | slist *newsl; 180 | newsl = (slist*)xmalloc(sizeof(slist)); 181 | *newsl = *sl; 182 | if (sl->slst != NULL) { 183 | assert(sl != sl->slst); 184 | newsl->slst = copysl(sl->slst); 185 | } 186 | switch(sl->type){ 187 | case 0 : 188 | if (sl->data.sl != NULL) { 189 | assert(sl != sl->data.sl); 190 | newsl->data.sl = copysl(sl->data.sl); 191 | } 192 | break; 193 | case 1 : case 4 : 194 | newsl->data.txt = (char*)xmalloc(strlen(sl->data.txt) + 1); 195 | strcpy(newsl->data.txt, sl->data.txt); 196 | break; 197 | } 198 | return newsl; 199 | } 200 | return NULL; 201 | } 202 | 203 | slist *addtxt(slist *sl, const char *s){ 204 | slist *p; 205 | 206 | if(s == NULL) 207 | return sl; 208 | p = (slist*)xmalloc(sizeof *p); 209 | p->type = 1; 210 | p->slst = sl; 211 | p->data.txt = (char*)xmalloc(strlen(s) + 1); 212 | strcpy(p->data.txt, s); 213 | 214 | return p; 215 | } 216 | 217 | slist *addothers(slist *sl, char *s){ 218 | slist *p; 219 | 220 | if(s == NULL) 221 | return sl; 222 | p = (slist*)xmalloc(sizeof *p); 223 | p->type = 4; 224 | p->slst = sl; 225 | p->data.txt = (char*)xmalloc(strlen(s) + 1); 226 | strcpy(p->data.txt, s); 227 | 228 | return p; 229 | } 230 | 231 | slist *addptxt(slist *sl, char **s){ 232 | slist *p; 233 | 234 | if(s == NULL) 235 | return sl; 236 | 237 | p = (slist*)xmalloc(sizeof *p); 238 | p->type = 3; 239 | p->slst = sl; 240 | p->data.ptxt = s; 241 | 242 | return p; 243 | } 244 | 245 | slist *addval(slist *sl, int val){ 246 | slist *p; 247 | 248 | p = (slist*)xmalloc(sizeof(slist)); 249 | p->type = 2; 250 | p->slst = sl; 251 | p->data.val = val; 252 | 253 | return p; 254 | } 255 | 256 | slist *addsl(slist *sl, slist *sl2){ 257 | slist *p; 258 | if(sl2 == NULL) return sl; 259 | p = (slist*)xmalloc(sizeof(slist)); 260 | p->type = 0; 261 | p->slst = sl; 262 | p->data.sl = sl2; 263 | return p; 264 | } 265 | 266 | slist *addvec(slist *sl, char *s){ 267 | sl=addval(sl,strlen(s)); 268 | sl=addtxt(sl,"'b "); 269 | sl=addtxt(sl,s); 270 | return sl; 271 | } 272 | 273 | slist *addvec_base(slist *sl, char *b, char *s){ 274 | const char *base_str="'b "; 275 | int base_mult=1; 276 | if (strcasecmp(b,"X") == 0) { 277 | base_str="'h "; base_mult=4; 278 | } else if (strcasecmp(b,"O") == 0) { 279 | base_str="'o "; base_mult=3; 280 | } else { 281 | fprintf(stderr,"Warning on line %d: NAME STRING rule matched but " 282 | "NAME='%s' is not X or O.\n",lineno, b); 283 | } 284 | sl=addval(sl,strlen(s)*base_mult); 285 | sl=addtxt(sl,base_str); 286 | sl=addtxt(sl,s); 287 | return sl; 288 | } 289 | 290 | slist *addind(slist *sl){ 291 | if(sl) 292 | sl=addsl(indents[indent],sl); 293 | return sl; 294 | } 295 | 296 | slist *addpar(slist *sl, vrange *v){ 297 | if(v->nlo != NULL) { /* indexes are simple expressions */ 298 | sl=addtxt(sl," ["); 299 | if(v->nhi != NULL){ 300 | sl=addsl(sl,v->nhi); 301 | sl=addtxt(sl,":"); 302 | } 303 | sl=addsl(sl,v->nlo); 304 | sl=addtxt(sl,"] "); 305 | } else { 306 | sl=addtxt(sl," "); 307 | } 308 | return sl; 309 | } 310 | 311 | slist *addpar_snug(slist *sl, vrange *v){ 312 | if(v->nlo != NULL) { /* indexes are simple expressions */ 313 | sl=addtxt(sl,"["); 314 | if(v->nhi != NULL){ 315 | sl=addsl(sl,v->nhi); 316 | sl=addtxt(sl,":"); 317 | } 318 | sl=addsl(sl,v->nlo); 319 | sl=addtxt(sl,"]"); 320 | } 321 | return sl; 322 | } 323 | 324 | /* This function handles array of vectors in signal lists */ 325 | slist *addpar_snug2(slist *sl, vrange *v, vrange *v1){ 326 | if(v->nlo != NULL) { /* indexes are simple expressions */ 327 | sl=addtxt(sl,"["); 328 | if(v->nhi != NULL){ 329 | sl=addsl(sl,v->nhi); 330 | sl=addtxt(sl,":"); 331 | } 332 | sl=addsl(sl,v->nlo); 333 | sl=addtxt(sl,"]"); 334 | } 335 | if(v1->nlo != NULL) { /* indexes are simple expressions */ 336 | sl=addtxt(sl,"["); 337 | if(v1->nhi != NULL){ 338 | sl=addsl(sl,v1->nhi); 339 | sl=addtxt(sl,":"); 340 | } 341 | sl=addsl(sl,v1->nlo); 342 | sl=addtxt(sl,"]"); 343 | } 344 | return sl; 345 | } 346 | 347 | slist *addpost(slist *sl, vrange *v){ 348 | if(v->xlo != NULL) { 349 | sl=addtxt(sl,"["); 350 | if(v->xhi != NULL){ 351 | sl=addsl(sl,v->xhi); 352 | sl=addtxt(sl,":"); 353 | } 354 | sl=addsl(sl,v->xlo); 355 | sl=addtxt(sl,"]"); 356 | } 357 | return sl; 358 | } 359 | 360 | slist *addwrap(const char *l,slist *sl,const char *r){ 361 | slist *s; 362 | s=addtxt(NULL,l); 363 | s=addsl(s,sl); 364 | return addtxt(s,r); 365 | } 366 | 367 | expdata *addnest(struct expdata *inner) 368 | { 369 | expdata *e; 370 | e=(expdata*)xmalloc(sizeof(expdata)); 371 | if (inner->op == EXPDATA_TYPE_C) { 372 | e->sl=addwrap("{",inner->sl,"}"); 373 | } else { 374 | e->sl=addwrap("(",inner->sl,")"); 375 | } 376 | return e; 377 | } 378 | 379 | slist *addrem(slist *sl, slist *rem) 380 | { 381 | if (rem) { 382 | sl=addtxt(sl, " "); 383 | sl=addsl(sl, rem); 384 | } else { 385 | sl=addtxt(sl, "\n"); 386 | } 387 | return sl; 388 | } 389 | 390 | sglist *lookup(sglist *sg,char *s){ 391 | for(;;){ 392 | if(sg == NULL || strcmp(sg->name,s)==0) 393 | return sg; 394 | sg=sg->next; 395 | } 396 | } 397 | 398 | char *sbottom(slist *sl){ 399 | while(sl->slst != NULL) 400 | sl=sl->slst; 401 | return sl->data.txt; 402 | } 403 | 404 | const char *inout_string(int type) 405 | { 406 | const char *name=NULL; 407 | switch(type) { 408 | case 0: name="input" ; break; 409 | case 1: name="output" ; break; 410 | case 2: name="inout" ; break; 411 | default: break; 412 | } 413 | return name; 414 | } 415 | 416 | int prec(int op){ 417 | switch(op){ 418 | case EXPDATA_TYPE_OTHERS: /* others */ 419 | return 9; 420 | break; 421 | case EXPDATA_TYPE_TERMINAL: 422 | case EXPDATA_TYPE_N: 423 | return 8; 424 | break; 425 | case EXPDATA_TYPE_TILDE: 426 | return 7; 427 | break; 428 | case EXPDATA_TYPE_P: 429 | case EXPDATA_TYPE_M: 430 | return 6; 431 | break; 432 | case EXPDATA_TYPE_MULT: 433 | case EXPDATA_TYPE_DIV: 434 | case EXPDATA_TYPE_MOD: 435 | return 5; 436 | break; 437 | case EXPDATA_TYPE_ADD: 438 | case EXPDATA_TYPE_SUBTRACT: 439 | return 4; 440 | break; 441 | case EXPDATA_TYPE_AND: 442 | return 3; 443 | break; 444 | case EXPDATA_TYPE_CARET: 445 | return 2; 446 | break; 447 | case EXPDATA_TYPE_OR: 448 | return 1; 449 | break; 450 | default: 451 | return 0; 452 | break; 453 | } 454 | } 455 | 456 | expdata *addexpr(expdata *expr1,int op,const char* opstr,expdata *expr2){ 457 | slist *sl1,*sl2; 458 | if(expr1 == NULL) 459 | sl1=NULL; 460 | else if(expr1->op == EXPDATA_TYPE_C) 461 | sl1=addwrap("{",expr1->sl,"}"); 462 | else if(prec(expr1->op) < prec(op)) 463 | sl1=addwrap("(",expr1->sl,")"); 464 | else 465 | sl1=expr1->sl; 466 | 467 | if(expr2->op == EXPDATA_TYPE_C) 468 | sl2=addwrap("{",expr2->sl,"}"); 469 | else if(prec(expr2->op) < prec(op)) 470 | sl2=addwrap("(",expr2->sl,")"); 471 | else 472 | sl2=expr2->sl; 473 | 474 | if(expr1 == NULL) 475 | expr1=expr2; 476 | else 477 | free(expr2); 478 | 479 | expr1->op = (expdata_type_t)op; 480 | sl1=addtxt(sl1,opstr); 481 | sl1=addsl(sl1,sl2); 482 | expr1->sl=sl1; 483 | return expr1; 484 | } 485 | 486 | void slTxtReplace(slist *sl, const char *match, const char *replace){ 487 | if(sl){ 488 | slTxtReplace(sl->slst, match, replace); 489 | switch(sl->type) { 490 | case 0 : 491 | slTxtReplace(sl->data.sl, match, replace); 492 | break; 493 | case 1 : 494 | if (strcmp(sl->data.txt, match) == 0) { 495 | sl->data.txt = strdup(replace); 496 | } 497 | break; 498 | case 3 : 499 | if (strcmp(*(sl->data.ptxt), match) == 0) { 500 | *(sl->data.ptxt) = strdup(replace); 501 | } 502 | break; 503 | } 504 | } 505 | } 506 | 507 | 508 | /* XXX todo: runtime engage clkedge debug */ 509 | void push_clkedge(int val, const char *comment) 510 | { 511 | if (0) fprintf(stderr,"clock event push: line=%d clkptr=%d, value=%d (%s)\n",lineno,clkptr,val,comment); 512 | clkedges[clkptr++]=val; 513 | assert(clkptr < MAXEDGES); 514 | } 515 | 516 | int pull_clkedge(slist *sensitivities) 517 | { 518 | int clkedge; 519 | assert(clkptr>0); 520 | clkedge = clkedges[--clkptr]; 521 | if (0) { 522 | fprintf(stderr,"clock event pull: value=%d, sensistivity list = ", clkedge); 523 | fslprint(stderr,sensitivities); 524 | fprintf(stderr,"\n"); 525 | } 526 | return clkedge; 527 | } 528 | 529 | /* XXX maybe it's a bug that some uses don't munge clocks? */ 530 | slist *add_always(slist *sl, slist *sensitivities, slist *decls, int munge) 531 | { 532 | int clkedge; 533 | sl=addsl(sl,indents[indent]); 534 | sl=addtxt(sl,"always @("); 535 | if (munge) { 536 | clkedge = pull_clkedge(sensitivities); 537 | if(clkedge) { 538 | sl=addtxt(sl,"posedge "); 539 | /* traverse $4->sl replacing " or " with " or posedge " if there is a clockedge */ 540 | slTxtReplace(sensitivities," or ", " or posedge "); 541 | } else { 542 | sl=addtxt(sl,"negedge "); 543 | slTxtReplace(sensitivities," or ", " or negedge "); 544 | } 545 | } 546 | sl=addsl(sl,sensitivities); 547 | sl=addtxt(sl,") begin"); 548 | if(decls){ 549 | sl=addtxt(sl," : P"); 550 | sl=addval(sl,np++); 551 | sl=addtxt(sl,"\n"); 552 | sl=addsl(sl,decls); 553 | } 554 | sl=addtxt(sl,"\n"); 555 | return sl; 556 | } 557 | 558 | void fixothers(slist *size_expr, slist *sl) { 559 | if(sl) { 560 | fixothers(size_expr, sl->slst); 561 | switch(sl->type) { 562 | case 0 : 563 | fixothers(size_expr,sl->data.sl); 564 | break; 565 | case 4 : { 566 | /* found an (OTHERS => 'x') clause - change to type 0, and insert the 567 | * size_expr for the corresponding signal */ 568 | slist *p; 569 | slist *size_copy = (slist*)xmalloc(sizeof(slist)); 570 | size_copy = copysl(size_expr); 571 | if (0) { 572 | fprintf(stderr,"fixothers type 4 size_expr "); 573 | fslprint(stderr,size_expr); 574 | fprintf(stderr,"\n"); 575 | } 576 | p = addtxt(NULL, "1'b"); 577 | p = addtxt(p, sl->data.txt); 578 | p = addwrap("{",p,"}"); 579 | p = addsl(size_copy, p); 580 | p = addwrap("{",p,"}"); 581 | sl->type=0; 582 | sl->slst=p; 583 | sl->data.sl=NULL; 584 | break; 585 | } /* case 4 */ 586 | } /* switch */ 587 | } 588 | } 589 | 590 | void findothers(slval *sgin,slist *sl){ 591 | sglist *sg = NULL; 592 | int size = -1; 593 | int useExpr=0; 594 | if (0) { 595 | fprintf(stderr,"findothers lhs "); 596 | fslprint(stderr,sgin->sl); 597 | fprintf(stderr,", sgin->val %d\n", sgin->val); 598 | } 599 | if(sgin->val>0) { 600 | size=sgin->val; 601 | } else if (sgin->range != NULL) { 602 | if (sgin->range->vtype != tVRANGE) { 603 | size=1; 604 | } else if (sgin->range->sizeval > 0) { 605 | size=sgin->range->sizeval; 606 | } else if (sgin->range->size_expr != NULL) { 607 | useExpr = 1; 608 | fixothers(sgin->range->size_expr, sl); 609 | } 610 | } else { 611 | if((sg=lookup(io_list,sgin->sl->data.txt))==NULL) { 612 | sg=lookup(sig_list,sgin->sl->data.txt); 613 | } 614 | if(sg) { 615 | if(sg->range->vtype != tVRANGE) { 616 | size=1; 617 | } else { 618 | if (sg->range->sizeval > 0) { 619 | size = sg->range->sizeval; 620 | } else { 621 | assert (sg->range->size_expr != NULL); 622 | useExpr = 1; 623 | fixothers(sg->range->size_expr, sl); 624 | } 625 | } 626 | } else { 627 | /* lookup failed, there was no vrange or size value in sgin - so just punt, and assign size=1 */ 628 | size=1; 629 | } /* if(sg) */ 630 | } 631 | if (!useExpr) { 632 | slist *p; 633 | assert(size>0); 634 | /* use size */ 635 | p = addval(NULL,size); 636 | fixothers(p,sl); 637 | } 638 | } 639 | 640 | /* code to find bit number of the msb of n */ 641 | int find_msb(int n) 642 | { 643 | int k=0; 644 | if(n&0xff00){ 645 | k|=8; 646 | n&=0xff00; 647 | } 648 | if(n&0xf0f0){ 649 | k|=4; 650 | n&=0xf0f0; 651 | } 652 | if(n&0xcccc){ 653 | k|=2; 654 | n&=0xcccc; 655 | } 656 | if(n&0xaaaa){ 657 | k|=1; 658 | n&=0xaaaa; 659 | } 660 | return k; 661 | } 662 | 663 | static char time_unit[2]= { '\0', '\0' }, new_unit[2]= { '\0', '\0' }; 664 | static void set_timescale(const char *s) 665 | { 666 | if (0) fprintf(stderr,"set_timescale (%s)\n", s); 667 | new_unit[0] = time_unit[0]; 668 | if (strcasecmp(s,"ms") == 0) { new_unit[0] = 'm'; } 669 | else if (strcasecmp(s,"us") == 0) { new_unit[0] = 'u'; } 670 | else if (strcasecmp(s,"ns") == 0) { new_unit[0] = 'n'; } 671 | else if (strcasecmp(s,"ps") == 0) { new_unit[0] = 'p'; } 672 | else { 673 | fprintf(stderr,"Warning on line %d: AFTER NATURAL NAME pattern" 674 | " matched, but NAME='%s' should be a time unit.\n",lineno,s); 675 | } 676 | if (new_unit[0] != time_unit[0]) { 677 | if (time_unit[0] != 0) { 678 | fprintf(stderr,"Warning on line %d: inconsistent time unit (%s) ignored\n", lineno, s); 679 | } else { 680 | time_unit[0] = new_unit[0]; 681 | } 682 | } 683 | } 684 | 685 | slist *output_timescale(slist *sl) 686 | { 687 | if (time_unit[0] != 0) { 688 | sl = addtxt(sl, "`timescale 1 "); 689 | sl = addtxt(sl, time_unit); 690 | sl = addtxt(sl, "s / 1 "); 691 | sl = addtxt(sl, time_unit); 692 | sl = addtxt(sl, "s\n"); 693 | } else { 694 | sl = addtxt(sl, "// no timescale needed\n"); 695 | } 696 | return sl; 697 | } 698 | 699 | slist *setup_port(sglist *s_list, int dir, vrange *type) { 700 | slist *sl; 701 | sglist *p; 702 | if (vlog_ver == 1) { 703 | sl=addtxt(NULL,NULL); 704 | } 705 | else { 706 | sl=addtxt(NULL,inout_string(dir)); 707 | sl=addpar(sl,type); 708 | } 709 | p=s_list; 710 | for(;;){ 711 | p->type=wire; 712 | if (vlog_ver == 1) p->dir=inout_string(dir); 713 | p->range=type; 714 | if (vlog_ver == 0) sl=addtxt(sl, p->name); 715 | if(p->next==NULL) 716 | break; 717 | p=p->next; 718 | if (vlog_ver == 0) sl=addtxt(sl,", "); 719 | } 720 | if (vlog_ver == 0) sl=addtxt(sl,";\n"); 721 | p->next=io_list; 722 | io_list=s_list; 723 | return sl; 724 | } 725 | 726 | slist *emit_io_list(slist *sl) 727 | { 728 | // sglist *p; 729 | // sl=addtxt(sl,"(\n"); 730 | // p=io_list; 731 | // for(;;){ 732 | // if (vlog_ver == 1) { 733 | // sl=addtxt(sl,p->dir); 734 | // sl=addtxt(sl," "); 735 | // sl=addptxt(sl,&(p->type)); 736 | // sl=addpar(sl,p->range); 737 | // } 738 | // sl=addtxt(sl,p->name); 739 | // p=p->next; 740 | // if(p) 741 | // sl=addtxt(sl,",\n"); 742 | // else{ 743 | // sl=addtxt(sl,"\n"); 744 | // break; 745 | // } 746 | // } 747 | // sl=addtxt(sl,");\n\n"); 748 | return sl; 749 | } 750 | 751 | 752 | AstNode *make_wire(std::string name, port_dir_t dir, struct vrange *type) { 753 | struct AstNode *wire; 754 | wire = new AstNode(AST_WIRE); 755 | wire->str = name; 756 | switch (dir) { 757 | case DIR_IN: 758 | wire->is_input = true; 759 | break; 760 | case DIR_OUT: 761 | wire->is_output = true; 762 | break; 763 | case DIR_INOUT: 764 | wire->is_input = true; 765 | wire->is_output = true; 766 | break; 767 | case DIR_NONE: 768 | break; 769 | default: 770 | delete wire; 771 | frontend_vhdl_yyerror("unhandled direction %d\n", (int)dir); 772 | } 773 | 774 | switch (type->vtype) { 775 | case tSCALAR: 776 | break; 777 | 778 | case tVRANGE: { 779 | log_assert(type->nhi->type == 2); 780 | log_assert(type->nlo->type == 2); 781 | AstNode *high = AstNode::mkconst_int(type->nhi->data.val, false, 32); 782 | AstNode *low = AstNode::mkconst_int(type->nlo->data.val, false, 32); 783 | AstNode *range = new AstNode(AST_RANGE, high, low); 784 | wire->children.push_back(range); 785 | break; 786 | } 787 | 788 | // case tSUBSCRIPT: 789 | default: 790 | delete wire; 791 | frontend_vhdl_yyerror("unhandled type\n"); 792 | // not reached 793 | } 794 | 795 | return wire; 796 | } 797 | 798 | 799 | void add_wire(std::vector *v, AstNode *wire) { 800 | if (v == NULL) { 801 | frontend_vhdl_yyerror("adding wire to a NULL vector\n"); 802 | return; 803 | } 804 | if (wire == NULL) { 805 | frontend_vhdl_yyerror("adding a NULL wire\n"); 806 | return; 807 | } 808 | v->push_back(wire); 809 | } 810 | 811 | 812 | void add_wire(std::vector *v, std::string name, port_dir_t dir, struct vrange *type) { 813 | add_wire(v, make_wire(name, dir, type)); 814 | } 815 | 816 | 817 | void add_portlist_wires(AstNode *module, std::vector *portlist) { 818 | int port_id = 1; 819 | for (auto &wire: *portlist) { 820 | wire->port_id = port_id; 821 | port_id++; 822 | module->children.push_back(wire); 823 | } 824 | } 825 | 826 | 827 | AstNode *expr_to_ast(expdata *expr) { 828 | struct AstNode *node = NULL; 829 | 830 | if (expr->op == EXPDATA_TYPE_AST) { 831 | node = expr->node; 832 | 833 | } else if (expr->op == EXPDATA_TYPE_BITS) { 834 | // bit vector 835 | node = Yosys::AST::AstNode::mkconst_bits(expr->bits, false); 836 | if (node == NULL) { 837 | frontend_vhdl_yyerror("failed to make AST node from bit string\n"); 838 | } 839 | 840 | } else { 841 | frontend_vhdl_yyerror("unhandled expression\n"); 842 | } 843 | 844 | return node; 845 | } 846 | 847 | 848 | void print_signal_list(std::vector *signal_list) { 849 | printf("signal list %p:\n", signal_list); 850 | for (auto &name: *signal_list) { 851 | printf(" port %s\n", name.c_str()); 852 | } 853 | } 854 | 855 | 856 | void print_type(struct vrange *vrange) { 857 | printf("vrange %p:", vrange); 858 | switch (vrange->vtype) { 859 | case tSCALAR: 860 | printf(" tSCALAR"); 861 | break; 862 | case tSUBSCRIPT: 863 | printf(" tSCUBSCRIPT"); 864 | break; 865 | case tVRANGE: 866 | printf(" tVRANGE"); 867 | break; 868 | default: 869 | printf(" (unknown type)"); 870 | break; 871 | } 872 | printf("\n"); 873 | } 874 | 875 | void string_to_bits(std::vector &bits, std::string s) { 876 | if (s.length() != 1) { 877 | frontend_vhdl_yyerror("invalid string constant `%s'.", s.c_str()); 878 | return; 879 | } 880 | 881 | bits.clear(); 882 | 883 | if (s[0] == '0') { 884 | bits.push_back(RTLIL::S0); 885 | } else if (s[0] == '1') { 886 | bits.push_back(RTLIL::S1); 887 | } else { 888 | frontend_vhdl_yyerror("invalid string constant `%s'.", s.c_str()); 889 | return; 890 | } 891 | } 892 | 893 | void expr_set_bits(expdata *e, std::string s) { 894 | printf("setting bits of expdata %p to %s\n", e, s.c_str()); 895 | 896 | if (s.length() != 1) { 897 | frontend_vhdl_yyerror("invalid string constant `%s'.", s.c_str()); 898 | return; 899 | } 900 | 901 | log_assert(e != NULL); 902 | 903 | e->op = EXPDATA_TYPE_BITS; 904 | e->bits.clear(); 905 | 906 | if (s[0] == '0') { 907 | e->bits.push_back(RTLIL::S0); 908 | } else if (s[0] == '1') { 909 | e->bits.push_back(RTLIL::S1); 910 | } else { 911 | frontend_vhdl_yyerror("invalid string constant `%s'.", s.c_str()); 912 | return; 913 | } 914 | } 915 | 916 | %} 917 | 918 | %name-prefix "frontend_vhdl_yy" 919 | 920 | %union { 921 | std::string *string; 922 | struct Yosys::AST::AstNode *ast; 923 | std::map *al; 924 | std::vector *vector_string; 925 | std::vector *vector_ast; 926 | bool boolean; 927 | char * txt; /* String */ 928 | int n; /* Value */ 929 | vrange *v; /* Signal range */ 930 | sglist *sg; /* Signal list */ 931 | slist *sl; /* String list */ 932 | expdata *e; /* Expression structure */ 933 | slval *ss; /* Signal structure */ 934 | } 935 | 936 | %token REM ENTITY IS PORT GENERIC IN OUT INOUT MAP 937 | %token INTEGER BIT BITVECT DOWNTO TO TYPE END 938 | %token ARCHITECTURE COMPONENT OF ARRAY 939 | %token SIGNAL BEGN NOT WHEN WITH EXIT 940 | %token SELECT OTHERS PROCESS VARIABLE CONSTANT 941 | %token IF THEN ELSIF ELSE CASE 942 | %token FOR LOOP GENERATE 943 | %token AFTER AND OR XOR MOD 944 | %token LASTVALUE EVENT POSEDGE NEGEDGE 945 | %token STRING NAME RANGE NULLV OPEN 946 | %token CONVFUNC_1 CONVFUNC_2 BASED FLOAT LEFT 947 | %token NATURAL 948 | 949 | %type trad 950 | %type rem remlist 951 | %type entity_name 952 | %type entity 953 | %type genlist 954 | %type architecture 955 | %type portlist 956 | %type a_decl 957 | %type p_decl oname 958 | %type a_body 959 | %type map_list map_item mvalue 960 | %type sigvalue 961 | %type generic_map_list generic_map_item 962 | %type optname gen_optname 963 | %type exprc 964 | %type conf 965 | %type p_body 966 | %type sign_list 967 | %type edge 968 | %type wlist wvalue cases 969 | %type elsepart // one or more AST_COND, ending with an AST_DEFAULT one 970 | %type with_item with_list 971 | %type s_list 972 | %type dir delay 973 | %type type vec_range 974 | %type updown 975 | %type expr 976 | %type simple_expr 977 | %type signal 978 | %type opt_is opt_generic opt_entity opt_architecture opt_begin 979 | %type generate endgenerate 980 | 981 | %right '=' 982 | /* Logic operators: */ 983 | %left ORL 984 | %left ANDL 985 | /* Binary operators: */ 986 | %left OR 987 | %left XOR 988 | %left XNOR 989 | %left AND 990 | %left MOD 991 | /* Comparison: */ 992 | %left '<' '>' BIGEQ LESSEQ NOTEQ EQUAL 993 | %left '+' '-' '&' 994 | %left '*' '/' 995 | %right UMINUS UPLUS NOTL NOT 996 | %error-verbose 997 | 998 | /* rule for "...ELSE IF edge THEN..." causes 1 shift/reduce conflict */ 999 | /* rule for opt_begin causes 1 shift/reduce conflict */ 1000 | %expect 2 1001 | 1002 | %debug 1003 | 1004 | /* glr-parser is needed because processes can start with if statements, but 1005 | * not have edges in them - more than one level of look-ahead is needed in that case 1006 | * %glr-parser 1007 | * unfortunately using glr-parser causes slists to become self-referential, causing core dumps! 1008 | */ 1009 | %% 1010 | 1011 | input: trad { 1012 | // current_ast is the callers AST_DESIGN node 1013 | // $trad is the AST_MODULE we just parsed 1014 | current_ast->children.push_back($trad); 1015 | }; 1016 | 1017 | /* Input file must contain entity declaration followed by architecture */ 1018 | trad : rem entity rem architecture rem { 1019 | log_assert($entity->str.compare($architecture->str) == 0); 1020 | $trad = $entity; 1021 | for (auto &i: $architecture->children) { 1022 | $trad->children.push_back(i); 1023 | } 1024 | 1025 | /* some people put entity declarations and architectures in separate files - 1026 | * translate each piece - note that this will not make a legal Verilog file 1027 | * - let them take care of that manually 1028 | */ 1029 | } | rem entity rem { 1030 | $trad = $entity; 1031 | 1032 | } | rem architecture rem { 1033 | $trad = $architecture; 1034 | }; 1035 | 1036 | /* Comments */ 1037 | rem : /* Empty */ {$$=NULL; } 1038 | | remlist {$$=$1; } 1039 | ; 1040 | 1041 | remlist : REM {$$=addtxt(indents[indent],$1);} 1042 | | REM remlist { 1043 | slist *sl; 1044 | sl=addtxt(indents[indent],$1); 1045 | $$=addsl(sl,$2);} 1046 | ; 1047 | 1048 | opt_is : /* Empty */ {$$=NULL;} | IS ; 1049 | 1050 | opt_entity : /* Empty */ {$$=NULL;} | ENTITY ; 1051 | 1052 | opt_architecture : /* Empty */ {$$=NULL;} | ARCHITECTURE ; 1053 | 1054 | opt_begin : /* Empty */ {$$=NULL;} | BEGN; 1055 | 1056 | generate : GENERATE opt_begin; 1057 | 1058 | endgenerate : END GENERATE; 1059 | 1060 | /* tell the lexer to discard or keep comments ('-- ') - this makes the grammar much easier */ 1061 | norem : /*Empty*/ {skipRem = 1;} 1062 | yesrem : /*Empty*/ {skipRem = 0;} 1063 | 1064 | entity_name: ENTITY NAME { 1065 | AstNode *module = new AstNode(AST_MODULE); 1066 | module->str = $2; 1067 | modules[$NAME] = module; 1068 | $entity_name = module; 1069 | }; 1070 | 1071 | /* Entity */ 1072 | entity: 1073 | /* 1 2 3 4 5 6 7 8 9 10 11 12 */ 1074 | entity_name IS rem PORT '(' rem portlist ')' ';' rem END opt_entity oname ';' { 1075 | $entity = $entity_name; 1076 | add_portlist_wires($entity, $portlist); 1077 | 1078 | // slist *sl; 1079 | // sglist *p; 1080 | // sl=addtxt(NULL,"\nmodule "); 1081 | // sl=addtxt(sl,current_ast_mod->str.c_str()); /* NAME */ 1082 | // /* Add the signal list */ 1083 | // sl=emit_io_list(sl); 1084 | // sl=addsl(sl,$6); /* rem */ 1085 | // sl=addsl(sl,$7); /* portlist */ 1086 | // sl=addtxt(sl,"\n"); 1087 | // p=io_list; 1088 | // if (vlog_ver == 0) { 1089 | // do{ 1090 | // sl=addptxt(sl,&(p->type)); 1091 | // /*sl=addtxt(sl,p->type);*/ 1092 | // sl=addpar(sl,p->range); 1093 | // sl=addtxt(sl,p->name); 1094 | // /* sl=addpost(sl,p->range); */ 1095 | // sl=addtxt(sl,";\n"); 1096 | // p=p->next; 1097 | // } while(p!=NULL); 1098 | // } 1099 | // sl=addtxt(sl,"\n"); 1100 | // sl=addsl(sl,$10); /* rem2 */ 1101 | // $$=addtxt(sl,"\n"); 1102 | current_ast_mod = NULL; 1103 | 1104 | /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 */ 1105 | } | entity_name IS GENERIC yeslist '(' rem genlist ')' ';' rem PORT yeslist '(' rem portlist ')' ';' rem END opt_entity oname ';' { 1106 | $entity = $entity_name; 1107 | add_portlist_wires($entity, $portlist); 1108 | 1109 | // slist *sl; 1110 | // sglist *p; 1111 | // if (0) fprintf(stderr,"matched ENTITY GENERIC\n"); 1112 | // sl=addtxt(NULL,"\nmodule "); 1113 | // sl=addtxt(sl,current_ast_mod->str.c_str()); /* NAME */ 1114 | // sl=emit_io_list(sl); 1115 | // sl=addsl(sl,$6); /* rem */ 1116 | // sl=addsl(sl,$7); /* genlist */ 1117 | // sl=addsl(sl,$10); /* rem */ 1118 | // sl=addsl(sl,$14); /* rem */ 1119 | // sl=addsl(sl,$15); /* portlist */ 1120 | // sl=addtxt(sl,"\n"); 1121 | // p=io_list; 1122 | // if (vlog_ver == 0) { 1123 | // do{ 1124 | // sl=addptxt(sl,&(p->type)); 1125 | // /*sl=addtxt(sl,p->type);*/ 1126 | // sl=addpar(sl,p->range); 1127 | // sl=addtxt(sl,p->name); 1128 | // sl=addtxt(sl,";\n"); 1129 | // p=p->next; 1130 | // } while(p!=NULL); 1131 | // } 1132 | // sl=addtxt(sl,"\n"); 1133 | // sl=addsl(sl,$18); /* rem2 */ 1134 | // $$=addtxt(sl,"\n"); 1135 | current_ast_mod = NULL; 1136 | }; 1137 | 1138 | 1139 | /* 1 2 3 4 5 6 7 */ 1140 | genlist : s_list ':' type ':' '=' expr rem { 1141 | NOT_IMPLEMENTED; 1142 | // if(dolist){ 1143 | // slist *sl; 1144 | // sglist *p; 1145 | // sl=addtxt(NULL,"parameter"); 1146 | // sl=addpar(sl,$3); /* type */ 1147 | // p=$1; 1148 | // for(;;){ 1149 | // sl=addtxt(sl,p->name); 1150 | // sl=addtxt(sl,"="); 1151 | // sl=addsl(sl, $6->sl); /* expr */ 1152 | // sl=addtxt(sl,";\n"); 1153 | // p=p->next; 1154 | // if(p==NULL) break; 1155 | // } 1156 | // $$=addsl(sl,$7); /* rem */ 1157 | // } else { 1158 | // $$=NULL; 1159 | // } 1160 | 1161 | /* 1 2 3 4 5 6 7 8 9 */ 1162 | } | s_list ':' type ':' '=' expr ';' rem genlist { 1163 | NOT_IMPLEMENTED; 1164 | // if(dolist){ 1165 | // slist *sl; 1166 | // sglist *p; 1167 | // sl=addtxt(NULL,"parameter"); 1168 | // sl=addpar(sl,$3); /* type */ 1169 | // p=$1; 1170 | // for(;;){ 1171 | // sl=addtxt(sl,p->name); 1172 | // sl=addtxt(sl,"="); 1173 | // sl=addsl(sl, $6->sl); /* expr */ 1174 | // sl=addtxt(sl,";\n"); 1175 | // p=p->next; 1176 | // if(p==NULL) break; 1177 | // } 1178 | // $$=addsl(sl,$8); /* rem */ 1179 | // $$=addsl(sl,$9); /* genlist */ 1180 | // } else { 1181 | // $$=NULL; 1182 | // } 1183 | 1184 | /* 1 2 3 4 5 6 */ 1185 | } | s_list ':' type ';' rem genlist { 1186 | NOT_IMPLEMENTED; 1187 | // if(dolist){ 1188 | // slist *sl; 1189 | // sglist *p; 1190 | // sl=addtxt(NULL,"parameter"); 1191 | // sl=addpar(sl,$3); /* type */ 1192 | // p=$1; 1193 | // for(;;){ 1194 | // sl=addtxt(sl,p->name); 1195 | // sl=addtxt(sl,";\n"); 1196 | // p=p->next; 1197 | // if(p==NULL) break; 1198 | // } 1199 | // $$=addsl(sl,$5); /* rem */ 1200 | // $$=addsl(sl,$6); /* genlist */ 1201 | // } else { 1202 | // $$=NULL; 1203 | // } 1204 | 1205 | /* 1 2 3 4 */ 1206 | } | s_list ':' type rem { 1207 | NOT_IMPLEMENTED; 1208 | // if(dolist){ 1209 | // slist *sl; 1210 | // sglist *p; 1211 | // sl=addtxt(NULL,"parameter"); 1212 | // sl=addpar(sl,$3); /* type */ 1213 | // p=$1; 1214 | // for(;;){ 1215 | // sl=addtxt(sl,p->name); 1216 | // sl=addtxt(sl,";\n"); 1217 | // p=p->next; 1218 | // if(p==NULL) break; 1219 | // } 1220 | // $$=addsl(sl,$4); /* rem */ 1221 | // } else { 1222 | // $$=NULL; 1223 | // } 1224 | }; 1225 | 1226 | 1227 | /* 1 2 3 4 5 */ 1228 | portlist[portlist_new] : s_list ':' dir type rem { 1229 | $portlist_new = new std::vector; 1230 | for (auto &name: *$s_list) { 1231 | $portlist_new->insert($portlist_new->begin(), make_wire(name, (port_dir_t)$dir, $type)); 1232 | } 1233 | 1234 | // slist *sl; 1235 | 1236 | // if(dolist){ 1237 | // io_list=NULL; 1238 | // sl=setup_port($1,$3,$4); /* modifies io_list global */ 1239 | // $$=addsl(sl,$5); 1240 | // } else{ 1241 | // free($5); 1242 | // free($4); 1243 | // } 1244 | 1245 | /* 1 2 3 4 5 6 7 */ 1246 | } | s_list ':' dir type ';' rem portlist[portlist_orig] { 1247 | $portlist_new = $portlist_orig; 1248 | for (auto &name: *$s_list) { 1249 | $portlist_new->insert($portlist_new->begin(), make_wire(name, (port_dir_t)$dir, $type)); 1250 | } 1251 | // slist *sl; 1252 | 1253 | // if(dolist){ 1254 | // sl=setup_port($1,$3,$4); /* modifies io_list global */ 1255 | // sl=addsl(sl,$6); 1256 | // $$=addsl(sl,$7); 1257 | // } else{ 1258 | // free($6); 1259 | // free($4); 1260 | // } 1261 | /* 1 2 3 4 5 6 7 8 */ 1262 | } | s_list ':' dir type ':' '=' expr rem { 1263 | $portlist_new = new std::vector; 1264 | NOT_IMPLEMENTED; 1265 | // slist *sl; 1266 | // fprintf(stderr,"Warning on line %d: " 1267 | // "port default initialization ignored\n",lineno); 1268 | // if(dolist){ 1269 | // io_list=NULL; 1270 | // sl=setup_port($1,$3,$4); /* modifies io_list global */ 1271 | // $$=addsl(sl,$8); 1272 | // } else{ 1273 | // free($8); 1274 | // free($4); 1275 | // } 1276 | 1277 | /* 1 2 3 4 5 6 7 8 9 10 */ 1278 | } | s_list ':' dir type ':' '=' expr ';' rem portlist[portlist_orig] { 1279 | $portlist_new = $portlist_orig; 1280 | NOT_IMPLEMENTED; 1281 | // slist *sl; 1282 | // fprintf(stderr,"Warning on line %d: " 1283 | // "port default initialization ignored\n",lineno); 1284 | // if(dolist){ 1285 | // sl=setup_port($1,$3,$4); /* modifies io_list global */ 1286 | // sl=addsl(sl,$9); 1287 | // $$=addsl(sl,$10); 1288 | // } else{ 1289 | // free($9); 1290 | // free($4); 1291 | // } 1292 | }; 1293 | 1294 | 1295 | dir : IN { $$ = DIR_IN; } 1296 | | OUT { $$ = DIR_OUT; } 1297 | | INOUT { $$ = DIR_INOUT; } 1298 | ; 1299 | 1300 | 1301 | type : BIT { 1302 | $$=new_vrange(tSCALAR); 1303 | 1304 | } | INTEGER RANGE expr TO expr { 1305 | NOT_IMPLEMENTED; 1306 | // fprintf(stderr,"Warning on line %d: integer range ignored\n",lineno); 1307 | // $$=new_vrange(tSCALAR); 1308 | // $$->nlo = addtxt(NULL,"0"); 1309 | // $$->nhi = addtxt(NULL,"31"); 1310 | 1311 | } | INTEGER { 1312 | NOT_IMPLEMENTED; 1313 | // $$=new_vrange(tSCALAR); 1314 | // $$->nlo = addtxt(NULL,"0"); 1315 | // $$->nhi = addtxt(NULL,"31"); 1316 | 1317 | } | BITVECT '(' vec_range ')' { 1318 | $$ = $3; 1319 | 1320 | } | NAME { 1321 | NOT_IMPLEMENTED; 1322 | // sglist *sg; 1323 | // sg=lookup(type_list,$1); 1324 | // if(sg) 1325 | // $$=sg->range; 1326 | // else{ 1327 | // fprintf(stderr,"Undefined type '%s' on line %d\n",$1,lineno); 1328 | // YYABORT; 1329 | // } 1330 | }; 1331 | 1332 | 1333 | /* using expr instead of simple_expr here makes the grammar ambiguous (why?) */ 1334 | vec_range : simple_expr updown simple_expr { 1335 | $$=new_vrange(tVRANGE); 1336 | $$->nhi=$1->sl; 1337 | $$->nlo=$3->sl; 1338 | $$->sizeval = -1; /* undefined size */ 1339 | /* calculate the width of this vrange */ 1340 | if ($1->op == EXPDATA_TYPE_N && $3->op == EXPDATA_TYPE_N) { 1341 | if ($2==-1) { /* (nhi:natural downto nlo:natural) */ 1342 | $$->sizeval = $1->value - $3->value + 1; 1343 | } else { /* (nhi:natural to nlo:natural) */ 1344 | $$->sizeval = $3->value - $1->value + 1; 1345 | } 1346 | } else { 1347 | /* make an expression to calculate the width of this vrange: 1348 | * create an expression that calculates: 1349 | * size expr = (simple_expr1) - (simple_expr2) + 1 1350 | */ 1351 | expdata *size_expr1 = (expdata*)xmalloc(sizeof(expdata)); 1352 | expdata *size_expr2 = (expdata*)xmalloc(sizeof(expdata)); 1353 | expdata *diff12 = (expdata*)xmalloc(sizeof(expdata)); 1354 | expdata *plusone = (expdata*)xmalloc(sizeof(expdata)); 1355 | expdata *finalexpr = (expdata*)xmalloc(sizeof(expdata)); 1356 | size_expr1->sl = addwrap("(",$1->sl,")"); 1357 | size_expr2->sl = addwrap("(",$3->sl,")"); 1358 | plusone->op=EXPDATA_TYPE_TERMINAL; 1359 | plusone->sl=addtxt(NULL,"1"); 1360 | if ($2==-1) { 1361 | /* (simple_expr1 downto simple_expr1) */ 1362 | diff12 = addexpr(size_expr1,'-',"-",size_expr2); 1363 | } else { 1364 | /* (simple_expr1 to simple_expr1) */ 1365 | diff12 = addexpr(size_expr2,'-',"-",size_expr1); 1366 | } 1367 | finalexpr = addexpr(diff12,'+',"+",plusone); 1368 | finalexpr->sl = addwrap("(",finalexpr->sl,")"); 1369 | $$->size_expr = finalexpr->sl; 1370 | } 1371 | 1372 | } | simple_expr { 1373 | NOT_IMPLEMENTED; 1374 | // $$=new_vrange(tSUBSCRIPT); 1375 | // $$->nlo=$1->sl; 1376 | } | NAME '\'' RANGE { 1377 | NOT_IMPLEMENTED; 1378 | // /* lookup NAME and copy its vrange */ 1379 | // sglist *sg = NULL; 1380 | // if((sg=lookup(io_list,$1))==NULL) { 1381 | // sg=lookup(sig_list,$1); 1382 | // } 1383 | // if(sg) { 1384 | // $$ = sg->range; 1385 | // } else { 1386 | // fprintf(stderr,"Undefined range \"%s'range\" on line %d\n",$1,lineno); 1387 | // YYABORT; 1388 | // } 1389 | }; 1390 | 1391 | 1392 | updown : DOWNTO {$$=-1;} 1393 | | TO {$$=1;} 1394 | ; 1395 | 1396 | /* Architecture */ 1397 | architecture: 1398 | ARCHITECTURE NAME OF NAME IS rem a_decl BEGN doindent a_body END opt_architecture oname ';' unindent { 1399 | printf("architecture, name='%s'\n", $4); 1400 | $architecture = new AstNode(AST_MODULE); 1401 | $architecture->str = $4; 1402 | modules[$4] = $architecture; 1403 | 1404 | for (auto &i: *$a_decl) { 1405 | $architecture->children.push_back(i); 1406 | } 1407 | delete $a_decl; 1408 | 1409 | for (auto &i: *$a_body) { 1410 | $architecture->children.push_back(i); 1411 | } 1412 | delete $a_body; 1413 | }; 1414 | 1415 | /* Extends indentation by one level */ 1416 | doindent : /* Empty */ {indent= indent < MAXINDENT ? indent + 1 : indent;} 1417 | ; 1418 | /* Shorten indentation by one level */ 1419 | unindent : /* Empty */ {indent= indent > 0 ? indent - 1 : indent;} 1420 | 1421 | /* Declarative part of the architecture */ 1422 | a_decl[a_decl_new] : { 1423 | $$ = NULL; 1424 | 1425 | } | a_decl[a_decl_orig] SIGNAL s_list ':' type ';' rem { 1426 | NOT_IMPLEMENTED; 1427 | // sglist *sg; 1428 | // slist *sl; 1429 | // 1430 | // sl=$1; 1431 | // sg=$3; 1432 | // for(;;){ 1433 | // sg->type=wire; 1434 | // sg->range=$5; 1435 | // sl=addptxt(sl,&(sg->type)); 1436 | // sl=addpar(sl,$5); 1437 | // sl=addtxt(sl,sg->name); 1438 | // sl=addpost(sl,$5); 1439 | // sl=addtxt(sl,";"); 1440 | // if(sg->next == NULL) 1441 | // break; 1442 | // sl=addtxt(sl," "); 1443 | // sg=sg->next; 1444 | // } 1445 | // sg->next=sig_list; 1446 | // sig_list=$3; 1447 | // $$=addrem(sl,$7); 1448 | 1449 | } | a_decl[a_decl_orig] SIGNAL s_list ':' type ':' '=' expr ';' rem { 1450 | $a_decl_new = $a_decl_orig; 1451 | if ($a_decl_new == NULL) { 1452 | $a_decl_new = new std::vector; 1453 | } 1454 | for (auto &name: *$s_list) { 1455 | add_wire($a_decl_new, name, DIR_NONE, $type); 1456 | 1457 | struct AstNode *identifier = new AstNode(AST_IDENTIFIER); 1458 | identifier->str = name; 1459 | 1460 | struct AstNode *value = expr_to_ast($expr); 1461 | 1462 | struct AstNode *assign = new AstNode(AST_ASSIGN_LE, identifier, value); 1463 | struct AstNode *initial = new AstNode(AST_INITIAL); 1464 | initial->children.push_back(assign); 1465 | 1466 | $a_decl_new->push_back(initial); 1467 | } 1468 | 1469 | // sglist *sg; 1470 | // slist *sl; 1471 | // 1472 | // sl=$1; 1473 | // sg=$3; 1474 | // for(;;){ 1475 | // sg->type=wire; 1476 | // sg->range=$5; 1477 | // sl=addptxt(sl,&(sg->type)); 1478 | // sl=addpar(sl,$5); 1479 | // sl=addtxt(sl,sg->name); 1480 | // sl=addpost(sl,$5); 1481 | // sl=addtxt(sl," = "); 1482 | // sl=addsl(sl,$8->sl); 1483 | // sl=addtxt(sl,";"); 1484 | // if(sg->next == NULL) 1485 | // break; 1486 | // sl=addtxt(sl," "); 1487 | // sg=sg->next; 1488 | // } 1489 | // sg->next=sig_list; 1490 | // sig_list=$3; 1491 | // $$=addrem(sl,$10); 1492 | 1493 | } | a_decl CONSTANT NAME ':' type ':' '=' expr ';' rem { 1494 | NOT_IMPLEMENTED; 1495 | // slist * sl; 1496 | // sl=addtxt($1,"parameter "); 1497 | // sl=addtxt(sl,$3); 1498 | // sl=addtxt(sl," = "); 1499 | // sl=addsl(sl,$8->sl); 1500 | // sl=addtxt(sl,";"); 1501 | // $$=addrem(sl,$10); 1502 | 1503 | } | a_decl TYPE NAME IS '(' s_list ')' ';' rem { 1504 | NOT_IMPLEMENTED; 1505 | // slist *sl, *sl2; 1506 | // sglist *p; 1507 | // int n,k; 1508 | // n=0; 1509 | // sl=NULL; 1510 | // p=$6; 1511 | // for(;;){ 1512 | // sl=addtxt(sl," "); 1513 | // sl=addtxt(sl,p->name); 1514 | // sl=addtxt(sl," = "); 1515 | // sl=addval(sl,n++); 1516 | // p=p->next; 1517 | // if(p==NULL){ 1518 | // sl=addtxt(sl,";\n"); 1519 | // break; 1520 | // } else 1521 | // sl=addtxt(sl,",\n"); 1522 | // } 1523 | // n--; 1524 | // k=find_msb(n); 1525 | // sl2=addtxt(NULL,"parameter ["); 1526 | // sl2=addval(sl2,k); 1527 | // sl2=addtxt(sl2,":0]\n"); 1528 | // sl=addsl(sl2,sl); 1529 | // sl=addsl($1,sl); 1530 | // $$=addrem(sl,$9); 1531 | // p=(sglist*)xmalloc(sizeof(sglist)); 1532 | // p->name=$3; 1533 | // if(k>0) { 1534 | // p->range=new_vrange(tVRANGE); 1535 | // p->range->sizeval = k+1; 1536 | // p->range->nhi=addval(NULL,k); 1537 | // p->range->nlo=addtxt(NULL,"0"); 1538 | // } else { 1539 | // p->range=new_vrange(tSCALAR); 1540 | // } 1541 | // p->next=type_list; 1542 | // type_list=p; 1543 | 1544 | } | a_decl TYPE NAME IS ARRAY '(' vec_range ')' OF type ';' rem { 1545 | NOT_IMPLEMENTED; 1546 | // slist *sl=NULL; 1547 | // sglist *p; 1548 | // $$=addrem(sl,$12); 1549 | // p=(sglist*)xmalloc(sizeof(sglist)); 1550 | // p->name=$3; 1551 | // p->range=$10; 1552 | // p->range->xhi=$7->nhi; 1553 | // p->range->xlo=$7->nlo; 1554 | // p->next=type_list; 1555 | // type_list=p; 1556 | 1557 | /* 1 2 3 4 5r1 6 7 8 9r2 10 11 12 13r3 14 15 16 17 18 19r4 */ 1558 | } | a_decl COMPONENT NAME opt_is rem opt_generic PORT nolist '(' rem portlist ')' ';' rem END COMPONENT oname ';' yeslist rem { 1559 | NOT_IMPLEMENTED; 1560 | // $$=addsl($1,$20); /* a_decl, rem4 */ 1561 | // free($3); /* NAME */ 1562 | // free($10); /* rem2 */ 1563 | // free($14);/* rem3 */ 1564 | }; 1565 | 1566 | opt_generic : /* Empty */ { 1567 | NOT_IMPLEMENTED; 1568 | // $$=NULL; 1569 | } | GENERIC nolist '(' rem genlist ')' ';' rem { 1570 | NOT_IMPLEMENTED; 1571 | // if (0) fprintf(stderr,"matched opt_generic\n"); 1572 | // free($4); /* rem */ 1573 | // free($8); /* rem */ 1574 | // $$=NULL; 1575 | }; 1576 | 1577 | nolist : /*Empty*/ { 1578 | NOT_IMPLEMENTED; 1579 | dolist = 0; 1580 | } 1581 | 1582 | yeslist : /*Empty*/ { 1583 | NOT_IMPLEMENTED; 1584 | // dolist = 1; 1585 | } 1586 | 1587 | /* XXX wishlist: record comments into slist, play them back later */ 1588 | s_list[s_list_new] : NAME rem { 1589 | $s_list_new = new std::vector; 1590 | $s_list_new->push_back($NAME); 1591 | 1592 | // sglist * sg; 1593 | // if(dolist){ 1594 | // sg=(sglist*)xmalloc(sizeof(sglist)); 1595 | // sg->name=$1; 1596 | // sg->next=NULL; 1597 | // $$=sg; 1598 | // } else{ 1599 | // free($1); 1600 | // $$=NULL; 1601 | // } 1602 | // free($2); 1603 | } | NAME ',' rem s_list[s_list_orig] { 1604 | $s_list_new = $s_list_orig; 1605 | $s_list_new->push_back($NAME); 1606 | 1607 | // sglist * sg; 1608 | // if(dolist){ 1609 | // sg=(sglist*)xmalloc(sizeof(sglist)); 1610 | // sg->name=$1; 1611 | // sg->next=$4; 1612 | // $$=sg; 1613 | // } else{ 1614 | // free($1); 1615 | // $$=NULL; 1616 | // } 1617 | // free($3); 1618 | }; 1619 | 1620 | a_body[a_body_new] : rem { 1621 | // $$=addind($1); 1622 | 1623 | /* 1 2 3 4 5 6 7 8 9 */ 1624 | } | rem signal '<' '=' rem norem sigvalue yesrem a_body[a_body_orig] { 1625 | $a_body_new = $a_body_orig; 1626 | if ($a_body_new == NULL) { 1627 | $a_body_new = new std::vector; 1628 | } 1629 | struct AstNode *assign = new AstNode(AST_ASSIGN, $signal, expr_to_ast($sigvalue)); 1630 | $a_body_new->insert($a_body_new->begin(), assign); 1631 | // slist *sl; 1632 | // sl=addsl($1,indents[indent]); 1633 | // sl=addtxt(sl,"assign "); 1634 | // sl=addsl(sl,$2->sl); 1635 | // findothers($2,$7); 1636 | // free($2); 1637 | // sl=addtxt(sl," = "); 1638 | // sl=addsl(sl,$7); 1639 | // sl=addtxt(sl,";\n"); 1640 | // $$=addsl(sl,$9); 1641 | 1642 | } | rem BEGN signal '<' '=' rem norem sigvalue yesrem a_body[a_body_orig] END NAME ';' { 1643 | NOT_IMPLEMENTED; 1644 | // slist *sl; 1645 | // sl=addsl($1,indents[indent]); 1646 | // sl=addtxt(sl,"assign "); 1647 | // sl=addsl(sl,$3->sl); 1648 | // findothers($3,$8); 1649 | // free($3); 1650 | // sl=addtxt(sl," = "); 1651 | // sl=addsl(sl,$8); 1652 | // sl=addtxt(sl,";\n"); 1653 | // $$=addsl(sl,$10); 1654 | 1655 | /* 1 2 3 4 5 6 7 8 9 10 11 */ 1656 | } | rem WITH expr SELECT rem yeswith signal '<' '=' with_list a_body[a_body_orig] { 1657 | NOT_IMPLEMENTED; 1658 | // slist *sl; 1659 | // sglist *sg; 1660 | // char *s; 1661 | // sl=addsl($1,indents[indent]); 1662 | // sl=addtxt(sl,"always @(*) begin\n"); 1663 | // sl=addsl(sl,indents[indent]); 1664 | // sl=addtxt(sl," case("); 1665 | // sl=addsl(sl,$3->sl); 1666 | // free($3); 1667 | // sl=addtxt(sl,")\n"); 1668 | // if($5) 1669 | // sl=addsl(sl,$5); 1670 | // s=sbottom($7->sl); 1671 | // if((sg=lookup(io_list,s))==NULL) 1672 | // sg=lookup(sig_list,s); 1673 | // if(sg) 1674 | // sg->type=reg; 1675 | // findothers($7,$10); 1676 | // free($7); 1677 | // sl=addsl(sl,$10); 1678 | // sl=addsl(sl,indents[indent]); 1679 | // sl=addtxt(sl," endcase\n"); 1680 | // sl=addsl(sl,indents[indent]); 1681 | // sl=addtxt(sl,"end\n\n"); 1682 | // $$=addsl(sl,$11); 1683 | 1684 | /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ 1685 | } | rem NAME ':' NAME rem PORT MAP '(' doindent map_list rem ')' ';' unindent a_body[a_body_orig] { 1686 | NOT_IMPLEMENTED; 1687 | // slist *sl; 1688 | // sl=addsl($1,indents[indent]); 1689 | // sl=addtxt(sl,$4); /* NAME2 */ 1690 | // sl=addtxt(sl," "); 1691 | // sl=addtxt(sl,$2); /* NAME1 */ 1692 | // sl=addtxt(sl,"(\n"); 1693 | // sl=addsl(sl,indents[indent]); 1694 | // sl=addsl(sl,$10); /* map_list */ 1695 | // sl=addtxt(sl,");\n\n"); 1696 | // $$=addsl(sl,$15); /* a_body */ 1697 | 1698 | /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 */ 1699 | } | rem NAME ':' NAME rem GENERIC MAP '(' doindent generic_map_list ')' unindent PORT MAP '(' doindent map_list ')' ';' unindent a_body[a_body_orig] { 1700 | NOT_IMPLEMENTED; 1701 | // slist *sl; 1702 | // sl=addsl($1,indents[indent]); 1703 | // sl=addtxt(sl,$4); /* NAME2 (component name) */ 1704 | // if ($5) { 1705 | // sl=addsl(sl,$5); 1706 | // sl=addsl(sl,indents[indent]); 1707 | // } 1708 | // sl=addtxt(sl," #(\n"); 1709 | // sl=addsl(sl,indents[indent]); 1710 | // sl=addsl(sl,$10); /* (generic) map_list */ 1711 | // sl=addtxt(sl,")\n"); 1712 | // sl=addsl(sl,indents[indent]); 1713 | // sl=addtxt(sl,$2); /* NAME1 (instance name) */ 1714 | // sl=addtxt(sl,"(\n"); 1715 | // sl=addsl(sl,indents[indent]); 1716 | // sl=addsl(sl,$17); /* map_list */ 1717 | // sl=addtxt(sl,");\n\n"); 1718 | // $$=addsl(sl,$21); /* a_body */ 1719 | 1720 | } | optname PROCESS '(' sign_list ')' p_decl opt_is BEGN doindent p_body END PROCESS oname ';' unindent a_body[a_body_orig] { 1721 | log_assert($p_body != NULL); 1722 | log_assert($p_body->type == AST_BLOCK); 1723 | $a_body_new = $a_body_orig; 1724 | if ($a_body_new == NULL) { 1725 | $a_body_new = new std::vector; 1726 | } 1727 | AstNode *always = new AstNode(AST_ALWAYS); 1728 | for (auto &i: *$sign_list) { 1729 | AstNode *edge = new AstNode(AST_EDGE); 1730 | edge->children.push_back(i); 1731 | always->children.push_back(edge); 1732 | } 1733 | always->children.push_back($p_body); 1734 | $a_body_new->insert($a_body_new->begin(), always); 1735 | 1736 | } | optname PROCESS '(' sign_list ')' p_decl opt_is BEGN doindent rem IF edge THEN p_body END IF ';' END PROCESS oname ';' unindent a_body[a_body_orig] { 1737 | log_assert($p_body != NULL); 1738 | log_assert($p_body->type == AST_BLOCK); 1739 | 1740 | // FIXME: the sign_list is ignored, that's probably not right 1741 | 1742 | $a_body_new = $a_body_orig; 1743 | if ($a_body_new == NULL) { 1744 | $a_body_new = new std::vector; 1745 | } 1746 | AstNode *always = new AstNode(AST_ALWAYS, $edge, $p_body); 1747 | $a_body_new->insert($a_body_new->begin(), always); 1748 | 1749 | // slist *sl; 1750 | // if (0) fprintf(stderr,"process style 2: if then end if\n"); 1751 | // sl=add_always($1,$4,$6,1); 1752 | // if($10){ 1753 | // sl=addsl(sl,indents[indent]); 1754 | // sl=addsl(sl,$10); 1755 | // } 1756 | // sl=addsl(sl,$14); 1757 | // sl=addsl(sl,indents[indent]); 1758 | // sl=addtxt(sl,"end\n\n"); 1759 | // $$=addsl(sl,$23); 1760 | 1761 | /* 1 2 3 4 5 6 7 8 9 */ 1762 | } | optname PROCESS '(' sign_list ')' p_decl opt_is BEGN doindent 1763 | /* 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 */ 1764 | rem IF exprc THEN doindent p_body[p_body_if] unindent ELSIF edge THEN doindent p_body[p_body_elseif] unindent END IF ';' 1765 | /* 26 27 28 29 30 31 */ 1766 | END PROCESS oname ';' unindent a_body[a_body_orig] { 1767 | log_assert(($p_body_if != NULL) && ($p_body_if->type == AST_BLOCK)); 1768 | log_assert(($p_body_elseif != NULL) && ($p_body_elseif->type == AST_BLOCK)); 1769 | NOT_IMPLEMENTED; 1770 | // slist *sl; 1771 | // if (0) fprintf(stderr,"process style 3: if then elsif then end if\n"); 1772 | // sl=add_always($1,$4,$6,1); 1773 | // if($10){ 1774 | // sl=addsl(sl,indents[indent]); 1775 | // sl=addsl(sl,$10); 1776 | // } 1777 | // sl=addsl(sl,indents[indent]); 1778 | // sl=addtxt(sl," if("); 1779 | // sl=addsl(sl,$12); 1780 | // sl=addtxt(sl,") begin\n"); 1781 | // sl=addsl(sl,$15); 1782 | // sl=addsl(sl,indents[indent]); 1783 | // sl=addtxt(sl," end else begin\n"); 1784 | // sl=addsl(sl,$21); 1785 | // sl=addsl(sl,indents[indent]); 1786 | // sl=addtxt(sl," end\n"); 1787 | // sl=addsl(sl,indents[indent]); 1788 | // sl=addtxt(sl,"end\n\n"); 1789 | // $$=addsl(sl,$31); 1790 | 1791 | /* 1 2 3 4 5 6 7 8 9 */ 1792 | } | optname PROCESS '(' sign_list ')' p_decl opt_is BEGN doindent 1793 | /* 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 */ 1794 | rem IF exprc THEN doindent p_body[p_body_if] unindent ELSE IF edge THEN doindent p_body[p_body_elseif] unindent END IF ';' END IF ';' 1795 | /* 30 31 32 33 34 35 */ 1796 | END PROCESS oname ';' unindent a_body[a_body_orig] { 1797 | log_assert(($p_body_if == NULL) || ($p_body_if->type == AST_BLOCK)); 1798 | log_assert(($p_body_elseif == NULL) || ($p_body_elseif->type == AST_BLOCK)); 1799 | NOT_IMPLEMENTED; 1800 | // slist *sl; 1801 | // if (0) fprintf(stderr,"process style 4: if then else if then end if\n"); 1802 | // sl=add_always($1,$4,$6,1); 1803 | // if($10){ 1804 | // sl=addsl(sl,indents[indent]); 1805 | // sl=addsl(sl,$10); 1806 | // } 1807 | // sl=addsl(sl,indents[indent]); 1808 | // sl=addtxt(sl," if("); 1809 | // sl=addsl(sl,$12); /* exprc */ 1810 | // sl=addtxt(sl,") begin\n"); 1811 | // sl=addsl(sl,$15); /* p_body:1 */ 1812 | // sl=addsl(sl,indents[indent]); 1813 | // sl=addtxt(sl," end else begin\n"); 1814 | // sl=addsl(sl,$22); /* p_body:2 */ 1815 | // sl=addsl(sl,indents[indent]); 1816 | // sl=addtxt(sl," end\n"); 1817 | // sl=addsl(sl,indents[indent]); 1818 | // sl=addtxt(sl,"end\n\n"); 1819 | // $$=addsl(sl,$35); /* a_body */ 1820 | 1821 | /* note vhdl does not allow an else in an if generate statement */ 1822 | /* 1 2 3 4 5 6 7 8 9 10 11 12 */ 1823 | } | gen_optname IF exprc generate doindent a_body[a_body_orig1] unindent endgenerate oname ';' a_body[a_body_orig2] { 1824 | NOT_IMPLEMENTED; 1825 | // slist *sl; 1826 | // blknamelist *tname_list; 1827 | // sl=addsl($1,indents[indent]); 1828 | // sl=addtxt(sl,"generate "); 1829 | // sl=addtxt(sl,"if ("); 1830 | // sl=addsl(sl,$3); /* exprc */ 1831 | // sl=addtxt(sl,") begin: "); 1832 | // tname_list=blkname_list; 1833 | // sl=addtxt(sl,tname_list->name); 1834 | // blkname_list=blkname_list->next; 1835 | // if (tname_list!=NULL) { 1836 | // free(tname_list->name); 1837 | // free(tname_list); 1838 | // } 1839 | // sl=addtxt(sl,"\n"); 1840 | // sl=addsl(sl,indents[indent]); 1841 | // sl=addsl(sl,$6); /* a_body:1 */ 1842 | // sl=addsl(sl,indents[indent]); 1843 | // sl=addtxt(sl,"end\n"); 1844 | // sl=addsl(sl,indents[indent]); 1845 | // sl=addtxt(sl,"endgenerate\n"); 1846 | // $$=addsl(sl,$11); /* a_body:2 */ 1847 | 1848 | /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ 1849 | } | gen_optname FOR signal IN expr TO expr generate doindent a_body[a_body_orig1] unindent endgenerate oname ';' a_body[a_body_orig2] { 1850 | NOT_IMPLEMENTED; 1851 | // slist *sl; 1852 | // blknamelist *tname_list; 1853 | // sl=addsl($1,indents[indent]); 1854 | // sl=addtxt(sl,"genvar "); 1855 | // sl=addsl(sl,$3->sl); /* signal */ 1856 | // sl=addtxt(sl,";\n"); 1857 | // sl=addsl(sl,indents[indent]); 1858 | // sl=addtxt(sl,"generate "); 1859 | // sl=addtxt(sl,"for ("); 1860 | // sl=addsl(sl,$3->sl); /* signal */ 1861 | // sl=addtxt(sl,"="); 1862 | // sl=addsl(sl,$5->sl); /* expr:1 */ 1863 | // sl=addtxt(sl,"; "); 1864 | // sl=addsl(sl,$3->sl); /* signal */ 1865 | // sl=addtxt(sl," <= "); 1866 | // sl=addsl(sl,$7->sl); /* expr:2 */ 1867 | // sl=addtxt(sl,"; "); 1868 | // sl=addsl(sl,$3->sl); /* signal */ 1869 | // sl=addtxt(sl," = "); 1870 | // sl=addsl(sl,$3->sl); /* signal */ 1871 | // sl=addtxt(sl," + 1) begin: "); 1872 | // tname_list=blkname_list; 1873 | // sl=addtxt(sl,tname_list->name); 1874 | // blkname_list=blkname_list->next; 1875 | // if (tname_list!=NULL) { 1876 | // free(tname_list->name); 1877 | // free(tname_list); 1878 | // } 1879 | // sl=addtxt(sl,"\n"); 1880 | // sl=addsl(sl,indents[indent]); 1881 | // sl=addsl(sl,$10); /* a_body:1 */ 1882 | // sl=addsl(sl,indents[indent]); 1883 | // sl=addtxt(sl,"end\n"); 1884 | // sl=addsl(sl,indents[indent]); 1885 | // sl=addtxt(sl,"endgenerate\n"); 1886 | // $$=addsl(sl,$15); /* a_body:2 */ 1887 | 1888 | /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ 1889 | } | gen_optname FOR signal IN expr DOWNTO expr generate doindent a_body[a_body_orig1] unindent endgenerate oname ';' a_body[a_body_orig2] { 1890 | NOT_IMPLEMENTED; 1891 | // slist *sl; 1892 | // blknamelist* tname_list; 1893 | // sl=addsl($1,indents[indent]); 1894 | // sl=addtxt(sl,"genvar "); 1895 | // sl=addsl(sl,$3->sl); /* signal */ 1896 | // sl=addtxt(sl,";\n"); 1897 | // sl=addsl(sl,indents[indent]); 1898 | // sl=addtxt(sl,"generate "); 1899 | // sl=addtxt(sl,"for ("); 1900 | // sl=addsl(sl,$3->sl); /* signal */ 1901 | // sl=addtxt(sl,"="); 1902 | // sl=addsl(sl,$5->sl); /* expr:1 */ 1903 | // sl=addtxt(sl,"; "); 1904 | // sl=addsl(sl,$3->sl); /* signal */ 1905 | // sl=addtxt(sl," >= "); 1906 | // sl=addsl(sl,$7->sl); /* expr:2 */ 1907 | // sl=addtxt(sl,"; "); 1908 | // sl=addsl(sl,$3->sl); /* signal */ 1909 | // sl=addtxt(sl," = "); 1910 | // sl=addsl(sl,$3->sl); /* signal */ 1911 | // sl=addtxt(sl," - 1) begin: "); 1912 | // tname_list=blkname_list; 1913 | // sl=addtxt(sl,tname_list->name); 1914 | // blkname_list=blkname_list->next; 1915 | // if (tname_list!=NULL) { 1916 | // free(tname_list->name); 1917 | // free(tname_list); 1918 | // } 1919 | // sl=addtxt(sl,"\n"); 1920 | // sl=addsl(sl,$10); /* a_body:1 */ 1921 | // sl=addsl(sl,indents[indent]); 1922 | // sl=addtxt(sl,"end\n"); 1923 | // sl=addsl(sl,indents[indent]); 1924 | // sl=addtxt(sl,"endgenerate\n"); 1925 | // $$=addsl(sl,$15); /* a_body:2 */ 1926 | }; 1927 | 1928 | oname : { 1929 | $$=NULL; 1930 | } | NAME { 1931 | // FIXME: must match the matching name 1932 | free($1); 1933 | $$=NULL; 1934 | }; 1935 | 1936 | optname : rem { 1937 | $$ = NULL; 1938 | 1939 | } | rem NAME ':' { 1940 | NOT_IMPLEMENTED; 1941 | // $$=$1; 1942 | // free($2); 1943 | } 1944 | 1945 | gen_optname : rem { 1946 | NOT_IMPLEMENTED; 1947 | // $$=$1; 1948 | 1949 | } | rem NAME ':' { 1950 | NOT_IMPLEMENTED; 1951 | // blknamelist *tname_list; 1952 | // tname_list = (blknamelist*)xmalloc (sizeof(blknamelist)); 1953 | // tname_list->name = (char*)xmalloc(strlen($2)); 1954 | // strcpy(tname_list->name, $2); 1955 | // tname_list->next = blkname_list; 1956 | // blkname_list=tname_list; 1957 | // $$=$1; 1958 | // free($2); 1959 | }; 1960 | 1961 | edge : '(' edge ')' { 1962 | NOT_IMPLEMENTED; 1963 | // $$ = $2; 1964 | // $$=addwrap("(",$2,")"); 1965 | 1966 | } | NAME '\'' EVENT AND exprc { 1967 | NOT_IMPLEMENTED; 1968 | // push_clkedge($5->data.sl->data.txt[0]-'0', "name'event and exprc"); 1969 | 1970 | } | exprc AND NAME '\'' EVENT { 1971 | NOT_IMPLEMENTED; 1972 | // push_clkedge($1->data.sl->data.txt[0]-'0', "exprc and name'event"); 1973 | 1974 | } | POSEDGE '(' NAME ')' { 1975 | AstNode *id = new AstNode(AST_IDENTIFIER); 1976 | id->str = $NAME; 1977 | 1978 | AstNode *edge = new AstNode(AST_POSEDGE); 1979 | edge->children.push_back(id); 1980 | 1981 | $$ = edge; 1982 | 1983 | // push_clkedge(1, "explicit"); 1984 | 1985 | } | NEGEDGE '(' NAME ')' { 1986 | NOT_IMPLEMENTED; 1987 | // AstNode *always = new AstNode(AST_ALWAYS); 1988 | // push_clkedge(0, "explicit"); 1989 | }; 1990 | 1991 | yeswith : { 1992 | NOT_IMPLEMENTED; 1993 | // dowith=1; 1994 | } 1995 | 1996 | with_list : with_item ';' { 1997 | NOT_IMPLEMENTED; 1998 | // $$=$1; 1999 | } | with_item ',' rem with_list { 2000 | NOT_IMPLEMENTED; 2001 | // slist *sl; 2002 | // if($3){ 2003 | // sl=addsl($1,$3); 2004 | // $$=addsl(sl,$4); 2005 | // } else 2006 | // $$=addsl($1,$4); 2007 | 2008 | } | expr delay WHEN OTHERS ';' { 2009 | NOT_IMPLEMENTED; 2010 | // slist *sl; 2011 | // sl=addtxt(indents[indent]," default : "); 2012 | // sl=addsl(sl,slwith); 2013 | // sl=addtxt(sl," <= "); 2014 | // if(delay && $2){ 2015 | // sl=addtxt(sl,"# "); 2016 | // sl=addval(sl,$2); 2017 | // sl=addtxt(sl," "); 2018 | // } 2019 | // if($1->op == 'c') 2020 | // sl=addsl(sl,addwrap("{",$1->sl,"}")); 2021 | // else 2022 | // sl=addsl(sl,$1->sl); 2023 | // free($1); 2024 | // delay=1; 2025 | // $$=addtxt(sl,";\n"); 2026 | } 2027 | 2028 | with_item : expr delay WHEN wlist { 2029 | NOT_IMPLEMENTED; 2030 | // slist *sl; 2031 | // sl=addtxt(indents[indent]," "); 2032 | // sl=addsl(sl,$4); 2033 | // sl=addtxt(sl," : "); 2034 | // sl=addsl(sl,slwith); 2035 | // sl=addtxt(sl," <= "); 2036 | // if(delay && $2){ 2037 | // sl=addtxt(sl,"# "); 2038 | // sl=addval(sl,$2); 2039 | // sl=addtxt(sl," "); 2040 | // } 2041 | // if($1->op == 'c') 2042 | // sl=addsl(sl,addwrap("{",$1->sl,"}")); 2043 | // else 2044 | // sl=addsl(sl,$1->sl); 2045 | // free($1); 2046 | // delay=1; 2047 | // $$=addtxt(sl,";\n"); 2048 | } 2049 | 2050 | p_decl : rem { 2051 | $$ = NULL; 2052 | 2053 | } | rem VARIABLE s_list ':' type ';' p_decl { 2054 | NOT_IMPLEMENTED; 2055 | // slist *sl; 2056 | // sglist *sg, *p; 2057 | // sl=addtxt($1," reg"); 2058 | // sl=addpar(sl,$5); 2059 | // free($5); 2060 | // sg=$3; 2061 | // for(;;){ 2062 | // sl=addtxt(sl,sg->name); 2063 | // p=sg; 2064 | // sg=sg->next; 2065 | // free(p); 2066 | // if(sg) 2067 | // sl=addtxt(sl,", "); 2068 | // else 2069 | // break; 2070 | // } 2071 | // sl=addtxt(sl,";\n"); 2072 | // $$=addsl(sl,$7); 2073 | 2074 | } | rem VARIABLE s_list ':' type ':' '=' expr ';' p_decl { 2075 | NOT_IMPLEMENTED; 2076 | // slist *sl; 2077 | // sglist *sg, *p; 2078 | // sl=addtxt($1," reg"); 2079 | // sl=addpar(sl,$5); 2080 | // free($5); 2081 | // sg=$3; 2082 | // for(;;){ 2083 | // sl=addtxt(sl,sg->name); 2084 | // p=sg; 2085 | // sg=sg->next; 2086 | // free(p); 2087 | // if(sg) 2088 | // sl=addtxt(sl,", "); 2089 | // else 2090 | // break; 2091 | // } 2092 | // sl=addtxt(sl," = "); 2093 | // sl=addsl(sl,$8->sl); 2094 | // sl=addtxt(sl,";\n"); 2095 | // $$=addsl(sl,$10); 2096 | }; 2097 | 2098 | 2099 | p_body[p_body_result] : rem { 2100 | $$ = NULL; 2101 | /* 1 2 3 4 5 6 7 8 9 */ 2102 | } | rem signal ':' '=' norem expr ';' yesrem p_body[p_body_orig] { 2103 | log_assert(($p_body_orig == NULL) || ($p_body_orig->type == AST_BLOCK)); 2104 | NOT_IMPLEMENTED; 2105 | // slist *sl; 2106 | // sl=addsl($1,indents[indent]); 2107 | // sl=addsl(sl,$2->sl); 2108 | // findothers($2,$6->sl); 2109 | // sl=addtxt(sl," = "); 2110 | // if($6->op == 'c') 2111 | // sl=addsl(sl,addwrap("{",$6->sl,"}")); 2112 | // else 2113 | // sl=addsl(sl,$6->sl); 2114 | // sl=addtxt(sl,";\n"); 2115 | // $$=addsl(sl,$9); 2116 | /* 1 2 3 4 5 6 7 8 */ 2117 | } | rem signal norem '<' '=' sigvalue yesrem p_body[p_body_orig] { 2118 | log_assert(($p_body_orig == NULL) || ($p_body_orig->type == AST_BLOCK)); 2119 | log_assert($sigvalue->op == EXPDATA_TYPE_AST); 2120 | AstNode *n = new AstNode(AST_ASSIGN_LE, $signal, $sigvalue->node); 2121 | if ($p_body_orig == NULL) { 2122 | $p_body_orig = new AstNode(AST_BLOCK); 2123 | } 2124 | $p_body_orig->children.insert($p_body_orig->children.begin(), n); 2125 | free($sigvalue); 2126 | $p_body_result = $p_body_orig; 2127 | 2128 | 2129 | /* 1 2 3 4 5 6:1 7 8 9 10 11 12:2 */ 2130 | } | rem IF exprc THEN doindent p_body[p_body_if] unindent elsepart END IF ';' p_body[p_body_orig] { 2131 | log_assert($p_body_if != NULL); 2132 | log_assert($p_body_if->type == AST_BLOCK); 2133 | log_assert(($p_body_orig == NULL) || ($p_body_orig->type == AST_BLOCK)); 2134 | log_assert($exprc != NULL); 2135 | 2136 | $p_body_result = $p_body_orig; 2137 | if ($p_body_result == NULL) { 2138 | $p_body_result = new AstNode(AST_BLOCK); 2139 | } 2140 | 2141 | AstNode *reduce; 2142 | if ($exprc->type == AST_REDUCE_BOOL) { 2143 | reduce = $exprc; 2144 | } else { 2145 | reduce = new AstNode(AST_REDUCE_BOOL); 2146 | reduce->children.push_back($exprc); 2147 | } 2148 | 2149 | AstNode *case_node = new AstNode(AST_CASE); 2150 | case_node->children.push_back(reduce); 2151 | 2152 | AstNode *true_const; 2153 | true_const = AstNode::mkconst_int(1, false); 2154 | AstNode *if_cond = new AstNode(AST_COND, true_const, $p_body_if); 2155 | 2156 | case_node->children.push_back(if_cond); 2157 | 2158 | if ($elsepart != NULL) { 2159 | for (auto &i: *$elsepart) { 2160 | log_assert(i->type == AST_COND); 2161 | case_node->children.push_back(i); 2162 | } 2163 | } 2164 | 2165 | $p_body_result->children.insert($p_body_result->children.begin(), case_node); 2166 | 2167 | // slist *sl; 2168 | // sl=addsl($1,indents[indent]); 2169 | // sl=addtxt(sl,"if("); 2170 | // sl=addsl(sl,$3); 2171 | // sl=addtxt(sl,") begin\n"); 2172 | // sl=addsl(sl,$6); 2173 | // sl=addsl(sl,indents[indent]); 2174 | // sl=addtxt(sl,"end\n"); 2175 | // sl=addsl(sl,$8); 2176 | // $$=addsl(sl,$12); 2177 | /* 1 2 3 4 5:1 6 7:2 8 9 10:1 11 12 13 14 15:2 */ 2178 | } | rem FOR signal IN expr TO expr LOOP doindent p_body[p_body_internal] unindent END LOOP ';' p_body[p_body_orig] { 2179 | log_assert(($p_body_internal == NULL) || ($p_body_internal->type == AST_BLOCK)); 2180 | log_assert(($p_body_orig == NULL) || ($p_body_orig->type == AST_BLOCK)); 2181 | NOT_IMPLEMENTED; 2182 | // slist *sl; 2183 | // sl=addsl($1,indents[indent]); 2184 | // sl=addtxt(sl,"for ("); 2185 | // sl=addsl(sl,$3->sl); /* signal */ 2186 | // sl=addtxt(sl,"="); 2187 | // sl=addsl(sl,$5->sl); /* expr:1 */ 2188 | // sl=addtxt(sl,"; "); 2189 | // sl=addsl(sl,$3->sl); /* signal */ 2190 | // sl=addtxt(sl," <= "); 2191 | // sl=addsl(sl,$7->sl); /* expr:2 */ 2192 | // sl=addtxt(sl,"; "); 2193 | // sl=addsl(sl,$3->sl); /* signal */ 2194 | // sl=addtxt(sl," = "); 2195 | // sl=addsl(sl,$3->sl); /* signal */ 2196 | // sl=addtxt(sl," + 1) begin\n"); 2197 | // sl=addsl(sl,$10); /* p_body:1 */ 2198 | // sl=addsl(sl,indents[indent]); 2199 | // sl=addtxt(sl,"end\n"); 2200 | // $$=addsl(sl,$15); /* p_body:2 */ 2201 | /* 1 2 3 4 5:1 6 7:2 8 9 10:1 11 12 13 14 15:2 */ 2202 | } | rem FOR signal IN expr DOWNTO expr LOOP doindent p_body[p_body_internal] unindent END LOOP ';' p_body[p_body_orig] { 2203 | log_assert(($p_body_internal == NULL) || ($p_body_internal->type == AST_BLOCK)); 2204 | log_assert(($p_body_orig == NULL) || ($p_body_orig->type == AST_BLOCK)); 2205 | NOT_IMPLEMENTED; 2206 | // slist *sl; 2207 | // sl=addsl($1,indents[indent]); 2208 | // sl=addtxt(sl,"for ("); 2209 | // sl=addsl(sl,$3->sl); /* signal */ 2210 | // sl=addtxt(sl,"="); 2211 | // sl=addsl(sl,$5->sl); /* expr:1 */ 2212 | // sl=addtxt(sl,"; "); 2213 | // sl=addsl(sl,$3->sl); /* signal */ 2214 | // sl=addtxt(sl," >= "); 2215 | // sl=addsl(sl,$7->sl); /* expr:2 */ 2216 | // sl=addtxt(sl,"; "); 2217 | // sl=addsl(sl,$3->sl); /* signal */ 2218 | // sl=addtxt(sl," = "); 2219 | // sl=addsl(sl,$3->sl); /* signal */ 2220 | // sl=addtxt(sl," - 1) begin\n"); 2221 | // sl=addsl(sl,$10); /* p_body:1 */ 2222 | // sl=addsl(sl,indents[indent]); 2223 | // sl=addtxt(sl,"end\n"); 2224 | // $$=addsl(sl,$15); /* p_body:2 */ 2225 | /* 1 2 3 4 5 6 7 8 9 10 */ 2226 | } | rem CASE signal IS rem cases END CASE ';' p_body[p_body_orig] { 2227 | log_assert(($p_body_orig == NULL) || ($p_body_orig->type == AST_BLOCK)); 2228 | NOT_IMPLEMENTED; 2229 | // slist *sl; 2230 | // sl=addsl($1,indents[indent]); 2231 | // sl=addtxt(sl,"case("); 2232 | // sl=addsl(sl,$3->sl); /* signal */ 2233 | // sl=addtxt(sl,")\n"); 2234 | // if($5){ 2235 | // sl=addsl(sl,indents[indent]); 2236 | // sl=addsl(sl,$5); 2237 | // } 2238 | // sl=addsl(sl,$6); 2239 | // sl=addsl(sl,indents[indent]); 2240 | // sl=addtxt(sl,"endcase\n"); 2241 | // $$=addsl(sl,$10); 2242 | } | rem EXIT ';' p_body[p_body_orig] { 2243 | log_assert(($p_body_orig == NULL) || ($p_body_orig->type == AST_BLOCK)); 2244 | NOT_IMPLEMENTED; 2245 | // slist *sl; 2246 | // sl=addsl($1,indents[indent]); 2247 | // sl=addtxt(sl,"disable; //VHD2VL: add block name here\n"); 2248 | // $$=addsl(sl,$4); 2249 | } | rem NULLV ';' p_body[p_body_orig] { 2250 | log_assert(($p_body_orig == NULL) || ($p_body_orig->type == AST_BLOCK)); 2251 | NOT_IMPLEMENTED; 2252 | // slist *sl; 2253 | // if($1){ 2254 | // sl=addsl($1,indents[indent]); 2255 | // $$=addsl(sl,$4); 2256 | // }else 2257 | // $$=$4; 2258 | }; 2259 | 2260 | 2261 | elsepart[elsepart_new] : { 2262 | $$=NULL; 2263 | 2264 | } | ELSIF exprc THEN doindent p_body unindent elsepart[elsepart_orig] { 2265 | log_assert(($p_body == NULL) || ($p_body->type == AST_BLOCK)); 2266 | $elsepart_new = $elsepart_orig; 2267 | NOT_IMPLEMENTED; 2268 | // slist *sl; 2269 | // sl=addtxt(indents[indent],"else if("); 2270 | // sl=addsl(sl,$2); 2271 | // sl=addtxt(sl,") begin\n"); 2272 | // sl=addsl(sl,$5); 2273 | // sl=addsl(sl,indents[indent]); 2274 | // sl=addtxt(sl,"end\n"); 2275 | // $$=addsl(sl,$7); 2276 | 2277 | } | ELSE doindent p_body unindent { 2278 | log_assert($p_body != NULL); 2279 | log_assert($p_body->type == AST_BLOCK); 2280 | AstNode *default_const = new AstNode(AST_DEFAULT); 2281 | AstNode *else_cond = new AstNode(AST_COND, default_const, $p_body); 2282 | $elsepart_new = new std::vector; 2283 | $elsepart_new->push_back(else_cond); 2284 | }; 2285 | 2286 | 2287 | cases : WHEN wlist '=' '>' doindent p_body unindent cases { 2288 | log_assert(($p_body == NULL) || ($p_body->type == AST_BLOCK)); 2289 | NOT_IMPLEMENTED; 2290 | // slist *sl; 2291 | // sl=addsl(indents[indent],$2); 2292 | // sl=addtxt(sl," : begin\n"); 2293 | // sl=addsl(sl,$6); 2294 | // sl=addsl(sl,indents[indent]); 2295 | // sl=addtxt(sl,"end\n"); 2296 | // $$=addsl(sl,$8); 2297 | 2298 | } | WHEN OTHERS '=' '>' doindent p_body unindent { 2299 | log_assert(($p_body == NULL) || ($p_body->type == AST_BLOCK)); 2300 | NOT_IMPLEMENTED; 2301 | // slist *sl; 2302 | // sl=addtxt(indents[indent],"default : begin\n"); 2303 | // sl=addsl(sl,$6); 2304 | // sl=addsl(sl,indents[indent]); 2305 | // $$=addtxt(sl,"end\n"); 2306 | 2307 | } | /* Empty */ { 2308 | $$=NULL; 2309 | }; /* List without WHEN OTHERS */ 2310 | 2311 | 2312 | wlist: wvalue { 2313 | NOT_IMPLEMENTED; 2314 | // $$=$1; 2315 | 2316 | } | wlist '|' wvalue { 2317 | NOT_IMPLEMENTED; 2318 | // slist *sl; 2319 | // sl=addtxt($1,","); 2320 | // $$=addsl(sl,$3); 2321 | }; 2322 | 2323 | 2324 | wvalue : STRING { 2325 | NOT_IMPLEMENTED; 2326 | // $$=addvec(NULL,$1); 2327 | 2328 | } | NAME STRING { 2329 | NOT_IMPLEMENTED; 2330 | // $$=addvec_base(NULL,$1,$2); 2331 | 2332 | } | NAME { 2333 | NOT_IMPLEMENTED; 2334 | // $$=addtxt(NULL,$1); 2335 | }; 2336 | 2337 | 2338 | sign_list : signal { 2339 | $$ = new std::vector; 2340 | $$->push_back($signal); 2341 | 2342 | } | signal ',' sign_list { 2343 | $3->insert($3->begin(), $signal); 2344 | $$ = $3; 2345 | }; 2346 | 2347 | 2348 | sigvalue[sigvalue_new]: expr delay ';' { 2349 | $sigvalue_new = $expr; 2350 | // FIXME: deal with the delay 2351 | 2352 | // slist *sl; 2353 | // if(delay && $2){ 2354 | // sl=addtxt(NULL,"# "); 2355 | // sl=addval(sl,$2); 2356 | // sl=addtxt(sl," "); 2357 | // } else 2358 | // sl=NULL; 2359 | // if($1->op == 'c') 2360 | // sl=addsl(sl,addwrap("{",$1->sl,"}")); 2361 | // else 2362 | // sl=addsl(sl,$1->sl); 2363 | // free($1); 2364 | // delay=1; 2365 | // $$=sl; 2366 | 2367 | } | expr delay WHEN exprc ';' { 2368 | NOT_IMPLEMENTED; 2369 | // fprintf(stderr,"Warning on line %d: Can't translate 'expr delay WHEN exprc;' expressions\n",lineno); 2370 | // $$=NULL; 2371 | 2372 | } | expr delay WHEN exprc ELSE nodelay sigvalue[sigvalue_orig] { 2373 | log_assert($exprc != NULL); 2374 | 2375 | log_assert($expr != NULL); 2376 | log_assert($expr->op == EXPDATA_TYPE_AST); 2377 | 2378 | log_assert($sigvalue_orig != NULL); 2379 | log_assert($sigvalue_orig->op == EXPDATA_TYPE_AST); 2380 | 2381 | AstNode *ternary = new AstNode(AST_TERNARY); 2382 | ternary->children.push_back($exprc); 2383 | ternary->children.push_back($expr->node); 2384 | ternary->children.push_back($sigvalue_orig->node); 2385 | free($expr); 2386 | 2387 | $sigvalue_new = $sigvalue_orig; 2388 | $sigvalue_new->node = ternary; 2389 | 2390 | // slist *sl; 2391 | // sl=addtxt($4," ? "); 2392 | // if($1->op == 'c') 2393 | // sl=addsl(sl,addwrap("{",$1->sl,"}")); 2394 | // else 2395 | // sl=addsl(sl,$1->sl); 2396 | // free($1); 2397 | // sl=addtxt(sl," : "); 2398 | // $$=addsl(sl,$7); 2399 | }; 2400 | 2401 | nodelay : /* empty */ { 2402 | delay=0; 2403 | }; 2404 | 2405 | delay : /* empty */ { 2406 | $$=0; 2407 | } | AFTER NATURAL NAME { 2408 | NOT_IMPLEMENTED; 2409 | // set_timescale($3); 2410 | // $$=$2; 2411 | }; 2412 | 2413 | map_list : rem map_item { 2414 | NOT_IMPLEMENTED; 2415 | // slist *sl; 2416 | // sl=addsl($1,indents[indent]); 2417 | // $$=addsl(sl,$2); 2418 | 2419 | } | rem map_item ',' map_list { 2420 | NOT_IMPLEMENTED; 2421 | // slist *sl; 2422 | // sl=addsl($1,indents[indent]); 2423 | // sl=addsl(sl,$2); 2424 | // sl=addtxt(sl,",\n"); 2425 | // $$=addsl(sl,$4); 2426 | }; 2427 | 2428 | map_item : mvalue { 2429 | NOT_IMPLEMENTED; 2430 | // $$=$1; 2431 | 2432 | } | NAME '=' '>' mvalue { 2433 | NOT_IMPLEMENTED; 2434 | // slist *sl; 2435 | // sl=addtxt(NULL,"."); 2436 | // sl=addtxt(sl,$1); 2437 | // sl=addtxt(sl,"("); 2438 | // sl=addsl(sl,$4); 2439 | // $$=addtxt(sl,")"); 2440 | }; 2441 | 2442 | mvalue : STRING { 2443 | NOT_IMPLEMENTED; 2444 | // $$=addvec(NULL,$1); 2445 | 2446 | } | signal { 2447 | NOT_IMPLEMENTED; 2448 | // $$=addsl(NULL,$1->sl); 2449 | 2450 | } | NATURAL { 2451 | NOT_IMPLEMENTED; 2452 | // $$=addval(NULL,$1); 2453 | 2454 | } | NAME STRING { 2455 | NOT_IMPLEMENTED; 2456 | // $$=addvec_base(NULL,$1,$2); 2457 | 2458 | } | OPEN { 2459 | NOT_IMPLEMENTED; 2460 | // $$=addtxt(NULL,"/* open */"); 2461 | 2462 | } | '(' OTHERS '=' '>' STRING ')' { 2463 | NOT_IMPLEMENTED; 2464 | // $$=addtxt(NULL,"{broken{"); 2465 | // $$=addtxt($$,$5); 2466 | // $$=addtxt($$,"}}"); 2467 | // fprintf(stderr,"Warning on line %d: broken width on port with OTHERS\n",lineno); 2468 | }; 2469 | 2470 | 2471 | generic_map_list : rem generic_map_item { 2472 | NOT_IMPLEMENTED; 2473 | // slist *sl; 2474 | // sl=addsl($1,indents[indent]); 2475 | // $$=addsl(sl,$2); 2476 | 2477 | } | rem generic_map_item ',' generic_map_list { 2478 | NOT_IMPLEMENTED; 2479 | // slist *sl; 2480 | // sl=addsl($1,indents[indent]); 2481 | // sl=addsl(sl,$2); 2482 | // sl=addtxt(sl,",\n"); 2483 | // $$=addsl(sl,$4); 2484 | } | rem expr { /* only allow a single un-named map item */ 2485 | NOT_IMPLEMENTED; 2486 | // $$=addsl(NULL,$2->sl); 2487 | }; 2488 | 2489 | generic_map_item : NAME '=' '>' expr { 2490 | NOT_IMPLEMENTED; 2491 | printf("generic_map_item\n"); 2492 | // slist *sl; 2493 | // sl=addtxt(NULL,"."); 2494 | // sl=addtxt(sl,$1); 2495 | // sl=addtxt(sl,"("); 2496 | // sl=addsl(sl,$4->sl); 2497 | // $$=addtxt(sl,")"); 2498 | }; 2499 | 2500 | signal : NAME { 2501 | AstNode *wire = new AstNode(AST_IDENTIFIER); 2502 | wire->str = $NAME; 2503 | $$ = wire; 2504 | // slist *sl; 2505 | // slval *ss; 2506 | // ss=(slval*)xmalloc(sizeof(slval)); 2507 | // sl=addtxt(NULL,$1); 2508 | // if(dowith){ 2509 | // slwith=sl; 2510 | // dowith=0; 2511 | // } 2512 | // ss->sl=sl; 2513 | // ss->val=-1; 2514 | // ss->range=NULL; 2515 | // $$=ss; 2516 | 2517 | } | NAME '(' vec_range ')' { 2518 | NOT_IMPLEMENTED; 2519 | // slval *ss; 2520 | // slist *sl; 2521 | // ss=(slval*)xmalloc(sizeof(slval)); 2522 | // sl=addtxt(NULL,$1); 2523 | // sl=addpar_snug(sl,$3); 2524 | // if(dowith){ 2525 | // slwith=sl; 2526 | // dowith=0; 2527 | // } 2528 | // ss->sl=sl; 2529 | // ss->range=$3; 2530 | // if($3->vtype==tVRANGE) { 2531 | // if (0) { 2532 | // fprintf(stderr,"ss->val set to 1 for "); 2533 | // fslprint(stderr,ss->sl); 2534 | // fprintf(stderr,", why?\n"); 2535 | // } 2536 | // ss->val = -1; /* width is in the vrange */ 2537 | // } else { 2538 | // ss->val = 1; 2539 | // } 2540 | // $$=ss; 2541 | 2542 | } | NAME '(' vec_range ')' '(' vec_range ')' { 2543 | NOT_IMPLEMENTED; 2544 | // slval *ss; 2545 | // slist *sl; 2546 | // ss=(slval*)xmalloc(sizeof(slval)); 2547 | // sl=addtxt(NULL,$1); 2548 | // sl=addpar_snug2(sl,$3, $6); 2549 | // if(dowith){ 2550 | // slwith=sl; 2551 | // dowith=0; 2552 | // } 2553 | // ss->sl=sl; 2554 | // ss->range=$3; 2555 | // if($3->vtype==tVRANGE) { 2556 | // ss->val = -1; /* width is in the vrange */ 2557 | // } else { 2558 | // ss->val = 1; 2559 | // } 2560 | // $$=ss; 2561 | }; 2562 | 2563 | /* Expressions */ 2564 | expr : signal { 2565 | expdata *e; 2566 | e = (expdata*)xmalloc(sizeof(expdata)); 2567 | e->op = EXPDATA_TYPE_AST; 2568 | e->node = $signal; 2569 | $$ = e; 2570 | 2571 | } | STRING { 2572 | std::vector bits; 2573 | string_to_bits(bits, $STRING); 2574 | 2575 | expdata *e; 2576 | e = (expdata*)xmalloc(sizeof(expdata)); 2577 | e->op = EXPDATA_TYPE_AST; 2578 | e->node = Yosys::AST::AstNode::mkconst_bits(bits, false); 2579 | 2580 | $$ = e; 2581 | 2582 | } | FLOAT { 2583 | NOT_IMPLEMENTED; 2584 | // expdata *e=(expdata*)xmalloc(sizeof(expdata)); 2585 | // e->op='t'; /* Terminal symbol */ 2586 | // e->sl=addtxt(NULL,$1); 2587 | // $$=e; 2588 | 2589 | } | NATURAL { 2590 | expdata *e = (expdata*)xmalloc(sizeof(expdata)); 2591 | e->op = EXPDATA_TYPE_AST; 2592 | e->node = Yosys::AST::AstNode::mkconst_int($NATURAL, false); 2593 | $$ = e; 2594 | 2595 | } | NATURAL BASED { /* e.g. 16#55aa# */ 2596 | NOT_IMPLEMENTED; 2597 | /* XXX unify this code with addvec_base */ 2598 | // expdata *e=(expdata*)xmalloc(sizeof(expdata)); 2599 | // char *natval = (char*)xmalloc(strlen($2)+34); 2600 | // e->op='t'; /* Terminal symbol */ 2601 | // switch($1) { 2602 | // case 2: 2603 | // sprintf(natval, "'B%s",$2); 2604 | // break; 2605 | // case 8: 2606 | // sprintf(natval, "'O%s",$2); 2607 | // break; 2608 | // case 10: 2609 | // sprintf(natval, "'D%s",$2); 2610 | // break; 2611 | // case 16: 2612 | // sprintf(natval, "'H%s",$2); 2613 | // break; 2614 | // default: 2615 | // sprintf(natval,"%d#%s#",$1,$2); 2616 | // fprintf(stderr,"Warning on line %d: Can't translate based number %s (only bases of 2, 8, 10, and 16 are translatable)\n",lineno,natval); 2617 | // } 2618 | // e->sl=addtxt(NULL,natval); 2619 | // $$=e; 2620 | 2621 | } | NAME STRING { 2622 | NOT_IMPLEMENTED; 2623 | // expdata *e=(expdata*)xmalloc(sizeof(expdata)); 2624 | // e->op='t'; /* Terminal symbol */ 2625 | // e->sl=addvec_base(NULL,$1,$2); 2626 | // $$=e; 2627 | 2628 | } | '(' OTHERS '=' '>' STRING ')' { 2629 | // FIXME: OTHERS in a vector still needs to be dealt with 2630 | 2631 | std::vector bits; 2632 | string_to_bits(bits, $STRING); 2633 | 2634 | expdata *e; 2635 | e = (expdata*)xmalloc(sizeof(expdata)); 2636 | e->op = EXPDATA_TYPE_AST; 2637 | e->node = Yosys::AST::AstNode::mkconst_bits(bits, false); 2638 | 2639 | $$ = e; 2640 | 2641 | } | expr '&' expr { /* Vector chaining */ 2642 | NOT_IMPLEMENTED; 2643 | // slist *sl; 2644 | // sl=addtxt($1->sl,","); 2645 | // sl=addsl(sl,$3->sl); 2646 | // free($3); 2647 | // $1->op='c'; 2648 | // $1->sl=sl; 2649 | // $$=$1; 2650 | 2651 | } | '-' expr %prec UMINUS { 2652 | NOT_IMPLEMENTED; 2653 | // $$=addexpr(NULL,'m'," -",$2); 2654 | 2655 | } | '+' expr %prec UPLUS { 2656 | NOT_IMPLEMENTED; 2657 | // $$=addexpr(NULL,'p'," +",$2); 2658 | 2659 | } | expr '+' expr { 2660 | expdata *e; 2661 | e = (expdata*)xmalloc(sizeof(expdata)); 2662 | e->op = EXPDATA_TYPE_AST; 2663 | e->node = new AstNode(AST_ADD, $1->node, $3->node); 2664 | $$ = e; 2665 | 2666 | } | expr '-' expr { 2667 | expdata *e; 2668 | e = (expdata*)xmalloc(sizeof(expdata)); 2669 | e->op = EXPDATA_TYPE_AST; 2670 | e->node = new AstNode(AST_SUB, $1->node, $3->node); 2671 | $$ = e; 2672 | 2673 | } | expr '*' expr { 2674 | expdata *e; 2675 | e = (expdata*)xmalloc(sizeof(expdata)); 2676 | e->op = EXPDATA_TYPE_AST; 2677 | e->node = new AstNode(AST_MUL, $1->node, $3->node); 2678 | $$ = e; 2679 | 2680 | } | expr '/' expr { 2681 | expdata *e; 2682 | e = (expdata*)xmalloc(sizeof(expdata)); 2683 | e->op = EXPDATA_TYPE_AST; 2684 | e->node = new AstNode(AST_DIV, $1->node, $3->node); 2685 | $$ = e; 2686 | 2687 | } | expr[expr1] MOD expr[expr2] { 2688 | log_assert($expr1 != NULL); 2689 | log_assert($expr1->op == EXPDATA_TYPE_AST); 2690 | log_assert($expr2 != NULL); 2691 | log_assert($expr2->op == EXPDATA_TYPE_AST); 2692 | 2693 | expdata *e; 2694 | e = (expdata*)xmalloc(sizeof(expdata)); 2695 | e->op = EXPDATA_TYPE_AST; 2696 | e->node = new AstNode(AST_MOD, $expr1->node, $expr2->node); 2697 | $$ = e; 2698 | free($expr1); 2699 | free($expr2); 2700 | 2701 | } | NOT expr[expr1] { 2702 | log_assert($expr1 != NULL); 2703 | log_assert($expr1->op == EXPDATA_TYPE_AST); 2704 | AstNode *not_node = new AstNode(AST_BIT_NOT); 2705 | not_node->children.push_back($expr1->node); 2706 | $expr1->node = not_node; 2707 | $$ = $expr1; 2708 | 2709 | } | expr AND expr { 2710 | NOT_IMPLEMENTED; 2711 | // $$=addexpr($1,'&'," & ",$3); 2712 | 2713 | } | expr OR expr { 2714 | NOT_IMPLEMENTED; 2715 | // $$=addexpr($1,'|'," | ",$3); 2716 | 2717 | } | expr XOR expr { 2718 | NOT_IMPLEMENTED; 2719 | // $$=addexpr($1,'^'," ^ ",$3); 2720 | 2721 | } | expr XNOR expr { 2722 | NOT_IMPLEMENTED; 2723 | // $$=addexpr(NULL,'~'," ~",addexpr($1,'^'," ^ ",$3)); 2724 | 2725 | } | BITVECT '(' expr ')' { 2726 | NOT_IMPLEMENTED; 2727 | /* single argument type conversion function e.g. std_ulogic_vector(x) */ 2728 | // expdata *e; 2729 | // e=(expdata*)xmalloc(sizeof(expdata)); 2730 | // if ($3->op == 'c') { 2731 | // e->sl=addwrap("{",$3->sl,"}"); 2732 | // } else { 2733 | // e->sl=addwrap("(",$3->sl,")"); 2734 | // } 2735 | // $$=e; 2736 | 2737 | } | CONVFUNC_2 '(' expr ',' NATURAL ')' { 2738 | NOT_IMPLEMENTED; 2739 | /* two argument type conversion e.g. to_unsigned(x, 3) */ 2740 | // $$ = addnest($3); 2741 | 2742 | } | CONVFUNC_2 '(' expr ',' NAME ')' { 2743 | NOT_IMPLEMENTED; 2744 | // $$ = addnest($3); 2745 | 2746 | } | '(' expr[expr1] ')' { 2747 | log_assert($expr1 != NULL); 2748 | log_assert($expr1->op == EXPDATA_TYPE_AST); 2749 | $$ = $expr1; 2750 | }; 2751 | 2752 | /* Conditional expressions */ 2753 | exprc : conf { 2754 | log_assert($conf != NULL); 2755 | $exprc = $conf; 2756 | 2757 | } | '(' exprc ')' { 2758 | log_assert($2 != NULL); 2759 | $$ = $2; 2760 | 2761 | } | exprc AND exprc %prec ANDL { 2762 | NOT_IMPLEMENTED; 2763 | // slist *sl; 2764 | // sl=addtxt($1," && "); 2765 | // $$=addsl(sl,$3); 2766 | } | exprc OR exprc %prec ORL { 2767 | NOT_IMPLEMENTED; 2768 | // slist *sl; 2769 | // sl=addtxt($1," || "); 2770 | // $$=addsl(sl,$3); 2771 | } | NOT exprc %prec NOTL { 2772 | NOT_IMPLEMENTED; 2773 | // slist *sl; 2774 | // sl=addtxt(NULL,"!"); 2775 | // $$=addsl(sl,$2); 2776 | }; 2777 | 2778 | /* Comparisons */ 2779 | conf : expr[expr1] '=' expr[expr2] %prec EQUAL { 2780 | log_assert(($expr1 != NULL) && ($expr1->op = EXPDATA_TYPE_AST)); 2781 | log_assert(($expr2 != NULL) && ($expr2->op = EXPDATA_TYPE_AST)); 2782 | $conf = new AstNode(AST_EQ, $expr1->node, $expr2->node); 2783 | free($expr1); 2784 | free($expr2); 2785 | 2786 | // slist *sl; 2787 | // if($1->op == 'c') 2788 | // sl=addwrap("{",$1->sl,"} == "); 2789 | // else if($1->op != 't') 2790 | // sl=addwrap("(",$1->sl,") == "); 2791 | // else 2792 | // sl=addtxt($1->sl," == "); 2793 | // if($3->op == 'c') 2794 | // $$=addsl(sl,addwrap("{",$3->sl,"}")); 2795 | // else if($3->op != 't') 2796 | // $$=addsl(sl,addwrap("(",$3->sl,")")); 2797 | // else 2798 | // $$=addsl(sl,$3->sl); 2799 | // free($1); 2800 | // free($3); 2801 | } | expr[expr1] '>' expr[expr2] { 2802 | log_assert(($expr1 != NULL) && ($expr1->op = EXPDATA_TYPE_AST)); 2803 | log_assert(($expr2 != NULL) && ($expr2->op = EXPDATA_TYPE_AST)); 2804 | $conf = new AstNode(AST_GT, $expr1->node, $expr2->node); 2805 | free($expr1); 2806 | free($expr2); 2807 | // slist *sl; 2808 | // if($1->op == 'c') 2809 | // sl=addwrap("{",$1->sl,"} > "); 2810 | // else if($1->op != 't') 2811 | // sl=addwrap("(",$1->sl,") > "); 2812 | // else 2813 | // sl=addtxt($1->sl," > "); 2814 | // if($3->op == 'c') 2815 | // $$=addsl(sl,addwrap("{",$3->sl,"}")); 2816 | // else if($3->op != 't') 2817 | // $$=addsl(sl,addwrap("(",$3->sl,")")); 2818 | // else 2819 | // $$=addsl(sl,$3->sl); 2820 | // free($1); 2821 | // free($3); 2822 | } | expr[expr1] '>' '=' expr[expr2] %prec BIGEQ { 2823 | log_assert(($expr1 != NULL) && ($expr1->op = EXPDATA_TYPE_AST)); 2824 | log_assert(($expr2 != NULL) && ($expr2->op = EXPDATA_TYPE_AST)); 2825 | $conf = new AstNode(AST_GE, $expr1->node, $expr2->node); 2826 | free($expr1); 2827 | free($expr2); 2828 | // slist *sl; 2829 | // if($1->op == 'c') 2830 | // sl=addwrap("{",$1->sl,"} >= "); 2831 | // else if($1->op != 't') 2832 | // sl=addwrap("(",$1->sl,") >= "); 2833 | // else 2834 | // sl=addtxt($1->sl," >= "); 2835 | // if($4->op == 'c') 2836 | // $$=addsl(sl,addwrap("{",$4->sl,"}")); 2837 | // else if($4->op != 't') 2838 | // $$=addsl(sl,addwrap("(",$4->sl,")")); 2839 | // else 2840 | // $$=addsl(sl,$4->sl); 2841 | // free($1); 2842 | // free($4); 2843 | } | expr[expr1] '<' expr[expr2] { 2844 | log_assert(($expr1 != NULL) && ($expr1->op = EXPDATA_TYPE_AST)); 2845 | log_assert(($expr2 != NULL) && ($expr2->op = EXPDATA_TYPE_AST)); 2846 | $conf = new AstNode(AST_LT, $expr1->node, $expr2->node); 2847 | free($expr1); 2848 | free($expr2); 2849 | // slist *sl; 2850 | // if($1->op == 'c') 2851 | // sl=addwrap("{",$1->sl,"} < "); 2852 | // else if($1->op != 't') 2853 | // sl=addwrap("(",$1->sl,") < "); 2854 | // else 2855 | // sl=addtxt($1->sl," < "); 2856 | // if($3->op == 'c') 2857 | // $$=addsl(sl,addwrap("{",$3->sl,"}")); 2858 | // else if($3->op != 't') 2859 | // $$=addsl(sl,addwrap("(",$3->sl,")")); 2860 | // else 2861 | // $$=addsl(sl,$3->sl); 2862 | // free($1); 2863 | // free($3); 2864 | } | expr[expr1] '<' '=' expr[expr2] %prec LESSEQ { 2865 | log_assert(($expr1 != NULL) && ($expr1->op = EXPDATA_TYPE_AST)); 2866 | log_assert(($expr2 != NULL) && ($expr2->op = EXPDATA_TYPE_AST)); 2867 | $conf = new AstNode(AST_LE, $expr1->node, $expr2->node); 2868 | free($expr1); 2869 | free($expr2); 2870 | // slist *sl; 2871 | // if($1->op == 'c') 2872 | // sl=addwrap("{",$1->sl,"} <= "); 2873 | // else if($1->op != 't') 2874 | // sl=addwrap("(",$1->sl,") <= "); 2875 | // else 2876 | // sl=addtxt($1->sl," <= "); 2877 | // if($4->op == 'c') 2878 | // $$=addsl(sl,addwrap("{",$4->sl,"}")); 2879 | // else if($4->op != 't') 2880 | // $$=addsl(sl,addwrap("(",$4->sl,")")); 2881 | // else 2882 | // $$=addsl(sl,$4->sl); 2883 | // free($1); 2884 | // free($4); 2885 | } | expr[expr1] '/' '=' expr[expr2] %prec NOTEQ { 2886 | log_assert(($expr1 != NULL) && ($expr1->op = EXPDATA_TYPE_AST)); 2887 | log_assert(($expr2 != NULL) && ($expr2->op = EXPDATA_TYPE_AST)); 2888 | $conf = new AstNode(AST_NE, $expr1->node, $expr2->node); 2889 | free($expr1); 2890 | free($expr2); 2891 | // slist *sl; 2892 | // if($1->op == 'c') 2893 | // sl=addwrap("{",$1->sl,"} != "); 2894 | // else if($1->op != 't') 2895 | // sl=addwrap("(",$1->sl,") != "); 2896 | // else 2897 | // sl=addtxt($1->sl," != "); 2898 | // if($4->op == 'c') 2899 | // $$=addsl(sl,addwrap("{",$4->sl,"}")); 2900 | // else if($4->op != 't') 2901 | // $$=addsl(sl,addwrap("(",$4->sl,")")); 2902 | // else 2903 | // $$=addsl(sl,$4->sl); 2904 | // free($1); 2905 | // free($4); 2906 | }; 2907 | 2908 | simple_expr : signal { 2909 | NOT_IMPLEMENTED; 2910 | // expdata *e; 2911 | // e=(expdata*)xmalloc(sizeof(expdata)); 2912 | // e->op='t'; /* Terminal symbol */ 2913 | // e->sl=$1->sl; 2914 | // free($1); 2915 | // $$=e; 2916 | 2917 | } | STRING { 2918 | expdata *e; 2919 | e=(expdata*)xmalloc(sizeof(expdata)); 2920 | expr_set_bits(e, $STRING); 2921 | $$=e; 2922 | 2923 | } | NATURAL { 2924 | expdata *e; 2925 | e=(expdata*)xmalloc(sizeof(expdata)); 2926 | e->op=EXPDATA_TYPE_N; 2927 | e->value=$1; 2928 | e->sl=addval(NULL,$1); 2929 | $$=e; 2930 | 2931 | } | NAME '\'' LEFT { 2932 | NOT_IMPLEMENTED; 2933 | /* lookup NAME and get its left */ 2934 | // sglist *sg = NULL; 2935 | // if((sg=lookup(io_list,$1))==NULL) { 2936 | // sg=lookup(sig_list,$1); 2937 | // } 2938 | // if(sg) { 2939 | // expdata *e; 2940 | // e=(expdata*)xmalloc(sizeof(expdata)); 2941 | // e->sl=addwrap("(",sg->range->nhi,")"); /* XXX left vs. high? */ 2942 | // $$=e; 2943 | // } else { 2944 | // fprintf(stderr,"Undefined left \"%s'left\" on line %d\n",$1,lineno); 2945 | // YYABORT; 2946 | // } 2947 | 2948 | } | simple_expr '+' simple_expr { 2949 | NOT_IMPLEMENTED; 2950 | // $$=addexpr($1,'+'," + ",$3); 2951 | 2952 | } | simple_expr '-' simple_expr { 2953 | NOT_IMPLEMENTED; 2954 | // $$=addexpr($1,'-'," - ",$3); 2955 | 2956 | } | simple_expr '*' simple_expr { 2957 | NOT_IMPLEMENTED; 2958 | // $$=addexpr($1,'*'," * ",$3); 2959 | 2960 | } | simple_expr '/' simple_expr { 2961 | NOT_IMPLEMENTED; 2962 | // $$=addexpr($1,'/'," / ",$3); 2963 | 2964 | } | CONVFUNC_1 '(' simple_expr ')' { 2965 | NOT_IMPLEMENTED; 2966 | /* one argument type conversion e.g. conv_integer(x) */ 2967 | // expdata *e; 2968 | // e=(expdata*)xmalloc(sizeof(expdata)); 2969 | // e->sl=addwrap("(",$3->sl,")"); 2970 | // $$=e; 2971 | 2972 | } | '(' simple_expr ')' { 2973 | NOT_IMPLEMENTED; 2974 | // expdata *e; 2975 | // e=(expdata*)xmalloc(sizeof(expdata)); 2976 | // e->sl=addwrap("(",$2->sl,")"); 2977 | // $$=e; 2978 | }; 2979 | 2980 | %% 2981 | 2982 | const char *outfile; /* Output file */ 2983 | const char *sourcefile; /* Input file */ 2984 | 2985 | --------------------------------------------------------------------------------