gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AbstractController.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2014 Mark D. Hill and David A. Wood
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 
30 
31 #include "debug/RubyQueue.hh"
32 #include "mem/protocol/MemoryMsg.hh"
37 #include "sim/system.hh"
38 
40  : MemObject(p), Consumer(this), m_version(p->version),
41  m_clusterID(p->cluster_id),
42  m_masterId(p->system->getMasterId(name())), m_is_blocking(false),
43  m_number_of_TBEs(p->number_of_TBEs),
44  m_transitions_per_cycle(p->transitions_per_cycle),
45  m_buffer_size(p->buffer_size), m_recycle_latency(p->recycle_latency),
46  memoryPort(csprintf("%s.memory", name()), this, "")
47 {
48  if (m_version == 0) {
49  // Combine the statistics from all controllers
50  // of this particular type.
52  }
53 }
54 
55 void
57 {
58  params()->ruby_system->registerAbstractController(this);
61  for (uint32_t i = 0; i < size; i++) {
62  m_delayVCHistogram.push_back(new Stats::Histogram());
63  m_delayVCHistogram[i]->init(10);
64  }
65 }
66 
67 void
69 {
72  for (uint32_t i = 0; i < size; i++) {
73  m_delayVCHistogram[i]->reset();
74  }
75 }
76 
77 void
79 {
81 
83  .name(name() + ".fully_busy_cycles")
84  .desc("cycles for which number of transistions == max transitions")
86 }
87 
88 void
89 AbstractController::profileMsgDelay(uint32_t virtualNetwork, Cycles delay)
90 {
91  assert(virtualNetwork < m_delayVCHistogram.size());
92  m_delayHistogram.sample(delay);
93  m_delayVCHistogram[virtualNetwork]->sample(delay);
94 }
95 
96 void
98 {
99  if (m_waiting_buffers.count(addr) == 0) {
100  MsgVecType* msgVec = new MsgVecType;
101  msgVec->resize(m_in_ports, NULL);
102  m_waiting_buffers[addr] = msgVec;
103  }
104  DPRINTF(RubyQueue, "stalling %s port %d addr %#x\n", buf, m_cur_in_port,
105  addr);
106  assert(m_in_ports > m_cur_in_port);
107  (*(m_waiting_buffers[addr]))[m_cur_in_port] = buf;
108 }
109 
110 void
112 {
113  if (m_waiting_buffers.count(addr) > 0) {
114  //
115  // Wake up all possible lower rank (i.e. lower priority) buffers that could
116  // be waiting on this message.
117  //
118  for (int in_port_rank = m_cur_in_port - 1;
119  in_port_rank >= 0;
120  in_port_rank--) {
121  if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) {
122  (*(m_waiting_buffers[addr]))[in_port_rank]->
123  reanalyzeMessages(addr, clockEdge());
124  }
125  }
126  delete m_waiting_buffers[addr];
127  m_waiting_buffers.erase(addr);
128  }
129 }
130 
131 void
133 {
134  if (m_waiting_buffers.count(addr) > 0) {
135  //
136  // Wake up all possible lower rank (i.e. lower priority) buffers that could
137  // be waiting on this message.
138  //
139  for (int in_port_rank = m_in_ports - 1;
140  in_port_rank >= 0;
141  in_port_rank--) {
142  if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) {
143  (*(m_waiting_buffers[addr]))[in_port_rank]->
144  reanalyzeMessages(addr, clockEdge());
145  }
146  }
147  delete m_waiting_buffers[addr];
148  m_waiting_buffers.erase(addr);
149  }
150 }
151 
152 void
154 {
155  //
156  // Wake up all possible buffers that could be waiting on any message.
157  //
158 
159  std::vector<MsgVecType*> wokeUpMsgVecs;
160  MsgBufType wokeUpMsgBufs;
161 
162  if (m_waiting_buffers.size() > 0) {
163  for (WaitingBufType::iterator buf_iter = m_waiting_buffers.begin();
164  buf_iter != m_waiting_buffers.end();
165  ++buf_iter) {
166  for (MsgVecType::iterator vec_iter = buf_iter->second->begin();
167  vec_iter != buf_iter->second->end();
168  ++vec_iter) {
169  //
170  // Make sure the MessageBuffer has not already be reanalyzed
171  //
172  if (*vec_iter != NULL &&
173  (wokeUpMsgBufs.count(*vec_iter) == 0)) {
174  (*vec_iter)->reanalyzeAllMessages(clockEdge());
175  wokeUpMsgBufs.insert(*vec_iter);
176  }
177  }
178  wokeUpMsgVecs.push_back(buf_iter->second);
179  }
180 
181  for (std::vector<MsgVecType*>::iterator wb_iter = wokeUpMsgVecs.begin();
182  wb_iter != wokeUpMsgVecs.end();
183  ++wb_iter) {
184  delete (*wb_iter);
185  }
186 
187  m_waiting_buffers.clear();
188  }
189 }
190 
191 void
193 {
194  m_is_blocking = true;
195  m_block_map[addr] = port;
196 }
197 
198 bool
200 {
201  return m_is_blocking && (m_block_map.find(addr) != m_block_map.end());
202 }
203 
204 void
206 {
207  m_block_map.erase(addr);
208  if (m_block_map.size() == 0) {
209  m_is_blocking = false;
210  }
211 }
212 
213 bool
215 {
216  return (m_block_map.count(addr) > 0);
217 }
218 
220 AbstractController::getMasterPort(const std::string &if_name,
221  PortID idx)
222 {
223  return memoryPort;
224 }
225 
226 void
228  Cycles latency)
229 {
230  RequestPtr req = new Request(addr, RubySystem::getBlockSizeBytes(), 0,
231  m_masterId);
232 
233  PacketPtr pkt = Packet::createRead(req);
234  uint8_t *newData = new uint8_t[RubySystem::getBlockSizeBytes()];
235  pkt->dataDynamic(newData);
236 
237  SenderState *s = new SenderState(id);
238  pkt->pushSenderState(s);
239 
240  // Use functional rather than timing accesses during warmup
243  recvTimingResp(pkt);
244  return;
245  }
246 
247  memoryPort.schedTimingReq(pkt, clockEdge(latency));
248 }
249 
250 void
252  Cycles latency, const DataBlock &block)
253 {
254  RequestPtr req = new Request(addr, RubySystem::getBlockSizeBytes(), 0,
255  m_masterId);
256 
257  PacketPtr pkt = Packet::createWrite(req);
258  uint8_t *newData = new uint8_t[RubySystem::getBlockSizeBytes()];
259  pkt->dataDynamic(newData);
260  memcpy(newData, block.getData(0, RubySystem::getBlockSizeBytes()),
262 
263  SenderState *s = new SenderState(id);
264  pkt->pushSenderState(s);
265 
266  // Use functional rather than timing accesses during warmup
269  recvTimingResp(pkt);
270  return;
271  }
272 
273  // Create a block and copy data from the block.
274  memoryPort.schedTimingReq(pkt, clockEdge(latency));
275 }
276 
277 void
279  Cycles latency,
280  const DataBlock &block, int size)
281 {
282  RequestPtr req = new Request(addr, size, 0, m_masterId);
283 
284  PacketPtr pkt = Packet::createWrite(req);
285  uint8_t *newData = new uint8_t[size];
286  pkt->dataDynamic(newData);
287  memcpy(newData, block.getData(getOffset(addr), size), size);
288 
289  SenderState *s = new SenderState(id);
290  pkt->pushSenderState(s);
291 
292  // Create a block and copy data from the block.
293  memoryPort.schedTimingReq(pkt, clockEdge(latency));
294 }
295 
296 void
298 {
300 }
301 
302 int
304 {
305  int num_functional_writes = 0;
306 
307  // Check the buffer from the controller to the memory.
308  if (memoryPort.checkFunctional(pkt)) {
309  num_functional_writes++;
310  }
311 
312  // Update memory itself.
314  return num_functional_writes + 1;
315 }
316 
317 void
319 {
320  assert(getMemoryQueue());
321  assert(pkt->isResponse());
322 
323  std::shared_ptr<MemoryMsg> msg = std::make_shared<MemoryMsg>(clockEdge());
324  (*msg).m_addr = pkt->getAddr();
325  (*msg).m_Sender = m_machineID;
326 
327  SenderState *s = dynamic_cast<SenderState *>(pkt->senderState);
328  (*msg).m_OriginalRequestorMachId = s->id;
329  delete s;
330 
331  if (pkt->isRead()) {
332  (*msg).m_Type = MemoryRequestType_MEMORY_READ;
333  (*msg).m_MessageSize = MessageSizeType_Response_Data;
334 
335  // Copy data from the packet
336  (*msg).m_DataBlk.setData(pkt->getPtr<uint8_t>(), 0,
338  } else if (pkt->isWrite()) {
339  (*msg).m_Type = MemoryRequestType_MEMORY_WB;
340  (*msg).m_MessageSize = MessageSizeType_Writeback_Control;
341  } else {
342  panic("Incorrect packet type received from memory controller!");
343  }
344 
346  delete pkt->req;
347  delete pkt;
348 }
349 
350 bool
352 {
354  return true;
355 }
356 
358  AbstractController *_controller,
359  const std::string &_label)
360  : QueuedMasterPort(_name, _controller, reqQueue, snoopRespQueue),
361  reqQueue(*_controller, *this, _label),
362  snoopRespQueue(*_controller, *this, _label),
363  controller(_controller)
364 {
365 }
RubyTester::SenderState SenderState
Definition: Check.cc:37
#define DPRINTF(x,...)
Definition: trace.hh:212
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the slave port.
virtual MessageBuffer * getMemoryQueue() const =0
WaitingBufType m_waiting_buffers
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
#define panic(...)
Definition: misc.hh:153
void recvTimingResp(PacketPtr pkt)
virtual void regStats()
Register statistics for this object.
Tick cyclesToTicks(Cycles c) const
AbstractController(const Params *p)
static uint32_t getNumberOfVirtualNetworks()
Definition: Network.hh:69
The QueuedMasterPort combines two queues, a request queue and a snoop response queue, that both share the same port.
Definition: qport.hh:107
ip6_addr_t addr
Definition: inet.hh:335
bool isWrite() const
Definition: packet.hh:503
std::map< Addr, MessageBuffer * > m_block_map
Histogram & init(size_type size)
Set the parameters of this histogram.
Definition: statistics.hh:2560
std::set< MessageBuffer * > MsgBufType
void queueMemoryRead(const MachineID &id, Addr addr, Cycles latency)
std::vector< MessageBuffer * > MsgVecType
void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Definition: statistics.hh:311
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:959
bool isBlocked(Addr) const
static bool getWarmupEnabled()
Definition: RubySystem.hh:77
void queueMemoryWrite(const MachineID &id, Addr addr, Cycles latency, const DataBlock &block)
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
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
Bitfield< 4 > s
Definition: miscregs.hh:1738
Callback class used for collating statistics from all the controller of this type.
virtual void resetStats()=0
Reset statistics associated with this object.
bool checkFunctional(PacketPtr pkt)
Check the list of buffered packets against the supplied functional request.
Definition: qport.hh:162
std::vector< Stats::Histogram * > m_delayVCHistogram
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
A simple histogram stat.
Definition: statistics.hh:2551
int functionalMemoryWrite(PacketPtr)
Addr getOffset(Addr addr)
Definition: Address.cc:106
MemObjectParams Params
Definition: mem_object.hh:63
void profileMsgDelay(uint32_t virtualNetwork, Cycles delay)
Profiles the delay associated with messages.
Stats::Scalar m_fully_busy_cycles
Counter for the number of cycles when the transitions carried out were equal to the maximum allowed...
bool isRead() const
Definition: packet.hh:502
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
void reset()
Reset stat value to default.
Definition: statistics.hh:1893
void registerDumpCallback(Callback *cb)
Register a callback that should be called whenever statistics are about to be dumped.
Definition: statistics.cc:535
void blockOnQueue(Addr, MessageBuffer *)
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
Definition: statistics.hh:254
const uint8_t * getData(int offset, int len) const
Definition: DataBlock.cc:95
int size()
Definition: pagetable.hh:146
virtual const std::string name() const
Definition: sim_object.hh:117
MemoryPort(const std::string &_name, AbstractController *_controller, const std::string &_label)
void schedTimingReq(PacketPtr pkt, Tick when)
Schedule the sending of a timing request.
Definition: qport.hh:147
void wakeUpBuffers(Addr addr)
const Params * params() const
SenderState * senderState
This packet's sender state.
Definition: packet.hh:454
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
void queueMemoryWritePartial(const MachineID &id, Addr addr, Cycles latency, const DataBlock &block, int size)
static PacketPtr createRead(const RequestPtr req)
Constructor-like methods that return Packets based on Request objects.
Definition: packet.hh:809
void stallBuffer(MessageBuffer *buf, Addr addr)
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:947
void pushSenderState(SenderState *sender_state)
Push a new sender state to the packet and make the current sender state the predecessor of the new on...
Definition: packet.cc:329
const MasterID m_masterId
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
Definition: statistics.hh:287
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:181
void functionalMemoryRead(PacketPtr)
static PacketPtr createWrite(const RequestPtr req)
Definition: packet.hh:815
const FlagsType nozero
Don't print if this is zero.
Definition: info.hh:57
Bitfield< 0 > p
static uint32_t getBlockSizeBytes()
Definition: RubySystem.hh:74
void enqueue(MsgPtr message, Tick curTime, Tick delta)
void regStats() override
Register statistics for this object.
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1869
Stats::Histogram m_delayHistogram
Histogram for profiling delay for the messages this controller cares for.
void sendFunctional(PacketPtr pkt)
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.cc:173
bool isResponse() const
Definition: packet.hh:506
Addr getAddr() const
Definition: packet.hh:639
BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
A function used to return the port associated with this bus object.

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