&#34; sc_signal <t>不能有多个驱动程序&#34;错误,SystemC

时间:2016-09-22 13:18:44

标签: signals systemc

我尝试使用我在SystemC(this one)网站上找到的一个示例来测试我的环境。以下是示例的代码:

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

没什么。交易者和DUV是模块的扩展类,交易者生成地址并将其发送到DUV,DUV用该地址从内存中读取数据。一切看起来都很好但是当我尝试运行它时我得到错误:

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 

当只有DUV发送该信号并且交易者只读取信号时,我无法看到多个驱动器在哪里。即使我删除了对此信号执行任何操作的所有行,它仍然显示相同的错误。

2 个答案:

答案 0 :(得分:8)

之前的回复是正确的:错误是duv.bus_datatr.bus_data sc_inout端口的结果。 SystemC将其标记为错误,因为两个端口都可以写入信号。

有三种解决方案:

  1. 在运行模拟之前将环境变量SC_SIGNAL_WRITE_CHECK设置为DISABLE。这种方法已经过时了。
  2. 编译代码时将SC_DEFAULT_WRITER_POLICY预处理器变量设置为SC_MANY_WRITERS
  3. 为信号定义编写器策略,使其允许许多编写者:sc_signal<sc_uint<8>, SC_MANY_WRITERS> bus_data。这是您最好的选择。
  4. 有关详细信息,请参阅Accellera SystemC发行版根目录中的INSTALL文件。

    使用此代码来证明上述解决方案:

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

答案 1 :(得分:1)

由于duv.bus_data和tr.bus_data都是sc_inout类型,我相信它们都可以写入信号,SystemC可能不允许。如果您注释掉绑定到该信号的其中一行,例如行

duv.bus_addr(bus_addr);

错误可能会消失,这会暗示这是问题所在。此讨论似乎与您的问题有关:

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