diff --git a/tgt-vhdl/logic.cc b/tgt-vhdl/logic.cc index ccf95d9f0..6b3d1f55f 100644 --- a/tgt-vhdl/logic.cc +++ b/tgt-vhdl/logic.cc @@ -120,9 +120,10 @@ static void udp_logic(vhdl_arch *arch, ivl_net_logic_t log) vhdl_signal_decl *tmp_decl = new vhdl_signal_decl(ss.str().c_str(), tmp_type); arch->get_scope()->add_decl(tmp_decl); - + + int nin = ivl_udp_nin(udp); vhdl_expr *tmp_rhs; - if (ivl_udp_nin(udp) == 1) { + if (nin == 1) { tmp_rhs = nexus_to_var_ref(arch->get_scope(), ivl_logic_pin(log, 1)); tmp_rhs = tmp_rhs->cast(tmp_type); } @@ -137,7 +138,29 @@ static void udp_logic(vhdl_arch *arch, ivl_net_logic_t log) vhdl_var_ref *tmp_ref = new vhdl_var_ref(tmp_decl->get_name().c_str(), NULL); arch->add_stmt(new vhdl_cassign_stmt(tmp_ref, tmp_rhs)); + + // Now we can implement the UDP as a `with .. select' statement + // by reading values out of the table + ivl_nexus_t output_nex = ivl_logic_pin(log, 0); + vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), output_nex); + vhdl_with_select_stmt *ws = + new vhdl_with_select_stmt(new vhdl_var_ref(*tmp_ref), out); + int nrows = ivl_udp_rows(udp); + for (int i = 0; i < nrows; i++) { + const char *row = ivl_udp_row(udp, i); + + vhdl_expr *value = new vhdl_const_bit(row[nin]); + vhdl_expr *cond = new vhdl_const_bits(row, nin, false); + + ws->add_condition(value, cond); + } + + ss.str(""); + ss << "UDP " << ivl_udp_name(udp); + ws->set_comment(ss.str()); + + arch->add_stmt(ws); } static vhdl_expr *translate_logic_inputs(vhdl_scope *scope, ivl_net_logic_t log) diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index d07edc7ce..0e4716400 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -892,6 +892,7 @@ void vhdl_param_decl::emit(std::ostream &of, int level) const vhdl_with_select_stmt::~vhdl_with_select_stmt() { delete test_; + delete out_; for (when_list_t::const_iterator it = whens_.begin(); it != whens_.end(); @@ -903,15 +904,21 @@ vhdl_with_select_stmt::~vhdl_with_select_stmt() void vhdl_with_select_stmt::emit(std::ostream &of, int level) const { - emit_comment(of, level); - of << "with "; test_->emit(of, level); of << " select"; + emit_comment(of, level, true); newline(of, indent(level)); + out_->emit(of, level); + of << " <= "; + when_list_t::const_iterator it = whens_.begin(); while (it != whens_.end()) { + (*it).value->emit(of, level); + of << " when "; + (*it).cond->emit(of, level); + if (++it != whens_.end()) { of << ","; newline(of, indent(level)); diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index 6d3bf8fc5..281e5b459 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -288,13 +288,15 @@ private: class vhdl_with_select_stmt : public vhdl_conc_stmt { public: - vhdl_with_select_stmt(vhdl_expr *test) : test_(test) {} + vhdl_with_select_stmt(vhdl_expr *test, vhdl_var_ref *out) + : test_(test), out_(out) {} ~vhdl_with_select_stmt(); void emit(std::ostream &of, int level) const; void add_condition(vhdl_expr *value, vhdl_expr *cond); private: vhdl_expr *test_; + vhdl_var_ref *out_; when_list_t whens_; };