diff --git a/tgt-vhdl/lpm.cc b/tgt-vhdl/lpm.cc index a9ae1b4cc..98396f609 100644 --- a/tgt-vhdl/lpm.cc +++ b/tgt-vhdl/lpm.cc @@ -23,19 +23,19 @@ #include #include -static int draw_binop_lpm(vhdl_arch *arch, ivl_lpm_t lpm, vhdl_binop_t op) +static vhdl_expr *draw_binop_lpm(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t op) { - vhdl_expr *lhs = nexus_to_var_ref(arch->get_scope(), ivl_lpm_data(lpm, 0)); + vhdl_expr *lhs = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0)); if (NULL == lhs) - return 1; + return NULL; - vhdl_expr *rhs = nexus_to_var_ref(arch->get_scope(), ivl_lpm_data(lpm, 1)); + vhdl_expr *rhs = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 1)); if (NULL == rhs) - return 1; + return NULL; - vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm, 0)); + vhdl_var_ref *out = nexus_to_var_ref(scope, ivl_lpm_q(lpm, 0)); if (NULL == out) - return 1; + return NULL; vhdl_type *result_type = new vhdl_type(*lhs->get_type()); vhdl_expr *expr = new vhdl_binop_expr(lhs, op, rhs, result_type); @@ -53,20 +53,18 @@ static int draw_binop_lpm(vhdl_arch *arch, ivl_lpm_t lpm, vhdl_binop_t op) expr = resize; } - arch->add_stmt(new vhdl_cassign_stmt(out, expr)); - - return 0; + return expr; } /* * Return the base of a part select. */ -static vhdl_expr *part_select_base(vhdl_arch *arch, ivl_lpm_t lpm) +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(arch->get_scope(), base); + off = nexus_to_var_ref(scope, base); else off = new vhdl_const_int(ivl_lpm_base(lpm)); @@ -75,23 +73,18 @@ static vhdl_expr *part_select_base(vhdl_arch *arch, ivl_lpm_t lpm) return off->cast(&integer); } -static int draw_part_select_vp_lpm(vhdl_arch *arch, ivl_lpm_t lpm) +static vhdl_expr *draw_part_select_vp_lpm(vhdl_scope *scope, ivl_lpm_t lpm) { - vhdl_var_ref *selfrom = nexus_to_var_ref(arch->get_scope(), ivl_lpm_data(lpm, 0)); + vhdl_var_ref *selfrom = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0)); if (NULL == selfrom) - return 1; + return NULL; - vhdl_expr *off = part_select_base(arch, lpm);; + vhdl_expr *off = part_select_base(scope, lpm);; if (NULL == off) - return 1; - - vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm, 0)); - if (NULL == out) - return 1; + return NULL; selfrom->set_slice(off, ivl_lpm_width(lpm) - 1); - arch->add_stmt(new vhdl_cassign_stmt(out, selfrom)); - return 0; + return selfrom; } static int draw_part_select_pv_lpm(vhdl_arch *arch, ivl_lpm_t lpm) @@ -100,7 +93,7 @@ static int draw_part_select_pv_lpm(vhdl_arch *arch, ivl_lpm_t lpm) if (NULL == selfrom) return 1; - vhdl_expr *off = part_select_base(arch, lpm);; + vhdl_expr *off = part_select_base(arch->get_scope(), lpm);; if (NULL == off) return 1; @@ -113,103 +106,98 @@ static int draw_part_select_pv_lpm(vhdl_arch *arch, ivl_lpm_t lpm) return 0; } -static int draw_ufunc_lpm(vhdl_arch *arch, ivl_lpm_t lpm) +static vhdl_expr *draw_ufunc_lpm(vhdl_scope *scope, ivl_lpm_t lpm) { vhdl_fcall *fcall = new vhdl_fcall(ivl_lpm_basename(lpm), NULL); for (unsigned i = 0; i < ivl_lpm_size(lpm); i++) { - vhdl_var_ref *ref = nexus_to_var_ref(arch->get_scope(), ivl_lpm_data(lpm, i)); + vhdl_var_ref *ref = nexus_to_var_ref(scope, ivl_lpm_data(lpm, i)); if (NULL == ref) - return 1; + return NULL; fcall->add_expr(ref); } - vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm, 0)); - if (NULL == out) - return 1; - - arch->add_stmt(new vhdl_cassign_stmt(out, fcall)); - - return 0; + return fcall; } -static int draw_reduction_lpm(vhdl_arch *arch, ivl_lpm_t lpm, const char *rfunc, - bool invert) +static vhdl_expr *draw_reduction_lpm(vhdl_scope *scope, ivl_lpm_t lpm, + const char *rfunc, bool invert) { vhdl_fcall *fcall = new vhdl_fcall(rfunc, vhdl_type::std_logic()); - vhdl_var_ref *ref = nexus_to_var_ref(arch->get_scope(), ivl_lpm_data(lpm, 0)); + vhdl_var_ref *ref = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0)); if (NULL == ref) - return 1; + return NULL; fcall->add_expr(ref); - vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm, 0)); - if (NULL == out) - return 1; - if (invert) - arch->add_stmt - (new vhdl_cassign_stmt - (out, new vhdl_unaryop_expr(VHDL_UNARYOP_NOT, fcall, vhdl_type::std_logic()))); + return new vhdl_unaryop_expr + (VHDL_UNARYOP_NOT, fcall, vhdl_type::std_logic()); else - arch->add_stmt(new vhdl_cassign_stmt(out, fcall)); - - return 0; + return fcall; } -static int draw_sign_extend_lpm(vhdl_arch *arch, ivl_lpm_t lpm) +static vhdl_expr *draw_sign_extend_lpm(vhdl_scope *scope, ivl_lpm_t lpm) { - vhdl_expr *ref = nexus_to_var_ref(arch->get_scope(), ivl_lpm_data(lpm, 0)); - if (NULL == ref) - return 1; + vhdl_expr *ref = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0)); + if (ref) + return ref->resize(ivl_lpm_width(lpm)); + else + return NULL; +} - ref = ref->resize(ivl_lpm_width(lpm)); - - vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm, 0)); - if (NULL == out) - return 1; - - arch->add_stmt(new vhdl_cassign_stmt(out, ref)); - - return 0; +vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) +{ + switch (ivl_lpm_type(lpm)) { + case IVL_LPM_ADD: + return draw_binop_lpm(scope, lpm, VHDL_BINOP_ADD); + case IVL_LPM_SUB: + return draw_binop_lpm(scope, lpm, VHDL_BINOP_SUB); + case IVL_LPM_MULT: + return draw_binop_lpm(scope, lpm, VHDL_BINOP_MULT); + case IVL_LPM_CONCAT: + return draw_binop_lpm(scope, lpm, VHDL_BINOP_CONCAT); + case IVL_LPM_PART_VP: + return draw_part_select_vp_lpm(scope, lpm); + case IVL_LPM_UFUNC: + return draw_ufunc_lpm(scope, lpm); + case IVL_LPM_RE_AND: + return draw_reduction_lpm(scope, lpm, "Reduce_AND", false); + case IVL_LPM_RE_NAND: + return draw_reduction_lpm(scope, lpm, "Reduce_AND", true); + case IVL_LPM_RE_NOR: + return draw_reduction_lpm(scope, lpm, "Reduce_OR", true); + case IVL_LPM_RE_OR: + return draw_reduction_lpm(scope, lpm, "Reduce_OR", false); + case IVL_LPM_RE_XOR: + return draw_reduction_lpm(scope, lpm, "Reduce_XOR", false); + case IVL_LPM_RE_XNOR: + return draw_reduction_lpm(scope, lpm, "Reduce_XNOR", false); + case IVL_LPM_SIGN_EXT: + return draw_sign_extend_lpm(scope, lpm); + default: + error("Unsupported LPM type: %d", ivl_lpm_type(lpm)); + return NULL; + } } int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm) { - switch (ivl_lpm_type(lpm)) { - case IVL_LPM_ADD: - return draw_binop_lpm(arch, lpm, VHDL_BINOP_ADD); - case IVL_LPM_SUB: - return draw_binop_lpm(arch, lpm, VHDL_BINOP_SUB); - case IVL_LPM_MULT: - return draw_binop_lpm(arch, lpm, VHDL_BINOP_MULT); - case IVL_LPM_CONCAT: - return draw_binop_lpm(arch, lpm, VHDL_BINOP_CONCAT); - case IVL_LPM_PART_PV: + if (ivl_lpm_type(lpm) == IVL_LPM_PART_PV) return draw_part_select_pv_lpm(arch, lpm); - case IVL_LPM_PART_VP: - return draw_part_select_vp_lpm(arch, lpm); - case IVL_LPM_UFUNC: - return draw_ufunc_lpm(arch, lpm); - case IVL_LPM_RE_AND: - return draw_reduction_lpm(arch, lpm, "Reduce_AND", false); - case IVL_LPM_RE_NAND: - return draw_reduction_lpm(arch, lpm, "Reduce_AND", true); - case IVL_LPM_RE_NOR: - return draw_reduction_lpm(arch, lpm, "Reduce_OR", true); - case IVL_LPM_RE_OR: - return draw_reduction_lpm(arch, lpm, "Reduce_OR", false); - case IVL_LPM_RE_XOR: - return draw_reduction_lpm(arch, lpm, "Reduce_XOR", false); - case IVL_LPM_RE_XNOR: - return draw_reduction_lpm(arch, lpm, "Reduce_XNOR", false); - case IVL_LPM_SIGN_EXT: - return draw_sign_extend_lpm(arch, lpm); - default: - error("Unsupported LPM type: %d", ivl_lpm_type(lpm)); - return 1; + 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 (NULL == out) + return 1; + + arch->add_stmt(new vhdl_cassign_stmt(out, f)); + return 0; } }