ARM: Make GIC function that should only be called by GIC protected.
[gem5.git] / src / dev / etherlink.cc
index 5b6531c2e367cfe6df5435e83b4709de7e4c247f..289b7454342b659c725a76bb259daed492ce8288 100644 (file)
@@ -24,6 +24,9 @@
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ *          Ron Dreslinski
  */
 
 /* @file
 
 #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/root.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);
-
-    interface[0] = new Interface(name + ".int0", link[0], link[1]);
-    interface[1] = new Interface(name + ".int1", link[1], link[0]);
+    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]->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];
@@ -73,6 +75,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)
 {
@@ -118,7 +137,7 @@ class LinkDelayEvent : public Event
   public:
     // non-scheduling version for createForUnserialize()
     LinkDelayEvent();
-    LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when);
+    LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt);
 
     void process();
 
@@ -136,7 +155,8 @@ EtherLink::Link::txDone()
 
     if (linkDelay > 0) {
         DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay);
-        new LinkDelayEvent(this, packet, curTick + linkDelay);
+        Event *event = new LinkDelayEvent(this, packet);
+        parent->schedule(event, curTick() + linkDelay);
     } else {
         txComplete(packet);
     }
@@ -160,13 +180,12 @@ EtherLink::Link::transmit(EthPacketPtr pkt)
 
     packet = pkt;
     Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
-    if (delayVar != 0) {
-        Random<Tick> var;
-        delay +=  var.uniform(0, delayVar);
-    }
+    if (delayVar != 0)
+        delay += random_mt.random<Tick>(0, delayVar);
+
     DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
             delay, ticksPerByte);
-    doneEvent.schedule(curTick + delay);
+    parent->schedule(doneEvent, curTick() + delay);
 
     return true;
 }
@@ -204,23 +223,22 @@ EtherLink::Link::unserialize(const string &base, Checkpoint *cp,
     if (event_scheduled) {
         Tick event_time;
         paramIn(cp, section, base + ".event_time", event_time);
-        doneEvent.schedule(event_time);
+        parent->schedule(doneEvent, event_time);
     }
 }
 
 LinkDelayEvent::LinkDelayEvent()
-    : Event(&mainEventQueue), link(NULL)
+    : link(NULL)
 {
     setFlags(AutoSerialize);
     setFlags(AutoDelete);
 }
 
-LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p, Tick when)
-    : Event(&mainEventQueue), link(l), packet(p)
+LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p)
+    : link(l), packet(p)
 {
     setFlags(AutoSerialize);
     setFlags(AutoDelete);
-    schedule(when);
 }
 
 void
@@ -269,32 +287,8 @@ LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string &section)
 
 REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)
 
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
-
-    SimObjectParam<EtherInt *> int1;
-    SimObjectParam<EtherInt *> int2;
-    Param<double> speed;
-    Param<Tick> delay;
-    Param<Tick> delay_var;
-    SimObjectParam<EtherDump *> 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)