From fc29e51e41b3be40c0474abc9dd897d0e2834bac Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 25 Feb 2024 21:48:39 +0000 Subject: [PATCH] Fix synthesis of signal and part select to keep signed/unsigned type. If a signal has been cast to a different type, synthesis needs to reflect the expression type, not the base signal type. If a part select selects the entire signal, unless otherwise cast, the expression is unsigned, regardless of the base signal type. This fixes the additional issues reported in issue #1099. --- expr_synth.cc | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/expr_synth.cc b/expr_synth.cc index ba4696485..668df7482 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -1259,8 +1259,21 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root) // padding.) If this was for an actual part select that at // this point the output vector_width is exactly right, and we // are done. - if (sub->vector_width() == expr_width()) - return sub; + if (sub->vector_width() == expr_width()) { + if (sub->get_signed() == has_sign()) + return sub; + + // If the signal and expression type don't match, we + // need to add an intermediate signal to reflect that. + + auto tmp_vec = new netvector_t(sub->data_type(), sub->vector_width() - 1, 0); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::IMPLICIT, + tmp_vec); + tmp->set_line(*this); + tmp->local_flag(true); + connect(sub->pin(0), tmp->pin(0)); + return tmp; + } netvector_t*net_vec = new netvector_t(expr_type(), expr_width()-1, 0); net_vec->set_signed(has_sign()); @@ -1423,8 +1436,21 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root) return tmp; } - if (word_ == 0) - return net_; + if (word_ == 0) { + if (net_->get_signed() == has_sign()) + return net_; + + // If the signal has been cast to a different type, we + // need to add an intermediate signal to reflect that. + + auto tmp_vec = new netvector_t(net_->data_type(), net_->vector_width() - 1, 0); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::IMPLICIT, + tmp_vec); + tmp->set_line(*this); + tmp->local_flag(true); + connect(net_->pin(0), tmp->pin(0)); + return tmp; + } netvector_t*tmp_vec = new netvector_t(net_->data_type(), net_->vector_width()-1, 0);