Implement part select for LHS of assignment
This commit is contained in:
parent
37fe6e4219
commit
b0de1a8d7e
|
|
@ -110,15 +110,23 @@ static int draw_noop(vhdl_procedural *proc, stmt_container *container,
|
||||||
*/
|
*/
|
||||||
template <class T>
|
template <class T>
|
||||||
static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container,
|
static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container,
|
||||||
ivl_signal_t sig, vhdl_expr *rhs, bool blocking)
|
ivl_signal_t sig, vhdl_expr *rhs, bool blocking,
|
||||||
|
vhdl_expr *base = NULL, unsigned lval_width = 0)
|
||||||
{
|
{
|
||||||
std::string signame(get_renamed_signal(sig));
|
std::string signame(get_renamed_signal(sig));
|
||||||
|
|
||||||
vhdl_decl *decl = proc->get_scope()->get_decl(signame);
|
vhdl_decl *decl = proc->get_scope()->get_decl(signame);
|
||||||
assert(decl);
|
assert(decl);
|
||||||
|
|
||||||
|
// TODO: Fix casting when there is a part select
|
||||||
|
if (base == NULL)
|
||||||
rhs = rhs->cast(decl->get_type());
|
rhs = rhs->cast(decl->get_type());
|
||||||
|
|
||||||
|
if (base) {
|
||||||
|
vhdl_type integer(VHDL_TYPE_INTEGER);
|
||||||
|
base = base->cast(&integer);
|
||||||
|
}
|
||||||
|
|
||||||
bool isvar = strip_var(signame) != signame;
|
bool isvar = strip_var(signame) != signame;
|
||||||
|
|
||||||
// Where possible, move constant assignments into the
|
// Where possible, move constant assignments into the
|
||||||
|
|
@ -154,6 +162,9 @@ static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container,
|
||||||
vhdl_var_ref *lval_ref = new vhdl_var_ref(renamed.c_str(), NULL);
|
vhdl_var_ref *lval_ref = new vhdl_var_ref(renamed.c_str(), NULL);
|
||||||
vhdl_var_ref *sig_ref = new vhdl_var_ref(signame.c_str(), NULL);
|
vhdl_var_ref *sig_ref = new vhdl_var_ref(signame.c_str(), NULL);
|
||||||
|
|
||||||
|
if (base)
|
||||||
|
lval_ref->set_slice(base, lval_width-1);
|
||||||
|
|
||||||
T *a = new T(lval_ref, sig_ref);
|
T *a = new T(lval_ref, sig_ref);
|
||||||
container->add_stmt(a);
|
container->add_stmt(a);
|
||||||
|
|
||||||
|
|
@ -174,6 +185,8 @@ static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container,
|
||||||
|
|
||||||
// The type here can be null as it is never actually needed
|
// The type here can be null as it is never actually needed
|
||||||
vhdl_var_ref *lval_ref = new vhdl_var_ref(signame.c_str(), NULL);
|
vhdl_var_ref *lval_ref = new vhdl_var_ref(signame.c_str(), NULL);
|
||||||
|
if (base)
|
||||||
|
lval_ref->set_slice(base, lval_width-1);
|
||||||
|
|
||||||
T *a = new T(lval_ref, rhs);
|
T *a = new T(lval_ref, rhs);
|
||||||
container->add_stmt(a);
|
container->add_stmt(a);
|
||||||
|
|
@ -198,6 +211,16 @@ static T *make_assignment(vhdl_procedural *proc, stmt_container *container,
|
||||||
ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
|
ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
|
||||||
ivl_signal_t sig;
|
ivl_signal_t sig;
|
||||||
if ((sig = ivl_lval_sig(lval))) {
|
if ((sig = ivl_lval_sig(lval))) {
|
||||||
|
|
||||||
|
vhdl_expr *base = NULL;
|
||||||
|
ivl_expr_t e_off = ivl_lval_part_off(lval);
|
||||||
|
if (e_off) {
|
||||||
|
if ((base = translate_expr(e_off)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned lval_width = ivl_lval_width(lval);
|
||||||
|
|
||||||
ivl_expr_t rval = ivl_stmt_rval(stmt);
|
ivl_expr_t rval = ivl_stmt_rval(stmt);
|
||||||
if (ivl_expr_type(rval) == IVL_EX_TERNARY) {
|
if (ivl_expr_type(rval) == IVL_EX_TERNARY) {
|
||||||
// Expand ternary expressions into an if statement
|
// Expand ternary expressions into an if statement
|
||||||
|
|
@ -210,9 +233,9 @@ static T *make_assignment(vhdl_procedural *proc, stmt_container *container,
|
||||||
|
|
||||||
vhdl_if_stmt *vhdif = new vhdl_if_stmt(test);
|
vhdl_if_stmt *vhdif = new vhdl_if_stmt(test);
|
||||||
make_vhdl_assignment<T>(proc, vhdif->get_then_container(), sig,
|
make_vhdl_assignment<T>(proc, vhdif->get_then_container(), sig,
|
||||||
true_part, blocking);
|
true_part, blocking, base, lval_width);
|
||||||
make_vhdl_assignment<T>(proc, vhdif->get_else_container(), sig,
|
make_vhdl_assignment<T>(proc, vhdif->get_else_container(), sig,
|
||||||
false_part, blocking);
|
false_part, blocking, base, lval_width);
|
||||||
|
|
||||||
container->add_stmt(vhdif);
|
container->add_stmt(vhdif);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -222,7 +245,7 @@ static T *make_assignment(vhdl_procedural *proc, stmt_container *container,
|
||||||
if (NULL == rhs)
|
if (NULL == rhs)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return make_vhdl_assignment<T>(proc, container, sig, rhs, blocking);
|
return make_vhdl_assignment<T>(proc, container, sig, rhs, blocking, base, lval_width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -477,6 +477,10 @@ void vhdl_var_ref::emit(std::ostream &of, int level) const
|
||||||
of << name_;
|
of << name_;
|
||||||
if (slice_) {
|
if (slice_) {
|
||||||
of << "(";
|
of << "(";
|
||||||
|
if (slice_width_ > 0) {
|
||||||
|
slice_->emit(of, level);
|
||||||
|
of << " + " << slice_width_ << " downto ";
|
||||||
|
}
|
||||||
slice_->emit(of, level);
|
slice_->emit(of, level);
|
||||||
of << ")";
|
of << ")";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,11 @@ public:
|
||||||
|
|
||||||
void emit(std::ostream &of, int level) const;
|
void emit(std::ostream &of, int level) const;
|
||||||
const std::string &get_name() const { return name_; }
|
const std::string &get_name() const { return name_; }
|
||||||
void set_slice(vhdl_expr *s) { slice_ = s; }
|
void set_slice(vhdl_expr *s, int w=0) { slice_ = s; slice_width_ = w; }
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
vhdl_expr *slice_;
|
vhdl_expr *slice_;
|
||||||
|
unsigned slice_width_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue