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