quick.gif

space2.gif

space2.gif

space2.gif

space2.gif

space2.gif

space2.gif

space2.gif

   

space.gif

   

space.gif

  ../images/main/bulllet_4dots_orange.gif 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.

   

space.gif

   

space.gif

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.

   

space.gif

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.

   

space.gif

   

space.gif

  ../images/main/bullet_star_pink.gif Example : Transaction Recording

Below Example is taken from the scv examples directory

   

space.gif


   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<8> addr_t;
   8    typedef sc_uint<8> 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<rw_task_if::addr_t> addr;
  21    scv_extensions<rw_task_if::data_t> 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< bool > clk;
  31    sc_inout< bool > rw;
  32    sc_inout< bool > addr_req;
  33    sc_inout< bool > addr_ack;
  34    sc_inout< sc_uint<8> > bus_addr;
  35    sc_inout< bool > data_rdy;
  36    sc_inout< sc_uint<8> > 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<sc_uint<8>, sc_uint<8> > read_gen;
  56    scv_tr_generator<sc_uint<8>, sc_uint<8> > write_gen;
  57    scv_tr_generator<sc_uint<8> > addr_gen;
  58    scv_tr_generator<sc_uint<8> > 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< rw_task_if > 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<rw_task_if::write_t> 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<int> 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<rw_task_if::addr_t> 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<rw_task_if::write_t> write;
 149    for (int i=0; i<3; i++) {
 150      write->next();
 151      transactor->write( write->get_instance() );
 152      cout << "send data : " << write->data << endl;
 153    }
 154 
 155    scv_smart_ptr<int> data;
 156    scv_bag<int> distribution;
 157    distribution.push(1,40);
 158    distribution.push(2,60);
 159    data->set_mode(distribution);
 160    for (int i=0;i<3; i++) { data->next(); process(data); }
 161 }
 162 
 163 class design : public pipelined_bus_ports {
 164    list< sc_uint<8> > outstandingAddresses;
 165    list< bool > outstandingType;
 166    sc_uint<8>  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<ram_size; ++i) { memory[i] = 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<8> _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< bool > rw;
 239    sc_signal< bool > addr_req;
 240    sc_signal< bool > addr_ack;
 241    sc_signal< sc_uint<8> > bus_addr;
 242    sc_signal< bool > data_rdy;
 243    sc_signal< sc_uint<8> > 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 
You could download file scv_recording.cpp here
   

space.gif

  ../images/main/bullet_star_pink.gif Simulation Output : Transcation Recording
   

space.gif

 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
   

space.gif

   

space.gif

   

space.gif

   

space.gif

space2.gif

space2.gif

space2.gif

space2.gif

space2.gif

  

Copyright 1998-2014

Deepak Kumar Tala - All rights reserved

Do you have any Comment? mail me at:deepak@asic-world.com