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 #ifndef INC_VHDL_SYNTAX_HH
22 #define INC_VHDL_SYNTAX_HH
23 
24 #include <inttypes.h>
25 #include <set>
26 #include <cassert>
27 #include "vhdl_element.hh"
28 #include "vhdl_type.hh"
29 
30 using namespace std;
31 
32 class vhdl_scope;
33 class vhdl_entity;
34 class vhdl_arch;
35 class vhdl_var_ref;
36 
37 typedef set<vhdl_var_ref*> vhdl_var_set_t;
38 
39 class vhdl_expr : public vhdl_element {
40 public:
vhdl_expr(const vhdl_type * type,bool isconst=false)41    vhdl_expr(const vhdl_type* type, bool isconst=false)
42       : type_(type), isconst_(isconst) {}
43    virtual ~vhdl_expr();
44 
get_type() const45    const vhdl_type *get_type() const { return type_; }
constant() const46    bool constant() const { return isconst_; }
47 
48    vhdl_expr *cast(const vhdl_type *to);
49    virtual vhdl_expr *resize(int newwidth);
50    virtual vhdl_expr *to_boolean();
51    virtual vhdl_expr *to_integer();
52    virtual vhdl_expr *to_std_logic();
53    virtual vhdl_expr *to_std_ulogic();
54    virtual vhdl_expr *to_vector(vhdl_type_name_t name, int w);
55    virtual vhdl_expr *to_string();
find_vars(vhdl_var_set_t &)56    virtual void find_vars(vhdl_var_set_t&) {}
57 
58 protected:
59    static void open_parens(ostream& of);
60    static void close_parens(ostream& of);
61    static int paren_levels;
62 
63    const vhdl_type *type_;
64    bool isconst_;
65 };
66 
67 
68 /*
69  * A scalar or array variable reference.
70  */
71 class vhdl_var_ref : public vhdl_expr {
72 public:
vhdl_var_ref(const string & name,const vhdl_type * type,vhdl_expr * slice=NULL)73    vhdl_var_ref(const string& name, const vhdl_type *type,
74                 vhdl_expr *slice = NULL)
75       : vhdl_expr(type), name_(name), slice_(slice), slice_width_(0) {}
76    ~vhdl_var_ref();
77 
78    void emit(std::ostream &of, int level) const;
get_name() const79    const std::string &get_name() const { return name_; }
set_name(const std::string & name)80    void set_name(const std::string &name) { name_ = name; }
81    void set_slice(vhdl_expr *s, int w=0);
82    void find_vars(vhdl_var_set_t& read);
83 private:
84    std::string name_;
85    vhdl_expr *slice_;
86    unsigned slice_width_;
87 };
88 
89 enum vhdl_binop_t {
90    VHDL_BINOP_AND = 0,
91    VHDL_BINOP_OR,
92    VHDL_BINOP_EQ,
93    VHDL_BINOP_NEQ,
94    VHDL_BINOP_ADD,
95    VHDL_BINOP_SUB,
96    VHDL_BINOP_MULT,
97    VHDL_BINOP_LT,
98    VHDL_BINOP_GT,
99    VHDL_BINOP_LEQ,
100    VHDL_BINOP_GEQ,
101    VHDL_BINOP_SL,
102    VHDL_BINOP_SR,
103    VHDL_BINOP_XOR,
104    VHDL_BINOP_CONCAT,
105    VHDL_BINOP_NAND,
106    VHDL_BINOP_NOR,
107    VHDL_BINOP_XNOR,
108    VHDL_BINOP_DIV,
109    VHDL_BINOP_MOD,
110    VHDL_BINOP_POWER,
111    VHDL_BINOP_SRA
112 };
113 
114 /*
115  * A binary expression contains a list of operands rather
116  * than just two: this is to model n-input gates and the
117  * like. A second constructor is provided to handle the
118  * common case of a true binary expression.
119  */
120 class vhdl_binop_expr : public vhdl_expr {
121 public:
vhdl_binop_expr(vhdl_binop_t op,const vhdl_type * type)122    vhdl_binop_expr(vhdl_binop_t op, const vhdl_type *type)
123       : vhdl_expr(type), op_(op) {}
124    vhdl_binop_expr(vhdl_expr *left, vhdl_binop_t op,
125                    vhdl_expr *right, const vhdl_type *type);
126    ~vhdl_binop_expr();
127 
128    void add_expr(vhdl_expr *e);
129    void add_expr_front(vhdl_expr *e);
130    void emit(std::ostream &of, int level) const;
131    void find_vars(vhdl_var_set_t& read);
132 private:
133    std::list<vhdl_expr*> operands_;
134    vhdl_binop_t op_;
135 };
136 
137 
138 enum vhdl_unaryop_t {
139    VHDL_UNARYOP_NOT,
140    VHDL_UNARYOP_NEG
141 };
142 
143 class vhdl_unaryop_expr : public vhdl_expr {
144 public:
vhdl_unaryop_expr(vhdl_unaryop_t op,vhdl_expr * operand,vhdl_type * type)145    vhdl_unaryop_expr(vhdl_unaryop_t op, vhdl_expr *operand,
146                      vhdl_type *type)
147       : vhdl_expr(type), op_(op), operand_(operand) {}
148    ~vhdl_unaryop_expr();
149 
150    void emit(std::ostream &of, int level) const;
151    void find_vars(vhdl_var_set_t& read);
152 private:
153    vhdl_unaryop_t op_;
154    vhdl_expr *operand_;
155 };
156 
157 
158 /*
159  * An expression like (0 => '1', 2 => '0', others => 'Z')
160  */
161 class vhdl_bit_spec_expr : public vhdl_expr {
162 public:
vhdl_bit_spec_expr(vhdl_type * type,vhdl_expr * others)163    vhdl_bit_spec_expr(vhdl_type *type, vhdl_expr *others)
164       : vhdl_expr(type), others_(others) {}
165    ~vhdl_bit_spec_expr();
166 
167    void add_bit(int bit, vhdl_expr *e);
168    void emit(std::ostream &of, int level) const;
169 private:
170    vhdl_expr *others_;
171    struct bit_map {
172       int bit;
173       vhdl_expr *e;
174    };
175    std::list<bit_map> bits_;
176 };
177 
178 
179 class vhdl_const_string : public vhdl_expr {
180 public:
vhdl_const_string(const string & value)181    explicit vhdl_const_string(const string& value)
182       : vhdl_expr(vhdl_type::string(), true), value_(value) {}
183 
184    void emit(std::ostream &of, int level) const;
185 private:
186    std::string value_;
187 };
188 
189 class vhdl_const_bits : public vhdl_expr {
190 public:
191    vhdl_const_bits(const char *value, int width, bool issigned,
192                    bool qualify=false);
193    void emit(std::ostream &of, int level) const;
get_value() const194    const std::string &get_value() const { return value_; }
195    vhdl_expr *to_integer();
196    vhdl_expr *to_std_logic();
197    vhdl_expr *to_vector(vhdl_type_name_t name, int w);
198    vhdl_expr *resize(int w);
199 private:
200    int64_t bits_to_int() const;
201    char sign_bit() const;
202    bool has_meta_bits() const;
203 
204    std::string value_;
205    bool qualified_, signed_;
206 };
207 
208 class vhdl_const_bit : public vhdl_expr {
209 public:
vhdl_const_bit(char bit)210    explicit vhdl_const_bit(char bit)
211       : vhdl_expr(vhdl_type::std_logic(), true), bit_(bit) {}
212    void emit(std::ostream &of, int level) const;
213    vhdl_expr *to_boolean();
214    vhdl_expr *to_integer();
215    vhdl_expr *to_vector(vhdl_type_name_t name, int w);
216    vhdl_expr *to_std_ulogic();
217 private:
218    char bit_;
219 };
220 
221 enum time_unit_t {
222    TIME_UNIT_PS,
223    TIME_UNIT_NS,
224    TIME_UNIT_US,
225    TIME_UNIT_MS
226 };
227 
228 class vhdl_const_time : public vhdl_expr {
229 public:
vhdl_const_time(uint64_t value,time_unit_t units=TIME_UNIT_NS)230    vhdl_const_time(uint64_t value, time_unit_t units = TIME_UNIT_NS)
231       : vhdl_expr(vhdl_type::time(), true), value_(value), units_(units) {}
232    void emit(std::ostream &of, int level) const;
233 private:
234    uint64_t value_;
235    time_unit_t units_;
236 };
237 
238 class vhdl_const_int : public vhdl_expr {
239 public:
vhdl_const_int(int64_t value)240    explicit vhdl_const_int(int64_t value)
241       : vhdl_expr(vhdl_type::integer(), true), value_(value) {}
242    void emit(std::ostream &of, int level) const;
243    vhdl_expr *to_vector(vhdl_type_name_t name, int w);
244 private:
245    int64_t value_;
246 };
247 
248 class vhdl_const_bool : public vhdl_expr {
249 public:
vhdl_const_bool(bool value)250    explicit vhdl_const_bool(bool value)
251       : vhdl_expr(vhdl_type::boolean(), true), value_(value) {}
252    void emit(std::ostream &of, int level) const;
253 private:
254    bool value_;
255 };
256 
257 class vhdl_expr_list : public vhdl_element {
258 public:
259    ~vhdl_expr_list();
260 
261    void emit(std::ostream &of, int level) const;
empty() const262    bool empty() const { return exprs_.empty(); }
263    void add_expr(vhdl_expr *e);
264    void find_vars(vhdl_var_set_t& read);
265 private:
266    std::list<vhdl_expr*> exprs_;
267 };
268 
269 
270 /*
271  * A function call within an expression.
272  */
273 class vhdl_fcall : public vhdl_expr {
274 public:
vhdl_fcall(const string & name,const vhdl_type * rtype)275    vhdl_fcall(const string& name, const vhdl_type *rtype)
276       : vhdl_expr(rtype), name_(name) {};
~vhdl_fcall()277    ~vhdl_fcall() {}
278 
add_expr(vhdl_expr * e)279    void add_expr(vhdl_expr *e) { exprs_.add_expr(e); }
280    void emit(std::ostream &of, int level) const;
281    void find_vars(vhdl_var_set_t& read);
282 private:
283    std::string name_;
284    vhdl_expr_list exprs_;
285 };
286 
287 /*
288  * A concurrent statement appears in architecture bodies/
289  */
290 class vhdl_conc_stmt : public vhdl_element {
291 public:
~vhdl_conc_stmt()292    virtual ~vhdl_conc_stmt() {}
293 };
294 
295 typedef std::list<vhdl_conc_stmt*> conc_stmt_list_t;
296 
297 /*
298  * A '<value> when <cond>' clause that appears in several
299  * statement types.
300  */
301 struct when_part_t {
302    vhdl_expr *value, *cond, *delay;
303 };
304 typedef std::list<when_part_t> when_list_t;
305 
306 
307 /*
308  * A concurrent signal assignment (i.e. not part of a process).
309  * Can have any number of `when' clauses, in which case the original
310  * rhs becomes the `else' part.
311  */
312 class vhdl_cassign_stmt : public vhdl_conc_stmt {
313 public:
vhdl_cassign_stmt(vhdl_var_ref * lhs,vhdl_expr * rhs)314    vhdl_cassign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs)
315       : lhs_(lhs), rhs_(rhs), after_(NULL) {}
316    ~vhdl_cassign_stmt();
317 
318    void emit(std::ostream &of, int level) const;
319    void add_condition(vhdl_expr *value, vhdl_expr *cond);
set_after(vhdl_expr * a)320    void set_after(vhdl_expr *a) { after_ = a; }
321 private:
322    vhdl_var_ref *lhs_;
323    vhdl_expr *rhs_;
324    vhdl_expr *after_;
325    when_list_t whens_;
326 };
327 
328 
329 class vhdl_with_select_stmt : public vhdl_conc_stmt {
330 public:
vhdl_with_select_stmt(vhdl_expr * test,vhdl_var_ref * out)331    vhdl_with_select_stmt(vhdl_expr *test, vhdl_var_ref *out)
332       : test_(test), out_(out), others_(NULL) {}
333    ~vhdl_with_select_stmt();
334 
335    void emit(std::ostream &of, int level) const;
336    void add_condition(vhdl_expr *value, vhdl_expr *cond, vhdl_expr *delay=NULL);
337    void add_default(vhdl_expr* value);
338 private:
339    vhdl_expr *test_;
340    vhdl_var_ref *out_;
341    when_list_t whens_;
342    vhdl_expr* others_;
343 };
344 
345 
346 /*
347  * Any sequential statement in a process.
348  */
349 class vhdl_seq_stmt : public vhdl_element {
350 public:
~vhdl_seq_stmt()351    virtual ~vhdl_seq_stmt() {}
352 
353    // Find all the variables that are read or written in the
354    // expressions within this statement
355    // This is used to clean up the VHDL output
356    virtual void find_vars(vhdl_var_set_t& read,
357                           vhdl_var_set_t& write) = 0;
358 };
359 
360 
361 /*
362  * A list of sequential statements. For example inside a
363  * process, loop, or if statement.
364  */
365 class stmt_container {
366 public:
367    ~stmt_container();
368 
369    void add_stmt(vhdl_seq_stmt *stmt);
370    void move_stmts_from(stmt_container *other);
371    void emit(std::ostream &of, int level, bool newline=true) const;
empty() const372    bool empty() const { return stmts_.empty(); }
373    void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write);
374 
375    typedef std::list<vhdl_seq_stmt*> stmt_list_t;
get_stmts()376    stmt_list_t &get_stmts() { return stmts_; }
377 private:
378    stmt_list_t stmts_;
379 };
380 
381 
382 /*
383  * Shared between blocking and non-blocking assignment.
384  */
385 class vhdl_abstract_assign_stmt : public vhdl_seq_stmt {
386 public:
vhdl_abstract_assign_stmt(vhdl_var_ref * lhs,vhdl_expr * rhs)387    vhdl_abstract_assign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs)
388       : lhs_(lhs), rhs_(rhs), after_(NULL) {}
389    virtual ~vhdl_abstract_assign_stmt();
390 
set_after(vhdl_expr * after)391    void set_after(vhdl_expr *after) { after_ = after; }
392    void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write);
393 protected:
394    vhdl_var_ref *lhs_;
395    vhdl_expr *rhs_, *after_;
396 };
397 
398 
399 /*
400  * Similar to Verilog non-blocking assignment, except the LHS
401  * must be a signal not a variable.
402  */
403 class vhdl_nbassign_stmt : public vhdl_abstract_assign_stmt {
404 public:
vhdl_nbassign_stmt(vhdl_var_ref * lhs,vhdl_expr * rhs)405    vhdl_nbassign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs)
406       : vhdl_abstract_assign_stmt(lhs, rhs) {}
407 
408    void emit(std::ostream &of, int level) const;
409 };
410 
411 
412 class vhdl_assign_stmt : public vhdl_abstract_assign_stmt {
413 public:
vhdl_assign_stmt(vhdl_var_ref * lhs,vhdl_expr * rhs)414    vhdl_assign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs)
415       : vhdl_abstract_assign_stmt(lhs, rhs) {}
416 
417    void emit(std::ostream &of, int level) const;
418 };
419 
420 
421 enum vhdl_wait_type_t {
422    VHDL_WAIT_INDEF,  // Suspend indefinitely
423    VHDL_WAIT_FOR,    // Wait for a constant amount of time
424    VHDL_WAIT_FOR0,   // Special wait for zero time
425    VHDL_WAIT_UNTIL,  // Wait on an expression
426    VHDL_WAIT_ON      // Wait on a sensitivity list
427 };
428 
429 /*
430  * Delay simulation indefinitely, until an event, or for a
431  * specified time.
432  */
433 class vhdl_wait_stmt : public vhdl_seq_stmt {
434 public:
vhdl_wait_stmt(vhdl_wait_type_t type=VHDL_WAIT_INDEF,vhdl_expr * expr=NULL)435    vhdl_wait_stmt(vhdl_wait_type_t type = VHDL_WAIT_INDEF,
436                   vhdl_expr *expr = NULL)
437       : type_(type), expr_(expr) {}
438    ~vhdl_wait_stmt();
439 
440    void emit(std::ostream &of, int level) const;
add_sensitivity(const std::string & s)441    void add_sensitivity(const std::string &s) { sensitivity_.push_back(s); }
get_type() const442    vhdl_wait_type_t get_type() const { return type_; }
443    void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write);
444 private:
445    vhdl_wait_type_t type_;
446    vhdl_expr *expr_;
447    string_list_t sensitivity_;
448 };
449 
450 
451 class vhdl_null_stmt : public vhdl_seq_stmt {
452 public:
453    void emit(std::ostream &of, int level) const;
find_vars(vhdl_var_set_t &,vhdl_var_set_t &)454    void find_vars(vhdl_var_set_t&, vhdl_var_set_t&) {}
455 };
456 
457 
458 enum vhdl_severity_t {
459    SEVERITY_NOTE,
460    SEVERITY_WARNING,
461    SEVERITY_ERROR,
462    SEVERITY_FAILURE
463 };
464 
465 class vhdl_report_stmt : public vhdl_seq_stmt {
466 public:
467    vhdl_report_stmt(vhdl_expr *text,
468                     vhdl_severity_t severity = SEVERITY_NOTE);
~vhdl_report_stmt()469    virtual ~vhdl_report_stmt() {}
470 
471    virtual void emit(ostream& of, int level) const;
472    void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write);
473 private:
474    vhdl_severity_t severity_;
475    vhdl_expr *text_;
476 };
477 
478 
479 class vhdl_assert_stmt : public vhdl_report_stmt {
480 public:
481    explicit vhdl_assert_stmt(const char *reason);
482 
483    void emit(ostream &of, int level) const;
484 };
485 
486 
487 class vhdl_if_stmt : public vhdl_seq_stmt {
488 public:
489    explicit vhdl_if_stmt(vhdl_expr *test);
490    ~vhdl_if_stmt();
491 
get_then_container()492    stmt_container *get_then_container() { return &then_part_; }
get_else_container()493    stmt_container *get_else_container() { return &else_part_; }
494    stmt_container *add_elsif(vhdl_expr *test);
495    void emit(std::ostream &of, int level) const;
496    void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write);
497 private:
498    struct elsif {
499       vhdl_expr *test;
500       stmt_container *container;
501    };
502 
503    vhdl_expr *test_;
504    stmt_container then_part_, else_part_;
505    std::list<elsif> elsif_parts_;
506 };
507 
508 
509 /*
510  * A single branch in a case statement consisting of an
511  * expression part and a statement container.
512  */
513 class vhdl_case_branch : public vhdl_element {
514    friend class vhdl_case_stmt;
515 public:
vhdl_case_branch(vhdl_expr * when)516    explicit vhdl_case_branch(vhdl_expr *when) : when_(when) {}
517    ~vhdl_case_branch();
518 
get_container()519    stmt_container *get_container() { return &stmts_; }
520    void emit(std::ostream &of, int level) const;
521 private:
522    vhdl_expr *when_;
523    stmt_container stmts_;
524 };
525 
526 typedef std::list<vhdl_case_branch*> case_branch_list_t;
527 
528 class vhdl_case_stmt : public vhdl_seq_stmt {
529 public:
vhdl_case_stmt(vhdl_expr * test)530    explicit vhdl_case_stmt(vhdl_expr *test) : test_(test) {}
531    ~vhdl_case_stmt();
532 
add_branch(vhdl_case_branch * b)533    void add_branch(vhdl_case_branch *b) { branches_.push_back(b); }
534    void emit(std::ostream &of, int level) const;
535    void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write);
536 private:
537    vhdl_expr *test_;
538    case_branch_list_t branches_;
539 };
540 
541 
542 class vhdl_loop_stmt : public vhdl_seq_stmt {
543 public:
~vhdl_loop_stmt()544    virtual ~vhdl_loop_stmt() {}
545 
get_container()546    stmt_container *get_container() { return &stmts_; }
547    void emit(std::ostream &of, int level) const;
548    virtual void find_vars(vhdl_var_set_t& read,
549                           vhdl_var_set_t& write);
550 private:
551    stmt_container stmts_;
552 };
553 
554 
555 class vhdl_while_stmt : public vhdl_loop_stmt {
556 public:
vhdl_while_stmt(vhdl_expr * test)557    explicit vhdl_while_stmt(vhdl_expr *test) : test_(test) {}
558    ~vhdl_while_stmt();
559 
560    void emit(std::ostream &of, int level) const;
561    void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write);
562 private:
563    vhdl_expr *test_;
564 };
565 
566 
567 class vhdl_for_stmt : public vhdl_loop_stmt {
568 public:
vhdl_for_stmt(const char * lname,vhdl_expr * from,vhdl_expr * to)569    vhdl_for_stmt(const char *lname, vhdl_expr *from, vhdl_expr *to)
570       : lname_(lname), from_(from), to_(to) {}
571    ~vhdl_for_stmt();
572 
573    void emit(std::ostream &of, int level) const;
574    void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write);
575 private:
576    const char *lname_;
577    vhdl_expr *from_, *to_;
578 };
579 
580 
581 /*
582  * A procedure call. Which is a statement, unlike a function
583  * call which is an expression.
584  */
585 class vhdl_pcall_stmt : public vhdl_seq_stmt {
586 public:
vhdl_pcall_stmt(const char * name)587    explicit vhdl_pcall_stmt(const char *name) : name_(name) {}
588 
589    void emit(std::ostream &of, int level) const;
add_expr(vhdl_expr * e)590    void add_expr(vhdl_expr *e) { exprs_.add_expr(e); }
591    void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write);
592 private:
593    std::string name_;
594    vhdl_expr_list exprs_;
595 };
596 
597 
598 /*
599  * A declaration of some sort (variable, component, etc.).
600  * Declarations have names, which is the identifier of the variable,
601  * constant, etc. not the type.
602  */
603 class vhdl_decl : public vhdl_element {
604 public:
vhdl_decl(const string & name,const vhdl_type * type=NULL,vhdl_expr * initial=NULL)605    vhdl_decl(const string& name, const vhdl_type *type = NULL,
606              vhdl_expr *initial = NULL)
607       : name_(name), type_(type), initial_(initial),
608         has_initial_(initial != NULL) {}
609    virtual ~vhdl_decl();
610 
get_name() const611    const std::string &get_name() const { return name_; }
612    const vhdl_type *get_type() const;
set_type(vhdl_type * t)613    void set_type(vhdl_type *t) { type_ = t; }
614    void set_initial(vhdl_expr *initial);
has_initial() const615    bool has_initial() const { return has_initial_; }
616 
617    // Return a new reference to this declaration
618    vhdl_var_ref* make_ref() const;
619 
620    // The different sorts of assignment statement
621    // ASSIGN_CONST is used to generate a variable to shadow a
622    // constant that cannot be assigned to (e.g. a function parameter)
623    enum assign_type_t { ASSIGN_BLOCK, ASSIGN_NONBLOCK, ASSIGN_CONST };
624 
625    // Get the sort of assignment statement to generate for
626    // assignments to this declaration
627    // For some sorts of declarations it doesn't make sense
628    // to assign to it so calling assignment_type just raises
629    // an assertion failure
assignment_type() const630    virtual assign_type_t assignment_type() const { assert(false);
631                                                    return ASSIGN_BLOCK; }
632 
633    // True if this declaration can be read from
is_readable() const634    virtual bool is_readable() const { return true; }
635 
636    // Modify this declaration so it can be read from
637    // This does nothing for most declaration types
ensure_readable()638    virtual void ensure_readable() {}
639 protected:
640    std::string name_;
641    const vhdl_type *type_;
642    vhdl_expr *initial_;
643    bool has_initial_;
644 };
645 
646 typedef std::list<vhdl_decl*> decl_list_t;
647 
648 
649 /*
650  * A forward declaration of a component. At the moment it is assumed
651  * that components declarations will only ever be for entities
652  * generated by this code generator. This is enforced by making the
653  * constructor private (use component_decl_for instead).
654  */
655 class vhdl_component_decl : public vhdl_decl {
656 public:
657    static vhdl_component_decl *component_decl_for(vhdl_entity *ent);
658 
659    void emit(std::ostream &of, int level) const;
660 private:
661    explicit vhdl_component_decl(const char *name);
662 
663    decl_list_t ports_;
664 };
665 
666 
667 class vhdl_type_decl : public vhdl_decl {
668 public:
vhdl_type_decl(const string & name,const vhdl_type * base)669    vhdl_type_decl(const string& name, const vhdl_type *base)
670       : vhdl_decl(name, base) {}
671    void emit(std::ostream &of, int level) const;
672 };
673 
674 /*
675  * A variable declaration inside a process (although this isn't
676  * enforced here).
677  */
678 class vhdl_var_decl : public vhdl_decl {
679 public:
vhdl_var_decl(const string & name,const vhdl_type * type)680    vhdl_var_decl(const string& name, const vhdl_type *type)
681       : vhdl_decl(name, type) {}
682    void emit(std::ostream &of, int level) const;
assignment_type() const683    assign_type_t assignment_type() const { return ASSIGN_BLOCK; }
684 };
685 
686 
687 /*
688  * A signal declaration in architecture.
689  */
690 class vhdl_signal_decl : public vhdl_decl {
691 public:
vhdl_signal_decl(const string & name,const vhdl_type * type)692    vhdl_signal_decl(const string& name, const vhdl_type* type)
693       : vhdl_decl(name, type) {}
694    virtual void emit(std::ostream &of, int level) const;
assignment_type() const695    assign_type_t assignment_type() const { return ASSIGN_NONBLOCK; }
696 };
697 
698 
699 /*
700  * A parameter to a function.
701  */
702 class vhdl_param_decl : public vhdl_decl {
703 public:
vhdl_param_decl(const char * name,vhdl_type * type)704    vhdl_param_decl(const char *name, vhdl_type *type)
705       : vhdl_decl(name, type) {}
706    void emit(std::ostream &of, int level) const;
assignment_type() const707    assign_type_t assignment_type() const { return ASSIGN_CONST; }
708 };
709 
710 enum vhdl_port_mode_t {
711    VHDL_PORT_IN,
712    VHDL_PORT_OUT,
713    VHDL_PORT_INOUT,
714    VHDL_PORT_BUFFER
715 };
716 
717 /*
718  * A port declaration is like a signal declaration except
719  * it has a direction and appears in the entity rather than
720  * the architecture.
721  */
722 class vhdl_port_decl : public vhdl_decl {
723 public:
vhdl_port_decl(const char * name,vhdl_type * type,vhdl_port_mode_t mode)724    vhdl_port_decl(const char *name, vhdl_type *type,
725                   vhdl_port_mode_t mode)
726       : vhdl_decl(name, type), mode_(mode) {}
727 
728    void emit(std::ostream &of, int level) const;
get_mode() const729    vhdl_port_mode_t get_mode() const { return mode_; }
set_mode(vhdl_port_mode_t m)730    void set_mode(vhdl_port_mode_t m) { mode_ = m; }
assignment_type() const731    assign_type_t assignment_type() const { return ASSIGN_NONBLOCK; }
732    void ensure_readable();
733    bool is_readable() const;
734 private:
735    vhdl_port_mode_t mode_;
736 };
737 
738 /*
739  * A mapping from port name to an expression.
740  */
741 struct port_map_t {
742    std::string name;
743    vhdl_expr *expr;
744 };
745 
746 typedef std::list<port_map_t> port_map_list_t;
747 
748 /*
749  * Instantiation of component. This is really only a placeholder
750  * at the moment until the port mappings are worked out.
751  */
752 class vhdl_comp_inst : public vhdl_conc_stmt {
753 public:
754    vhdl_comp_inst(const char *inst_name, const char *comp_name);
755    ~vhdl_comp_inst();
756 
757    void emit(std::ostream &of, int level) const;
758    void map_port(const string& name, vhdl_expr *expr);
759 
get_comp_name() const760    const std::string &get_comp_name() const { return comp_name_; }
get_inst_name() const761    const std::string &get_inst_name() const { return inst_name_; }
762 private:
763    std::string comp_name_, inst_name_;
764    port_map_list_t mapping_;
765 };
766 
767 
768 /*
769  * Contains a list of declarations in a hierarchy.
770  * A scope can be `initializing' where assignments automatically
771  * create initial values for declarations.
772  */
773 class vhdl_scope {
774 public:
775    vhdl_scope();
776    ~vhdl_scope();
777 
778    void add_decl(vhdl_decl *decl);
779    void add_forward_decl(vhdl_decl *decl);
780    vhdl_decl *get_decl(const std::string &name) const;
781    bool have_declared(const std::string &name) const;
782    bool name_collides(const string& name) const;
783    bool contained_within(const vhdl_scope *other) const;
784    vhdl_scope *get_parent() const;
785 
empty() const786    bool empty() const { return decls_.empty(); }
get_decls() const787    const decl_list_t &get_decls() const { return decls_; }
set_parent(vhdl_scope * p)788    void set_parent(vhdl_scope *p) { parent_ = p; }
789 
initializing() const790    bool initializing() const { return init_; }
791    void set_initializing(bool i);
792    bool hoisted_initialiser() const;
793    void hoisted_initialiser(bool h);
794 
set_allow_signal_assignment(bool b)795    void set_allow_signal_assignment(bool b) { sig_assign_ = b; }
allow_signal_assignment() const796    bool allow_signal_assignment() const { return sig_assign_; }
797 private:
798    decl_list_t decls_;
799    vhdl_scope *parent_;
800    bool init_, sig_assign_;
801    bool hoisted_init_;
802 };
803 
804 
805 /*
806  * Any sort of procedural element: process, function, or
807  * procedure. Roughly these map onto Verilog's processes,
808  * functions, and tasks.
809  */
810 class vhdl_procedural {
811 public:
vhdl_procedural()812    vhdl_procedural() : contains_wait_stmt_(false) {}
~vhdl_procedural()813    virtual ~vhdl_procedural() {}
814 
get_container()815    virtual stmt_container *get_container() { return &stmts_; }
get_scope()816    virtual vhdl_scope *get_scope() { return &scope_; }
817 
added_wait_stmt()818    void added_wait_stmt() { contains_wait_stmt_ = true; }
contains_wait_stmt() const819    bool contains_wait_stmt() const { return contains_wait_stmt_; }
820 
821    // Managing set of blocking assignment targets in this block
822    void add_blocking_target(vhdl_var_ref* ref);
823    bool is_blocking_target(vhdl_var_ref* ref) const;
824 
825 protected:
826    stmt_container stmts_;
827    vhdl_scope scope_;
828 
829    // If this is true then the body contains a `wait' statement
830    // embedded in it somewhere
831    // If this is the case then we can't use a sensitivity list for
832    // the process
833    bool contains_wait_stmt_;
834 
835    // The set of variable we have performed a blocking
836    // assignment to
837    set<string> blocking_targets_;
838 };
839 
840 
841 class vhdl_function : public vhdl_decl, public vhdl_procedural {
842    friend class vhdl_forward_fdecl;
843 public:
844    vhdl_function(const char *name, vhdl_type *ret_type);
845 
846    virtual void emit(std::ostream &of, int level) const;
get_scope()847    vhdl_scope *get_scope() { return &variables_; }
add_param(vhdl_param_decl * p)848    void add_param(vhdl_param_decl *p) { scope_.add_decl(p); }
849 private:
850    vhdl_scope variables_;
851 };
852 
853 class vhdl_forward_fdecl : public vhdl_decl {
854 public:
vhdl_forward_fdecl(const vhdl_function * f)855    explicit vhdl_forward_fdecl(const vhdl_function *f)
856       : vhdl_decl((f->get_name() + "_Forward").c_str()), f_(f) {}
857 
858    void emit(std::ostream &of, int level) const;
859 private:
860    const vhdl_function *f_;
861 };
862 
863 
864 class vhdl_process : public vhdl_conc_stmt, public vhdl_procedural {
865 public:
vhdl_process(const char * name="")866    explicit vhdl_process(const char *name = "") : name_(name) {}
867 
868    void emit(std::ostream &of, int level) const;
869    void add_sensitivity(const std::string &name);
870 private:
871    std::string name_;
872    string_list_t sens_;
873 };
874 
875 
876 /*
877  * An architecture which implements an entity.
878  */
879 class vhdl_arch : public vhdl_element {
880 public:
vhdl_arch(const string & entity,const string & name)881    vhdl_arch(const string& entity, const string& name)
882       : name_(name), entity_(entity) {}
883    virtual ~vhdl_arch();
884 
885    void emit(std::ostream &of, int level=0) const;
886    void add_stmt(vhdl_process *proc);
887    void add_stmt(vhdl_conc_stmt *stmt);
get_scope()888    vhdl_scope *get_scope() { return &scope_; }
889 private:
890    conc_stmt_list_t stmts_;
891    vhdl_scope scope_;
892    std::string name_, entity_;
893 };
894 
895 /*
896  * An entity defines the ports, parameters, etc. of a module. Each
897  * entity is associated with a single architecture (although
898  * technically this need not be the case).  Entities are `derived'
899  * from instantiations of Verilog module scopes in the hierarchy.
900  */
901 class vhdl_entity : public vhdl_element {
902 public:
903    vhdl_entity(const string& name, vhdl_arch *arch, int depth=0);
904    virtual ~vhdl_entity();
905 
906    void emit(std::ostream &of, int level=0) const;
907    void add_port(vhdl_port_decl *decl);
get_arch() const908    vhdl_arch *get_arch() const { return arch_; }
get_name() const909    const std::string &get_name() const { return name_; }
910 
get_scope()911    vhdl_scope *get_scope() { return &ports_; }
912 
913    void set_time_units(int units, int precision);
914    friend vhdl_const_time* scale_time(const vhdl_entity* ent, uint64_t t);
915 
916    // Each entity has an associated depth which is how deep in
917    // the Verilog module hierarchy it was found
918    // This is used to limit the maximum depth of modules emitted
919    const int depth;
920 private:
921    std::string name_;
922    vhdl_arch *arch_;  // Entity may only have a single architecture
923    vhdl_scope ports_;
924 
925    // Entities have an associated VHDL time unit
926    // This is used to implement the Verilog timescale directive
927    time_unit_t time_unit_;
928 };
929 
930 typedef std::list<vhdl_entity*> entity_list_t;
931 
932 #endif
933 
934