Actually you try to call an array operator for the port i_i in mux_4_to_1. This does not access the respective bit in the data but the n-th interface of a (potential) multi-port. So you need to do a explcit read to the the sc_bit and then an array access:
// Multiplexer Logic
void mux(){
// Convert bit vector to int
int select_value = s_i.read().to_uint();
auto in_val = i_i.read();
switch(select_value){
case 0 : y_o.write(in_val[0]);
break;
case 1 : y_o.write(in_val[1]);
break;
case 2 : y_o.write(in_val[2]);
break;
case 3 : y_o.write(in_val[3]);
break;
default : y_o.write(false);
}
}
There are several other things to your code:
You should use C++11
You should name your ports and signals. Using C++11 this would look like
sc_out<sc_bv<4>> i_i{"i_i"};
This eases debugging (and tracing).
sc_main should only instantiate the toplevel module/testbench. No structural code and no signals in sc_main. This eases reuse of modules and porting it to other simulators (Synopsys, SiemensEDA, or Cadence). The only other code should be paring command line arguments, setting up tracing/logging, starting simulation and evaluating the results. It also unifies your sc_main across different models.
Maros SC_CTOR and SC_MODULE are discuraged and, as far as I know, will be deprecated and removed from future standards. The do not add substantial functionality.