Skip to content
Newer
Older
100644 593 lines (499 sloc) 17.5 KB
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
1 /*
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
2 * Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 */
19
b825f8d Create a config.h.in file to hold all the config
steve authored
20 # include "config.h"
21
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
22 # include "PExpr.h"
23 # include "netlist.h"
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
24 # include "netmisc.h"
48de739 Switch to control warnings.
steve authored
25 # include "compiler.h"
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
26
8ea3b6b @ldoolitt header includes for gcc-4.3 compatibility
ldoolitt authored
27 # include <cstdlib>
28 # include <cstring>
b825f8d Create a config.h.in file to hold all the config
steve authored
29 # include <iostream>
b2e1db6 Add method to bind assertions to verilog source lines.
steve authored
30 # include "ivl_assert.h"
b825f8d Create a config.h.in file to hold all the config
steve authored
31
d1f0bcf Catch unsized expressions in continuous assigns.
steve authored
32 /*
cfd8cbf Port expressions for output ports are lnets, not nets.
steve authored
33 * The concatenation is also OK an an l-value. This method elaborates
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
34 * it as a structural l-value. The return values is the *input* net of
35 * the l-value, which may feed via part selects to the final
36 * destination. The caller can connect gate outputs to this signal to
37 * make the l-value connections.
cfd8cbf Port expressions for output ports are lnets, not nets.
steve authored
38 */
a2c036d Allow concatenations as arguments to inout ports.
steve authored
39 NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
40 bool bidirectional_flag) const
cfd8cbf Port expressions for output ports are lnets, not nets.
steve authored
41 {
42 assert(scope);
43
44 svector<NetNet*>nets (parms_.count());
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
45 unsigned width = 0;
cfd8cbf Port expressions for output ports are lnets, not nets.
steve authored
46 unsigned errors = 0;
47
48 if (repeat_) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
49 cerr << get_fileline() << ": sorry: I do not know how to"
cfd8cbf Port expressions for output ports are lnets, not nets.
steve authored
50 " elaborate repeat concatenation nets." << endl;
51 return 0;
52 }
53
54 /* Elaborate the operands of the concatenation. */
55 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
07a427b Detect null arguments to concatenation operator.
steve authored
56
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
57 if (debug_elaborate) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
58 cerr << get_fileline() << ": debug: Elaborate subexpression "
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
59 << idx << " of " << nets.count() << " l-values: "
60 << *parms_[idx] << endl;
61 }
62
07a427b Detect null arguments to concatenation operator.
steve authored
63 if (parms_[idx] == 0) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
64 cerr << get_fileline() << ": error: Empty expressions "
07a427b Detect null arguments to concatenation operator.
steve authored
65 << "not allowed in concatenations." << endl;
66 errors += 1;
67 continue;
68 }
69
a2c036d Allow concatenations as arguments to inout ports.
steve authored
70 if (bidirectional_flag) {
71 nets[idx] = parms_[idx]->elaborate_bi_net(des, scope);
72 } else {
d26ae86 @steveicarus Move implicit net creation from elaboration to elaborate_sig
authored
73 nets[idx] = parms_[idx]->elaborate_lnet(des, scope);
a2c036d Allow concatenations as arguments to inout ports.
steve authored
74 }
cfd8cbf Port expressions for output ports are lnets, not nets.
steve authored
75 if (nets[idx] == 0)
76 errors += 1;
77 else
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
78 width += nets[idx]->vector_width();
cfd8cbf Port expressions for output ports are lnets, not nets.
steve authored
79 }
80
81 /* If any of the sub expressions failed to elaborate, then
82 delete all those that did and abort myself. */
83 if (errors) {
84 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
85 if (nets[idx]) delete nets[idx];
86 }
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
87 des->errors += errors;
cfd8cbf Port expressions for output ports are lnets, not nets.
steve authored
88 return 0;
89 }
90
91 /* Make the temporary signal that connects to all the
92 operands, and connect it up. Scan the operands of the
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
93 concat operator from most significant to least significant,
94 which is the order they are given in the concat list. */
95
badad63 All NetObj objects have lex_string base names.
steve authored
96 NetNet*osig = new NetNet(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
97 NetNet::IMPLICIT, width);
98
0c9fb76 Get the data type of part select results right.
steve authored
99 /* Assume that the data types of the nets are all the same, so
100 we can take the data type of any, the first will do. */
101 osig->data_type(nets[0]->data_type());
326329d Set some missing local flags.
steve authored
102 osig->local_flag(true);
103 osig->set_line(*this);
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
104
73e2b29 @steveicarus Replace the NetPartSelect:BI with NetTran(VP).
authored
105 if (bidirectional_flag) {
106 if (debug_elaborate) {
107 cerr << get_fileline() << ": debug: Generating tran(VP) "
108 << "to connect input l-value to subexpressions."
109 << endl;
110 }
cfd8cbf Port expressions for output ports are lnets, not nets.
steve authored
111
73e2b29 @steveicarus Replace the NetPartSelect:BI with NetTran(VP).
authored
112 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
113 unsigned wid = nets[idx]->vector_width();
114 unsigned off = width - wid;
115 NetTran*ps = new NetTran(scope, scope->local_symbol(),
116 osig->vector_width(), wid, off);
117 des->add_node(ps);
118 ps->set_line(*this);
a2c036d Allow concatenations as arguments to inout ports.
steve authored
119
73e2b29 @steveicarus Replace the NetPartSelect:BI with NetTran(VP).
authored
120 connect(ps->pin(0), osig->pin(0));
121 connect(ps->pin(1), nets[idx]->pin(0));
122
123 ivl_assert(*this, wid <= width);
124 width -= wid;
125 }
126
127 } else {
128 if (debug_elaborate) {
129 cerr << get_fileline() << ": debug: Generating part selects "
130 << "to connect input l-value to subexpressions."
131 << endl;
132 }
133
134 NetPartSelect::dir_t part_dir = NetPartSelect::VP;
135
136 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
137 unsigned wid = nets[idx]->vector_width();
138 unsigned off = width - wid;
139 NetPartSelect*ps = new NetPartSelect(osig, off, wid, part_dir);
140 des->add_node(ps);
141 ps->set_line(*this);
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
142
73e2b29 @steveicarus Replace the NetPartSelect:BI with NetTran(VP).
authored
143 connect(ps->pin(1), osig->pin(0));
144 connect(ps->pin(0), nets[idx]->pin(0));
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
145
73e2b29 @steveicarus Replace the NetPartSelect:BI with NetTran(VP).
authored
146 assert(wid <= width);
147 width -= wid;
148 }
149 assert(width == 0);
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
150 }
151
a8b86ea More explicit datatype setup.
steve authored
152 osig->data_type(nets[0]->data_type());
cfd8cbf Port expressions for output ports are lnets, not nets.
steve authored
153 osig->local_flag(true);
154 return osig;
155 }
156
d26ae86 @steveicarus Move implicit net creation from elaboration to elaborate_sig
authored
157 NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope) const
a2c036d Allow concatenations as arguments to inout ports.
steve authored
158 {
d26ae86 @steveicarus Move implicit net creation from elaboration to elaborate_sig
authored
159 return elaborate_lnet_common_(des, scope, false);
a2c036d Allow concatenations as arguments to inout ports.
steve authored
160 }
161
162 NetNet* PEConcat::elaborate_bi_net(Design*des, NetScope*scope) const
163 {
d26ae86 @steveicarus Move implicit net creation from elaboration to elaborate_sig
authored
164 return elaborate_lnet_common_(des, scope, true);
a2c036d Allow concatenations as arguments to inout ports.
steve authored
165 }
166
cfd8cbf Port expressions for output ports are lnets, not nets.
steve authored
167 /*
4a8be3d Implement bi-directional part selects.
steve authored
168 * A private method to create an implicit net.
169 */
170 NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const
171 {
172 NetNet::Type nettype = scope->default_nettype();
13d4a73 @steveicarus Elaborate implicit signals that are arguments to module instances.
authored
173 assert(nettype != NetNet::NONE);
174
175 NetNet*sig = new NetNet(scope, peek_tail_name(path_),
176 NetNet::IMPLICIT, 1);
177 sig->set_line(*this);
178 /* Implicit nets are always scalar logic. */
179 sig->data_type(IVL_VT_LOGIC);
180
181 if (warn_implicit) {
182 cerr << get_fileline() << ": warning: implicit "
183 "definition of wire logic " << scope_path(scope)
184 << "." << peek_tail_name(path_) << "." << endl;
4a8be3d Implement bi-directional part selects.
steve authored
185 }
186
187 return sig;
188 }
189
190 /*
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
191 * This private method evaluates the part selects (if any) for the
192 * signal. The sig argument is the NetNet already located for the
193 * PEIdent name. The midx and lidx arguments are loaded with the
194 * results, which may be the whole vector, or a single bit, or
195 * anything in between. The values are in canonical indices.
196 */
197 bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
198 long&midx, long&lidx) const
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
199 {
ddd36ec Rework the heirarchical identifier parse syntax and pform
steve authored
200 const name_component_t&name_tail = path_.back();
201 // Only treat as part/bit selects any index that is beyond the
202 // word selects for an array. This is not an array, then
203 // dimensions==0 and any index is treated as a select.
204 if (name_tail.index.size() <= sig->array_dimensions()) {
205 midx = sig->vector_width()-1;
206 lidx = 0;
207 return true;
208 }
209
210 ivl_assert(*this, !name_tail.index.empty());
211
212 const index_component_t&index_tail = name_tail.index.back();
213
214 switch (index_tail.sel) {
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
215 default:
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
216 cerr << get_fileline() << ": internal error: "
ddd36ec Rework the heirarchical identifier parse syntax and pform
steve authored
217 << "Unexpected sel_ value = " << index_tail.sel << endl;
218 ivl_assert(*this, 0);
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
219 break;
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
220
ddd36ec Rework the heirarchical identifier parse syntax and pform
steve authored
221 case index_component_t::SEL_IDX_DO:
222 case index_component_t::SEL_IDX_UP: {
223 NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
224 NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
e26b9e7 @caryr More array fixes and down indexed part selects can be a lval.
caryr authored
225 if (!tmp) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
226 cerr << get_fileline() << ": error: indexed part select of "
e26b9e7 @caryr More array fixes and down indexed part selects can be a lval.
caryr authored
227 << sig->name()
228 << " must be a constant in this context." << endl;
229 des->errors += 1;
230 return 0;
231 }
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
232
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
233 long midx_val = tmp->value().as_long();
234 midx = sig->sb_to_idx(midx_val);
235 delete tmp_ex;
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
236
018f1a6 @steveicarus Handle indexed part select in continuous assign.
authored
237 /* The width (a constant) is calculated here. */
238 unsigned long wid = 0;
239 bool flag = calculate_up_do_width_(des, scope, wid);
240 if (! flag)
241 return false;
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
242
ddd36ec Rework the heirarchical identifier parse syntax and pform
steve authored
243 if (index_tail.sel == index_component_t::SEL_IDX_UP)
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
244 lidx = sig->sb_to_idx(midx_val+wid-1);
245 else
246 lidx = sig->sb_to_idx(midx_val-wid+1);
247
248 if (midx < lidx) {
249 long tmp = midx;
250 midx = lidx;
251 lidx = tmp;
252 }
253
254 break;
255 }
256
ddd36ec Rework the heirarchical identifier parse syntax and pform
steve authored
257 case index_component_t::SEL_PART: {
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
258
018f1a6 @steveicarus Handle indexed part select in continuous assign.
authored
259 long msb, lsb;
25ad1c1 @ldoolitt Clean up compiler warnings
ldoolitt authored
260 /* bool flag = */ calculate_parts_(des, scope, msb, lsb);
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
261
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
262 long lidx_tmp = sig->sb_to_idx(lsb);
263 long midx_tmp = sig->sb_to_idx(msb);
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
264 /* Detect reversed indices of a part select. */
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
265 if (lidx_tmp > midx_tmp) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
266 cerr << get_fileline() << ": error: Part select "
018f1a6 @steveicarus Handle indexed part select in continuous assign.
authored
267 << sig->name() << "[" << msb << ":"
268 << lsb << "] indices reversed." << endl;
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
269 cerr << get_fileline() << ": : Did you mean "
018f1a6 @steveicarus Handle indexed part select in continuous assign.
authored
270 << sig->name() << "[" << lsb << ":"
271 << msb << "]?" << endl;
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
272 long tmp = midx_tmp;
273 midx_tmp = lidx_tmp;
274 lidx_tmp = tmp;
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
275 des->errors += 1;
276 }
277
278 /* Detect a part select out of range. */
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
279 if (midx_tmp >= (long)sig->vector_width() || lidx_tmp < 0) {
280 cerr << get_fileline() << ": warning: Part select "
018f1a6 @steveicarus Handle indexed part select in continuous assign.
authored
281 << sig->name() << "[" << msb << ":"
282 << lsb << "] out of range." << endl;
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
283 #if 0
284 midx_tmp = sig->vector_width() - 1;
285 lidx_tmp = 0;
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
286 des->errors += 1;
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
287 #endif
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
288 }
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
289
290 midx = midx_tmp;
291 lidx = lidx_tmp;
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
292 break;
293 }
294
ddd36ec Rework the heirarchical identifier parse syntax and pform
steve authored
295 case index_component_t::SEL_BIT:
296 if (name_tail.index.size() > sig->array_dimensions()) {
129a064 Handle bit/part select of array words in nets.
steve authored
297 verinum*mval = index_tail.msb->eval_const(des, scope);
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
298 if (mval == 0) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
299 cerr << get_fileline() << ": error: Index of " << path_ <<
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
300 " needs to be constant in this context." <<
301 endl;
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
302 cerr << get_fileline() << ": : Index expression is: "
129a064 Handle bit/part select of array words in nets.
steve authored
303 << *index_tail.msb << endl;
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
304 cerr << get_fileline() << ": : Context scope is: "
8ec6d99 Put instantiated modules in the proper generated scope.
steve authored
305 << scope_path(scope) << endl;
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
306 des->errors += 1;
307 return false;
308 }
309 assert(mval);
310
311 midx = sig->sb_to_idx(mval->as_long());
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
312 if (midx >= (long)sig->vector_width()) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
313 cerr << get_fileline() << ": error: Index " << sig->name()
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
314 << "[" << mval->as_long() << "] out of range."
315 << endl;
316 des->errors += 1;
317 midx = 0;
318 }
319 lidx = midx;
320
321 } else {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
322 cerr << get_fileline() << ": internal error: "
ddd36ec Rework the heirarchical identifier parse syntax and pform
steve authored
323 << "Bit select " << path_ << endl;
324 ivl_assert(*this, 0);
c2ff3d5 Fix support for indexed part select in continuous assign l-values.
steve authored
325 midx = sig->vector_width() - 1;
326 lidx = 0;
327 }
328 break;
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
329 }
330
331 return true;
332 }
333
334 /*
4a8be3d Implement bi-directional part selects.
steve authored
335 * This is the common code for l-value nets and bi-directional
336 * nets. There is very little that is different between the two cases,
337 * so most of the work for both is done here.
a81dcd7 Support memories in continuous assignments.
steve authored
338 */
4a8be3d Implement bi-directional part selects.
steve authored
339 NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
340 bool bidirectional_flag) const
a81dcd7 Support memories in continuous assignments.
steve authored
341 {
6937945 Remove find_memory method from Design class.
steve authored
342 assert(scope);
343
344 NetNet* sig = 0;
345 const NetExpr*par = 0;
346 NetEvent* eve = 0;
347
91d84e7 Major rework of array handling. Memories are replaced with the
steve authored
348 symbol_search(des, scope, path_, sig, par, eve);
6937945 Remove find_memory method from Design class.
steve authored
349
350 if (eve != 0) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
351 cerr << get_fileline() << ": error: named events (" << path_
6937945 Remove find_memory method from Design class.
steve authored
352 << ") cannot be l-values in continuous "
353 << "assignments." << endl;
354 des->errors += 1;
355 return 0;
356 }
357
a81dcd7 Support memories in continuous assignments.
steve authored
358 if (sig == 0) {
d26ae86 @steveicarus Move implicit net creation from elaboration to elaborate_sig
authored
359 cerr << get_fileline() << ": error: Net " << path_
360 << " is not defined in this context." << endl;
361 des->errors += 1;
362 return 0;
a81dcd7 Support memories in continuous assignments.
steve authored
363 }
364
365 assert(sig);
366
367 /* Don't allow registers as assign l-values. */
368 if (sig->type() == NetNet::REG) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
369 cerr << get_fileline() << ": error: reg " << sig->name()
c96598a Primitive outputs have same limitations as continuous assignment.
steve authored
370 << "; cannot be driven by primitives"
371 << " or continuous assignment." << endl;
372 des->errors += 1;
a81dcd7 Support memories in continuous assignments.
steve authored
373 return 0;
374 }
375
4d0b840 Coerse input to inout when assigned to.
steve authored
376 if (sig->port_type() == NetNet::PINPUT) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
377 cerr << get_fileline() << ": warning: L-value ``"
c032186 Reword some error messages for clarity.
steve authored
378 << sig->name() << "'' is also an input port." << endl;
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
379 cerr << sig->get_fileline() << ": warning: input "
c032186 Reword some error messages for clarity.
steve authored
380 << sig->name() << "; is coerced to inout." << endl;
4d0b840 Coerse input to inout when assigned to.
steve authored
381 sig->port_type(NetNet::PINOUT);
382 }
383
91d84e7 Major rework of array handling. Memories are replaced with the
steve authored
384 // Default part select is the entire word.
385 unsigned midx = sig->vector_width()-1, lidx = 0;
386 // The default word select is the first.
387 unsigned widx = 0;
388
ddd36ec Rework the heirarchical identifier parse syntax and pform
steve authored
389 const name_component_t&name_tail = path_.back();
390
91d84e7 Major rework of array handling. Memories are replaced with the
steve authored
391 if (sig->array_dimensions() > 0) {
392
e26b9e7 @caryr More array fixes and down indexed part selects can be a lval.
caryr authored
393 if (name_tail.index.empty()) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
394 cerr << get_fileline() << ": error: array " << sig->name()
e26b9e7 @caryr More array fixes and down indexed part selects can be a lval.
caryr authored
395 << " must be used with an index." << endl;
396 des->errors += 1;
397 return 0;
398 }
ddd36ec Rework the heirarchical identifier parse syntax and pform
steve authored
399
400 const index_component_t&index_head = name_tail.index.front();
e39b3fe @caryr Display a warning for a part select of an array.
caryr authored
401 if (index_head.sel == index_component_t::SEL_PART) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
402 cerr << get_fileline() << ": error: cannot perform a part "
e39b3fe @caryr Display a warning for a part select of an array.
caryr authored
403 << "select on array " << sig->name() << "." << endl;
404 des->errors += 1;
405 return 0;
406 }
ddd36ec Rework the heirarchical identifier parse syntax and pform
steve authored
407 ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
408
409 NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
91d84e7 Major rework of array handling. Memories are replaced with the
steve authored
410 NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
51293b6 @caryr Fix/enhance array part select code.
caryr authored
411 if (!tmp) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
412 cerr << get_fileline() << ": error: array " << sig->name()
51293b6 @caryr Fix/enhance array part select code.
caryr authored
413 << " index must be a constant in this context." << endl;
414 des->errors += 1;
415 return 0;
416 }
91d84e7 Major rework of array handling. Memories are replaced with the
steve authored
417
418 long widx_val = tmp->value().as_long();
419 widx = sig->array_index_to_address(widx_val);
420 delete tmp_ex;
421
422 if (debug_elaborate)
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
423 cerr << get_fileline() << ": debug: Use [" << widx << "]"
91d84e7 Major rework of array handling. Memories are replaced with the
steve authored
424 << " to index l-value array." << endl;
425
51293b6 @caryr Fix/enhance array part select code.
caryr authored
426 /* The array has a part/bit select at the end. */
e26b9e7 @caryr More array fixes and down indexed part selects can be a lval.
caryr authored
427 if (name_tail.index.size() > sig->array_dimensions()) {
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
428 long midx_tmp, lidx_tmp;
429 if (! eval_part_select_(des, scope, sig, midx_tmp, lidx_tmp))
51293b6 @caryr Fix/enhance array part select code.
caryr authored
430 return 0;
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
431 ivl_assert(*this, lidx_tmp >= 0);
432 midx = midx_tmp;
433 lidx = lidx_tmp;
51293b6 @caryr Fix/enhance array part select code.
caryr authored
434 }
ddd36ec Rework the heirarchical identifier parse syntax and pform
steve authored
435 } else if (!name_tail.index.empty()) {
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
436 long midx_tmp, lidx_tmp;
437 if (! eval_part_select_(des, scope, sig, midx_tmp, lidx_tmp))
91d84e7 Major rework of array handling. Memories are replaced with the
steve authored
438 return 0;
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
439
440 ivl_assert(*this, lidx_tmp >= 0);
441 midx = midx_tmp;
442 lidx = lidx_tmp;
91d84e7 Major rework of array handling. Memories are replaced with the
steve authored
443 }
4eed86d Detect part select errors on l-values.
steve authored
444
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
445 unsigned subnet_wid = midx-lidx+1;
446
91d84e7 Major rework of array handling. Memories are replaced with the
steve authored
447 if (sig->pin_count() > 1) {
448 assert(widx < sig->pin_count());
449
450 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
451 sig->type(), sig->vector_width());
452 tmp->set_line(*this);
453 tmp->local_flag(true);
4919b70 @steveicarus Give l-value nets their proper type.
authored
454 tmp->data_type( sig->data_type() );
91d84e7 Major rework of array handling. Memories are replaced with the
steve authored
455 connect(sig->pin(widx), tmp->pin(0));
456 sig = tmp;
457 }
458
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
459 /* If the desired l-value vector is narrower then the
460 signal itself, then use a NetPartSelect node to
461 arrange for connection to the desired bits. All this
462 can be skipped if the desired with matches the
463 original vector. */
464
465 if (subnet_wid != sig->vector_width()) {
4a8be3d Implement bi-directional part selects.
steve authored
466 /* If we are processing a tran or inout, then the
467 partselect is bi-directional. Otherwise, it is a
468 Part-to-Vector select. */
469
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
470 if (debug_elaborate)
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
471 cerr << get_fileline() << ": debug: "
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
472 << "Elaborate lnet part select "
473 << sig->name()
474 << "[base=" << lidx
475 << " wid=" << subnet_wid <<"]"
476 << endl;
a81dcd7 Support memories in continuous assignments.
steve authored
477
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
478 NetNet*subsig = new NetNet(sig->scope(),
479 sig->scope()->local_symbol(),
480 NetNet::WIRE, subnet_wid);
9a16e03 Match data type of PV select input/output.
steve authored
481 subsig->data_type( sig->data_type() );
326329d Set some missing local flags.
steve authored
482 subsig->local_flag(true);
483 subsig->set_line(*this);
a81dcd7 Support memories in continuous assignments.
steve authored
484
73e2b29 @steveicarus Replace the NetPartSelect:BI with NetTran(VP).
authored
485 if (bidirectional_flag) {
486 // Make a tran(VP)
487 NetTran*sub = new NetTran(scope, scope->local_symbol(),
488 sig->vector_width(),
489 subnet_wid, lidx);
490 sub->set_line(*this);
491 des->add_node(sub);
492 connect(sub->pin(0), sig->pin(0));
493 connect(sub->pin(1), subsig->pin(0));
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
494
73e2b29 @steveicarus Replace the NetPartSelect:BI with NetTran(VP).
authored
495 } else {
496 NetPartSelect*sub = new NetPartSelect(sig, lidx, subnet_wid,
497 NetPartSelect::PV);
498 des->add_node(sub);
499 sub->set_line(*this);
500 connect(sub->pin(0), subsig->pin(0));
501 }
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
502 sig = subsig;
a81dcd7 Support memories in continuous assignments.
steve authored
503 }
504
505 return sig;
506 }
507
206b37e Fix NetConst being set to zero width, and clean
steve authored
508 /*
4a8be3d Implement bi-directional part selects.
steve authored
509 * Identifiers in continuous assignment l-values are limited to wires
510 * and that ilk. Detect registers and memories here and report errors.
511 */
d26ae86 @steveicarus Move implicit net creation from elaboration to elaborate_sig
authored
512 NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
4a8be3d Implement bi-directional part selects.
steve authored
513 {
d26ae86 @steveicarus Move implicit net creation from elaboration to elaborate_sig
authored
514 return elaborate_lnet_common_(des, scope, false);
4a8be3d Implement bi-directional part selects.
steve authored
515 }
516
517 NetNet* PEIdent::elaborate_bi_net(Design*des, NetScope*scope) const
518 {
d26ae86 @steveicarus Move implicit net creation from elaboration to elaborate_sig
authored
519 return elaborate_lnet_common_(des, scope, true);
4a8be3d Implement bi-directional part selects.
steve authored
520 }
521
522 /*
3676d66 Module ports are really special PEIdent
steve authored
523 * This method is used to elaborate identifiers that are ports to a
524 * scope. The scope is presumed to be that of the module that has the
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
525 * port. This elaboration is done inside the module, and is only done
526 * to PEIdent objects. This method is used by elaboration of a module
527 * instantiation (PGModule::elaborate_mod_) to get NetNet objects for
528 * the port.
3676d66 Module ports are really special PEIdent
steve authored
529 */
530 NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
531 {
ab6c8cb Parser and pform use hierarchical names as hname_t
steve authored
532 NetNet*sig = des->find_signal(scope, path_);
3676d66 Module ports are really special PEIdent
steve authored
533 if (sig == 0) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
534 cerr << get_fileline() << ": error: no wire/reg " << path_
c7d97f4 Properly evaluate scope path expressions.
steve authored
535 << " in module " << scope_path(scope) << "." << endl;
3676d66 Module ports are really special PEIdent
steve authored
536 des->errors += 1;
537 return 0;
538 }
539
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
540 /* Check the port_type of the signal to make sure it is really
541 a port, and its direction is resolved. */
a59bbde Proper error messages when port direction is missing.
steve authored
542 switch (sig->port_type()) {
543 case NetNet::PINPUT:
544 case NetNet::POUTPUT:
545 case NetNet::PINOUT:
546 break;
547
548 /* If the name matches, but the signal is not a port,
549 then the user declared the object but there is no
550 matching input/output/inout declaration. */
551
552 case NetNet::NOT_A_PORT:
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
553 cerr << get_fileline() << ": error: signal " << path_ << " in"
c7d97f4 Properly evaluate scope path expressions.
steve authored
554 << " module " << scope_path(scope) << " is not a port." << endl;
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
555 cerr << get_fileline() << ": : Are you missing an input/"
a59bbde Proper error messages when port direction is missing.
steve authored
556 << "output/inout declaration?" << endl;
557 des->errors += 1;
558 return 0;
559
560 /* This should not happen. A PWire can only become
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
561 PIMPLICIT if this is a UDP reg port, and the make_udp
a59bbde Proper error messages when port direction is missing.
steve authored
562 function should turn it into an output.... I think. */
563
564 case NetNet::PIMPLICIT:
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
565 cerr << get_fileline() << ": internal error: signal " << path_
c7d97f4 Properly evaluate scope path expressions.
steve authored
566 << " in module " << scope_path(scope) << " is left as "
a59bbde Proper error messages when port direction is missing.
steve authored
567 << "port type PIMPLICIT." << endl;
568 des->errors += 1;
569 return 0;
570 }
571
dfb7bf5 @steveicarus Handle part selects of nets that fall of the ends of the identifier.
authored
572 long midx;
573 long lidx;
3676d66 Module ports are really special PEIdent
steve authored
574
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
575 /* Evaluate the part/bit select expressions, to get the part
576 select of the signal that attaches to the port. Also handle
577 range and direction checking here. */
3676d66 Module ports are really special PEIdent
steve authored
578
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
579 if (! eval_part_select_(des, scope, sig, midx, lidx))
580 return 0;
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
581
3676d66 Module ports are really special PEIdent
steve authored
582
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
583 unsigned swid = midx - lidx + 1;
3676d66 Module ports are really special PEIdent
steve authored
584
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
585 if (swid < sig->vector_width()) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
586 cerr << get_fileline() << ": XXXX: Forgot to implement part select"
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
587 << " of signal port." << endl;
3676d66 Module ports are really special PEIdent
steve authored
588 }
589
590 return sig;
591 }
592
Something went wrong with that request. Please try again.