Merge blocking and non-blocking assignment code
This commit is contained in:
parent
a298b03735
commit
5aeff6d47d
|
|
@ -208,7 +208,7 @@ static vhdl_expr *translate_binary(ivl_expr_t e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vhdl_expr *translate_select(ivl_expr_t e)
|
static vhdl_expr *translate_select(ivl_expr_t e)
|
||||||
{
|
{
|
||||||
vhdl_expr *from = translate_expr(ivl_expr_oper1(e));
|
vhdl_expr *from = translate_expr(ivl_expr_oper1(e));
|
||||||
if (NULL == from)
|
if (NULL == from)
|
||||||
|
|
@ -218,7 +218,7 @@ vhdl_expr *translate_select(ivl_expr_t e)
|
||||||
return from->resize(ivl_expr_width(e));
|
return from->resize(ivl_expr_width(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
vhdl_expr *translate_ufunc(ivl_expr_t e)
|
static vhdl_expr *translate_ufunc(ivl_expr_t e)
|
||||||
{
|
{
|
||||||
ivl_scope_t defscope = ivl_expr_def(e);
|
ivl_scope_t defscope = ivl_expr_def(e);
|
||||||
ivl_scope_t parentscope = ivl_scope_parent(defscope);
|
ivl_scope_t parentscope = ivl_scope_parent(defscope);
|
||||||
|
|
@ -252,6 +252,13 @@ vhdl_expr *translate_ufunc(ivl_expr_t e)
|
||||||
return fcall;
|
return fcall;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static vhdl_expr *translate_ternary(ivl_expr_t e)
|
||||||
|
{
|
||||||
|
error("Ternary expression only supported as RHS of assignment");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate a VHDL expression from a Verilog expression.
|
* Generate a VHDL expression from a Verilog expression.
|
||||||
*/
|
*/
|
||||||
|
|
@ -275,6 +282,8 @@ vhdl_expr *translate_expr(ivl_expr_t e)
|
||||||
return translate_select(e);
|
return translate_select(e);
|
||||||
case IVL_EX_UFUNC:
|
case IVL_EX_UFUNC:
|
||||||
return translate_ufunc(e);
|
return translate_ufunc(e);
|
||||||
|
case IVL_EX_TERNARY:
|
||||||
|
return translate_ternary(e);
|
||||||
default:
|
default:
|
||||||
error("No VHDL translation for expression at %s:%d (type = %d)",
|
error("No VHDL translation for expression at %s:%d (type = %d)",
|
||||||
ivl_expr_file(e), ivl_expr_lineno(e), type);
|
ivl_expr_file(e), ivl_expr_lineno(e), type);
|
||||||
|
|
|
||||||
128
tgt-vhdl/stmt.cc
128
tgt-vhdl/stmt.cc
|
|
@ -102,35 +102,31 @@ static int draw_noop(vhdl_procedural *proc, stmt_container *container,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
template <class T>
|
||||||
* A non-blocking assignment inside a process. The semantics for
|
static T *make_assignment(vhdl_procedural *proc, stmt_container *container,
|
||||||
* this are essentially the same as VHDL's non-blocking signal
|
ivl_statement_t stmt, bool blocking)
|
||||||
* assignment.
|
|
||||||
*/
|
|
||||||
static int draw_nbassign(vhdl_procedural *proc, stmt_container *container,
|
|
||||||
ivl_statement_t stmt, vhdl_expr *after = NULL)
|
|
||||||
{
|
{
|
||||||
int nlvals = ivl_stmt_lvals(stmt);
|
int nlvals = ivl_stmt_lvals(stmt);
|
||||||
if (nlvals != 1) {
|
if (nlvals != 1) {
|
||||||
error("Can only have 1 lval at the moment (found %d)", nlvals);
|
error("Can only have 1 lval at the moment (found %d)", nlvals);
|
||||||
return 1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(proc->get_scope()->allow_signal_assignment());
|
|
||||||
|
|
||||||
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))) {
|
||||||
const char *signame = get_renamed_signal(sig).c_str();
|
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);
|
||||||
|
|
||||||
vhdl_expr *rhs_raw = translate_expr(ivl_stmt_rval(stmt));
|
vhdl_expr *rhs_raw = translate_expr(ivl_stmt_rval(stmt));
|
||||||
if (NULL == rhs_raw)
|
if (NULL == rhs_raw)
|
||||||
return 1;
|
return NULL;
|
||||||
vhdl_expr *rhs = rhs_raw->cast(decl->get_type());
|
vhdl_expr *rhs = rhs_raw->cast(decl->get_type());
|
||||||
|
|
||||||
|
bool isvar = strip_var(signame) != signame;
|
||||||
|
|
||||||
// Where possible, move constant assignments into the
|
// Where possible, move constant assignments into the
|
||||||
// declaration as initializers. This optimisation is only
|
// declaration as initializers. This optimisation is only
|
||||||
// performed on assignments of constant values to prevent
|
// performed on assignments of constant values to prevent
|
||||||
|
|
@ -147,63 +143,12 @@ static int draw_nbassign(vhdl_procedural *proc, stmt_container *container,
|
||||||
// internal signals not ports
|
// internal signals not ports
|
||||||
if (proc->get_scope()->initializing()
|
if (proc->get_scope()->initializing()
|
||||||
&& ivl_signal_port(sig) == IVL_SIP_NONE
|
&& ivl_signal_port(sig) == IVL_SIP_NONE
|
||||||
&& !decl->has_initial() && rhs->constant()) {
|
&& !decl->has_initial() && rhs->constant()
|
||||||
|
|
||||||
decl->set_initial(rhs);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// The type here can be null as it is never actually needed
|
|
||||||
vhdl_var_ref *lval_ref = new vhdl_var_ref(signame, NULL);
|
|
||||||
|
|
||||||
vhdl_nbassign_stmt *assign = new vhdl_nbassign_stmt(lval_ref, rhs);
|
|
||||||
if (after != NULL)
|
|
||||||
assign->set_after(after);
|
|
||||||
container->add_stmt(assign);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
error("Only signals as lvals supported at the moment");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int draw_assign(vhdl_procedural *proc, stmt_container *container,
|
|
||||||
ivl_statement_t stmt)
|
|
||||||
{
|
|
||||||
int nlvals = ivl_stmt_lvals(stmt);
|
|
||||||
if (nlvals != 1) {
|
|
||||||
error("Can only have 1 lval at the moment (found %d)", nlvals);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
|
|
||||||
ivl_signal_t sig;
|
|
||||||
if ((sig = ivl_lval_sig(lval))) {
|
|
||||||
const std::string signame(get_renamed_signal(sig));
|
|
||||||
|
|
||||||
vhdl_decl *decl = proc->get_scope()->get_decl(signame);
|
|
||||||
assert(decl);
|
|
||||||
|
|
||||||
vhdl_expr *rhs_raw = translate_expr(ivl_stmt_rval(stmt));
|
|
||||||
if (NULL == rhs_raw)
|
|
||||||
return 1;
|
|
||||||
vhdl_expr *rhs = rhs_raw->cast(decl->get_type());
|
|
||||||
|
|
||||||
bool isvar = strip_var(signame) != signame;
|
|
||||||
|
|
||||||
// As with non-blocking assignment, push constant assignments
|
|
||||||
// into the initialisation if we can (but only if this is
|
|
||||||
// the first time we assign to this variable).
|
|
||||||
if (proc->get_scope()->initializing()
|
|
||||||
&& ivl_signal_port(sig) == IVL_SIP_NONE
|
|
||||||
&& rhs->constant() && !decl->has_initial()
|
|
||||||
&& !isvar) {
|
&& !isvar) {
|
||||||
|
|
||||||
decl->set_initial(rhs);
|
decl->set_initial(rhs);
|
||||||
|
|
||||||
if (proc->get_scope()->allow_signal_assignment()) {
|
if (blocking && proc->get_scope()->allow_signal_assignment()) {
|
||||||
// This signal may be used e.g. in a loop test so we need
|
// This signal may be used e.g. in a loop test so we need
|
||||||
// to make a variable as well
|
// to make a variable as well
|
||||||
blocking_assign_to(proc, sig);
|
blocking_assign_to(proc, sig);
|
||||||
|
|
@ -214,30 +159,65 @@ static int draw_assign(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);
|
||||||
|
|
||||||
vhdl_assign_stmt *assign = new vhdl_assign_stmt(lval_ref, sig_ref);
|
return new T(lval_ref, sig_ref);
|
||||||
container->add_stmt(assign);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return NULL; // No statement need be emitted
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (proc->get_scope()->allow_signal_assignment()) {
|
if (blocking && proc->get_scope()->allow_signal_assignment()) {
|
||||||
// Remember we need to write the variable back to the
|
// Remember we need to write the variable back to the
|
||||||
// original signal
|
// original signal
|
||||||
blocking_assign_to(proc, sig);
|
blocking_assign_to(proc, sig);
|
||||||
}
|
|
||||||
|
|
||||||
// The signal may have been renamed by the above call
|
// The signal may have been renamed by the above call
|
||||||
const std::string &renamed = get_renamed_signal(sig);
|
signame = get_renamed_signal(sig);
|
||||||
|
}
|
||||||
|
|
||||||
// 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(renamed.c_str(), NULL);
|
vhdl_var_ref *lval_ref = new vhdl_var_ref(signame.c_str(), NULL);
|
||||||
|
|
||||||
vhdl_assign_stmt *assign = new vhdl_assign_stmt(lval_ref, rhs);
|
return new T(lval_ref, rhs);
|
||||||
container->add_stmt(assign);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
error("Only signals as lvals supported at the moment");
|
error("Only signals as lvals supported at the moment");
|
||||||
return 1;
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A non-blocking assignment inside a process. The semantics for
|
||||||
|
* this are essentially the same as VHDL's non-blocking signal
|
||||||
|
* assignment.
|
||||||
|
*/
|
||||||
|
static int draw_nbassign(vhdl_procedural *proc, stmt_container *container,
|
||||||
|
ivl_statement_t stmt, vhdl_expr *after = NULL)
|
||||||
|
{
|
||||||
|
assert(proc->get_scope()->allow_signal_assignment());
|
||||||
|
|
||||||
|
vhdl_nbassign_stmt *a =
|
||||||
|
make_assignment<vhdl_nbassign_stmt>(proc, container, stmt, false);
|
||||||
|
|
||||||
|
if (a != NULL) {
|
||||||
|
// Assignment is a statement and not moved into the initialisation
|
||||||
|
if (after != NULL)
|
||||||
|
a->set_after(after);
|
||||||
|
container->add_stmt(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int draw_assign(vhdl_procedural *proc, stmt_container *container,
|
||||||
|
ivl_statement_t stmt)
|
||||||
|
{
|
||||||
|
vhdl_assign_stmt *a =
|
||||||
|
make_assignment<vhdl_assign_stmt>(proc, container, stmt, true);
|
||||||
|
|
||||||
|
if (a != NULL) {
|
||||||
|
// Assignment is a statement and not moved into the initialisation
|
||||||
|
container->add_stmt(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue