
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.
| ||||||||||||||||
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