diff --git a/tgt-vhdl/display.cc b/tgt-vhdl/display.cc index c599aabc3..e70f1bce5 100644 --- a/tgt-vhdl/display.cc +++ b/tgt-vhdl/display.cc @@ -162,7 +162,7 @@ int draw_stask_display(vhdl_procedural *proc, stmt_container *container, } else { vhdl_expr *base = translate_expr(net); - if (NULL == base) + if (NULL == base) return 1; display_write(container, base); diff --git a/tgt-vhdl/expr.cc b/tgt-vhdl/expr.cc index f64ac4ac6..007abb203 100644 --- a/tgt-vhdl/expr.cc +++ b/tgt-vhdl/expr.cc @@ -149,6 +149,9 @@ static vhdl_expr *translate_unary(ivl_expr_t e) case '~': return new vhdl_unaryop_expr (VHDL_UNARYOP_NOT, operand, new vhdl_type(*operand->get_type())); + case '-': + return new vhdl_unaryop_expr + (VHDL_UNARYOP_NEG, operand, new vhdl_type(*operand->get_type())); case 'N': // NOR return translate_reduction(SF_REDUCE_OR, true, operand); case '|': @@ -352,8 +355,10 @@ static vhdl_expr *translate_select(ivl_expr_t e) { vhdl_var_ref *from = dynamic_cast(translate_expr(ivl_expr_oper1(e))); - if (NULL == from) + if (NULL == from) { + error("Can only select from variable reference"); return NULL; + } ivl_expr_t o2 = ivl_expr_oper2(e); if (o2) { @@ -451,7 +456,7 @@ vhdl_expr *translate_expr(ivl_expr_t e) { assert(e); ivl_expr_type_t type = ivl_expr_type(e); - + switch (type) { case IVL_EX_STRING: return translate_string(e); @@ -481,3 +486,21 @@ vhdl_expr *translate_expr(ivl_expr_t e) return NULL; } } + +/* + * Translate an expression into a time. This is achieved simply + * by multiplying the expression by 1ns. + */ +vhdl_expr *translate_time_expr(ivl_expr_t e) +{ + vhdl_expr *time = translate_expr(e); + if (NULL == time) + return NULL; + + vhdl_type integer(VHDL_TYPE_INTEGER); + time = time->cast(&integer); + + vhdl_expr *ns1 = new vhdl_const_time(1, TIME_UNIT_NS); + return new vhdl_binop_expr(time, VHDL_BINOP_MULT, ns1, + vhdl_type::time()); +} diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index ac1202fff..826def5ad 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -242,9 +242,15 @@ static void declare_logic(vhdl_arch *arch, ivl_scope_t scope) dynamic_cast(nexus_to_expr(arch->get_scope(), output)); if (NULL == lhs) continue; // Not suitable for continuous assignment - + vhdl_expr *rhs = translate_logic(arch->get_scope(), log); - arch->add_stmt(new vhdl_cassign_stmt(lhs, rhs)); + vhdl_cassign_stmt *ass = new vhdl_cassign_stmt(lhs, rhs); + + ivl_expr_t delay = ivl_logic_delay(log, 1); + if (delay) + ass->set_after(translate_time_expr(delay)); + + arch->add_stmt(ass); } } } diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index 87efac0e2..187134854 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -269,19 +269,8 @@ static T *make_assignment(vhdl_procedural *proc, stmt_container *container, container->add_stmt(a); ivl_expr_t i_delay; - if (NULL == after && (i_delay = ivl_stmt_delay_expr(stmt))) { - if ((after = translate_expr(i_delay)) == NULL) - return NULL; - - // Need to make 'after' a time value - // we can do this by multiplying by 1ns - vhdl_type integer(VHDL_TYPE_INTEGER); - after = after->cast(&integer); - - vhdl_expr *ns1 = new vhdl_const_time(1, TIME_UNIT_NS); - after = new vhdl_binop_expr(after, VHDL_BINOP_MULT, ns1, - vhdl_type::time()); - } + if (NULL == after && (i_delay = ivl_stmt_delay_expr(stmt))) + after = translate_time_expr(i_delay); if (after != NULL) a->set_after(after); @@ -349,16 +338,9 @@ static int draw_delay(vhdl_procedural *proc, stmt_container *container, time = new vhdl_const_time(value, TIME_UNIT_NS); } else { - time = translate_expr(ivl_stmt_delay_expr(stmt)); + time = translate_time_expr(ivl_stmt_delay_expr(stmt)); if (NULL == time) return 1; - - vhdl_type integer(VHDL_TYPE_INTEGER); - time = time->cast(&integer); - - vhdl_expr *ns1 = new vhdl_const_time(1, TIME_UNIT_NS); - time = new vhdl_binop_expr(time, VHDL_BINOP_MULT, ns1, - vhdl_type::time()); } // If the sub-statement is an assignment then VHDL lets @@ -577,6 +559,37 @@ int draw_while(vhdl_procedural *proc, stmt_container *container, return 0; } +int draw_forever(vhdl_procedural *proc, stmt_container *container, + ivl_statement_t stmt) +{ + vhdl_loop_stmt *loop = new vhdl_loop_stmt; + container->add_stmt(loop); + + draw_stmt(proc, loop->get_container(), ivl_stmt_sub_stmt(stmt)); + + return 0; +} + +int draw_repeat(vhdl_procedural *proc, stmt_container *container, + ivl_statement_t stmt) +{ + vhdl_expr *times = translate_expr(ivl_stmt_cond_expr(stmt)); + if (NULL == times) + return 1; + + vhdl_type integer(VHDL_TYPE_INTEGER); + times = times->cast(&integer); + + const char *it_name = "Verilog_Repeat"; + vhdl_for_stmt *loop = + new vhdl_for_stmt(it_name, new vhdl_const_int(1), times); + container->add_stmt(loop); + + draw_stmt(proc, loop->get_container(), ivl_stmt_sub_stmt(stmt)); + + return 0; +} + /* * Generate VHDL statements for the given Verilog statement and * add them to the given VHDL process. The container is the @@ -611,6 +624,10 @@ int draw_stmt(vhdl_procedural *proc, stmt_container *container, return draw_case(proc, container, stmt); case IVL_ST_WHILE: return draw_while(proc, container, stmt); + case IVL_ST_FOREVER: + return draw_forever(proc, container, stmt); + case IVL_ST_REPEAT: + return draw_repeat(proc, container, stmt); default: error("No VHDL translation for statement at %s:%d (type = %d)", ivl_stmt_file(stmt), ivl_stmt_lineno(stmt), diff --git a/tgt-vhdl/support.cc b/tgt-vhdl/support.cc index 159618739..4c396407f 100644 --- a/tgt-vhdl/support.cc +++ b/tgt-vhdl/support.cc @@ -86,9 +86,9 @@ void support_function::emit(std::ostream &of, int level) const of << "(B : Boolean) return std_logic is" << nl_string(level) << "begin" << nl_string(indent(level)) << "if B then" << nl_string(indent(indent(level))) - << "return '1'" << nl_string(indent(level)) + << "return '1';" << nl_string(indent(level)) << "else" << nl_string(indent(indent(level))) - << "return '0'" << nl_string(indent(level)) + << "return '0';" << nl_string(indent(level)) << "end if;" << nl_string(level); break; case SF_REDUCE_OR: diff --git a/tgt-vhdl/vhdl_helper.hh b/tgt-vhdl/vhdl_helper.hh index a3f6f0704..d003ff1ef 100644 --- a/tgt-vhdl/vhdl_helper.hh +++ b/tgt-vhdl/vhdl_helper.hh @@ -28,7 +28,8 @@ template void emit_children(std::ostream &of, const std::list &children, - int level, const char *delim="") + int level, const char *delim = "", + bool trailing_newline = true) { // Don't indent if there are no children if (children.size() == 0) @@ -42,7 +43,8 @@ void emit_children(std::ostream &of, if (--sz > 0) of << delim; } - newline(of, level); + if (trailing_newline) + newline(of, level); } } diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index 3cc70853a..aa3b419d8 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -192,9 +192,9 @@ void stmt_container::add_stmt(vhdl_seq_stmt *stmt) stmts_.push_back(stmt); } -void stmt_container::emit(std::ostream &of, int level) const +void stmt_container::emit(std::ostream &of, int level, bool newline) const { - emit_children(of, stmts_, level); + emit_children(of, stmts_, level, "", newline); } vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name) @@ -611,6 +611,12 @@ void vhdl_cassign_stmt::emit(std::ostream &of, int level) const of << "else "; } rhs_->emit(of, level); + + if (after_) { + of << " after "; + after_->emit(of, level); + } + of << ";"; } @@ -657,6 +663,9 @@ void vhdl_unaryop_expr::emit(std::ostream &of, int level) const case VHDL_UNARYOP_NOT: of << "not "; break; + case VHDL_UNARYOP_NEG: + of << "-"; + break; } operand_->emit(of, level); of << ")"; @@ -715,7 +724,7 @@ void vhdl_case_branch::emit(std::ostream &of, int level) const of << "when "; when_->emit(of, level); of << " =>"; - stmts_.emit(of, indent(level)); + stmts_.emit(of, indent(level), false); } vhdl_case_stmt::~vhdl_case_stmt() @@ -731,8 +740,14 @@ void vhdl_case_stmt::emit(std::ostream &of, int level) const newline(of, indent(level)); case_branch_list_t::const_iterator it; - for (it = branches_.begin(); it != branches_.end(); ++it) + int n = branches_.size(); + for (it = branches_.begin(); it != branches_.end(); ++it) { (*it)->emit(of, level); + if (--n > 0) + newline(of, indent(level)); + else + newline(of, level); + } of << "end case;"; } @@ -746,11 +761,33 @@ void vhdl_while_stmt::emit(std::ostream &of, int level) const { of << "while "; test_->emit(of, level); - of << " loop"; + of << " "; + vhdl_loop_stmt::emit(of, level); +} + +void vhdl_loop_stmt::emit(std::ostream &of, int level) const +{ + of << "loop"; stmts_.emit(of, level); of << "end loop;"; } +vhdl_for_stmt::~vhdl_for_stmt() +{ + delete from_; + delete to_; +} + +void vhdl_for_stmt::emit(std::ostream &of, int level) const +{ + of << "for " << lname_ << " in "; + from_->emit(of, level); + of << " to "; + to_->emit(of, level); + of << " "; + vhdl_loop_stmt::emit(of, level); +} + vhdl_function::vhdl_function(const char *name, vhdl_type *ret_type) : vhdl_decl(name, ret_type) { diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index fcf06286a..551e4636f 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -107,6 +107,7 @@ private: enum vhdl_unaryop_t { VHDL_UNARYOP_NOT, + VHDL_UNARYOP_NEG, }; class vhdl_unaryop_expr : public vhdl_expr { @@ -226,14 +227,15 @@ typedef std::list conc_stmt_list_t; class vhdl_cassign_stmt : public vhdl_conc_stmt { public: vhdl_cassign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs) - : lhs_(lhs), rhs_(rhs) {} + : lhs_(lhs), rhs_(rhs), after_(NULL) {} ~vhdl_cassign_stmt(); void emit(std::ostream &of, int level) const; void add_condition(vhdl_expr *value, vhdl_expr *cond); + void set_after(vhdl_expr *a) { after_ = a; } private: vhdl_var_ref *lhs_; - vhdl_expr *rhs_; + vhdl_expr *rhs_, *after_; struct when_part_t { vhdl_expr *value, *cond; @@ -259,7 +261,7 @@ public: ~stmt_container(); void add_stmt(vhdl_seq_stmt *stmt); - void emit(std::ostream &of, int level) const; + void emit(std::ostream &of, int level, bool newline=true) const; bool empty() const { return stmts_.empty(); } private: std::list stmts_; @@ -393,16 +395,38 @@ private: }; -class vhdl_while_stmt : public vhdl_seq_stmt { +class vhdl_loop_stmt : public vhdl_seq_stmt { +public: + virtual ~vhdl_loop_stmt() {} + + stmt_container *get_container() { return &stmts_; } + void emit(std::ostream &of, int level) const; +private: + stmt_container stmts_; +}; + + +class vhdl_while_stmt : public vhdl_loop_stmt { public: vhdl_while_stmt(vhdl_expr *test) : test_(test) {} ~vhdl_while_stmt(); - stmt_container *get_container() { return &stmts_; } void emit(std::ostream &of, int level) const; private: vhdl_expr *test_; - stmt_container stmts_; +}; + + +class vhdl_for_stmt : public vhdl_loop_stmt { +public: + vhdl_for_stmt(const char *lname, vhdl_expr *from, vhdl_expr *to) + : lname_(lname), from_(from), to_(to) {} + ~vhdl_for_stmt(); + + void emit(std::ostream &of, int level) const; +private: + const char *lname_; + vhdl_expr *from_, *to_; }; diff --git a/tgt-vhdl/vhdl_target.h b/tgt-vhdl/vhdl_target.h index 20584eecf..62e784845 100644 --- a/tgt-vhdl/vhdl_target.h +++ b/tgt-vhdl/vhdl_target.h @@ -22,6 +22,7 @@ int draw_stmt(vhdl_procedural *proc, stmt_container *container, int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm); vhdl_expr *translate_expr(ivl_expr_t e); +vhdl_expr *translate_time_expr(ivl_expr_t e); vhdl_var_ref *lpm_output(vhdl_scope *scope, ivl_lpm_t lpm); void remember_entity(vhdl_entity *ent);