From fbf85398da7db7f9ac7e4651373636f2cff67694 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 7 Jun 2008 16:19:10 +0100 Subject: [PATCH] Support converting bit strings to std_logic --- tgt-vhdl/expr.cc | 10 +++++ tgt-vhdl/scope.cc | 11 ++++-- tgt-vhdl/stmt.cc | 6 ++- tgt-vhdl/vhdl_element.cc | 83 +++++++++++++++++++++++++++++++++++----- tgt-vhdl/vhdl_element.hh | 41 ++++++++++++++++++-- 5 files changed, 135 insertions(+), 16 deletions(-) diff --git a/tgt-vhdl/expr.cc b/tgt-vhdl/expr.cc index 80b9a05bc..b208700c8 100644 --- a/tgt-vhdl/expr.cc +++ b/tgt-vhdl/expr.cc @@ -47,6 +47,14 @@ static vhdl_expr *translate_signal(ivl_expr_t e) return new vhdl_var_ref(ivl_signal_basename(sig), type); } +/* + * A numeric literal ends up as std_logic bit string. + */ +static vhdl_expr *translate_number(ivl_expr_t e) +{ + return new vhdl_const_bits(ivl_expr_bits(e)); +} + /* * Generate a VHDL expression from a Verilog expression. */ @@ -59,6 +67,8 @@ vhdl_expr *translate_expr(ivl_expr_t e) return translate_string(e); case IVL_EX_SIGNAL: return translate_signal(e); + case IVL_EX_NUMBER: + return translate_number(e); default: error("No VHDL translation for expression at %s:%d (type = %d)", ivl_expr_file(e), ivl_expr_lineno(e), type); diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index 4c9f46a08..d804e67dd 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -33,10 +33,15 @@ static void declare_signals(vhdl_arch *arch, ivl_scope_t scope) int nsigs = ivl_scope_sigs(scope); for (int i = 0; i < nsigs; i++) { ivl_signal_t sig = ivl_scope_sig(scope, i); - vhdl_scalar_type *std_logic = - new vhdl_scalar_type("std_logic"); + + int width = ivl_signal_width(sig); + vhdl_type *sig_type; + if (width > 0) + sig_type = vhdl_scalar_type::std_logic(); + else + sig_type = vhdl_vector_type::std_logic_vector(width-1, 0); vhdl_signal_decl *decl = - new vhdl_signal_decl(ivl_signal_basename(sig), std_logic); + new vhdl_signal_decl(ivl_signal_basename(sig), sig_type); arch->add_decl(decl); } } diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index edb18d585..fb4e071fc 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -164,7 +164,11 @@ static int draw_nbassign(vhdl_process *proc, ivl_statement_t stmt) if ((sig = ivl_lval_sig(lval))) { const char *signame = ivl_signal_basename(sig); - vhdl_expr *rhs = translate_expr(ivl_stmt_rval(stmt)); + vhdl_decl *decl = proc->get_parent()->get_decl(signame); + assert(decl); + + vhdl_expr *rhs = + decl->get_type()->cast(translate_expr(ivl_stmt_rval(stmt))); if (NULL == rhs) return 1; diff --git a/tgt-vhdl/vhdl_element.cc b/tgt-vhdl/vhdl_element.cc index a3b499a95..211102aef 100644 --- a/tgt-vhdl/vhdl_element.cc +++ b/tgt-vhdl/vhdl_element.cc @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -343,15 +344,6 @@ void vhdl_wait_stmt::emit(std::ofstream &of, int level) const of << "wait;"; } -/* - * Create a deep copy of this type, so it can appear in more - * than one place in the AST. - */ -vhdl_type *vhdl_scalar_type::clone() const -{ - return new vhdl_scalar_type(name_.c_str()); -} - vhdl_scalar_type *vhdl_scalar_type::std_logic() { return new vhdl_scalar_type("std_logic"); @@ -372,6 +364,55 @@ void vhdl_scalar_type::emit(std::ofstream &of, int level) const of << name_; } +/* + * Cast something to a scalar type. There are a few ugly hacks here + * to handle special cases. + */ +vhdl_expr *vhdl_scalar_type::cast(vhdl_expr *expr) const +{ + if (typeid(*expr) == typeid(vhdl_const_bits) + && name_ == "std_logic") { + + // Converting a literal bit string to std_logic is fairly + // common so this hack is justified by the increase in + // output readability :-) + + const std::string &value = + dynamic_cast(expr)->get_value(); + + // Take the least significant bit + char lsb = value[0]; + + // Discard the given expression and return a brand new one + delete expr; + return new vhdl_const_bit(lsb); + } + else { + // Otherwise just assume there's a pre-defined conversion + const char *c_name = name_.c_str(); + vhdl_fcall *conv = + new vhdl_fcall(c_name, new vhdl_scalar_type(c_name)); + conv->add_expr(expr); + + return conv; + } +} + +vhdl_vector_type *vhdl_vector_type::std_logic_vector(int msb, int lsb) +{ + return new vhdl_vector_type("std_logic_vector", msb, lsb); +} + +void vhdl_vector_type::emit(std::ofstream &of, int level) const +{ + of << name_ << "(" << msb_ << " downto " << lsb_ << ")"; +} + +vhdl_expr *vhdl_vector_type::cast(vhdl_expr *expr) const +{ + return expr; +} + vhdl_var_decl::~vhdl_var_decl() { delete type_; @@ -467,3 +508,27 @@ void vhdl_nbassign_stmt::emit(std::ofstream &of, int level) const rhs_->emit(of, level); of << ";"; } + +vhdl_const_bits::vhdl_const_bits(const char *value) + : vhdl_expr(vhdl_vector_type::std_logic_vector(strlen(value)-1, 0)), + value_(value) +{ + +} + +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 28d38b6bf..dd5b27129 100644 --- a/tgt-vhdl/vhdl_element.hh +++ b/tgt-vhdl/vhdl_element.hh @@ -27,6 +27,7 @@ class vhdl_entity; class vhdl_arch; +class vhdl_expr; typedef std::list string_list_t; @@ -54,7 +55,7 @@ public: vhdl_type(const char *name) : name_(name) {} virtual ~vhdl_type() {} - virtual vhdl_type *clone() const = 0; + virtual vhdl_expr *cast(vhdl_expr *expr) const = 0; const std::string &get_name() const { return name_; } protected: @@ -72,14 +73,31 @@ public: : vhdl_type(name) {} void emit(std::ofstream &of, int level) const; - vhdl_type *clone() const; - + vhdl_expr *cast(vhdl_expr *expr) const; + // Common types static vhdl_scalar_type *std_logic(); static vhdl_scalar_type *string(); static vhdl_scalar_type *line(); }; +/* + * A vector type like std_logic_vector. + */ +class vhdl_vector_type : public vhdl_type { +public: + vhdl_vector_type(const char *name, int msb, int lsb) + : vhdl_type(name), msb_(msb), lsb_(lsb) {} + + void emit(std::ofstream &of, int level) const; + vhdl_expr *cast(vhdl_expr *expr) const; + + // Common types + static vhdl_vector_type *std_logic_vector(int msb, int lsb); +private: + int msb_, lsb_; +}; + class vhdl_expr : public vhdl_element { public: vhdl_expr(vhdl_type* type) : type_(type) {} @@ -115,6 +133,23 @@ 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_; } +private: + std::string value_; +}; + +class vhdl_const_bit : public vhdl_expr { +public: + vhdl_const_bit(char bit) + : vhdl_expr(vhdl_scalar_type::std_logic()), bit_(bit) {} + void emit(std::ofstream &of, int level) const; +private: + char bit_; +}; class vhdl_expr_list : public vhdl_element { public: