⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bus.cc

📁 M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作为模拟平台
💻 CC
📖 第 1 页 / 共 2 页
字号:
                return defaultId;            }        }        if (responderSet) {            panic("Unable to find destination for addr (user set default "                  "responder): %#llx", addr);        } else {            DPRINTF(Bus, "Unable to find destination for addr: %#llx, will use "                    "default port", addr);            return defaultId;        }    }    return dest_id;}/** Function called by the port when the bus is receiving a Atomic * transaction.*/TickBus::recvAtomic(PacketPtr pkt){    DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",            pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());    assert(pkt->getDest() == Packet::Broadcast);    assert(pkt->isRequest());    // Variables for recording original command and snoop response (if    // any)... if a snooper respondes, we will need to restore    // original command so that additional snoops can take place    // properly    MemCmd orig_cmd = pkt->cmd;    MemCmd snoop_response_cmd = MemCmd::InvalidCmd;    Tick snoop_response_latency = 0;    int orig_src = pkt->getSrc();    int target_port_id = findPort(pkt->getAddr());    BusPort *target_port;    if (target_port_id == defaultId)        target_port = defaultPort;    else {      target_port = checkBusCache(target_port_id);      if (target_port == NULL) {          target_port = interfaces[target_port_id];          updateBusCache(target_port_id, target_port);      }    }    SnoopIter s_end = snoopPorts.end();    for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {        BusPort *p = *s_iter;        // same port should not have both target addresses and snooping        assert(p != target_port);        if (p->getId() != pkt->getSrc()) {            Tick latency = p->sendAtomic(pkt);            if (pkt->isResponse()) {                // response from snoop agent                assert(pkt->cmd != orig_cmd);                assert(pkt->memInhibitAsserted());                // should only happen once                assert(snoop_response_cmd == MemCmd::InvalidCmd);                // save response state                snoop_response_cmd = pkt->cmd;                snoop_response_latency = latency;                // restore original packet state for remaining snoopers                pkt->cmd = orig_cmd;                pkt->setSrc(orig_src);                pkt->setDest(Packet::Broadcast);            }        }    }    Tick response_latency = 0;    // we can get requests sent up from the memory side of the bus for    // snooping... don't send them back down!    if (target_port_id != pkt->getSrc()) {        response_latency = target_port->sendAtomic(pkt);    }    // if we got a response from a snooper, restore it here    if (snoop_response_cmd != MemCmd::InvalidCmd) {        // no one else should have responded        assert(!pkt->isResponse());        assert(pkt->cmd == orig_cmd);        pkt->cmd = snoop_response_cmd;        response_latency = snoop_response_latency;    }    // why do we have this packet field and the return value both???    pkt->finishTime = curTick + response_latency;    return response_latency;}/** Function called by the port when the bus is receiving a Functional * transaction.*/voidBus::recvFunctional(PacketPtr pkt){    if (!pkt->isPrint()) {        // don't do DPRINTFs on PrintReq as it clutters up the output        DPRINTF(Bus,                "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n",                pkt->getSrc(), pkt->getDest(), pkt->getAddr(),                pkt->cmdString());    }    assert(pkt->getDest() == Packet::Broadcast);    int port_id = findPort(pkt->getAddr());    Port *port = (port_id == defaultId) ? defaultPort : interfaces[port_id];    // The packet may be changed by another bus on snoops, restore the    // id after each    int src_id = pkt->getSrc();    assert(pkt->isRequest()); // hasn't already been satisfied    SnoopIter s_end = snoopPorts.end();    for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {        BusPort *p = *s_iter;        if (p != port && p->getId() != src_id) {            p->sendFunctional(pkt);        }        if (pkt->isResponse()) {            break;        }        pkt->setSrc(src_id);    }    // If the snooping hasn't found what we were looking for, keep going.    if (!pkt->isResponse() && port_id != pkt->getSrc()) {        port->sendFunctional(pkt);    }}/** Function called by the port when the bus is receiving a status change.*/voidBus::recvStatusChange(Port::Status status, int id){    AddrRangeList ranges;    bool snoops;    AddrRangeIter iter;    if (inRecvStatusChange.count(id))        return;    inRecvStatusChange.insert(id);    assert(status == Port::RangeChange &&           "The other statuses need to be implemented.");    DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);    clearPortCache();    if (id == defaultId) {        defaultRange.clear();        // Only try to update these ranges if the user set a default responder.        if (responderSet) {            defaultPort->getPeerAddressRanges(ranges, snoops);            assert(snoops == false);            for(iter = ranges.begin(); iter != ranges.end(); iter++) {                defaultRange.push_back(*iter);                DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n",                        iter->start, iter->end);            }        }    } else {        assert((id < maxId && id >= 0) || id == defaultId);        BusPort *port = interfaces[id];        // Clean out any previously existent ids        for (PortIter portIter = portMap.begin();             portIter != portMap.end(); ) {            if (portIter->second == id)                portMap.erase(portIter++);            else                portIter++;        }        for (SnoopIter s_iter = snoopPorts.begin();             s_iter != snoopPorts.end(); ) {            if ((*s_iter)->getId() == id)                s_iter = snoopPorts.erase(s_iter);            else                s_iter++;        }        port->getPeerAddressRanges(ranges, snoops);        if (snoops) {            DPRINTF(BusAddrRanges, "Adding id %d to snoop list\n", id);            snoopPorts.push_back(port);        }        for (iter = ranges.begin(); iter != ranges.end(); iter++) {            DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n",                    iter->start, iter->end, id);            if (portMap.insert(*iter, id) == portMap.end())                panic("Two devices with same range\n");        }    }    DPRINTF(MMU, "port list has %d entries\n", portMap.size());    // tell all our peers that our address range has changed.    // Don't tell the device that caused this change, it already knows    m5::hash_map<short,BusPort*>::iterator intIter;    for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)        if (intIter->first != id && intIter->first != funcPortId)            intIter->second->sendStatusChange(Port::RangeChange);    if (id != defaultId && defaultPort)        defaultPort->sendStatusChange(Port::RangeChange);    inRecvStatusChange.erase(id);}voidBus::addressRanges(AddrRangeList &resp, bool &snoop, int id){    resp.clear();    snoop = false;    DPRINTF(BusAddrRanges, "received address range request, returning:\n");    for (AddrRangeIter dflt_iter = defaultRange.begin();         dflt_iter != defaultRange.end(); dflt_iter++) {        resp.push_back(*dflt_iter);        DPRINTF(BusAddrRanges, "  -- Dflt: %#llx : %#llx\n",dflt_iter->start,                dflt_iter->end);    }    for (PortIter portIter = portMap.begin();         portIter != portMap.end(); portIter++) {        bool subset = false;        for (AddrRangeIter dflt_iter = defaultRange.begin();             dflt_iter != defaultRange.end(); dflt_iter++) {            if ((portIter->first.start < dflt_iter->start &&                portIter->first.end >= dflt_iter->start) ||               (portIter->first.start < dflt_iter->end &&                portIter->first.end >= dflt_iter->end))                fatal("Devices can not set ranges that itersect the default set\                        but are not a subset of the default set.\n");            if (portIter->first.start >= dflt_iter->start &&                portIter->first.end <= dflt_iter->end) {                subset = true;                DPRINTF(BusAddrRanges, "  -- %#llx : %#llx is a SUBSET\n",                    portIter->first.start, portIter->first.end);            }        }        if (portIter->second != id && !subset) {            resp.push_back(portIter->first);            DPRINTF(BusAddrRanges, "  -- %#llx : %#llx\n",                    portIter->first.start, portIter->first.end);        }    }    for (SnoopIter s_iter = snoopPorts.begin(); s_iter != snoopPorts.end();         s_iter++) {        if ((*s_iter)->getId() != id) {            snoop = true;            break;        }    }}intBus::findBlockSize(int id){    if (cachedBlockSizeValid)        return cachedBlockSize;    int max_bs = -1;    PortIter p_end = portMap.end();    for (PortIter p_iter = portMap.begin(); p_iter != p_end; p_iter++) {        int tmp_bs = interfaces[p_iter->second]->peerBlockSize();        if (tmp_bs > max_bs)            max_bs = tmp_bs;    }    SnoopIter s_end = snoopPorts.end();    for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {        int tmp_bs = (*s_iter)->peerBlockSize();        if (tmp_bs > max_bs)            max_bs = tmp_bs;    }    if (max_bs <= 0)        max_bs = defaultBlockSize;    if (max_bs != 64)        warn_once("Blocksize found to not be 64... hmm... probably not.\n");    cachedBlockSize = max_bs;    cachedBlockSizeValid = true;    return max_bs;}unsigned intBus::drain(Event * de){    //We should check that we're not "doing" anything, and that noone is    //waiting. We might be idle but have someone waiting if the device we    //contacted for a retry didn't actually retry.    if (retryList.size() || (curTick < tickNextIdle && busIdle.scheduled())) {        drainEvent = de;        return 1;    }    return 0;}voidBus::startup(){    if (tickNextIdle < curTick)        tickNextIdle = (curTick / clock) * clock + clock;}Bus *BusParams::create(){    return new Bus(this);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -