OpenCores
URL https://opencores.org/ocsvn/nocmodel/nocmodel/trunk

Subversion Repositories nocmodel

[/] [nocmodel/] [trunk/] [nocmodel/] [basicmodels/] [basic_router.py] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dargor
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
 
4
#
5
# Basic Router model
6
#  * TLM model
7
#
8
# Author:  Oscar Diaz
9
# Version: 0.1
10
# Date:    03-03-2011
11
 
12
#
13
# This code is free software; you can redistribute it and/or
14
# modify it under the terms of the GNU Lesser General Public
15
# License as published by the Free Software Foundation; either
16
# version 2.1 of the License, or (at your option) any later version.
17
#
18
# This code is distributed in the hope that it will be useful,
19
# but WITHOUT ANY WARRANTY; without even the implied warranty of
20
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21
# Lesser General Public License for more details.
22
#
23
# You should have received a copy of the GNU Lesser General Public
24
# License along with this library; if not, write to the
25
# Free Software  Foundation, Inc., 59 Temple Place, Suite 330,
26
# Boston, MA  02111-1307  USA
27
#
28
 
29
#
30
# Changelog:
31
#
32
# 03-03-2011 : (OD) initial release
33
#
34
 
35
"""
36
Basic router TLM model
37
"""
38
 
39
from nocmodel.noc_tlm_base import *
40
 
41
# ---------------------------
42
# Router TLM model
43
 
44
class basic_router_tlm(noc_tlm_base):
45
    """
46
    TLM model of a NoC router. This router uses store-and-forward technique,
47
    using the routing information from the router object. This model just
48
    forward the packet, and if the packet is in its router destination, send it
49
    to its ipcore. Each package that the ipcore generates is delivered
50
    automátically.
51
 
52
    Attributes:
53
    * router_ref : base reference
54
    * fifo_len: max number of packets to hold in each port
55
 
56
    Notes:
57
    * This model is completely behavioral.
58
    * See code comments to better understanding.
59
    """
60
    def __init__(self, router_ref, fifo_len=4):
61
        noc_tlm_base.__init__(self)
62
        if isinstance(router_ref, router):
63
            self.router_ref = router_ref
64
            self.graph_ref = router_ref.graph_ref
65
            self.logname = "Router '%s'" % router_ref.name
66
            if router_ref.name == "":
67
                self.logname = "Router addr '%s'" % router_ref.address
68
        else:
69
            raise TypeError("This class needs a router object as constructor argument.")
70
 
71
        self.debug("constructor")
72
 
73
        # generic parameters
74
        self.fifo_len = fifo_len
75
 
76
        # delay parameters
77
        self.delay_route = 5        # delay for each routing decisition
78
        self.delay_outfromfifo = 2  # delay for extract packet from fifo to output port
79
        self.delay_ipcorebus = 1    # delay for ipcore local bus operations
80
 
81
        # router parameters (Assume rectangular coords)
82
        self.myaddress = router_ref.address
83
        self.mynodecoord = (router_ref.coord_x, router_ref.coord_y)
84
 
85
        # port additions: use a copy of the ports list, and add
86
        # fifo storage and signal events
87
        router_ref.update_ports_info()
88
        self.ports_info = router_ref.ports.copy()
89
        for p in self.ports_info.itervalues():
90
            p["fifo_in"] = []
91
            p["fifo_out"] = []
92
            p["fifo_in_event"] = myhdl.Signal(False)
93
            p["fifo_out_event"] = myhdl.Signal(False)
94
 
95
        # extract a list of all fifo event signals
96
        self.list_fifo_in_events = [i["fifo_in_event"] for i in self.ports_info.itervalues()]
97
        self.list_fifo_out_events = [i["fifo_out_event"] for i in self.ports_info.itervalues()]
98
 
99
        # the routing table is generated from the routes_info dict
100
        # key: its destination address
101
        # values: a list of ports where the package should send it. First element
102
        #    is the default option, next elements are alternate routes
103
        router_ref.update_routes_info()
104
        self.detailed_routingtable = self.router_ref.routes_info.copy()
105
        self.routingtable = {}
106
        for dest, data in self.detailed_routingtable.iteritems():
107
            self.routingtable[dest] = [x["next"] for x in data]
108
        # add route to myself
109
        self.routingtable[self.myaddress] = [self.myaddress]
110
 
111
        # log interesting info
112
        self.info(" router params: fifo_len=%d" % self.fifo_len)
113
        self.info(" router info: addr=%d coord=%s" % (self.myaddress, repr(self.mynodecoord)))
114
        self.info(" router ports: %s" % repr(self.ports_info))
115
        self.info(" router routing table: %s" % repr(self.routingtable))
116
 
117
        # myhdl generators (concurrent processes)
118
        self.generators = []
119
 
120
        # fifo out process
121
        @myhdl.instance
122
        def flush_fifo_out():
123
            while True:
124
                for port, data in self.ports_info.iteritems():
125
                    if len(data["fifo_out"]) > 0:
126
                        if not data["fifo_out_event"].val:
127
                            self.debug("flush_fifo_out CATCH fifo not empty and NO trigger! fifo has %s" % repr(data["fifo_out"]))
128
                        self.info("flush_fifo_out event in port %d" % port)
129
                        packet = data["fifo_out"].pop(0)
130
                        self.debug("flush_fifo_out port %d packet is %s (delay %d)" % (port, repr(packet), self.delay_outfromfifo))
131
                        # DELAY model: time to move from fifo to external port in destination object
132
                        yield myhdl.delay(self.delay_outfromfifo)
133
                        # try to send it
134
                        retval = self.send(self.router_ref, data["channel"], packet)
135
                        if retval == noc_tlm_errcodes.no_error:
136
                            # clean trigger
137
                            data["fifo_out_event"].next = False
138
                            #continue
139
                        else:
140
                            self.error("flush_fifo_out FAILED in port %d (code %d)" % (port, retval))
141
                            # error management: 
142
                            #TODO: temporally put back to fifo
143
                            self.info("flush_fifo_out packet went back to fifo.")
144
                            data["fifo_out"].append(packet)
145
                yield self.list_fifo_out_events
146
                self.debug("flush_fifo_out event hit. list %s" % repr(self.list_fifo_out_events))
147
 
148
        # routing loop
149
        @myhdl.instance
150
        def routing_loop():
151
            while True:
152
                # routing update: check all fifos
153
                for port, data in self.ports_info.iteritems():
154
                    while len(data["fifo_in"]) > 0:
155
                        if not data["fifo_in_event"].val:
156
                            self.debug("routing_loop CATCH fifo not empty and NO trigger! fifo has %s" % repr(data["fifo_in"]))
157
                        self.info("routing_loop fifo_in event in port %d" % port)
158
                        # data in fifo
159
                        packet = data["fifo_in"].pop(0)
160
                        data["fifo_in_event"].next = False
161
                        self.debug("routing_loop port %d packet %s to ipcore (delay %d)" % (port, repr(packet), self.delay_route))
162
                        # destination needed. extract from routing table
163
                        destaddr = packet["dst"]
164
                        self.debug("routing_loop port %d routingtable %s (dest %d)" % (port, repr(self.routingtable), destaddr))
165
                        nextaddr = self.routingtable[destaddr][0]
166
                        self.debug("routing_loop port %d to port %s (dest %d)" % (port, nextaddr, destaddr))
167
                        # DELAY model: time spent to make a route decisition
168
                        yield myhdl.delay(self.delay_route)
169
                        self.ports_info[nextaddr]["fifo_out"].append(packet)
170
                        # fifo trigger
171
                        if self.ports_info[nextaddr]["fifo_out_event"]:
172
                            self.debug("routing_loop CATCH possible miss event because port %d fifo_out_event=True", self.myaddress)
173
                        self.ports_info[nextaddr]["fifo_out_event"].next = True
174
 
175
                yield self.list_fifo_in_events
176
                self.debug("routing_loop event hit. list %s" % repr(self.list_fifo_in_events))
177
 
178
        # list of all generators
179
        self.generators.extend([flush_fifo_out, routing_loop])
180
        self.debugstate()
181
 
182
    # Transaction - related methods
183
    def send(self, src, dest, packet, addattrs=None):
184
        """
185
        This method will be called on a fifo available data event
186
 
187
        Notes:
188
        * Ignore src object.
189
        * dest should be a channel object, but also can be a router address or
190
          a router object.
191
        """
192
        self.debug("-> send( %s , %s , %s , %s )" % (repr(src), repr(dest), repr(packet), repr(addattrs)))
193
        if isinstance(dest, int):
194
            # it means dest is a router address
195
            therouter = self.graph_ref.get_router_by_address(dest)
196
            if therouter == False:
197
                self.error("-> send: dest %s not found" % repr(dest) )
198
                return noc_tlm_errcodes.tlm_badcall_send
199
            # extract channel ref from ports_info
200
            thedest = self.ports_info[therouter.address]["channel"]
201
        elif isinstance(dest, router):
202
            # extract channel ref from ports_info
203
            thedest = self.ports_info[dest.address]["channel"]
204
        elif isinstance(dest, channel):
205
            # use it directly
206
            thedest = dest
207
        else:
208
            self.error("-> send: what is dest '%s'?" % repr(dest) )
209
            return noc_tlm_errcodes.tlm_badcall_send
210
 
211
        # call recv on the dest channel object
212
        retval = thedest.tlm.recv(self.router_ref, thedest, packet, addattrs)
213
 
214
        # TODO: something to do with the retval?
215
        self.debug("-> send returns code '%s'" % repr(retval))
216
        return retval
217
 
218
    def recv(self, src, dest, packet, addattrs=None):
219
        """
220
        This method will be called by channel objects connected to this router.
221
 
222
        Notes:
223
        * The recv method only affect the receiver FIFO sets
224
        * Ignore dest object.
225
        """
226
 
227
        self.debug("-> recv( %s , %s , %s , %s )" % (repr(src), repr(dest), repr(packet), repr(addattrs)))
228
        # src can be an address or a noc object.
229
        # convert to addresses
230
        if isinstance(src, int):
231
            thesrc = src
232
        elif isinstance(src, router):
233
            thesrc = src.address
234
        elif isinstance(src, channel):
235
            # get address from the other end. Use the endpoints to calculate
236
            # source router
237
            src_index = src.endpoints.index(self.router_ref) - 1
238
            theend = src.endpoints[src_index]
239
            if isinstance(theend, router):
240
                thesrc = theend.address
241
            elif isinstance(theend, ipcore):
242
                thesrc = theend.router_ref.address
243
            else:
244
                self.error("-> recv: what is endpoint '%s' in channel '%s'?" % (repr(theend), repr(src)) )
245
                return noc_tlm_errcodes.tlm_badcall_recv
246
        else:
247
            self.error("-> recv: what is src '%s'?" % repr(src) )
248
            return noc_tlm_errcodes.tlm_badcall_recv
249
 
250
        # thesrc becomes the port number
251
        # check if there is enough space on the FIFO
252
        if len(self.ports_info[thesrc]["fifo_in"]) == self.fifo_len:
253
            # full FIFO
254
            self.error("-> recv: full fifo. Try later.")
255
            return noc_tlm_errcodes.full_fifo
256
        # get into fifo
257
        self.ports_info[thesrc]["fifo_in"].append(packet)
258
        # trigger a new routing event
259
        if self.ports_info[thesrc]["fifo_in_event"].val:
260
            self.debug("-> recv: CATCH possible miss event because in port %d fifo_in_event=True", thesrc)
261
        self.ports_info[thesrc]["fifo_in_event"].next = True
262
 
263
        self.debug("-> recv returns 'noc_tlm_errcodes.no_error'")
264
        return noc_tlm_errcodes.no_error

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.