1 /*
2 * VHDL abstract syntax elements.
3 *
4 * Copyright (C) 2008-2013 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_syntax.hh"
22 #include "vhdl_helper.hh"
23
24 #include <cassert>
25 #include <cstring>
26 #include <iostream>
27 #include <typeinfo>
28 #include <algorithm>
29 #include <iomanip>
30
31 using namespace std;
32
vhdl_scope()33 vhdl_scope::vhdl_scope()
34 : parent_(NULL), init_(false), sig_assign_(true),
35 hoisted_init_(false)
36 {
37
38 }
39
~vhdl_scope()40 vhdl_scope::~vhdl_scope()
41 {
42
43 }
44
set_initializing(bool i)45 void vhdl_scope::set_initializing(bool i)
46 {
47 init_ = i;
48 if (parent_)
49 parent_->set_initializing(i);
50 }
51
add_decl(vhdl_decl * decl)52 void vhdl_scope::add_decl(vhdl_decl *decl)
53 {
54 decls_.push_back(decl);
55 }
56
add_forward_decl(vhdl_decl * decl)57 void vhdl_scope::add_forward_decl(vhdl_decl *decl)
58 {
59 decls_.push_front(decl);
60 }
61
get_decl(const std::string & name) const62 vhdl_decl *vhdl_scope::get_decl(const std::string &name) const
63 {
64 decl_list_t::const_iterator it;
65 for (it = decls_.begin(); it != decls_.end(); ++it) {
66 if (strcasecmp((*it)->get_name().c_str(), name.c_str()) == 0)
67 return *it;
68 }
69
70 return parent_ ? parent_->get_decl(name) : NULL;
71 }
72
have_declared(const std::string & name) const73 bool vhdl_scope::have_declared(const std::string &name) const
74 {
75 return get_decl(name) != NULL;
76 }
77
78 // True if `name' differs in all but case from another declaration
name_collides(const string & name) const79 bool vhdl_scope::name_collides(const string& name) const
80 {
81 const vhdl_decl* decl = get_decl(name);
82 if (decl)
83 return strcasecmp(decl->get_name().c_str(), name.c_str()) == 0;
84 else
85 return false;
86 }
87
contained_within(const vhdl_scope * other) const88 bool vhdl_scope::contained_within(const vhdl_scope *other) const
89 {
90 if (this == other)
91 return true;
92 else if (NULL == parent_)
93 return false;
94 else
95 return parent_->contained_within(other);
96 }
97
get_parent() const98 vhdl_scope *vhdl_scope::get_parent() const
99 {
100 assert(parent_);
101 return parent_;
102 }
103
hoisted_initialiser() const104 bool vhdl_scope::hoisted_initialiser() const
105 {
106 return hoisted_init_;
107 }
108
hoisted_initialiser(bool h)109 void vhdl_scope::hoisted_initialiser(bool h)
110 {
111 hoisted_init_ = h;
112 }
113
vhdl_entity(const string & name,vhdl_arch * arch,int depth__)114 vhdl_entity::vhdl_entity(const string& name, vhdl_arch *arch, int depth__)
115 : depth(depth__), name_(name), arch_(arch),
116 time_unit_(TIME_UNIT_NS)
117 {
118 arch->get_scope()->set_parent(&ports_);
119 }
120
~vhdl_entity()121 vhdl_entity::~vhdl_entity()
122 {
123
124 }
125
add_port(vhdl_port_decl * decl)126 void vhdl_entity::add_port(vhdl_port_decl *decl)
127 {
128 ports_.add_decl(decl);
129 }
130
emit(std::ostream & of,int level) const131 void vhdl_entity::emit(std::ostream &of, int level) const
132 {
133 // Pretty much every design will use std_logic so we
134 // might as well include it by default
135 of << "library ieee;" << std::endl;
136 of << "use ieee.std_logic_1164.all;" << std::endl;
137 of << "use ieee.numeric_std.all;" << std::endl;
138 of << std::endl;
139
140 emit_comment(of, level);
141 of << "entity " << name_ << " is";
142
143 if (!ports_.empty()) {
144 newline(of, indent(level));
145 of << "port (";
146 emit_children<vhdl_decl>(of, ports_.get_decls(), indent(level), ";");
147 of << ");";
148 }
149
150 newline(of, level);
151 of << "end entity; ";
152 blank_line(of, level); // Extra blank line after entities
153 arch_->emit(of, level);
154 }
155
156 // Return a VHDL time constant scaled to the correct time scale
157 // for this entity
scale_time(const vhdl_entity * ent,uint64_t t)158 vhdl_const_time* scale_time(const vhdl_entity* ent, uint64_t t)
159 {
160 return new vhdl_const_time(t, ent->time_unit_);
161 }
162
163 // Work out the best VHDL units to use given the Verilog timescale
set_time_units(int units,int precision)164 void vhdl_entity::set_time_units(int units, int precision)
165 {
166 int vhdl_units = std::min(units, precision);
167
168 if (vhdl_units >= -3)
169 time_unit_ = TIME_UNIT_MS;
170 else if (vhdl_units >= -6)
171 time_unit_ = TIME_UNIT_US;
172 else if (vhdl_units >= -9)
173 time_unit_ = TIME_UNIT_NS;
174 else
175 time_unit_ = TIME_UNIT_PS;
176 }
177
~vhdl_arch()178 vhdl_arch::~vhdl_arch()
179 {
180
181 }
182
add_stmt(vhdl_process * proc)183 void vhdl_arch::add_stmt(vhdl_process *proc)
184 {
185 proc->get_scope()->set_parent(&scope_);
186 stmts_.push_back(proc);
187 }
188
add_stmt(vhdl_conc_stmt * stmt)189 void vhdl_arch::add_stmt(vhdl_conc_stmt *stmt)
190 {
191 stmts_.push_back(stmt);
192 }
193
emit(std::ostream & of,int level) const194 void vhdl_arch::emit(std::ostream &of, int level) const
195 {
196 emit_comment(of, level);
197 of << "architecture " << name_ << " of " << entity_;
198 of << " is";
199 emit_children<vhdl_decl>(of, scope_.get_decls(), level);
200 of << "begin";
201 emit_children<vhdl_conc_stmt>(of, stmts_, level);
202 of << "end architecture;";
203 blank_line(of, level); // Extra blank line after architectures;
204 }
205
add_blocking_target(vhdl_var_ref * ref)206 void vhdl_procedural::add_blocking_target(vhdl_var_ref* ref)
207 {
208 blocking_targets_.insert(ref->get_name());
209 }
210
is_blocking_target(vhdl_var_ref * ref) const211 bool vhdl_procedural::is_blocking_target(vhdl_var_ref* ref) const
212 {
213 return blocking_targets_.find(ref->get_name()) != blocking_targets_.end();
214 }
215
add_sensitivity(const std::string & name)216 void vhdl_process::add_sensitivity(const std::string &name)
217 {
218 sens_.push_back(name);
219 }
220
emit(std::ostream & of,int level) const221 void vhdl_process::emit(std::ostream &of, int level) const
222 {
223 // If there are no statements in the body, this process
224 // can't possibly do anything, so don't bother to emit it
225 if (stmts_.empty()) {
226 of << "-- Removed one empty process";
227 newline(of, level);
228 return;
229 }
230
231 newline(of, level);
232 emit_comment(of, level);
233 if (! name_.empty())
234 of << name_ << ": ";
235 of << "process ";
236
237 int num_sens = sens_.size();
238 if (num_sens > 0) {
239 of << "(";
240 string_list_t::const_iterator it;
241 for (it = sens_.begin(); it != sens_.end(); ++it) {
242 of << *it;
243 if (--num_sens > 0)
244 of << ", ";
245 }
246 of << ") ";
247 }
248
249 of << "is";
250 emit_children<vhdl_decl>(of, scope_.get_decls(), level);
251 of << "begin";
252 stmts_.emit(of, level);
253 of << "end process;";
254 }
255
~stmt_container()256 stmt_container::~stmt_container()
257 {
258
259 }
260
add_stmt(vhdl_seq_stmt * stmt)261 void stmt_container::add_stmt(vhdl_seq_stmt *stmt)
262 {
263 // Add a statement at the end of the block
264 stmts_.push_back(stmt);
265 }
266
267 /*
268 * Move all the statements from one container into another.
269 * This is useful, for example, if we want to wrap a container
270 * in an `if' statement.
271 */
move_stmts_from(stmt_container * other)272 void stmt_container::move_stmts_from(stmt_container *other)
273 {
274 copy(other->stmts_.begin(), other->stmts_.end(), back_inserter(stmts_));
275 other->stmts_.clear();
276 }
277
find_vars(vhdl_var_set_t & read,vhdl_var_set_t & write)278 void stmt_container::find_vars(vhdl_var_set_t& read,
279 vhdl_var_set_t& write)
280 {
281 // Iterate over each sub-statement and find all its
282 // read/written variables
283
284 for (stmt_list_t::const_iterator it = stmts_.begin();
285 it != stmts_.end(); ++it)
286 (*it)->find_vars(read, write);
287 }
288
emit(std::ostream & of,int level,bool newline) const289 void stmt_container::emit(std::ostream &of, int level, bool newline) const
290 {
291 emit_children<vhdl_seq_stmt>(of, stmts_, level, "", newline);
292 }
293
vhdl_comp_inst(const char * inst_name,const char * comp_name)294 vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name)
295 : comp_name_(comp_name), inst_name_(inst_name)
296 {
297
298 }
299
~vhdl_comp_inst()300 vhdl_comp_inst::~vhdl_comp_inst()
301 {
302
303 }
304
map_port(const string & name,vhdl_expr * expr)305 void vhdl_comp_inst::map_port(const string& name, vhdl_expr *expr)
306 {
307 port_map_t pmap = { name, expr };
308 mapping_.push_back(pmap);
309 }
310
emit(std::ostream & of,int level) const311 void vhdl_comp_inst::emit(std::ostream &of, int level) const
312 {
313 newline(of, level);
314 emit_comment(of, level);
315 of << inst_name_ << ": " << comp_name_;
316
317 // If there are no ports or generics we don't need to mention them...
318 if (! mapping_.empty()) {
319 newline(of, indent(level));
320 of << "port map (";
321
322 int sz = mapping_.size();
323 port_map_list_t::const_iterator it;
324 for (it = mapping_.begin(); it != mapping_.end(); ++it) {
325 newline(of, indent(indent(level)));
326 of << (*it).name << " => ";
327 (*it).expr->emit(of, level);
328 if (--sz > 0)
329 of << ",";
330 }
331 newline(of, indent(level));
332 of << ")";
333 }
334
335 of << ";";
336 }
337
vhdl_component_decl(const char * name)338 vhdl_component_decl::vhdl_component_decl(const char *name)
339 : vhdl_decl(name)
340 {
341
342 }
343
344 /*
345 * Create a component declaration for the given entity.
346 */
component_decl_for(vhdl_entity * ent)347 vhdl_component_decl *vhdl_component_decl::component_decl_for(vhdl_entity *ent)
348 {
349 assert(ent != NULL);
350
351 vhdl_component_decl *decl = new vhdl_component_decl
352 (ent->get_name().c_str());
353
354 decl->ports_ = ent->get_scope()->get_decls();
355
356 return decl;
357 }
358
emit(std::ostream & of,int level) const359 void vhdl_component_decl::emit(std::ostream &of, int level) const
360 {
361 newline(of, level);
362 emit_comment(of, level);
363 of << "component " << name_ << " is";
364
365 if (! ports_.empty()) {
366 newline(of, indent(level));
367 of << "port (";
368 emit_children<vhdl_decl>(of, ports_, indent(level), ";");
369 of << ");";
370 }
371
372 newline(of, level);
373 of << "end component;";
374 }
375
~vhdl_wait_stmt()376 vhdl_wait_stmt::~vhdl_wait_stmt()
377 {
378
379 }
380
find_vars(vhdl_var_set_t & read,vhdl_var_set_t &)381 void vhdl_wait_stmt::find_vars(vhdl_var_set_t& read,
382 vhdl_var_set_t&)
383 {
384 if (expr_)
385 expr_->find_vars(read);
386 }
387
emit(std::ostream & of,int level) const388 void vhdl_wait_stmt::emit(std::ostream &of, int level) const
389 {
390 of << "wait";
391
392 switch (type_) {
393 case VHDL_WAIT_INDEF:
394 break;
395 case VHDL_WAIT_FOR:
396 assert(expr_);
397 of << " for ";
398 expr_->emit(of, level);
399 break;
400 case VHDL_WAIT_FOR0:
401 of << " for 0 ns";
402 break;
403 case VHDL_WAIT_UNTIL:
404 assert(expr_);
405 of << " until ";
406 expr_->emit(of, level);
407 break;
408 case VHDL_WAIT_ON:
409 {
410 of << " on ";
411 string_list_t::const_iterator it = sensitivity_.begin();
412 while (it != sensitivity_.end()) {
413 of << *it;
414 if (++it != sensitivity_.end())
415 of << ", ";
416 }
417 }
418 break;
419 }
420
421 of << ";";
422 emit_comment(of, level, true);
423 }
424
~vhdl_decl()425 vhdl_decl::~vhdl_decl()
426 {
427
428 }
429
430 // Make a reference object to this declaration
make_ref() const431 vhdl_var_ref* vhdl_decl::make_ref() const
432 {
433 return new vhdl_var_ref(name_, type_);
434 }
435
get_type() const436 const vhdl_type *vhdl_decl::get_type() const
437 {
438 assert(type_);
439 return type_;
440 }
441
set_initial(vhdl_expr * initial)442 void vhdl_decl::set_initial(vhdl_expr *initial)
443 {
444 if (!has_initial_) {
445 assert(initial_ == NULL);
446 initial_ = initial;
447 has_initial_ = true;
448 }
449 }
450
emit(std::ostream & of,int level) const451 void vhdl_port_decl::emit(std::ostream &of, int level) const
452 {
453 of << name_ << " : ";
454
455 switch (mode_) {
456 case VHDL_PORT_IN:
457 of << "in ";
458 break;
459 case VHDL_PORT_OUT:
460 of << "out ";
461 break;
462 case VHDL_PORT_INOUT:
463 of << "inout ";
464 break;
465 case VHDL_PORT_BUFFER:
466 of << "buffer ";
467 break;
468 }
469
470 type_->emit(of, level);
471 }
472
473 // If this is an `out' port make it a `buffer' so we can read from it
ensure_readable()474 void vhdl_port_decl::ensure_readable()
475 {
476 if (mode_ == VHDL_PORT_OUT)
477 mode_ = VHDL_PORT_BUFFER;
478 }
479
480 // A port is readable if it is not `out'.
481 // We also make `buffer' ports not readable for these purposes since
482 // buffers cannot be directly mapped to outputs without an intermediate
483 // signal.
is_readable() const484 bool vhdl_port_decl::is_readable() const
485 {
486 return mode_ != VHDL_PORT_OUT && mode_ != VHDL_PORT_BUFFER;
487 }
488
emit(std::ostream & of,int level) const489 void vhdl_var_decl::emit(std::ostream &of, int level) const
490 {
491 of << "variable " << name_ << " : ";
492 type_->emit(of, level);
493
494 if (initial_) {
495 of << " := ";
496 initial_->emit(of, level);
497 }
498
499 of << ";";
500 emit_comment(of, level, true);
501 }
502
emit(std::ostream & of,int level) const503 void vhdl_signal_decl::emit(std::ostream &of, int level) const
504 {
505 of << "signal " << name_ << " : ";
506 type_->emit(of, level);
507
508 if (initial_) {
509 of << " := ";
510 initial_->emit(of, level);
511 }
512
513 of << ";";
514 emit_comment(of, level, true);
515 }
516
emit(std::ostream & of,int level) const517 void vhdl_type_decl::emit(std::ostream &of, int level) const
518 {
519 of << "type " << name_ << " is ";
520 of << type_->get_type_decl_string() << ";";
521 emit_comment(of, level, true);
522 }
523
~vhdl_expr()524 vhdl_expr::~vhdl_expr()
525 {
526
527 }
528
add_expr(vhdl_expr * e)529 void vhdl_expr_list::add_expr(vhdl_expr *e)
530 {
531 exprs_.push_back(e);
532 }
533
~vhdl_expr_list()534 vhdl_expr_list::~vhdl_expr_list()
535 {
536
537 }
538
find_vars(vhdl_var_set_t & read)539 void vhdl_expr_list::find_vars(vhdl_var_set_t& read)
540 {
541 for (list<vhdl_expr*>::const_iterator it = exprs_.begin();
542 it != exprs_.end(); ++it)
543 (*it)->find_vars(read);
544 }
545
emit(std::ostream & of,int level) const546 void vhdl_expr_list::emit(std::ostream &of, int level) const
547 {
548 of << "(";
549
550 int size = exprs_.size();
551 std::list<vhdl_expr*>::const_iterator it;
552 for (it = exprs_.begin(); it != exprs_.end(); ++it) {
553 (*it)->emit(of, level);
554 if (--size > 0)
555 of << ", ";
556 }
557
558 of << ")";
559 }
560
emit(std::ostream & of,int level) const561 void vhdl_pcall_stmt::emit(std::ostream &of, int level) const
562 {
563 of << name_;
564 if (!exprs_.empty())
565 exprs_.emit(of, level);
566 of << ";";
567 }
568
find_vars(vhdl_var_set_t & read,vhdl_var_set_t &)569 void vhdl_pcall_stmt::find_vars(vhdl_var_set_t& read,
570 vhdl_var_set_t&)
571 {
572 exprs_.find_vars(read);
573 }
574
~vhdl_var_ref()575 vhdl_var_ref::~vhdl_var_ref()
576 {
577
578 }
579
set_slice(vhdl_expr * s,int w)580 void vhdl_var_ref::set_slice(vhdl_expr *s, int w)
581 {
582 assert(type_);
583
584 slice_ = s;
585 slice_width_ = w;
586
587 vhdl_type_name_t tname = type_->get_name();
588 if (tname == VHDL_TYPE_ARRAY) {
589 type_ = type_->get_base();
590 }
591 else {
592 assert(tname == VHDL_TYPE_UNSIGNED || tname == VHDL_TYPE_SIGNED);
593
594 if (w > 0)
595 type_ = new vhdl_type(tname, w);
596 else
597 type_ = vhdl_type::std_logic();
598 }
599 }
600
find_vars(vhdl_var_set_t & read)601 void vhdl_var_ref::find_vars(vhdl_var_set_t& read)
602 {
603 read.insert(this);
604 }
605
emit(std::ostream & of,int level) const606 void vhdl_var_ref::emit(std::ostream &of, int level) const
607 {
608 of << name_;
609 if (slice_) {
610 of << "(";
611 if (slice_width_ > 0) {
612 slice_->emit(of, level);
613 of << " + " << slice_width_ << " downto ";
614 }
615 slice_->emit(of, level);
616 of << ")";
617 }
618 }
619
emit(std::ostream & of,int) const620 void vhdl_const_string::emit(std::ostream &of, int) const
621 {
622 of << "\"" << value_ << "\"";
623 }
624
emit(std::ostream & of,int level) const625 void vhdl_null_stmt::emit(std::ostream &of, int level) const
626 {
627 of << "null;";
628 emit_comment(of, level, true);
629 }
630
find_vars(vhdl_var_set_t & read)631 void vhdl_fcall::find_vars(vhdl_var_set_t& read)
632 {
633 exprs_.find_vars(read);
634 }
635
emit(std::ostream & of,int level) const636 void vhdl_fcall::emit(std::ostream &of, int level) const
637 {
638 of << name_;
639 exprs_.emit(of, level);
640 }
641
~vhdl_abstract_assign_stmt()642 vhdl_abstract_assign_stmt::~vhdl_abstract_assign_stmt()
643 {
644
645 }
646
find_vars(vhdl_var_set_t & read,vhdl_var_set_t & write)647 void vhdl_abstract_assign_stmt::find_vars(vhdl_var_set_t& read,
648 vhdl_var_set_t& write)
649 {
650 lhs_->find_vars(write);
651 rhs_->find_vars(read);
652 }
653
emit(std::ostream & of,int level) const654 void vhdl_nbassign_stmt::emit(std::ostream &of, int level) const
655 {
656 lhs_->emit(of, level);
657 of << " <= ";
658 rhs_->emit(of, level);
659
660 if (after_) {
661 of << " after ";
662 after_->emit(of, level);
663 }
664
665 of << ";";
666 }
667
emit(std::ostream & of,int level) const668 void vhdl_assign_stmt::emit(std::ostream &of, int level) const
669 {
670 lhs_->emit(of, level);
671 of << " := ";
672 rhs_->emit(of, level);
673 of << ";";
674 }
675
vhdl_const_bits(const char * value,int width,bool issigned,bool qualify)676 vhdl_const_bits::vhdl_const_bits(const char *value, int width, bool issigned,
677 bool qualify)
678 : vhdl_expr(issigned ? vhdl_type::nsigned(width)
679 : vhdl_type::nunsigned(width), true),
680 qualified_(qualify),
681 signed_(issigned)
682 {
683 // Can't rely on value being NULL-terminated
684 while (width--)
685 value_.push_back(*value++);
686 }
687
688 // True if char is not '1' or '0'
is_meta_bit(char c)689 static bool is_meta_bit(char c)
690 {
691 return c != '1' && c != '0';
692 }
693
694 // True if the bit strings contains characters other than '1' and '0'
has_meta_bits() const695 bool vhdl_const_bits::has_meta_bits() const
696 {
697 return find_if(value_.begin(), value_.end(), is_meta_bit) != value_.end();
698 }
699
emit(std::ostream & of,int) const700 void vhdl_const_bits::emit(std::ostream &of, int) const
701 {
702 if (qualified_)
703 of << (signed_ ? "signed" : "unsigned") << "'(";
704
705 // If it's a width we can write in hex, prefer that over binary
706 size_t bits = value_.size();
707 int64_t ival = bits_to_int();
708 if ((!signed_ || ival >= 0)
709 && !has_meta_bits() && bits <= 64 && bits % 4 == 0) {
710 of << "X\"" << hex << setfill('0') << setw(bits / 4) << ival;
711 }
712 else {
713 of << "\"";
714
715 std::string::const_reverse_iterator it;
716 for (it = value_.rbegin(); it != value_.rend(); ++it)
717 of << vl_to_vhdl_bit(*it);
718 }
719
720 of << (qualified_ ? "\")" : "\"");
721 }
722
emit(std::ostream & of,int) const723 void vhdl_const_bit::emit(std::ostream &of, int) const
724 {
725 of << "'" << vl_to_vhdl_bit(bit_) << "'";
726 }
727
emit(std::ostream & of,int) const728 void vhdl_const_int::emit(std::ostream &of, int) const
729 {
730 of << dec << value_;
731 // We need to find a way to display a comment, since $time, etc. add one.
732 }
733
emit(std::ostream & of,int) const734 void vhdl_const_bool::emit(std::ostream &of, int) const
735 {
736 of << (value_ ? "True" : "False");
737 }
738
emit(std::ostream & of,int) const739 void vhdl_const_time::emit(std::ostream &of, int) const
740 {
741 of << dec << value_;
742 switch (units_) {
743 case TIME_UNIT_PS: of << " ps"; break;
744 case TIME_UNIT_NS: of << " ns"; break;
745 case TIME_UNIT_US: of << " us"; break;
746 case TIME_UNIT_MS: of << " ms"; break;
747 }
748 }
749
~vhdl_cassign_stmt()750 vhdl_cassign_stmt::~vhdl_cassign_stmt()
751 {
752
753 }
754
add_condition(vhdl_expr * value,vhdl_expr * cond)755 void vhdl_cassign_stmt::add_condition(vhdl_expr *value, vhdl_expr *cond)
756 {
757 when_part_t when = { value, cond, NULL };
758 whens_.push_back(when);
759 }
760
emit(std::ostream & of,int level) const761 void vhdl_cassign_stmt::emit(std::ostream &of, int level) const
762 {
763 lhs_->emit(of, level);
764 of << " <= ";
765 if (!whens_.empty()) {
766 for (std::list<when_part_t>::const_iterator it = whens_.begin();
767 it != whens_.end();
768 ++it) {
769 (*it).value->emit(of, level);
770 of << " when ";
771 (*it).cond->emit(of, level);
772 of << " ";
773 }
774 of << "else ";
775 }
776 rhs_->emit(of, level);
777
778 if (after_) {
779 of << " after ";
780 after_->emit(of, level);
781 }
782
783 of << ";";
784 }
785
vhdl_report_stmt(vhdl_expr * text,vhdl_severity_t severity)786 vhdl_report_stmt::vhdl_report_stmt(vhdl_expr *text,
787 vhdl_severity_t severity)
788 : severity_(severity),
789 text_(text)
790 {
791
792 }
793
emit(ostream & of,int level) const794 void vhdl_report_stmt::emit(ostream& of, int level) const
795 {
796 of << "report ";
797 text_->emit(of, level);
798
799 if (severity_ != SEVERITY_NOTE) {
800 const char *levels[] = { "note", "warning", "error", "failure" };
801 of << " severity " << levels[severity_];
802 }
803
804 of << ";";
805 }
806
find_vars(vhdl_var_set_t & read,vhdl_var_set_t &)807 void vhdl_report_stmt::find_vars(vhdl_var_set_t& read, vhdl_var_set_t&)
808 {
809 text_->find_vars(read);
810 }
811
vhdl_assert_stmt(const char * reason)812 vhdl_assert_stmt::vhdl_assert_stmt(const char *reason)
813 : vhdl_report_stmt(new vhdl_const_string(reason), SEVERITY_FAILURE)
814 {
815
816 }
817
emit(std::ostream & of,int level) const818 void vhdl_assert_stmt::emit(std::ostream &of, int level) const
819 {
820 of << "assert false "; // TODO: Allow arbitrary expression
821 vhdl_report_stmt::emit(of, level);
822 }
823
vhdl_if_stmt(vhdl_expr * test)824 vhdl_if_stmt::vhdl_if_stmt(vhdl_expr *test)
825 {
826 // Need to ensure that the expression is Boolean
827 vhdl_type boolean(VHDL_TYPE_BOOLEAN);
828 test_ = test->cast(&boolean);
829 }
830
~vhdl_if_stmt()831 vhdl_if_stmt::~vhdl_if_stmt()
832 {
833
834 }
835
add_elsif(vhdl_expr * test)836 stmt_container *vhdl_if_stmt::add_elsif(vhdl_expr *test)
837 {
838 elsif ef = { test, new stmt_container };
839 elsif_parts_.push_back(ef);
840 return ef.container;
841 }
842
emit(std::ostream & of,int level) const843 void vhdl_if_stmt::emit(std::ostream &of, int level) const
844 {
845 emit_comment(of, level);
846
847 of << "if ";
848 test_->emit(of, level);
849 of << " then";
850 then_part_.emit(of, level);
851
852 std::list<elsif>::const_iterator it;
853 for (it = elsif_parts_.begin(); it != elsif_parts_.end(); ++it) {
854 of << "elsif ";
855 (*it).test->emit(of, level);
856 of << " then";
857 (*it).container->emit(of, level);
858 }
859
860 if (!else_part_.empty()) {
861 of << "else";
862 else_part_.emit(of, level);
863 }
864 of << "end if;";
865 }
866
find_vars(vhdl_var_set_t & read,vhdl_var_set_t & write)867 void vhdl_if_stmt::find_vars(vhdl_var_set_t& read,
868 vhdl_var_set_t& write)
869 {
870 test_->find_vars(read);
871
872 then_part_.find_vars(read, write);
873 else_part_.find_vars(read, write);
874
875 for (list<elsif>::const_iterator it = elsif_parts_.begin();
876 it != elsif_parts_.end(); ++it) {
877 (*it).test->find_vars(read);
878 (*it).container->find_vars(read, write);
879 }
880 }
881
882 int vhdl_expr::paren_levels(0);
883
open_parens(std::ostream & of)884 void vhdl_expr::open_parens(std::ostream& of)
885 {
886 if (paren_levels++ > 0)
887 of << "(";
888 }
889
close_parens(std::ostream & of)890 void vhdl_expr::close_parens(std::ostream& of)
891 {
892 assert(paren_levels > 0);
893
894 if (--paren_levels > 0)
895 of << ")";
896 }
897
~vhdl_unaryop_expr()898 vhdl_unaryop_expr::~vhdl_unaryop_expr()
899 {
900
901 }
902
find_vars(vhdl_var_set_t & read)903 void vhdl_unaryop_expr::find_vars(vhdl_var_set_t& read)
904 {
905 operand_->find_vars(read);
906 }
907
emit(std::ostream & of,int level) const908 void vhdl_unaryop_expr::emit(std::ostream &of, int level) const
909 {
910 open_parens(of);
911
912 switch (op_) {
913 case VHDL_UNARYOP_NOT:
914 of << "not ";
915 break;
916 case VHDL_UNARYOP_NEG:
917 of << "-";
918 break;
919 }
920 operand_->emit(of, level);
921
922 close_parens(of);
923 }
924
vhdl_binop_expr(vhdl_expr * left,vhdl_binop_t op,vhdl_expr * right,const vhdl_type * type)925 vhdl_binop_expr::vhdl_binop_expr(vhdl_expr *left, vhdl_binop_t op,
926 vhdl_expr *right, const vhdl_type *type)
927 : vhdl_expr(type), op_(op)
928 {
929 add_expr(left);
930 add_expr(right);
931 }
932
~vhdl_binop_expr()933 vhdl_binop_expr::~vhdl_binop_expr()
934 {
935
936 }
937
add_expr(vhdl_expr * e)938 void vhdl_binop_expr::add_expr(vhdl_expr *e)
939 {
940 operands_.push_back(e);
941 }
942
add_expr_front(vhdl_expr * e)943 void vhdl_binop_expr::add_expr_front(vhdl_expr *e)
944 {
945 operands_.push_front(e);
946 }
947
find_vars(vhdl_var_set_t & read)948 void vhdl_binop_expr::find_vars(vhdl_var_set_t& read)
949 {
950 for (list<vhdl_expr*>::const_iterator it = operands_.begin();
951 it != operands_.end(); ++it)
952 (*it)->find_vars(read);
953 }
954
emit(std::ostream & of,int level) const955 void vhdl_binop_expr::emit(std::ostream &of, int level) const
956 {
957 open_parens(of);
958
959 assert(! operands_.empty());
960 std::list<vhdl_expr*>::const_iterator it = operands_.begin();
961
962 (*it)->emit(of, level);
963 while (++it != operands_.end()) {
964 const char* ops[] = {
965 "and", "or", "=", "/=", "+", "-", "*", "<",
966 ">", "<=", ">=", "sll", "srl", "xor", "&",
967 "nand", "nor", "xnor", "/", "mod", "**", "sra", NULL
968 };
969
970 of << " " << ops[op_] << " ";
971
972 (*it)->emit(of, level);
973 }
974
975 close_parens(of);
976 }
977
~vhdl_bit_spec_expr()978 vhdl_bit_spec_expr::~vhdl_bit_spec_expr()
979 {
980
981 }
982
add_bit(int bit,vhdl_expr * e)983 void vhdl_bit_spec_expr::add_bit(int bit, vhdl_expr *e)
984 {
985 bit_map bm = { bit, e };
986 bits_.push_back(bm);
987 }
988
emit(std::ostream & of,int level) const989 void vhdl_bit_spec_expr::emit(std::ostream &of, int level) const
990 {
991 of << "(";
992
993 std::list<bit_map>::const_iterator it;
994 it = bits_.begin();
995 while (it != bits_.end()) {
996 of << (*it).bit << " => ";
997 (*it).e->emit(of, level);
998 if (++it != bits_.end())
999 of << ", ";
1000 }
1001
1002 if (others_) {
1003 of << (bits_.empty() ? "" : ", ") << "others => ";
1004 others_->emit(of, level);
1005 }
1006
1007 of << ")";
1008 }
1009
~vhdl_case_branch()1010 vhdl_case_branch::~vhdl_case_branch()
1011 {
1012
1013 }
1014
emit(std::ostream & of,int level) const1015 void vhdl_case_branch::emit(std::ostream &of, int level) const
1016 {
1017 of << "when ";
1018 when_->emit(of, level);
1019 of << " =>";
1020 stmts_.emit(of, indent(level), false);
1021 }
1022
~vhdl_case_stmt()1023 vhdl_case_stmt::~vhdl_case_stmt()
1024 {
1025
1026 }
1027
find_vars(vhdl_var_set_t & read,vhdl_var_set_t & write)1028 void vhdl_case_stmt::find_vars(vhdl_var_set_t& read,
1029 vhdl_var_set_t& write)
1030 {
1031 test_->find_vars(read);
1032
1033 for (case_branch_list_t::const_iterator it = branches_.begin();
1034 it != branches_.end(); ++it) {
1035 (*it)->when_->find_vars(read);
1036 (*it)->stmts_.find_vars(read, write);
1037 }
1038 }
1039
emit(std::ostream & of,int level) const1040 void vhdl_case_stmt::emit(std::ostream &of, int level) const
1041 {
1042 of << "case ";
1043 test_->emit(of, level);
1044 of << " is";
1045 newline(of, indent(level));
1046
1047 case_branch_list_t::const_iterator it;
1048 int n = branches_.size();
1049 for (it = branches_.begin(); it != branches_.end(); ++it) {
1050 (*it)->emit(of, level);
1051 if (--n > 0)
1052 newline(of, indent(level));
1053 else
1054 newline(of, level);
1055 }
1056
1057 of << "end case;";
1058 }
1059
~vhdl_while_stmt()1060 vhdl_while_stmt::~vhdl_while_stmt()
1061 {
1062
1063 }
1064
find_vars(vhdl_var_set_t & read,vhdl_var_set_t & write)1065 void vhdl_while_stmt::find_vars(vhdl_var_set_t& read,
1066 vhdl_var_set_t& write)
1067 {
1068 test_->find_vars(read);
1069
1070 vhdl_loop_stmt::find_vars(read, write);
1071 }
1072
emit(std::ostream & of,int level) const1073 void vhdl_while_stmt::emit(std::ostream &of, int level) const
1074 {
1075 of << "while ";
1076 test_->emit(of, level);
1077 of << " ";
1078 vhdl_loop_stmt::emit(of, level);
1079 }
1080
find_vars(vhdl_var_set_t & read,vhdl_var_set_t & write)1081 void vhdl_loop_stmt::find_vars(vhdl_var_set_t& read,
1082 vhdl_var_set_t& write)
1083 {
1084 stmts_.find_vars(read, write);
1085 }
1086
emit(std::ostream & of,int level) const1087 void vhdl_loop_stmt::emit(std::ostream &of, int level) const
1088 {
1089 of << "loop";
1090 stmts_.emit(of, level);
1091 of << "end loop;";
1092 }
1093
~vhdl_for_stmt()1094 vhdl_for_stmt::~vhdl_for_stmt()
1095 {
1096
1097 }
1098
1099
find_vars(vhdl_var_set_t & read,vhdl_var_set_t & write)1100 void vhdl_for_stmt::find_vars(vhdl_var_set_t& read,
1101 vhdl_var_set_t& write)
1102 {
1103 from_->find_vars(read);
1104 to_->find_vars(write);
1105
1106 vhdl_loop_stmt::find_vars(read, write);
1107 }
1108
emit(std::ostream & of,int level) const1109 void vhdl_for_stmt::emit(std::ostream &of, int level) const
1110 {
1111 of << "for " << lname_ << " in ";
1112 from_->emit(of, level);
1113 of << " to ";
1114 to_->emit(of, level);
1115 of << " ";
1116 vhdl_loop_stmt::emit(of, level);
1117 }
1118
vhdl_function(const char * name,vhdl_type * ret_type)1119 vhdl_function::vhdl_function(const char *name, vhdl_type *ret_type)
1120 : vhdl_decl(name, ret_type)
1121 {
1122 // A function contains two scopes:
1123 // scope_ = The parameters
1124 // variables_ = Local variables
1125 // A call to get_scope returns variables_ whose parent is scope_
1126 variables_.set_parent(&scope_);
1127 }
1128
emit(std::ostream & of,int level) const1129 void vhdl_function::emit(std::ostream &of, int level) const
1130 {
1131 newline(of, level);
1132 emit_comment(of, level);
1133 of << "function " << name_ << " (";
1134 emit_children<vhdl_decl>(of, scope_.get_decls(), level, ";");
1135 of << ") ";
1136 newline(of, level);
1137 of << "return " << type_->get_string() << " is";
1138 emit_children<vhdl_decl>(of, variables_.get_decls(), level);
1139 of << "begin";
1140 stmts_.emit(of, level);
1141 of << " return " << name_ << "_Result;";
1142 newline(of, level);
1143 of << "end function;";
1144 }
1145
emit(std::ostream & of,int level) const1146 void vhdl_forward_fdecl::emit(std::ostream &of, int level) const
1147 {
1148 of << "function " << f_->get_name() << " (";
1149 emit_children<vhdl_decl>(of, f_->scope_.get_decls(), level, ";");
1150 of << ") ";
1151 newline(of, level);
1152 of << "return " << f_->type_->get_string() << ";";
1153 newline(of, level);
1154 }
1155
emit(std::ostream & of,int level) const1156 void vhdl_param_decl::emit(std::ostream &of, int level) const
1157 {
1158 of << name_ << " : ";
1159 type_->emit(of, level);
1160 }
1161
~vhdl_with_select_stmt()1162 vhdl_with_select_stmt::~vhdl_with_select_stmt()
1163 {
1164
1165 }
1166
emit(std::ostream & of,int level) const1167 void vhdl_with_select_stmt::emit(std::ostream &of, int level) const
1168 {
1169 of << "with ";
1170 test_->emit(of, level);
1171 of << " select";
1172 emit_comment(of, level, true);
1173 newline(of, indent(level));
1174
1175 out_->emit(of, level);
1176 of << " <= ";
1177
1178 when_list_t::const_iterator it = whens_.begin();
1179 while (it != whens_.end()) {
1180 (*it).value->emit(of, level);
1181 if ((*it).delay) {
1182 of << " after ";
1183 (*it).delay->emit(of, level);
1184 }
1185 of << " when ";
1186 (*it).cond->emit(of, level);
1187
1188 if (++it != whens_.end() || others_ != NULL) {
1189 of << ",";
1190 newline(of, indent(level));
1191 }
1192 else
1193 of << ";";
1194 }
1195
1196 if (others_) {
1197 others_->emit(of, level);
1198 of << " when others;";
1199 }
1200 }
1201
add_condition(vhdl_expr * value,vhdl_expr * cond,vhdl_expr * delay)1202 void vhdl_with_select_stmt::add_condition(vhdl_expr *value, vhdl_expr *cond, vhdl_expr *delay)
1203 {
1204 when_part_t when = { value, cond, delay };
1205 whens_.push_back(when);
1206 }
1207
add_default(vhdl_expr * value)1208 void vhdl_with_select_stmt::add_default(vhdl_expr* value)
1209 {
1210 others_ = value;
1211 }
1212