From 2d22f43ba74d0732b741141672b58ef8f9ff4743 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 3 Jan 2024 21:43:07 -0800 Subject: [PATCH] Use NetReplicate to implement replication for concat Currently replication in a concatenation is implemented by simply concatenating the input signals multiple times by the replication amount. Replace this to use NetReplicate on the concatenation instead. In case there is only one input vector to the concatenation the replication will directly connect to the input vector. This is slightly more efficient in vvp since the replication functor has only one input while the concatenation has multiple inputs connected to the same wire. When an update of the input occurs the replication functor will only receive a single update, while the concatenation will receive multiple update events, one for each replication. Signed-off-by: Lars-Peter Clausen --- expr_synth.cc | 67 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/expr_synth.cc b/expr_synth.cc index fe10f0c28..54142e51c 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -776,23 +776,24 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root) return 0; } - /* Make a NetNet object to carry the output vector. */ - perm_string path = scope->local_symbol(); - netvector_t*osig_vec = new netvector_t(data_type, expr_width()-1, 0); - NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, osig_vec); - osig->set_line(*this); - osig->local_flag(true); + NetNet *osig = nullptr; - NetConcat*cncat = new NetConcat(scope, scope->local_symbol(), - osig->vector_width(), - num_parms * repeat()); - cncat->set_line(*this); - des->add_node(cncat); - connect(cncat->pin(0), osig->pin(0)); + if (num_parms != 1) { + /* Make a NetNet object to carry the output vector. */ + auto osig_vec = new netvector_t(data_type, expr_width() / repeat() - 1, 0); + osig = new NetNet(scope, scope->local_symbol(), NetNet::IMPLICIT, + osig_vec); + osig->set_line(*this); + osig->local_flag(true); - unsigned count_input_width = 0; - unsigned cur_pin = 1; - for (unsigned rpt = 0; rpt < repeat(); rpt += 1) { + auto cncat = new NetConcat(scope, scope->local_symbol(), + osig->vector_width(), num_parms); + cncat->set_line(*this); + des->add_node(cncat); + connect(cncat->pin(0), osig->pin(0)); + + unsigned count_input_width = 0; + unsigned cur_pin = 1; for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) { unsigned concat_item = parms_.size()-idx-1; if (tmp[concat_item] == 0) continue; @@ -800,14 +801,38 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root) cur_pin += 1; count_input_width += tmp[concat_item]->vector_width(); } + + if (count_input_width != osig->vector_width()) { + cerr << get_fileline() << ": internal error: " + << "NetEConcat input width = " << count_input_width + << ", expecting " << osig->vector_width() + << endl; + des->errors += 1; + } + } else { + /* There is exactly one input signal */ + for (unsigned idx = 0; idx < parms_.size(); idx++) { + if (tmp[idx]) { + osig = tmp[idx]; + break; + } + } + ivl_assert(*this, osig); } - if (count_input_width != osig->vector_width()) { - cerr << get_fileline() << ": internal error: " - << "NetEConcat input width = " << count_input_width - << ", expecting " << osig->vector_width() - << " (repeat=" << repeat() << ")" << endl; - des->errors += 1; + if (repeat() != 1) { + auto rep = new NetReplicate(scope, scope->local_symbol(), + expr_width(), repeat()); + rep->set_line(*this); + des->add_node(rep); + connect(rep->pin(1), osig->pin(0)); + + auto osig_vec = new netvector_t(data_type, expr_width() - 1, 0); + osig = new NetNet(scope, scope->local_symbol(), NetNet::IMPLICIT, + osig_vec); + osig->set_line(*this); + osig->local_flag(true); + connect(rep->pin(0), osig->pin(0)); } delete[]tmp;