Commit a3f7f58e authored by Eyesisbox Elphel's avatar Eyesisbox Elphel
Browse files

continue on DDR initialization

parent 496a0d6f
Loading
Loading
Loading
Loading
+394 −13

File changed.

Preview size limit exceeded, changes collapsed.

+212 −211

File changed.

Preview size limit exceeded, changes collapsed.

ezynq_ddrcfg_defs.py

0 → 100755
+166 −0
Original line number Original line Diff line number Diff line
#!/usr/bin/env python
# Copyright (C) 2013, Elphel.inc.
# Definitions of configuration parameters for DDR memory 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2013, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
#Use 'TYPE':'I' for decimal output, 'H' - for hex. On input both are accepted
DDR_CFG_DEFS=[
    {'NAME':'ENABLE',          'CONF_NAME':'CONFIG_EZYNQ_DDR_ENABLE','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':True,
                'DESCRIPTION':'Enable DDR memory'},              
    {'NAME':'MEMORY_TYPE',     'CONF_NAME':'CONFIG_EZYNQ_DDR_MEMORY_TYPE','TYPE':('DDR3','DDR3L','DDR2','LPDDR2'),'MANDATORY':True,'DERIVED':False,'DEFAULT':'DDR3',
                'DESCRIPTION':'DDR memory type'},              
    {'NAME':'TARGET_FREQ_MHZ', 'CONF_NAME':'CONFIG_EZYNQ_DDR_TARGET_FREQ_MHZ','TYPE':'F','MANDATORY':True,'DERIVED':True,'DEFAULT':533.333333,
                'DESCRIPTION':'Target DDR clock frequency in MHz (actual frequency will depend on the clock/clock muxes)'},              
    {'NAME':'FREQ_MHZ',        'CONF_NAME':'CONFIG_EZYNQ_DDR_FREQ_MHZ','TYPE':'F','MANDATORY':True,'DERIVED':True,'DEFAULT':533.333333,
                'DESCRIPTION':'Actual DDR clock frequency in MHz, may be derived form CONFIG_EZYNQ_DDR_TARGET_FREQ_MHZ and clock multiplexer settings'},              
    {'NAME':'CL',              'CONF_NAME':'CONFIG_EZYNQ_DDR_CL','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':7,
                'DESCRIPTION':'CAS read latency (in tCK)'},              
    {'NAME':'AL',              'CONF_NAME':'CONFIG_EZYNQ_DDR_AL','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':0,
                'DESCRIPTION':'Posted CAS additive latency (in tCK)'},              
    {'NAME':'CWL',             'CONF_NAME':'CONFIG_EZYNQ_DDR_CWL','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':6,
                'DESCRIPTION':'CAS write latency (in tCK)'},              
    {'NAME':'RCD',             'CONF_NAME':'CONFIG_EZYNQ_DDR_RCD','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':7,
                'DESCRIPTION':'RAS to CAS delay (in tCK)'},              
    {'NAME':'RP',              'CONF_NAME':'CONFIG_EZYNQ_DDR_RP','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':7,
                'DESCRIPTION':'Row Precharge time (in tCK)'},              
    {'NAME':'T_RC',            'CONF_NAME':'CONFIG_EZYNQ_DDR_T_RC','TYPE':'F','MANDATORY':True,'DERIVED':False,'DEFAULT':48.75,
                'DESCRIPTION':'Activate to Activate or Refresh command period (ns)'},              
    {'NAME':'T_RAS_MIN',       'CONF_NAME':'CONFIG_EZYNQ_DDR_T_RAS_MIN','TYPE':'F','MANDATORY':True,'DERIVED':False,'DEFAULT':35.0,
                'DESCRIPTION':'Minimal Row Active time (ns)'},              
    {'NAME':'T_FAW',           'CONF_NAME':'CONFIG_EZYNQ_DDR_T_FAW','TYPE':'F','MANDATORY':True,'DERIVED':False,'DEFAULT':40.0,
                'DESCRIPTION':'Minimal running window for 4 page activates (ns)'},   
    {'NAME':'T_RFC',           'CONF_NAME':'CONFIG_EZYNQ_DDR_T_RFC','TYPE':'F','MANDATORY':True,'DERIVED':False,'DEFAULT':350.0,
                'DESCRIPTION':'Minimal Refresh-to-Activate or Refresh command period (ns)'},   
    {'NAME':'T_WR',           'CONF_NAME':'CONFIG_EZYNQ_DDR_T_WR','TYPE':'F','MANDATORY':True,'DERIVED':False,'DEFAULT':15.0,
                'DESCRIPTION':'Write recovery time (ns)'},   
    {'NAME':'BANK_ADDR_COUNT', 'CONF_NAME':'CONFIG_EZYNQ_DDR_BANK_ADDR_COUNT','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':3,
                'DESCRIPTION':'Number of DDR banks'},              
    {'NAME':'ROW_ADDR_COUNT',  'CONF_NAME':'CONFIG_EZYNQ_DDR_ROW_ADDR_COUNT','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':15,
                'DESCRIPTION':'Number of DDR banks'},              
    {'NAME':'COL_ADDR_COUNT',  'CONF_NAME':'CONFIG_EZYNQ_DDR_COL_ADDR_COUNT','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':10,
                'DESCRIPTION':'Number of DDR banks'},              
    {'NAME':'ECC',             'CONF_NAME':'CONFIG_EZYNQ_DDR_ECC','TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':False,
                'DESCRIPTION':'Enable ECC for the DDR memory'},
    {'NAME':'BUS_WIDTH',       'CONF_NAME':'CONFIG_EZYNQ_DDR_BUS_WIDTH','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':32,
                'DESCRIPTION':'SoC DDR bus width'},
    {'NAME':'BL',              'CONF_NAME':'CONFIG_EZYNQ_DDR_BL','TYPE':(8,4),'MANDATORY':True,'DERIVED':False,'DEFAULT':8, # DDR2 may have different lengths?
                'DESCRIPTION':'Burst length'},
    {'NAME':'HIGH_TEMP',       'CONF_NAME':'CONFIG_EZYNQ_DDR_HIGH_TEMP','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
                'DESCRIPTION':'High temperature (influences refresh)'},
    {'NAME':'T_REFI_US',           'CONF_NAME':'CONFIG_EZYNQ_DDR_T_REFI_US','TYPE':'F','MANDATORY':False,'DERIVED':False,'DEFAULT':7.8,
                'DESCRIPTION':'Maximal average periodic refresh, microseconds. Will be automatically reduced if high temperature option is selected'},              

    {'NAME':'PARTNO',          'CONF_NAME':'CONFIG_EZYNQ_DDR_PARTNO','TYPE':'T','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
                'DESCRIPTION':'Memory part number  (currently not used - derive some parameters later)'},
    {'NAME':'DRAM_WIDTH',      'CONF_NAME':'CONFIG_EZYNQ_DDR_DRAM_WIDTH','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':16,
                'DESCRIPTION':'Memory chip bus width'},
    {'NAME':'SPEED_BIN',       'CONF_NAME':'CONFIG_EZYNQ_DDR_SPEED_BIN','TYPE':'T','MANDATORY':True,'DERIVED':False,'DEFAULT':'DDR3_1066F',
                'DESCRIPTION':'Memory speed bin (currently not used - derive timing later)'},
    {'NAME':'TRAIN_WRITE_LEVEL','CONF_NAME':'CONFIG_EZYNQ_DDR_TRAIN_WRITE_LEVEL','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
                'DESCRIPTION':'Automatically train write leveling during initialization'},
    {'NAME':'TRAIN_READ_GATE', 'CONF_NAME':'CONFIG_EZYNQ_DDR_TRAIN_READ_GATE','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
                'DESCRIPTION':'Automatically train read gate timing during initialization'},
    {'NAME':'TRAIN_DATA_EYE',  'CONF_NAME':'CONFIG_EZYNQ_DDR_TRAIN_DATA_EYE','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
                'DESCRIPTION':'Automatically train data eye during initialization'},
    {'NAME':'CLOCK_STOP_EN',   'CONF_NAME':'CONFIG_EZYNQ_DDR_CLOCK_STOP_EN','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
                'DESCRIPTION':'Enable clock stop'},
    {'NAME':'INTERNAL_VREF',   'CONF_NAME':'CONFIG_EZYNQ_DDR_USE_INTERNAL_VREF','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
                'DESCRIPTION':'Use internal Vref'},
    {'NAME':'OUT_SLEW_NEG',    'CONF_NAME':'CONFIG_EZYNQ_DDR_OUT_SLEW_NEG','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':26,
                'DESCRIPTION':'Slew rate negative for DDR address/clock outputs'},
    {'NAME':'OUT_SLEW_POS',    'CONF_NAME':'CONFIG_EZYNQ_DDR_OUT_SLEW_POS','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':26,
                'DESCRIPTION':'Slew rate positive for DDR address/clock outputs'},
    {'NAME':'OUT_DRIVE_NEG',   'CONF_NAME':'CONFIG_EZYNQ_DDR_OUT_DRIVE_NEG','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':12,
                'DESCRIPTION':'Drive strength negative for DDR address/clock outputs'},
    {'NAME':'OUT_DRIVE_POS',   'CONF_NAME':'CONFIG_EZYNQ_DDR_OUT_DRIVE_POS','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':28,
                'DESCRIPTION':'Drive strength positive for DDR address/clock outputs'},
    {'NAME':'BIDIR_SLEW_NEG',    'CONF_NAME':'CONFIG_EZYNQ_DDR_BIDIR_SLEW_NEG','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':31,
                'DESCRIPTION':'Slew rate negative for driving DDR DQ/DQS signals'},
    {'NAME':'BIDIR_SLEW_POS',    'CONF_NAME':'CONFIG_EZYNQ_DDR_BIDIR_SLEW_POS','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':6,
                'DESCRIPTION':'Drive strength positive for driving DDR DQ/DQS signals'},
    {'NAME':'BIDIR_DRIVE_NEG',   'CONF_NAME':'CONFIG_EZYNQ_DDR_BIDIR_DRIVE_NEG','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':12,
                'DESCRIPTION':'Drive strength negative for driving DDR DQ/DQS signals'},
    {'NAME':'BIDIR_DRIVE_POS',   'CONF_NAME':'CONFIG_EZYNQ_DDR_BIDIR_DRIVE_POS','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':28,
                'DESCRIPTION':'Slew rate positive for driving DDR DQ/DQS signals'},
    {'NAME':'RTP',             'CONF_NAME':'CONFIG_EZYNQ_DDR_RTP','TYPE':'I','MANDATORY':False,'DERIVED':False,'DEFAULT':4,
                'DESCRIPTION':'Minimal Read-to-Precharge time (in tCK). Will use max of this and CONFIG_EZYNQ_DDR_T_RTP/CONFIG_EZYNQ_DDR_T_CK'},              
    {'NAME':'T_RTP',           'CONF_NAME':'CONFIG_EZYNQ_DDR_T_RTP','TYPE':'F','MANDATORY':False,'DERIVED':False,'DEFAULT':7.5,
                'DESCRIPTION':'Minimal Read-to-Precharge time  (ns). Will use max of this divided by CONFIG_EZYNQ_DDR_T_CK and CONFIG_EZYNQ_DDR_RTP'},   
    {'NAME':'WTR',             'CONF_NAME':'CONFIG_EZYNQ_DDR_WTR','TYPE':'I','MANDATORY':False,'DERIVED':False,'DEFAULT':4,
                'DESCRIPTION':'Minimal Write-to-Read time (in tCK). Will use max of this and CONFIG_EZYNQ_DDR_T_WTR/CONFIG_EZYNQ_DDR_T_CK'},              
    {'NAME':'T_WTR',           'CONF_NAME':'CONFIG_EZYNQ_DDR_T_WTR','TYPE':'F','MANDATORY':False,'DERIVED':False,'DEFAULT':7.5,
                'DESCRIPTION':'Minimal Write-to-Read time  (ns). Will use max of this divided by CONFIG_EZYNQ_DDR_T_CK and CONFIG_EZYNQ_DDR_WTR'},   
    {'NAME':'XP',             'CONF_NAME':'CONFIG_EZYNQ_DDR_XP','TYPE':'I','MANDATORY':False,'DERIVED':False,'DEFAULT':4,
                'DESCRIPTION':'Minimal Minimal time from power down (DLL on) to any operation (in tCK)'},              
    {'NAME':'T_DQSCK_MAX',           'CONF_NAME':'CONFIG_EZYNQ_DDR_T_DQSCK_MAX','TYPE':'F','MANDATORY':False,'DERIVED':False,'DEFAULT':7.5,
                'DESCRIPTION':'DQS output access time from CK (ns). Used for LPDDR2 '},   
              
# CONFIG_EZYNQ_DDR_RTP = 4
# CONFIG_EZYNQ_DDR_T_RTP = 7.5
# CONFIG_EZYNQ_DDR_WTR = 4
# CONFIG_EZYNQ_DDR_T_WTR = 7.5
# CONFIG_EZYNQ_DDR_XP = 4 # power down (DLL on) to any operation, cycles
# CONFIG_EZYNQ_DDR_T_DQSCK_MAX = 5.5 # (LPDDR2 only)
              
              
]


#TODO make some of (possibly) derived, leave '_T_' for ns only!
# CONFIG_EZYNQ_DDR_FREQ_MHZ = 533.333333 *
# CONFIG_EZYNQ_DDR_CL = 7  *
# CONFIG_EZYNQ_DDR_CWL = 6  *
# CONFIG_EZYNQ_DDR_RCD = 7 (was CONFIG_EZYNQ_DDR_T_RCD = 7) *
# CONFIG_EZYNQ_DDR_RP = 7 (was CONFIG_EZYNQ_DDR_T_RP = 7) *
# CONFIG_EZYNQ_DDR_T_RC = 48.75 *
# CONFIG_EZYNQ_DDR_T_RAS_MIN = 35.0 *
# CONFIG_EZYNQ_DDR_T_FAW = 40.0 *
# CONFIG_EZYNQ_DDR_T_RFC = 350.0
# CONFIG_EZYNQ_DDR_T_WR =  15.0
# CONFIG_EZYNQ_DDR_RTP = 4
# CONFIG_EZYNQ_DDR_tRTP = 7.5
# CONFIG_EZYNQ_DDR_WTR = 4
# CONFIG_EZYNQ_DDR_tWTR = 7.5


# CONFIG_EZYNQ_DDR_AL = 0 *
# CONFIG_EZYNQ_DDR_BANK_ADDR_COUNT = 3 *
# CONFIG_EZYNQ_DDR_ROW_ADDR_COUNT = 15 *
# CONFIG_EZYNQ_DDR_COL_ADDR_COUNT = 10 *

# CONFIG_EZYNQ_DDR_ENABLE = 1          *
# CONFIG_EZYNQ_DDR_MEMORY_TYPE = DDR3  *
# CONFIG_EZYNQ_DDR_ECC = Disabled      *
# CONFIG_EZYNQ_DDR_BUS_WIDTH = 32      *
# CONFIG_EZYNQ_DDR_BL = 8              *
# CONFIG_EZYNQ_DDR_T_REFI_US = 7.8 *
# CONFIG_EZYNQ_DDR_HIGH_TEMP = Normal  *
# CONFIG_EZYNQ_DDR_PARTNO = MT41K256M16RE-125 *
# CONFIG_EZYNQ_DDR_DRAM_WIDTH = 16     *
# CONFIG_EZYNQ_DDR_SPEED_BIN = DDR3_1066F *
# CONFIG_EZYNQ_DDR_TRAIN_WRITE_LEVEL = 0
# CONFIG_EZYNQ_DDR_TRAIN_READ_GATE = 0
# CONFIG_EZYNQ_DDR_TRAIN_DATA_EYE = 0
# CONFIG_EZYNQ_DDR_CLOCK_STOP_EN = 0
# CONFIG_EZYNQ_DDR_USE_INTERNAL_VREF = 0

#CONFIG_EZYNQ_DDR_DEVICE_CAPACITY_MBITS = 4096 - can be calculated

ezynq_ddriob_def.py

0 → 100644
+207 −0

File added.

Preview size limit exceeded, changes collapsed.

+193 −0
Original line number Original line Diff line number Diff line
#!/usr/bin/env python
# Copyright (C) 2013, Elphel.inc.
# process configuration of features
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2013, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
class EzynqFeatures:
    #Modify for this class
    ERRORS={
            'ERR_NOT_A_VARIANT':   'Specified value is not a valid variant',
            'ERR_NOT_AN_INTEGER':  'Value is not an integer',
            'ERR_NOT_A_FLOAT':     'Value is not a float',
            'ERR_NOT_A_BOOLEAN':   'Value is not a boolean'
            }
    BOOLEANS=(('0','FALSE','DISABLE','DISABLED','N'),
              ('1','TRUE', 'ENABLE','ENABLED','Y'))
#  defines - a list, order determines HTML output order
#  Each element has fields:
#  'NAME' - unique name to access this parameter
#  'CONF_NAME' - how it appears in configuration file, '@' may be replaced by str(channel)
#  'TYPE' - either "I" for integer, F - float, T - text, B- boolean (may be false/true, 0/1 or enable{d}/disable{d} or tuple with valid options for value
#  'MANDATORY' - boolean: this parameter is mandatory (either directly specified or derived from some others)
#  'DERIVED' - TBD later
#  'DEFAULT' - default value (to be suggested on error? Use if not mandatory parameter?
#  'DESCRIPTION' - Parameter description - use in error message?
    def _choice_val(self,t,value):
        if isinstance(t,tuple) :
            for c in t:
                if isinstance(c,int):
                    try:
                        if (c==int(value,0)):
                            return c
                    except:
                        pass
                elif isinstance(c,float):
                    try:
                        if (c==float(value)):
                            return c
                    except:
                        pass
                elif isinstance(c, bool):
                    if value in self.BOOLEANS[1]:
                        return True
                    elif value in self.BOOLEANS[0]:
                        return False
                elif isinstance(c, str):
                    return value
            else:
                return None
                         
        
 
    def __init__(self,defines,channel=0):
        self.defs={}
        for i,feature in enumerate(defines):
            self.defs[feature['NAME']]=feature
            self.defs[feature['NAME']]['INDEX']=i
        self.channel=channel
        self.pars={}
        self.config_names={}
        self.defined=[]
        for name in self.defs:
            cn=self.defs[name];
            self.config_names[cn['CONF_NAME'].replace('@',str(channel))]=name
                            
            
        
    def parse_features(self,raw_configs):
        for line in raw_configs:
            conf_name =  line['KEY']
            value =      line['VALUE']
            value=str(value).upper()
            try:
                name=self.config_names[conf_name]
            except:
                continue
            feature= self.defs[name]
            if (value=='HELP'):
                try:
                    print conf_name+': '+feature['DESCRIPTION']
                except:
                    print conf_name+': description is not available'
                continue
            if isinstance(feature['TYPE'], tuple):
                val=self._choice_val(feature['TYPE'],value)
                if val==None:
                    raise Exception(self.BOOLEANS['ERR_NOT_A_VARIANT']+': '+line['VALUE'] +' is not a valid variant for parameter '+
                                    conf_name+'. Valid are:'+str(feature['TYPE']))
                else:
                    value=val
            elif (feature['TYPE']=='I') or (feature['TYPE']=='H'):
                try:
                    value= int(value,0)
                except:
                    raise Exception(self.ERRORS['ERR_NOT_AN_INTEGER']+': '+line['VALUE'] +' is not a valid INTEGER value for parameter '+ conf_name)
            elif (feature['TYPE']=='F'):
                try:
                    value= float(value)
                except:
                    raise Exception(self.ERRORS['ERR_NOT_A_FLOAT']+': '+line['VALUE'] +' is not a valid FLOAT value for parameter '+ conf_name)
            elif (feature['TYPE']=='B'):
                if value in self.BOOLEANS[1]:
                    value=True
                elif value in self.BOOLEANS[0]:
                    value=False
                else:
#                    print line['VALUE'],type(line['VALUE'])
#                    print line['VALUE'] in self.BOOLEANS[1]
                    raise Exception(self.ERRORS['ERR_NOT_A_BOOLEAN']+': '+line['VALUE'] +' is not a valid boolean value for parameter '+ conf_name+
                                    '. Valid for "True" are:'+str(self.BOOLEANS[1])+', for "False" - '+str(self.BOOLEANS[0]))
            elif (feature['TYPE']=='T'):
                pass #keep string value
            self.pars[name]=value
            self.defined.append(name)
    #check after calculating derivative parameters                    
    def check_missing_features(self):
        all_set=True
        for name in self.defs:
            if (not name in self.pars):
                if self.defs[name]['MANDATORY']:
                    all_set=False
                    print "Configuration file is missing mandatory parameter "+self.defs[name]['CONF_NAME']+': '+self.defs[name]['DESCRIPTION']
                else:
                    # use default parameter
#                    print 'Adding default : ',name,'=', self.defs[name]['DEFAULT']
                    self.pars[name]=self.defs[name]['DEFAULT']
        return all_set
    def get_par_names(self):
#        name_offs=sorted([(name,self.registers[name]['OFFS']) for name in self.registers], key = lambda l: l[1])
#        print '---self.registers=',self.registers 
#        unsorted_name_offs=[(name,self.defs[name]['OFFS']) for name in self.registers]
#        print '---unsorted_name_offs=',unsorted_name_offs 
#        name_offs=sorted(unsorted_name_offs, key = lambda l: l[1]) 
#        print '---name_offs=',name_offs 
#        return [n for n in name_offs]
# sort register names in the order of addresses
#        name_index=sorted([(name,self.defs[name]['INDEX']) for name in self.pars], key = lambda l: l[1])
#        return [n for n in sorted([(name,self.defs[name]['OFFS']) for name in self.registers], key = lambda l: l[1])]
        return [n[0] for n in sorted([(name,self.defs[name]['INDEX']) for name in self.pars], key = lambda l: l[1])]
#TODO: Use SELECT for options?
    def get_par_value(self,name):
        try:
            return self.pars[name]
        except:
            print 'name=',name
            print self.pars
            raise Exception (name+' not found in self.pars')               
    def html_list_features(self,html_file):
        html_file.write('<table border="1">\n')
        html_file.write('<tr><th>Configuration name</th><th>Value</th><th>Type/<br/>Choices</th><th>Mandatory</th><th>Derived</th><th>Default</th><th>Description</th></tr>\n')
#        print  self.get_par_names()
#        for name in self.pars:
        for name in self.get_par_names():
#            name=    self.config_names[conf_name]
            feature= self.defs[name]
            value=   self.get_par_value(name)
            if isinstance(value,int):
                if (feature['TYPE']=='H'):
                    value=hex(value)
                else:
                    value=str(value)
            derived= not name in self.defined
            if isinstance (feature['TYPE'],tuple):
                par_type='<select>\n'
                for t in feature['TYPE']:
                    par_type+='  <option>'+str(t)+'</option>\n'
#                    par_type+=('','<br/>')[i>0]+str(t)
                par_type+='</select>\n'    
            else:        
                par_type={'H':'Integer','I':'Integer','F':'Float','B':'Boolean','T':'Text'}[feature['TYPE']]

            html_file.write('<tr><th>'+feature['CONF_NAME']+'</th><td>'+str(value)+'</td><td>'+par_type+
                            '</td><td>'+('-','Y')[feature['MANDATORY']]+'</td><td>'+('-','Y')[derived]+'</td><td>'+str(feature['DEFAULT'])+'</td><td>'+feature['DESCRIPTION']+'</td></tr>\n')
        html_file.write('</table>\n')

        
 No newline at end of file
Loading