Refactor LPM code
This commit is contained in:
parent
0b48f69b4e
commit
b8e758edf0
116
tgt-vhdl/lpm.cc
116
tgt-vhdl/lpm.cc
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue