Pertanyaan "Sc_signal tidak dapat memiliki lebih dari satu driver" kesalahan, SystemC


Saya mencoba menguji lingkungan saya dengan salah satu contoh yang saya temukan di situs web untuk SystemC (yang ini). Berikut ini kode contohnya:

#include "scv.h"

const unsigned ram_size = 256;

class rw_task_if : virtual public sc_interface {
public:
   typedef sc_uint<8> addr_t;
   typedef sc_uint<8> data_t;
   struct write_t {
     addr_t addr;
     data_t data;
   };

   virtual data_t read(const addr_t*) = 0;
   virtual void write(const write_t*) = 0;
};

SCV_EXTENSIONS(rw_task_if::write_t) {
public:
   scv_extensions<rw_task_if::addr_t> addr;
   scv_extensions<rw_task_if::data_t> data;
   SCV_EXTENSIONS_CTOR(rw_task_if::write_t) {
     SCV_FIELD(addr);
     SCV_FIELD(data);
   }
};

class pipelined_bus_ports : public sc_module {
public:
   sc_in< bool > clk;
   sc_inout< bool > rw;
   sc_inout< bool > addr_req;
   sc_inout< bool > addr_ack;
   sc_inout< sc_uint<8> > bus_addr;
   sc_inout< bool > data_rdy;
   sc_inout< sc_uint<8> > bus_data;

   SC_CTOR(pipelined_bus_ports)
     : clk("clk"), rw("rw"),
       addr_req("addr_req"),
       addr_ack("addr_ack"), bus_addr("bus_addr"),
       data_rdy("data_rdy"), bus_data("bus_data") {}
};

class rw_pipelined_transactor
   : public rw_task_if,
     public pipelined_bus_ports {

   sc_mutex addr_phase;
   sc_mutex data_phase;

   scv_tr_stream pipelined_stream;
   scv_tr_stream addr_stream;
   scv_tr_stream data_stream;
   scv_tr_generator<sc_uint<8>, sc_uint<8> > read_gen;
   scv_tr_generator<sc_uint<8>, sc_uint<8> > write_gen;
   scv_tr_generator<sc_uint<8> > addr_gen;
   scv_tr_generator<sc_uint<8> > data_gen;

public:
   rw_pipelined_transactor(sc_module_name nm) :  
       pipelined_bus_ports(nm),
       addr_phase("addr_phase"),
       data_phase("data_phase"),
       pipelined_stream("pipelined_stream", "transactor"),
       addr_stream("addr_stream", "transactor"),
       data_stream("data_stream", "transactor"),
       read_gen("read",pipelined_stream,"addr","data"),
       write_gen("write",pipelined_stream,"addr","data"),
       addr_gen("addr",addr_stream,"addr"),
       data_gen("data",data_stream,"data")
   {}
   virtual data_t read(const addr_t* p_addr);
   virtual void write(const write_t * req);
};

rw_task_if::data_t rw_pipelined_transactor::read(const rw_task_if::addr_t* 
addr) {
   addr_phase.lock();
   scv_tr_handle h = read_gen.begin_transaction(*addr);

   scv_tr_handle h1 = addr_gen.begin_transaction(*addr,"addr_phase",h);
   wait(clk->posedge_event());
   bus_addr = *addr;
   addr_req = 1;
   wait(addr_ack->posedge_event());
   wait(clk->negedge_event());
   addr_req = 0;
   wait(addr_ack->negedge_event());
   addr_gen.end_transaction(h1);
   addr_phase.unlock();

   data_phase.lock();
   scv_tr_handle h2 = data_gen.begin_transaction("data_phase",h);
   wait(data_rdy->posedge_event());
   data_t data = bus_data.read();
   wait(data_rdy->negedge_event());
   data_gen.end_transaction(h2);
   read_gen.end_transaction(h,data);
   data_phase.unlock();

   return data;
}

void rw_pipelined_transactor::write(const write_t * req) {
   scv_tr_handle h = write_gen.begin_transaction(req->addr);
   // ...
   write_gen.end_transaction(h,req->data);
}

class test : public sc_module {
public:
   sc_port< rw_task_if > transactor;
   SC_CTOR(test) {
     SC_THREAD(main);
   }
   void main();
};

class write_constraint : virtual public scv_constraint_base {
public:
   scv_smart_ptr<rw_task_if::write_t> write;
   SCV_CONSTRAINT_CTOR(write_constraint) {
     SCV_CONSTRAINT( write->addr() <= ram_size );
     SCV_CONSTRAINT( write->addr() != write->data() );
   }
};

inline void process(scv_smart_ptr<int> data) {}

inline void test::main() {
   // simple sequential tests
   for (int i=0; i<3; i++) {
     rw_task_if::addr_t addr = i;
     rw_task_if::data_t data = transactor->read(&addr);
     cout << "at time " << sc_time_stamp() << ": ";
     cout << "received data : " << data << endl;
   }

   scv_smart_ptr<rw_task_if::addr_t> addr;
   for (int i=0; i<3; i++) {

     addr->next();
     rw_task_if::data_t data = transactor->read( addr->get_instance() );
     cout << "data for address " << *addr << " is " << data << endl;
   }

   scv_smart_ptr<rw_task_if::write_t> write;
   for (int i=0; i<3; i++) {
     write->next();
     transactor->write( write->get_instance() );
     cout << "send data : " << write->data << endl;
   }

   scv_smart_ptr<int> data;
   scv_bag<int> distribution;
   distribution.push(1,40);
   distribution.push(2,60);
   data->set_mode(distribution);
   for (int i=0;i<3; i++) { data->next(); process(data); }
}

class design : public pipelined_bus_ports {
   list< sc_uint<8> > outstandingAddresses;
   list< bool > outstandingType;
   sc_uint<8>  memory[ram_size];

public:
   SC_HAS_PROCESS(design);
   design(sc_module_name nm) : pipelined_bus_ports(nm) {
     for (unsigned i=0; i<ram_size; ++i) { memory[i] = i; }
     SC_THREAD(addr_phase);
     SC_THREAD(data_phase);
   }
   void addr_phase();
   void data_phase();
};

inline void design::addr_phase() {
   while (1) {
     while (addr_req.read() != 1) {
       wait(addr_req->value_changed_event());
     }
     sc_uint<8> _addr = bus_addr.read();
     bool _rw = rw.read();

     int cycle = rand() % 10 + 1;
     while (cycle-- > 0) {
       wait(clk->posedge_event());
     }

     addr_ack = 1;
     wait(clk->posedge_event());
     addr_ack = 0;

     outstandingAddresses.push_back(_addr);
     outstandingType.push_back(_rw);
     cout << "at time " << sc_time_stamp() << ": ";
     cout << "received request for memory address " << _addr << endl;
   }
}

inline void design::data_phase() {
   while (1) {
     while (outstandingAddresses.empty()) {
       wait(clk->posedge_event());
     }
     int cycle = rand() % 10 + 1;
     while (cycle-- > 0) {
       wait(clk->posedge_event());
     }
     if (outstandingType.front() == 0) {
       cout << "reading memory address " << outstandingAddresses.front()
            << " with value " << memory[outstandingAddresses.front()] << endl;
       bus_data = memory[outstandingAddresses.front()];
       data_rdy = 1;
       wait(clk->posedge_event());
       data_rdy = 0;

     } else {
       cout << "not implemented yet" << endl;
     }
     outstandingAddresses.pop_front();
     outstandingType.pop_front();
   }
}

int sc_main (int argc , char *argv[])
{
   scv_startup();

   scv_tr_text_init();
   scv_tr_db db("my_db");
   scv_tr_db::set_default_db(&db);

   // create signals
   sc_clock clk("clk",20,SC_NS,0.5,0,SC_NS,true);
   sc_signal< bool > rw;
   sc_signal< bool > addr_req;
   sc_signal< bool > addr_ack;
   sc_signal< sc_uint<8> > bus_addr;
   sc_signal< bool > data_rdy;
   sc_signal< sc_uint<8> > bus_data;

   // create modules/channels
   test t("t");
   rw_pipelined_transactor tr("tr");
   design duv("duv");

   // connect them up
   t.transactor(tr);

   tr.clk(clk);
   tr.rw(rw);
   tr.addr_req(addr_req);
   tr.addr_ack(addr_ack);
   tr.bus_addr(bus_addr);
   tr.data_rdy(data_rdy);
   tr.bus_data(bus_data);

   duv.clk(clk);
   duv.rw(rw);
   duv.addr_req(addr_req);
   duv.addr_ack(addr_ack);
   duv.bus_addr(bus_addr);
   duv.data_rdy(data_rdy);
   duv.bus_data(bus_data);

   // run the simulation
   sc_start(1000000, SC_NS);

   return 0;
}

Tidak banyak. Transactor dan DUV adalah kelas diperpanjang dari modul dan transactor menghasilkan alamat dan mengirimkannya ke DUV dan DUV membaca data dari memori dengan alamat itu. Semuanya terlihat baik-baik saja tetapi ketika saya mencoba untuk menjalankannya saya mendapatkan error:

TB Transaction Recording has started, file = my_db
Transaction Recording is closing file: my_db

Error: (E115) sc_signal<T> cannot have more than one driver: 
 signal 'signal_5' (sc_signal)
 first driver 'duv.bus_data'  (sc_inout)
 second driver 'tr.bus_data' (sc_inout)
In file: ../../../../src/sysc/communication/sc_signal.cpp:73 

Saya tidak bisa melihat di mana banyak driver ketika hanya DUV mengirim sinyal itu dan transactor hanya membaca sinyal. Bahkan jika saya menghapus semua garis yang melakukan apa pun dengan sinyal ini, itu masih menunjukkan kesalahan yang sama.


5
2017-09-22 13:18


asal


Jawaban:


Jawaban sebelumnya benar: kesalahan adalah hasil dari keduanya duv.bus_data dan tr.bus_data makhluk sc_inout port Bendera SystemC itu sebagai kesalahan karena kedua port bisa tulis ke sinyal.

Ada tiga solusi:

  1. Tetapkan variabel lingkungan SC_SIGNAL_WRITE_CHECK untuk DISABLE sebelum menjalankan simulasi Anda. Metode ini keluar bertanggal.
  2. Mengatur SC_DEFAULT_WRITER_POLICY variabel preprocesor ke SC_MANY_WRITERS saat mengkompilasi kode Anda.
  3. Tentukan kebijakan penulis untuk sinyal sedemikian rupa sehingga memungkinkan banyak penulis: sc_signal<sc_uint<8>, SC_MANY_WRITERS> bus_data. Ini adalah opsi terbaik Anda.

Lihat INSTALL file di root dari distribusi Accellera SystemC untuk informasi lebih lanjut.

Gunakan kode ini untuk mengajukan solusi di atas:

#include <systemc.h>

SC_MODULE(Module) {
    sc_inout< sc_uint<8> > bus_data;
    SC_CTOR(Module): bus_data("bus_data") {}
};

int sc_main (int argc , char *argv[]) {
    // sc_signal< sc_uint<8> > bus_data;
    sc_signal<sc_uint<8>, SC_MANY_WRITERS> bus_data;
    Module m1("m1");
    Module m2("m2");
    m1.bus_data(bus_data);
    m2.bus_data(bus_data);

    sc_start(1, SC_NS);

    return 0;
}

8
2017-09-23 01:18



Karena duv.bus_data dan tr.bus_data adalah tipe sc_inout, saya yakin keduanya dapat menulis ke sinyal, yang mungkin tidak diizinkan oleh SystemC. Jika Anda berkomentar salah satu garis di mana Anda mengikat sinyal itu, seperti garis

duv.bus_addr (bus_addr);

kesalahan mungkin hilang, yang akan memberi petunjuk bahwa ini adalah masalahnya. Diskusi ini tampaknya terkait dengan pertanyaan Anda:

http://forums.accellera.org/topic/2311-inout-port-binding-issue/


1
2017-09-22 15:59