Support converting bit strings to std_logic

This commit is contained in:
Nick Gasson 2008-06-07 16:19:10 +01:00
parent 1e4b96aa0a
commit fbf85398da
5 changed files with 135 additions and 16 deletions

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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;

View File

@ -22,6 +22,7 @@
#include <algorithm>
#include <cassert>
#include <cstring>
#include <typeinfo>
#include <iostream>
@ -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<vhdl_const_bits*>(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_ << "'";
}

View File

@ -27,6 +27,7 @@
class vhdl_entity;
class vhdl_arch;
class vhdl_expr;
typedef std::list<std::string> 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: