gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GarnetSyntheticTraffic.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Georgia Institute of Technology
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * Authors: Tushar Krishna
29  */
30 
32 
33 #include <cmath>
34 #include <iomanip>
35 #include <set>
36 #include <string>
37 #include <vector>
38 
39 #include "base/misc.hh"
40 #include "base/random.hh"
41 #include "base/statistics.hh"
42 #include "debug/GarnetSyntheticTraffic.hh"
43 #include "mem/mem_object.hh"
44 #include "mem/packet.hh"
45 #include "mem/port.hh"
46 #include "mem/request.hh"
47 #include "sim/sim_events.hh"
48 #include "sim/stats.hh"
49 #include "sim/system.hh"
50 
51 using namespace std;
52 
54 
55 bool
57 {
58  tester->completeRequest(pkt);
59  return true;
60 }
61 
62 void
64 {
65  tester->doRetry();
66 }
67 
68 void
70 {
71  if (!cachePort.sendTimingReq(pkt)) {
72  retryPkt = pkt; // RubyPort will retry sending
73  }
74  numPacketsSent++;
75 }
76 
78  : MemObject(p),
79  tickEvent(this),
80  cachePort("GarnetSyntheticTraffic", this),
81  retryPkt(NULL),
82  size(p->memory_size),
83  blockSizeBits(p->block_offset),
84  numDestinations(p->num_dest),
85  simCycles(p->sim_cycles),
86  numPacketsMax(p->num_packets_max),
87  numPacketsSent(0),
88  singleSender(p->single_sender),
89  singleDest(p->single_dest),
90  trafficType(p->traffic_type),
91  injRate(p->inj_rate),
92  injVnet(p->inj_vnet),
93  precision(p->precision),
94  responseLimit(p->response_limit),
95  masterId(p->system->getMasterId(name()))
96 {
97  // set up counters
98  noResponseCycles = 0;
99  schedule(tickEvent, 0);
100 
101  initTrafficType();
102  if (trafficStringToEnum.count(trafficType) == 0) {
103  fatal("Unknown Traffic Type: %s!\n", traffic);
104  }
106 
107  id = TESTER_NETWORK++;
108  DPRINTF(GarnetSyntheticTraffic,"Config Created: Name = %s , and id = %d\n",
109  name(), id);
110 }
111 
113 GarnetSyntheticTraffic::getMasterPort(const std::string &if_name, PortID idx)
114 {
115  if (if_name == "test")
116  return cachePort;
117  else
118  return MemObject::getMasterPort(if_name, idx);
119 }
120 
121 void
123 {
124  numPacketsSent = 0;
125 }
126 
127 
128 void
130 {
131  Request *req = pkt->req;
132 
134  "Completed injection of %s packet for address %x\n",
135  pkt->isWrite() ? "write" : "read\n",
136  req->getPaddr());
137 
138  assert(pkt->isResponse());
139  noResponseCycles = 0;
140  delete req;
141  delete pkt;
142 }
143 
144 
145 void
147 {
148  if (++noResponseCycles >= responseLimit) {
149  fatal("%s deadlocked at cycle %d\n", name(), curTick());
150  }
151 
152  // make new request based on injection rate
153  // (injection rate's range depends on precision)
154  // - generate a random number between 0 and 10^precision
155  // - send pkt if this number is < injRate*(10^precision)
156  bool sendAllowedThisCycle;
157  double injRange = pow((double) 10, (double) precision);
158  unsigned trySending = random_mt.random<unsigned>(0, (int) injRange);
159  if (trySending < injRate*injRange)
160  sendAllowedThisCycle = true;
161  else
162  sendAllowedThisCycle = false;
163 
164  // always generatePkt unless fixedPkts or singleSender is enabled
165  if (sendAllowedThisCycle) {
166  bool senderEnable = true;
167 
169  senderEnable = false;
170 
171  if (singleSender >= 0 && id != singleSender)
172  senderEnable = false;
173 
174  if (senderEnable)
175  generatePkt();
176  }
177 
178  // Schedule wakeup
179  if (curTick() >= simCycles)
180  exitSimLoop("Network Tester completed simCycles");
181  else {
182  if (!tickEvent.scheduled())
184  }
185 }
186 
187 void
189 {
190  int num_destinations = numDestinations;
191  int radix = (int) sqrt(num_destinations);
192  unsigned destination = id;
193  int dest_x = -1;
194  int dest_y = -1;
195  int source = id;
196  int src_x = id%radix;
197  int src_y = id/radix;
198 
199  if (singleDest >= 0)
200  {
201  destination = singleDest;
202  } else if (traffic == UNIFORM_RANDOM_) {
203  destination = random_mt.random<unsigned>(0, num_destinations - 1);
204  } else if (traffic == BIT_COMPLEMENT_) {
205  dest_x = radix - src_x - 1;
206  dest_y = radix - src_y - 1;
207  destination = dest_y*radix + dest_x;
208  } else if (traffic == BIT_REVERSE_) {
209  unsigned int straight = source;
210  unsigned int reverse = source & 1; // LSB
211 
212  int num_bits = (int) log2(num_destinations);
213 
214  for (int i = 1; i < num_bits; i++)
215  {
216  reverse <<= 1;
217  straight >>= 1;
218  reverse |= (straight & 1); // LSB
219  }
220  destination = reverse;
221  } else if (traffic == BIT_ROTATION_) {
222  if (source%2 == 0)
223  destination = source/2;
224  else // (source%2 == 1)
225  destination = ((source/2) + (num_destinations/2));
226  } else if (traffic == NEIGHBOR_) {
227  dest_x = (src_x + 1) % radix;
228  dest_y = src_y;
229  destination = dest_y*radix + dest_x;
230  } else if (traffic == SHUFFLE_) {
231  if (source < num_destinations/2)
232  destination = source*2;
233  else
234  destination = (source*2 - num_destinations + 1);
235  } else if (traffic == TRANSPOSE_) {
236  dest_x = src_y;
237  dest_y = src_x;
238  destination = dest_y*radix + dest_x;
239  } else if (traffic == TORNADO_) {
240  dest_x = (src_x + (int) ceil(radix/2) - 1) % radix;
241  dest_y = src_y;
242  destination = dest_y*radix + dest_x;
243  }
244  else {
245  fatal("Unknown Traffic Type: %s!\n", traffic);
246  }
247 
248  // The source of the packets is a cache.
249  // The destination of the packets is a directory.
250  // The destination bits are embedded in the address after byte-offset.
251  Addr paddr = destination;
252  paddr <<= blockSizeBits;
253  unsigned access_size = 1; // Does not affect Ruby simulation
254 
255  // Modeling different coherence msg types over different msg classes.
256  //
257  // GarnetSyntheticTraffic assumes the Garnet_standalone coherence protocol
258  // which models three message classes/virtual networks.
259  // These are: request, forward, response.
260  // requests and forwards are "control" packets (typically 8 bytes),
261  // while responses are "data" packets (typically 72 bytes).
262  //
263  // Life of a packet from the tester into the network:
264  // (1) This function generatePkt() generates packets of one of the
265  // following 3 types (randomly) : ReadReq, INST_FETCH, WriteReq
266  // (2) mem/ruby/system/RubyPort.cc converts these to RubyRequestType_LD,
267  // RubyRequestType_IFETCH, RubyRequestType_ST respectively
268  // (3) mem/ruby/system/Sequencer.cc sends these to the cache controllers
269  // in the coherence protocol.
270  // (4) Network_test-cache.sm tags RubyRequestType:LD,
271  // RubyRequestType:IFETCH and RubyRequestType:ST as
272  // Request, Forward, and Response events respectively;
273  // and injects them into virtual networks 0, 1 and 2 respectively.
274  // It immediately calls back the sequencer.
275  // (5) The packet traverses the network (simple/garnet) and reaches its
276  // destination (Directory), and network stats are updated.
277  // (6) Network_test-dir.sm simply drops the packet.
278  //
279  MemCmd::Command requestType;
280 
281  Request *req = nullptr;
282  Request::Flags flags;
283 
284  // Inject in specific Vnet
285  // Vnet 0 and 1 are for control packets (1-flit)
286  // Vnet 2 is for data packets (5-flit)
287  int injReqType = injVnet;
288 
289  if (injReqType < 0 || injReqType > 2)
290  {
291  // randomly inject in any vnet
292  injReqType = random_mt.random(0, 2);
293  }
294 
295  if (injReqType == 0) {
296  // generate packet for virtual network 0
297  requestType = MemCmd::ReadReq;
298  req = new Request(paddr, access_size, flags, masterId);
299  } else if (injReqType == 1) {
300  // generate packet for virtual network 1
301  requestType = MemCmd::ReadReq;
302  flags.set(Request::INST_FETCH);
303  req = new Request(0, 0x0, access_size, flags, masterId, 0x0, 0);
304  req->setPaddr(paddr);
305  } else { // if (injReqType == 2)
306  // generate packet for virtual network 2
307  requestType = MemCmd::WriteReq;
308  req = new Request(paddr, access_size, flags, masterId);
309  }
310 
311  req->setContext(id);
312 
313  //No need to do functional simulation
314  //We just do timing simulation of the network
315 
317  "Generated packet with destination %d, embedded in address %x\n",
318  destination, req->getPaddr());
319 
320  PacketPtr pkt = new Packet(req, requestType);
321  pkt->dataDynamic(new uint8_t[req->getSize()]);
322  pkt->senderState = NULL;
323 
324  sendPkt(pkt);
325 }
326 
327 void
329 {
330  trafficStringToEnum["bit_complement"] = BIT_COMPLEMENT_;
331  trafficStringToEnum["bit_reverse"] = BIT_REVERSE_;
332  trafficStringToEnum["bit_rotation"] = BIT_ROTATION_;
333  trafficStringToEnum["neighbor"] = NEIGHBOR_;
334  trafficStringToEnum["shuffle"] = SHUFFLE_;
335  trafficStringToEnum["tornado"] = TORNADO_;
336  trafficStringToEnum["transpose"] = TRANSPOSE_;
337  trafficStringToEnum["uniform_random"] = UNIFORM_RANDOM_;
338 }
339 
340 void
342 {
344  retryPkt = NULL;
345  }
346 }
347 
348 void
350 {
351  cachePort.printAddr(a);
352 }
353 
354 
356 GarnetSyntheticTrafficParams::create()
357 {
358  return new GarnetSyntheticTraffic(this);
359 }
#define DPRINTF(x,...)
Definition: trace.hh:212
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
const std::string & name()
Definition: trace.cc:49
Bitfield< 7 > i
Definition: miscregs.hh:1378
int TESTER_NETWORK
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
Bitfield< 8 > a
Definition: miscregs.hh:1377
MemObject declaration.
bool isWrite() const
Definition: packet.hh:503
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:381
void completeRequest(PacketPtr pkt)
Port Object Declaration.
GarnetSyntheticTraffic(const Params *p)
void setContext(ContextID context_id)
Set up Context numbers.
Definition: request.hh:449
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
Definition: port.cc:180
Declaration of Statistics objects.
std::enable_if< std::is_integral< T >::value, T >::type random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:83
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
system
Definition: isa.cc:226
Tick curTick()
The current simulated tick.
Definition: core.hh:47
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
virtual bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the slave port.
void printAddr(Addr a)
Print state of address in memory system via PrintReq (for debugging).
Addr getPaddr() const
Definition: request.hh:519
#define fatal(...)
Definition: misc.hh:163
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
GarnetSyntheticTrafficParams Params
std::map< std::string, TrafficType > trafficStringToEnum
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
void printAddr(Addr a)
Inject a PrintReq for the given address to print the state of that address throughout the memory syst...
Definition: port.cc:200
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
Definition: sim_events.cc:83
int size()
Definition: pagetable.hh:146
virtual const std::string name() const
Definition: sim_object.hh:117
Declaration of the Packet class.
The request was an instruction fetch.
Definition: request.hh:104
virtual BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a master port with a given name and index.
The MemObject class extends the ClockedObject with accessor functions to get its master and slave por...
Definition: mem_object.hh:60
A BaseMasterPort is a protocol-agnostic master port, responsible only for the structural connection t...
Definition: port.hh:115
Random random_mt
Definition: random.cc:100
void schedule(Event &event, Tick when)
Definition: eventq.hh:728
virtual void recvReqRetry()
Called by the slave port if sendTimingReq was called on this master port (causing recvTimingReq to be...
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:181
Command
List of all commands associated with a packet.
Definition: packet.hh:81
unsigned getSize() const
Definition: request.hh:552
void setPaddr(Addr paddr)
Set just the physical address.
Definition: request.hh:487
Bitfield< 0 > p
void set(Type flags)
Definition: flags.hh:70
virtual BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a master port with a given name and index.
Definition: mem_object.cc:52
bool isResponse() const
Definition: packet.hh:506
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:102

Generated on Fri Jun 9 2017 13:03:44 for gem5 by doxygen 1.8.6