1 /*
2  *  Support functions for VHDL output.
3  *
4  *  Copyright (C) 2008-2009  Nick Gasson (nick@nickg.me.uk)
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License along
17  *  with this program; if not, write to the Free Software Foundation, Inc.,
18  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include "vhdl_target.h"
22 #include "support.hh"
23 #include "state.hh"
24 
25 #include <cassert>
26 #include <iostream>
27 
require_support_function(support_function_t f)28 void require_support_function(support_function_t f)
29 {
30    vhdl_scope *scope = get_active_entity()->get_arch()->get_scope();
31    if (!scope->have_declared(support_function::function_name(f)))
32       scope->add_decl(new support_function(f));
33 }
34 
function_name(support_function_t type)35 const char *support_function::function_name(support_function_t type)
36 {
37    switch (type) {
38    case SF_UNSIGNED_TO_BOOLEAN: return "Unsigned_To_Boolean";
39    case SF_SIGNED_TO_BOOLEAN:   return "Signed_To_Boolean";
40    case SF_BOOLEAN_TO_LOGIC:    return "Boolean_To_Logic";
41    case SF_REDUCE_OR:           return "Reduce_OR";
42    case SF_REDUCE_AND:          return "Reduce_AND";
43    case SF_REDUCE_XOR:          return "Reduce_XOR";
44    case SF_REDUCE_XNOR:         return "Reduce_XNOR";
45    case SF_TERNARY_LOGIC:       return "Ternary_Logic";
46    case SF_TERNARY_UNSIGNED:    return "Ternary_Unsigned";
47    case SF_TERNARY_SIGNED:      return "Ternary_Signed";
48    case SF_LOGIC_TO_INTEGER:    return "Logic_To_Integer";
49    case SF_SIGNED_TO_LOGIC:     return "Signed_To_Logic";
50    case SF_UNSIGNED_TO_LOGIC:   return "Unsigned_To_Logic";
51    default:
52       assert(false);
53    }
54    return "Invalid";
55 }
56 
function_type(support_function_t type)57 vhdl_type *support_function::function_type(support_function_t type)
58 {
59    switch (type) {
60    case SF_UNSIGNED_TO_BOOLEAN:
61    case SF_SIGNED_TO_BOOLEAN:
62       return vhdl_type::boolean();
63    case SF_BOOLEAN_TO_LOGIC:
64    case SF_REDUCE_OR:
65    case SF_REDUCE_AND:
66    case SF_REDUCE_XOR:
67    case SF_REDUCE_XNOR:
68    case SF_TERNARY_LOGIC:
69    case SF_SIGNED_TO_LOGIC:
70    case SF_UNSIGNED_TO_LOGIC:
71       return vhdl_type::std_logic();
72    case SF_TERNARY_SIGNED:
73       return new vhdl_type(VHDL_TYPE_SIGNED);
74    case SF_TERNARY_UNSIGNED:
75       return new vhdl_type(VHDL_TYPE_UNSIGNED);
76    case SF_LOGIC_TO_INTEGER:
77       return vhdl_type::integer();
78    }
79    assert(false);
80    return vhdl_type::boolean();
81 }
82 
emit_ternary(std::ostream & of,int level) const83 void support_function::emit_ternary(std::ostream &of, int level) const
84 {
85    of << nl_string(level) << "begin" << nl_string(indent(level))
86       << "if T then return X; else return Y; end if;";
87 }
88 
emit_reduction(std::ostream & of,int level,const char * op,char unit) const89 void support_function::emit_reduction(std::ostream &of, int level,
90                                       const char *op, char unit) const
91 {
92    // Emit a VHDL function emulating a Verilog reduction operator
93    // Where op is the corresponding VHDL operator and unit is the
94    // right-unit of the operator
95 
96    of << "(X : std_logic_vector) return std_logic is"
97       << nl_string(indent(level))
98       << "variable R : std_logic := '" << unit << "';" << nl_string(level)
99       << "begin" << nl_string(indent(level))
100       << "for I in X'Range loop" << nl_string(indent(indent(level)))
101       << "R := X(I) " << op << " R;" << nl_string(indent(level))
102       << "end loop;" << nl_string(indent(level))
103       << "return R;";
104 }
105 
emit(std::ostream & of,int level) const106 void support_function::emit(std::ostream &of, int level) const
107 {
108    of << nl_string(level) << "function " << function_name(type_);
109 
110    switch (type_) {
111    case SF_UNSIGNED_TO_BOOLEAN:
112       of << "(X : unsigned) return Boolean is" << nl_string(level)
113          << "begin" << nl_string(indent(level))
114          << "return X /= To_Unsigned(0, X'Length);";
115       break;
116    case SF_SIGNED_TO_BOOLEAN:
117       of << "(X : signed) return Boolean is" << nl_string(level)
118          << "begin" << nl_string(indent(level))
119          << "return X /= To_Signed(0, X'Length);";
120       break;
121    case SF_BOOLEAN_TO_LOGIC:
122       of << "(B : Boolean) return std_logic is" << nl_string(level)
123          << "begin" << nl_string(indent(level))
124          << "if B then" << nl_string(indent(indent(level)))
125          << "return '1';" << nl_string(indent(level))
126          << "else" << nl_string(indent(indent(level)))
127          << "return '0';" << nl_string(indent(level))
128          << "end if;";
129       break;
130    case SF_UNSIGNED_TO_LOGIC:
131       of << "(X : unsigned) return std_logic is" << nl_string(level)
132          << "begin" << nl_string(indent(level))
133          << "return X(0);";
134       break;
135    case SF_SIGNED_TO_LOGIC:
136       of << "(X : signed) return std_logic is" << nl_string(level)
137          << "begin" << nl_string(indent(level))
138          << "return X(0);";
139       break;
140    case SF_REDUCE_OR:
141       emit_reduction(of, level, "or", '0');
142       break;
143    case SF_REDUCE_AND:
144       emit_reduction(of, level, "and", '1');
145       break;
146    case SF_REDUCE_XOR:
147       emit_reduction(of, level, "xor", '0');
148       break;
149    case SF_REDUCE_XNOR:
150       emit_reduction(of, level, "xnor", '0');
151       break;
152    case SF_TERNARY_LOGIC:
153       of << "(T : Boolean; X, Y : std_logic) return std_logic is";
154       emit_ternary(of, level);
155       break;
156    case SF_TERNARY_SIGNED:
157       of << "(T : Boolean; X, Y : signed) return signed is";
158       emit_ternary(of, level);
159       break;
160    case SF_TERNARY_UNSIGNED:
161       of << "(T : Boolean; X, Y : unsigned) return unsigned is";
162       emit_ternary(of, level);
163       break;
164    case SF_LOGIC_TO_INTEGER:
165       of << "(X : std_logic) return integer is" << nl_string(level)
166          << "begin" << nl_string(indent(level))
167          << "if X = '1' then return 1; else return 0; end if;";
168       break;
169    default:
170       assert(false);
171    }
172 
173    of << nl_string(level) << "end function;";
174 }
175