/* * Copyright (c) 1997 University of Southern California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Information Sciences * Institute of the University of Southern California. * 4. Neither the name of the University nor of the Institute may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY 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. * */ #include "sincos.h" #include "config.h" #include "lan.h" #include "edge.h" #include "packet.h" #include "node.h" #include "view.h" #include "psview.h" #include "paint.h" #include "netmodel.h" #include "trace.h" LanLink::LanLink(Edge *e): edge_(e) { /*need to search through the destination node's links to find the link that's the twin of this one (i.e, same nodes, other direction) */ int lan=e->src(); Node *n=e->neighbor(); Edge *te=n->links(); while (te!=NULL) { if (te->dst()==lan) { pair_=te; break; } te=te->next_; } } int LanLink::placed() { return edge_->neighbor()->marked(); } //---------------------------------------------------------------------- // Lan::Lan(const char *name, NetModel *nm, double ps, double bw, // double delay, double angle) //---------------------------------------------------------------------- Lan::Lan(const char *name, NetModel *nm, double ps, double bw, double delay, double angle) : Animation(0,0), nm_(nm), links_(NULL), ps_(ps), bw_(bw), delay_(delay), angle_(angle), marked_(0), max_(0) { virtual_node_ = new VirtualNode(name, this); name_ = new char[strlen(name) + 1]; strcpy(name_, name); ln_ = atoi(name); /*XXX*/ paint_ = Paint::instance()->thick(); dropHash_ = new Tcl_HashTable; // XXX: unique packet id == (src, dst, id). Its size may be changed later. Tcl_InitHashTable(dropHash_, 3); } //---------------------------------------------------------------------- //---------------------------------------------------------------------- Lan::~Lan() { if (dropHash_ != NULL) { Tcl_DeleteHashTable(dropHash_); delete dropHash_; } delete virtual_node_; } float Lan::distance(float /*x*/, float /*y*/) const { // TODO: to be added return HUGE_VAL; } //---------------------------------------------------------------------- //---------------------------------------------------------------------- static int to_the_left(Edge *e, double angle, int incoming) { double edge_angle = e->angle(); if (incoming) edge_angle = 1.0 + edge_angle; if (edge_angle > 2.0) edge_angle -= 2.0; double a = angle - edge_angle; if (a < 0) { a += 2.0; } if (a > 1.0) { return 1; } else { return 0; } } //---------------------------------------------------------------------- // void Lan::add_link(Edge *e) // - add a link to the shared bus line //---------------------------------------------------------------------- void Lan::add_link(Edge *e) { int left = 0; int right = 0; double sine, cosine, left_length, right_length; Node * source, * destination; LanLink * ll; ll = new LanLink(e); source = e->getSourceNode(); destination = e->getDestinationNode(); SINCOSPI(angle_, &sine, &cosine); ll->next(links_); links_ = ll; virtual_node_->add_link(e); // Keep track of how long the "bus" is ll = links_; while (ll != NULL) { if (to_the_left(ll->edge(), angle_, 0)) { left++; } else { right++; } ll = ll->next(); } left_length = left * (destination->size() + source->size() + size_); right_length = right * (destination->size() + source->size() + size_); if (max_ < left_length) { max_ = (int) ceil(left_length); } if (max_ < right_length) { max_ = (int) ceil(right_length); } } //---------------------------------------------------------------------- //---------------------------------------------------------------------- void Lan::update_bb() { double s,c; SINCOSPI(angle_,&s,&c); bb_.xmin = x_ - size_*c; bb_.xmax = x_+size_*c*(2*max_+1); bb_.ymin = y_ - size_*s; bb_.ymax = y_+size_*s*(2*max_+1); } //---------------------------------------------------------------------- //---------------------------------------------------------------------- void Lan::size(double size) { size_ = size; update_bb(); } //---------------------------------------------------------------------- //---------------------------------------------------------------------- void Lan::place(double x, double y) { x_ = x; y_ = y; update_bb(); } //---------------------------------------------------------------------- //---------------------------------------------------------------------- void Lan::draw(class View* nv, double time) { double s, c; SINCOSPI(angle_, &s, &c); //nv->line(x_ - size_ * c, y_ - size_ * s, // x_ + size_ * c * (2 * max_ + 1), y_ + size_ * s * (2 * max_ + 1), // paint_); nv->line(x_ - size_ * c, y_ - size_ * s, x_ + size_ * c + c * max_, y_ + size_ * s + s * max_, paint_); } //void Lan::draw(class PSView* nv, double /*time*/) const { /* double s,c; SINCOSPI(angle_,&s,&c); nv->line(x_-size_*c, y_-size_*s, x_+size_*c*(2*max_+1), y_+size_*s*(2*max_+1), paint_); } */ void Lan::remove_drop(const TraceEvent &e) { int id[3]; id[0] = e.pe.src; id[1] = e.pe.dst; id[2] = e.pe.pkt.id; Tcl_HashEntry *he = Tcl_FindHashEntry(dropHash_, (const char *)id); if (he != NULL) { TraceEvent *pe = (TraceEvent *)Tcl_GetHashValue(he); delete pe; Tcl_DeleteHashEntry(he); } } void Lan::register_drop(const TraceEvent &e) { int newEntry = 1; int id[3]; id[0] = e.pe.src; id[1] = e.pe.dst; id[2] = e.pe.pkt.id; Tcl_HashEntry *he = Tcl_CreateHashEntry(dropHash_, (const char *)id, &newEntry); if (he == NULL) return; if (newEntry) { TraceEvent *pe = new TraceEvent; *pe = e; Tcl_SetHashValue(he, (ClientData)pe); } } void Lan::arrive_packet(Packet *p, Edge *e, double atime) { /*need to duplicate the packet on all other links except the arrival link*/ LanLink *l=links_; PacketAttr pkt; int id[3]; pkt.size=p->size(); pkt.id=p->id(); pkt.attr=p->attr(); strcpy(pkt.type,p->type()); strcpy(pkt.convid,p->convid()); while (l!=NULL) { Edge *ne=l->edge(); if (l->pair()!=e) { // Packet *np = nm_->newPacket(pkt, ne, atime); nm_->newPacket(pkt, ne, atime); id[0] = ne->src(); id[1] = ne->dst(); id[2] = p->id(); Tcl_HashEntry *he = Tcl_FindHashEntry(dropHash_, (const char *)id); if (he != NULL) { // This is a drop packet, fake a trace event and add a drop TraceEvent *pe = (TraceEvent *)Tcl_GetHashValue(he); pe->time = atime; // The fact that this trace event is still there implies that // we are going forwards. nm_->add_drop(*pe, atime, FORWARDS); delete pe; Tcl_DeleteHashEntry(he); } } l=l->next(); } rgb *color = Paint::instance()->paint_to_rgb(p->paint()); paint_ = Paint::instance()->lookup(color->colorname, 5); } void Lan::delete_packet(Packet *) { paint_ = Paint::instance()->thick(); } //---------------------------------------------------------------------- //---------------------------------------------------------------------- double Lan::x(Edge *e) const { double sine, cosine; SINCOSPI(angle_, &sine, &cosine); LanLink * l = links_; int incoming =- 1; int left = -1; int right = -1; Node * source, * destination; source = e->getSourceNode(); destination = e->getDestinationNode(); while (l != NULL) { if (to_the_left(l->edge(), angle_, 0)) { left++; } else { right++; } if (l->pair() == e) { incoming = 1; break; } else if (l->edge()==e) { incoming = 0; break; } l = l->next(); } if (to_the_left(e, angle_, incoming)) { return x_ + cosine * left * (destination->size() + source->size() + size_); //return x_ + cosine * left * 2 * size_; } else { return x_ + cosine * right * (destination->size() + source->size() + size_); //return x_ + cosine * right * 2 * size_; } } double Lan::y(Edge *e) const { double s,c; SINCOSPI(angle_,&s,&c); LanLink *l=links_; int incoming=-1; int left=-1; int right=-1; while (l!=NULL) { if (to_the_left(l->edge(), angle_,0)) { left++; } else { right++; } if (l->pair()==e) { incoming=1; break; } else if (l->edge()==e) { incoming=0; break; } l=l->next(); } Node * destination = e->getDestinationNode(); if (to_the_left(e, angle_, incoming)) { return y_ + s * left * destination->size(); } else { return y_ + s * right * destination->size(); } } #ifdef NOTDEF Edge *Lan::lookupEdge(Node *n) { LanNode *ln=nodes_; while(ln!=NULL) { if (ln->node()==n) { return ln->e1_; } } return NULL; } #endif