diff --git a/t-dll-api.cc b/t-dll-api.cc index 206943f1a3..179a42a62c 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1424,6 +1424,36 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net) return net->u_.repeat.count; case IVL_LPM_CONCAT: return net->u_.concat.inputs; + case IVL_LPM_ABS: + case IVL_LPM_CAST_INT: + case IVL_LPM_CAST_INT2: + case IVL_LPM_CAST_REAL: + case IVL_LPM_RE_AND: + case IVL_LPM_RE_OR: + case IVL_LPM_RE_XOR: + case IVL_LPM_RE_NAND: + case IVL_LPM_RE_NOR: + case IVL_LPM_RE_XNOR: + case IVL_LPM_SIGN_EXT: + case IVL_LPM_FF: + return 1; + case IVL_LPM_ADD: + case IVL_LPM_CMP_EEQ: + case IVL_LPM_CMP_EQ: + case IVL_LPM_CMP_GE: + case IVL_LPM_CMP_GT: + case IVL_LPM_CMP_NE: + case IVL_LPM_CMP_NEE: + case IVL_LPM_DIVIDE: + case IVL_LPM_MOD: + case IVL_LPM_MULT: + case IVL_LPM_POW: + case IVL_LPM_SUB: + case IVL_LPM_SHIFTL: + case IVL_LPM_SHIFTR: + case IVL_LPM_PART_VP: + case IVL_LPM_PART_PV: + return 2; default: assert(0); return 0; diff --git a/tgt-vhdl/lpm.cc b/tgt-vhdl/lpm.cc index c68d6bebef..3c7c5bca48 100644 --- a/tgt-vhdl/lpm.cc +++ b/tgt-vhdl/lpm.cc @@ -41,26 +41,6 @@ static vhdl_expr *part_select_base(vhdl_scope *scope, ivl_lpm_t lpm) return off->cast(&integer); } -static vhdl_expr *concat_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) -{ - vhdl_type *result_type = - vhdl_type::type_for(ivl_lpm_width(lpm), ivl_lpm_signed(lpm) != 0); - vhdl_binop_expr *expr = - new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type); - - for (int i = ivl_lpm_size(lpm) - 1; i >= 0; i--) { - vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i)); - if (NULL == e) { - delete expr; - return NULL; - } - - expr->add_expr(e); - } - - return expr; -} - static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t op) { unsigned out_width = ivl_lpm_width(lpm); @@ -68,14 +48,21 @@ static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop vhdl_type::type_for(out_width, ivl_lpm_signed(lpm) != 0); vhdl_binop_expr *expr = new vhdl_binop_expr(op, result_type); - for (int i = 0; i < 2; i++) { + for (unsigned i = 0; i < ivl_lpm_size(lpm); i++) { vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i)); - if (NULL == e) { - delete expr; + if (NULL == e) return NULL; - } - expr->add_expr(e->cast(result_type)); + // It's possible that the inputs are a mixture of signed and unsigned + // in which case we must cast them to the output type + e = e->cast(vhdl_type::type_for(e->get_type()->get_width(), + ivl_lpm_signed(lpm) != 0)); + + // Bit of a hack: the LPM inputs are in the wrong order for concatenation + if (op == VHDL_BINOP_CONCAT) + expr->add_expr_front(e); + else + expr->add_expr(e); } if (op == VHDL_BINOP_MULT) { @@ -256,7 +243,7 @@ static vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) case IVL_LPM_MOD: return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_MOD); case IVL_LPM_CONCAT: - return concat_lpm_to_expr(scope, lpm); + return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_CONCAT); case IVL_LPM_CMP_GE: return rel_lpm_to_expr(scope, lpm, VHDL_BINOP_GEQ); case IVL_LPM_CMP_GT: diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index 56d3139334..190b18590a 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -239,7 +239,16 @@ void draw_nexus(ivl_nexus_t nexus) vhdl_type *type = vhdl_type::type_for(lpm_temp_width, ivl_lpm_signed(lpm) != 0); ostringstream ss; - ss << "LPM" << ivl_lpm_basename(lpm); + ss << "LPM"; + if (nexus == ivl_lpm_q(lpm)) + ss << "_q"; + else { + for (unsigned d = 0; d < ivl_lpm_size(lpm); d++) { + if (nexus == ivl_lpm_data(lpm, d)) + ss << "_d" << d; + } + } + ss << ivl_lpm_basename(lpm); if (!vhdl_scope->have_declared(ss.str())) vhdl_scope->add_decl(new vhdl_signal_decl(ss.str().c_str(), type)); diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index 4f231e1ee0..747717e248 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -940,6 +940,11 @@ void vhdl_binop_expr::add_expr(vhdl_expr *e) operands_.push_back(e); } +void vhdl_binop_expr::add_expr_front(vhdl_expr *e) +{ + operands_.push_front(e); +} + void vhdl_binop_expr::find_vars(vhdl_var_set_t& read) { for (list::const_iterator it = operands_.begin(); diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index 32745b0976..b591d5ebfa 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -126,6 +126,7 @@ public: ~vhdl_binop_expr(); void add_expr(vhdl_expr *e); + void add_expr_front(vhdl_expr *e); void emit(std::ostream &of, int level) const; void find_vars(vhdl_var_set_t& read); private: