From 254ccb9ccb4d6721fcb43824d0444fc904e4fc49 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Wed, 18 Jun 2008 13:06:27 +0100 Subject: [PATCH] First passing at blocking assignment --- tgt-vhdl/process.cc | 6 ++-- tgt-vhdl/stmt.cc | 63 ++++++++++++++++++++++++++++++----------- tgt-vhdl/vhdl_syntax.cc | 21 ++++++++++++++ tgt-vhdl/vhdl_syntax.hh | 10 +++++++ tgt-vhdl/vhdl_target.h | 2 +- 5 files changed, 82 insertions(+), 20 deletions(-) diff --git a/tgt-vhdl/process.cc b/tgt-vhdl/process.cc index f400a504b..1342f1e53 100644 --- a/tgt-vhdl/process.cc +++ b/tgt-vhdl/process.cc @@ -24,13 +24,15 @@ #include #include #include +#include /* * TODO: Explanation here. */ -static string_list_t g_assign_vars; +typedef std::set string_set_t; +static string_set_t g_assign_vars; -void blocking_assign_to(std::string var) +void blocking_assign_to(vhdl_process *proc, std::string var) { std::cout << "blocking_assign_to " << var << std::endl; } diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index c7e6adf59..7a8a6075c 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -178,9 +178,13 @@ static int draw_noop(vhdl_process *proc, stmt_container *container, return 0; } -template -static int draw_generic_assign(vhdl_process *proc, stmt_container *container, - ivl_statement_t stmt, vhdl_expr *after = 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_process *proc, stmt_container *container, + ivl_statement_t stmt, vhdl_expr *after = NULL) { int nlvals = ivl_stmt_lvals(stmt); if (nlvals != 1) { @@ -218,7 +222,7 @@ static int draw_generic_assign(vhdl_process *proc, stmt_container *container, // The type here can be null as it is never actually needed vhdl_var_ref *lval_ref = new vhdl_var_ref(signame, NULL); - T *assign = new T(lval_ref, rhs); + vhdl_nbassign_stmt *assign = new vhdl_nbassign_stmt(lval_ref, rhs); if (after != NULL) assign->set_after(after); container->add_stmt(assign); @@ -232,22 +236,47 @@ static int draw_generic_assign(vhdl_process *proc, stmt_container *container, return 0; } -/* - * 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_process *proc, stmt_container *container, - ivl_statement_t stmt, vhdl_expr *after = NULL) -{ - return draw_generic_assign - (proc, container, stmt, after); -} - static int draw_assign(vhdl_process *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); + + blocking_assign_to(proc, signame); + + vhdl_decl *decl = proc->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()); + + // As with non-blocking assignment, push assignments into the + // initialisation if we can + if (proc->is_initial() && ivl_signal_port(sig) == IVL_SIP_NONE) { + 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.c_str(), NULL); + + vhdl_assign_stmt *assign = new vhdl_assign_stmt(lval_ref, rhs); + container->add_stmt(assign); + } + } + else { + error("Only signals as lvals supported at the moment"); + return 1; + } return 0; } diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index 3cfcf6c0c..4a55dbf21 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -202,6 +202,19 @@ void vhdl_process::add_decl(vhdl_decl* decl) decls_.push_back(decl); } +vhdl_decl *vhdl_process::get_decl(const std::string &name) const +{ + decl_list_t::const_iterator it; + for (it = decls_.begin(); it != decls_.end(); ++it) { + if ((*it)->get_name() == name) + return *it; + } + + // Maybe it's a signal rather than a variable? + assert(get_parent()); + return get_parent()->get_decl(name); +} + void vhdl_process::add_sensitivity(const char *name) { sens_.push_back(name); @@ -548,6 +561,14 @@ void vhdl_nbassign_stmt::emit(std::ofstream &of, int level) const of << ";"; } +void vhdl_assign_stmt::emit(std::ofstream &of, int level) const +{ + lhs_->emit(of, level); + of << " := "; + rhs_->emit(of, level); + of << ";"; +} + vhdl_const_bits::vhdl_const_bits(const char *value, int width) : vhdl_expr(vhdl_type::nsigned(width)) { diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index 30399dfd2..07a9efa1f 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -256,6 +256,15 @@ public: }; +class vhdl_assign_stmt : public vhdl_abstract_assign_stmt { +public: + vhdl_assign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs) + : vhdl_abstract_assign_stmt(lhs, rhs) {} + + void emit(std::ofstream &of, int level) const; +}; + + enum vhdl_wait_type_t { VHDL_WAIT_INDEF, // Suspend indefinitely VHDL_WAIT_FOR_NS, // Wait for a constant number of nanoseconds @@ -456,6 +465,7 @@ public: void add_decl(vhdl_decl *decl); void add_sensitivity(const char *name); bool have_declared_var(const std::string &name) const; + vhdl_decl *get_decl(const std::string &name) const; void set_initial(bool i) { initial_ = i; } bool is_initial() const { return initial_; } private: diff --git a/tgt-vhdl/vhdl_target.h b/tgt-vhdl/vhdl_target.h index 0401c33e3..785b01000 100644 --- a/tgt-vhdl/vhdl_target.h +++ b/tgt-vhdl/vhdl_target.h @@ -31,7 +31,7 @@ void rename_signal(ivl_signal_t sig, const std::string &renamed); const vhdl_entity *find_entity_for_signal(ivl_signal_t sig); const std::string &get_renamed_signal(ivl_signal_t sig); -void blocking_assign_to(std::string var); +void blocking_assign_to(vhdl_process *proc, std::string var); #endif /* #ifndef INC_VHDL_TARGET_H */