简体   繁体   English

“sc_signal <T> 不能有多个驱动程序“错误,SystemC

[英]“sc_signal<T> cannot have more than one driver” error, SystemC

I tried to test my environment with one of the examples I found on a website for SystemC ( this one ). 我尝试使用我在SystemC网站上找到的一个示例来测试我的环境( 这个 )。 Here is the code of the example: 这是示例的代码:

#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;
}

It's nothing much. 没什么。 The transactor and the DUV are extended classes of the module and the transactor generates the address and sends it to the DUV and the DUV reads the data from memory with that address. 交易者和DUV是模块的扩展类,交易者生成地址并将其发送到DUV,DUV用该地址从内存中读取数据。 Everything looks fine but when I try to run it i get 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 

I can't see where are multiple drivers when only the DUV sends that signal and the transactor only reads the signal. 当只有DUV发送该信号并且交易者只读取信号时,我看不到多个驱动器在哪里。 Even if I delete all of the lines that do anything with this signal it still shows the same error. 即使我删除了对此信号执行任何操作的所有行,它仍然显示相同的错误。

The previous reply is correct: the error is the result of both duv.bus_data and tr.bus_data being sc_inout ports. 前面的回复是正确的:错误是duv.bus_datatr.bus_data都是sc_inout端口的结果。 SystemC flags that as an error because both ports could write to the signal. SystemC将其标记为错误,因为两个端口都可以写入信号。

There are three solutions: 有三种解决方案:

  1. Set the environment variable SC_SIGNAL_WRITE_CHECK to DISABLE before running your simulation. 在运行模拟之前,将环境变量SC_SIGNAL_WRITE_CHECK设置为DISABLE This method is out dated. 这种方法已经过时了。
  2. Set the SC_DEFAULT_WRITER_POLICY preprocesor variable to SC_MANY_WRITERS when compiling your code. 设置SC_DEFAULT_WRITER_POLICY preprocesor变量SC_MANY_WRITERS编译代码时。
  3. Define the writer policy for the signal such that it allows many writers: sc_signal<sc_uint<8>, SC_MANY_WRITERS> bus_data . 为信号定义编写器策略,使其允许许多编写器: sc_signal<sc_uint<8>, SC_MANY_WRITERS> bus_data This is your best option. 这是您的最佳选择。

See the INSTALL file at the root of the Accellera SystemC distribution for more information. 有关详细信息,请参阅Accellera SystemC发行版根目录下的INSTALL文件。

Use this code to proove the above solutions: 使用此代码来证明上述解决方案:

#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;
}

Since both duv.bus_data and tr.bus_data are of type sc_inout, I believe they can both write to the signal, which SystemC may not allow. 由于duv.bus_data和tr.bus_data都是sc_inout类型,我相信它们都可以写入信号,而SystemC可能不允许这样做。 If you comment out one of the lines where you are binding to that signal, such as the line 如果您注释掉绑定到该信号的其中一行,例如行

duv.bus_addr(bus_addr); duv.bus_addr(bus_addr);

the error might go away, which would give a hint that this is the problem. 错误可能会消失,这会暗示这是问题所在。 This discussion appears to be related to your question: 此讨论似乎与您的问题有关:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM