X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fdev%2Fetherlink.cc;h=1c88a31dda477a2a91ace431d0fc142694260146;hb=53001e6e09d31063784c408f0f35caad45afeef1;hp=5d30e17440f124c4bc6165e96ab84273fea3fb19;hpb=ea7bdf9f60c404761dfc568d5291c75747a2dd88;p=gem5.git diff --git a/src/dev/etherlink.cc b/src/dev/etherlink.cc index 5d30e1744..1c88a31dd 100644 --- a/src/dev/etherlink.cc +++ b/src/dev/etherlink.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2015 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -40,33 +52,32 @@ #include "base/random.hh" #include "base/trace.hh" +#include "debug/Ethernet.hh" +#include "debug/EthernetData.hh" #include "dev/etherdump.hh" #include "dev/etherint.hh" #include "dev/etherlink.hh" #include "dev/etherpkt.hh" -#include "sim/builder.hh" +#include "params/EtherLink.hh" +#include "sim/core.hh" #include "sim/serialize.hh" #include "sim/system.hh" -#include "sim/core.hh" using namespace std; -EtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1, - double rate, Tick delay, Tick delayVar, EtherDump *dump) - : SimObject(name) +EtherLink::EtherLink(const Params *p) + : EtherObject(p) { - link[0] = new Link(name + ".link0", this, 0, rate, delay, delayVar, dump); - link[1] = new Link(name + ".link1", this, 1, rate, delay, delayVar, dump); + link[0] = new Link(name() + ".link0", this, 0, p->speed, + p->delay, p->delay_var, p->dump); + link[1] = new Link(name() + ".link1", this, 1, p->speed, + p->delay, p->delay_var, p->dump); - interface[0] = new Interface(name + ".int0", link[0], link[1]); - interface[1] = new Interface(name + ".int1", link[1], link[0]); - - interface[0]->setPeer(peer0); - peer0->setPeer(interface[0]); - interface[1]->setPeer(peer1); - peer1->setPeer(interface[1]); + interface[0] = new Interface(name() + ".int0", link[0], link[1]); + interface[1] = new Interface(name() + ".int1", link[1], link[0]); } + EtherLink::~EtherLink() { delete link[0]; @@ -76,6 +87,23 @@ EtherLink::~EtherLink() delete interface[1]; } +EtherInt* +EtherLink::getEthPort(const std::string &if_name, int idx) +{ + Interface *i; + if (if_name == "int0") + i = interface[0]; + else if (if_name == "int1") + i = interface[1]; + else + return NULL; + if (i->getPeer()) + panic("interface already connected to\n"); + + return i; +} + + EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) : EtherInt(name), txlink(tx) { @@ -87,21 +115,21 @@ EtherLink::Link::Link(const string &name, EtherLink *p, int num, double rate, Tick delay, Tick delay_var, EtherDump *d) : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d), - doneEvent(this) + doneEvent(this), txQueueEvent(this) { } void -EtherLink::serialize(ostream &os) +EtherLink::serialize(CheckpointOut &cp) const { - link[0]->serialize("link0", os); - link[1]->serialize("link1", os); + link[0]->serialize("link0", cp); + link[1]->serialize("link1", cp); } void -EtherLink::unserialize(Checkpoint *cp, const string §ion) +EtherLink::unserialize(CheckpointIn &cp) { - link[0]->unserialize("link0", cp, section); - link[1]->unserialize("link1", cp, section); + link[0]->unserialize("link0", cp); + link[1]->unserialize("link1", cp); } void @@ -112,25 +140,6 @@ EtherLink::Link::txComplete(EthPacketPtr packet) rxint->sendPacket(packet); } -class LinkDelayEvent : public Event -{ - protected: - EtherLink::Link *link; - EthPacketPtr packet; - - public: - // non-scheduling version for createForUnserialize() - LinkDelayEvent(); - LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when); - - void process(); - - virtual void serialize(ostream &os); - virtual void unserialize(Checkpoint *cp, const string §ion); - static Serializable *createForUnserialize(Checkpoint *cp, - const string §ion); -}; - void EtherLink::Link::txDone() { @@ -139,8 +148,11 @@ EtherLink::Link::txDone() if (linkDelay > 0) { DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); - new LinkDelayEvent(this, packet, curTick + linkDelay); + txQueue.emplace_back(std::make_pair(curTick() + linkDelay, packet)); + if (!txQueueEvent.scheduled()) + parent->schedule(txQueueEvent, txQueue.front().first); } else { + assert(txQueue.empty()); txComplete(packet); } @@ -150,6 +162,23 @@ EtherLink::Link::txDone() txint->sendDone(); } +void +EtherLink::Link::processTxQueue() +{ + auto cur(txQueue.front()); + txQueue.pop_front(); + + // Schedule a new event to process the next packet in the queue. + if (!txQueue.empty()) { + auto next(txQueue.front()); + assert(next.first > curTick()); + parent->schedule(txQueueEvent, next.first); + } + + assert(cur.first == curTick()); + txComplete(cur.second); +} + bool EtherLink::Link::transmit(EthPacketPtr pkt) { @@ -163,141 +192,88 @@ EtherLink::Link::transmit(EthPacketPtr pkt) packet = pkt; Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0); - if (delayVar != 0) { - Random var; - delay += var.uniform(0, delayVar); - } + if (delayVar != 0) + delay += random_mt.random(0, delayVar); + DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", delay, ticksPerByte); - doneEvent.schedule(curTick + delay); + parent->schedule(doneEvent, curTick() + delay); return true; } void -EtherLink::Link::serialize(const string &base, ostream &os) +EtherLink::Link::serialize(const string &base, CheckpointOut &cp) const { - bool packet_exists = packet; - paramOut(os, base + ".packet_exists", packet_exists); + bool packet_exists = packet != nullptr; + paramOut(cp, base + ".packet_exists", packet_exists); if (packet_exists) - packet->serialize(base + ".packet", os); + packet->serialize(base + ".packet", cp); bool event_scheduled = doneEvent.scheduled(); - paramOut(os, base + ".event_scheduled", event_scheduled); + paramOut(cp, base + ".event_scheduled", event_scheduled); if (event_scheduled) { Tick event_time = doneEvent.when(); - paramOut(os, base + ".event_time", event_time); + paramOut(cp, base + ".event_time", event_time); } + const size_t tx_queue_size(txQueue.size()); + paramOut(cp, base + ".tx_queue_size", tx_queue_size); + unsigned idx(0); + for (const auto &pe : txQueue) { + paramOut(cp, csprintf("%s.txQueue[%i].tick", base, idx), pe.first); + pe.second->serialize(csprintf("%s.txQueue[%i].packet", base, idx), cp); + + ++idx; + } } void -EtherLink::Link::unserialize(const string &base, Checkpoint *cp, - const string §ion) +EtherLink::Link::unserialize(const string &base, CheckpointIn &cp) { bool packet_exists; - paramIn(cp, section, base + ".packet_exists", packet_exists); + paramIn(cp, base + ".packet_exists", packet_exists); if (packet_exists) { - packet = new EthPacketData(16384); - packet->unserialize(base + ".packet", cp, section); + packet = make_shared(16384); + packet->unserialize(base + ".packet", cp); } bool event_scheduled; - paramIn(cp, section, base + ".event_scheduled", event_scheduled); + paramIn(cp, base + ".event_scheduled", event_scheduled); if (event_scheduled) { Tick event_time; - paramIn(cp, section, base + ".event_time", event_time); - doneEvent.schedule(event_time); + paramIn(cp, base + ".event_time", event_time); + parent->schedule(doneEvent, event_time); } -} -LinkDelayEvent::LinkDelayEvent() - : Event(&mainEventQueue), link(NULL) -{ - setFlags(AutoSerialize); - setFlags(AutoDelete); -} + size_t tx_queue_size; + if (optParamIn(cp, base + ".tx_queue_size", tx_queue_size)) { + for (size_t idx = 0; idx < tx_queue_size; ++idx) { + Tick tick; + EthPacketPtr delayed_packet = make_shared(16384); -LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p, Tick when) - : Event(&mainEventQueue), link(l), packet(p) -{ - setFlags(AutoSerialize); - setFlags(AutoDelete); - schedule(when); -} + paramIn(cp, csprintf("%s.txQueue[%i].tick", base, idx), tick); + delayed_packet->unserialize( + csprintf("%s.txQueue[%i].packet", base, idx), cp); -void -LinkDelayEvent::process() -{ - link->txComplete(packet); -} - -void -LinkDelayEvent::serialize(ostream &os) -{ - paramOut(os, "type", string("LinkDelayEvent")); - Event::serialize(os); - - EtherLink *parent = link->parent; - bool number = link->number; - SERIALIZE_OBJPTR(parent); - SERIALIZE_SCALAR(number); - - packet->serialize("packet", os); -} - - -void -LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) -{ - Event::unserialize(cp, section); - - EtherLink *parent; - bool number; - UNSERIALIZE_OBJPTR(parent); - UNSERIALIZE_SCALAR(number); - - link = parent->link[number]; + fatal_if(!txQueue.empty() && txQueue.back().first > tick, + "Invalid txQueue packet order in EtherLink!\n"); + txQueue.emplace_back(std::make_pair(tick, delayed_packet)); + } - packet = new EthPacketData(16384); - packet->unserialize("packet", cp, section); -} - - -Serializable * -LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) -{ - return new LinkDelayEvent(); + if (!txQueue.empty()) + parent->schedule(txQueueEvent, txQueue.front().first); + } else { + // We can't reliably convert in-flight packets from old + // checkpoints. In fact, gem5 hasn't been able to load these + // packets for at least two years before the format change. + warn("Old-style EtherLink serialization format detected, " + "in-flight packets may have been dropped.\n"); + } } -REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink) - - SimObjectParam int1; - SimObjectParam int2; - Param speed; - Param delay; - Param delay_var; - SimObjectParam dump; - -END_DECLARE_SIM_OBJECT_PARAMS(EtherLink) - -BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink) - - INIT_PARAM(int1, "interface 1"), - INIT_PARAM(int2, "interface 2"), - INIT_PARAM(speed, "link speed in bits per second"), - INIT_PARAM(delay, "transmit delay of packets in us"), - INIT_PARAM(delay_var, "Difference in amount of time to traverse wire"), - INIT_PARAM(dump, "object to dump network packets to") - -END_INIT_SIM_OBJECT_PARAMS(EtherLink) - -CREATE_SIM_OBJECT(EtherLink) +EtherLink * +EtherLinkParams::create() { - return new EtherLink(getInstanceName(), int1, int2, speed, delay, delay_var, - dump); + return new EtherLink(this); } - -REGISTER_SIM_OBJECT("EtherLink", EtherLink)