1 #include "base/random.hh"
2 #include "debug/HMCController.hh"
3 #include "mem/hmc_controller.hh"
5 HMCController::HMCController(const HMCControllerParams
* p
) :
7 n_master_ports(p
->port_master_connection_count
),
10 assert(p
->port_slave_connection_count
== 1);
14 HMCControllerParams::create()
16 return new HMCController(this);
19 // Since this module is a load distributor, all its master ports have the same
20 // range so we should keep only one of the ranges and ignore the others
21 void HMCController::recvRangeChange(PortID master_port_id
)
23 if (master_port_id
== 0)
25 gotAllAddrRanges
= true;
26 BaseXBar::recvRangeChange(master_port_id
);
29 gotAddrRanges
[master_port_id
] = true;
32 int HMCController::rotate_counter()
34 int current_value
= rr_counter
;
36 if (rr_counter
== n_master_ports
)
41 bool HMCController::recvTimingReq(PacketPtr pkt
, PortID slave_port_id
)
43 // determine the source port based on the id
44 SlavePort
*src_port
= slavePorts
[slave_port_id
];
46 // we should never see express snoops on a non-coherent component
47 assert(!pkt
->isExpressSnoop());
49 // For now, this is a simple round robin counter, for distribution the
50 // load among the serial links
51 PortID master_port_id
= rotate_counter();
53 // test if the layer should be considered occupied for the current
55 if (!reqLayers
[master_port_id
]->tryTiming(src_port
)) {
56 DPRINTF(HMCController
, "recvTimingReq: src %s %s 0x%x BUSY\n",
57 src_port
->name(), pkt
->cmdString(), pkt
->getAddr());
61 DPRINTF(HMCController
, "recvTimingReq: src %s %s 0x%x\n",
62 src_port
->name(), pkt
->cmdString(), pkt
->getAddr());
64 // store size and command as they might be modified when
65 // forwarding the packet
66 unsigned int pkt_size
= pkt
->hasData() ? pkt
->getSize() : 0;
67 unsigned int pkt_cmd
= pkt
->cmdToIndex();
69 // store the old header delay so we can restore it if needed
70 Tick old_header_delay
= pkt
->headerDelay
;
72 // a request sees the frontend and forward latency
73 Tick xbar_delay
= (frontendLatency
+ forwardLatency
) * clockPeriod();
75 // set the packet header and payload delay
76 calcPacketTiming(pkt
, xbar_delay
);
78 // determine how long to be layer is busy
79 Tick packetFinishTime
= clockEdge(Cycles(1)) + pkt
->payloadDelay
;
81 // before forwarding the packet (and possibly altering it),
82 // remember if we are expecting a response
83 const bool expect_response
= pkt
->needsResponse() &&
84 !pkt
->memInhibitAsserted();
86 // since it is a normal request, attempt to send the packet
87 bool success
= masterPorts
[master_port_id
]->sendTimingReq(pkt
);
90 // inhibited packets should never be forced to retry
91 assert(!pkt
->memInhibitAsserted());
93 DPRINTF(HMCController
, "recvTimingReq: src %s %s 0x%x RETRY\n",
94 src_port
->name(), pkt
->cmdString(), pkt
->getAddr());
96 // restore the header delay as it is additive
97 pkt
->headerDelay
= old_header_delay
;
99 // occupy until the header is sent
100 reqLayers
[master_port_id
]->failedTiming(src_port
,
101 clockEdge(Cycles(1)));
106 // remember where to route the response to
107 if (expect_response
) {
108 assert(routeTo
.find(pkt
->req
) == routeTo
.end());
109 routeTo
[pkt
->req
] = slave_port_id
;
112 reqLayers
[master_port_id
]->succeededTiming(packetFinishTime
);
115 pktCount
[slave_port_id
][master_port_id
]++;
116 pktSize
[slave_port_id
][master_port_id
] += pkt_size
;
117 transDist
[pkt_cmd
]++;