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

Subversion Repositories nocmodel

[/] [nocmodel/] [trunk/] [nocmodel/] [noc_tbm_base.py] - Rev 4

Compare with Previous | Blame | View Log

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
#
# NoC TBM simulation support
#   This module declares classes for Transaction Based Model simulation
#
# Author:  Oscar Diaz
# Version: 0.2
# Date:    17-03-2011
 
#
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software  Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA  02111-1307  USA
#
 
#
# Changelog:
#
# 03-03-2011 : (OD) initial release
#
 
"""
===============================
NoCmodel TBM simulation support
===============================
 
This module declares classes for Transaction Based Model simulation
 
* Class 'noc_tbm_base'
* Class 'noc_tbm_simulation'
* Class 'noc_tbm_errcodes'
"""
 
import networkx as nx
import myhdl
import logging
 
from noc_base import *
 
import inspect
 
class noc_tbm_base():
    """
    Base class for NoC TBM simulator.
 
    This class add methods to a NoC object, required for the TBM model. Each 
    derived class must override the methods:
 
    * __init__() : its constructor contains the object TBM model (data 
      structures, generators, etc).
    * send() 
    * recv()
 
    Other methods are related to simulation configuration and logging support.
    """
    def __init__(self):
        self.log = logging.getLogger()
        self.logname = "BASECLASS"
        self.generators = []
        self.tracesend = []
        self.tracerecv = []
 
    def __repr__(self):
        if self.logname != "":
            return "<%s '%s'>" % (self.__class__.__name__, self.logname)
        else:
            return "<%s at '%d'>" % (self.__class__.__name__, id(self))
 
    def get_generators(self):
        return self.generators
 
    def _do_build_generators(self):
        self.generators.extend(self.build_generators())
 
    # TBM main: every object must define this functions
    def send(self, src, dest, data, addattrs=None):
        """
        SEND method: this method MUST be called only by the local
        object who wants to start a transaction.
 
        This function will call the recv method in the right object.
 
        Arguments:
        * src: source object (or router address) that call this method, i.e. the
          object that starts the transaction.
        * dest: destination object (or router address) that receive the data in
          the transaction. This method will call dest' recv method.
        * data: data to be sent. Can be anything, but normally is an object of
          type packet.
        * addattrs: optional dictionary with additional arguments
 
        Return: Must return a number: 0 for everything OK, != 0 to show an error
            relevant to the caller, an exception in case of attribute error
        """
        self.debug("-> send( %s , %s , %s , %s )" % (repr(src), repr(dest), repr(packet), repr(addattrs)))
        return noc_tbm_errcodes.not_implemented
 
    def recv(self, src, dest, data, addattrs=None):
        """
        RECV method: this method MUST be called only by the send
        method of the object who started the transaction.
 
        Arguments:
        * src: source object (or router address) that call this method, i.e. the
          object that starts the transaction.
        * dest: destination object (or router address) that receive the data in
          the transaction. This method will call dest' recv method.
        * data: data to be sent. Can be anything, but normally is an object of
          type packet.
        * addattrs: optional dictionary with additional arguments
 
        @return Must return a number: 0 for everything OK, != 0 to show an error
            relevant to the caller, an exception in case of attribute error
        """
        self.debug("-> recv( %s , %s , %s , %s )" % (repr(src), repr(dest), repr(packet), repr(addattrs)))
        return noc_tbm_errcodes.not_implemented
 
    # logging methods (only use 4 levels)
    def debug(self, msg, *args, **kwargs):
        self.log.debug(msg, extra={"objname": self.logname}, *args, **kwargs)
    def info(self, msg, *args, **kwargs):
        self.log.info(msg, extra={"objname": self.logname}, *args, **kwargs)
    def warning(self, msg, *args, **kwargs):
        self.log.warning(msg, extra={"objname": self.logname}, *args, **kwargs)
    def error(self, msg, *args, **kwargs):
        self.log.error(msg, extra={"objname": self.logname}, *args, **kwargs)
 
    # special log
    def debugstate(self):
        self.debug(" '%s' object state: " % repr(self))
        for i in dir(self):
            # exclude hidden attributes
            if i[0] == "_":
                continue
            self.debug("     ['%s'] = %s " % (i, repr(getattr(self, i))))
    def generators_info(self):
        self.debug(" Registered generators for '%s': " % repr(self))
        for g in self.generators:
            self.debug("     '%s': %s" % (getattr(g, "name", "-GEN-"), repr(g)))
 
class noc_tbm_simulation():
    """
    NoC TBM simulator object
 
    This class manages the MyHDL simulation on a NoC object and its logging 
    support.
 
    Attributes:
    * noc_ref: reference to NoC model to simulate
    * log_file: optional file to save the simulation log
    * log_level: optional logging level for the previous file
    * kwargs: optional attributes to add to this object
    """
    def __init__(self, noc_ref, log_file=None, log_level=logging.INFO, **kwargs):
        if isinstance(noc_ref, noc):
            self.noc_ref = noc_ref
        else:
            raise TypeError("This class needs a noc object as constructor argument.")
        # configure logging system
        # log errors to console, custom log to log_file if specified
        addmsg = ""
        self.log = logging.getLogger()
        self.log.setLevel(log_level)
        console_hdl = logging.StreamHandler()
        console_hdl.setLevel(logging.WARNING)
        class SimTimeFilter(logging.Filter):
            def filter(self, record):
                record.myhdltime = myhdl.now()
                return True
        self.log.addFilter(SimTimeFilter())
        self.noc_formatter = logging.Formatter("%(myhdltime)4d:%(levelname)-5s:%(objname)-16s - %(message)s")
        console_hdl.setFormatter(self.noc_formatter)
        self.log.addHandler(console_hdl)
        if log_file != None:
            file_hdl = logging.FileHandler(log_file, 'w')
            file_hdl.setLevel(log_level)
            file_hdl.setFormatter(self.noc_formatter)
            self.log.addHandler(file_hdl)
            addmsg = "and on file (%s) level %s" % (log_file, logging._levelNames[log_level])
        # ready to roll
        self.debug("Logging enabled! Running log on console level WARNING %s" % addmsg)
 
    def configure_simulation(self, max_time=None, add_generators=[]):
        """
        Configure MyHDL simulation.
 
        Arguments:
        * max_time: optional max time to simulate. None means simulation 
          without time limit.
        * add_generators: external MyHDL generators to add to the simulation
        """
        # myhdl simulation: extract all generators and prepare 
        # arguments
        for obj in self.noc_ref.all_list():
            prevcount = len(add_generators)
            add_generators.extend(obj.tbm.get_generators())
            #self.debug("configure_simulation: adding %d generators from object %s" % (len(add_generators)-prevcount, repr(obj)))
            if isinstance(obj, ipcore):
                add_generators.extend(obj.channel_ref.tbm.get_generators())
                #self.debug("configure_simulation: plus ipcore channel: adding %d generators from object %s" % (len(add_generators)-prevcount, repr(obj.channel_ref)))
        # --------------------------------
        # debug info
        # TODO: try to get info about generators, particularly obtain origin 
        # info about @always and @always_comb generators
        #self.debug("configure_simulation: list of generators: (count = %d)" % len(add_generators))
        #for genl in add_generators:
            #if not isinstance(genl, list):
                #gen2 = [genl]
            #else:
                #gen2 = genl
                #self.debug("configure_simulation:   generator list '%s'" % repr(genl))
            #for gen in gen2:
                #self.debug("configure_simulation:   generator '%s'" % repr(gen))
                #try:
                    #self.debug("configure_simulation:   inspect info name '%s'" % gen.gen.__name__)
                    #self.debug("configure_simulation:   inspect info locals '%s'" % repr(gen.gen.gi_frame.f_locals.keys()))
                    #for k, v in gen.gen.gi_frame.f_locals.iteritems():
                        #self.debug("configure_simulation:   inspect info locals[%s] '%s'" % (k, repr(v)))
                    #if gen.gen.__name__ == "genfunc":
                        #self.debug("configure_simulation:   inspect info deep name '%s'" % gen.func.__name__)
                #except:
                    #pass
        # --------------------------------
        self.sim_object = myhdl.Simulation(*add_generators)
        self.sim_duration = max_time
        self.debug("configure_simulation: will run until simulation time '%d'" % max_time)
 
    def run(self):
        """
        Run MyHDL simulation
        """
        self.debug("Start simulation")
        self.sim_object.run(self.sim_duration)
        self.debug("End simulation")
 
    # custom logging methods (only use 4 levels)
    def debug(self, msg, *args, **kwargs):
        self.log.debug(msg, extra={"objname": "TopNoC"}, *args, **kwargs)
    def info(self, msg, *args, **kwargs):
        self.log.info(msg, extra={"objname": "TopNoC"}, *args, **kwargs)
    def warning(self, msg, *args, **kwargs):
        self.log.warning(msg, extra={"objname": "TopNoC"}, *args, **kwargs)
    def error(self, msg, *args, **kwargs):
        self.log.error(msg, extra={"objname": "TopNoC"}, *args, **kwargs)
 
    # special log filter: log individually by object name
    def configure_byobject_logging(self, basefilename="", log_level=logging.INFO):
        """
        Special log filter: log individually by object name
 
        Arguments:
        * basefilename: generated filenames will start with this string
        * log_level: optional logging level for previous files
        """
        # base filter
        class ObjFilter(logging.Filter):
            def __init__(self, basename):
                self.basename = basename
            def filter(self, record):
                if record.objname == self.basename:
                    return True
                return False
        # need a handler for each object
        for obj in self.noc_ref.all_list():
            newfilter = ObjFilter(obj.tbm.logname)
            newhandler = logging.FileHandler("%s_%s.log" % (basefilename, obj.tbm.logname), "w")
            newhandler.setLevel(log_level)
            newhandler.addFilter(newfilter)
            newhandler.setFormatter(self.noc_formatter)
            self.log.addHandler(newhandler)
        # Transactions logger
        class TransFilter(logging.Filter):
            def filter(self, record):
                if record.message.find("->") == 0:
                    return True
                return False
        newhandler = logging.FileHandler("%s_transactions.log" % basefilename, "w")
        newhandler.setLevel(log_level)
        newhandler.addFilter(TransFilter())
        newhandler.setFormatter(self.noc_formatter)
        self.log.addHandler(newhandler)
        # TopNoC will not be added to this set
        self.debug("Special logging enabled. basefilename=%s level %s" % (basefilename, logging._levelNames[log_level]))
 
class noc_tbm_errcodes():
    """
    Common error codes definition
    """
    no_error = 0
    full_fifo = -1
    packet_bad_data = -2
    tbm_badcall_recv = -3
    tbm_badcall_send = -4
    tbm_busy_channel = -5
    not_implemented = -15
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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