Commit 8de61d31 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

next snapshot, implemented more expression types in parameter parsing

parent 21e45a99
Loading
Loading
Loading
Loading
+175 −27
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ __status__ = "Development"
import re
import os
import string
from verilog_utils import getParWidth 
class VerilogParameters(object): #this is Borg
    __shared_state = {}
    def __init__(self, parameters=None):
@@ -94,17 +95,32 @@ class ImportVerilogParameters(object):
                return c
            except:
                return None
        def skipWS(start=0):
            cp[0]=start
            while (cp[0]<len(line)) and (line[cp[0]] in string.whitespace):
                cp[0]+=1
            return cp[0]    
                    
        def useBest(first, second):
            if first is None:
                return second
            elif second is None:
                return first
            elif first[2]>second[2]:
                return first
            else:
                return second

        def parseString():
            if line[0]!="\"":
        def parseString(start=0):
            if line[start]!="\"":
                return None
            endPointer=line[1:].find("\"")
            endPointer=line[start+1:].find("\"")
            if (endPointer<0):
                endPointer=len(line)
            else:
                endPointer+=1
                endPointer+=2
            return (line[1:endPointer],"STRING",endPointer)

        def parseUnsignedNumber(start=0):
            dChars=string.digits+"_"
            cp[0]=start;
@@ -122,6 +138,7 @@ class ImportVerilogParameters(object):
            if cp[0] <= start:
                return None
            return (d,"INTEGER",cp[0])
        
        def parseUnsignedFraction(start=0):
            dChars=string.digits+"_"
            cp[0]=start;
@@ -145,6 +162,7 @@ class ImportVerilogParameters(object):
            if cp[0] <= start+1:
                return None
            return (d/k,"REAL",cp[0])
        
        def parseSign(start=0):
            sign=1
            cp[0]=start;
@@ -158,6 +176,7 @@ class ImportVerilogParameters(object):
            else: 
                cp[0]-=1
            return sign
        
        def parseBase(start=0):
            cp[0]=start
            c=getNextChar()
@@ -197,11 +216,10 @@ class ImportVerilogParameters(object):
            else:
                return ((un[0]+fp[0])*sign,fp[1],fp[2])
        
        
        def parseNumber(start=0):
            #try number of bits prefix
            sign=1
            baseStart=start
#            baseStart=start
            width=0 # undefined
            sdn=parseDecimalNumber(start)
            if sdn is None:
@@ -247,16 +265,141 @@ class ImportVerilogParameters(object):
                if width > 0:
                    et="[%d:0]"%(width-1)
                return (sign*d,et,cp[0])
        def useBest(first, second):
            if first is None:
                return second
            elif second is None:
                return first
            elif first[2]>second[2]:
                return first
            else:
                return second
        return useBest(useBest(parseString(),parseNumber()),parseRealNumber())


        def parseParameter(start=0):
            l=0
            par=None
            if (self.verbose>2) and(start !=0):
                print ("parseParameter(start=%d)"%(start))

            for parName in self.parameters:
                if (line[start:start+len(parName)] == parName) and (len(parName)>l) :
                    par=parName
                    l=len(parName)
                    
            if l==0:
                return None
            end=start+l
            try:
                pass
                if (line[end] in string.ascii_letters) or (line[end] in string.digits) or (line[end] == '_'):
                    return None # Real parameter name is longer
            except:
                pass #Ok if it is the end of line
            if (self.verbose>2) and (start !=0):
                print ("parseParameter(start=%d), end=%d, line=%s, parName=%s, par=%s"%(start,end,line,parName,str(self.parameters[par])))

            return (self.parameters[par][0],self.parameters[par][1],end)
        def binop_add(exp1,exp2):
            return (exp1[0] + exp2[0],max(exp1[1],exp2[1]))
        def binop_sub(exp1,exp2):
            return (exp1[0] - exp2[0],max(exp1[1],exp2[1]))
        def binop_bitor(exp1,exp2):
            return (exp1[0] | exp2[0],max(exp1[1],exp2[1]))
        def binop_bitand(exp1,exp2):
            return (exp1[0] & exp2[0],max(exp1[1],exp2[1]))
        def binop_bitxor(exp1,exp2):
            return (exp1[0] ^ exp2[0],max(exp1[1],exp2[1]))
        def binop_mult(exp1,exp2):
            return (exp1[0] * exp2[0],exp1[1]+exp2[1])
        def binop_div(exp1,exp2):
            return (exp1[0] / exp2[0],exp1[1])
        def binop_mod(exp1,exp2):
            return (exp1[0] % exp2[0],exp2[1])
        def binop_lshift(exp1,exp2):
            return (exp1[0] << exp2[0],exp1[1]+exp2[0])
        def binop_rshift(exp1,exp2):
            return (exp1[0] >> exp2[0],exp1[1])
        
        binops=(
                ('+',binop_add),
                ('-',binop_sub),
                ('|',binop_bitor),
                ('&',binop_bitand),
                ('^',binop_bitxor),
                ('*',binop_mult),
                ('/',binop_div),
                ('%',binop_mod),
                ('<<',binop_lshift),
                ('>>',binop_rshift)
                )
        def getBinOp(start):
            l=0
            op=None
            for opTuple in binops:
                opName=opTuple[0]
                if (line[start:start+len(opName)] == opName) and (len(opName)>l) :
                    op=opTuple
                    l=len(opName)
            return op
            
            pass
        def parsePrimary(start=0):
            return useBest(useBest(useBest(parseString(start),parseNumber(start)),parseRealNumber(start)),parseParameter(start))
        def parsePraamryOrBinary(start=0):
            operand1=parsePrimary(start)
            if (self.verbose>2) and (start !=0):
                print ("parsePraamryOrBinary(start=%d), line=%s, result=%s"%(start,line,str(operand1)))
                
            opStart=skipWS(operand1[2])
            if opStart == len(line): # just primary
                return operand1
        # Try binary operation    
            op=getBinOp(opStart)
            if not op:
                print("ERROR: Next token in '%s' (starting from %s) is not a binary operation"%(line,line[opStart:]))
                return None
            start2=skipWS(opStart+len(op[0]))
            if (self.verbose>2):
                print ("line=%s"%line)
                print ("start=%d, opStart=%d, start2=%d"%(start,opStart, start2))
            operand2=parseExp(start2)
            if not operand2:
                print("ERROR: Could not get the second operand for '%s' in '%s'"%(op[0],line))
                return None
            width1=getParWidth(operand1[1])  
            width2=getParWidth(operand2[1])
            if (self.verbose>2):
                print("operand1=%s"%str(operand1))
                print("operand2=%s"%str(operand2))
            exp=op[1]((operand1[0],width1),(operand2[0],width2))
            if (self.verbose>2):
                print("exp=%s"%str(exp))
            if not exp:
                print("ERROR: Failed '%s' in '%s'"%(op[0],line))
                return None
            #Try limiting to 32 bits
            width=exp[1]
            if (width1==32) and (exp[1]>32) and ((width >> 32) == 0):
                width=32
            return (exp[0],"[%d:0]"%(width-1),operand2[2])

        def parseExp(start=0):
            start=skipWS(start)
            if start>=len(line):
                print ("ERROR: EOL reached when expression was expected in '%s'"%line)
                return None
            if line[start]=='(':
                exp=parseExp(start+1)
                if not exp:
                    print ("ERROR: failed to evaluate expression in '%s' (starting from '%s'"%(line,line[start:]))
                    return None
                endPos=skipWS(exp[2])
                if endPosp >= len(line):
                    print ("ERROR: EOL reached when closing ')' was expected in '%s'"%line)
                    return None
                if line[ep] != ")":
                    print ("ERROR: Found '%s'when closing ')' was expected in '%s'"%(line[endPos],line))
                    return None
                endPos=skipWS(endPos+1)
                return (exp[0],"[%d:0]"%(exp[1]-1),endPos)
            return parsePraamryOrBinary(start)
        '''
        parseExpression top level code
        no support for bit select, &&, ||, ~ ! ? and more... 
        '''
        return parseExp(0)

    '''
    Read parameters defined in parameter port list (inside #(,,,), comma separated (last may have no comma)
@@ -431,7 +574,7 @@ class ImportVerilogParameters(object):

                    def skipToWS(): # all tabs are already replaced with spaces
                        try:
                            indx==preprocessedLines[textPointer["line"]].find(" ",[textPointer["char"]])
                            indx=preprocessedLines[textPointer["line"]].find(" ",[textPointer["char"]])
                        except:
                            return
                        if (indx<0):
@@ -495,6 +638,9 @@ class ImportVerilogParameters(object):
                            preprocessedLines=[] # Nothing left
                    # process expression here, for now - just use expression string
                    ev= self.parseExpression(expLine)
                    if (self.verbose>2):
                        print (parName+": -> "+expLine)
                        print (ev)
                    if ev is None:
                        self.parameters[parName]= (expLine,parType,expLine)
                    else:
@@ -503,6 +649,8 @@ class ImportVerilogParameters(object):
#                        self.parameters[parName]= (ev[0],parType)
                        self.parameters[parName]= (ev[0],parType,expLine)
#                    if portMode: # while True:
                    if (self.verbose>2):
                        print (parName+": "+str(self.parameters[parName]))
                    if portMode or (termChar == ";"): # while True:
                        break;
#        print ("======= Parameters =======")
+23 −7
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ from import_verilog_parameters import VerilogParameters
import x393_mem
import x393_axi_control_status
import x393_pio_sequences
import x393_mcntrl_timing
__all__ = []
__version__ = 0.1
__date__ = '2015-03-01'
@@ -90,7 +91,8 @@ def execTask(commandLine):
            funcArgs[i]=eval(arg) # Try parsing parameters as numbers, if possible
        except:
            pass
#    result = callableTasks[funcName]['func'](callableTasks[funcName]['inst'],*funcArgs)
    result = callableTasks[funcName]['func'](callableTasks[funcName]['inst'],*funcArgs)
    '''
    try:
        result = callableTasks[funcName]['func'](callableTasks[funcName]['inst'],*funcArgs)
    except Exception as e:
@@ -107,6 +109,7 @@ def execTask(commandLine):
            sFuncArgs+=' <'+str(a)+'>'
        print ("Usage:\n%s %s"%(funcName,sFuncArgs))
        print ("exception message:"+str(e))
    '''
    return result
def hx(obj):
    try:
@@ -226,6 +229,7 @@ USAGE
    x393mem=    x393_mem.X393Mem(verbose,True) #add dry run parameter
    x393tasks=  x393_axi_control_status.X393AxiControlStatus(verbose,True)
    x393Pio=    x393_pio_sequences.X393PIOSequences(verbose,True)
    x393Timing= x393_mcntrl_timing.X393McntrlTiming(verbose,True)
    '''
    print ("----------------------")
    print("x393_mem.__dict__="+str(x393_mem.__dict__))
@@ -243,6 +247,7 @@ USAGE
    extractTasks(x393_mem.X393Mem,x393mem)
    extractTasks(x393_axi_control_status.X393AxiControlStatus,x393tasks)
    extractTasks(x393_pio_sequences.X393PIOSequences,x393Pio)
    extractTasks(x393_mcntrl_timing.X393McntrlTiming,x393Timing)

    if verbose > 3:     
        funcName="read_mem"
@@ -291,16 +296,27 @@ USAGE
                print ('\n"parameters" and "defines" list known defined parameters and macros')
            elif line == 'parameters':
                parameters=ivp.getParameters()
                for par,val in sorted(parameters.items()):
                    try:
                        print (par+" = "+hex(val[0])+" (type = "+val[1]+" raw = "+val[2]+")")        
                    except:
                        print (par+" = "+str(val[0])+" (type = "+val[1]+" raw = "+val[2]+")")
                
                '''
                for par in parameters:
                    try:
                        print (par+" = "+hex(parameters[par][0])+" (type = "+parameters[par][1]+" raw = "+parameters[par][2]+")")        
                    except:
                        print (par+" = "+str(parameters[par][0])+" (type = "+parameters[par][1]+" raw = "+parameters[par][2]+")")
                '''        

            elif (line == 'defines') or (line == 'macros'):
                defines= ivp.getDefines()
                for macro in defines:
                    print ("`"+macro+": "+defines[macro])        
                for macro,val in sorted(parameters.items()):
                    print ("`"+macro+": "+val)        

#                for macro in defines:
#                    print ("`"+macro+": "+defines[macro])        
            else:
                cmdLine=line.split()
                rslt= execTask(cmdLine)

py393/verilog_utils.py

0 → 100644
+98 −0
Original line number Diff line number Diff line
from __future__ import print_function
'''
# Copyright (C) 2015, Elphel.inc.
# Methods that mimic Verilog tasks used for simulation  
# 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:  2015 Elphel, Inc.
@license:    GPLv3.0+
@contact:    andrey@elphel.coml
@deffield    updated: Updated
'''
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2015, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
#import sys
#import x393_mem
#MCNTRL_TEST01_CHN4_STATUS_CNTRL=0
def hx(obj):
    try:
        return "0x%x"%obj
    except:
        return str(obj)
'''
Simulate Verilog concatenation. Input list tuple of items, each being a pair of (value, width)
'''    
def concat(items):
    val=0
    width=0
    for vw in reversed(items):
        v=vw[0]
        if vw[1]==1:
            v=(0,1)[v] # So True/False will also work, not juet o/1
        val |= (v & ((1 << vw[1])-1))<<width
        width += vw[1]
    return (val,width)

def bits(val,field):
    try:
        high=field[0]
        low=field[1]
        if low > high:
            low,high=high,low
    except:
        low=field+0 # will be error if not a number
        high=low
    return (val >> low) & ((1 << (high-low+1))-1)    
def getParWidthLo(bitRange):
        if bitRange=='INTEGER':
            return (32,0)
        else:
            try:
                if bitRange[0] != '[':
                    return None # may also fail through except if bitRange=""
                startPosHi=1
                endPosHi=bitRange.index(':')
                startPosLo=endPosHi+1
                endPosLo=bitRange.index(']')
                if endPosHi<0:
                    endPosHi=endPosLo
                    startPosLo=-1
            except:
                return None
            if endPosHi <0:
                return None # no ":" or terminating "]"
            loBit=0
            try:
                if startPosLo >0:
                    loBit=int(bitRange[startPosLo,endPosLo])
                    width=int(bitRange[startPosHi,endPosHi])-loBit+1
                return (width,loBit)
            except:
                return None # could not parse: undefined width
                    
def getParWidth(bitRange):
    wl=getParWidthLo(bitRange)
#    print("bitRange=%s wl=%s"%(bitRange,str(wl)))
    if not wl:
        return None
    else:
        return wl[0]
                    
            
 No newline at end of file
+2 −30
Original line number Diff line number Diff line
@@ -32,36 +32,8 @@ __status__ = "Development"
#import x393_mem
from import_verilog_parameters import VerilogParameters
from x393_mem import X393Mem
#MCNTRL_TEST01_CHN4_STATUS_CNTRL=0
def hx(obj):
    try:
        return "0x%x"%obj
    except:
        return str(obj)
'''
Simulate Verilog concatenation. Input list tuple of items, each being a pair of (value, width)
'''    
def concat(items):
    val=0
    width=0
    for vw in reversed(items):
        v=vw[0]
        if vw[1]==1:
            v=(0,1)[v] # So True/False will also work, not juet o/1
        val |= (v & ((1 << vw[1])-1))<<width
        width += vw[1]
    return (val,width)

def bits(val,field):
    try:
        high=field[0]
        low=field[1]
        if low > high:
            low,high=high,low
    except:
        low=field+0 # will be error if not a number
        high=low
    return (val >> low) & ((1 << (high-low+1))-1)    
#from verilog_utils import hx,concat, bits 
from verilog_utils import hx 
        
class X393AxiControlStatus(object):
    DRY_MODE= True # True
+174 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading