From 7a363625d448e2c55780e15770207667263f8acb Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 25 Apr 2010 14:15:35 -0700 Subject: [PATCH] Add support for bit <-> real conversion for output ports. This patch adds support for converting bit based ports to real signals. You can only do this for single instances. Arrayed instance would create multiple instances driving the same real signal. Any real port can be connected to a bit based signal. The only limitation is that the signal width must be an integer multiple of the instance count since all the real conversions must have the same width. Also add an error message for an arrayed instance with real to real output connections. Again multiple drivers. This patch also adds errors for inout real and bit based inout ports driving a real signal. There is no logical way to deal with the full capabilities of inout and real ports/signals. So for now they are not allowed. (cherry picked from commit e0001de3bad4bd3c0f7ebd9aaea23f11ede4577a) --- elab_sig.cc | 24 +++++++++++---- elaborate.cc | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 6 deletions(-) diff --git a/elab_sig.cc b/elab_sig.cc index bae8cbefe..0a182196b 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -92,10 +92,10 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const && (sig->port_type() == NetNet::PINPUT) && (sig->type() == NetNet::REG)) { - cerr << cur->get_fileline() << ": error: " - << cur->basename() << " in " + cerr << cur->get_fileline() << ": error: Port " + << cur->basename() << " of module " << scope->module_name() - << " declared as input and as a reg type." << endl; + << " is declared as input and as a reg type." << endl; des->errors += 1; } @@ -104,10 +104,22 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const && (sig->port_type() == NetNet::PINOUT) && (sig->type() == NetNet::REG)) { - cerr << cur->get_fileline() << ": error: " - << cur->basename() << " in " + cerr << cur->get_fileline() << ": error: Port " + << cur->basename() << " of module " << scope->module_name() - << " declared as inout and as a reg type." << endl; + << " is declared as inout and as a reg type." << endl; + des->errors += 1; + } + + if (sig && (sig->scope() == scope) + && (scope->type() == NetScope::MODULE) + && (sig->port_type() == NetNet::PINOUT) + && (sig->data_type() == IVL_VT_REAL)) { + + cerr << cur->get_fileline() << ": error: Port " + << cur->basename() << " of module " + << scope->module_name() + << " is declared as a real inout port." << endl; des->errors += 1; } diff --git a/elaborate.cc b/elaborate.cc index 0cacecc7c..8557dd262 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1332,6 +1332,30 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const continue; } + // We do not support automatic bits to real conversion + // for inout ports. + if ((sig->data_type() == IVL_VT_REAL ) && + !prts.empty() && (prts[0]->data_type() != IVL_VT_REAL )) { + cerr << pins[idx]->get_fileline() << ": error: " + << "Cannot automatically connect bit based " + "inout port " << rmod->ports[idx]->name + << " of module " << rmod->mod_name() << " to real " + "signal " << sig->name() << "." << endl; + des->errors += 1; + continue; + } + + // We do not support real inout ports at all. + if (!prts.empty() && (prts[0]->data_type() == IVL_VT_REAL )) { + cerr << pins[idx]->get_fileline() << ": error: " + << "No support for connecting real inout ports (" + "port " + << rmod->ports[idx]->name << " of module " + << rmod->mod_name() << ")." << endl; + des->errors += 1; + continue; + } + } else { @@ -1354,6 +1378,69 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const continue; } + // If we have a real port driving a bit/vector signal + // then we convert the real value using the appropriate + // width cast. Since a real is only one bit the whole + // thing needs to go to each instance when arrayed. + if ((sig->data_type() != IVL_VT_REAL ) && + !prts.empty() && (prts[0]->data_type() == IVL_VT_REAL )) { + if (sig->vector_width() % instance.size() != 0) { + cerr << pins[idx]->get_fileline() << ": error: " + "When automatically converting a real " + "port of an arrayed instance to a bit " + "signal" << endl; + cerr << pins[idx]->get_fileline() << ": : " + "the signal width (" + << sig->vector_width() << ") must be an " + "integer multiple of the instance count (" + << instance.size() << ")." << endl; + des->errors += 1; + continue; + } + prts_vector_width = sig->vector_width(); + for (unsigned idx = 0; idx < prts.size(); idx += 1) { + prts[idx]->port_type(NetNet::NOT_A_PORT); + prts[idx] = cast_to_int(des, scope, prts[idx], + prts_vector_width / + instance.size()); + prts[idx]->port_type(NetNet::POUTPUT); + } + } + + // If we have a bit/vector port driving a single real + // signal then we convert the value to a real. + if ((sig->data_type() == IVL_VT_REAL ) && + !prts.empty() && (prts[0]->data_type() != IVL_VT_REAL )) { + prts_vector_width -= prts[0]->vector_width() - 1; + prts[0]->port_type(NetNet::NOT_A_PORT); + prts[0] = cast_to_real(des, scope, prts[0]); + prts[0]->port_type(NetNet::POUTPUT); + // No support for multiple real drivers. + if (instance.size() != 1) { + cerr << pins[idx]->get_fileline() << ": error: " + << "Cannot connect an arrayed instance of " + "module " << rmod->mod_name() << " to " + "real signal " << sig->name() << "." + << endl; + des->errors += 1; + continue; + } + } + + // A real to real connection is not allowed for arrayed + // instances. You cannot have multiple real drivers. + if ((sig->data_type() == IVL_VT_REAL ) && + !prts.empty() && (prts[0]->data_type() == IVL_VT_REAL ) && + instance.size() != 1) { + cerr << pins[idx]->get_fileline() << ": error: " + << "An arrayed instance of " << rmod->mod_name() + << " cannot have a real port (" + << rmod->ports[idx]->name << ") connected to a " + "real signal (" << sig->name() << ")." << endl; + des->errors += 1; + continue; + } + } ivl_assert(*this, sig);