Reputation: 15
I am trying to make a circuit which computes the carries for an addition.
In this piece of code, I would like to connect the output port rOut
of the submodule pg
to two output ports (rOut
and carries[0]
) of the parent module, so both get the same value.
template<>
struct Carries<1> : ::sc_core::sc_module {
sc_vector<sc_in<bool>> a, b;
sc_in<bool> rIn;
sc_out<bool> p, g, rOut;
sc_vector<sc_out<bool>> carries;
CarryPropGen pg {"PG"};
SC_CTOR(Carries)
: a {"vectA", 1}, b {"vectB", 1},
rIn {"rIn"},
p {"p"}, g {"g"}, rOut {"rOut"},
carries {"vectCarries", 1} {
pg.a(a[0]);
pg.b(b[0]);
pg.r(rIn);
pg.p(p);
pg.g(g);
pg.rOut(rOut);
pg.rOut(carries[0]);
}
};
However, I get the error (E109) complete binding failed: 2 binds exceeds maximum of 1 allowed: port 'Carries.PG.port_5' (sc_out)
.
I also tried with a signal, with and without the writer policy SC_MANY_WRITER
, as it was suggested by someone on a forum, but it didn't work either.
I am new to SystemC and while I understand the error, I don't really understand why this can't work and how to do it differently.
So, is there a way to bind one submodule's output to multiple sc_out
of the parent module, and how?
Upvotes: 0
Views: 2314
Reputation: 4038
Ports in SystemC are not wires, but smart pointers. Unlike regular C++ pointers, SystemC ports are safe and support hierarchical binding. Similarly to a regular pointers, by default, you can't connect port to 2 channels simultaneously.
While this may be inconvenient for low-level modeling, this allows to use ports with any kind of high-level channels, like FIFOs or TLM channels.
Looks like you need something like broadcast port : when you write to such a port message should be written to all connected channels.
To create a port that can be binded to a multiple channels, use second template parameter N of sc_port :
// ----------------------------------------------------------------------------
// CLASS : sc_port
//
// Generic port class and base class for other port classes.
// N is the maximum number of channels (with interface IF) that can be bound
// to this port. N <= 0 means no maximum.
// ----------------------------------------------------------------------------
template <class IF, int N = 1, sc_port_policy P=SC_ONE_OR_MORE_BOUND>
class sc_port
Lets test it:
#include <systemc.h>
SC_MODULE(test) {
// Create broadcast_port that allows any number of binded channels
sc_port<sc_signal_inout_if<int>, 0> SC_NAMED(broadcast_port);
// create some signals
sc_signal<int> SC_NAMED(a);
sc_signal<int> SC_NAMED(b);
sc_signal<int> SC_NAMED(c);
SC_CTOR(test) {
// bind port to signals
broadcast_port(a);
broadcast_port(b);
broadcast_port(c);
SC_THREAD(test_thread);
}
void test_thread() {
// write 42 to all connected signals
for (size_t ii = 0; ii < broadcast_port.size(); ++ii) {
broadcast_port[ii]->write(42);
}
wait(SC_ZERO_TIME);
// print results
std::cout << a << "\n";
std::cout << b << "\n";
std::cout << c << "\n";
}
};
int sc_main(int, char *[]) {
test SC_NAMED(test_top);
sc_start();
return 0;
}
This is not exactly what we wanted : here we need to iterate over all connected channels each time we need to write something into broadcast port.
Let's create a derived class that will do this automatically:
template <typename T>
class sc_out_broadcast : public sc_port<sc_signal_inout_if<int>, 0>
{
public:
explicit sc_out_broadcast(const char *name_) : sc_port(name_) {}
// write the new value to all connected signals
void write( const T& value_ )
{
for (size_t ii = 0; ii < this->size(); ++ii) {
(*this)[ii]->write(value_);
}
}
};
Here is how we use it in test_thread :
void test_thread() {
broadcast_port.write(42);
wait(SC_ZERO_TIME);
std::cout << a << "\n";
std::cout << b << "\n";
std::cout << c << "\n";
}
Upvotes: 2