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

Subversion Repositories nocmodel

[/] [nocmodel/] [trunk/] [nocmodel/] [basicmodels/] [basic_router.py] - Diff between revs 2 and 4

Show entire file | Details | Blame | View Log

Rev 2 Rev 4
Line 1... Line 1...
#!/usr/bin/env python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
 
 
#
#
# Basic Router model
# Basic Router model
#  * TLM model
#  * TBM model
 
#  * Code generation model
#
#
# Author:  Oscar Diaz
# Author:  Oscar Diaz
# Version: 0.1
# Version: 0.2
# Date:    03-03-2011
# Date:    14-03-2011
 
 
#
#
# This code is free software; you can redistribute it and/or
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# License as published by the Free Software Foundation; either
Line 28... Line 29...
 
 
#
#
# Changelog:
# Changelog:
#
#
# 03-03-2011 : (OD) initial release
# 03-03-2011 : (OD) initial release
 
# 14-03-2011 : (OD) adding code generation model
#
#
 
 
"""
"""
Basic router TLM model
* Basic router TBM model
 
* Router code generation model
"""
"""
 
 
from nocmodel.noc_tlm_base import *
from nocmodel.noc_tbm_base import *
 
from nocmodel.noc_codegen_base import *
 
from intercon_model import *
 
 
# ---------------------------
# ---------------------------
# Router TLM model
# Router TBM model
 
 
class basic_router_tlm(noc_tlm_base):
class basic_router_tbm(noc_tbm_base):
    """
    """
    TLM model of a NoC router. This router uses store-and-forward technique,
    TBM model of a NoC router. This router uses store-and-forward technique,
    using the routing information from the router object. This model just
    using the routing information from the router object. This model just
    forward the packet, and if the packet is in its router destination, send it
    forward the packet, and if the packet is in its router destination, send it
    to its ipcore. Each package that the ipcore generates is delivered
    to its ipcore. Each package that the ipcore generates is delivered
    automátically.
    automátically.
 
 
Line 55... Line 60...
 
 
    Notes:
    Notes:
    * This model is completely behavioral.
    * This model is completely behavioral.
    * See code comments to better understanding.
    * See code comments to better understanding.
    """
    """
    def __init__(self, router_ref, fifo_len=4):
    def __init__(self, router_ref, fifo_len=5):
        noc_tlm_base.__init__(self)
        noc_tbm_base.__init__(self)
        if isinstance(router_ref, router):
        if isinstance(router_ref, router):
            self.router_ref = router_ref
            self.router_ref = router_ref
            self.graph_ref = router_ref.graph_ref
            self.graph_ref = router_ref.graph_ref
            self.logname = "Router '%s'" % router_ref.name
            self.logname = "Router '%s'" % router_ref.name
            if router_ref.name == "":
            if router_ref.name == "":
Line 89... Line 94...
        for p in self.ports_info.itervalues():
        for p in self.ports_info.itervalues():
            p["fifo_in"] = []
            p["fifo_in"] = []
            p["fifo_out"] = []
            p["fifo_out"] = []
            p["fifo_in_event"] = myhdl.Signal(False)
            p["fifo_in_event"] = myhdl.Signal(False)
            p["fifo_out_event"] = myhdl.Signal(False)
            p["fifo_out_event"] = myhdl.Signal(False)
 
        self.idlesignal = myhdl.Signal(True)
 
 
        # extract a list of all fifo event signals
        # extract a list of all fifo event signals
        self.list_fifo_in_events = [i["fifo_in_event"] for i in self.ports_info.itervalues()]
        self.list_fifo_in_events = [i["fifo_in_event"] for i in self.ports_info.itervalues()]
        self.list_fifo_out_events = [i["fifo_out_event"] for i in self.ports_info.itervalues()]
        self.list_fifo_out_events = [i["fifo_out_event"] for i in self.ports_info.itervalues()]
 
 
Line 121... Line 127...
        @myhdl.instance
        @myhdl.instance
        def flush_fifo_out():
        def flush_fifo_out():
            while True:
            while True:
                for port, data in self.ports_info.iteritems():
                for port, data in self.ports_info.iteritems():
                    if len(data["fifo_out"]) > 0:
                    if len(data["fifo_out"]) > 0:
 
                        self.idlesignal.next = False
                        if not data["fifo_out_event"].val:
                        if not data["fifo_out_event"].val:
                            self.debug("flush_fifo_out CATCH fifo not empty and NO trigger! fifo has %s" % repr(data["fifo_out"]))
                            self.debug("flush_fifo_out CATCH fifo not empty and NO trigger! fifo has %s" % repr(data["fifo_out"]))
                        self.info("flush_fifo_out event in port %d" % port)
                        self.info("flush_fifo_out event in port %d" % port)
                        packet = data["fifo_out"].pop(0)
                        packet = data["fifo_out"].pop(0)
                        self.debug("flush_fifo_out port %d packet is %s (delay %d)" % (port, repr(packet), self.delay_outfromfifo))
                        self.debug("flush_fifo_out port %d packet is %s (delay %d)" % (port, repr(packet), self.delay_outfromfifo))
                        # DELAY model: time to move from fifo to external port in destination object
                        # DELAY model: time to move from fifo to external port in destination object
                        yield myhdl.delay(self.delay_outfromfifo)
                        yield myhdl.delay(self.delay_outfromfifo)
 
                        self.idlesignal.next = False
                        # try to send it
                        # try to send it
                        retval = self.send(self.router_ref, data["channel"], packet)
                        retval = self.send(self.router_ref, data["channel"], packet)
                        if retval == noc_tlm_errcodes.no_error:
                        if retval == noc_tbm_errcodes.no_error:
                            # clean trigger
                            # clean trigger
                            data["fifo_out_event"].next = False
                            data["fifo_out_event"].next = False
 
                            self.debug("flush_fifo_out clean trigger. list %s" % repr(self.list_fifo_out_events))
                            #continue
                            #continue
                        else:
                        else:
                            self.error("flush_fifo_out FAILED in port %d (code %d)" % (port, retval))
                            self.error("flush_fifo_out FAILED in port %d (code %d)" % (port, retval))
                            # error management: 
                            # error management: 
                            #TODO: temporally put back to fifo
                            #TODO: temporally put back to fifo
                            self.info("flush_fifo_out packet went back to fifo.")
                            self.info("flush_fifo_out packet went back to fifo.")
                            data["fifo_out"].append(packet)
                            data["fifo_out"].append(packet)
 
                    else:
 
                        if data["fifo_out_event"].val:
 
                            self.debug("flush_fifo_out CATCH fifo_out empty and trigger ON! Cleaning trigger")
 
                            data["fifo_out_event"].next = False
 
                self.idlesignal.next = True
                yield self.list_fifo_out_events
                yield self.list_fifo_out_events
                self.debug("flush_fifo_out event hit. list %s" % repr(self.list_fifo_out_events))
                self.debug("flush_fifo_out event hit. list %s" % repr(self.list_fifo_out_events))
 
 
        # routing loop
        # routing loop
        @myhdl.instance
        @myhdl.instance
        def routing_loop():
        def routing_loop():
            while True:
            while True:
                # routing update: check all fifos
                # routing update: check all fifos
                for port, data in self.ports_info.iteritems():
                for port, data in self.ports_info.iteritems():
                    while len(data["fifo_in"]) > 0:
                    while len(data["fifo_in"]) > 0:
 
                        self.idlesignal.next = False
                        if not data["fifo_in_event"].val:
                        if not data["fifo_in_event"].val:
                            self.debug("routing_loop CATCH fifo not empty and NO trigger! fifo has %s" % repr(data["fifo_in"]))
                            self.debug("routing_loop CATCH fifo not empty and NO trigger! fifo has %s" % repr(data["fifo_in"]))
                        self.info("routing_loop fifo_in event in port %d" % port)
                        self.info("routing_loop fifo_in event in port %d" % port)
                        # data in fifo
                        # data in fifo
                        packet = data["fifo_in"].pop(0)
                        packet = data["fifo_in"].pop(0)
Line 164... Line 179...
                        self.debug("routing_loop port %d routingtable %s (dest %d)" % (port, repr(self.routingtable), destaddr))
                        self.debug("routing_loop port %d routingtable %s (dest %d)" % (port, repr(self.routingtable), destaddr))
                        nextaddr = self.routingtable[destaddr][0]
                        nextaddr = self.routingtable[destaddr][0]
                        self.debug("routing_loop port %d to port %s (dest %d)" % (port, nextaddr, destaddr))
                        self.debug("routing_loop port %d to port %s (dest %d)" % (port, nextaddr, destaddr))
                        # DELAY model: time spent to make a route decisition
                        # DELAY model: time spent to make a route decisition
                        yield myhdl.delay(self.delay_route)
                        yield myhdl.delay(self.delay_route)
 
                        self.idlesignal.next = False
                        self.ports_info[nextaddr]["fifo_out"].append(packet)
                        self.ports_info[nextaddr]["fifo_out"].append(packet)
                        # fifo trigger
                        # fifo trigger
                        if self.ports_info[nextaddr]["fifo_out_event"]:
                        if self.ports_info[nextaddr]["fifo_out_event"]:
                            self.debug("routing_loop CATCH possible miss event because port %d fifo_out_event=True", self.myaddress)
                            self.debug("routing_loop CATCH possible miss event because port %d fifo_out_event=True", self.myaddress)
                        self.ports_info[nextaddr]["fifo_out_event"].next = True
                        self.ports_info[nextaddr]["fifo_out_event"].next = True
 
                    # assuming empty fifo_in
 
                    if data["fifo_in_event"].val:
 
                        self.debug("routing_loop CATCH fifo_in empty and trigger ON! Cleaning trigger")
 
                        data["fifo_in_event"].next = False
 
                self.idlesignal.next = True
 
                self.debug("routing_loop idle. fifo_in_events list %s" % repr(self.list_fifo_in_events))
 
                if not any(self.list_fifo_in_events):
                yield self.list_fifo_in_events
                yield self.list_fifo_in_events
                self.debug("routing_loop event hit. list %s" % repr(self.list_fifo_in_events))
                else:
 
                    self.debug("routing_loop pending fifo_in_events list %s" % repr(self.list_fifo_in_events))
 
                self.debug("routing_loop fifo_in event hit. list %s" % repr(self.list_fifo_in_events))
 
 
        # list of all generators
        # list of all generators
        self.generators.extend([flush_fifo_out, routing_loop])
        self.generators.extend([flush_fifo_out, routing_loop])
        self.debugstate()
        self.debugstate()
 
 
Line 193... Line 217...
        if isinstance(dest, int):
        if isinstance(dest, int):
            # it means dest is a router address
            # it means dest is a router address
            therouter = self.graph_ref.get_router_by_address(dest)
            therouter = self.graph_ref.get_router_by_address(dest)
            if therouter == False:
            if therouter == False:
                self.error("-> send: dest %s not found" % repr(dest) )
                self.error("-> send: dest %s not found" % repr(dest) )
                return noc_tlm_errcodes.tlm_badcall_send
                return noc_tbm_errcodes.tbm_badcall_send
            # extract channel ref from ports_info
            # extract channel ref from ports_info
            thedest = self.ports_info[therouter.address]["channel"]
            thedest = self.ports_info[therouter.address]["channel"]
        elif isinstance(dest, router):
        elif isinstance(dest, router):
            # extract channel ref from ports_info
            # extract channel ref from ports_info
            thedest = self.ports_info[dest.address]["channel"]
            thedest = self.ports_info[dest.address]["channel"]
        elif isinstance(dest, channel):
        elif isinstance(dest, channel):
            # use it directly
            # use it directly
            thedest = dest
            thedest = dest
        else:
        else:
            self.error("-> send: what is dest '%s'?" % repr(dest) )
            self.error("-> send: what is dest '%s'?" % repr(dest) )
            return noc_tlm_errcodes.tlm_badcall_send
            return noc_tbm_errcodes.tbm_badcall_send
 
 
        # call recv on the dest channel object
        # call recv on the dest channel object
        retval = thedest.tlm.recv(self.router_ref, thedest, packet, addattrs)
        retval = thedest.tbm.recv(self.router_ref, thedest, packet, addattrs)
 
 
        # TODO: something to do with the retval?
        # TODO: something to do with the retval?
        self.debug("-> send returns code '%s'" % repr(retval))
        self.debug("-> send returns code '%s'" % repr(retval))
        return retval
        return retval
 
 
Line 240... Line 264...
                thesrc = theend.address
                thesrc = theend.address
            elif isinstance(theend, ipcore):
            elif isinstance(theend, ipcore):
                thesrc = theend.router_ref.address
                thesrc = theend.router_ref.address
            else:
            else:
                self.error("-> recv: what is endpoint '%s' in channel '%s'?" % (repr(theend), repr(src)) )
                self.error("-> recv: what is endpoint '%s' in channel '%s'?" % (repr(theend), repr(src)) )
                return noc_tlm_errcodes.tlm_badcall_recv
                return noc_tbm_errcodes.tbm_badcall_recv
        else:
        else:
            self.error("-> recv: what is src '%s'?" % repr(src) )
            self.error("-> recv: what is src '%s'?" % repr(src) )
            return noc_tlm_errcodes.tlm_badcall_recv
            return noc_tbm_errcodes.tbm_badcall_recv
 
 
        # thesrc becomes the port number
        # thesrc becomes the port number
        # check if there is enough space on the FIFO
        # check if there is enough space on the FIFO
        if len(self.ports_info[thesrc]["fifo_in"]) == self.fifo_len:
        if len(self.ports_info[thesrc]["fifo_in"]) == self.fifo_len:
            # full FIFO
            # full FIFO
            self.error("-> recv: full fifo. Try later.")
            self.error("-> recv: full fifo. Try later.")
            return noc_tlm_errcodes.full_fifo
            self.debug("-> recv: port %s fifo_in contents: %s" % (thesrc, repr(self.ports_info[thesrc]["fifo_in"])))
 
            return noc_tbm_errcodes.full_fifo
        # get into fifo
        # get into fifo
        self.ports_info[thesrc]["fifo_in"].append(packet)
        self.ports_info[thesrc]["fifo_in"].append(packet)
        # trigger a new routing event
        # trigger a new routing event
        if self.ports_info[thesrc]["fifo_in_event"].val:
        if self.ports_info[thesrc]["fifo_in_event"].val:
            self.debug("-> recv: CATCH possible miss event because in port %d fifo_in_event=True", thesrc)
            self.debug("-> recv: CATCH possible miss event because in port %d fifo_in_event=True", thesrc)
 
            self.debug("-> recv: CATCH fifo_in_event list %s" % repr(self.list_fifo_in_events))
        self.ports_info[thesrc]["fifo_in_event"].next = True
        self.ports_info[thesrc]["fifo_in_event"].next = True
 
 
        self.debug("-> recv returns 'noc_tlm_errcodes.no_error'")
        self.debug("-> recv returns 'noc_tbm_errcodes.no_error'")
        return noc_tlm_errcodes.no_error
        return noc_tbm_errcodes.no_error
 
 
 
# ---------------------------
 
# Router code generation model
 
 
 
class basic_router_codegen(noc_codegen_ext):
 
    """
 
    Code generation extension for Router objects.
 
    """
 
 
 
    def __init__(self, codegen_ref):
 
        noc_codegen_ext.__init__(self, codegen_ref)
 
        self.router_ref = codegen_ref.nocobject_ref
 
        if not isinstance(self.router_ref, router):
 
            raise TypeError("Argument must be a 'noc_codegen_base' instance defined for a router object.")
 
 
 
        # router model: This basic router has some parameters put in the 
 
        # generics list, and a fixed number of NoC ports: 4. 
 
 
 
        # assumptions: use 4 ports 'dualwb_intercon' plus 1 port 'slavewb_intercon'
 
 
 
        codegen_ref.modulename = "basic_4P_router"
 
 
 
        # 1. convert basic attributes to generics
 
        codegen_ref.add_generic("name", self.router_ref.name, "Router Name")
 
        codegen_ref.add_generic("address", self.router_ref.address, "Router Address")
 
        # assuming rectangular layout
 
        codegen_ref.add_generic("coord_x", self.router_ref.coord_x, "Router X-axis Coord")
 
        codegen_ref.add_generic("coord_y", self.router_ref.coord_y, "Router Y-axis Coord")
 
 
 
        # 2. Calculate which of 4 ports is used by who
 
        portinfo = {"N": None, "E": None, "S": None, "W": None}
 
        for pname, pvalues in self.router_ref.ports.iteritems():
 
            if pname != self.router_ref.address:
 
                # check correct intercon
 
                if not isinstance(pvalues["channel"].ports[self.router_ref.address]["intercon"], dualwb_intercon):
 
                    raise UserWarning("Port '%d' on router '%s' does not use intercon 'dualwb_intercon'." % (pname, self.router_ref.name))
 
                # calculate which port
 
                dx = self.router_ref.coord_x - pvalues["peer"].coord_x
 
                dy = self.router_ref.coord_y - pvalues["peer"].coord_y
 
                if dx == 0:
 
                    if dy > 0:
 
                        portinfo["S"] = pname
 
                    else:
 
                        portinfo["N"] = pname
 
                if dy == 0:
 
                    if dx > 0:
 
                        portinfo["W"] = pname
 
                    else:
 
                        portinfo["E"] = pname
 
            else:
 
                # check correct intercon
 
                if not isinstance(pvalues["channel"].ports[self.router_ref.address]["intercon"], slavewb_intercon):
 
                    raise UserWarning("Port 'Local' on router '%s' does not use intercon 'slavewb_intercon'." % self.router_ref.name)
 
 
 
        icon_ref = dualwb_intercon()
 
        # 3. Add ports and info through generics
 
        for pname, pvalue in portinfo.iteritems():
 
            # add new port
 
            pstr = "Port%s" % pname
 
            codegen_ref.add_port(pstr, None, "Port %s" % pname, type=icon_ref.intercon_type, nocport=pvalue)
 
            for signame, sigval in icon_ref.signals.iteritems():
 
                stmp = get_new_signal(
 
                    name=signame,
 
                    direction=sigval["direction"],
 
                    default_value=intbv(0)[sigval["width"]:],
 
                    description=sigval["description"])
 
                codegen_ref.add_port(pstr, stmp)
 
            # determine if the port is used
 
            if pvalue is None:
 
                penable = 0
 
                paddr = 0
 
            else:
 
                penable = 1
 
                paddr = pvalue
 
            codegen_ref.add_generic("Use_Port%s" % pname, penable, "Is Port%s being used?" % pname)
 
            codegen_ref.add_generic("Dest_Port%s" % pname, paddr, "Dest address in Port%s" % pname)
 
        # 4. Local port
 
        icon_ref = slavewb_intercon()
 
        codegen_ref.add_port("PortLocal", None, "Port Local", type=icon_ref.intercon_type)
 
        for signame, sigval in icon_ref.signals.iteritems():
 
            stmp = get_new_signal(
 
                name=signame,
 
                direction=sigval["direction"],
 
                default_value=intbv(0)[sigval["width"]:],
 
                description=sigval["description"])
 
            codegen_ref.add_port("PortLocal", stmp)
 
 
 
        # 5. Calculate a hash with generics and ports info. This hash will help 
 
        # codegen to establish equivalent router implementations.
 
        codegen_ref.model_hash()
 
 
 
        # 6. Implementation comment
 
        codegen_ref.implementation += "-- Add here implementation code for Router %s" % self.router_ref.name
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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