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

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [ssbccPeripheral.py] - Diff between revs 8 and 9

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 8 Rev 9
################################################################################
################################################################################
#
#
# Copyright 2012-2014, Sinclair R.F., Inc.
# Copyright 2012-2014, Sinclair R.F., Inc.
#
#
################################################################################
################################################################################
 
 
import re
import re
 
 
from ssbccUtil import IsIntExpr
from ssbccUtil import IsIntExpr
from ssbccUtil import IsPosInt
from ssbccUtil import IsPosInt
from ssbccUtil import IsPowerOf2
from ssbccUtil import IsPowerOf2
from ssbccUtil import ParseIntExpr
from ssbccUtil import ParseIntExpr
from ssbccUtil import SSBCCException
from ssbccUtil import SSBCCException
 
 
class SSBCCperipheral:
class SSBCCperipheral:
  """Base class for peripherals"""
  """Base class for peripherals"""
 
 
  def __init__(self,peripheralFile,config,param_list,loc):
  def __init__(self,peripheralFile,config,param_list,loc):
    """
    """
    Prototype constructor.
    Prototype constructor.
    peripheralFile      the full path name of the peripheral source
    peripheralFile      the full path name of the peripheral source
                        Note:  "__file__" doesn't work because 'execfile" and
                        Note:  "__file__" doesn't work because 'execfile" and
                        "exec" are used to load the python script for the
                        "exec" are used to load the python script for the
                        peripheral.
                        peripheral.
    config              the ssbccConfig object for the processor core
    config              the ssbccConfig object for the processor core
    param_list          parameter list for the processor
    param_list          parameter list for the processor
    loc                 file name and line number for error messages
    loc                 file name and line number for error messages
    """
    """
    pass;
    pass;
 
 
  def AddAttr(self,config,name,value,reformat,loc,optFn=None):
  def AddAttr(self,config,name,value,reformat,loc,optFn=None):
    """
    """
    Add attribute to the peripheral:
    Add attribute to the peripheral:
    config      ssbccConfig object for the procedssor core
    config      ssbccConfig object for the procedssor core
    name        attribute name
    name        attribute name
    value       possibly optional value for the attribute
    value       possibly optional value for the attribute
    reformat    regular expression format for the attribute value
    reformat    regular expression format for the attribute value
                Note:  reformat=None means the attribute can only be set to True
                Note:  reformat=None means the attribute can only be set to True
    loc         file name and line number for error messages
    loc         file name and line number for error messages
    optFn       optional function to set stored type
    optFn       optional function to set stored type
                Note:  See IntPow, RateMethod, etc. below for example methods.
                Note:  See IntPow, RateMethod, etc. below for example methods.
    """
    """
    if hasattr(self,name):
    if hasattr(self,name):
      raise SSBCCException('%s repeated at %s' % (name,loc,));
      raise SSBCCException('%s repeated at %s' % (name,loc,));
    if reformat == None:
    if reformat == None:
      if value != None:
      if value != None:
        raise SSBCCException('No parameter allowed for %s at %s' % (name,loc,));
        raise SSBCCException('No parameter allowed for %s at %s' % (name,loc,));
      setattr(self,name,True);
      setattr(self,name,True);
    else:
    else:
      if value == None:
      if value == None:
        raise SSBCCException('%s missing value at %s' % (name,loc,));
        raise SSBCCException('%s missing value at %s' % (name,loc,));
      if not re.match(reformat,value):
      if not re.match(reformat,value):
        raise SSBCCException('I/O symbol at %s does not match required format "%s":  "%s"' % (loc,reformat,value,));
        raise SSBCCException('I/O symbol at %s does not match required format "%s":  "%s"' % (loc,reformat,value,));
      if optFn != None:
      if optFn != None:
        try:
        try:
          value = optFn(value);
          value = optFn(value);
        except SSBCCException,msg:
        except SSBCCException,msg:
          raise SSBCCException('Parameter "%s=%s" at %s:  %s' % (name,value,loc,str(msg),));
          raise SSBCCException('Parameter "%s=%s" at %s:  %s' % (name,value,loc,str(msg),));
        except:
        except:
          raise SSBCCException('Value for "%s" not parsable at %s:  "%s"' % (name,loc,value,));
          raise SSBCCException('Value for "%s" not parsable at %s:  "%s"' % (name,loc,value,));
      setattr(self,name,value);
      setattr(self,name,value);
 
 
  def GenAssembly(self,config):
  def GenAssembly(self,config):
    """
    """
    Virtual method to generate assembly modules associated with the peripheral.
    Virtual method to generate assembly modules associated with the peripheral.
    """
    """
    pass;
    pass;
 
 
  def GenHDL(self,fp,config):
  def GenHDL(self,fp,config):
    """
    """
    Generate the peripheral HDL.
    Generate the peripheral HDL.
    fp          file pointer for the output processor
    fp          file pointer for the output processor
    config      ssbccConfig object for the procedssor core
    config      ssbccConfig object for the procedssor core
    """
    """
    if config.Get('hdl') == 'Verilog':
    if config.Get('hdl') == 'Verilog':
      self.GenVerilog(fp,config);
      self.GenVerilog(fp,config);
    elif config.Get('hdl') == 'VHDL':
    elif config.Get('hdl') == 'VHDL':
      self.GenVHDL(fp,config);
      self.GenVHDL(fp,config);
    else:
    else:
      raise SSBCCException('HDL "%s" not implemented' % config.Get('hdl'));
      raise SSBCCException('HDL "%s" not implemented' % config.Get('hdl'));
 
 
  def GenVerilog(self,fp,config):
  def GenVerilog(self,fp,config):
    """
    """
    Virtual method to generate the Verilog version of the peripheral.
    Virtual method to generate the Verilog version of the peripheral.
    Raise an exception if there is no Verilog version of the peripheral.
    Raise an exception if there is no Verilog version of the peripheral.
    """
    """
    raise Exception('Verilog is not implemented for this peripheral');
    raise Exception('Verilog is not implemented for this peripheral');
 
 
  def GenVerilogFinal(self,config,body):
  def GenVerilogFinal(self,config,body):
    """
    """
    Clean up the peripheral code.
    Clean up the peripheral code.
    Change "$clog2" to "clog2" for simulators and synthesis tools that don't
    Change "$clog2" to "clog2" for simulators and synthesis tools that don't
      recognize or process "$clog2."
      recognize or process "$clog2."
    """
    """
    if config.Get('define_clog2'):
    if config.Get('define_clog2'):
      body = re.sub('\$clog2','clog2',body);
      body = re.sub('\$clog2','clog2',body);
    return body;
    return body;
 
 
  def GenVHDL(self,fp,config):
  def GenVHDL(self,fp,config):
    """
    """
    Virtual method to generate the VHDL version of the peripheral.
    Virtual method to generate the VHDL version of the peripheral.
    Raise an exception if there is no VHDL version of the peripheral.
    Raise an exception if there is no VHDL version of the peripheral.
    """
    """
    raise Exception('VHDL is not implemented for this peripheral');
    raise Exception('VHDL is not implemented for this peripheral');
 
 
  def LoadCore(self,filename,extension):
  def LoadCore(self,filename,extension):
    """
    """
    Read the source HDL for the peripheral from the same directory as the python
    Read the source HDL for the peripheral from the same directory as the python
    script.
    script.
    filename    name for the python peripheral (usually "__file__")
    filename    name for the python peripheral (usually "__file__")
    extension   the string such as ".v" or ".vhd" required by the HDL\n
    extension   the string such as ".v" or ".vhd" required by the HDL\n
    Note:  The '.' must be included in the extension.  For example, the UART
    Note:  The '.' must be included in the extension.  For example, the UART
           peripheral uses '_Rx.v' and '_Tx.v' or similar to invoke the UART_Tx
           peripheral uses '_Rx.v' and '_Tx.v' or similar to invoke the UART_Tx
           and UART_Rx HDL files.
           and UART_Rx HDL files.
    """
    """
    hdlName = re.sub(r'\.py$',extension,filename);
    hdlName = re.sub(r'\.py$',extension,filename);
    fp = open(hdlName,'r');
    fp = open(hdlName,'r');
    body = fp.read();
    body = fp.read();
    fp.close();
    fp.close();
    return body;
    return body;
 
 
  ##############################################################################
  ##############################################################################
  #
  #
  # Methods to supplement python intrisics for the optFn argument of AddAttr
  # Methods to supplement python intrisics for the optFn argument of AddAttr
  #
  #
  # Note:  AddAttr embelleshes exception messages with the symbol name and
  # Note:  AddAttr embelleshes exception messages with the symbol name and
  #        source code line number.
  #        source code line number.
  #
  #
  # Note:  One weird side effect of using lambda expressions is that the
  # Note:  One weird side effect of using lambda expressions is that the
  #        functions won't be recognized unless they're members of the
  #        functions won't be recognized unless they're members of the
  #        SSBCCperipheral class.
  #        SSBCCperipheral class.
  #
  #
  ##############################################################################
  ##############################################################################
 
 
  def FixedPow2(self,config,lowLimit,highLimit,value):
  def IntPow2Method(self,config,value,lowLimit=1,highLimit=None):
    """
    """
    Check the provided constant as a power of 2 between the provided limits.\n
    Return the integer value of the argument if it is a power of 2 between the
    Note:  This differs from InpPow2 in that localparams and constants are
    optional limits (inclusive).  Otherwise throw an error.\n
           permitted.
    Note:  Other than a lower limit of 1 for "lowLimit", IntMethod validates
 
           "lowLimit" and "highLimit".
    """
    """
 
    value = self.IntMethod(config,value,lowLimit,highLimit)
 
    if lowLimit < 1:
 
      raise SSBCCException('Program bug:  lowLimit = %d is less than 1' % lowLimit);
 
    if not IsPowerOf2(value):
 
      raise SSBCCException('Must be a power of 2');
 
    return value;
 
 
 
  def IntMethod(self,config,value,lowLimit=None,highLimit=None):
 
    """
 
    Return the integer value of the argument.  Throw an error if the argument is
 
    unrecognized, not an integer, or is outside the optionally specified range.
 
    """
 
    if (lowLimit != None) and (highLimit != None) and (highLimit < lowLimit):
 
      raise SSBCCException('Program bug:  lowLimit = %d and highLimit = %d conflict' % (lowLimit,highLimit,));
    if re.match(r'L_\w+$',value):
    if re.match(r'L_\w+$',value):
      if not config.IsParameter(value):
      if not config.IsParameter(value):
        raise SSBCCException('Unrecognized parameter');
        raise SSBCCException('Unrecognized parameter');
      ix = [param[0] for param in config.parameters].index(value);
      ix = [param[0] for param in config.parameters].index(value);
      value = config.parameters[ix][1];
      value = config.parameters[ix][1];
    elif re.match(r'C_\w+$',value):
    elif re.match(r'C_\w+$',value):
      if not config.IsConstant(value):
      if not config.IsConstant(value):
        raise SSBCCException('Unrecognized constant');
        raise SSBCCException('Unrecognized constant');
      value = config.constants[value];
      value = config.constants[value];
    if not IsPosInt(value):
 
      raise SSBCCException('Must be a constant positive integer');
 
    value = ParseIntExpr(value);
 
    if not IsPowerOf2(value):
 
      raise SSBCCException('Must be a power of 2');
 
    if not (lowLimit <= value <= highLimit):
 
      raise SSBCCException('Must be between %d and %d inclusive' % (lowLimit,highLimit,));
 
    return value;
 
 
 
  def IntPow2(self,value,minValue=1):
 
    """
 
    Return the integer value of the argument if it is a power of 2.  Otherwise
 
    throw an error.
 
    """
 
    if not IsPosInt(value):
 
      raise SSBCCException('Not a positive integer');
 
    value = ParseIntExpr(value);
    value = ParseIntExpr(value);
    if not IsPowerOf2(value):
    if (lowLimit != None) and value < lowLimit:
      raise SSBCCException('Not a power of 2');
      if lowLimit == 1:
    if value < minValue:
        raise SSBCCException('Must be a positive integer');
      raise SSBCCException('Must be at least %d' % minValue);
      else:
    return value;
        raise SSBCCException('Cannot be less than %d' % lowLimit);
 
    if (highLimit != None) and value > highLimit:
  def PosInt(self,value,maxValue=0):
      raise SSBCCException('Cannot be more than %d' % highLimit);
    """
 
    Return the integer value of the argument unless it is out of bounds.\n
 
    Note:  maxValue=0 means that there is no upper limit.
 
    """
 
    if not IsPosInt(value):
 
      raise SSBCCException('Not a positive integer');
 
    value = ParseIntExpr(value);
 
    if (maxValue != 0) and (value > maxValue):
 
      raise SSBCCException('Out of bounds -- can be at most %d' % maxValue);
 
    return value;
    return value;
 
 
  def RateMethod(self,config,value):
  def RateMethod(self,config,value):
    """
    """
    Return the string to evaluate the provided value or ratio of two values.
    Return the string to evaluate the provided value or ratio of two values.
    The value can be an integer (including underscores) or a parameter.  Ratios
    The value can be an integer (including underscores), a constant, or a
    are restated to do rounding instead of truncation.\n
    parameter.  Ratios are restated to do rounding instead of truncation.\n
    Examples:
    Examples:
      123456
      123456
      123_456
      123_456
      L_DIVISION_RATIO
      L_DIVISION_RATIO
      G_CLOCK_FREQUENCY_HZ/19200
      G_CLOCK_FREQUENCY_HZ/19200
 
      C_CLOCK_FREQUENCY_HZ/19200
      G_CLOCK_FREQUENCY_HZ/L_BAUD_RATE
      G_CLOCK_FREQUENCY_HZ/L_BAUD_RATE
      100_000_000/G_BAUD_RATE
      100_000_000/G_BAUD_RATE
    """
    """
    def TestAndGetValue(self,config,value,position):
    def LocalIntMethod(self,config,value,position=None):
      if IsIntExpr(value):
      try:
        return str(ParseIntExpr(value));
        if config.IsParameter(value):
      elif config.IsConstant(value):
 
        value = config.constants[value];
 
        if not value > 0:
 
          raise SSBCCException('Constant "%s" must be positive');
 
        return str(value);
 
      elif config.IsParameter(value):
 
        return value;
        return value;
      else:
      else:
        raise SSBCCException('%s must be a positive integer or a previously declared positive constant or a parameter', position);
          v = self.IntMethod(config,value,lowLimit=1);
 
          return str(v);
 
      except SSBCCException, msg:
 
        if not position:
 
          raise SSBCCException(msg);
 
        else:
 
          raise SSBCCException('%s in %s' % (msg,position,));
    if value.find('/') < 0:
    if value.find('/') < 0:
      return TestAndGetValue(self,config,value,'Value');
      return LocalIntMethod(self,config,value);
    else:
    else:
      ratearg = re.findall('([^/]+)',value);
      ratearg = re.findall('([^/]+)',value);
      if len(ratearg) != 2:
      if len(ratearg) != 2:
        raise SSBCCException('Only one "/" allowed in expression');
        raise SSBCCException('Only one "/" allowed in expression');
      ratearg[0] = TestAndGetValue(self,config,ratearg[0],'Numerator');
      ratearg[0] = LocalIntMethod(self,config,ratearg[0],'numerator');
      ratearg[1] = TestAndGetValue(self,config,ratearg[1],'Denominator');
      ratearg[1] = LocalIntMethod(self,config,ratearg[1],'denominator');
      return '(%s+%s/2)/%s' % (ratearg[0],ratearg[1],ratearg[1],);
      return '(%s+%s/2)/%s' % (ratearg[0],ratearg[1],ratearg[1],);
 
 
 No newline at end of file
 No newline at end of file
 
  def TimeMethod(self,config,value,lowLimit=None,highLimit=None):
 
    """
 
    Convert the provided time from the specified units to seconds.
 
    """
 
    if not re.match(r'(0|[1-9]\d*)(\.\d*)?(e[+-]?\d+)?[mun]?s$',value):
 
      raise SSBCCException('Malformed time value');
 
    if value[-2:] == 'ms':
 
      v = float(value[:-2]) * 1.e-3;
 
    elif value[-2:] == 'us':
 
      v = float(value[:-2]) * 1.e-6;
 
    elif value[-2:] == 'ns':
 
      v = float(value[:-2]) * 1.e-9;
 
    else:
 
      v = float(value[:-1]);
 
    if (lowLimit != None) and (v < lowLimit):
 
      raise SSBCCException('%s must be %s or greater' % (v,lowLimit,));
 
    if (highLimit != None) and (v > highLimit):
 
      raise SSBCCException('%s must be %s or smaller' % (v,highLimit,));
 
    return v;
 
 
 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.