1 /*
2  * Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com)
3  *
4  *    This source code is free software; you can redistribute it
5  *    and/or modify it in source code form under the terms of the GNU
6  *    General Public License as published by the Free Software
7  *    Foundation; either version 2 of the License, or (at your option)
8  *    any later version.
9  *
10  *    This program is distributed in the hope that it will be useful,
11  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *    GNU General Public License for more details.
14  *
15  *    You should have received a copy of the GNU General Public License
16  *    along with this program; if not, write to the Free Software
17  *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 # include "config.h"
21 # include  "PWire.h"
22 # include  "PExpr.h"
23 # include  <cassert>
24 
PWire(perm_string n,NetNet::Type t,NetNet::PortType pt,ivl_variable_type_t dt)25 PWire::PWire(perm_string n,
26 	     NetNet::Type t,
27 	     NetNet::PortType pt,
28 	     ivl_variable_type_t dt)
29 : name_(n), type_(t), port_type_(pt), data_type_(dt),
30   signed_(false), isint_(false),
31   port_set_(false), net_set_(false), is_scalar_(false),
32   error_cnt_(0), uarray_type_(0), set_data_type_(0),
33   discipline_(0)
34 {
35       if (t == NetNet::INTEGER) {
36 	    type_ = NetNet::REG;
37 	    signed_ = true;
38 	    isint_ = true;
39       }
40 }
41 
get_wire_type() const42 NetNet::Type PWire::get_wire_type() const
43 {
44       return type_;
45 }
46 
basename() const47 perm_string PWire::basename() const
48 {
49       return name_;
50 }
51 
set_wire_type(NetNet::Type t)52 bool PWire::set_wire_type(NetNet::Type t)
53 {
54       assert(t != NetNet::IMPLICIT);
55 
56       switch (type_) {
57 	  case NetNet::IMPLICIT:
58 	    type_ = t;
59 	    return true;
60 	  case NetNet::IMPLICIT_REG:
61 	    if (t == NetNet::REG) {
62 		  type_ = t;
63 		  return true;
64 	    }
65 	    if (t == NetNet::INTEGER) {
66 		  type_ = NetNet::REG;
67 		  isint_ = true;
68 		  return true;
69 	    }
70 	    if (t == NetNet::IMPLICIT_REG) return true;
71 	    return false;
72 	  case NetNet::REG:
73 	    if (t == NetNet::INTEGER) {
74 		  isint_ = true;
75 		  return true;
76 	    }
77 	    if (t == NetNet::REG) return true;
78 	    return false;
79 	  default:
80 	    if (type_ != t)
81 		  return false;
82 	    else
83 		  return true;
84       }
85 }
86 
get_port_type() const87 NetNet::PortType PWire::get_port_type() const
88 {
89       return port_type_;
90 }
91 
set_port_type(NetNet::PortType pt)92 bool PWire::set_port_type(NetNet::PortType pt)
93 {
94       assert(pt != NetNet::NOT_A_PORT);
95       assert(pt != NetNet::PIMPLICIT);
96 
97       switch (port_type_) {
98 	  case NetNet::PIMPLICIT:
99 	    port_type_ = pt;
100 	    return true;
101 
102 	  case NetNet::NOT_A_PORT:
103 	    return false;
104 
105 	  default:
106 	    if (port_type_ != pt)
107 		  return false;
108 	    else
109 		  return true;
110       }
111 }
112 
set_data_type(ivl_variable_type_t dt)113 bool PWire::set_data_type(ivl_variable_type_t dt)
114 {
115       if (data_type_ != IVL_VT_NO_TYPE) {
116 	    if (data_type_ != dt)
117 		  return false;
118 	    else
119 		  return true;
120       }
121 
122       assert(data_type_ == IVL_VT_NO_TYPE);
123       data_type_ = dt;
124 
125       return true;
126 }
127 
get_data_type() const128 ivl_variable_type_t PWire::get_data_type() const
129 {
130       return data_type_;
131 }
132 
set_signed(bool flag)133 void PWire::set_signed(bool flag)
134 {
135       signed_ = flag;
136 }
137 
get_signed() const138 bool PWire::get_signed() const
139 {
140       return signed_;
141 }
142 
get_isint() const143 bool PWire::get_isint() const
144 {
145       if (isint_)
146 	    return true;
147 
148       if (vector_type_t*tmp = dynamic_cast<vector_type_t*>(set_data_type_)) {
149 	    return tmp->integer_flag;
150       }
151 
152       return false;
153 }
154 
get_scalar() const155 bool PWire::get_scalar() const
156 {
157       return is_scalar_;
158 }
159 
set_range_scalar(PWSRType type)160 void PWire::set_range_scalar(PWSRType type)
161 {
162       is_scalar_ = true;
163       switch (type) {
164 	  case SR_PORT:
165 	    if (port_set_) {
166 		  cerr << get_fileline() << ": error: Port ``" << name_
167 		       << "'' has already been declared a port." << endl;
168 		  error_cnt_ += 1;
169 	    } else {
170 		  port_set_ = true;
171 	    }
172 	    return;
173 
174 	  case SR_NET:
175 	    if (net_set_) {
176 		  cerr << get_fileline() << ": error: Net ``" << name_
177 		       << "'' has already been declared." << endl;
178 		  error_cnt_ += 1;
179 	    } else {
180 		  net_set_ = true;
181 	    }
182 	    return;
183 
184 	  case SR_BOTH:
185 	    if (port_set_ || net_set_) {
186 		  if (port_set_) {
187 		        cerr << get_fileline() << ": error: Port ``" << name_
188 		             << "'' has already been declared a port." << endl;
189 		        error_cnt_ += 1;
190 		  }
191 		  if (net_set_) {
192 		        cerr << get_fileline() << ": error: Net ``" << name_
193 		             << "'' has already been declared." << endl;
194 		        error_cnt_ += 1;
195 		  }
196 	    } else {
197 		  port_set_ = true;
198 		  net_set_ = true;
199 	    }
200 	    return;
201       }
202 }
203 
set_range(const list<pform_range_t> & rlist,PWSRType type)204 void PWire::set_range(const list<pform_range_t>&rlist, PWSRType type)
205 {
206       switch (type) {
207 	  case SR_PORT:
208 	    if (port_set_) {
209 		  cerr << get_fileline() << ": error: Port ``" << name_
210 		       << "'' has already been declared a port." << endl;
211 		  error_cnt_ += 1;
212 	    } else {
213 		  port_ = rlist;
214 		  port_set_ = true;
215 		  is_scalar_ = false;
216 	    }
217 	    return;
218 
219 	  case SR_NET:
220 	    if (net_set_) {
221 		  cerr << get_fileline() << ": error: Net ``" << name_
222 		       << "'' has already been declared." << endl;
223 		  error_cnt_ += 1;
224 	    } else {
225 		  net_ = rlist;
226 		  net_set_ = true;
227 		  is_scalar_ = false;
228 	    }
229 	    return;
230 
231 	  case SR_BOTH:
232 	    if (port_set_ || net_set_) {
233 		  if (port_set_) {
234 		        cerr << get_fileline() << ": error: Port ``" << name_
235 		             << "'' has already been declared a port." << endl;
236 		        error_cnt_ += 1;
237 		  }
238 		  if (net_set_) {
239 		        cerr << get_fileline() << ": error: Net ``" << name_
240 		             << "'' has already been declared." << endl;
241 		        error_cnt_ += 1;
242 		  }
243 	    } else {
244 		  port_ = rlist;
245 		  port_set_ = true;
246 		  net_ = rlist;
247 		  net_set_ = true;
248 		  is_scalar_ = false;
249 	    }
250 	    return;
251       }
252 }
253 
set_unpacked_idx(const list<pform_range_t> & ranges)254 void PWire::set_unpacked_idx(const list<pform_range_t>&ranges)
255 {
256       if (! unpacked_.empty()) {
257 	    cerr << get_fileline() << ": error: Array ``" << name_
258 	         << "'' has already been declared." << endl;
259 	    error_cnt_ += 1;
260       } else {
261 	    unpacked_ = ranges;
262       }
263 }
264 
set_data_type(data_type_t * type)265 void PWire::set_data_type(data_type_t*type)
266 {
267       assert(set_data_type_ == 0);
268       set_data_type_ = type;
269 
270       if (vector_type_t*tmp = dynamic_cast<vector_type_t*>(type)) {
271 	    if (tmp->integer_flag)
272 		  isint_ = true;
273       }
274 }
275 
set_discipline(ivl_discipline_t d)276 void PWire::set_discipline(ivl_discipline_t d)
277 {
278       assert(discipline_ == 0);
279       discipline_ = d;
280 }
281 
get_discipline(void) const282 ivl_discipline_t PWire::get_discipline(void) const
283 {
284       return discipline_;
285 }
286 
symbol_type() const287 PNamedItem::SymbolType PWire::symbol_type() const
288 {
289       switch (type_) {
290           case NetNet::IMPLICIT_REG:
291           case NetNet::INTEGER:
292           case NetNet::REG:
293             return VAR;
294           default:
295             return NET;
296     }
297 }
298