From b8e758edf01f2b57a9be2e112baeaa534b712c5a Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Tue, 15 Jul 2008 14:09:24 +0100 Subject: [PATCH] Refactor LPM code --- tgt-vhdl/lpm.cc | 116 ++++++++++++++++++++--------------------- tgt-vhdl/scope.cc | 21 ++++++-- tgt-vhdl/stmt.cc | 4 +- tgt-vhdl/vhdl_target.h | 2 +- 4 files changed, 77 insertions(+), 66 deletions(-) diff --git a/tgt-vhdl/lpm.cc b/tgt-vhdl/lpm.cc index d13a651b9..a1f3ed846 100644 --- a/tgt-vhdl/lpm.cc +++ b/tgt-vhdl/lpm.cc @@ -23,6 +23,53 @@ #include #include +/* + * Return the base of a part select. + */ +static vhdl_expr *part_select_base(vhdl_scope *scope, ivl_lpm_t lpm) +{ + vhdl_expr *off; + ivl_nexus_t base = ivl_lpm_data(lpm, 1); + if (base != NULL) + off = nexus_to_var_ref(scope, base); + else + off = new vhdl_const_int(ivl_lpm_base(lpm)); + + // Array indexes must be integers + vhdl_type integer(VHDL_TYPE_INTEGER); + return off->cast(&integer); +} + +vhdl_var_ref *lpm_output(vhdl_scope *scope, ivl_lpm_t lpm) +{ + vhdl_var_ref *out = nexus_to_var_ref(scope, ivl_lpm_q(lpm, 0)); + if (NULL == out) { + vhdl_type *type = + vhdl_type::type_for(ivl_lpm_width(lpm), + ivl_lpm_signed(lpm) != 0); + string name("LPM"); + name += ivl_lpm_basename(lpm); + name += "_Out"; + + if (!scope->have_declared(name)) { + scope->add_decl + (new vhdl_signal_decl(name.c_str(), new vhdl_type(*type))); + } + + out = new vhdl_var_ref(name.c_str(), type); + } + + if (ivl_lpm_type(lpm) == IVL_LPM_PART_PV) { + vhdl_expr *off = part_select_base(scope, lpm); + assert(off); + + out->set_slice(off, ivl_lpm_width(lpm) - 1); + } + + return out; +} + + static vhdl_expr *concat_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) { vhdl_type *result_type = @@ -71,23 +118,6 @@ static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop return expr; } -/* - * Return the base of a part select. - */ -static vhdl_expr *part_select_base(vhdl_scope *scope, ivl_lpm_t lpm) -{ - vhdl_expr *off; - ivl_nexus_t base = ivl_lpm_data(lpm, 1); - if (base != NULL) - off = nexus_to_var_ref(scope, base); - else - off = new vhdl_const_int(ivl_lpm_base(lpm)); - - // Array indexes must be integers - vhdl_type integer(VHDL_TYPE_INTEGER); - return off->cast(&integer); -} - static vhdl_expr *part_select_vp_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) { vhdl_var_ref *selfrom = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0)); @@ -102,37 +132,10 @@ static vhdl_expr *part_select_vp_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) return selfrom; } + static vhdl_expr *part_select_pv_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) { - vhdl_expr *off = part_select_base(scope, lpm);; - if (NULL == off) - return NULL; - - vhdl_var_ref *out = nexus_to_var_ref(scope, ivl_lpm_q(lpm, 0)); - if (NULL == out) - return NULL; - - out->set_slice(off, ivl_lpm_width(lpm) - 1); - return out; -} - -static int draw_part_select_pv_lpm(vhdl_arch *arch, ivl_lpm_t lpm) -{ - vhdl_var_ref *out; - vhdl_var_ref *selfrom; - if (NULL == (out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm, 0))) - || NULL == (selfrom = nexus_to_var_ref(arch->get_scope(), ivl_lpm_data(lpm, 0)))) { - // Not continuous assignment to signal: ignore it - return 0; - } - - vhdl_expr *off = part_select_base(arch->get_scope(), lpm);; - if (NULL == off) - return 1; - - out->set_slice(off, ivl_lpm_width(lpm) - 1); - arch->add_stmt(new vhdl_cassign_stmt(out, selfrom)); - return 0; + return nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0)); } static vhdl_expr *ufunc_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) @@ -200,7 +203,7 @@ static vhdl_expr *array_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) return ref; } -vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) +static vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) { switch (ivl_lpm_type(lpm)) { case IVL_LPM_ADD: @@ -241,18 +244,13 @@ vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm) { - if (ivl_lpm_type(lpm) == IVL_LPM_PART_PV) - return draw_part_select_pv_lpm(arch, lpm); - else { - vhdl_expr *f = lpm_to_expr(arch->get_scope(), lpm); - if (NULL == f) - return 1; - - vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm, 0)); - if (out) - arch->add_stmt(new vhdl_cassign_stmt(out, f)); - + vhdl_expr *f = lpm_to_expr(arch->get_scope(), lpm); + if (NULL == f) return 0; - } + + vhdl_var_ref *out = lpm_output(arch->get_scope(), lpm); + arch->add_stmt(new vhdl_cassign_stmt(out, f)); + + return 0; } diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index 33af741a8..76b959a5d 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -77,7 +77,7 @@ static vhdl_expr *nexus_to_expr(vhdl_scope *arch_scope, ivl_nexus_t nexus, } else if ((allowed & NEXUS_TO_OTHER) && (lpm = ivl_nexus_ptr_lpm(nexus_ptr))) { - return lpm_to_expr(arch_scope, lpm); + return lpm_output(arch_scope, lpm); } else if ((allowed & NEXUS_TO_CONST) && (con = ivl_nexus_ptr_con(nexus_ptr))) { @@ -370,8 +370,9 @@ static void declare_lpm(vhdl_arch *arch, ivl_scope_t scope) { int nlpms = ivl_scope_lpms(scope); for (int i = 0; i < nlpms; i++) { - if (draw_lpm(arch, ivl_scope_lpm(scope, i)) != 0) - error("Failed to translate LPM"); + ivl_lpm_t lpm = ivl_scope_lpm(scope, i); + if (draw_lpm(arch, lpm) != 0) + error("Failed to translate LPM %s", ivl_lpm_name(lpm)); } } @@ -423,7 +424,7 @@ static vhdl_entity *create_entity_for(ivl_scope_t scope) */ static void map_signal(ivl_signal_t to, vhdl_entity *parent, vhdl_comp_inst *inst) -{ +{ // TODO: Work for multiple words ivl_nexus_t nexus = ivl_signal_nex(to, 0); @@ -564,11 +565,21 @@ static int draw_module(ivl_scope_t scope, ivl_scope_t parent) } // And an instantiation statement - std::string inst_name(ivl_scope_basename(scope)); + string inst_name(ivl_scope_basename(scope)); if (inst_name == ent->get_name()) { // Cannot have instance name the same as type in VHDL inst_name += "_Inst"; } + + // Need to replace any [ and ] characters that result + // from generate statements + string::size_type loc = inst_name.find('[', 0); + if (loc != string::npos) + inst_name.erase(loc, 1); + + loc = inst_name.find(']', 0); + if (loc != string::npos) + inst_name.erase(loc, 1); vhdl_comp_inst *inst = new vhdl_comp_inst(inst_name.c_str(), ent->get_name().c_str()); diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index a7ef4150a..106d1a24d 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -289,7 +289,9 @@ static int draw_assign(vhdl_procedural *proc, stmt_container *container, ivl_statement_t stmt) { if (proc->get_scope()->allow_signal_assignment()) { - // TODO: Explain blocking assignment here + // Blocking assignment is implemented as non-blocking assignment + // followed by a zero-time wait + // This follows the Verilog semantics fairly closely. vhdl_nbassign_stmt *a = make_assignment(proc, container, stmt, false); diff --git a/tgt-vhdl/vhdl_target.h b/tgt-vhdl/vhdl_target.h index 4d7f808e2..9dc559c96 100644 --- a/tgt-vhdl/vhdl_target.h +++ b/tgt-vhdl/vhdl_target.h @@ -19,8 +19,8 @@ int draw_stmt(vhdl_procedural *proc, stmt_container *container, ivl_statement_t stmt); int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm); -vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm); vhdl_expr *translate_expr(ivl_expr_t e); +vhdl_var_ref *lpm_output(vhdl_scope *scope, ivl_lpm_t lpm); void remember_entity(vhdl_entity *ent); vhdl_entity *find_entity(const string &tname);