signals - "sc_signal<T> cannot have more than one driver" error, SystemC -
i tried test environment 1 of examples found on website systemc (this one). here code of 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 (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; (int i=0; i<3; i++) { addr->next(); rw_task_if::data_t data = transactor->read( addr->get_instance() ); cout << "data address " << *addr << " " << data << endl; } scv_smart_ptr<rw_task_if::write_t> write; (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); (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) { (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 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() << " 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 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 simulation sc_start(1000000, sc_ns); return 0; }
it's nothing much. transactor , duv extended classes of module , transactor generates address , sends duv , duv reads data memory address. looks fine when try run error:
tb transaction recording has started, file = my_db transaction recording closing file: my_db error: (e115) sc_signal<t> cannot have more 1 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 multiple drivers when duv sends signal , transactor reads signal. if delete of lines signal still shows same error.
the previous reply correct: error result of both duv.bus_data
, tr.bus_data
being sc_inout
ports. systemc flags error because both ports could write signal.
there 3 solutions:
- set environment variable
sc_signal_write_check
disable
before running simulation. method out dated. - set
sc_default_writer_policy
preprocesor variablesc_many_writers
when compiling code. - define writer policy signal such allows many writers:
sc_signal<sc_uint<8>, sc_many_writers> bus_data
. best option.
see install
file @ root of accellera systemc distribution more information.
use code proove 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; }
Comments
Post a Comment