2 * Copyright (c) 2017 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Copyright (c) 2011-2014 Mark D. Hill and David A. Wood
15 * All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include "mem/ruby/slicc_interface/AbstractController.hh"
43 #include "debug/RubyQueue.hh"
44 #include "mem/protocol/MemoryMsg.hh"
45 #include "mem/ruby/network/Network.hh"
46 #include "mem/ruby/system/GPUCoalescer.hh"
47 #include "mem/ruby/system/RubySystem.hh"
48 #include "mem/ruby/system/Sequencer.hh"
49 #include "sim/system.hh"
51 AbstractController::AbstractController(const Params
*p
)
52 : MemObject(p
), Consumer(this), m_version(p
->version
),
53 m_clusterID(p
->cluster_id
),
54 m_masterId(p
->system
->getMasterId(this)), m_is_blocking(false),
55 m_number_of_TBEs(p
->number_of_TBEs
),
56 m_transitions_per_cycle(p
->transitions_per_cycle
),
57 m_buffer_size(p
->buffer_size
), m_recycle_latency(p
->recycle_latency
),
58 memoryPort(csprintf("%s.memory", name()), this, ""),
59 addrRanges(p
->addr_ranges
.begin(), p
->addr_ranges
.end())
62 // Combine the statistics from all controllers
63 // of this particular type.
64 Stats::registerDumpCallback(new StatsCallback(this));
69 AbstractController::init()
71 params()->ruby_system
->registerAbstractController(this);
72 m_delayHistogram
.init(10);
73 uint32_t size
= Network::getNumberOfVirtualNetworks();
74 for (uint32_t i
= 0; i
< size
; i
++) {
75 m_delayVCHistogram
.push_back(new Stats::Histogram());
76 m_delayVCHistogram
[i
]->init(10);
81 AbstractController::resetStats()
83 m_delayHistogram
.reset();
84 uint32_t size
= Network::getNumberOfVirtualNetworks();
85 for (uint32_t i
= 0; i
< size
; i
++) {
86 m_delayVCHistogram
[i
]->reset();
91 AbstractController::regStats()
93 MemObject::regStats();
96 .name(name() + ".fully_busy_cycles")
97 .desc("cycles for which number of transistions == max transitions")
98 .flags(Stats::nozero
);
102 AbstractController::profileMsgDelay(uint32_t virtualNetwork
, Cycles delay
)
104 assert(virtualNetwork
< m_delayVCHistogram
.size());
105 m_delayHistogram
.sample(delay
);
106 m_delayVCHistogram
[virtualNetwork
]->sample(delay
);
110 AbstractController::stallBuffer(MessageBuffer
* buf
, Addr addr
)
112 if (m_waiting_buffers
.count(addr
) == 0) {
113 MsgVecType
* msgVec
= new MsgVecType
;
114 msgVec
->resize(m_in_ports
, NULL
);
115 m_waiting_buffers
[addr
] = msgVec
;
117 DPRINTF(RubyQueue
, "stalling %s port %d addr %#x\n", buf
, m_cur_in_port
,
119 assert(m_in_ports
> m_cur_in_port
);
120 (*(m_waiting_buffers
[addr
]))[m_cur_in_port
] = buf
;
124 AbstractController::wakeUpBuffers(Addr addr
)
126 if (m_waiting_buffers
.count(addr
) > 0) {
128 // Wake up all possible lower rank (i.e. lower priority) buffers that could
129 // be waiting on this message.
131 for (int in_port_rank
= m_cur_in_port
- 1;
134 if ((*(m_waiting_buffers
[addr
]))[in_port_rank
] != NULL
) {
135 (*(m_waiting_buffers
[addr
]))[in_port_rank
]->
136 reanalyzeMessages(addr
, clockEdge());
139 delete m_waiting_buffers
[addr
];
140 m_waiting_buffers
.erase(addr
);
145 AbstractController::wakeUpAllBuffers(Addr addr
)
147 if (m_waiting_buffers
.count(addr
) > 0) {
149 // Wake up all possible lower rank (i.e. lower priority) buffers that could
150 // be waiting on this message.
152 for (int in_port_rank
= m_in_ports
- 1;
155 if ((*(m_waiting_buffers
[addr
]))[in_port_rank
] != NULL
) {
156 (*(m_waiting_buffers
[addr
]))[in_port_rank
]->
157 reanalyzeMessages(addr
, clockEdge());
160 delete m_waiting_buffers
[addr
];
161 m_waiting_buffers
.erase(addr
);
166 AbstractController::wakeUpAllBuffers()
169 // Wake up all possible buffers that could be waiting on any message.
172 std::vector
<MsgVecType
*> wokeUpMsgVecs
;
173 MsgBufType wokeUpMsgBufs
;
175 if (m_waiting_buffers
.size() > 0) {
176 for (WaitingBufType::iterator buf_iter
= m_waiting_buffers
.begin();
177 buf_iter
!= m_waiting_buffers
.end();
179 for (MsgVecType::iterator vec_iter
= buf_iter
->second
->begin();
180 vec_iter
!= buf_iter
->second
->end();
183 // Make sure the MessageBuffer has not already be reanalyzed
185 if (*vec_iter
!= NULL
&&
186 (wokeUpMsgBufs
.count(*vec_iter
) == 0)) {
187 (*vec_iter
)->reanalyzeAllMessages(clockEdge());
188 wokeUpMsgBufs
.insert(*vec_iter
);
191 wokeUpMsgVecs
.push_back(buf_iter
->second
);
194 for (std::vector
<MsgVecType
*>::iterator wb_iter
= wokeUpMsgVecs
.begin();
195 wb_iter
!= wokeUpMsgVecs
.end();
200 m_waiting_buffers
.clear();
205 AbstractController::blockOnQueue(Addr addr
, MessageBuffer
* port
)
207 m_is_blocking
= true;
208 m_block_map
[addr
] = port
;
212 AbstractController::isBlocked(Addr addr
) const
214 return m_is_blocking
&& (m_block_map
.find(addr
) != m_block_map
.end());
218 AbstractController::unblock(Addr addr
)
220 m_block_map
.erase(addr
);
221 if (m_block_map
.size() == 0) {
222 m_is_blocking
= false;
227 AbstractController::isBlocked(Addr addr
)
229 return (m_block_map
.count(addr
) > 0);
233 AbstractController::getMasterPort(const std::string
&if_name
,
240 AbstractController::queueMemoryRead(const MachineID
&id
, Addr addr
,
243 RequestPtr req
= std::make_shared
<Request
>(
244 addr
, RubySystem::getBlockSizeBytes(), 0, m_masterId
);
246 PacketPtr pkt
= Packet::createRead(req
);
247 uint8_t *newData
= new uint8_t[RubySystem::getBlockSizeBytes()];
248 pkt
->dataDynamic(newData
);
250 SenderState
*s
= new SenderState(id
);
251 pkt
->pushSenderState(s
);
253 // Use functional rather than timing accesses during warmup
254 if (RubySystem::getWarmupEnabled()) {
255 memoryPort
.sendFunctional(pkt
);
260 memoryPort
.schedTimingReq(pkt
, clockEdge(latency
));
264 AbstractController::queueMemoryWrite(const MachineID
&id
, Addr addr
,
265 Cycles latency
, const DataBlock
&block
)
267 RequestPtr req
= std::make_shared
<Request
>(
268 addr
, RubySystem::getBlockSizeBytes(), 0, m_masterId
);
270 PacketPtr pkt
= Packet::createWrite(req
);
272 pkt
->setData(block
.getData(0, RubySystem::getBlockSizeBytes()));
274 SenderState
*s
= new SenderState(id
);
275 pkt
->pushSenderState(s
);
277 // Use functional rather than timing accesses during warmup
278 if (RubySystem::getWarmupEnabled()) {
279 memoryPort
.sendFunctional(pkt
);
284 // Create a block and copy data from the block.
285 memoryPort
.schedTimingReq(pkt
, clockEdge(latency
));
289 AbstractController::queueMemoryWritePartial(const MachineID
&id
, Addr addr
,
291 const DataBlock
&block
, int size
)
293 RequestPtr req
= std::make_shared
<Request
>(addr
, size
, 0, m_masterId
);
295 PacketPtr pkt
= Packet::createWrite(req
);
297 pkt
->setData(block
.getData(getOffset(addr
), size
));
299 SenderState
*s
= new SenderState(id
);
300 pkt
->pushSenderState(s
);
302 // Create a block and copy data from the block.
303 memoryPort
.schedTimingReq(pkt
, clockEdge(latency
));
307 AbstractController::functionalMemoryRead(PacketPtr pkt
)
309 memoryPort
.sendFunctional(pkt
);
313 AbstractController::functionalMemoryWrite(PacketPtr pkt
)
315 int num_functional_writes
= 0;
317 // Check the buffer from the controller to the memory.
318 if (memoryPort
.trySatisfyFunctional(pkt
)) {
319 num_functional_writes
++;
322 // Update memory itself.
323 memoryPort
.sendFunctional(pkt
);
324 return num_functional_writes
+ 1;
328 AbstractController::recvTimingResp(PacketPtr pkt
)
330 assert(getMemoryQueue());
331 assert(pkt
->isResponse());
333 std::shared_ptr
<MemoryMsg
> msg
= std::make_shared
<MemoryMsg
>(clockEdge());
334 (*msg
).m_addr
= pkt
->getAddr();
335 (*msg
).m_Sender
= m_machineID
;
337 SenderState
*s
= dynamic_cast<SenderState
*>(pkt
->senderState
);
338 (*msg
).m_OriginalRequestorMachId
= s
->id
;
342 (*msg
).m_Type
= MemoryRequestType_MEMORY_READ
;
343 (*msg
).m_MessageSize
= MessageSizeType_Response_Data
;
345 // Copy data from the packet
346 (*msg
).m_DataBlk
.setData(pkt
->getPtr
<uint8_t>(), 0,
347 RubySystem::getBlockSizeBytes());
348 } else if (pkt
->isWrite()) {
349 (*msg
).m_Type
= MemoryRequestType_MEMORY_WB
;
350 (*msg
).m_MessageSize
= MessageSizeType_Writeback_Control
;
352 panic("Incorrect packet type received from memory controller!");
355 getMemoryQueue()->enqueue(msg
, clockEdge(), cyclesToTicks(Cycles(1)));
360 AbstractController::recvAtomic(PacketPtr pkt
)
362 return ticksToCycles(memoryPort
.sendAtomic(pkt
));
366 AbstractController::mapAddressToMachine(Addr addr
, MachineType mtype
) const
368 NodeID node
= m_net_ptr
->addressToNodeID(addr
, mtype
);
369 MachineID mach
= {mtype
, node
};
374 AbstractController::MemoryPort::recvTimingResp(PacketPtr pkt
)
376 controller
->recvTimingResp(pkt
);
380 AbstractController::MemoryPort::MemoryPort(const std::string
&_name
,
381 AbstractController
*_controller
,
382 const std::string
&_label
)
383 : QueuedMasterPort(_name
, _controller
, reqQueue
, snoopRespQueue
),
384 reqQueue(*_controller
, *this, _label
),
385 snoopRespQueue(*_controller
, *this, false, _label
),
386 controller(_controller
)