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