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