From 1d28b935e8612c85f96d472af901c4acbfb1da38 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 8 Jun 2008 13:27:48 +0100 Subject: [PATCH] Split vhdl_element.cc into multiple files --- tgt-vhdl/Makefile.in | 3 +- tgt-vhdl/vhdl_element.cc | 475 +-------------------------------------- tgt-vhdl/vhdl_element.hh | 359 +---------------------------- tgt-vhdl/vhdl_helper.hh | 54 +++++ tgt-vhdl/vhdl_syntax.cc | 419 ++++++++++++++++++++++++++++++++++ tgt-vhdl/vhdl_syntax.hh | 345 ++++++++++++++++++++++++++++ tgt-vhdl/vhdl_target.h | 3 +- tgt-vhdl/vhdl_type.cc | 72 ++++++ tgt-vhdl/vhdl_type.hh | 60 +++++ 9 files changed, 961 insertions(+), 829 deletions(-) create mode 100644 tgt-vhdl/vhdl_helper.hh create mode 100644 tgt-vhdl/vhdl_syntax.cc create mode 100644 tgt-vhdl/vhdl_syntax.hh create mode 100644 tgt-vhdl/vhdl_type.cc create mode 100644 tgt-vhdl/vhdl_type.hh diff --git a/tgt-vhdl/Makefile.in b/tgt-vhdl/Makefile.in index c63aa9134..0eb413ff6 100644 --- a/tgt-vhdl/Makefile.in +++ b/tgt-vhdl/Makefile.in @@ -49,7 +49,8 @@ dep: $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o mv $*.d dep -O = vhdl.o vhdl_element.o scope.o process.o stmt.o expr.o +O = vhdl.o vhdl_element.o vhdl_type.o vhdl_syntax.o scope.o process.o \ + stmt.o expr.o \ ifeq (@WIN32@,yes) TGTLDFLAGS=-L.. -livl diff --git a/tgt-vhdl/vhdl_element.cc b/tgt-vhdl/vhdl_element.cc index 216d04d16..5391736f7 100644 --- a/tgt-vhdl/vhdl_element.cc +++ b/tgt-vhdl/vhdl_element.cc @@ -30,7 +30,7 @@ static const int VHDL_INDENT = 2; // Spaces to indent -static int indent(int level) +int indent(int level) { return level + VHDL_INDENT; } @@ -38,46 +38,19 @@ static int indent(int level) /* * Emit a newline and indent to the correct level. */ -static void newline(std::ofstream &of, int level) +void newline(std::ofstream &of, int level) { of << std::endl; while (level--) of << ' '; } -static void blank_line(std::ofstream &of, int level) +void blank_line(std::ofstream &of, int level) { of << std::endl; newline(of, level); } -template -void emit_children(std::ofstream &of, - const std::list &children, - int level) -{ - // Don't indent if there are no children - if (children.size() == 0) - newline(of, level); - else { - typename std::list::const_iterator it; - for (it = children.begin(); it != children.end(); ++it) { - newline(of, indent(level)); - (*it)->emit(of, indent(level)); - } - newline(of, level); - } -} - -template -void delete_children(std::list &children) -{ - typename std::list::iterator it; - for (it = children.begin(); it != children.end(); ++it) - delete *it; - children.clear(); -} - void vhdl_element::set_comment(std::string comment) { comment_ = comment; @@ -99,445 +72,3 @@ void vhdl_element::emit_comment(std::ofstream &of, int level, newline(of, level); } } - -vhdl_entity::vhdl_entity(const char *name, const char *derived_from, - vhdl_arch *arch) - : name_(name), arch_(arch), derived_from_(derived_from) -{ - arch->parent_ = this; -} - -vhdl_entity::~vhdl_entity() -{ - delete arch_; -} - -/* - * Add a package to the list of `use' statements before - * the entity. - */ -void vhdl_entity::requires_package(const char *spec) -{ - std::string pname(spec); - std::list::iterator it; - for (it = uses_.begin(); it != uses_.end(); ++it) { - if (*it == pname) - return; - } - uses_.push_back(spec); -} - -void vhdl_entity::emit(std::ofstream &of, int level) const -{ - // Pretty much every design will use std_logic so we - // might as well include it by default - of << "library ieee;" << std::endl; - of << "use ieee.std_logic_1164.all;" << std::endl; - - for (std::list::const_iterator it = uses_.begin(); - it != uses_.end(); - ++it) - of << "use " << *it << ".all;" << std::endl; - of << std::endl; - - emit_comment(of, level); - of << "entity " << name_ << " is"; - // ...ports... - // newline(indent(level)); - newline(of, level); - of << "end entity; "; - blank_line(of, level); // Extra blank line after entities - arch_->emit(of, level); -} - -vhdl_arch::vhdl_arch(const char *entity, const char *name) - : parent_(NULL), name_(name), entity_(entity) -{ - -} - -vhdl_arch::~vhdl_arch() -{ - delete_children(stmts_); - delete_children(decls_); -} - -void vhdl_arch::add_stmt(vhdl_conc_stmt *stmt) -{ - stmt->parent_ = this; - stmts_.push_back(stmt); -} - -void vhdl_arch::add_decl(vhdl_decl *decl) -{ - decls_.push_back(decl); -} - -vhdl_entity *vhdl_arch::get_parent() const -{ - assert(parent_); - return parent_; -} - -void vhdl_arch::emit(std::ofstream &of, int level) const -{ - emit_comment(of, level); - of << "architecture " << name_ << " of " << entity_; - of << " is"; - emit_children(of, decls_, level); - of << "begin"; - emit_children(of, stmts_, level); - of << "end architecture;"; - blank_line(of, level); // Extra blank line after architectures; -} - -vhdl_decl *vhdl_arch::get_decl(const std::string &name) const -{ - decl_list_t::const_iterator it; - for (it = decls_.begin(); it != decls_.end(); ++it) { - if ((*it)->get_name() == name) - return *it; - } - return NULL; -} - -/* - * True if component `name' has already been declared in this - * architecture. This is a bit of hack, since it uses typeid - * to distinguish between components and other declarations. - */ -bool vhdl_arch::have_declared_component(const std::string &name) const -{ - std::string comp_typename(typeid(vhdl_component_decl).name()); - decl_list_t::const_iterator it; - for (it = decls_.begin(); it != decls_.end(); ++it) { - if (comp_typename == typeid(**it).name() - && (*it)->get_name() == name) - return true; - } - return false; -} - -/* - * True if any declaration of `name' has been added to the - * architecture. - */ -bool vhdl_arch::have_declared(const std::string &name) const -{ - return get_decl(name) != NULL; -} - -vhdl_arch *vhdl_conc_stmt::get_parent() const -{ - assert(parent_); - return parent_; -} - -vhdl_process::vhdl_process(const char *name) - : name_(name) -{ - -} - -vhdl_process::~vhdl_process() -{ - delete_children(stmts_); - delete_children(decls_); -} - -void vhdl_process::add_stmt(vhdl_seq_stmt* stmt) -{ - stmts_.push_back(stmt); -} - -void vhdl_process::add_decl(vhdl_decl* decl) -{ - decls_.push_back(decl); -} - -void vhdl_process::add_sensitivity(const char *name) -{ - sens_.push_back(name); -} - -bool vhdl_process::have_declared_var(const std::string &name) const -{ - decl_list_t::const_iterator it; - for (it = decls_.begin(); it != decls_.end(); ++it) { - if ((*it)->get_name() == name) - return true; - } - return false; -} - -void vhdl_process::emit(std::ofstream &of, int level) const -{ - emit_comment(of, level); - if (name_.size() > 0) - of << name_ << ": "; - of << "process "; - - int num_sens = sens_.size(); - if (num_sens > 0) { - of << "("; - string_list_t::const_iterator it; - for (it = sens_.begin(); it != sens_.end(); ++it) { - of << *it; - if (--num_sens > 0) - of << ", "; - } - of << ") "; - } - - of << "is"; - emit_children(of, decls_, level); - of << "begin"; - emit_children(of, stmts_, level); - of << "end process;"; - newline(of, level); -} - -vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name) - : comp_name_(comp_name), inst_name_(inst_name) -{ - -} - -void vhdl_comp_inst::emit(std::ofstream &of, int level) const -{ - // If there are no ports or generics we don't need to mention them... - emit_comment(of, level); - of << inst_name_ << ": " << comp_name_ << ";"; - newline(of, level); -} - -vhdl_component_decl::vhdl_component_decl(const char *name) - : vhdl_decl(name) -{ - -} - -/* - * Create a component declaration for the given entity. - */ -vhdl_component_decl *vhdl_component_decl::component_decl_for(const vhdl_entity *ent) -{ - assert(ent != NULL); - - vhdl_component_decl *decl = new vhdl_component_decl - (ent->get_name().c_str()); - - return decl; -} - -void vhdl_component_decl::emit(std::ofstream &of, int level) const -{ - emit_comment(of, level); - of << "component " << name_ << " is"; - // ...ports... - newline(of, level); - of << "end component;"; -} - -void vhdl_wait_stmt::emit(std::ofstream &of, int level) const -{ - // TODO: There are lots of different types of `wait' - of << "wait;"; -} - -vhdl_type *vhdl_type::std_logic() -{ - return new vhdl_type(VHDL_TYPE_STD_LOGIC); -} - -vhdl_type *vhdl_type::string() -{ - return new vhdl_type(VHDL_TYPE_STRING); -} - -vhdl_type *vhdl_type::line() -{ - return new vhdl_type(VHDL_TYPE_LINE); -} - -std::string vhdl_type::get_string() const -{ - switch (name_) { - case VHDL_TYPE_STD_LOGIC: - return std::string("std_logic"); - case VHDL_TYPE_STD_LOGIC_VECTOR: - { - std::ostringstream ss; - ss << "std_logic_vector(" << msb_; - ss << " downto " << lsb_ << ")"; - return ss.str(); - } - case VHDL_TYPE_STRING: - return std::string("String"); - case VHDL_TYPE_LINE: - return std::string("Line"); - case VHDL_TYPE_FILE: - return std::string("File"); - default: - return std::string("BadType"); - } -} - -void vhdl_type::emit(std::ofstream &of, int level) const -{ - of << get_string(); -} - -vhdl_type *vhdl_type::std_logic_vector(int msb, int lsb) -{ - return new vhdl_type(VHDL_TYPE_STD_LOGIC_VECTOR, msb, lsb); -} - -vhdl_var_decl::~vhdl_var_decl() -{ - delete type_; -} - -void vhdl_var_decl::emit(std::ofstream &of, int level) const -{ - of << "variable " << name_ << " : "; - type_->emit(of, level); - of << ";"; - emit_comment(of, level, true); -} - -vhdl_signal_decl::~vhdl_signal_decl() -{ - delete type_; -} - -void vhdl_signal_decl::emit(std::ofstream &of, int level) const -{ - of << "signal " << name_ << " : "; - type_->emit(of, level); - of << ";"; - emit_comment(of, level, true); -} - -vhdl_expr::~vhdl_expr() -{ - delete type_; -} - -/* - * The default cast just assumes there's a VHDL cast function to - * do the job for us. - */ -vhdl_expr *vhdl_expr::cast(const vhdl_type *to) -{ - vhdl_fcall *conv = - new vhdl_fcall(to->get_string().c_str(), new vhdl_type(*to)); - conv->add_expr(this); - - return conv; -} - -void vhdl_expr_list::add_expr(vhdl_expr *e) -{ - exprs_.push_back(e); -} - -vhdl_expr_list::~vhdl_expr_list() -{ - delete_children(exprs_); -} - -void vhdl_expr_list::emit(std::ofstream &of, int level) const -{ - of << "("; - - int size = exprs_.size(); - std::list::const_iterator it; - for (it = exprs_.begin(); it != exprs_.end(); ++it) { - (*it)->emit(of, level); - if (--size > 0) - of << ", "; - } - - of << ")"; -} - -void vhdl_pcall_stmt::emit(std::ofstream &of, int level) const -{ - of << name_; - exprs_.emit(of, level); - of << ";"; -} - -void vhdl_var_ref::emit(std::ofstream &of, int level) const -{ - of << name_; -} - -void vhdl_const_string::emit(std::ofstream &of, int level) const -{ - // In some instances a string literal can be ambiguous between - // a String type and some other types (e.g. std_logic_vector) - // The explicit cast to String removes this ambiguity (although - // isn't always strictly necessary) - of << "String'(\"" << value_ << "\")"; -} - -void vhdl_null_stmt::emit(std::ofstream &of, int level) const -{ - of << "null;"; -} - -void vhdl_fcall::emit(std::ofstream &of, int level) const -{ - of << name_; - exprs_.emit(of, level); -} - -void vhdl_nbassign_stmt::emit(std::ofstream &of, int level) const -{ - lhs_->emit(of, level); - of << " <= "; - rhs_->emit(of, level); - of << ";"; -} - -vhdl_const_bits::vhdl_const_bits(const char *value) - : vhdl_expr(vhdl_type::std_logic_vector(strlen(value)-1, 0)), - value_(value) -{ - -} - -vhdl_expr *vhdl_const_bits::cast(const vhdl_type *to) -{ - if (to->get_name() == VHDL_TYPE_STD_LOGIC) { - // VHDL won't let us cast directly between a vector and - // a scalar type - // But we don't need to here as we have the bits available - - // Take the least significant bit - char lsb = value_[0]; - - return new vhdl_const_bit(lsb); - } - else - return vhdl_expr::cast(to); -} - -void vhdl_const_bits::emit(std::ofstream &of, int level) const -{ - of << "std_logic_vector'(\""; - - // The bits appear to be in reverse order - std::string::const_reverse_iterator it; - for (it = value_.rbegin(); it != value_.rend(); ++it) - of << *it; - - of << "\")"; -} - -void vhdl_const_bit::emit(std::ofstream &of, int level) const -{ - of << "'" << bit_ << "'"; -} diff --git a/tgt-vhdl/vhdl_element.hh b/tgt-vhdl/vhdl_element.hh index c657039f4..f73ea0949 100644 --- a/tgt-vhdl/vhdl_element.hh +++ b/tgt-vhdl/vhdl_element.hh @@ -25,10 +25,6 @@ #include #include -class vhdl_entity; -class vhdl_arch; -class vhdl_expr; - typedef std::list string_list_t; /* @@ -48,358 +44,11 @@ private: std::string comment_; }; -typedef std::list element_list_t; - - -enum vhdl_type_name_t { - VHDL_TYPE_STD_LOGIC, - VHDL_TYPE_STD_LOGIC_VECTOR, - VHDL_TYPE_STRING, - VHDL_TYPE_LINE, - VHDL_TYPE_FILE -}; - -/* - * A type at the moment is just a name. It shouldn't get - * too much more complex, as Verilog's type system is much - * simpler than VHDL's. - */ -class vhdl_type : public vhdl_element { -public: - vhdl_type(vhdl_type_name_t name, int msb = 0, int lsb = 0) - : name_(name), msb_(msb), lsb_(lsb) {} - virtual ~vhdl_type() {} - - void emit(std::ofstream &of, int level) const; - vhdl_type_name_t get_name() const { return name_; } - std::string get_string() const; - int get_width() const { return msb_ - lsb_ + 1; } - - // Common types - static vhdl_type *std_logic(); - static vhdl_type *string(); - static vhdl_type *line(); - static vhdl_type *std_logic_vector(int msb, int lsb); -protected: - vhdl_type_name_t name_; - int msb_, lsb_; -}; - - -class vhdl_expr : public vhdl_element { -public: - vhdl_expr(vhdl_type* type) : type_(type) {} - virtual ~vhdl_expr(); - - const vhdl_type *get_type() const { return type_; } - virtual vhdl_expr *cast(const vhdl_type *to); -private: - vhdl_type *type_; -}; - - -/* - * A normal scalar variable reference. - */ -class vhdl_var_ref : public vhdl_expr { -public: - vhdl_var_ref(const char *name, vhdl_type *type) - : vhdl_expr(type), name_(name) {} - - void emit(std::ofstream &of, int level) const; -private: - std::string name_; -}; - - -class vhdl_const_string : public vhdl_expr { -public: - vhdl_const_string(const char *value) - : vhdl_expr(vhdl_type::string()), value_(value) {} - - void emit(std::ofstream &of, int level) const; -private: - std::string value_; -}; - -class vhdl_const_bits : public vhdl_expr { -public: - vhdl_const_bits(const char *value); - void emit(std::ofstream &of, int level) const; - const std::string &get_value() const { return value_; } - vhdl_expr *cast(const vhdl_type *to); -private: - std::string value_; -}; - -class vhdl_const_bit : public vhdl_expr { -public: - vhdl_const_bit(char bit) - : vhdl_expr(vhdl_type::std_logic()), bit_(bit) {} - void emit(std::ofstream &of, int level) const; -private: - char bit_; -}; - -class vhdl_expr_list : public vhdl_element { -public: - ~vhdl_expr_list(); - - void emit(std::ofstream &of, int level) const; - void add_expr(vhdl_expr *e); -private: - std::list exprs_; -}; - - -/* - * A function call within an expression. - */ -class vhdl_fcall : public vhdl_expr { -public: - vhdl_fcall(const char *name, vhdl_type *rtype) - : vhdl_expr(rtype), name_(name) {}; - ~vhdl_fcall() {} - - void add_expr(vhdl_expr *e) { exprs_.add_expr(e); } - void emit(std::ofstream &of, int level) const; -private: - std::string name_; - vhdl_expr_list exprs_; -}; - - -/* - * A concurrent statement appears in architecture bodies but not - * processes. - */ -class vhdl_conc_stmt : public vhdl_element { - friend class vhdl_arch; // Can set its parent -public: - vhdl_conc_stmt() : parent_(NULL) {} - virtual ~vhdl_conc_stmt() {} - - vhdl_arch *get_parent() const; -private: - vhdl_arch *parent_; -}; - -typedef std::list conc_stmt_list_t; - - -/* - * Any sequential statement in a process. - */ -class vhdl_seq_stmt : public vhdl_element { -public: - virtual ~vhdl_seq_stmt() {} -}; - -typedef std::list seq_stmt_list_t; - - -/* - * Similar to Verilog non-blocking assignment, except the LHS - * must be a signal not a variable. - */ -class vhdl_nbassign_stmt : public vhdl_seq_stmt { -public: - vhdl_nbassign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs) - : lhs_(lhs), rhs_(rhs) {} - - void emit(std::ofstream &of, int level) const; -private: - vhdl_var_ref *lhs_; - vhdl_expr *rhs_; -}; - -/* - * Delay simulation indefinitely, until an event, or for a - * specified time. - */ -class vhdl_wait_stmt : public vhdl_seq_stmt { -public: - void emit(std::ofstream &of, int level) const; -}; - - -class vhdl_null_stmt : public vhdl_seq_stmt { -public: - void emit(std::ofstream &of, int level) const; -}; - - -/* - * A procedure call. Which is a statement, unlike a function - * call which is an expression. - */ -class vhdl_pcall_stmt : public vhdl_seq_stmt { -public: - vhdl_pcall_stmt(const char *name) : name_(name) {} - - void emit(std::ofstream &of, int level) const; - void add_expr(vhdl_expr *e) { exprs_.add_expr(e); } -private: - std::string name_; - vhdl_expr_list exprs_; -}; - - -/* - * A declaration of some sort (variable, component, etc.). - * Declarations have names, which is the identifier of the variable, - * constant, etc. not the type. - */ -class vhdl_decl : public vhdl_element { -public: - vhdl_decl(const char *name, vhdl_type *type=NULL) - : name_(name), type_(type) {} - virtual ~vhdl_decl() {}; - - const std::string &get_name() const { return name_; } - const vhdl_type *get_type() const { return type_; } -protected: - std::string name_; - vhdl_type *type_; -}; - -typedef std::list decl_list_t; - - -/* - * A forward declaration of a component. At the moment it is assumed - * that components declarations will only ever be for entities - * generated by this code generator. This is enforced by making the - * constructor private (use component_decl_for instead). - */ -class vhdl_component_decl : public vhdl_decl { -public: - virtual ~vhdl_component_decl() {}; - - static vhdl_component_decl *component_decl_for(const vhdl_entity *ent); - - void emit(std::ofstream &of, int level) const; -private: - vhdl_component_decl(const char *name); - - // TODO: Ports, etc. -}; - - -/* - * A variable declaration inside a process (although this isn't - * enforced here). - */ -class vhdl_var_decl : public vhdl_decl { -public: - vhdl_var_decl(const char *name, vhdl_type *type) - : vhdl_decl(name, type) {} - ~vhdl_var_decl(); - - void emit(std::ofstream &of, int level) const; -}; - - -/* - * A signal declaration in architecture. - */ -class vhdl_signal_decl : public vhdl_decl { -public: - vhdl_signal_decl(const char *name, vhdl_type *type) - : vhdl_decl(name, type) {} - ~vhdl_signal_decl(); - - void emit(std::ofstream &of, int level) const; -}; - - -/* - * Instantiation of component. This is really only a placeholder - * at the moment until the port mappings are worked out. - */ -class vhdl_comp_inst : public vhdl_conc_stmt { -public: - vhdl_comp_inst(const char *inst_name, const char *comp_name); - virtual ~vhdl_comp_inst() {} - - void emit(std::ofstream &of, int level) const; -private: - std::string comp_name_, inst_name_; - - // TODO: Port mappings, etc. -}; - - -/* - * Container for sequential statements. - */ -class vhdl_process : public vhdl_conc_stmt { -public: - vhdl_process(const char *name = ""); - virtual ~vhdl_process(); - - void emit(std::ofstream &of, int level) const; - void add_stmt(vhdl_seq_stmt *stmt); - void add_decl(vhdl_decl *decl); - void add_sensitivity(const char *name); - bool have_declared_var(const std::string &name) const; -private: - seq_stmt_list_t stmts_; - decl_list_t decls_; - std::string name_; - string_list_t sens_; -}; - - -/* - * An architecture which implements an entity. - */ -class vhdl_arch : public vhdl_element { - friend class vhdl_entity; // Can set its parent -public: - vhdl_arch(const char *entity, const char *name="Behavioural"); - virtual ~vhdl_arch(); - - void emit(std::ofstream &of, int level=0) const; - bool have_declared_component(const std::string &name) const; - bool have_declared(const std::string &name) const; - vhdl_decl *get_decl(const std::string &name) const; - void add_decl(vhdl_decl *decl); - void add_stmt(vhdl_conc_stmt *stmt); - vhdl_entity *get_parent() const; -private: - vhdl_entity *parent_; - conc_stmt_list_t stmts_; - decl_list_t decls_; - std::string name_, entity_; -}; - -/* - * An entity defines the ports, parameters, etc. of a module. Each - * entity is associated with a single architecture (although - * technically this need not be the case). Entities are `derived' - * from instantiations of Verilog module scopes in the hierarchy. - */ -class vhdl_entity : public vhdl_element { -public: - vhdl_entity(const char *name, const char *derived_from, - vhdl_arch *arch); - virtual ~vhdl_entity(); - - void emit(std::ofstream &of, int level=0) const; - vhdl_arch *get_arch() const { return arch_; } - const std::string &get_name() const { return name_; } - void requires_package(const char *spec); - const std::string &get_derived_from() const { return derived_from_; } -private: - std::string name_; - vhdl_arch *arch_; // Entity may only have a single architecture - std::string derived_from_; - string_list_t uses_; -}; - -typedef std::list entity_list_t; +typedef std::list element_list_t; +int indent(int level); +void newline(std::ofstream &of, int level); +void blank_line(std::ofstream &of, int level); #endif diff --git a/tgt-vhdl/vhdl_helper.hh b/tgt-vhdl/vhdl_helper.hh new file mode 100644 index 000000000..b6dc0444f --- /dev/null +++ b/tgt-vhdl/vhdl_helper.hh @@ -0,0 +1,54 @@ +/* + * Helper functions for VHDL syntax elements. + * + * Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef INC_VHDL_HELPER_HH +#define INC_VHDL_HELPER_HH + +#include +#include + +template +void emit_children(std::ofstream &of, + const std::list &children, + int level) +{ + // Don't indent if there are no children + if (children.size() == 0) + newline(of, level); + else { + typename std::list::const_iterator it; + for (it = children.begin(); it != children.end(); ++it) { + newline(of, indent(level)); + (*it)->emit(of, indent(level)); + } + newline(of, level); + } +} + +template +void delete_children(std::list &children) +{ + typename std::list::iterator it; + for (it = children.begin(); it != children.end(); ++it) + delete *it; + children.clear(); +} + +#endif diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc new file mode 100644 index 000000000..3924ec22b --- /dev/null +++ b/tgt-vhdl/vhdl_syntax.cc @@ -0,0 +1,419 @@ +/* + * VHDL abstract syntax elements. + * + * Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "vhdl_syntax.hh" +#include "vhdl_helper.hh" + +#include + +vhdl_entity::vhdl_entity(const char *name, const char *derived_from, + vhdl_arch *arch) + : name_(name), arch_(arch), derived_from_(derived_from) +{ + arch->parent_ = this; +} + +vhdl_entity::~vhdl_entity() +{ + delete arch_; +} + +/* + * Add a package to the list of `use' statements before + * the entity. + */ +void vhdl_entity::requires_package(const char *spec) +{ + std::string pname(spec); + std::list::iterator it; + for (it = uses_.begin(); it != uses_.end(); ++it) { + if (*it == pname) + return; + } + uses_.push_back(spec); +} + +void vhdl_entity::emit(std::ofstream &of, int level) const +{ + // Pretty much every design will use std_logic so we + // might as well include it by default + of << "library ieee;" << std::endl; + of << "use ieee.std_logic_1164.all;" << std::endl; + + for (std::list::const_iterator it = uses_.begin(); + it != uses_.end(); + ++it) + of << "use " << *it << ".all;" << std::endl; + of << std::endl; + + emit_comment(of, level); + of << "entity " << name_ << " is"; + // ...ports... + // newline(indent(level)); + newline(of, level); + of << "end entity; "; + blank_line(of, level); // Extra blank line after entities + arch_->emit(of, level); +} + +vhdl_arch::vhdl_arch(const char *entity, const char *name) + : parent_(NULL), name_(name), entity_(entity) +{ + +} + +vhdl_arch::~vhdl_arch() +{ + delete_children(stmts_); + delete_children(decls_); +} + +void vhdl_arch::add_stmt(vhdl_conc_stmt *stmt) +{ + stmt->parent_ = this; + stmts_.push_back(stmt); +} + +void vhdl_arch::add_decl(vhdl_decl *decl) +{ + decls_.push_back(decl); +} + +vhdl_entity *vhdl_arch::get_parent() const +{ + assert(parent_); + return parent_; +} + +void vhdl_arch::emit(std::ofstream &of, int level) const +{ + emit_comment(of, level); + of << "architecture " << name_ << " of " << entity_; + of << " is"; + emit_children(of, decls_, level); + of << "begin"; + emit_children(of, stmts_, level); + of << "end architecture;"; + blank_line(of, level); // Extra blank line after architectures; +} + +vhdl_decl *vhdl_arch::get_decl(const std::string &name) const +{ + decl_list_t::const_iterator it; + for (it = decls_.begin(); it != decls_.end(); ++it) { + if ((*it)->get_name() == name) + return *it; + } + return NULL; +} + +/* + * True if component `name' has already been declared in this + * architecture. This is a bit of hack, since it uses typeid + * to distinguish between components and other declarations. + */ +bool vhdl_arch::have_declared_component(const std::string &name) const +{ + std::string comp_typename(typeid(vhdl_component_decl).name()); + decl_list_t::const_iterator it; + for (it = decls_.begin(); it != decls_.end(); ++it) { + if (comp_typename == typeid(**it).name() + && (*it)->get_name() == name) + return true; + } + return false; +} + +/* + * True if any declaration of `name' has been added to the + * architecture. + */ +bool vhdl_arch::have_declared(const std::string &name) const +{ + return get_decl(name) != NULL; +} + +vhdl_arch *vhdl_conc_stmt::get_parent() const +{ + assert(parent_); + return parent_; +} + +vhdl_process::vhdl_process(const char *name) + : name_(name) +{ + +} + +vhdl_process::~vhdl_process() +{ + delete_children(stmts_); + delete_children(decls_); +} + +void vhdl_process::add_stmt(vhdl_seq_stmt* stmt) +{ + stmts_.push_back(stmt); +} + +void vhdl_process::add_decl(vhdl_decl* decl) +{ + decls_.push_back(decl); +} + +void vhdl_process::add_sensitivity(const char *name) +{ + sens_.push_back(name); +} + +bool vhdl_process::have_declared_var(const std::string &name) const +{ + decl_list_t::const_iterator it; + for (it = decls_.begin(); it != decls_.end(); ++it) { + if ((*it)->get_name() == name) + return true; + } + return false; +} + +void vhdl_process::emit(std::ofstream &of, int level) const +{ + emit_comment(of, level); + if (name_.size() > 0) + of << name_ << ": "; + of << "process "; + + int num_sens = sens_.size(); + if (num_sens > 0) { + of << "("; + string_list_t::const_iterator it; + for (it = sens_.begin(); it != sens_.end(); ++it) { + of << *it; + if (--num_sens > 0) + of << ", "; + } + of << ") "; + } + + of << "is"; + emit_children(of, decls_, level); + of << "begin"; + emit_children(of, stmts_, level); + of << "end process;"; + newline(of, level); +} + +vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name) + : comp_name_(comp_name), inst_name_(inst_name) +{ + +} + +void vhdl_comp_inst::emit(std::ofstream &of, int level) const +{ + // If there are no ports or generics we don't need to mention them... + emit_comment(of, level); + of << inst_name_ << ": " << comp_name_ << ";"; + newline(of, level); +} + +vhdl_component_decl::vhdl_component_decl(const char *name) + : vhdl_decl(name) +{ + +} + +/* + * Create a component declaration for the given entity. + */ +vhdl_component_decl *vhdl_component_decl::component_decl_for(const vhdl_entity *ent) +{ + assert(ent != NULL); + + vhdl_component_decl *decl = new vhdl_component_decl + (ent->get_name().c_str()); + + return decl; +} + +void vhdl_component_decl::emit(std::ofstream &of, int level) const +{ + emit_comment(of, level); + of << "component " << name_ << " is"; + // ...ports... + newline(of, level); + of << "end component;"; +} + +void vhdl_wait_stmt::emit(std::ofstream &of, int level) const +{ + // TODO: There are lots of different types of `wait' + of << "wait;"; +} + + +vhdl_var_decl::~vhdl_var_decl() +{ + delete type_; +} + +void vhdl_var_decl::emit(std::ofstream &of, int level) const +{ + of << "variable " << name_ << " : "; + type_->emit(of, level); + of << ";"; + emit_comment(of, level, true); +} + +vhdl_signal_decl::~vhdl_signal_decl() +{ + delete type_; +} + +void vhdl_signal_decl::emit(std::ofstream &of, int level) const +{ + of << "signal " << name_ << " : "; + type_->emit(of, level); + of << ";"; + emit_comment(of, level, true); +} + +vhdl_expr::~vhdl_expr() +{ + delete type_; +} + +/* + * The default cast just assumes there's a VHDL cast function to + * do the job for us. + */ +vhdl_expr *vhdl_expr::cast(const vhdl_type *to) +{ + vhdl_fcall *conv = + new vhdl_fcall(to->get_string().c_str(), new vhdl_type(*to)); + conv->add_expr(this); + + return conv; +} + +void vhdl_expr_list::add_expr(vhdl_expr *e) +{ + exprs_.push_back(e); +} + +vhdl_expr_list::~vhdl_expr_list() +{ + delete_children(exprs_); +} + +void vhdl_expr_list::emit(std::ofstream &of, int level) const +{ + of << "("; + + int size = exprs_.size(); + std::list::const_iterator it; + for (it = exprs_.begin(); it != exprs_.end(); ++it) { + (*it)->emit(of, level); + if (--size > 0) + of << ", "; + } + + of << ")"; +} + +void vhdl_pcall_stmt::emit(std::ofstream &of, int level) const +{ + of << name_; + exprs_.emit(of, level); + of << ";"; +} + +void vhdl_var_ref::emit(std::ofstream &of, int level) const +{ + of << name_; +} + +void vhdl_const_string::emit(std::ofstream &of, int level) const +{ + // In some instances a string literal can be ambiguous between + // a String type and some other types (e.g. std_logic_vector) + // The explicit cast to String removes this ambiguity (although + // isn't always strictly necessary) + of << "String'(\"" << value_ << "\")"; +} + +void vhdl_null_stmt::emit(std::ofstream &of, int level) const +{ + of << "null;"; +} + +void vhdl_fcall::emit(std::ofstream &of, int level) const +{ + of << name_; + exprs_.emit(of, level); +} + +void vhdl_nbassign_stmt::emit(std::ofstream &of, int level) const +{ + lhs_->emit(of, level); + of << " <= "; + rhs_->emit(of, level); + of << ";"; +} + +vhdl_const_bits::vhdl_const_bits(const char *value) + : vhdl_expr(vhdl_type::std_logic_vector(strlen(value)-1, 0)), + value_(value) +{ + +} + +vhdl_expr *vhdl_const_bits::cast(const vhdl_type *to) +{ + if (to->get_name() == VHDL_TYPE_STD_LOGIC) { + // VHDL won't let us cast directly between a vector and + // a scalar type + // But we don't need to here as we have the bits available + + // Take the least significant bit + char lsb = value_[0]; + + return new vhdl_const_bit(lsb); + } + else + return vhdl_expr::cast(to); +} + +void vhdl_const_bits::emit(std::ofstream &of, int level) const +{ + of << "std_logic_vector'(\""; + + // The bits appear to be in reverse order + std::string::const_reverse_iterator it; + for (it = value_.rbegin(); it != value_.rend(); ++it) + of << *it; + + of << "\")"; +} + +void vhdl_const_bit::emit(std::ofstream &of, int level) const +{ + of << "'" << bit_ << "'"; +} diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh new file mode 100644 index 000000000..525fc1493 --- /dev/null +++ b/tgt-vhdl/vhdl_syntax.hh @@ -0,0 +1,345 @@ +/* + * VHDL abstract syntax elements. + * + * Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef INC_VHDL_SYNTAX_HH +#define INC_VHDL_SYNTAX_HH + +#include "vhdl_element.hh" +#include "vhdl_type.hh" + +class vhdl_entity; +class vhdl_arch; + +class vhdl_expr : public vhdl_element { +public: + vhdl_expr(vhdl_type* type) : type_(type) {} + virtual ~vhdl_expr(); + + const vhdl_type *get_type() const { return type_; } + virtual vhdl_expr *cast(const vhdl_type *to); +private: + vhdl_type *type_; +}; + + +/* + * A normal scalar variable reference. + */ +class vhdl_var_ref : public vhdl_expr { +public: + vhdl_var_ref(const char *name, vhdl_type *type) + : vhdl_expr(type), name_(name) {} + + void emit(std::ofstream &of, int level) const; +private: + std::string name_; +}; + + +class vhdl_const_string : public vhdl_expr { +public: + vhdl_const_string(const char *value) + : vhdl_expr(vhdl_type::string()), value_(value) {} + + void emit(std::ofstream &of, int level) const; +private: + std::string value_; +}; + +class vhdl_const_bits : public vhdl_expr { +public: + vhdl_const_bits(const char *value); + void emit(std::ofstream &of, int level) const; + const std::string &get_value() const { return value_; } + vhdl_expr *cast(const vhdl_type *to); +private: + std::string value_; +}; + +class vhdl_const_bit : public vhdl_expr { +public: + vhdl_const_bit(char bit) + : vhdl_expr(vhdl_type::std_logic()), bit_(bit) {} + void emit(std::ofstream &of, int level) const; +private: + char bit_; +}; + +class vhdl_expr_list : public vhdl_element { +public: + ~vhdl_expr_list(); + + void emit(std::ofstream &of, int level) const; + void add_expr(vhdl_expr *e); +private: + std::list exprs_; +}; + + +/* + * A function call within an expression. + */ +class vhdl_fcall : public vhdl_expr { +public: + vhdl_fcall(const char *name, vhdl_type *rtype) + : vhdl_expr(rtype), name_(name) {}; + ~vhdl_fcall() {} + + void add_expr(vhdl_expr *e) { exprs_.add_expr(e); } + void emit(std::ofstream &of, int level) const; +private: + std::string name_; + vhdl_expr_list exprs_; +}; + + +/* + * A concurrent statement appears in architecture bodies but not + * processes. + */ +class vhdl_conc_stmt : public vhdl_element { + friend class vhdl_arch; // Can set its parent +public: + vhdl_conc_stmt() : parent_(NULL) {} + virtual ~vhdl_conc_stmt() {} + + vhdl_arch *get_parent() const; +private: + vhdl_arch *parent_; +}; + +typedef std::list conc_stmt_list_t; + + +/* + * Any sequential statement in a process. + */ +class vhdl_seq_stmt : public vhdl_element { +public: + virtual ~vhdl_seq_stmt() {} +}; + +typedef std::list seq_stmt_list_t; + + +/* + * Similar to Verilog non-blocking assignment, except the LHS + * must be a signal not a variable. + */ +class vhdl_nbassign_stmt : public vhdl_seq_stmt { +public: + vhdl_nbassign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs) + : lhs_(lhs), rhs_(rhs) {} + + void emit(std::ofstream &of, int level) const; +private: + vhdl_var_ref *lhs_; + vhdl_expr *rhs_; +}; + +/* + * Delay simulation indefinitely, until an event, or for a + * specified time. + */ +class vhdl_wait_stmt : public vhdl_seq_stmt { +public: + void emit(std::ofstream &of, int level) const; +}; + + +class vhdl_null_stmt : public vhdl_seq_stmt { +public: + void emit(std::ofstream &of, int level) const; +}; + + +/* + * A procedure call. Which is a statement, unlike a function + * call which is an expression. + */ +class vhdl_pcall_stmt : public vhdl_seq_stmt { +public: + vhdl_pcall_stmt(const char *name) : name_(name) {} + + void emit(std::ofstream &of, int level) const; + void add_expr(vhdl_expr *e) { exprs_.add_expr(e); } +private: + std::string name_; + vhdl_expr_list exprs_; +}; + + +/* + * A declaration of some sort (variable, component, etc.). + * Declarations have names, which is the identifier of the variable, + * constant, etc. not the type. + */ +class vhdl_decl : public vhdl_element { +public: + vhdl_decl(const char *name, vhdl_type *type=NULL) + : name_(name), type_(type) {} + virtual ~vhdl_decl() {}; + + const std::string &get_name() const { return name_; } + const vhdl_type *get_type() const { return type_; } +protected: + std::string name_; + vhdl_type *type_; +}; + +typedef std::list decl_list_t; + + +/* + * A forward declaration of a component. At the moment it is assumed + * that components declarations will only ever be for entities + * generated by this code generator. This is enforced by making the + * constructor private (use component_decl_for instead). + */ +class vhdl_component_decl : public vhdl_decl { +public: + virtual ~vhdl_component_decl() {}; + + static vhdl_component_decl *component_decl_for(const vhdl_entity *ent); + + void emit(std::ofstream &of, int level) const; +private: + vhdl_component_decl(const char *name); + + // TODO: Ports, etc. +}; + + +/* + * A variable declaration inside a process (although this isn't + * enforced here). + */ +class vhdl_var_decl : public vhdl_decl { +public: + vhdl_var_decl(const char *name, vhdl_type *type) + : vhdl_decl(name, type) {} + ~vhdl_var_decl(); + + void emit(std::ofstream &of, int level) const; +}; + + +/* + * A signal declaration in architecture. + */ +class vhdl_signal_decl : public vhdl_decl { +public: + vhdl_signal_decl(const char *name, vhdl_type *type) + : vhdl_decl(name, type) {} + ~vhdl_signal_decl(); + + void emit(std::ofstream &of, int level) const; +}; + + +/* + * Instantiation of component. This is really only a placeholder + * at the moment until the port mappings are worked out. + */ +class vhdl_comp_inst : public vhdl_conc_stmt { +public: + vhdl_comp_inst(const char *inst_name, const char *comp_name); + virtual ~vhdl_comp_inst() {} + + void emit(std::ofstream &of, int level) const; +private: + std::string comp_name_, inst_name_; + + // TODO: Port mappings, etc. +}; + + +/* + * Container for sequential statements. + */ +class vhdl_process : public vhdl_conc_stmt { +public: + vhdl_process(const char *name = ""); + virtual ~vhdl_process(); + + void emit(std::ofstream &of, int level) const; + void add_stmt(vhdl_seq_stmt *stmt); + void add_decl(vhdl_decl *decl); + void add_sensitivity(const char *name); + bool have_declared_var(const std::string &name) const; +private: + seq_stmt_list_t stmts_; + decl_list_t decls_; + std::string name_; + string_list_t sens_; +}; + + +/* + * An architecture which implements an entity. + */ +class vhdl_arch : public vhdl_element { + friend class vhdl_entity; // Can set its parent +public: + vhdl_arch(const char *entity, const char *name="Behavioural"); + virtual ~vhdl_arch(); + + void emit(std::ofstream &of, int level=0) const; + bool have_declared_component(const std::string &name) const; + bool have_declared(const std::string &name) const; + vhdl_decl *get_decl(const std::string &name) const; + void add_decl(vhdl_decl *decl); + void add_stmt(vhdl_conc_stmt *stmt); + vhdl_entity *get_parent() const; +private: + vhdl_entity *parent_; + conc_stmt_list_t stmts_; + decl_list_t decls_; + std::string name_, entity_; +}; + +/* + * An entity defines the ports, parameters, etc. of a module. Each + * entity is associated with a single architecture (although + * technically this need not be the case). Entities are `derived' + * from instantiations of Verilog module scopes in the hierarchy. + */ +class vhdl_entity : public vhdl_element { +public: + vhdl_entity(const char *name, const char *derived_from, + vhdl_arch *arch); + virtual ~vhdl_entity(); + + void emit(std::ofstream &of, int level=0) const; + vhdl_arch *get_arch() const { return arch_; } + const std::string &get_name() const { return name_; } + void requires_package(const char *spec); + const std::string &get_derived_from() const { return derived_from_; } +private: + std::string name_; + vhdl_arch *arch_; // Entity may only have a single architecture + std::string derived_from_; + string_list_t uses_; +}; + +typedef std::list entity_list_t; + +#endif + diff --git a/tgt-vhdl/vhdl_target.h b/tgt-vhdl/vhdl_target.h index 8e23e8829..b154c5f18 100644 --- a/tgt-vhdl/vhdl_target.h +++ b/tgt-vhdl/vhdl_target.h @@ -4,7 +4,8 @@ #include "vhdl_config.h" #include "ivl_target.h" -#include "vhdl_element.hh" +#include "vhdl_syntax.hh" +#include "vhdl_type.hh" #include diff --git a/tgt-vhdl/vhdl_type.cc b/tgt-vhdl/vhdl_type.cc new file mode 100644 index 000000000..1896f113f --- /dev/null +++ b/tgt-vhdl/vhdl_type.cc @@ -0,0 +1,72 @@ +/* + * VHDL variable and signal types. + * + * Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "vhdl_type.hh" + +#include + + +vhdl_type *vhdl_type::std_logic() +{ + return new vhdl_type(VHDL_TYPE_STD_LOGIC); +} + +vhdl_type *vhdl_type::string() +{ + return new vhdl_type(VHDL_TYPE_STRING); +} + +vhdl_type *vhdl_type::line() +{ + return new vhdl_type(VHDL_TYPE_LINE); +} + +std::string vhdl_type::get_string() const +{ + switch (name_) { + case VHDL_TYPE_STD_LOGIC: + return std::string("std_logic"); + case VHDL_TYPE_STD_LOGIC_VECTOR: + { + std::ostringstream ss; + ss << "std_logic_vector(" << msb_; + ss << " downto " << lsb_ << ")"; + return ss.str(); + } + case VHDL_TYPE_STRING: + return std::string("String"); + case VHDL_TYPE_LINE: + return std::string("Line"); + case VHDL_TYPE_FILE: + return std::string("File"); + default: + return std::string("BadType"); + } +} + +void vhdl_type::emit(std::ofstream &of, int level) const +{ + of << get_string(); +} + +vhdl_type *vhdl_type::std_logic_vector(int msb, int lsb) +{ + return new vhdl_type(VHDL_TYPE_STD_LOGIC_VECTOR, msb, lsb); +} diff --git a/tgt-vhdl/vhdl_type.hh b/tgt-vhdl/vhdl_type.hh new file mode 100644 index 000000000..2bc28ad1f --- /dev/null +++ b/tgt-vhdl/vhdl_type.hh @@ -0,0 +1,60 @@ +/* + * VHDL variable and signal types. + * + * Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef INC_VHDL_TYPE_HH +#define INC_VHDL_TYPE_HH + +#include "vhdl_element.hh" + +enum vhdl_type_name_t { + VHDL_TYPE_STD_LOGIC, + VHDL_TYPE_STD_LOGIC_VECTOR, + VHDL_TYPE_STRING, + VHDL_TYPE_LINE, + VHDL_TYPE_FILE +}; + +/* + * A type at the moment is just a name. It shouldn't get + * too much more complex, as Verilog's type system is much + * simpler than VHDL's. + */ +class vhdl_type : public vhdl_element { +public: + vhdl_type(vhdl_type_name_t name, int msb = 0, int lsb = 0) + : name_(name), msb_(msb), lsb_(lsb) {} + virtual ~vhdl_type() {} + + void emit(std::ofstream &of, int level) const; + vhdl_type_name_t get_name() const { return name_; } + std::string get_string() const; + int get_width() const { return msb_ - lsb_ + 1; } + + // Common types + static vhdl_type *std_logic(); + static vhdl_type *string(); + static vhdl_type *line(); + static vhdl_type *std_logic_vector(int msb, int lsb); +protected: + vhdl_type_name_t name_; + int msb_, lsb_; +}; + +#endif