Add concatenation operator

This commit is contained in:
Nick Gasson 2008-07-06 18:21:34 +01:00
parent 85d2cc78d6
commit c33600bcc3
4 changed files with 42 additions and 22 deletions

View File

@ -218,6 +218,29 @@ static vhdl_expr *translate_select(ivl_expr_t e)
return from->resize(ivl_expr_width(e));
}
static vhdl_type *expr_to_vhdl_type(ivl_expr_t e)
{
if (ivl_expr_signed(e))
return vhdl_type::nsigned(ivl_expr_width(e));
else
return vhdl_type::nunsigned(ivl_expr_width(e));
}
template <class T>
static T *translate_parms(T *t, ivl_expr_t e)
{
int nparams = ivl_expr_parms(e);
for (int i = 0; i < nparams; i++) {
vhdl_expr *param = translate_expr(ivl_expr_parm(e, i));
if (NULL == param)
return NULL;
t->add_expr(param);
}
return t;
}
static vhdl_expr *translate_ufunc(ivl_expr_t e)
{
ivl_scope_t defscope = ivl_expr_def(e);
@ -232,24 +255,10 @@ static vhdl_expr *translate_ufunc(ivl_expr_t e)
const char *funcname = ivl_scope_tname(defscope);
vhdl_type *rettype;
if (ivl_expr_signed(e))
rettype = vhdl_type::nsigned(ivl_expr_width(e));
else
rettype = vhdl_type::nunsigned(ivl_expr_width(e));
vhdl_type *rettype = expr_to_vhdl_type(e);
vhdl_fcall *fcall = new vhdl_fcall(funcname, rettype);
int nparams = ivl_expr_parms(e);
for (int i = 0; i < nparams; i++) {
vhdl_expr *param = translate_expr(ivl_expr_parm(e, i));
if (NULL == param)
return NULL;
fcall->add_expr(param);
}
return fcall;
return translate_parms<vhdl_fcall>(fcall, e);
}
static vhdl_expr *translate_ternary(ivl_expr_t e)
@ -259,6 +268,14 @@ static vhdl_expr *translate_ternary(ivl_expr_t e)
return NULL;
}
static vhdl_expr *translate_concat(ivl_expr_t e)
{
vhdl_type *rtype = expr_to_vhdl_type(e);
vhdl_binop_expr *concat = new vhdl_binop_expr(VHDL_BINOP_CONCAT, rtype);
return translate_parms<vhdl_binop_expr>(concat, e);
}
/*
* Generate a VHDL expression from a Verilog expression.
*/
@ -284,6 +301,8 @@ vhdl_expr *translate_expr(ivl_expr_t e)
return translate_ufunc(e);
case IVL_EX_TERNARY:
return translate_ternary(e);
case IVL_EX_CONCAT:
return translate_concat(e);
default:
error("No VHDL translation for expression at %s:%d (type = %d)",
ivl_expr_file(e), ivl_expr_lineno(e), type);

View File

@ -185,7 +185,7 @@ static std::string make_safe_name(ivl_signal_t sig)
const char *vhdl_reserved[] = {
"in", "out", "entity", "architecture", "inout", "array",
"is", "not", "and", "or", "bus", "bit", // Etc...
"is", "not", "and", "or", "bus", "bit", "line", // Etc...
NULL
};
for (const char **p = vhdl_reserved; *p != NULL; p++) {
@ -354,16 +354,16 @@ static void map_signal(ivl_signal_t to, vhdl_entity *parent,
// result of the expression and that is mapped to the port
// This is actually a bit stricter than necessary: but turns out
// to be much easier to implement
const char *basename = ivl_signal_basename(to);
std::string name = make_safe_name(to);
vhdl_var_ref *to_ref;
if ((to_ref = dynamic_cast<vhdl_var_ref*>(to_e))) {
inst->map_port(basename, to_ref);
inst->map_port(name.c_str(), to_ref);
}
else {
// Not a static expression
std::string tmpname(inst->get_inst_name().c_str());
tmpname += "_";
tmpname += basename;
tmpname += name;
tmpname += "_Expr";
vhdl_type *tmptype = new vhdl_type(*to_e->get_type());
@ -374,7 +374,7 @@ static void map_signal(ivl_signal_t to, vhdl_entity *parent,
parent->get_arch()->add_stmt(new vhdl_cassign_stmt(tmp_ref1, to_e));
vhdl_var_ref *tmp_ref2 = new vhdl_var_ref(*tmp_ref1);
inst->map_port(basename, tmp_ref2);
inst->map_port(name.c_str(), tmp_ref2);
}
}

View File

@ -705,7 +705,7 @@ void vhdl_binop_expr::emit(std::ostream &of, int level) const
while (++it != operands_.end()) {
const char* ops[] = {
"and", "or", "=", "/=", "+", "-", "*", "<",
">", "sll", "srl", "xor"
">", "sll", "srl", "xor", "&"
};
of << " " << ops[op_] << " ";

View File

@ -76,6 +76,7 @@ enum vhdl_binop_t {
VHDL_BINOP_SL,
VHDL_BINOP_SR,
VHDL_BINOP_XOR,
VHDL_BINOP_CONCAT,
};
/*