Adding binary +

This commit is contained in:
Nick Gasson 2008-06-14 17:09:31 +01:00
parent 0ea64ad8ab
commit 919c1d695c
5 changed files with 84 additions and 0 deletions

View File

@ -68,6 +68,68 @@ static vhdl_expr *translate_unary(ivl_expr_t e)
default:
error("No translation for unary opcode '%c'\n",
ivl_expr_opcode(e));
delete operand;
return NULL;
}
}
/*
* Translate a numeric binary operator (+, -, etc.) to
* a VHDL equivalent using the numeric_std package.
*/
static vhdl_expr *translate_numeric(vhdl_expr *lhs, vhdl_expr *rhs,
vhdl_binop_t op)
{
int lwidth = lhs->get_type()->get_width();
int rwidth = rhs->get_type()->get_width();
vhdl_type ltype(VHDL_TYPE_UNSIGNED, lhs->get_type()->get_msb(),
lhs->get_type()->get_lsb());
vhdl_type rtype(VHDL_TYPE_UNSIGNED, rhs->get_type()->get_msb(),
rhs->get_type()->get_lsb());
vhdl_expr *l_cast = lhs->cast(&ltype);
vhdl_expr *r_cast = lhs->cast(&rtype);
// May need to resize the left or right hand side
if (lwidth < rwidth) {
vhdl_fcall *resize =
new vhdl_fcall("resize", vhdl_type::nunsigned(rwidth));
resize->add_expr(l_cast);
resize->add_expr(new vhdl_const_int(rwidth));
// l_cast = resize;
}
else if (rwidth < lwidth) {
vhdl_fcall *resize =
new vhdl_fcall("resize", vhdl_type::nunsigned(lwidth));
resize->add_expr(r_cast);
resize->add_expr(new vhdl_const_int(lwidth));
//r_cast = resize;
}
return new vhdl_binop_expr(l_cast, op, r_cast,
vhdl_type::nunsigned(lwidth));
}
static vhdl_expr *translate_binary(ivl_expr_t e)
{
vhdl_expr *lhs = translate_expr(ivl_expr_oper1(e));
if (NULL == lhs)
return NULL;
vhdl_expr *rhs = translate_expr(ivl_expr_oper2(e));
if (NULL == rhs)
return NULL;
switch (ivl_expr_opcode(e)) {
case '+':
return translate_numeric(lhs, rhs, VHDL_BINOP_ADD);
default:
error("No translation for binary opcode '%c'\n",
ivl_expr_opcode(e));
delete lhs;
delete rhs;
return NULL;
}
}
@ -88,6 +150,8 @@ vhdl_expr *translate_expr(ivl_expr_t e)
return translate_number(e);
case IVL_EX_UNARY:
return translate_unary(e);
case IVL_EX_BINARY:
return translate_binary(e);
default:
error("No VHDL translation for expression at %s:%d (type = %d)",
ivl_expr_file(e), ivl_expr_lineno(e), type);

View File

@ -689,6 +689,9 @@ void vhdl_binop_expr::emit(std::ofstream &of, int level) const
case VHDL_BINOP_EQ:
of << " = ";
break;
case VHDL_BINOP_ADD:
of << " + ";
break;
}
(*it)->emit(of, level);

View File

@ -57,6 +57,7 @@ enum vhdl_binop_t {
VHDL_BINOP_AND,
VHDL_BINOP_OR,
VHDL_BINOP_EQ,
VHDL_BINOP_ADD,
};
/*

View File

@ -48,6 +48,16 @@ vhdl_type *vhdl_type::integer()
return new vhdl_type(VHDL_TYPE_INTEGER);
}
vhdl_type *vhdl_type::nunsigned(int width)
{
return new vhdl_type(VHDL_TYPE_UNSIGNED, width-1, 0);
}
vhdl_type *vhdl_type::nsigned(int width)
{
return new vhdl_type(VHDL_TYPE_SIGNED, width-1, 0);
}
std::string vhdl_type::get_string() const
{
switch (name_) {

View File

@ -31,6 +31,8 @@ enum vhdl_type_name_t {
VHDL_TYPE_FILE,
VHDL_TYPE_INTEGER,
VHDL_TYPE_BOOLEAN,
VHDL_TYPE_SIGNED,
VHDL_TYPE_UNSIGNED,
};
/*
@ -48,12 +50,16 @@ public:
vhdl_type_name_t get_name() const { return name_; }
std::string get_string() const;
int get_width() const { return msb_ - lsb_ + 1; }
int get_msb() const { return msb_; }
int get_lsb() const { return lsb_; }
// 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);
static vhdl_type *nunsigned(int width);
static vhdl_type *nsigned(int width);
static vhdl_type *integer();
static vhdl_type *boolean();
protected: