Refactor LPM code

This commit is contained in:
Nick Gasson 2008-07-15 14:09:24 +01:00
parent 0b48f69b4e
commit b8e758edf0
4 changed files with 77 additions and 66 deletions

View File

@ -23,6 +23,53 @@
#include <iostream>
#include <cassert>
/*
* 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;
}

View File

@ -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));
}
}
@ -564,12 +565,22 @@ 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());
port_map(scope, parent_ent, inst);

View File

@ -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<vhdl_nbassign_stmt>(proc, container, stmt, false);

View File

@ -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);