1 #ifndef IVL_subprogram_H 2 #define IVL_subprogram_H 3 /* 4 * Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com) 5 * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) 6 * Copyright CERN 2015 7 * @author Maciej Suminski (maciej.suminski@cern.ch) 8 * 9 * This source code is free software; you can redistribute it 10 * and/or modify it in source code form under the terms of the GNU 11 * General Public License as published by the Free Software 12 * Foundation; either version 2 of the License, or (at your option) 13 * 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 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 23 */ 24 25 # include "StringHeap.h" 26 # include "LineInfo.h" 27 # include "scope.h" 28 # include <iostream> 29 # include <list> 30 # include <cassert> 31 32 class InterfacePort; 33 class SequentialStmt; 34 class Package; 35 class VType; 36 37 class SubprogramBody : public LineInfo, public ScopeBase { 38 39 public: 40 SubprogramBody(); 41 ~SubprogramBody(); 42 43 const InterfacePort*find_param(perm_string nam) const; 44 45 void set_statements(std::list<SequentialStmt*>*statements); empty_statements()46 inline bool empty_statements() const { return !statements_ || statements_->empty(); } 47 48 int elaborate(); 49 int emit(ostream&out, Entity*ent, ScopeBase*scope); 50 51 // Emit body as it would show up in a package. 52 int emit_package(std::ostream&fd); 53 54 void write_to_stream(std::ostream&fd) const; 55 void dump(std::ostream&fd) const; 56 header()57 const SubprogramHeader*header() const { return header_; } is_subprogram()58 bool is_subprogram() const { return true; } 59 60 private: 61 std::list<SequentialStmt*>*statements_; 62 SubprogramHeader*header_; 63 64 friend class SubprogramHeader; 65 }; 66 67 class SubprogramHeader : public LineInfo { 68 public: 69 SubprogramHeader(perm_string name, std::list<InterfacePort*>*ports, 70 const VType*return_type); 71 virtual ~SubprogramHeader(); 72 73 // Return true if the specification (name, types, ports) 74 // matches this subprogram and that subprogram. 75 bool compare_specification(SubprogramHeader*that) const; 76 param_count()77 int param_count() const { return ports_ ? ports_->size() : 0; } 78 const InterfacePort*find_param(perm_string nam) const; 79 const InterfacePort*peek_param(int idx) const; 80 const VType*peek_param_type(int idx) const; peek_return_type()81 const VType*peek_return_type() const { return return_type_; } 82 83 // Computes the exact return type (e.g. std_logic_vector(7 downto 0) 84 // instead of generic std_logic_vector) 85 virtual const VType*exact_return_type(const std::vector<Expression*>&, Entity*, ScopeBase*); 86 set_package(const Package * pkg)87 inline void set_package(const Package*pkg) { assert(!package_); package_ = pkg; } get_package()88 inline const Package*get_package() const { return package_; } 89 90 // Checks if either return type or parameters are unbounded vectors. 91 bool unbounded() const; 92 93 // Is the subprogram coming from the standard library? is_std()94 virtual bool is_std() const { return false; } 95 body()96 inline SubprogramBody*body() const { return body_; } 97 void set_body(SubprogramBody*bdy); 98 name()99 inline perm_string name() const { return name_; } 100 elaborate()101 int elaborate() { return (body_ ? body_->elaborate() : 0); } 102 103 // Elaborates an argument basing on the types stored in the subprogram header. 104 int elaborate_argument(Expression*expr, int idx, Entity*ent, ScopeBase*scope); 105 106 // Emits the function name, including the package if required. 107 int emit_full_name(const std::vector<Expression*>&argv, 108 std::ostream&out, Entity*, ScopeBase*) const; 109 110 // Function name used in the emission step. The main purpose of this 111 // method is to handle functions offered by standard VHDL libraries. 112 // Allows to return different function names depending on the arguments 113 // (think of size casting or signed/unsigned functions). 114 virtual int emit_name(const std::vector<Expression*>&argv, 115 std::ostream&out, Entity*, ScopeBase*) const; 116 117 // Emit arguments for a specific call. It allows to reorder or skip 118 // some of the arguments if function signature is different in 119 // SystemVerilog compared to VHDL. 120 virtual int emit_args(const std::vector<Expression*>&argv, 121 std::ostream&out, Entity*, ScopeBase*) const; 122 123 // Creates a new instance of the function that takes arguments of 124 // a different type. It is used to allow VHDL functions that work with 125 // unbounded std_logic_vectors, so there can be a separate instance 126 // for limited length logic vector. 127 SubprogramHeader*make_instance(std::vector<Expression*> arguments, ScopeBase*scope) const; 128 129 // Emit header as it would show up in a package. 130 int emit_package(std::ostream&fd) const; 131 132 void write_to_stream(std::ostream&fd) const; 133 void dump(std::ostream&fd) const; 134 135 protected: 136 // Tries to set the return type to a fixed type. VHDL functions that 137 // return std_logic_vectors do not specify its length, as SystemVerilog 138 // demands. 139 void fix_return_type(); 140 141 // Procedure/function name 142 perm_string name_; 143 144 std::list<InterfacePort*>*ports_; 145 const VType*return_type_; 146 SubprogramBody*body_; 147 const Package*package_; 148 }; 149 150 // Class to define functions headers defined in the standard VHDL libraries. 151 class SubprogramStdHeader : public SubprogramHeader 152 { 153 public: SubprogramStdHeader(perm_string nam,std::list<InterfacePort * > * ports,const VType * return_type)154 SubprogramStdHeader(perm_string nam, std::list<InterfacePort*>*ports, 155 const VType*return_type) : 156 SubprogramHeader(nam, ports, return_type) {} ~SubprogramStdHeader()157 virtual ~SubprogramStdHeader() {}; 158 is_std()159 bool is_std() const { return true; } 160 }; 161 162 // The simplest case, when only function name has to be changed. 163 class SubprogramBuiltin : public SubprogramStdHeader 164 { 165 public: SubprogramBuiltin(perm_string vhdl_name,perm_string sv_name,std::list<InterfacePort * > * ports,const VType * return_type)166 SubprogramBuiltin(perm_string vhdl_name, perm_string sv_name, 167 std::list<InterfacePort*>*ports, const VType*return_type) : 168 SubprogramStdHeader(vhdl_name, ports, return_type), sv_name_(sv_name) {} ~SubprogramBuiltin()169 ~SubprogramBuiltin() {} 170 171 int emit_name(const std::vector<Expression*>&, std::ostream&out, Entity*, ScopeBase*) const; 172 173 private: 174 // SystemVerilog counterpart function name 175 perm_string sv_name_; 176 }; 177 178 // Helper function to print out a human-readable function signature. 179 void emit_subprogram_sig(std::ostream&out, perm_string name, 180 const std::list<const VType*>&arg_types); 181 182 #endif /* IVL_subprogram_H */ 183