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 <iostream>
|
||||||
#include <cassert>
|
#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)
|
static vhdl_expr *concat_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
||||||
{
|
{
|
||||||
vhdl_type *result_type =
|
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 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)
|
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));
|
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;
|
return selfrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static vhdl_expr *part_select_pv_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
static vhdl_expr *part_select_pv_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
||||||
{
|
{
|
||||||
vhdl_expr *off = part_select_base(scope, lpm);;
|
return nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static vhdl_expr *ufunc_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
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;
|
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)) {
|
switch (ivl_lpm_type(lpm)) {
|
||||||
case IVL_LPM_ADD:
|
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)
|
int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm)
|
||||||
{
|
{
|
||||||
if (ivl_lpm_type(lpm) == IVL_LPM_PART_PV)
|
vhdl_expr *f = lpm_to_expr(arch->get_scope(), lpm);
|
||||||
return draw_part_select_pv_lpm(arch, lpm);
|
if (NULL == f)
|
||||||
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));
|
|
||||||
|
|
||||||
return 0;
|
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) &&
|
else if ((allowed & NEXUS_TO_OTHER) &&
|
||||||
(lpm = ivl_nexus_ptr_lpm(nexus_ptr))) {
|
(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) &&
|
else if ((allowed & NEXUS_TO_CONST) &&
|
||||||
(con = ivl_nexus_ptr_con(nexus_ptr))) {
|
(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);
|
int nlpms = ivl_scope_lpms(scope);
|
||||||
for (int i = 0; i < nlpms; i++) {
|
for (int i = 0; i < nlpms; i++) {
|
||||||
if (draw_lpm(arch, ivl_scope_lpm(scope, i)) != 0)
|
ivl_lpm_t lpm = ivl_scope_lpm(scope, i);
|
||||||
error("Failed to translate LPM");
|
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
|
// 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()) {
|
if (inst_name == ent->get_name()) {
|
||||||
// Cannot have instance name the same as type in VHDL
|
// Cannot have instance name the same as type in VHDL
|
||||||
inst_name += "_Inst";
|
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 =
|
vhdl_comp_inst *inst =
|
||||||
new vhdl_comp_inst(inst_name.c_str(), ent->get_name().c_str());
|
new vhdl_comp_inst(inst_name.c_str(), ent->get_name().c_str());
|
||||||
port_map(scope, parent_ent, inst);
|
port_map(scope, parent_ent, inst);
|
||||||
|
|
|
||||||
|
|
@ -289,7 +289,9 @@ static int draw_assign(vhdl_procedural *proc, stmt_container *container,
|
||||||
ivl_statement_t stmt)
|
ivl_statement_t stmt)
|
||||||
{
|
{
|
||||||
if (proc->get_scope()->allow_signal_assignment()) {
|
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 =
|
vhdl_nbassign_stmt *a =
|
||||||
make_assignment<vhdl_nbassign_stmt>(proc, container, stmt, false);
|
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);
|
ivl_statement_t stmt);
|
||||||
int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm);
|
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_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);
|
void remember_entity(vhdl_entity *ent);
|
||||||
vhdl_entity *find_entity(const string &tname);
|
vhdl_entity *find_entity(const string &tname);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue