Verification Using SystemC Part XI

In

Transcation Recording
Simulation activity in a testbench is best recorded at the transaction level. Transaction recording is the act of recording timing information and attribute information associated with transactions into the database. This information can be used to visualize simulation activities, debug, perform coverage analysis, and do other tasks.

Transaction recording API contains three major classes, scv_tr_db, scv_tr_stream, and scv_tr_generator. These classes are independent of the actual database format that is used in the simulation.

 

Class

Description

Analogy

Strategy

scv_tr_db

A transaction database containing a collection of transaction streams.

A directory containing multiple files.

Multiple instances represent multiple databases in a single simulation.

scv_tr_stream

A transaction stream containing a collection of related transactions.

A file containing a collection of records.

Each module or channel may use zero, one, or multiple streams to group the transactions that are being generated.

scv_tr_generator

A transaction generator for a specific transaction type, containing information such as the transaction type names, and attribute names.

A form for entering records of a specific record type, asking the user for information about individual fields.

Compile-time type checking, optimization, and preprocessing can be performed with minimal overhead in the creation of individual transactions.

Example : Transaction Recording

Below Example is taken from the scv examples directory

   1 #include "scv.h"

   2

   3 const unsigned ram_size = 256;

   4

   5 class rw_task_if : virtual public sc_interface {

   6 public:

   7    typedef sc_uint addr_t;

   8    typedef sc_uint data_t;

   9    struct write_t {

  10      addr_t addr;

  11      data_t data;

  12    };

  13

  14    virtual data_t read(const addr_t*) = 0;

  15    virtual void write(const write_t*) = 0;

  16 };

  17

  18 SCV_EXTENSIONS(rw_task_if::write_t) {

  19 public:

  20    scv_extensions addr;

  21    scv_extensions data;

  22    SCV_EXTENSIONS_CTOR(rw_task_if::write_t) {

  23      SCV_FIELD(addr);

  24      SCV_FIELD(data);

  25    }

  26 };

  27

  28 class pipelined_bus_ports : public sc_module {

  29 public:

  30    sc_in clk;

  31    sc_inout rw;

  32    sc_inout addr_req;

  33    sc_inout addr_ack;

  34    sc_inout bus_addr;

  35    sc_inout data_rdy;

  36    sc_inout bus_data;

  37

  38    SC_CTOR(pipelined_bus_ports)

  39      : clk("clk"), rw("rw"),

  40        addr_req("addr_req"),

  41        addr_ack("addr_ack"), bus_addr("bus_addr"),

  42        data_rdy("data_rdy"), bus_data("bus_data") {}

  43 };

  44

  45 class rw_pipelined_transactor

  46    : public rw_task_if,

  47      public pipelined_bus_ports {

  48

  49    sc_mutex addr_phase;

  50    sc_mutex data_phase;

  51

  52    scv_tr_stream pipelined_stream;

  53    scv_tr_stream addr_stream;

  54    scv_tr_stream data_stream;

  55    scv_tr_generator read_gen;

  56    scv_tr_generator write_gen;

  57    scv_tr_generator addr_gen;

  58    scv_tr_generator data_gen;

  59

  60 public:

  61    rw_pipelined_transactor(sc_module_name nm) :  

  62        pipelined_bus_ports(nm),

  63        addr_phase("addr_phase"),

  64        data_phase("data_phase"),

  65        pipelined_stream("pipelined_stream", "transactor"),

  66        addr_stream("addr_stream", "transactor"),

  67        data_stream("data_stream", "transactor"),

  68        read_gen("read",pipelined_stream,"addr","data"),

  69        write_gen("write",pipelined_stream,"addr","data"),

  70        addr_gen("addr",addr_stream,"addr"),

  71        data_gen("data",data_stream,"data")

  72    {}

  73    virtual data_t read(const addr_t* p_addr);

  74    virtual void write(const write_t * req);

  75 };

  76

  77 rw_task_if::data_t rw_pipelined_transactor::read(const rw_task_if::addr_t*

  78 addr) {

  79    addr_phase.lock();

  80    scv_tr_handle h = read_gen.begin_transaction(*addr);

  81

  82    scv_tr_handle h1 = addr_gen.begin_transaction(*addr,"addr_phase",h);

  83    wait(clk->posedge_event());

  84    bus_addr = *addr;

  85    addr_req = 1;

  86    wait(addr_ack->posedge_event());

  87    wait(clk->negedge_event());

  88    addr_req = 0;

  89    wait(addr_ack->negedge_event());

  90    addr_gen.end_transaction(h1);

  91    addr_phase.unlock();

  92

  93    data_phase.lock();

  94    scv_tr_handle h2 = data_gen.begin_transaction("data_phase",h);

  95    wait(data_rdy->posedge_event());

  96    data_t data = bus_data.read();

  97    wait(data_rdy->negedge_event());

  98    data_gen.end_transaction(h2);

  99    read_gen.end_transaction(h,data);

 100    data_phase.unlock();

 101

 102    return data;

 103 }

 104

 105 void rw_pipelined_transactor::write(const write_t * req) {

 106    scv_tr_handle h = write_gen.begin_transaction(req->addr);

 107    // ...

 108    write_gen.end_transaction(h,req->data);

 109 }

 110

 111 class test : public sc_module {

 112 public:

 113    sc_port transactor;

 114    SC_CTOR(test) {

 115      SC_THREAD(main);

 116    }

 117    void main();

 118 };

 119

 120 class write_constraint : virtual public scv_constraint_base {

 121 public:

 122    scv_smart_ptr write;

 123    SCV_CONSTRAINT_CTOR(write_constraint) {

 124      SCV_CONSTRAINT( write->addr() <= ram_size );

 125      SCV_CONSTRAINT( write->addr()  ! = write->data() );

 126    }

 127 };

 128

 129 inline void process(scv_smart_ptr data) {}

 130

 131 inline void test::main() {

 132    // simple sequential tests

 133    for (int i=0; i<3; i++) {

 134      rw_task_if::addr_t addr = i;

 135      rw_task_if::data_t data = transactor->read(&addr);

 136      cout << "at time " << sc_time_stamp() << ": ";

 137      cout << "received data : " << data << endl;

 138    }

 139

 140    scv_smart_ptr addr;

 141    for (int i=0; i<3; i++) {

 142

 143      addr->next();

 144      rw_task_if::data_t data = transactor->read( addr->get_instance() );

 145      cout << "data for address " << *addr << " is " << data << endl;

 146    }

 147

 148    scv_smart_ptr write;

 149    for (int i=0; i<3; i++) {

 150      write->next();

 151      transactor->write( write->get_instance() );

 152      cout << "send data : "

 153    }

 154

 155    scv_smart_ptr data;

 156    scv_bag distribution;

 157    distribution.push(1,40);

 158    distribution.push(2,60);

 159    data->set_mode(distribution);

 160    for (int i=0;inext(); process(data); }

 161 }

 162

 163 class design : public pipelined_bus_ports {

 164    list outstandingAddresses;

 165    list outstandingType;

 166    sc_uint  memory[ram_size];

 167

 168 public:

 169    SC_HAS_PROCESS(design);

 170    design(sc_module_name nm) : pipelined_bus_ports(nm) {

 171      for (unsigned i=0; i

 172      SC_THREAD(addr_phase);

 173      SC_THREAD(data_phase);

 174    }

 175    void addr_phase();

 176    void data_phase();

 177 };

 178

 179 inline void design::addr_phase() {

 180    while (1) {

 181      while (addr_req.read()  ! = 1) {

 182        wait(addr_req->value_changed_event());

 183      }

 184      sc_uint _addr = bus_addr.read();

 185      bool _rw = rw.read();

 186

 187      int cycle = rand() % 10 + 1;

 188      while (cycle-- > 0) {

 189        wait(clk->posedge_event());

 190      }

 191

 192      addr_ack = 1;

 193      wait(clk->posedge_event());

 194      addr_ack = 0;

 195

 196      outstandingAddresses.push_back(_addr);

 197      outstandingType.push_back(_rw);

 198      cout << "at time " << sc_time_stamp() << ": ";

 199      cout << "received request for memory address " << _addr << endl;

 200    }

 201 }

 202

 203 inline void design::data_phase() {

 204    while (1) {

 205      while (outstandingAddresses.empty()) {

 206        wait(clk->posedge_event());

 207      }

 208      int cycle = rand() % 10 + 1;

 209      while (cycle-- > 0) {

 210        wait(clk->posedge_event());

 211      }

 212      if (outstandingType.front() == 0) {

 213        cout << "reading memory address " << outstandingAddresses.front()

 214             << " with value " << memory[outstandingAddresses.front()] << endl;

 215        bus_data = memory[outstandingAddresses.front()];

 216        data_rdy = 1;

 217        wait(clk->posedge_event());

 218        data_rdy = 0;

 219

 220      } else {

 221        cout << "not implemented yet" << endl;

 222      }

 223      outstandingAddresses.pop_front();

 224      outstandingType.pop_front();

 225    }

 226 }

 227

 228 int sc_main (int argc , char *argv[])

 229 {

 230    scv_startup();

 231

 232    scv_tr_text_init();

 233    scv_tr_db db("my_db");

 234    scv_tr_db::set_default_db(&db);

 235

 236    // create signals

 237    sc_clock clk("clk",20,0.5,0,true);

 238    sc_signal rw;

 239    sc_signal addr_req;

 240    sc_signal addr_ack;

 241    sc_signal bus_addr;

 242    sc_signal data_rdy;

 243    sc_signal bus_data;

 244

 245    // create modules/channels

 246    test t("t");

 247    rw_pipelined_transactor tr("tr");

 248    design duv("duv");

 249

 250    // connect them up

 251    t.transactor(tr);

 252

 253    tr.clk(clk);

 254    tr.rw(rw);

 255    tr.addr_req(addr_req);

 256    tr.addr_ack(addr_ack);

 257    tr.bus_addr(bus_addr);

 258    tr.data_rdy(data_rdy);

 259    tr.bus_data(bus_data);

 260

 261    duv.clk(clk);

 262    duv.rw(rw);

 263    duv.addr_req(addr_req);

 264    duv.addr_ack(addr_ack);

 265    duv.bus_addr(bus_addr);

 266    duv.data_rdy(data_rdy);

 267    duv.bus_data(bus_data);

 268

 269    // run the simulation

 270    sc_start(1000000);

 271

 272    return 0;

 273 }

 274

Simulation Output : Transcation Recording

 TB Transaction Recording has started, file = my_db

 at time 100 ns: received request for memory address 0

 reading memory address 0 with value 0

 at time 260 ns: received data : 0

 at time 460 ns: received request for memory address 1

 reading memory address 1 with value 1

 at time 600 ns: received data : 1

 at time 720 ns: received request for memory address 2

 reading memory address 2 with value 2

 at time 860 ns: received data : 2

 at time 1040 ns: received request for memory address 52

 reading memory address 52 with value 52

 data for address 52 is 52

 at time 1380 ns: received request for memory address 145

 reading memory address 145 with value 145

 data for address 145 is 145

 at time 1540 ns: received request for memory address 203

 reading memory address 203 with value 203

 data for address 203 is 203

 send data : 9

 send data : 92

 send data : 63

 Transaction Recording is closing file: my_db

  Bạn Có Đam Mê Với Vi Mạch hay Nhúng      -     Bạn Muốn Trau Dồi Thêm Kĩ Năng

Mong Muốn Có Thêm Cơ Hội Trong Công Việc

Và Trở Thành Một Người Có Giá Trị Hơn

Bạn Chưa Biết Phương Thức Nào Nhanh Chóng Để Đạt Được Chúng

Hãy Để Chúng Tôi Hỗ Trợ Cho Bạn. SEMICON  

Lần cập nhật cuối ( Thứ ba, 29 Tháng 3 2022 00:42 )